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