]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/authenticate.c
kes Add code to help Dan debug 2drive-incremental-2disk test.
[bacula/bacula] / bacula / src / stored / 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 caller
30  *
31  *   Kern Sibbald, October 2000
32  *
33  *   Version $Id$
34  *
35  */
36
37
38 #include "bacula.h"
39 #include "stored.h"
40
41 static char Dir_sorry[] = "3999 No go\n";
42 static char OK_hello[]  = "3000 OK Hello\n";
43
44
45 /*********************************************************************
46  *
47  *
48  */
49 static int authenticate(int rcode, BSOCK *bs, JCR* jcr)
50 {
51    POOLMEM *dirname;
52    DIRRES *director = NULL;
53    int tls_local_need = BNET_TLS_NONE;
54    int tls_remote_need = BNET_TLS_NONE;
55    int compatible = true;                  /* require md5 compatible DIR */
56    bool auth_success = false;
57    alist *verify_list = NULL;
58
59    if (rcode != R_DIRECTOR) {
60       Dmsg1(50, "I only authenticate Directors, not %d\n", rcode);
61       Emsg1(M_FATAL, 0, _("I only authenticate Directors, not %d\n"), rcode);
62       return 0;
63    }
64    if (bs->msglen < 25 || bs->msglen > 500) {
65       Dmsg2(50, "Bad Hello command from Director at %s. Len=%d.\n",
66             bs->who(), bs->msglen);
67       Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
68             bs->who(), bs->msglen);
69       return 0;
70    }
71    dirname = get_pool_memory(PM_MESSAGE);
72    dirname = check_pool_memory_size(dirname, bs->msglen);
73
74    if (sscanf(bs->msg, "Hello Director %127s calling", dirname) != 1) {
75       bs->msg[100] = 0;
76       Dmsg2(50, "Bad Hello command from Director at %s: %s\n",
77             bs->who(), bs->msg);
78       Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
79             bs->who(), bs->msg);
80       return 0;
81    }
82    director = NULL;
83    unbash_spaces(dirname);
84    foreach_res(director, rcode) {
85       if (strcmp(director->hdr.name, dirname) == 0)
86          break;
87    }
88    if (!director) {
89       Dmsg2(50, "Connection from unknown Director %s at %s rejected.\n",
90             dirname, bs->who());
91       Emsg2(M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"
92        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
93             dirname, bs->who());
94       free_pool_memory(dirname);
95       return 0;
96    }
97
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    /* Timeout Hello after 10 mins */
112    btimer_t *tid = start_bsock_timer(bs, AUTH_TIMEOUT);
113    auth_success = cram_md5_challenge(bs, director->password, tls_local_need, compatible);
114    if (auth_success) {
115       auth_success = cram_md5_respond(bs, director->password, &tls_remote_need, &compatible);
116       if (!auth_success) {
117          Dmsg1(50, "cram_get_auth failed with %s\n", bs->who());
118       }
119    } else {
120       Dmsg1(50, "cram_auth failed with %s\n", bs->who());
121    }
122
123    if (!auth_success) {
124       Emsg0(M_FATAL, 0, _("Incorrect password given by Director.\n"
125        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
126       auth_success = false;
127       goto auth_fatal;
128    }
129
130    /* Verify that the remote host is willing to meet our TLS requirements */
131    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
132       Emsg0(M_FATAL, 0, _("Authorization problem: Remote server did not" 
133            " advertise required TLS support.\n"));
134       auth_success = false;
135       goto auth_fatal;
136    }
137
138    /* Verify that we are willing to meet the remote host's requirements */
139    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
140       Emsg0(M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
141       auth_success = false;
142       goto auth_fatal;
143    }
144
145    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
146       /* Engage TLS! Full Speed Ahead! */
147       if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) {
148          Emsg0(M_FATAL, 0, _("TLS negotiation failed.\n"));
149          auth_success = false;
150          goto auth_fatal;
151       }
152    }
153
154 auth_fatal:
155    stop_bsock_timer(tid);
156    free_pool_memory(dirname);
157    jcr->director = director;
158    return auth_success;
159 }
160
161 /*
162  * Inititiate the message channel with the Director.
163  * He has made a connection to our server.
164  *
165  * Basic tasks done here:
166  *   Assume the Hello message is already in the input
167  *     buffer.  We then authenticate him.
168  *   Get device, media, and pool information from Director
169  *
170  *   This is the channel across which we will send error
171  *     messages and job status information.
172  */
173 int authenticate_director(JCR *jcr)
174 {
175    BSOCK *dir = jcr->dir_bsock;
176
177    if (!authenticate(R_DIRECTOR, dir, jcr)) {
178       bnet_fsend(dir, "%s", Dir_sorry);
179       Dmsg1(50, "Unable to authenticate Director at %s.\n", dir->who());
180       Emsg1(M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who());
181       bmicrosleep(5, 0);
182       return 0;
183    }
184    return bnet_fsend(dir, "%s", OK_hello);
185 }
186
187 int authenticate_filed(JCR *jcr)
188 {
189    BSOCK *fd = jcr->file_bsock;
190    int tls_local_need = BNET_TLS_NONE;
191    int tls_remote_need = BNET_TLS_NONE;
192    int compatible = true;                 /* require md5 compatible FD */
193    bool auth_success = false;
194    alist *verify_list = NULL;
195
196    /* TLS Requirement */
197    if (me->tls_enable) {
198       if (me->tls_require) {
199          tls_local_need = BNET_TLS_REQUIRED;
200       } else {
201          tls_local_need = BNET_TLS_OK;
202       }
203    }
204
205    if (me->tls_verify_peer) {
206       verify_list = me->tls_allowed_cns;
207    }
208
209    /* Timeout Hello after 5 mins */
210    btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
211    /* Challenge FD */
212    if (debug_level == 3) {
213       Pmsg1(000, "sd_auth_key=%s\n", jcr->sd_auth_key);
214    }
215    auth_success = cram_md5_challenge(fd, jcr->sd_auth_key, tls_local_need, compatible);
216    if (auth_success) {
217        /* Respond to his challenge */
218        auth_success = cram_md5_respond(fd, jcr->sd_auth_key, &tls_remote_need, &compatible);
219        if (!auth_success) {
220           Dmsg1(50, "cram-get-auth failed with %s\n", fd->who());
221        }
222    } else {
223       Dmsg1(50, "cram-auth failed with %s\n", fd->who());
224    }
225
226    if (!auth_success) {
227       Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
228        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
229            fd->who());
230       auth_success = false;
231       goto auth_fatal;
232    }
233
234    /* Verify that the remote host is willing to meet our TLS requirements */
235    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
236       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" 
237            " advertise required TLS support.\n"));
238       auth_success = false;
239       goto auth_fatal;
240    }
241
242    /* Verify that we are willing to meet the remote host's requirements */
243    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
244       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
245       auth_success = false;
246       goto auth_fatal;
247    }
248
249    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
250       /* Engage TLS! Full Speed Ahead! */
251       if (!bnet_tls_server(me->tls_ctx, fd, verify_list)) {
252          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
253          auth_success = false;
254          goto auth_fatal;
255       }
256    }
257
258 auth_fatal:
259    stop_bsock_timer(tid);
260    if (!auth_success) {
261       Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
262        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
263            fd->who());
264    }
265    jcr->authenticated = auth_success;
266    return auth_success;
267 }