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