]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/authenticate.c
kes Begin implementing new comm signals for API.
[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 (job_canceled(jcr)) {
116       auth_success = false;
117       goto auth_fatal;                   /* quick exit */
118    }
119    if (auth_success) {
120       auth_success = cram_md5_respond(bs, director->password, &tls_remote_need, &compatible);
121       if (!auth_success) {
122           char addr[64];
123           char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
124           Dmsg1(50, "cram_get_auth failed for %s\n", who);
125       }
126    } else {
127        char addr[64];
128        char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
129        Dmsg1(50, "cram_auth failed for %s\n", who);
130    }
131    if (!auth_success) {
132        Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"),
133              bs->who());
134        goto auth_fatal;
135    }
136
137    /* Verify that the remote host is willing to meet our TLS requirements */
138    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
139       Emsg0(M_FATAL, 0, _("Authorization problem: Remote server did not"
140            " advertize required TLS support.\n"));
141       auth_success = false;
142       goto auth_fatal;
143    }
144
145    /* Verify that we are willing to meet the remote host's requirements */
146    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
147       Emsg0(M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
148       auth_success = false;
149       goto auth_fatal;
150    }
151
152    if (have_tls) {
153       if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
154          /* Engage TLS! Full Speed Ahead! */
155          if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) {
156             Emsg0(M_FATAL, 0, _("TLS negotiation failed.\n"));
157             auth_success = false;
158             goto auth_fatal;
159          }
160       }
161    }
162
163 auth_fatal:
164    if (tid) {
165       stop_bsock_timer(tid);
166       tid = NULL;
167    }
168    free_pool_memory(dirname);
169    jcr->director = director;
170    /* Single thread all failures to avoid DOS */
171    if (!auth_success) {
172       P(mutex);
173       bmicrosleep(6, 0);
174       V(mutex);
175    }
176    return auth_success;
177 }
178
179 /*
180  * Inititiate the communications with the Director.
181  * He has made a connection to our server.
182  *
183  * Basic tasks done here:
184  *   We read Director's initial message and authorize him.
185  *
186  */
187 int authenticate_director(JCR *jcr)
188 {
189    BSOCK *dir = jcr->dir_bsock;
190
191    if (!authenticate(R_DIRECTOR, dir, jcr)) {
192       bnet_fsend(dir, "%s", Dir_sorry);
193       Emsg0(M_FATAL, 0, _("Unable to authenticate Director\n"));
194       return 0;
195    }
196    return bnet_fsend(dir, "%s", OK_hello);
197 }
198
199 /*
200  * First prove our identity to the Storage daemon, then
201  * make him prove his identity.
202  */
203 int authenticate_storagedaemon(JCR *jcr)
204 {
205    BSOCK *sd = jcr->store_bsock;
206    int tls_local_need = BNET_TLS_NONE;
207    int tls_remote_need = BNET_TLS_NONE;
208    int compatible = true;
209    bool auth_success = false;
210
211    btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
212
213    /* TLS Requirement */
214    if (have_tls && me->tls_enable) {
215       if (me->tls_require) {
216          tls_local_need = BNET_TLS_REQUIRED;
217       } else {
218          tls_local_need = BNET_TLS_OK;
219       }
220    }
221
222    if (job_canceled(jcr)) {
223       auth_success = false;     /* force quick exit */
224       goto auth_fatal;
225    }
226
227    /* Respond to SD challenge */
228    auth_success = cram_md5_respond(sd, jcr->sd_auth_key, &tls_remote_need, &compatible);
229    if (job_canceled(jcr)) {
230       auth_success = false;     /* force quick exit */
231       goto auth_fatal;
232    }
233    if (!auth_success) {
234       Dmsg1(50, "cram_respond failed for %s\n", sd->who());
235    } else {
236       /* Now challenge him */
237       auth_success = cram_md5_challenge(sd, jcr->sd_auth_key, tls_local_need, compatible);
238       if (!auth_success) {
239          Dmsg1(50, "cram_challenge failed for %s\n", sd->who());
240       }
241    }
242
243    if (!auth_success) {
244       Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
245        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
246       goto auth_fatal;
247    }
248
249    /* Verify that the remote host is willing to meet our TLS requirements */
250    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
251       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" 
252            " advertise required TLS support.\n"));
253       auth_success = false;
254       goto auth_fatal;
255    }
256
257    /* Verify that we are willing to meet the remote host's requirements */
258    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
259       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
260       auth_success = false;
261       goto auth_fatal;
262    }
263
264    if (have_tls && tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
265       /* Engage TLS! Full Speed Ahead! */
266       if (!bnet_tls_client(me->tls_ctx, sd)) {
267          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
268          auth_success = false;
269          goto auth_fatal;
270       }
271    }
272
273 auth_fatal:
274    /* Destroy session key */
275    memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
276    stop_bsock_timer(tid);
277    /* Single thread all failures to avoid DOS */
278    if (!auth_success) {
279       P(mutex);
280       bmicrosleep(6, 0);
281       V(mutex);
282    }
283    return auth_success;
284 }