]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/authenticate.c
Backport from BEE
[bacula/bacula] / bacula / src / filed / authenticate.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from many
7    others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    Bacula® is a registered trademark of Kern Sibbald.
15 */
16 /*
17  * Authenticate Director who is attempting to connect.
18  *
19  *   Kern Sibbald, October 2000
20  *
21  */
22
23 #include "bacula.h"
24 #include "filed.h"
25
26 extern CLIENT *me;                 /* my resource */
27
28 const int dbglvl = 50;
29
30 /* Version at end of Hello
31  *   prior to 10Mar08 no version
32  *   1 10Mar08
33  *   2 13Mar09 - added the ability to restore from multiple storages
34  *   3 03Sep10 - added the restore object command for vss plugin 4.0
35  *   4 25Nov10 - added bandwidth command 5.1
36  *   5 01Jan14 - added SD Calls Client and api version to status command
37  */
38 #define FD_VERSION 5
39
40 static char hello_sd[]  = "Hello Bacula SD: Start Job %s %d\n";
41
42 static char hello_dir[]  = "2000 OK Hello %d\n";
43 static char Dir_sorry[] = "2999 Authentication failed.\n";
44 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
45
46 /*********************************************************************
47  *
48  */
49 static bool authenticate(int rcode, BSOCK *bs, JCR* jcr)
50 {
51    POOLMEM *dirname = get_pool_memory(PM_MESSAGE);
52    DIRRES *director = NULL;
53    int tls_local_need = BNET_TLS_NONE;
54    int tls_remote_need = BNET_TLS_NONE;
55    int compatible = true;                 /* Want md5 compatible DIR */
56    bool auth_success = false;
57    alist *verify_list = NULL;
58    btimer_t *tid = NULL;
59    int dir_version = 0;
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       goto auth_fatal;
65    }
66
67    dirname = check_pool_memory_size(dirname, bs->msglen);
68
69    if (sscanf(bs->msg, "Hello Director %s calling %d", dirname, &dir_version) != 2 &&
70        sscanf(bs->msg, "Hello Director %s calling", dirname) != 1) {
71       char addr[64];
72       char *who = bs->get_peer(addr, sizeof(addr)) ? bs->who() : addr;
73       bs->msg[100] = 0;
74       Dmsg2(dbglvl, "Bad Hello command from Director at %s: %s\n",
75             bs->who(), bs->msg);
76       Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
77             who, bs->msg);
78       goto auth_fatal;
79    }
80    unbash_spaces(dirname);
81    foreach_res(director, R_DIRECTOR) {
82       if (strcmp(director->hdr.name, dirname) == 0)
83          break;
84    }
85    if (!director) {
86       char addr[64];
87       char *who = bs->get_peer(addr, sizeof(addr)) ? bs->who() : addr;
88       Jmsg2(jcr, M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"),
89             dirname, who);
90       goto auth_fatal;
91    }
92
93    if (have_tls) {
94       /* TLS Requirement */
95       if (director->tls_enable) {
96          if (director->tls_require) {
97             tls_local_need = BNET_TLS_REQUIRED;
98          } else {
99             tls_local_need = BNET_TLS_OK;
100          }
101       }
102
103       if (director->tls_authenticate) {
104          tls_local_need = BNET_TLS_REQUIRED;
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 = bs->get_peer(addr, sizeof(addr)) ? bs->who() : addr;
124           Dmsg1(dbglvl, "cram_get_auth respond failed for Director: %s\n", who);
125       }
126    } else {
127        char addr[64];
128        char *who = bs->get_peer(addr, sizeof(addr)) ? bs->who() : addr;
129        Dmsg1(dbglvl, "cram_auth challenge failed for Director %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       Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
140            " advertize required TLS support.\n"));
141       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
142       auth_success = false;
143       goto auth_fatal;
144    }
145
146    /* Verify that we are willing to meet the remote host's requirements */
147    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
148       Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
149       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
150       auth_success = false;
151       goto auth_fatal;
152    }
153
154    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
155       /* Engage TLS! Full Speed Ahead! */
156       if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) {
157          Jmsg0(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
158          auth_success = false;
159          goto auth_fatal;
160       }
161       if (director->tls_authenticate) {         /* authentication only? */
162          bs->free_tls();                        /* shutodown tls */
163       }
164    }
165
166 auth_fatal:
167    if (tid) {
168       stop_bsock_timer(tid);
169       tid = NULL;
170    }
171    free_pool_memory(dirname);
172    jcr->director = director;
173    /* Single thread all failures to avoid DOS */
174    if (!auth_success) {
175       P(mutex);
176       bmicrosleep(6, 0);
177       V(mutex);
178    }
179    return auth_success;
180 }
181
182 /*
183  * Inititiate the communications with the Director.
184  * He has made a connection to our server.
185  *
186  * Basic tasks done here:
187  *   We read Director's initial message and authorize him.
188  *
189  */
190 int authenticate_director(JCR *jcr)
191 {
192    BSOCK *dir = jcr->dir_bsock;
193
194    if (!authenticate(R_DIRECTOR, dir, jcr)) {
195       dir->fsend("%s", Dir_sorry);
196       Emsg0(M_FATAL, 0, _("Unable to authenticate Director\n"));
197       return 0;
198    }
199    return dir->fsend(hello_dir, FD_VERSION);
200 }
201
202 /*
203  * First prove our identity to the Storage daemon, then
204  * make him prove his identity.
205  */
206 int authenticate_storagedaemon(JCR *jcr)
207 {
208    BSOCK *sd = jcr->store_bsock;
209    int tls_local_need = BNET_TLS_NONE;
210    int tls_remote_need = BNET_TLS_NONE;
211    int compatible = true;
212    bool auth_success = false;
213    int sd_version = 0;
214
215    btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
216
217    /* TLS Requirement */
218    if (have_tls && me->tls_enable) {
219       if (me->tls_require) {
220          tls_local_need = BNET_TLS_REQUIRED;
221       } else {
222          tls_local_need = BNET_TLS_OK;
223       }
224    }
225
226    if (me->tls_authenticate) {
227       tls_local_need = BNET_TLS_REQUIRED;
228    }
229
230    if (job_canceled(jcr)) {
231       auth_success = false;     /* force quick exit */
232       goto auth_fatal;
233    }
234
235
236    sd->fsend(hello_sd, jcr->Job, FD_VERSION);
237    Dmsg1(100, "Send to SD: %s\n", sd->msg);
238
239    /* Respond to SD challenge */
240    Dmsg0(050, "==== respond to SD challenge\n");
241    auth_success = cram_md5_respond(sd, jcr->sd_auth_key, &tls_remote_need, &compatible);
242    if (job_canceled(jcr)) {
243       auth_success = false;     /* force quick exit */
244       goto auth_fatal;
245    }
246    if (!auth_success) {
247       Dmsg1(dbglvl, "cram_respond failed for SD: %s\n", sd->who());
248    } else {
249       /* Now challenge him */
250       Dmsg0(050, "==== Challenge SD\n");
251       auth_success = cram_md5_challenge(sd, jcr->sd_auth_key, tls_local_need, compatible);
252       if (!auth_success) {
253          Dmsg1(dbglvl, "cram_challenge failed for SD: %s\n", sd->who());
254       }
255    }
256
257    if (!auth_success) {
258       Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
259        "Please see " MANUAL_AUTH_URL " for help.\n"));
260       goto auth_fatal;
261    } else {
262       Dmsg0(050, "Authorization with SD is OK\n");
263    }
264
265    /* Verify that the remote host is willing to meet our TLS requirements */
266    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
267       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
268            " advertize required TLS support.\n"));
269       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
270       auth_success = false;
271       goto auth_fatal;
272    }
273
274    /* Verify that we are willing to meet the remote host's requirements */
275    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
276       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
277       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
278       auth_success = false;
279       goto auth_fatal;
280    }
281
282    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
283       /* Engage TLS! Full Speed Ahead! */
284       if (!bnet_tls_client(me->tls_ctx, sd, NULL)) {
285          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
286          auth_success = false;
287          goto auth_fatal;
288       }
289       if (me->tls_authenticate) {           /* tls authentication only? */
290          sd->free_tls();                    /* yes, shutdown tls */
291       }
292    }
293    if (sd->recv() <= 0) {
294       auth_success = false;
295       goto auth_fatal;
296    }
297    sscanf(sd->msg, "3000 OK Hello %d", &sd_version);
298
299    /* At this point, we have successfully connected */
300
301 auth_fatal:
302    /* Destroy session key */
303    memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
304    stop_bsock_timer(tid);
305    /* Single thread all failures to avoid DOS */
306    if (!auth_success) {
307       P(mutex);
308       bmicrosleep(6, 0);
309       V(mutex);
310    }
311    return auth_success;
312 }