]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/authenticate.c
a8fdbbbdda11097d7df2f058827c0c6b512df770
[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)) {
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)) {
239          stop_bsock_timer(tid);
240          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with FD on \"%s:%d\".\n"),
241               fd->host(), fd->port());
242          return 0;
243       }
244    }
245
246    Dmsg1(116, ">filed: %s", fd->msg);
247    if (bnet_recv(fd) <= 0) {
248       stop_bsock_timer(tid);
249       Dmsg1(50, _("Bad response from File daemon to Hello command: ERR=%s\n"),
250          bnet_strerror(fd));
251       Jmsg(jcr, M_FATAL, 0, _("Bad response from File daemon on \"%s:%d\" to Hello command: ERR=%s\n"),
252          fd->host(), fd->port(), bnet_strerror(fd));
253       return 0;
254    }
255    Dmsg1(110, "<stored: %s", fd->msg);
256    stop_bsock_timer(tid);
257    if (strncmp(fd->msg, FDOKhello, sizeof(FDOKhello)) != 0) {
258       Dmsg0(50, _("File daemon rejected Hello command\n"));
259       Jmsg(jcr, M_FATAL, 0, _("File daemon on \"%s:%d\" rejected Hello command\n"),
260            fd->host(), fd->port());
261       return 0;
262    }
263    return 1;
264 }
265
266 /*********************************************************************
267  *
268  */
269 int authenticate_user_agent(UAContext *uac)
270 {
271    char name[MAX_NAME_LENGTH];
272    int tls_local_need = BNET_TLS_NONE;
273    int tls_remote_need = BNET_TLS_NONE;
274    int compatible = true;
275    CONRES *cons = NULL;
276    BSOCK *ua = uac->UA_sock;
277    bool auth_success = false;
278    TLS_CONTEXT *tls_ctx = NULL;
279    alist *verify_list = NULL;
280  
281
282 //  Emsg4(M_INFO, 0, _("UA Hello from %s:%s:%d is invalid. Len=%d\n"), ua->who(),
283 //          ua->host(), ua->port(), ua->msglen);
284    if (ua->msglen < 16 || ua->msglen >= MAX_NAME_LENGTH + 15) {
285       Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Len=%d\n"), ua->who(),
286             ua->host(), ua->port(), ua->msglen);
287       return 0;
288    }
289
290    if (sscanf(ua->msg, "Hello %127s calling\n", name) != 1) {
291       ua->msg[100] = 0;               /* terminate string */
292       Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Got: %s\n"), ua->who(),
293             ua->host(), ua->port(), ua->msg);
294       return 0;
295    }
296
297    name[sizeof(name)-1] = 0;             /* terminate name */
298    if (strcmp(name, "*UserAgent*") == 0) {  /* default console */
299       /* TLS Requirement */
300       if (director->tls_enable) {
301          if (director->tls_require) {
302             tls_local_need = BNET_TLS_REQUIRED;
303          } else {
304             tls_local_need = BNET_TLS_OK;
305          }
306       }
307
308       if (director->tls_verify_peer) {
309          verify_list = director->tls_allowed_cns;
310       }
311
312       auth_success = cram_md5_challenge(ua, director->password, tls_local_need,
313                                         compatible) &&
314                      cram_md5_respond(ua, director->password, &tls_remote_need, &compatible);
315    } else {
316       unbash_spaces(name);
317       cons = (CONRES *)GetResWithName(R_CONSOLE, name);
318       if (cons) {
319          /* TLS Requirement */
320          if (cons->tls_enable) {
321             if (cons->tls_require) {
322                tls_local_need = BNET_TLS_REQUIRED;
323             } else {
324                tls_local_need = BNET_TLS_OK;
325             }
326          }
327
328          if (cons->tls_verify_peer) {
329             verify_list = cons->tls_allowed_cns;
330          }
331
332          auth_success = cram_md5_challenge(ua, cons->password, tls_local_need,
333                                            compatible) &&
334                      cram_md5_respond(ua, cons->password, &tls_remote_need, &compatible);
335
336          if (auth_success) {
337             uac->cons = cons;         /* save console resource pointer */
338          }
339       } else {
340          auth_success = false;
341          goto auth_done;
342       }
343    }
344
345    /* Verify that the remote peer is willing to meet our TLS requirements */
346    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
347       Emsg0(M_FATAL, 0, _("Authorization problem:"
348             " Remote client did not advertise required TLS support.\n"));
349       auth_success = false;
350       goto auth_done;
351    }
352
353    /* Verify that we are willing to meet the peer's requirements */
354    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
355       Emsg0(M_FATAL, 0, _("Authorization problem:"
356             " Remote client requires TLS.\n"));
357       auth_success = false;
358       goto auth_done;
359    }
360
361    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
362       if (cons) {
363          tls_ctx = cons->tls_ctx;
364       } else {
365          tls_ctx = director->tls_ctx;
366       }
367
368       /* Engage TLS! Full Speed Ahead! */
369       if (!bnet_tls_server(tls_ctx, ua, verify_list)) {
370          Emsg0(M_ERROR, 0, _("TLS negotiation failed.\n"));
371          auth_success = false;
372          goto auth_done;
373       }
374    }
375
376
377 /* Authorization Completed */
378 auth_done:
379    if (!auth_success) {
380       bnet_fsend(ua, "%s", _(Dir_sorry));
381       Emsg4(M_ERROR, 0, _("Unable to authenticate console \"%s\" at %s:%s:%d.\n"),
382             name, ua->who(), ua->host(), ua->port());
383       sleep(5);
384       return 0;
385    }
386    bnet_fsend(ua, _("1000 OK: %s Version: %s (%s)\n"), my_name, VERSION, BDATE);
387    return 1;
388 }