]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/authenticate.c
ebl update
[bacula/bacula] / bacula / src / filed / authenticate.c
1 /*
2  * Authenticate Director who is attempting to connect.
3  *
4  *   Kern Sibbald, October 2000
5  *
6  *   Version $Id$
7  *
8  */
9 /*
10    Bacula® - The Network Backup Solution
11
12    Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
13
14    The main author of Bacula is Kern Sibbald, with contributions from
15    many others, a complete list can be found in the file AUTHORS.
16    This program is Free Software; you can redistribute it and/or
17    modify it under the terms of version two of the GNU General Public
18    License as published by the Free Software Foundation plus additions
19    that are listed in the file LICENSE.
20
21    This program is distributed in the hope that it will be useful, but
22    WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24    General Public License for more details.
25
26    You should have received a copy of the GNU General Public License
27    along with this program; if not, write to the Free Software
28    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
29    02110-1301, USA.
30
31    Bacula® is a registered trademark of John Walker.
32    The licensor of Bacula is the Free Software Foundation Europe
33    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
34    Switzerland, email:ftf@fsfeurope.org.
35 */
36
37 #include "bacula.h"
38 #include "filed.h"
39
40 static char OK_hello[]  = "2000 OK Hello\n";
41 static char Dir_sorry[] = "2999 No go\n";
42 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
43
44 /*********************************************************************
45  *
46  */
47 static bool authenticate(int rcode, BSOCK *bs, JCR* jcr)
48 {
49    POOLMEM *dirname = get_pool_memory(PM_MESSAGE);
50    DIRRES *director = NULL;
51    int tls_local_need = BNET_TLS_NONE;
52    int tls_remote_need = BNET_TLS_NONE;
53    int compatible = true;                 /* Want md5 compatible DIR */
54    bool auth_success = false;
55    alist *verify_list = NULL;
56    btimer_t *tid = NULL;
57
58    if (rcode != R_DIRECTOR) {
59       Dmsg1(50, "I only authenticate directors, not %d\n", rcode);
60       Emsg1(M_FATAL, 0, _("I only authenticate directors, not %d\n"), rcode);
61       goto auth_fatal;
62    }
63    if (bs->msglen < 25 || bs->msglen > 500) {
64       Dmsg2(50, "Bad Hello command from Director at %s. Len=%d.\n",
65             bs->who, bs->msglen);
66       char addr[64];
67       char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
68       Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
69              who, bs->msglen);
70       goto auth_fatal;
71    }
72    dirname = check_pool_memory_size(dirname, bs->msglen);
73
74    if (sscanf(bs->msg, "Hello Director %s calling", dirname) != 1) {
75       char addr[64];
76       char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
77       bs->msg[100] = 0;
78       Dmsg2(50, "Bad Hello command from Director at %s: %s\n",
79             bs->who, bs->msg);
80       Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
81             who, bs->msg);
82       goto auth_fatal;
83    }
84    unbash_spaces(dirname);
85    foreach_res(director, R_DIRECTOR) {
86       if (strcmp(director->hdr.name, dirname) == 0)
87          break;
88    }
89    if (!director) {
90        char addr[64];
91        char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
92       Emsg2(M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"), 
93             dirname, who);
94       goto auth_fatal;
95    }
96
97    if (have_tls) {
98       /* TLS Requirement */
99       if (director->tls_enable) {
100          if (director->tls_require) {
101             tls_local_need = BNET_TLS_REQUIRED;
102          } else {
103             tls_local_need = BNET_TLS_OK;
104          }
105       }
106
107       if (director->tls_verify_peer) {
108          verify_list = director->tls_allowed_cns;
109       }
110    }
111
112    tid = start_bsock_timer(bs, AUTH_TIMEOUT);
113    /* Challenge the director */
114    auth_success = cram_md5_challenge(bs, director->password, tls_local_need, compatible);  
115    if (auth_success) {
116       auth_success = cram_md5_respond(bs, director->password, &tls_remote_need, &compatible);
117       if (!auth_success) {
118           char addr[64];
119           char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
120           Dmsg1(50, "cram_get_auth failed for %s\n", who);
121       }
122    } else {
123        char addr[64];
124        char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
125        Dmsg1(50, "cram_auth failed for %s\n", who);
126    }
127    if (!auth_success) {
128        Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"),
129              bs->who);
130        goto auth_fatal;
131    }
132
133    /* Verify that the remote host is willing to meet our TLS requirements */
134    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
135       Emsg0(M_FATAL, 0, _("Authorization problem: Remote server did not"
136            " advertize required TLS support.\n"));
137       auth_success = false;
138       goto auth_fatal;
139    }
140
141    /* Verify that we are willing to meet the remote host's requirements */
142    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
143       Emsg0(M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
144       auth_success = false;
145       goto auth_fatal;
146    }
147
148    if (have_tls) {
149       if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
150          /* Engage TLS! Full Speed Ahead! */
151          if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) {
152             Emsg0(M_FATAL, 0, _("TLS negotiation failed.\n"));
153             auth_success = false;
154             goto auth_fatal;
155          }
156       }
157    }
158
159 auth_fatal:
160    if (tid) {
161       stop_bsock_timer(tid);
162       tid = NULL;
163    }
164    free_pool_memory(dirname);
165    jcr->director = director;
166    /* Single thread all failures to avoid DOS */
167    if (!auth_success) {
168       P(mutex);
169       bmicrosleep(6, 0);
170       V(mutex);
171    }
172    return auth_success;
173 }
174
175 /*
176  * Inititiate the communications with the Director.
177  * He has made a connection to our server.
178  *
179  * Basic tasks done here:
180  *   We read Director's initial message and authorize him.
181  *
182  */
183 int authenticate_director(JCR *jcr)
184 {
185    BSOCK *dir = jcr->dir_bsock;
186
187    if (!authenticate(R_DIRECTOR, dir, jcr)) {
188       bnet_fsend(dir, "%s", Dir_sorry);
189       Emsg0(M_FATAL, 0, _("Unable to authenticate Director\n"));
190       return 0;
191    }
192    return bnet_fsend(dir, "%s", OK_hello);
193 }
194
195 /*
196  * First prove our identity to the Storage daemon, then
197  * make him prove his identity.
198  */
199 int authenticate_storagedaemon(JCR *jcr)
200 {
201    BSOCK *sd = jcr->store_bsock;
202    int tls_local_need = BNET_TLS_NONE;
203    int tls_remote_need = BNET_TLS_NONE;
204    int compatible = true;
205    bool auth_success = false;
206
207    btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
208
209    /* TLS Requirement */
210    if (have_tls && me->tls_enable) {
211       if (me->tls_require) {
212          tls_local_need = BNET_TLS_REQUIRED;
213       } else {
214          tls_local_need = BNET_TLS_OK;
215       }
216    }
217
218    /* Respond to SD challenge */
219    auth_success = cram_md5_respond(sd, jcr->sd_auth_key, &tls_remote_need, &compatible);
220    if (!auth_success) {
221       Dmsg1(50, "cram_respond failed for %s\n", sd->who);
222    } else {
223       /* Now challenge him */
224       auth_success = cram_md5_challenge(sd, jcr->sd_auth_key, tls_local_need, compatible);
225       if (!auth_success) {
226          Dmsg1(50, "cram_challenge failed for %s\n", sd->who);
227       }
228    }
229
230    /* Destroy session key */
231    memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
232
233    if (!auth_success) {
234       Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
235        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
236       goto auth_fatal;
237    }
238
239    /* Verify that the remote host is willing to meet our TLS requirements */
240    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
241       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" 
242            " advertise required TLS support.\n"));
243       auth_success = false;
244       goto auth_fatal;
245    }
246
247    /* Verify that we are willing to meet the remote host's requirements */
248    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
249       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
250       auth_success = false;
251       goto auth_fatal;
252    }
253
254    if (have_tls && tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
255       /* Engage TLS! Full Speed Ahead! */
256       if (!bnet_tls_client(me->tls_ctx, sd)) {
257          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
258          auth_success = false;
259          goto auth_fatal;
260       }
261    }
262
263 auth_fatal:
264    stop_bsock_timer(tid);
265    /* Single thread all failures to avoid DOS */
266    if (!auth_success) {
267       P(mutex);
268       bmicrosleep(6, 0);
269       V(mutex);
270    }
271    return auth_success;
272 }