]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/authenticate.c
More connect debug code
[bacula/bacula] / bacula / src / stored / authenticate.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  * Authenticate caller
30  *
31  *   Kern Sibbald, October 2000
32  *
33  *   Version $Id$
34  *
35  */
36
37
38 #include "bacula.h"
39 #include "stored.h"
40
41 const int dbglvl = 3;
42
43 static char Dir_sorry[] = "3999 No go\n";
44 static char OK_hello[]  = "3000 OK Hello\n";
45
46
47 /*********************************************************************
48  *
49  *
50  */
51 static int authenticate(int rcode, BSOCK *bs, JCR* jcr)
52 {
53    POOLMEM *dirname;
54    DIRRES *director = NULL;
55    int tls_local_need = BNET_TLS_NONE;
56    int tls_remote_need = BNET_TLS_NONE;
57    int compatible = true;                  /* require md5 compatible DIR */
58    bool auth_success = false;
59    alist *verify_list = NULL;
60
61    if (rcode != R_DIRECTOR) {
62       Dmsg1(dbglvl, "I only authenticate Directors, not %d\n", rcode);
63       Emsg1(M_FATAL, 0, _("I only authenticate Directors, not %d\n"), rcode);
64       return 0;
65    }
66    if (bs->msglen < 25 || bs->msglen > 500) {
67       Dmsg2(dbglvl, "Bad Hello command from Director at %s. Len=%d.\n",
68             bs->who(), bs->msglen);
69       Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
70             bs->who(), bs->msglen);
71       return 0;
72    }
73    dirname = get_pool_memory(PM_MESSAGE);
74    dirname = check_pool_memory_size(dirname, bs->msglen);
75
76    if (sscanf(bs->msg, "Hello Director %127s calling", dirname) != 1) {
77       bs->msg[100] = 0;
78       Dmsg2(dbglvl, "Bad Hello command from Director at %s: %s\n",
79             bs->who(), bs->msg);
80       Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
81             bs->who(), bs->msg);
82       return 0;
83    }
84    director = NULL;
85    unbash_spaces(dirname);
86    foreach_res(director, rcode) {
87       if (strcmp(director->hdr.name, dirname) == 0)
88          break;
89    }
90    if (!director) {
91       Dmsg2(dbglvl, "Connection from unknown Director %s at %s rejected.\n",
92             dirname, bs->who());
93       Emsg2(M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"
94        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
95             dirname, bs->who());
96       free_pool_memory(dirname);
97       return 0;
98    }
99
100    /* TLS Requirement */
101    if (director->tls_enable) {
102       if (director->tls_require) {
103          tls_local_need = BNET_TLS_REQUIRED;
104       } else {
105          tls_local_need = BNET_TLS_OK;
106       }
107    }
108
109    if (director->tls_verify_peer) {
110       verify_list = director->tls_allowed_cns;
111    }
112
113    /* Timeout Hello after 10 mins */
114    btimer_t *tid = start_bsock_timer(bs, AUTH_TIMEOUT);
115    auth_success = cram_md5_challenge(bs, director->password, tls_local_need, compatible);
116    if (auth_success) {
117       auth_success = cram_md5_respond(bs, director->password, &tls_remote_need, &compatible);
118       if (!auth_success) {
119          Dmsg1(dbglvl, "cram_get_auth failed with %s\n", bs->who());
120       }
121    } else {
122       Dmsg1(dbglvl, "cram_auth failed with %s\n", bs->who());
123    }
124
125    if (!auth_success) {
126       Emsg0(M_FATAL, 0, _("Incorrect password given by Director.\n"
127        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
128       auth_success = false;
129       goto auth_fatal;
130    }
131
132    /* Verify that the remote host is willing to meet our TLS requirements */
133    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
134       Emsg0(M_FATAL, 0, _("Authorization problem: Remote server did not" 
135            " advertise required TLS support.\n"));
136       auth_success = false;
137       goto auth_fatal;
138    }
139
140    /* Verify that we are willing to meet the remote host's requirements */
141    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
142       Emsg0(M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
143       auth_success = false;
144       goto auth_fatal;
145    }
146
147    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
148       /* Engage TLS! Full Speed Ahead! */
149       if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) {
150          Emsg0(M_FATAL, 0, _("TLS negotiation failed.\n"));
151          auth_success = false;
152          goto auth_fatal;
153       }
154    }
155
156 auth_fatal:
157    stop_bsock_timer(tid);
158    free_pool_memory(dirname);
159    jcr->director = director;
160    return auth_success;
161 }
162
163 /*
164  * Inititiate the message channel with the Director.
165  * He has made a connection to our server.
166  *
167  * Basic tasks done here:
168  *   Assume the Hello message is already in the input
169  *     buffer.  We then authenticate him.
170  *   Get device, media, and pool information from Director
171  *
172  *   This is the channel across which we will send error
173  *     messages and job status information.
174  */
175 int authenticate_director(JCR *jcr)
176 {
177    BSOCK *dir = jcr->dir_bsock;
178
179    if (!authenticate(R_DIRECTOR, dir, jcr)) {
180       bnet_fsend(dir, "%s", Dir_sorry);
181       Dmsg1(dbglvl, "Unable to authenticate Director at %s.\n", dir->who());
182       Emsg1(M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who());
183       bmicrosleep(5, 0);
184       return 0;
185    }
186    return bnet_fsend(dir, "%s", OK_hello);
187 }
188
189 int authenticate_filed(JCR *jcr)
190 {
191    BSOCK *fd = jcr->file_bsock;
192    int tls_local_need = BNET_TLS_NONE;
193    int tls_remote_need = BNET_TLS_NONE;
194    int compatible = true;                 /* require md5 compatible FD */
195    bool auth_success = false;
196    alist *verify_list = NULL;
197
198    /* TLS Requirement */
199    if (me->tls_enable) {
200       if (me->tls_require) {
201          tls_local_need = BNET_TLS_REQUIRED;
202       } else {
203          tls_local_need = BNET_TLS_OK;
204       }
205    }
206
207    if (me->tls_verify_peer) {
208       verify_list = me->tls_allowed_cns;
209    }
210
211    /* Timeout Hello after 5 mins */
212    btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
213    /* Challenge FD */
214    if (debug_level == 3) {
215       Pmsg1(000, "sd_auth_key=%s\n", jcr->sd_auth_key);
216    }
217    auth_success = cram_md5_challenge(fd, jcr->sd_auth_key, tls_local_need, compatible);
218    if (auth_success) {
219        /* Respond to his challenge */
220        auth_success = cram_md5_respond(fd, jcr->sd_auth_key, &tls_remote_need, &compatible);
221        if (!auth_success) {
222           Dmsg1(dbglvl, "cram-get-auth failed with %s\n", fd->who());
223        }
224    } else {
225       Dmsg1(dbglvl, "cram-auth failed with %s\n", fd->who());
226    }
227
228    if (!auth_success) {
229       Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
230        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
231            fd->who());
232       auth_success = false;
233       goto auth_fatal;
234    }
235
236    /* Verify that the remote host is willing to meet our TLS requirements */
237    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
238       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" 
239            " advertise required TLS support.\n"));
240       auth_success = false;
241       goto auth_fatal;
242    }
243
244    /* Verify that we are willing to meet the remote host's requirements */
245    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
246       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
247       auth_success = false;
248       goto auth_fatal;
249    }
250
251    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
252       /* Engage TLS! Full Speed Ahead! */
253       if (!bnet_tls_server(me->tls_ctx, fd, verify_list)) {
254          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
255          auth_success = false;
256          goto auth_fatal;
257       }
258    }
259
260 auth_fatal:
261    stop_bsock_timer(tid);
262    if (!auth_success) {
263       Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
264        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
265            fd->who());
266    }
267    jcr->authenticated = auth_success;
268    return auth_success;
269 }