]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/authenticate.c
Add additional ACL flags for restore.
[bacula/bacula] / bacula / src / filed / authenticate.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2010 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 Director who is attempting to connect.
30  *
31  *   Kern Sibbald, October 2000
32  *
33  */
34
35 #include "bacula.h"
36 #include "filed.h"
37
38 const int dbglvl = 50;
39
40 /* Version at end of Hello
41  *   prior to 10Mar08 no version
42  *   1 10Mar08
43  *   2 13Mar09 - added the ability to restore from multiple storages
44  *   3 03Sep10 - added the restore object command for vss plugin 4.0
45  */
46 static char OK_hello[]  = "2000 OK Hello 3\n";
47 static char Dir_sorry[] = "2999 Authentication failed.\n";
48 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
49
50 /*********************************************************************
51  *
52  */
53 static bool authenticate(int rcode, BSOCK *bs, JCR* jcr)
54 {
55    POOLMEM *dirname = get_pool_memory(PM_MESSAGE);
56    DIRRES *director = NULL;
57    int tls_local_need = BNET_TLS_NONE;
58    int tls_remote_need = BNET_TLS_NONE;
59    int compatible = true;                 /* Want md5 compatible DIR */
60    bool auth_success = false;
61    alist *verify_list = NULL;
62    btimer_t *tid = NULL;
63
64    if (rcode != R_DIRECTOR) {
65       Dmsg1(dbglvl, "I only authenticate directors, not %d\n", rcode);
66       Jmsg1(jcr, M_FATAL, 0, _("I only authenticate directors, not %d\n"), rcode);
67       goto auth_fatal;
68    }
69    if (bs->msglen < 25 || bs->msglen > 500) {
70       Dmsg2(dbglvl, "Bad Hello command from Director at %s. Len=%d.\n",
71             bs->who(), bs->msglen);
72       char addr[64];
73       char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
74       Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
75              who, bs->msglen);
76       goto auth_fatal;
77    }
78    dirname = check_pool_memory_size(dirname, bs->msglen);
79
80    if (sscanf(bs->msg, "Hello Director %s calling", dirname) != 1) {
81       char addr[64];
82       char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
83       bs->msg[100] = 0;
84       Dmsg2(dbglvl, "Bad Hello command from Director at %s: %s\n",
85             bs->who(), bs->msg);
86       Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
87             who, bs->msg);
88       goto auth_fatal;
89    }
90    unbash_spaces(dirname);
91    foreach_res(director, R_DIRECTOR) {
92       if (strcmp(director->hdr.name, dirname) == 0)
93          break;
94    }
95    if (!director) {
96       char addr[64];
97       char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
98       Jmsg2(jcr, M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"), 
99             dirname, who);
100       goto auth_fatal;
101    }
102
103    if (have_tls) {
104       /* TLS Requirement */
105       if (director->tls_enable) {
106          if (director->tls_require) {
107             tls_local_need = BNET_TLS_REQUIRED;
108          } else {
109             tls_local_need = BNET_TLS_OK;
110          }
111       }
112
113       if (director->tls_authenticate) {
114          tls_local_need = BNET_TLS_REQUIRED;
115       }
116
117       if (director->tls_verify_peer) {
118          verify_list = director->tls_allowed_cns;
119       }
120    }
121
122    tid = start_bsock_timer(bs, AUTH_TIMEOUT);
123    /* Challenge the director */
124    auth_success = cram_md5_challenge(bs, director->password, tls_local_need, compatible);  
125    if (job_canceled(jcr)) {
126       auth_success = false;
127       goto auth_fatal;                   /* quick exit */
128    }
129    if (auth_success) {
130       auth_success = cram_md5_respond(bs, director->password, &tls_remote_need, &compatible);
131       if (!auth_success) {
132           char addr[64];
133           char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
134           Dmsg1(dbglvl, "cram_get_auth failed for %s\n", who);
135       }
136    } else {
137        char addr[64];
138        char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
139        Dmsg1(dbglvl, "cram_auth failed for %s\n", who);
140    }
141    if (!auth_success) {
142        Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"),
143              bs->who());
144        goto auth_fatal;
145    }
146
147    /* Verify that the remote host is willing to meet our TLS requirements */
148    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
149       Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
150            " advertize required TLS support.\n"));
151       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
152       auth_success = false;
153       goto auth_fatal;
154    }
155
156    /* Verify that we are willing to meet the remote host's requirements */
157    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
158       Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
159       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
160       auth_success = false;
161       goto auth_fatal;
162    }
163
164    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
165       /* Engage TLS! Full Speed Ahead! */
166       if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) {
167          Jmsg0(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
168          auth_success = false;
169          goto auth_fatal;
170       }
171       if (director->tls_authenticate) {         /* authentication only? */
172          bs->free_tls();                        /* shutodown tls */
173       }
174    }
175
176 auth_fatal:
177    if (tid) {
178       stop_bsock_timer(tid);
179       tid = NULL;
180    }
181    free_pool_memory(dirname);
182    jcr->director = director;
183    /* Single thread all failures to avoid DOS */
184    if (!auth_success) {
185       P(mutex);
186       bmicrosleep(6, 0);
187       V(mutex);
188    }
189    return auth_success;
190 }
191
192 /*
193  * Inititiate the communications with the Director.
194  * He has made a connection to our server.
195  *
196  * Basic tasks done here:
197  *   We read Director's initial message and authorize him.
198  *
199  */
200 int authenticate_director(JCR *jcr)
201 {
202    BSOCK *dir = jcr->dir_bsock;
203
204    if (!authenticate(R_DIRECTOR, dir, jcr)) {
205       bnet_fsend(dir, "%s", Dir_sorry);
206       Emsg0(M_FATAL, 0, _("Unable to authenticate Director\n"));
207       return 0;
208    }
209    return bnet_fsend(dir, "%s", OK_hello);
210 }
211
212 /*
213  * First prove our identity to the Storage daemon, then
214  * make him prove his identity.
215  */
216 int authenticate_storagedaemon(JCR *jcr)
217 {
218    BSOCK *sd = jcr->store_bsock;
219    int tls_local_need = BNET_TLS_NONE;
220    int tls_remote_need = BNET_TLS_NONE;
221    int compatible = true;
222    bool auth_success = false;
223
224    btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
225
226    /* TLS Requirement */
227    if (have_tls && me->tls_enable) {
228       if (me->tls_require) {
229          tls_local_need = BNET_TLS_REQUIRED;
230       } else {
231          tls_local_need = BNET_TLS_OK;
232       }
233    }
234
235    if (me->tls_authenticate) {
236       tls_local_need = BNET_TLS_REQUIRED;
237    }
238
239    if (job_canceled(jcr)) {
240       auth_success = false;     /* force quick exit */
241       goto auth_fatal;
242    }
243
244    /* Respond to SD challenge */
245    auth_success = cram_md5_respond(sd, jcr->sd_auth_key, &tls_remote_need, &compatible);
246    if (job_canceled(jcr)) {
247       auth_success = false;     /* force quick exit */
248       goto auth_fatal;
249    }
250    if (!auth_success) {
251       Dmsg1(dbglvl, "cram_respond failed for %s\n", sd->who());
252    } else {
253       /* Now challenge him */
254       auth_success = cram_md5_challenge(sd, jcr->sd_auth_key, tls_local_need, compatible);
255       if (!auth_success) {
256          Dmsg1(dbglvl, "cram_challenge failed for %s\n", sd->who());
257       }
258    }
259
260    if (!auth_success) {
261       Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
262        "Please see http://www.bacula.org/en/rel-manual/Bacula_Freque_Asked_Questi.html#SECTION003760000000000000000 for help.\n"));
263       goto auth_fatal;
264    }
265
266    /* Verify that the remote host is willing to meet our TLS requirements */
267    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
268       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" 
269            " advertize required TLS support.\n"));
270       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
271       auth_success = false;
272       goto auth_fatal;
273    }
274
275    /* Verify that we are willing to meet the remote host's requirements */
276    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
277       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
278       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
279       auth_success = false;
280       goto auth_fatal;
281    }
282
283    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
284       /* Engage TLS! Full Speed Ahead! */
285       if (!bnet_tls_client(me->tls_ctx, sd, NULL)) {
286          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
287          auth_success = false;
288          goto auth_fatal;
289       }
290       if (me->tls_authenticate) {           /* tls authentication only? */
291          sd->free_tls();                    /* yes, shutdown tls */
292       }
293    }
294
295 auth_fatal:
296    /* Destroy session key */
297    memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
298    stop_bsock_timer(tid);
299    /* Single thread all failures to avoid DOS */
300    if (!auth_success) {
301       P(mutex);
302       bmicrosleep(6, 0);
303       V(mutex);
304    }
305    return auth_success;
306 }