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