]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/authenticate.c
kes Implement bsr block level checking for disk files. However,
[bacula/bacula] / bacula / src / dird / authenticate.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2001-2008 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 Kern Sibbald.
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  *
30  *   Bacula Director -- authorize.c -- handles authorization of
31  *     Storage and File daemons.
32  *
33  *     Kern Sibbald, May MMI
34  *
35  *    This routine runs as a thread and must be thread reentrant.
36  *
37  *   Version $Id$
38  *
39  */
40
41 #include "bacula.h"
42 #include "dird.h"
43
44 static const int dbglvl = 50;
45
46 extern DIRRES *director;
47
48 /* Commands sent to Storage daemon and File daemon and received
49  *  from the User Agent */
50 static char hello[]    = "Hello Director %s calling\n";
51
52 /* Response from Storage daemon */
53 static char OKhello[]      = "3000 OK Hello\n";
54 static char FDOKhello[]    = "2000 OK Hello\n";
55 static char FDOKnewHello[] = "2000 OK Hello %d\n";
56
57 /* Sent to User Agent */
58 static char Dir_sorry[]  = "1999 You are not authorized.\n";
59
60 /* Forward referenced functions */
61
62 /*
63  * Authenticate Storage daemon connection
64  */
65 bool authenticate_storage_daemon(JCR *jcr, STORE *store)
66 {
67    BSOCK *sd = jcr->store_bsock;
68    char dirname[MAX_NAME_LENGTH];
69    int tls_local_need = BNET_TLS_NONE;
70    int tls_remote_need = BNET_TLS_NONE;
71    int compatible = true;
72    bool auth_success = false;
73
74    /*
75     * Send my name to the Storage daemon then do authentication
76     */
77    bstrncpy(dirname, director->hdr.name, sizeof(dirname));
78    bash_spaces(dirname);
79    /* Timeout Hello after 1 min */
80    btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
81    if (!sd->fsend(hello, dirname)) {
82       stop_bsock_timer(tid);
83       Dmsg1(dbglvl, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd));
84       Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd));
85       return 0;
86    }
87
88    /* TLS Requirement */
89    if (store->tls_enable) {
90      if (store->tls_require) {
91         tls_local_need = BNET_TLS_REQUIRED;
92      } else {
93         tls_local_need = BNET_TLS_OK;
94      }
95    }
96
97    if (store->tls_authenticate) {
98       tls_local_need = BNET_TLS_REQUIRED;
99    }
100
101    auth_success = cram_md5_respond(sd, store->password, &tls_remote_need, &compatible);
102    if (auth_success) {
103       auth_success = cram_md5_challenge(sd, store->password, tls_local_need, compatible);
104       if (!auth_success) {
105          Dmsg1(dbglvl, "cram_challenge failed for %s\n", sd->who());
106       }
107    } else {
108       Dmsg1(dbglvl, "cram_respond failed for %s\n", sd->who());
109    }
110
111    if (!auth_success) {
112       stop_bsock_timer(tid);
113       Dmsg0(dbglvl, _("Director and Storage daemon passwords or names not the same.\n"));
114       Jmsg2(jcr, M_FATAL, 0,
115             _("Director unable to authenticate with Storage daemon at \"%s:%d\". Possible causes:\n"
116             "Passwords or names not the same or\n"
117             "Maximum Concurrent Jobs exceeded on the SD or\n"
118             "SD networking messed up (restart daemon).\n"
119             "Please see http://www.bacula.org/en/rel-manual/Bacula_Freque_Asked_Questi.html#SECTION003760000000000000000 for help.\n"),
120             sd->host(), sd->port());
121       return 0;
122    }
123
124    /* Verify that the remote host is willing to meet our TLS requirements */
125    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
126       stop_bsock_timer(tid);
127       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not advertise required TLS support.\n"));
128       return 0;
129    }
130
131    /* Verify that we are willing to meet the remote host's requirements */
132    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
133       stop_bsock_timer(tid);
134       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
135       return 0;
136    }
137
138    /* Is TLS Enabled? */
139    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
140       /* Engage TLS! Full Speed Ahead! */
141       if (!bnet_tls_client(store->tls_ctx, sd, NULL)) {
142          stop_bsock_timer(tid);
143          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with SD at \"%s:%d\"\n"),
144             sd->host(), sd->port());
145          return 0;
146       }
147       if (store->tls_authenticate) {       /* authentication only? */
148          sd->free_tls();                   /* yes, stop tls */
149       }
150    }
151
152    Dmsg1(116, ">stored: %s", sd->msg);
153    if (sd->recv() <= 0) {
154       stop_bsock_timer(tid);
155       Jmsg3(jcr, M_FATAL, 0, _("bdird<stored: \"%s:%s\" bad response to Hello command: ERR=%s\n"),
156          sd->who(), sd->host(), sd->bstrerror());
157       return 0;
158    }
159    Dmsg1(110, "<stored: %s", sd->msg);
160    stop_bsock_timer(tid);
161    if (strncmp(sd->msg, OKhello, sizeof(OKhello)) != 0) {
162       Dmsg0(dbglvl, _("Storage daemon rejected Hello command\n"));
163       Jmsg2(jcr, M_FATAL, 0, _("Storage daemon at \"%s:%d\" rejected Hello command\n"),
164          sd->host(), sd->port());
165       return 0;
166    }
167    return 1;
168 }
169
170 /*
171  * Authenticate File daemon connection
172  */
173 int authenticate_file_daemon(JCR *jcr)
174 {
175    BSOCK *fd = jcr->file_bsock;
176    CLIENT *client = jcr->client;
177    char dirname[MAX_NAME_LENGTH];
178    int tls_local_need = BNET_TLS_NONE;
179    int tls_remote_need = BNET_TLS_NONE;
180    int compatible = true;
181    bool auth_success = false;
182
183    /*
184     * Send my name to the File daemon then do authentication
185     */
186    bstrncpy(dirname, director->name(), sizeof(dirname));
187    bash_spaces(dirname);
188    /* Timeout Hello after 1 min */
189    btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
190    if (!fd->fsend(hello, dirname)) {
191       stop_bsock_timer(tid);
192       Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to File daemon at \"%s:%d\". ERR=%s\n"), 
193            fd->host(), fd->port(), fd->bstrerror());
194       return 0;
195    }
196    Dmsg1(dbglvl, "Sent: %s", fd->msg);
197
198    /* TLS Requirement */
199    if (client->tls_enable) {
200      if (client->tls_require) {
201         tls_local_need = BNET_TLS_REQUIRED;
202      } else {
203         tls_local_need = BNET_TLS_OK;
204      }
205    }
206
207    if (client->tls_authenticate) {
208       tls_local_need = BNET_TLS_REQUIRED;
209    }
210
211    auth_success = cram_md5_respond(fd, client->password, &tls_remote_need, &compatible);
212    if (auth_success) {
213       auth_success = cram_md5_challenge(fd, client->password, tls_local_need, compatible);
214       if (!auth_success) {
215          Dmsg1(dbglvl, "cram_auth failed for %s\n", fd->who());
216       }
217    } else {
218       Dmsg1(dbglvl, "cram_get_auth failed for %s\n", fd->who());
219    }
220    if (!auth_success) {
221       stop_bsock_timer(tid);
222       Dmsg0(dbglvl, _("Director and File daemon passwords or names not the same.\n"));
223       Jmsg(jcr, M_FATAL, 0,
224             _("Unable to authenticate with File daemon at \"%s:%d\". Possible causes:\n"
225             "Passwords or names not the same or\n"
226             "Maximum Concurrent Jobs exceeded on the FD or\n"
227             "FD networking messed up (restart daemon).\n"
228             "Please see http://www.bacula.org/en/rel-manual/Bacula_Freque_Asked_Questi.html#SECTION003760000000000000000 for help.\n"),
229             fd->host(), fd->port());
230       return 0;
231    }
232
233    /* Verify that the remote host is willing to meet our TLS requirements */
234    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
235       stop_bsock_timer(tid);
236       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: FD \"%s:%s\" did not advertise required TLS support.\n"),
237            fd->who(), fd->host());
238       return 0;
239    }
240
241    /* Verify that we are willing to meet the remote host's requirements */
242    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
243       stop_bsock_timer(tid);
244       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: FD at \"%s:%d\" requires TLS.\n"),
245            fd->host(), fd->port());
246       return 0;
247    }
248
249    /* Is TLS Enabled? */
250    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
251       /* Engage TLS! Full Speed Ahead! */
252       if (!bnet_tls_client(client->tls_ctx, fd, client->tls_allowed_cns)) {
253          stop_bsock_timer(tid);
254          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with FD at \"%s:%d\".\n"),
255               fd->host(), fd->port());
256          return 0;
257       }
258       if (client->tls_authenticate) {        /* tls authentication only? */
259          fd->free_tls();                     /* yes, shutdown tls */
260       }
261    }
262
263    Dmsg1(116, ">filed: %s", fd->msg);
264    if (fd->recv() <= 0) {
265       stop_bsock_timer(tid);
266       Dmsg1(dbglvl, _("Bad response from File daemon to Hello command: ERR=%s\n"),
267          bnet_strerror(fd));
268       Jmsg(jcr, M_FATAL, 0, _("Bad response from File daemon at \"%s:%d\" to Hello command: ERR=%s\n"),
269          fd->host(), fd->port(), fd->bstrerror());
270       return 0;
271    }
272    Dmsg1(110, "<filed: %s", fd->msg);
273    stop_bsock_timer(tid);
274    jcr->FDVersion = 0;
275    if (strncmp(fd->msg, FDOKhello, sizeof(FDOKhello)) != 0 &&
276        sscanf(fd->msg, FDOKnewHello, &jcr->FDVersion) != 1) {
277       Dmsg0(dbglvl, _("File daemon rejected Hello command\n"));
278       Jmsg(jcr, M_FATAL, 0, _("File daemon at \"%s:%d\" rejected Hello command\n"),
279            fd->host(), fd->port());
280       return 0;
281    }
282    return 1;
283 }
284
285 /*********************************************************************
286  *
287  */
288 int authenticate_user_agent(UAContext *uac)
289 {
290    char name[MAX_NAME_LENGTH];
291    int tls_local_need = BNET_TLS_NONE;
292    int tls_remote_need = BNET_TLS_NONE;
293    bool need_tls;
294    bool tls_authenticate;
295    int compatible = true;
296    CONRES *cons = NULL;
297    BSOCK *ua = uac->UA_sock;
298    bool auth_success = false;
299    TLS_CONTEXT *tls_ctx = NULL;
300    alist *verify_list = NULL;
301  
302    if (ua->msglen < 16 || ua->msglen >= MAX_NAME_LENGTH + 15) {
303       Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Len=%d\n"), ua->who(),
304             ua->host(), ua->port(), ua->msglen);
305       return 0;
306    }
307
308    if (sscanf(ua->msg, "Hello %127s calling\n", name) != 1) {
309       ua->msg[100] = 0;               /* terminate string */
310       Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Got: %s\n"), ua->who(),
311             ua->host(), ua->port(), ua->msg);
312       return 0;
313    }
314
315    name[sizeof(name)-1] = 0;             /* terminate name */
316    if (strcmp(name, "*UserAgent*") == 0) {  /* default console */
317       /* TLS Requirement */
318       if (director->tls_enable) {
319          if (director->tls_require) {
320             tls_local_need = BNET_TLS_REQUIRED;
321          } else {
322             tls_local_need = BNET_TLS_OK;
323          }
324       }
325
326       tls_authenticate = director->tls_authenticate;
327       need_tls = director->tls_enable || tls_authenticate;
328
329       if (tls_authenticate) {
330          tls_local_need = BNET_TLS_REQUIRED;
331       }
332
333       if (director->tls_verify_peer) {
334          verify_list = director->tls_allowed_cns;
335       }
336
337       auth_success = cram_md5_challenge(ua, director->password, tls_local_need,
338                                         compatible) &&
339                      cram_md5_respond(ua, director->password, &tls_remote_need, &compatible);
340    } else {
341       unbash_spaces(name);
342       cons = (CONRES *)GetResWithName(R_CONSOLE, name);
343       if (cons) {
344          /* TLS Requirement */
345          if (cons->tls_enable) {
346             if (cons->tls_require) {
347                tls_local_need = BNET_TLS_REQUIRED;
348             } else {
349                tls_local_need = BNET_TLS_OK;
350             }
351          }
352
353          tls_authenticate = cons->tls_authenticate;
354          need_tls = cons->tls_enable || tls_authenticate;
355
356          if (tls_authenticate) {
357             tls_local_need = BNET_TLS_REQUIRED;
358          }
359
360          if (cons->tls_verify_peer) {
361             verify_list = cons->tls_allowed_cns;
362          }
363
364          auth_success = cram_md5_challenge(ua, cons->password, tls_local_need,
365                                            compatible) &&
366                      cram_md5_respond(ua, cons->password, &tls_remote_need, &compatible);
367
368          if (auth_success) {
369             uac->cons = cons;         /* save console resource pointer */
370          }
371       } else {
372          auth_success = false;
373          goto auth_done;
374       }
375    }
376
377
378    /* Verify that the remote peer is willing to meet our TLS requirements */
379    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
380       Emsg0(M_FATAL, 0, _("Authorization problem:"
381             " Remote client did not advertise required TLS support.\n"));
382       auth_success = false;
383       goto auth_done;
384    }
385
386    /* Verify that we are willing to meet the peer's requirements */
387    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
388       Emsg0(M_FATAL, 0, _("Authorization problem:"
389             " Remote client requires TLS.\n"));
390       auth_success = false;
391       goto auth_done;
392    }
393
394    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
395       if (cons) {
396          tls_ctx = cons->tls_ctx;
397       } else {
398          tls_ctx = director->tls_ctx;
399       }
400
401       /* Engage TLS! Full Speed Ahead! */
402       if (!bnet_tls_server(tls_ctx, ua, verify_list)) {
403          Emsg0(M_ERROR, 0, _("TLS negotiation failed.\n"));
404          auth_success = false;
405          goto auth_done;
406       }
407       if (tls_authenticate) {            /* authentication only? */
408          ua->free_tls();                 /* stop tls */
409       }
410    }
411
412
413 /* Authorization Completed */
414 auth_done:
415    if (!auth_success) {
416       ua->fsend("%s", _(Dir_sorry));
417       Emsg4(M_ERROR, 0, _("Unable to authenticate console \"%s\" at %s:%s:%d.\n"),
418             name, ua->who(), ua->host(), ua->port());
419       sleep(5);
420       return 0;
421    }
422    ua->fsend(_("1000 OK: %s Version: %s (%s)\n"), my_name, VERSION, BDATE);
423    return 1;
424 }