]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/authenticate.c
Add support for arbitrary client-to-server certificate CN matching (TLS Allowed CN...
[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    Bacula® - The Network Backup Solution
15
16    Copyright (C) 2001-2006 Free Software Foundation Europe e.V.
17
18    The main author of Bacula is Kern Sibbald, with contributions from
19    many others, a complete list can be found in the file AUTHORS.
20    This program is Free Software; you can redistribute it and/or
21    modify it under the terms of version two of the GNU General Public
22    License as published by the Free Software Foundation plus additions
23    that are listed in the file LICENSE.
24
25    This program is distributed in the hope that it will be useful, but
26    WITHOUT ANY WARRANTY; without even the implied warranty of
27    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28    General Public License for more details.
29
30    You should have received a copy of the GNU General Public License
31    along with this program; if not, write to the Free Software
32    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
33    02110-1301, USA.
34
35    Bacula® is a registered trademark of John Walker.
36    The licensor of Bacula is the Free Software Foundation Europe
37    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
38    Switzerland, email:ftf@fsfeurope.org.
39 */
40
41 #include "bacula.h"
42 #include "dird.h"
43
44 extern DIRRES *director;
45
46 /* Commands sent to Storage daemon and File daemon and received
47  *  from the User Agent */
48 static char hello[]    = "Hello Director %s calling\n";
49
50 /* Response from Storage daemon */
51 static char OKhello[]   = "3000 OK Hello\n";
52 static char FDOKhello[] = "2000 OK Hello\n";
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    if (!bnet_fsend(sd, hello, dirname)) {
79       stop_bsock_timer(tid);
80       Dmsg1(50, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd));
81       Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd));
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    auth_success = cram_md5_respond(sd, store->password, &tls_remote_need, &compatible);
95    if (auth_success) {
96       auth_success = cram_md5_challenge(sd, store->password, tls_local_need, compatible);
97       if (!auth_success) {
98          Dmsg1(50, "cram_challenge failed for %s\n", sd->who());
99       }
100    } else {
101       Dmsg1(50, "cram_respond failed for %s\n", sd->who());
102    }
103
104    if (!auth_success) {
105       stop_bsock_timer(tid);
106       Dmsg0(50, _("Director and Storage daemon passwords or names not the same.\n"));
107       Jmsg2(jcr, M_FATAL, 0,
108             _("Director unable to authenticate with Storage daemon on \"%s:%d\". Possible causes:\n"
109             "Passwords or names not the same or\n"
110             "Maximum Concurrent Jobs exceeded on the SD or\n"
111             "SD networking messed up (restart daemon).\n"
112             "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
113             sd->host(), sd->port());
114       return 0;
115    }
116
117    /* Verify that the remote host is willing to meet our TLS requirements */
118    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
119       stop_bsock_timer(tid);
120       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not advertise required TLS support.\n"));
121       return 0;
122    }
123
124    /* Verify that we are willing to meet the remote host's requirements */
125    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
126       stop_bsock_timer(tid);
127       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
128       return 0;
129    }
130
131    /* Is TLS Enabled? */
132    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
133       /* Engage TLS! Full Speed Ahead! */
134       if (!bnet_tls_client(store->tls_ctx, sd, NULL)) {
135          stop_bsock_timer(tid);
136          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with SD on \"%s:%d\"\n"),
137             sd->host(), sd->port());
138          return 0;
139       }
140    }
141
142    Dmsg1(116, ">stored: %s", sd->msg);
143    if (bnet_recv(sd) <= 0) {
144       stop_bsock_timer(tid);
145       Jmsg3(jcr, M_FATAL, 0, _("bdird<stored: \"%s:%s\" bad response to Hello command: ERR=%s\n"),
146          sd->who(), sd->host(), bnet_strerror(sd));
147       return 0;
148    }
149    Dmsg1(110, "<stored: %s", sd->msg);
150    stop_bsock_timer(tid);
151    if (strncmp(sd->msg, OKhello, sizeof(OKhello)) != 0) {
152       Dmsg0(50, _("Storage daemon rejected Hello command\n"));
153       Jmsg2(jcr, M_FATAL, 0, _("Storage daemon on \"%s:%d\" rejected Hello command\n"),
154          sd->host(), sd->port());
155       return 0;
156    }
157    return 1;
158 }
159
160 /*
161  * Authenticate File daemon connection
162  */
163 int authenticate_file_daemon(JCR *jcr)
164 {
165    BSOCK *fd = jcr->file_bsock;
166    CLIENT *client = jcr->client;
167    char dirname[MAX_NAME_LENGTH];
168    int tls_local_need = BNET_TLS_NONE;
169    int tls_remote_need = BNET_TLS_NONE;
170    int compatible = true;
171    bool auth_success = false;
172
173    /*
174     * Send my name to the File daemon then do authentication
175     */
176    bstrncpy(dirname, director->hdr.name, sizeof(dirname));
177    bash_spaces(dirname);
178    /* Timeout Hello after 10 mins */
179    btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
180    if (!bnet_fsend(fd, hello, dirname)) {
181       stop_bsock_timer(tid);
182       Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to File daemon on \"%s:%d\". ERR=%s\n"), 
183            fd->host(), fd->port(), bnet_strerror(fd));
184       return 0;
185    }
186    Dmsg1(50, "Sent: %s", fd->msg);
187
188    /* TLS Requirement */
189    if (client->tls_enable) {
190      if (client->tls_require) {
191         tls_local_need = BNET_TLS_REQUIRED;
192      } else {
193         tls_local_need = BNET_TLS_OK;
194      }
195    }
196
197    auth_success = cram_md5_respond(fd, client->password, &tls_remote_need, &compatible);
198    if (auth_success) {
199       auth_success = cram_md5_challenge(fd, client->password, tls_local_need, compatible);
200       if (!auth_success) {
201          Dmsg1(50, "cram_auth failed for %s\n", fd->who());
202       }
203    } else {
204       Dmsg1(50, "cram_get_auth failed for %s\n", fd->who());
205    }
206    if (!auth_success) {
207       stop_bsock_timer(tid);
208       Dmsg0(50, _("Director and File daemon passwords or names not the same.\n"));
209       Jmsg(jcr, M_FATAL, 0,
210             _("Unable to authenticate with File daemon on \"%s:%d\". Possible causes:\n"
211             "Passwords or names not the same or\n"
212             "Maximum Concurrent Jobs exceeded on the FD or\n"
213             "FD networking messed up (restart daemon).\n"
214             "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
215             fd->host(), fd->port());
216       return 0;
217    }
218
219    /* Verify that the remote host is willing to meet our TLS requirements */
220    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
221       stop_bsock_timer(tid);
222       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: FD \"%s:%s\" did not advertise required TLS support.\n"),
223            fd->who(), fd->host());
224       return 0;
225    }
226
227    /* Verify that we are willing to meet the remote host's requirements */
228    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
229       stop_bsock_timer(tid);
230       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: FD on \"%s:%d\" requires TLS.\n"),
231            fd->host(), fd->port());
232       return 0;
233    }
234
235    /* Is TLS Enabled? */
236    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
237       /* Engage TLS! Full Speed Ahead! */
238       if (!bnet_tls_client(client->tls_ctx, fd, client->tls_allowed_cns)) {
239
240          stop_bsock_timer(tid);
241          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with FD on \"%s:%d\".\n"),
242               fd->host(), fd->port());
243          return 0;
244       }
245    }
246
247    Dmsg1(116, ">filed: %s", fd->msg);
248    if (bnet_recv(fd) <= 0) {
249       stop_bsock_timer(tid);
250       Dmsg1(50, _("Bad response from File daemon to Hello command: ERR=%s\n"),
251          bnet_strerror(fd));
252       Jmsg(jcr, M_FATAL, 0, _("Bad response from File daemon on \"%s:%d\" to Hello command: ERR=%s\n"),
253          fd->host(), fd->port(), bnet_strerror(fd));
254       return 0;
255    }
256    Dmsg1(110, "<stored: %s", fd->msg);
257    stop_bsock_timer(tid);
258    if (strncmp(fd->msg, FDOKhello, sizeof(FDOKhello)) != 0) {
259       Dmsg0(50, _("File daemon rejected Hello command\n"));
260       Jmsg(jcr, M_FATAL, 0, _("File daemon on \"%s:%d\" rejected Hello command\n"),
261            fd->host(), fd->port());
262       return 0;
263    }
264    return 1;
265 }
266
267 /*********************************************************************
268  *
269  */
270 int authenticate_user_agent(UAContext *uac)
271 {
272    char name[MAX_NAME_LENGTH];
273    int tls_local_need = BNET_TLS_NONE;
274    int tls_remote_need = BNET_TLS_NONE;
275    int compatible = true;
276    CONRES *cons = NULL;
277    BSOCK *ua = uac->UA_sock;
278    bool auth_success = false;
279    TLS_CONTEXT *tls_ctx = NULL;
280    alist *verify_list = NULL;
281  
282
283 //  Emsg4(M_INFO, 0, _("UA Hello from %s:%s:%d is invalid. Len=%d\n"), ua->who(),
284 //          ua->host(), ua->port(), ua->msglen);
285    if (ua->msglen < 16 || ua->msglen >= MAX_NAME_LENGTH + 15) {
286       Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Len=%d\n"), ua->who(),
287             ua->host(), ua->port(), ua->msglen);
288       return 0;
289    }
290
291    if (sscanf(ua->msg, "Hello %127s calling\n", name) != 1) {
292       ua->msg[100] = 0;               /* terminate string */
293       Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Got: %s\n"), ua->who(),
294             ua->host(), ua->port(), ua->msg);
295       return 0;
296    }
297
298    name[sizeof(name)-1] = 0;             /* terminate name */
299    if (strcmp(name, "*UserAgent*") == 0) {  /* default console */
300       /* TLS Requirement */
301       if (director->tls_enable) {
302          if (director->tls_require) {
303             tls_local_need = BNET_TLS_REQUIRED;
304          } else {
305             tls_local_need = BNET_TLS_OK;
306          }
307       }
308
309       if (director->tls_verify_peer) {
310          verify_list = director->tls_allowed_cns;
311       }
312
313       auth_success = cram_md5_challenge(ua, director->password, tls_local_need,
314                                         compatible) &&
315                      cram_md5_respond(ua, director->password, &tls_remote_need, &compatible);
316    } else {
317       unbash_spaces(name);
318       cons = (CONRES *)GetResWithName(R_CONSOLE, name);
319       if (cons) {
320          /* TLS Requirement */
321          if (cons->tls_enable) {
322             if (cons->tls_require) {
323                tls_local_need = BNET_TLS_REQUIRED;
324             } else {
325                tls_local_need = BNET_TLS_OK;
326             }
327          }
328
329          if (cons->tls_verify_peer) {
330             verify_list = cons->tls_allowed_cns;
331          }
332
333          auth_success = cram_md5_challenge(ua, cons->password, tls_local_need,
334                                            compatible) &&
335                      cram_md5_respond(ua, cons->password, &tls_remote_need, &compatible);
336
337          if (auth_success) {
338             uac->cons = cons;         /* save console resource pointer */
339          }
340       } else {
341          auth_success = false;
342          goto auth_done;
343       }
344    }
345
346    /* Verify that the remote peer is willing to meet our TLS requirements */
347    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
348       Emsg0(M_FATAL, 0, _("Authorization problem:"
349             " Remote client did not advertise required TLS support.\n"));
350       auth_success = false;
351       goto auth_done;
352    }
353
354    /* Verify that we are willing to meet the peer's requirements */
355    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
356       Emsg0(M_FATAL, 0, _("Authorization problem:"
357             " Remote client requires TLS.\n"));
358       auth_success = false;
359       goto auth_done;
360    }
361
362    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
363       if (cons) {
364          tls_ctx = cons->tls_ctx;
365       } else {
366          tls_ctx = director->tls_ctx;
367       }
368
369       /* Engage TLS! Full Speed Ahead! */
370       if (!bnet_tls_server(tls_ctx, ua, verify_list)) {
371          Emsg0(M_ERROR, 0, _("TLS negotiation failed.\n"));
372          auth_success = false;
373          goto auth_done;
374       }
375    }
376
377
378 /* Authorization Completed */
379 auth_done:
380    if (!auth_success) {
381       bnet_fsend(ua, "%s", _(Dir_sorry));
382       Emsg4(M_ERROR, 0, _("Unable to authenticate console \"%s\" at %s:%s:%d.\n"),
383             name, ua->who(), ua->host(), ua->port());
384       sleep(5);
385       return 0;
386    }
387    bnet_fsend(ua, _("1000 OK: %s Version: %s (%s)\n"), my_name, VERSION, BDATE);
388    return 1;
389 }