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