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