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