]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/authenticate.c
Backport from BEE
[bacula/bacula] / bacula / src / stored / authenticate.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from many
7    others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    Bacula® is a registered trademark of Kern Sibbald.
15 */
16 /*
17  * Authenticate caller
18  *
19  *   Written by Kern Sibbald, October 2000
20  *
21  */
22
23
24 #include "bacula.h"
25 #include "stored.h"
26
27 extern STORES *me;               /* our Global resource */
28
29
30 const int dbglvl = 50;
31
32 /* Version at end of Hello
33  *   prior to 06Aug13 no version
34  *   1 06Aug13 - added comm line compression
35  *   2 13Dec13 - added api version to status command
36  *   3 22Feb14 - Added SD->SD with SD_Calls_Client
37  */
38 #define SD_VERSION 3
39 #define FD_VERSION 10
40 static char hello_sd[]  = "Hello Bacula SD: Start Job %s %d %d\n";
41
42
43 static char Dir_sorry[] = "3999 No go\n";
44 static char OK_hello[]  = "3000 OK Hello %d\n";
45
46 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
47
48 /*********************************************************************
49  *
50  *
51  */
52 static int authenticate(int rcode, BSOCK *bs, JCR* jcr)
53 {
54    POOLMEM *dirname;
55    DIRRES *director = NULL;
56    int tls_local_need = BNET_TLS_NONE;
57    int tls_remote_need = BNET_TLS_NONE;
58    int compatible = true;                  /* require md5 compatible DIR */
59    bool auth_success = false;
60    alist *verify_list = NULL;
61    int dir_version = 0;
62
63    if (rcode != R_DIRECTOR) {
64       Dmsg1(dbglvl, "I only authenticate Directors, not %d\n", rcode);
65       Jmsg1(jcr, M_FATAL, 0, _("I only authenticate Directors, not %d\n"), rcode);
66       return 0;
67    }
68    if (bs->msglen < 25 || bs->msglen > 500) {
69       Dmsg2(dbglvl, "Bad Hello command from Director at %s. Len=%d.\n",
70             bs->who(), bs->msglen);
71       Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
72             bs->who(), bs->msglen);
73       return 0;
74    }
75    dirname = get_pool_memory(PM_MESSAGE);
76    dirname = check_pool_memory_size(dirname, bs->msglen);
77
78    if (sscanf(bs->msg, "Hello SD: Bacula Director %127s calling %d",
79           dirname, &dir_version) != 2 &&
80        sscanf(bs->msg, "Hello SD: Bacula Director %127s calling",
81           dirname) != 1) {
82       bs->msg[100] = 0;
83       Dmsg2(dbglvl, "Bad Hello command from Director at %s: %s\n",
84             bs->who(), bs->msg);
85       Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
86             bs->who(), bs->msg);
87       free_pool_memory(dirname);
88       return 0;
89    }
90    director = NULL;
91    unbash_spaces(dirname);
92    foreach_res(director, rcode) {
93       if (strcasecmp(director->hdr.name, dirname) == 0) {
94          break;
95       }
96    }
97    if (!director) {
98       Dmsg2(dbglvl, "Connection from unknown Director %s at %s rejected.\n",
99             dirname, bs->who());
100       Jmsg2(jcr, M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"
101        "Please see " MANUAL_AUTH_URL " for help.\n"),
102             dirname, bs->who());
103       free_pool_memory(dirname);
104       return 0;
105    }
106
107    /* TLS Requirement */
108    if (director->tls_enable) {
109       if (director->tls_require) {
110          tls_local_need = BNET_TLS_REQUIRED;
111       } else {
112          tls_local_need = BNET_TLS_OK;
113       }
114    }
115
116    if (director->tls_authenticate) {
117       tls_local_need = BNET_TLS_REQUIRED;
118    }
119
120    if (director->tls_verify_peer) {
121       verify_list = director->tls_allowed_cns;
122    }
123
124    /* Timeout Hello after 10 mins */
125    btimer_t *tid = start_bsock_timer(bs, AUTH_TIMEOUT);
126    auth_success = cram_md5_challenge(bs, director->password, tls_local_need, compatible);
127    if (auth_success) {
128       auth_success = cram_md5_respond(bs, director->password, &tls_remote_need, &compatible);
129       if (!auth_success) {
130          Dmsg1(dbglvl, "cram_get_auth respond failed with Director %s\n", bs->who());
131       }
132    } else {
133       Dmsg1(dbglvl, "cram_auth challenge failed with Director %s\n", bs->who());
134    }
135
136    if (!auth_success) {
137       Jmsg0(jcr, M_FATAL, 0, _("Incorrect password given by Director.\n"
138        "Please see " MANUAL_AUTH_URL " for help.\n"));
139       auth_success = false;
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          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with DIR at \"%s:%d\"\n"),
164             bs->host(), bs->port());
165          auth_success = false;
166          goto auth_fatal;
167       }
168       if (director->tls_authenticate) {     /* authenticate with tls only? */
169          bs->free_tls();                    /* yes, shut it down */
170       }
171    }
172
173 auth_fatal:
174    stop_bsock_timer(tid);
175    free_pool_memory(dirname);
176    jcr->director = director;
177    return auth_success;
178 }
179
180 /*
181  * Inititiate the message channel with the Director.
182  * He has made a connection to our server.
183  *
184  * Basic tasks done here:
185  *   Assume the Hello message is already in the input
186  *     buffer.  We then authenticate him.
187  *   Get device, media, and pool information from Director
188  *
189  *   This is the channel across which we will send error
190  *     messages and job status information.
191  */
192 int authenticate_director(JCR *jcr)
193 {
194    BSOCK *dir = jcr->dir_bsock;
195
196    if (!authenticate(R_DIRECTOR, dir, jcr)) {
197       dir->fsend(Dir_sorry);
198       Dmsg1(dbglvl, "Unable to authenticate Director at %s.\n", dir->who());
199       Jmsg1(jcr, M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who());
200       bmicrosleep(5, 0);
201       return 0;
202    }
203    return dir->fsend(OK_hello, SD_VERSION);
204 }
205
206 int authenticate_filed(JCR *jcr)
207 {
208    BSOCK *fd = jcr->file_bsock;
209    int tls_local_need = BNET_TLS_NONE;
210    int tls_remote_need = BNET_TLS_NONE;
211    int compatible = true;                 /* require md5 compatible FD */
212    bool auth_success = false;
213    alist *verify_list = NULL;
214
215    /* TLS Requirement */
216    if (me->tls_enable) {
217       if (me->tls_require) {
218          tls_local_need = BNET_TLS_REQUIRED;
219       } else {
220          tls_local_need = BNET_TLS_OK;
221       }
222    }
223
224    if (me->tls_authenticate) {
225       tls_local_need = BNET_TLS_REQUIRED;
226    }
227
228    if (me->tls_verify_peer) {
229       verify_list = me->tls_allowed_cns;
230    }
231
232    /* Timeout Hello after 5 mins */
233    btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
234    /* Challenge FD */
235    Dmsg0(050, "Challenge FD\n");
236    auth_success = cram_md5_challenge(fd, jcr->sd_auth_key, tls_local_need, compatible);
237    if (auth_success) {
238        /* Respond to his challenge */
239        Dmsg0(050, "Respond to FD challenge\n");
240        auth_success = cram_md5_respond(fd, jcr->sd_auth_key, &tls_remote_need, &compatible);
241        if (!auth_success) {
242           Dmsg1(dbglvl, "Respond cram-get-auth respond failed with FD: %s\n", fd->who());
243        }
244    } else {
245       Dmsg1(dbglvl, "Challenge cram-auth failed with FD: %s\n", fd->who());
246    }
247
248    if (!auth_success) {
249       Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
250        "Please see " MANUAL_AUTH_URL " for help.\n"),
251            fd->who());
252       auth_success = false;
253       goto auth_fatal;
254    }
255
256    /* Verify that the remote host is willing to meet our TLS requirements */
257    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
258       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
259            " advertize required TLS support.\n"));
260       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
261       auth_success = false;
262       goto auth_fatal;
263    }
264
265    /* Verify that we are willing to meet the remote host's requirements */
266    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
267       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
268       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
269       auth_success = false;
270       goto auth_fatal;
271    }
272
273    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
274       /* Engage TLS! Full Speed Ahead! */
275       if (!bnet_tls_server(me->tls_ctx, fd, verify_list)) {
276          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with FD at \"%s:%d\"\n"),
277             fd->host(), fd->port());
278          auth_success = false;
279          goto auth_fatal;
280       }
281       if (me->tls_authenticate) {          /* tls authenticate only? */
282          fd->free_tls();                   /* yes, shut it down */
283       }
284    }
285
286 auth_fatal:
287    stop_bsock_timer(tid);
288    if (!auth_success) {
289       Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
290        "Please see " MANUAL_AUTH_URL " for help.\n"),
291            fd->who());
292    }
293    jcr->authenticated = auth_success;
294    if (auth_success && jcr->FDVersion >= 5) {
295       /* Send hello and our version to FD */
296       fd->fsend(OK_hello, SD_VERSION);
297    }
298    return auth_success;
299 }
300
301 /*
302  * First prove our identity to the Storage daemon, then
303  * make him prove his identity.
304  */
305 bool authenticate_storagedaemon(JCR *jcr, char *Job)
306 {
307    BSOCK *sd = jcr->store_bsock;
308    int tls_local_need = BNET_TLS_NONE;
309    int tls_remote_need = BNET_TLS_NONE;
310    int compatible = true;
311    bool auth_success = false;
312    int sd_version = 0;
313
314    btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
315
316    /* TLS Requirement */
317    if (have_tls && me->tls_enable) {
318       if (me->tls_require) {
319          tls_local_need = BNET_TLS_REQUIRED;
320       } else {
321          tls_local_need = BNET_TLS_OK;
322       }
323    }
324
325    if (me->tls_authenticate) {
326       tls_local_need = BNET_TLS_REQUIRED;
327    }
328
329    if (job_canceled(jcr)) {
330       auth_success = false;     /* force quick exit */
331       goto auth_fatal;
332    }
333
334
335    bash_spaces(Job);
336    sd->fsend(hello_sd, Job, FD_VERSION, SD_VERSION);
337    Dmsg1(100, "Send to SD: %s\n", sd->msg);
338
339    /* Respond to SD challenge */
340    Dmsg0(050, "Respond to SD challenge\n");
341    auth_success = cram_md5_respond(sd, jcr->sd_auth_key, &tls_remote_need, &compatible);
342    if (job_canceled(jcr)) {
343       auth_success = false;     /* force quick exit */
344       goto auth_fatal;
345    }
346    if (!auth_success) {
347       Dmsg1(dbglvl, "cram_respond failed for SD: %s\n", sd->who());
348    } else {
349       /* Now challenge him */
350       Dmsg0(050, "Challenge SD\n");
351       auth_success = cram_md5_challenge(sd, jcr->sd_auth_key, tls_local_need, compatible);
352       if (!auth_success) {
353          Dmsg1(dbglvl, "cram_challenge failed for SD: %s\n", sd->who());
354       }
355    }
356
357    if (!auth_success) {
358       Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
359        "Please see " MANUAL_AUTH_URL " for help.\n"));
360       goto auth_fatal;
361    } else {
362       Dmsg0(050, "Authorization with SD is OK\n");
363    }
364
365    /* Verify that the remote host is willing to meet our TLS requirements */
366    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
367       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
368            " advertize required TLS support.\n"));
369       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
370       auth_success = false;
371       goto auth_fatal;
372    }
373
374    /* Verify that we are willing to meet the remote host's requirements */
375    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
376       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
377       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
378       auth_success = false;
379       goto auth_fatal;
380    }
381
382    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
383       /* Engage TLS! Full Speed Ahead! */
384       if (!bnet_tls_client(me->tls_ctx, sd, NULL)) {
385          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
386          auth_success = false;
387          goto auth_fatal;
388       }
389       if (me->tls_authenticate) {           /* tls authentication only? */
390          sd->free_tls();                    /* yes, shutdown tls */
391       }
392    }
393    if (sd->recv() <= 0) {
394       auth_success = false;
395       goto auth_fatal;
396    }
397    sscanf(sd->msg, "3000 OK Hello %d", &sd_version);
398
399    /* At this point, we have successfully connected */
400
401 auth_fatal:
402    /* Destroy session key */
403    memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
404    stop_bsock_timer(tid);
405    /* Single thread all failures to avoid DOS */
406    if (!auth_success) {
407       P(mutex);
408       bmicrosleep(6, 0);
409       V(mutex);
410    }
411    return auth_success;
412 }