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