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