]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/authenticate.c
Switch from GPLv2 to AGPLv3
[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 three of the GNU Affero 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 Affero 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 Kern Sibbald.
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/en/rel-manual/Bacula_Freque_Asked_Questi.html#SECTION003760000000000000000 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_authenticate) {
110       tls_local_need = BNET_TLS_REQUIRED;
111    }
112
113    if (director->tls_verify_peer) {
114       verify_list = director->tls_allowed_cns;
115    }
116
117    /* Timeout Hello after 10 mins */
118    btimer_t *tid = start_bsock_timer(bs, AUTH_TIMEOUT);
119    auth_success = cram_md5_challenge(bs, director->password, tls_local_need, compatible);
120    if (auth_success) {
121       auth_success = cram_md5_respond(bs, director->password, &tls_remote_need, &compatible);
122       if (!auth_success) {
123          Dmsg1(dbglvl, "cram_get_auth failed with %s\n", bs->who());
124       }
125    } else {
126       Dmsg1(dbglvl, "cram_auth failed with %s\n", bs->who());
127    }
128
129    if (!auth_success) {
130       Jmsg0(jcr, M_FATAL, 0, _("Incorrect password given by Director.\n"
131        "Please see http://www.bacula.org/en/rel-manual/Bacula_Freque_Asked_Questi.html#SECTION003760000000000000000 for help.\n"));
132       auth_success = false;
133       goto auth_fatal;
134    }
135
136    /* Verify that the remote host is willing to meet our TLS requirements */
137    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
138       Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" 
139            " advertize required TLS support.\n"));
140       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
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       Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
148       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
149       auth_success = false;
150       goto auth_fatal;
151    }
152
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          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with DIR at \"%s:%d\"\n"),
157             bs->host(), bs->port());
158          auth_success = false;
159          goto auth_fatal;
160       }
161       if (director->tls_authenticate) {     /* authenticate with tls only? */
162          bs->free_tls();                    /* yes, shut it down */
163       }
164    }
165
166 auth_fatal:
167    stop_bsock_timer(tid);
168    free_pool_memory(dirname);
169    jcr->director = director;
170    return auth_success;
171 }
172
173 /*
174  * Inititiate the message channel with the Director.
175  * He has made a connection to our server.
176  *
177  * Basic tasks done here:
178  *   Assume the Hello message is already in the input
179  *     buffer.  We then authenticate him.
180  *   Get device, media, and pool information from Director
181  *
182  *   This is the channel across which we will send error
183  *     messages and job status information.
184  */
185 int authenticate_director(JCR *jcr)
186 {
187    BSOCK *dir = jcr->dir_bsock;
188
189    if (!authenticate(R_DIRECTOR, dir, jcr)) {
190       dir->fsend("%s", Dir_sorry);
191       Dmsg1(dbglvl, "Unable to authenticate Director at %s.\n", dir->who());
192       Jmsg1(jcr, M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who());
193       bmicrosleep(5, 0);
194       return 0;
195    }
196    return dir->fsend("%s", OK_hello);
197 }
198
199 int authenticate_filed(JCR *jcr)
200 {
201    BSOCK *fd = jcr->file_bsock;
202    int tls_local_need = BNET_TLS_NONE;
203    int tls_remote_need = BNET_TLS_NONE;
204    int compatible = true;                 /* require md5 compatible FD */
205    bool auth_success = false;
206    alist *verify_list = NULL;
207
208    /* TLS Requirement */
209    if (me->tls_enable) {
210       if (me->tls_require) {
211          tls_local_need = BNET_TLS_REQUIRED;
212       } else {
213          tls_local_need = BNET_TLS_OK;
214       }
215    }
216
217    if (me->tls_authenticate) {
218       tls_local_need = BNET_TLS_REQUIRED;
219    }
220
221    if (me->tls_verify_peer) {
222       verify_list = me->tls_allowed_cns;
223    }
224
225    /* Timeout Hello after 5 mins */
226    btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
227    /* Challenge FD */
228    auth_success = cram_md5_challenge(fd, jcr->sd_auth_key, tls_local_need, compatible);
229    if (auth_success) {
230        /* Respond to his challenge */
231        auth_success = cram_md5_respond(fd, jcr->sd_auth_key, &tls_remote_need, &compatible);
232        if (!auth_success) {
233           Dmsg1(dbglvl, "cram-get-auth failed with %s\n", fd->who());
234        }
235    } else {
236       Dmsg1(dbglvl, "cram-auth failed with %s\n", fd->who());
237    }
238
239    if (!auth_success) {
240       Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
241        "Please see http://www.bacula.org/en/rel-manual/Bacula_Freque_Asked_Questi.html#SECTION003760000000000000000 for help.\n"),
242            fd->who());
243       auth_success = false;
244       goto auth_fatal;
245    }
246
247    /* Verify that the remote host is willing to meet our TLS 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 did not" 
250            " advertize required TLS support.\n"));
251       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
252       auth_success = false;
253       goto auth_fatal;
254    }
255
256    /* Verify that we are willing to meet the remote host's requirements */
257    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
258       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
259       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
260       auth_success = false;
261       goto auth_fatal;
262    }
263
264    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
265       /* Engage TLS! Full Speed Ahead! */
266       if (!bnet_tls_server(me->tls_ctx, fd, verify_list)) {
267          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with FD at \"%s:%d\"\n"),
268             fd->host(), fd->port());
269          auth_success = false;
270          goto auth_fatal;
271       }
272       if (me->tls_authenticate) {          /* tls authenticate only? */
273          fd->free_tls();                   /* yes, shut it down */
274       }
275    }
276
277 auth_fatal:
278    stop_bsock_timer(tid);
279    if (!auth_success) {
280       Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
281        "Please see http://www.bacula.org/en/rel-manual/Bacula_Freque_Asked_Questi.html#SECTION003760000000000000000 for help.\n"),
282            fd->who());
283    }
284    jcr->authenticated = auth_success;
285    return auth_success;
286 }