]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/authenticate.c
Fix FD crash when plugin running and cancel given
[bacula/bacula] / bacula / src / filed / authenticate.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  * Authenticate Director who is attempting to connect.
30  *
31  *   Kern Sibbald, October 2000
32  *
33  *   Version $Id$
34  *
35  */
36
37 #include "bacula.h"
38 #include "filed.h"
39
40 const int dbglvl = 50;
41
42 /* Version at end of Hello
43  *   prior to 10Mar08 no version
44  *   1 10Mar08
45  *   2 13Mar09 - added the ability to restore from multiple storages
46  */
47 static char OK_hello[]  = "2000 OK Hello 2\n";
48 static char Dir_sorry[] = "2999 Authentication failed.\n";
49 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
50
51 /*********************************************************************
52  *
53  */
54 static bool authenticate(int rcode, BSOCK *bs, JCR* jcr)
55 {
56    POOLMEM *dirname = get_pool_memory(PM_MESSAGE);
57    DIRRES *director = NULL;
58    int tls_local_need = BNET_TLS_NONE;
59    int tls_remote_need = BNET_TLS_NONE;
60    int compatible = true;                 /* Want md5 compatible DIR */
61    bool auth_success = false;
62    alist *verify_list = NULL;
63    btimer_t *tid = NULL;
64
65    if (rcode != R_DIRECTOR) {
66       Dmsg1(dbglvl, "I only authenticate directors, not %d\n", rcode);
67       Jmsg1(jcr, M_FATAL, 0, _("I only authenticate directors, not %d\n"), rcode);
68       goto auth_fatal;
69    }
70    if (bs->msglen < 25 || bs->msglen > 500) {
71       Dmsg2(dbglvl, "Bad Hello command from Director at %s. Len=%d.\n",
72             bs->who(), bs->msglen);
73       char addr[64];
74       char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
75       Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
76              who, bs->msglen);
77       goto auth_fatal;
78    }
79    dirname = check_pool_memory_size(dirname, bs->msglen);
80
81    if (sscanf(bs->msg, "Hello Director %s calling", dirname) != 1) {
82       char addr[64];
83       char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
84       bs->msg[100] = 0;
85       Dmsg2(dbglvl, "Bad Hello command from Director at %s: %s\n",
86             bs->who(), bs->msg);
87       Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
88             who, bs->msg);
89       goto auth_fatal;
90    }
91    unbash_spaces(dirname);
92    foreach_res(director, R_DIRECTOR) {
93       if (strcmp(director->hdr.name, dirname) == 0)
94          break;
95    }
96    if (!director) {
97       char addr[64];
98       char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
99       Jmsg2(jcr, M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"), 
100             dirname, who);
101       goto auth_fatal;
102    }
103
104    if (have_tls) {
105       /* TLS Requirement */
106       if (director->tls_enable) {
107          if (director->tls_require) {
108             tls_local_need = BNET_TLS_REQUIRED;
109          } else {
110             tls_local_need = BNET_TLS_OK;
111          }
112       }
113
114       if (director->tls_authenticate) {
115          tls_local_need = BNET_TLS_REQUIRED;
116       }
117
118       if (director->tls_verify_peer) {
119          verify_list = director->tls_allowed_cns;
120       }
121    }
122
123    tid = start_bsock_timer(bs, AUTH_TIMEOUT);
124    /* Challenge the director */
125    auth_success = cram_md5_challenge(bs, director->password, tls_local_need, compatible);  
126    if (job_canceled(jcr)) {
127       auth_success = false;
128       goto auth_fatal;                   /* quick exit */
129    }
130    if (auth_success) {
131       auth_success = cram_md5_respond(bs, director->password, &tls_remote_need, &compatible);
132       if (!auth_success) {
133           char addr[64];
134           char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
135           Dmsg1(dbglvl, "cram_get_auth failed for %s\n", who);
136       }
137    } else {
138        char addr[64];
139        char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
140        Dmsg1(dbglvl, "cram_auth failed for %s\n", who);
141    }
142    if (!auth_success) {
143        Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"),
144              bs->who());
145        goto auth_fatal;
146    }
147
148    /* Verify that the remote host is willing to meet our TLS requirements */
149    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
150       Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
151            " advertize required TLS support.\n"));
152       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
153       auth_success = false;
154       goto auth_fatal;
155    }
156
157    /* Verify that we are willing to meet the remote host's requirements */
158    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
159       Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
160       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
161       auth_success = false;
162       goto auth_fatal;
163    }
164
165    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
166       /* Engage TLS! Full Speed Ahead! */
167       if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) {
168          Jmsg0(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
169          auth_success = false;
170          goto auth_fatal;
171       }
172       if (director->tls_authenticate) {         /* authentication only? */
173          bs->free_tls();                        /* shutodown tls */
174       }
175    }
176
177 auth_fatal:
178    if (tid) {
179       stop_bsock_timer(tid);
180       tid = NULL;
181    }
182    free_pool_memory(dirname);
183    jcr->director = director;
184    /* Single thread all failures to avoid DOS */
185    if (!auth_success) {
186       P(mutex);
187       bmicrosleep(6, 0);
188       V(mutex);
189    }
190    return auth_success;
191 }
192
193 /*
194  * Inititiate the communications with the Director.
195  * He has made a connection to our server.
196  *
197  * Basic tasks done here:
198  *   We read Director's initial message and authorize him.
199  *
200  */
201 int authenticate_director(JCR *jcr)
202 {
203    BSOCK *dir = jcr->dir_bsock;
204
205    if (!authenticate(R_DIRECTOR, dir, jcr)) {
206       bnet_fsend(dir, "%s", Dir_sorry);
207       Emsg0(M_FATAL, 0, _("Unable to authenticate Director\n"));
208       return 0;
209    }
210    return bnet_fsend(dir, "%s", OK_hello);
211 }
212
213 /*
214  * First prove our identity to the Storage daemon, then
215  * make him prove his identity.
216  */
217 int authenticate_storagedaemon(JCR *jcr)
218 {
219    BSOCK *sd = jcr->store_bsock;
220    int tls_local_need = BNET_TLS_NONE;
221    int tls_remote_need = BNET_TLS_NONE;
222    int compatible = true;
223    bool auth_success = false;
224
225    btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
226
227    /* TLS Requirement */
228    if (have_tls && me->tls_enable) {
229       if (me->tls_require) {
230          tls_local_need = BNET_TLS_REQUIRED;
231       } else {
232          tls_local_need = BNET_TLS_OK;
233       }
234    }
235
236    if (me->tls_authenticate) {
237       tls_local_need = BNET_TLS_REQUIRED;
238    }
239
240    if (job_canceled(jcr)) {
241       auth_success = false;     /* force quick exit */
242       goto auth_fatal;
243    }
244
245    /* Respond to SD challenge */
246    auth_success = cram_md5_respond(sd, jcr->sd_auth_key, &tls_remote_need, &compatible);
247    if (job_canceled(jcr)) {
248       auth_success = false;     /* force quick exit */
249       goto auth_fatal;
250    }
251    if (!auth_success) {
252       Dmsg1(dbglvl, "cram_respond failed for %s\n", sd->who());
253    } else {
254       /* Now challenge him */
255       auth_success = cram_md5_challenge(sd, jcr->sd_auth_key, tls_local_need, compatible);
256       if (!auth_success) {
257          Dmsg1(dbglvl, "cram_challenge failed for %s\n", sd->who());
258       }
259    }
260
261    if (!auth_success) {
262       Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
263        "Please see http://www.bacula.org/en/rel-manual/Bacula_Freque_Asked_Questi.html#SECTION003760000000000000000 for help.\n"));
264       goto auth_fatal;
265    }
266
267    /* Verify that the remote host is willing to meet our TLS requirements */
268    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
269       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" 
270            " advertize required TLS support.\n"));
271       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
272       auth_success = false;
273       goto auth_fatal;
274    }
275
276    /* Verify that we are willing to meet the remote host's requirements */
277    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
278       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
279       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
280       auth_success = false;
281       goto auth_fatal;
282    }
283
284    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
285       /* Engage TLS! Full Speed Ahead! */
286       if (!bnet_tls_client(me->tls_ctx, sd, NULL)) {
287          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
288          auth_success = false;
289          goto auth_fatal;
290       }
291       if (me->tls_authenticate) {           /* tls authentication only? */
292          sd->free_tls();                    /* yes, shutdown tls */
293       }
294    }
295
296 auth_fatal:
297    /* Destroy session key */
298    memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
299    stop_bsock_timer(tid);
300    /* Single thread all failures to avoid DOS */
301    if (!auth_success) {
302       P(mutex);
303       bmicrosleep(6, 0);
304       V(mutex);
305    }
306    return auth_success;
307 }