]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/authenticate.c
Tweaks
[bacula/bacula] / bacula / src / filed / authenticate.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2007 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 John Walker.
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 static char OK_hello[]  = "2000 OK Hello\n";
43 static char Dir_sorry[] = "2999 No go\n";
44 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
45
46 /*********************************************************************
47  *
48  */
49 static bool authenticate(int rcode, BSOCK *bs, JCR* jcr)
50 {
51    POOLMEM *dirname = get_pool_memory(PM_MESSAGE);
52    DIRRES *director = NULL;
53    int tls_local_need = BNET_TLS_NONE;
54    int tls_remote_need = BNET_TLS_NONE;
55    int compatible = true;                 /* Want md5 compatible DIR */
56    bool auth_success = false;
57    alist *verify_list = NULL;
58    btimer_t *tid = NULL;
59
60    if (rcode != R_DIRECTOR) {
61       Dmsg1(dbglvl, "I only authenticate directors, not %d\n", rcode);
62       Jmsg1(jcr, M_FATAL, 0, _("I only authenticate directors, not %d\n"), rcode);
63       goto auth_fatal;
64    }
65    if (bs->msglen < 25 || bs->msglen > 500) {
66       Dmsg2(dbglvl, "Bad Hello command from Director at %s. Len=%d.\n",
67             bs->who(), bs->msglen);
68       char addr[64];
69       char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
70       Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
71              who, bs->msglen);
72       goto auth_fatal;
73    }
74    dirname = check_pool_memory_size(dirname, bs->msglen);
75
76    if (sscanf(bs->msg, "Hello Director %s calling", dirname) != 1) {
77       char addr[64];
78       char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
79       bs->msg[100] = 0;
80       Dmsg2(dbglvl, "Bad Hello command from Director at %s: %s\n",
81             bs->who(), bs->msg);
82       Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
83             who, bs->msg);
84       goto auth_fatal;
85    }
86    unbash_spaces(dirname);
87    foreach_res(director, R_DIRECTOR) {
88       if (strcmp(director->hdr.name, dirname) == 0)
89          break;
90    }
91    if (!director) {
92       char addr[64];
93       char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
94       Jmsg2(jcr, M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"), 
95             dirname, who);
96       goto auth_fatal;
97    }
98
99    if (have_tls) {
100       /* TLS Requirement */
101       if (director->tls_enable) {
102          if (director->tls_require) {
103             tls_local_need = BNET_TLS_REQUIRED;
104          } else {
105             tls_local_need = BNET_TLS_OK;
106          }
107       }
108
109       if (director->tls_authenticate) {
110          tls_local_need = BNET_TLS_REQUIRED;
111       }
112
113       if (director->tls_verify_peer) {
114          verify_list = director->tls_allowed_cns;
115       }
116    }
117
118    tid = start_bsock_timer(bs, AUTH_TIMEOUT);
119    /* Challenge the director */
120    auth_success = cram_md5_challenge(bs, director->password, tls_local_need, compatible);  
121    if (job_canceled(jcr)) {
122       auth_success = false;
123       goto auth_fatal;                   /* quick exit */
124    }
125    if (auth_success) {
126       auth_success = cram_md5_respond(bs, director->password, &tls_remote_need, &compatible);
127       if (!auth_success) {
128           char addr[64];
129           char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
130           Dmsg1(dbglvl, "cram_get_auth failed for %s\n", who);
131       }
132    } else {
133        char addr[64];
134        char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
135        Dmsg1(dbglvl, "cram_auth failed for %s\n", who);
136    }
137    if (!auth_success) {
138        Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"),
139              bs->who());
140        goto auth_fatal;
141    }
142
143    /* Verify that the remote host is willing to meet our TLS requirements */
144    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
145       Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
146            " advertize required TLS support.\n"));
147       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
148       auth_success = false;
149       goto auth_fatal;
150    }
151
152    /* Verify that we are willing to meet the remote host's requirements */
153    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
154       Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
155       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
156       auth_success = false;
157       goto auth_fatal;
158    }
159
160    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
161       /* Engage TLS! Full Speed Ahead! */
162       if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) {
163          Jmsg0(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
164          auth_success = false;
165          goto auth_fatal;
166       }
167       if (director->tls_authenticate) {         /* authentication only? */
168          bs->free_tls();                        /* shutodown tls */
169       }
170    }
171
172 auth_fatal:
173    if (tid) {
174       stop_bsock_timer(tid);
175       tid = NULL;
176    }
177    free_pool_memory(dirname);
178    jcr->director = director;
179    /* Single thread all failures to avoid DOS */
180    if (!auth_success) {
181       P(mutex);
182       bmicrosleep(6, 0);
183       V(mutex);
184    }
185    return auth_success;
186 }
187
188 /*
189  * Inititiate the communications with the Director.
190  * He has made a connection to our server.
191  *
192  * Basic tasks done here:
193  *   We read Director's initial message and authorize him.
194  *
195  */
196 int authenticate_director(JCR *jcr)
197 {
198    BSOCK *dir = jcr->dir_bsock;
199
200    if (!authenticate(R_DIRECTOR, dir, jcr)) {
201       bnet_fsend(dir, "%s", Dir_sorry);
202       Emsg0(M_FATAL, 0, _("Unable to authenticate Director\n"));
203       return 0;
204    }
205    return bnet_fsend(dir, "%s", OK_hello);
206 }
207
208 /*
209  * First prove our identity to the Storage daemon, then
210  * make him prove his identity.
211  */
212 int authenticate_storagedaemon(JCR *jcr)
213 {
214    BSOCK *sd = jcr->store_bsock;
215    int tls_local_need = BNET_TLS_NONE;
216    int tls_remote_need = BNET_TLS_NONE;
217    int compatible = true;
218    bool auth_success = false;
219
220    btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
221
222    /* TLS Requirement */
223    if (have_tls && me->tls_enable) {
224       if (me->tls_require) {
225          tls_local_need = BNET_TLS_REQUIRED;
226       } else {
227          tls_local_need = BNET_TLS_OK;
228       }
229    }
230
231    if (me->tls_authenticate) {
232       tls_local_need = BNET_TLS_REQUIRED;
233    }
234
235    if (job_canceled(jcr)) {
236       auth_success = false;     /* force quick exit */
237       goto auth_fatal;
238    }
239
240    /* Respond to SD challenge */
241    auth_success = cram_md5_respond(sd, jcr->sd_auth_key, &tls_remote_need, &compatible);
242    if (job_canceled(jcr)) {
243       auth_success = false;     /* force quick exit */
244       goto auth_fatal;
245    }
246    if (!auth_success) {
247       Dmsg1(dbglvl, "cram_respond failed for %s\n", sd->who());
248    } else {
249       /* Now challenge him */
250       auth_success = cram_md5_challenge(sd, jcr->sd_auth_key, tls_local_need, compatible);
251       if (!auth_success) {
252          Dmsg1(dbglvl, "cram_challenge failed for %s\n", sd->who());
253       }
254    }
255
256    if (!auth_success) {
257       Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
258        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
259       goto auth_fatal;
260    }
261
262    /* Verify that the remote host is willing to meet our TLS requirements */
263    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
264       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" 
265            " advertize required TLS support.\n"));
266       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
267       auth_success = false;
268       goto auth_fatal;
269    }
270
271    /* Verify that we are willing to meet the remote host's requirements */
272    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
273       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
274       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
275       auth_success = false;
276       goto auth_fatal;
277    }
278
279    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
280       /* Engage TLS! Full Speed Ahead! */
281       if (!bnet_tls_client(me->tls_ctx, sd, NULL)) {
282          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
283          auth_success = false;
284          goto auth_fatal;
285       }
286       if (me->tls_authenticate) {           /* tls authentication only? */
287          sd->free_tls();                    /* yes, shutdown tls */
288       }
289    }
290
291 auth_fatal:
292    /* Destroy session key */
293    memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
294    stop_bsock_timer(tid);
295    /* Single thread all failures to avoid DOS */
296    if (!auth_success) {
297       P(mutex);
298       bmicrosleep(6, 0);
299       V(mutex);
300    }
301    return auth_success;
302 }