]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/authenticate.c
7572cd731a6af577479c05283ddd426b1f770d86
[bacula/bacula] / bacula / src / stored / authenticate.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2015 Kern Sibbald
5    Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
6
7    The original author of Bacula is Kern Sibbald, with contributions
8    from many others, a complete list can be found in the file AUTHORS.
9
10    You may use this file and others of this release according to the
11    license defined in the LICENSE file, which includes the Affero General
12    Public License, v3.0 ("AGPLv3") and some additional permissions and
13    terms pursuant to its AGPLv3 Section 7.
14
15    This notice must be preserved when any source code is 
16    conveyed and/or propagated.
17
18    Bacula(R) is a registered trademark of Kern Sibbald.
19 */
20 /*
21  * Authenticate caller
22  *
23  *   Written by Kern Sibbald, October 2000
24  *
25  */
26
27
28 #include "bacula.h"
29 #include "stored.h"
30
31 extern STORES *me;               /* our Global resource */
32
33 const int dbglvl = 50;
34
35 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
36
37 /*
38  * Authenticate the Director
39  */
40 bool authenticate_director(JCR* jcr)
41 {
42    DIRRES *director = jcr->director;
43    int tls_local_need = BNET_TLS_NONE;
44    int tls_remote_need = BNET_TLS_NONE;
45    int compatible = true;                  /* require md5 compatible DIR */
46    bool auth_success = false;
47    alist *verify_list = NULL;
48    BSOCK *dir = jcr->dir_bsock;
49
50    /* TLS Requirement */
51    if (director->tls_enable) {
52       if (director->tls_require) {
53          tls_local_need = BNET_TLS_REQUIRED;
54       } else {
55          tls_local_need = BNET_TLS_OK;
56       }
57    }
58
59    if (director->tls_authenticate) {
60       tls_local_need = BNET_TLS_REQUIRED;
61    }
62
63    if (director->tls_verify_peer) {
64       verify_list = director->tls_allowed_cns;
65    }
66
67    /* Timeout authentication after 10 mins */
68    btimer_t *tid = start_bsock_timer(dir, AUTH_TIMEOUT);
69    auth_success = cram_md5_challenge(dir, director->password, tls_local_need, compatible);
70    if (auth_success) {
71       auth_success = cram_md5_respond(dir, director->password, &tls_remote_need, &compatible);
72       if (!auth_success) {
73          Dmsg1(dbglvl, "cram_get_auth respond failed with Director %s\n", dir->who());
74       }
75    } else {
76       Dmsg1(dbglvl, "cram_auth challenge failed with Director %s\n", dir->who());
77    }
78
79    if (!auth_success) {
80       Jmsg0(jcr, M_FATAL, 0, _("Incorrect password given by Director.\n"
81        "For help, please see: " MANUAL_AUTH_URL "\n"));
82       auth_success = false;
83       goto auth_fatal;
84    }
85
86    /* Verify that the remote host is willing to meet our TLS requirements */
87    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
88       Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
89            " advertize required TLS support.\n"));
90       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
91       auth_success = false;
92       goto auth_fatal;
93    }
94
95    /* Verify that we are willing to meet the remote host's requirements */
96    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
97       Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
98       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
99       auth_success = false;
100       goto auth_fatal;
101    }
102
103    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
104       /* Engage TLS! Full Speed Ahead! */
105       if (!bnet_tls_server(director->tls_ctx, dir, verify_list)) {
106          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with DIR at \"%s:%d\"\n"),
107             dir->host(), dir->port());
108          auth_success = false;
109          goto auth_fatal;
110       }
111       if (director->tls_authenticate) {     /* authenticate with tls only? */
112          dir->free_tls();                   /* yes, shut it down */
113       }
114    }
115
116 auth_fatal:
117    stop_bsock_timer(tid);
118    jcr->director = director;
119    if (auth_success) {
120       return send_hello_ok(dir);
121    }
122    send_sorry(dir);
123    Dmsg1(dbglvl, "Unable to authenticate Director at %s.\n", dir->who());
124    Jmsg1(jcr, M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who());
125    bmicrosleep(5, 0);
126    return false;
127 }
128
129
130 int authenticate_filed(JCR *jcr, BSOCK *fd, int FDVersion)
131 {
132    int tls_local_need = BNET_TLS_NONE;
133    int tls_remote_need = BNET_TLS_NONE;
134    int compatible = true;                 /* require md5 compatible FD */
135    bool auth_success = false;
136    alist *verify_list = NULL;
137
138    /* TLS Requirement */
139    if (me->tls_enable) {
140       if (me->tls_require) {
141          tls_local_need = BNET_TLS_REQUIRED;
142       } else {
143          tls_local_need = BNET_TLS_OK;
144       }
145    }
146
147    if (me->tls_authenticate) {
148       tls_local_need = BNET_TLS_REQUIRED;
149    }
150
151    if (me->tls_verify_peer) {
152       verify_list = me->tls_allowed_cns;
153    }
154
155    /* Timeout authentication after 5 mins */
156    btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
157    /* Challenge FD */
158    Dmsg0(050, "Challenge FD\n");
159    auth_success = cram_md5_challenge(fd, jcr->sd_auth_key, tls_local_need, compatible);
160    if (auth_success) {
161        /* Respond to his challenge */
162        Dmsg0(050, "Respond to FD challenge\n");
163        auth_success = cram_md5_respond(fd, jcr->sd_auth_key, &tls_remote_need, &compatible);
164        if (!auth_success) {
165           Dmsg1(dbglvl, "Respond cram-get-auth respond failed with FD: %s\n", fd->who());
166        }
167    } else {
168       Dmsg1(dbglvl, "Challenge cram-auth failed with FD: %s\n", fd->who());
169    }
170
171    if (!auth_success) {
172       Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
173        "For help, please see: " MANUAL_AUTH_URL "\n"),
174            fd->who());
175       auth_success = false;
176       goto auth_fatal;
177    }
178
179    /* Verify that the remote host is willing to meet our TLS requirements */
180    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
181       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
182            " advertize required TLS support.\n"));
183       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
184       auth_success = false;
185       goto auth_fatal;
186    }
187
188    /* Verify that we are willing to meet the remote host's requirements */
189    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
190       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
191       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
192       auth_success = false;
193       goto auth_fatal;
194    }
195
196    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
197       /* Engage TLS! Full Speed Ahead! */
198       if (!bnet_tls_server(me->tls_ctx, fd, verify_list)) {
199          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with FD at \"%s:%d\"\n"),
200             fd->host(), fd->port());
201          auth_success = false;
202          goto auth_fatal;
203       }
204       if (me->tls_authenticate) {          /* tls authenticate only? */
205          fd->free_tls();                   /* yes, shut it down */
206       }
207    }
208
209 auth_fatal:
210    stop_bsock_timer(tid);
211    if (!auth_success) {
212       Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
213        "For help, please see: " MANUAL_AUTH_URL "\n"),
214            fd->who());
215    }
216
217    /* Version 5 of the protocol is a bit special, it is used by both 6.0.0
218     * Enterprise version and 7.0.x Community version, but do not support the
219     * same level of features. As nobody is using the 6.0.0 release, we can
220     * be pretty sure that the FD in version 5 is a community FD.
221     */
222    if (auth_success && (FDVersion >= 9 || FDVersion == 5)) {
223       send_hello_ok(fd);
224    }
225    return auth_success;
226 }
227
228 /*
229  * First prove our identity to the Storage daemon, then
230  * make him prove his identity.
231  */
232 bool authenticate_storagedaemon(JCR *jcr)
233 {
234    BSOCK *sd = jcr->store_bsock;
235    int tls_local_need = BNET_TLS_NONE;
236    int tls_remote_need = BNET_TLS_NONE;
237    int compatible = true;
238    bool auth_success = false;
239    int sd_version = 0;
240
241    btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
242
243    /* TLS Requirement */
244    if (have_tls && me->tls_enable) {
245       if (me->tls_require) {
246          tls_local_need = BNET_TLS_REQUIRED;
247       } else {
248          tls_local_need = BNET_TLS_OK;
249       }
250    }
251
252    if (me->tls_authenticate) {
253       tls_local_need = BNET_TLS_REQUIRED;
254    }
255
256    if (job_canceled(jcr)) {
257       auth_success = false;     /* force quick exit */
258       goto auth_fatal;
259    }
260
261    /* Respond to SD challenge */
262    Dmsg0(050, "Respond to SD challenge\n");
263    auth_success = cram_md5_respond(sd, jcr->sd_auth_key, &tls_remote_need, &compatible);
264    if (job_canceled(jcr)) {
265       auth_success = false;     /* force quick exit */
266       goto auth_fatal;
267    }
268    if (!auth_success) {
269       Dmsg1(dbglvl, "cram_respond failed for SD: %s\n", sd->who());
270    } else {
271       /* Now challenge him */
272       Dmsg0(050, "Challenge SD\n");
273       auth_success = cram_md5_challenge(sd, jcr->sd_auth_key, tls_local_need, compatible);
274       if (!auth_success) {
275          Dmsg1(dbglvl, "cram_challenge failed for SD: %s\n", sd->who());
276       }
277    }
278
279    if (!auth_success) {
280       Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
281        "Please see " MANUAL_AUTH_URL " for help.\n"));
282       goto auth_fatal;
283    } else {
284       Dmsg0(050, "Authorization with SD is OK\n");
285    }
286
287    /* Verify that the remote host is willing to meet our TLS requirements */
288    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
289       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
290            " advertize required TLS support.\n"));
291       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
292       auth_success = false;
293       goto auth_fatal;
294    }
295
296    /* Verify that we are willing to meet the remote host's requirements */
297    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
298       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
299       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
300       auth_success = false;
301       goto auth_fatal;
302    }
303
304    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
305       /* Engage TLS! Full Speed Ahead! */
306       if (!bnet_tls_client(me->tls_ctx, sd, NULL)) {
307          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
308          auth_success = false;
309          goto auth_fatal;
310       }
311       if (me->tls_authenticate) {           /* tls authentication only? */
312          sd->free_tls();                    /* yes, shutdown tls */
313       }
314    }
315    if (sd->recv() <= 0) {
316       auth_success = false;
317       goto auth_fatal;
318    }
319    sscanf(sd->msg, "3000 OK Hello %d", &sd_version);
320    /* At this point, we have successfully connected */
321
322 auth_fatal:
323    /* Destroy session key */
324    memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
325    stop_bsock_timer(tid);
326    /* Single thread all failures to avoid DOS */
327    if (!auth_success) {
328       P(mutex);
329       bmicrosleep(6, 0);
330       V(mutex);
331    }
332    return auth_success;
333 }