]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/authenticate.c
Tweak authentication to work with 1.38.x FDs
[bacula/bacula] / bacula / src / dird / authenticate.c
1 /*
2  *
3  *   Bacula Director -- authorize.c -- handles authorization of
4  *     Storage and File daemons.
5  *
6  *     Kern Sibbald, May MMI
7  *
8  *    This routine runs as a thread and must be thread reentrant.
9  *
10  *   Version $Id$
11  *
12  */
13 /*
14    Copyright (C) 2001-2006 Kern Sibbald
15
16    This program is free software; you can redistribute it and/or
17    modify it under the terms of the GNU General Public License
18    version 2 as amended with additional clauses defined in the
19    file LICENSE in the main source directory.
20
21    This program is distributed in the hope that it will be useful,
22    but WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
24    the file LICENSE for additional details.
25
26  */
27
28 #include "bacula.h"
29 #include "dird.h"
30
31 extern DIRRES *director;
32
33 /* Commands sent to Storage daemon and File daemon and received
34  *  from the User Agent */
35 static char hello[]    = "Hello Director %s calling\n";
36
37 /* Response from Storage daemon */
38 static char OKhello[]   = "3000 OK Hello\n";
39 static char FDOKhello[] = "2000 OK Hello\n";
40
41 /* Sent to User Agent */
42 static char Dir_sorry[]  = "1999 You are not authorized.\n";
43
44 /* Forward referenced functions */
45
46 /*
47  * Authenticate Storage daemon connection
48  */
49 bool authenticate_storage_daemon(JCR *jcr, STORE *store)
50 {
51    BSOCK *sd = jcr->store_bsock;
52    char dirname[MAX_NAME_LENGTH];
53    int tls_local_need = BNET_TLS_NONE;
54    int tls_remote_need = BNET_TLS_NONE;
55    int compatible = true;
56    bool auth_success = false;
57
58    /*
59     * Send my name to the Storage daemon then do authentication
60     */
61    bstrncpy(dirname, director->hdr.name, sizeof(dirname));
62    bash_spaces(dirname);
63    /* Timeout Hello after 1 min */
64    btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
65    if (!bnet_fsend(sd, hello, dirname)) {
66       stop_bsock_timer(tid);
67       Dmsg1(50, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd));
68       Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd));
69       return 0;
70    }
71
72    /* TLS Requirement */
73    if (store->tls_enable) {
74      if (store->tls_require) {
75         tls_local_need = BNET_TLS_REQUIRED;
76      } else {
77         tls_local_need = BNET_TLS_OK;
78      }
79    }
80
81    auth_success = cram_md5_respond(sd, store->password, &tls_remote_need, &compatible);
82    if (auth_success) {
83       auth_success = cram_md5_challenge(sd, store->password, tls_local_need, compatible);
84       if (!auth_success) {
85          Dmsg1(50, "cram_challenge failed for %s\n", sd->who);
86       }
87    } else {
88       Dmsg1(50, "cram_respond failed for %s\n", sd->who);
89    }
90
91    if (!auth_success) {
92       stop_bsock_timer(tid);
93       Dmsg0(50, _("Director and Storage daemon passwords or names not the same.\n"));
94       Jmsg0(jcr, M_FATAL, 0,
95             _("Director unable to authenticate with Storage daemon. Possible causes:\n"
96             "Passwords or names not the same or\n"
97             "Maximum Concurrent Jobs exceeded on the SD or\n"
98             "SD networking messed up (restart daemon).\n"
99             "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
100       return 0;
101    }
102
103    /* Verify that the remote host is willing to meet our TLS requirements */
104    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
105       stop_bsock_timer(tid);
106       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not advertise required TLS support.\n"));
107       return 0;
108    }
109
110    /* Verify that we are willing to meet the remote host's requirements */
111    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
112       stop_bsock_timer(tid);
113       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
114       return 0;
115    }
116
117    /* Is TLS Enabled? */
118    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
119       /* Engage TLS! Full Speed Ahead! */
120       if (!bnet_tls_client(store->tls_ctx, sd)) {
121          stop_bsock_timer(tid);
122          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
123          return 0;
124       }
125    }
126
127    Dmsg1(116, ">stored: %s", sd->msg);
128    if (bnet_recv(sd) <= 0) {
129       stop_bsock_timer(tid);
130       Jmsg1(jcr, M_FATAL, 0, _("bdird<stored: bad response to Hello command: ERR=%s\n"),
131          bnet_strerror(sd));
132       return 0;
133    }
134    Dmsg1(110, "<stored: %s", sd->msg);
135    stop_bsock_timer(tid);
136    if (strncmp(sd->msg, OKhello, sizeof(OKhello)) != 0) {
137       Dmsg0(50, _("Storage daemon rejected Hello command\n"));
138       Jmsg0(jcr, M_FATAL, 0, _("Storage daemon rejected Hello command\n"));
139       return 0;
140    }
141    return 1;
142 }
143
144 /*
145  * Authenticate File daemon connection
146  */
147 int authenticate_file_daemon(JCR *jcr)
148 {
149    BSOCK *fd = jcr->file_bsock;
150    CLIENT *client = jcr->client;
151    char dirname[MAX_NAME_LENGTH];
152    int tls_local_need = BNET_TLS_NONE;
153    int tls_remote_need = BNET_TLS_NONE;
154    int compatible = true;
155    bool auth_success = false;
156
157    /*
158     * Send my name to the File daemon then do authentication
159     */
160    bstrncpy(dirname, director->hdr.name, sizeof(dirname));
161    bash_spaces(dirname);
162    /* Timeout Hello after 10 mins */
163    btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
164    if (!bnet_fsend(fd, hello, dirname)) {
165       stop_bsock_timer(tid);
166       Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to File daemon. ERR=%s\n"), bnet_strerror(fd));
167       return 0;
168    }
169    Dmsg1(50, "Sent: %s", fd->msg);
170
171    /* TLS Requirement */
172    if (client->tls_enable) {
173      if (client->tls_require) {
174         tls_local_need = BNET_TLS_REQUIRED;
175      } else {
176         tls_local_need = BNET_TLS_OK;
177      }
178    }
179
180    auth_success = cram_md5_respond(fd, client->password, &tls_remote_need, &compatible);
181    if (auth_success) {
182       auth_success = cram_md5_challenge(fd, client->password, tls_local_need, compatible);
183       if (!auth_success) {
184          Dmsg1(50, "cram_auth failed for %s\n", fd->who);
185       }
186    } else {
187       Dmsg1(50, "cram_get_auth failed for %s\n", fd->who);
188    }
189    if (!auth_success) {
190       stop_bsock_timer(tid);
191       Dmsg0(50, _("Director and File daemon passwords or names not the same.\n"));
192       Jmsg(jcr, M_FATAL, 0,
193             _("Unable to authenticate with File daemon. Possible causes:\n"
194             "Passwords or names not the same or\n"
195             "Maximum Concurrent Jobs exceeded on the FD or\n"
196             "FD networking messed up (restart daemon).\n"
197             "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
198       return 0;
199    }
200
201    /* Verify that the remote host is willing to meet our TLS requirements */
202    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
203       stop_bsock_timer(tid);
204       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not advertise required TLS support.\n"));
205       return 0;
206    }
207
208    /* Verify that we are willing to meet the remote host's requirements */
209    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
210       stop_bsock_timer(tid);
211       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
212       return 0;
213    }
214
215    /* Is TLS Enabled? */
216    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
217       /* Engage TLS! Full Speed Ahead! */
218       if (!bnet_tls_client(client->tls_ctx, fd)) {
219          stop_bsock_timer(tid);
220          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
221          return 0;
222       }
223    }
224
225    Dmsg1(116, ">filed: %s", fd->msg);
226    if (bnet_recv(fd) <= 0) {
227       stop_bsock_timer(tid);
228       Dmsg1(50, _("Bad response from File daemon to Hello command: ERR=%s\n"),
229          bnet_strerror(fd));
230       Jmsg(jcr, M_FATAL, 0, _("Bad response from File daemon to Hello command: ERR=%s\n"),
231          bnet_strerror(fd));
232       return 0;
233    }
234    Dmsg1(110, "<stored: %s", fd->msg);
235    stop_bsock_timer(tid);
236    if (strncmp(fd->msg, FDOKhello, sizeof(FDOKhello)) != 0) {
237       Dmsg0(50, _("File daemon rejected Hello command\n"));
238       Jmsg(jcr, M_FATAL, 0, _("File daemon rejected Hello command\n"));
239       return 0;
240    }
241    return 1;
242 }
243
244 /*********************************************************************
245  *
246  */
247 int authenticate_user_agent(UAContext *uac)
248 {
249    char name[MAX_NAME_LENGTH];
250    int tls_local_need = BNET_TLS_NONE;
251    int tls_remote_need = BNET_TLS_NONE;
252    int compatible = true;
253    CONRES *cons = NULL;
254    BSOCK *ua = uac->UA_sock;
255    bool auth_success = false;
256    TLS_CONTEXT *tls_ctx = NULL;
257    alist *verify_list = NULL;
258  
259
260 //  Emsg4(M_INFO, 0, _("UA Hello from %s:%s:%d is invalid. Len=%d\n"), ua->who,
261 //          ua->host, ua->port, ua->msglen);
262    if (ua->msglen < 16 || ua->msglen >= MAX_NAME_LENGTH + 15) {
263       Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Len=%d\n"), ua->who,
264             ua->host, ua->port, ua->msglen);
265       return 0;
266    }
267
268    if (sscanf(ua->msg, "Hello %127s calling\n", name) != 1) {
269       ua->msg[100] = 0;               /* terminate string */
270       Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Got: %s\n"), ua->who,
271             ua->host, ua->port, ua->msg);
272       return 0;
273    }
274
275    name[sizeof(name)-1] = 0;             /* terminate name */
276    if (strcmp(name, "*UserAgent*") == 0) {  /* default console */
277       /* TLS Requirement */
278       if (director->tls_enable) {
279          if (director->tls_require) {
280             tls_local_need = BNET_TLS_REQUIRED;
281          } else {
282             tls_local_need = BNET_TLS_OK;
283          }
284       }
285
286       if (director->tls_verify_peer) {
287          verify_list = director->tls_allowed_cns;
288       }
289
290       auth_success = cram_md5_challenge(ua, director->password, tls_local_need,
291                                         compatible) &&
292                      cram_md5_respond(ua, director->password, &tls_remote_need, &compatible);
293    } else {
294       unbash_spaces(name);
295       cons = (CONRES *)GetResWithName(R_CONSOLE, name);
296       if (cons) {
297          /* TLS Requirement */
298          if (cons->tls_enable) {
299             if (cons->tls_require) {
300                tls_local_need = BNET_TLS_REQUIRED;
301             } else {
302                tls_local_need = BNET_TLS_OK;
303             }
304          }
305
306          if (cons->tls_verify_peer) {
307             verify_list = cons->tls_allowed_cns;
308          }
309
310          auth_success = cram_md5_challenge(ua, cons->password, tls_local_need,
311                                            compatible) &&
312                      cram_md5_respond(ua, cons->password, &tls_remote_need, &compatible);
313
314          if (auth_success) {
315             uac->cons = cons;         /* save console resource pointer */
316          }
317       } else {
318          auth_success = false;
319          goto auth_done;
320       }
321    }
322
323    /* Verify that the remote peer is willing to meet our TLS requirements */
324    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
325       Emsg0(M_FATAL, 0, _("Authorization problem:"
326             " Remote client did not advertise required TLS support.\n"));
327       auth_success = false;
328       goto auth_done;
329    }
330
331    /* Verify that we are willing to meet the peer's requirements */
332    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
333       Emsg0(M_FATAL, 0, _("Authorization problem:"
334             " Remote client requires TLS.\n"));
335       auth_success = false;
336       goto auth_done;
337    }
338
339    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
340       if (cons) {
341          tls_ctx = cons->tls_ctx;
342       } else {
343          tls_ctx = director->tls_ctx;
344       }
345
346       /* Engage TLS! Full Speed Ahead! */
347       if (!bnet_tls_server(tls_ctx, ua, verify_list)) {
348          Emsg0(M_ERROR, 0, _("TLS negotiation failed.\n"));
349          auth_success = false;
350          goto auth_done;
351       }
352    }
353
354
355 /* Authorization Completed */
356 auth_done:
357    if (!auth_success) {
358       bnet_fsend(ua, "%s", _(Dir_sorry));
359       Emsg4(M_ERROR, 0, _("Unable to authenticate console \"%s\" at %s:%s:%d.\n"),
360             name, ua->who, ua->host, ua->port);
361       sleep(5);
362       return 0;
363    }
364    bnet_fsend(ua, _("1000 OK: %s Version: %s (%s)\n"), my_name, VERSION, BDATE);
365    return 1;
366 }