]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/authenticate.c
ebl fix RunScript bug (in some case, After script wasn't launched)
[bacula/bacula] / bacula / src / filed / authenticate.c
1 /*
2  * Authenticate Director who is attempting to connect.
3  *
4  *   Kern Sibbald, October 2000
5  *
6  *   Version $Id$
7  *
8  */
9 /*
10    Copyright (C) 2000-2006 Kern Sibbald
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License
14    version 2 as amended with additional clauses defined in the
15    file LICENSE in the main source directory.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
20    the file LICENSE for additional details.
21
22  */
23
24 #include "bacula.h"
25 #include "filed.h"
26
27 static char OK_hello[]  = "2000 OK Hello\n";
28 static char Dir_sorry[] = "2999 No go\n";
29 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
30
31 /*********************************************************************
32  *
33  */
34 static bool authenticate(int rcode, BSOCK *bs, JCR* jcr)
35 {
36    POOLMEM *dirname = get_pool_memory(PM_MESSAGE);
37    DIRRES *director = NULL;
38    int tls_local_need = BNET_TLS_NONE;
39    int tls_remote_need = BNET_TLS_NONE;
40    int compatible = true;                 /* Want md5 compatible DIR */
41    bool auth_success = false;
42    alist *verify_list = NULL;
43    btimer_t *tid = NULL;
44
45    if (rcode != R_DIRECTOR) {
46       Dmsg1(50, "I only authenticate directors, not %d\n", rcode);
47       Emsg1(M_FATAL, 0, _("I only authenticate directors, not %d\n"), rcode);
48       goto auth_fatal;
49    }
50    if (bs->msglen < 25 || bs->msglen > 500) {
51       Dmsg2(50, "Bad Hello command from Director at %s. Len=%d.\n",
52             bs->who, bs->msglen);
53       char addr[64];
54       char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
55       Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
56              who, bs->msglen);
57       goto auth_fatal;
58    }
59    dirname = check_pool_memory_size(dirname, bs->msglen);
60
61    if (sscanf(bs->msg, "Hello Director %s calling", dirname) != 1) {
62       char addr[64];
63       char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
64       bs->msg[100] = 0;
65       Dmsg2(50, "Bad Hello command from Director at %s: %s\n",
66             bs->who, bs->msg);
67       Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
68             who, bs->msg);
69       goto auth_fatal;
70    }
71    unbash_spaces(dirname);
72    foreach_res(director, R_DIRECTOR) {
73       if (strcmp(director->hdr.name, dirname) == 0)
74          break;
75    }
76    if (!director) {
77        char addr[64];
78        char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
79       Emsg2(M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"), 
80             dirname, who);
81       goto auth_fatal;
82    }
83
84    if (have_tls) {
85       /* TLS Requirement */
86       if (director->tls_enable) {
87          if (director->tls_require) {
88             tls_local_need = BNET_TLS_REQUIRED;
89          } else {
90             tls_local_need = BNET_TLS_OK;
91          }
92       }
93
94       if (director->tls_verify_peer) {
95          verify_list = director->tls_allowed_cns;
96       }
97    }
98
99    tid = start_bsock_timer(bs, AUTH_TIMEOUT);
100    /* Challenge the director */
101    auth_success = cram_md5_challenge(bs, director->password, tls_local_need, compatible);  
102    if (auth_success) {
103       auth_success = cram_md5_respond(bs, director->password, &tls_remote_need, &compatible);
104       if (!auth_success) {
105           char addr[64];
106           char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
107           Dmsg1(50, "cram_get_auth failed for %s\n", who);
108       }
109    } else {
110        char addr[64];
111        char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
112        Dmsg1(50, "cram_auth failed for %s\n", who);
113    }
114    if (!auth_success) {
115        Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"),
116              bs->who);
117        goto auth_fatal;
118    }
119
120    /* Verify that the remote host is willing to meet our TLS requirements */
121    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
122       Emsg0(M_FATAL, 0, _("Authorization problem: Remote server did not"
123            " advertize required TLS support.\n"));
124       auth_success = false;
125       goto auth_fatal;
126    }
127
128    /* Verify that we are willing to meet the remote host's requirements */
129    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
130       Emsg0(M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
131       auth_success = false;
132       goto auth_fatal;
133    }
134
135    if (have_tls) {
136       if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
137          /* Engage TLS! Full Speed Ahead! */
138          if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) {
139             Emsg0(M_FATAL, 0, _("TLS negotiation failed.\n"));
140             auth_success = false;
141             goto auth_fatal;
142          }
143       }
144    }
145
146 auth_fatal:
147    if (tid) {
148       stop_bsock_timer(tid);
149       tid = NULL;
150    }
151    free_pool_memory(dirname);
152    jcr->director = director;
153    /* Single thread all failures to avoid DOS */
154    if (!auth_success) {
155       P(mutex);
156       bmicrosleep(6, 0);
157       V(mutex);
158    }
159    return auth_success;
160 }
161
162 /*
163  * Inititiate the communications with the Director.
164  * He has made a connection to our server.
165  *
166  * Basic tasks done here:
167  *   We read Director's initial message and authorize him.
168  *
169  */
170 int authenticate_director(JCR *jcr)
171 {
172    BSOCK *dir = jcr->dir_bsock;
173
174    if (!authenticate(R_DIRECTOR, dir, jcr)) {
175       bnet_fsend(dir, "%s", Dir_sorry);
176       Emsg0(M_FATAL, 0, _("Unable to authenticate Director\n"));
177       return 0;
178    }
179    return bnet_fsend(dir, "%s", OK_hello);
180 }
181
182 /*
183  * First prove our identity to the Storage daemon, then
184  * make him prove his identity.
185  */
186 int authenticate_storagedaemon(JCR *jcr)
187 {
188    BSOCK *sd = jcr->store_bsock;
189    int tls_local_need = BNET_TLS_NONE;
190    int tls_remote_need = BNET_TLS_NONE;
191    int compatible = true;
192    bool auth_success = false;
193
194    btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
195
196    /* TLS Requirement */
197    if (have_tls && 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    /* Respond to SD challenge */
206    auth_success = cram_md5_respond(sd, jcr->sd_auth_key, &tls_remote_need, &compatible);
207    if (!auth_success) {
208       Dmsg1(50, "cram_respond failed for %s\n", sd->who);
209    } else {
210       /* Now challenge him */
211       auth_success = cram_md5_challenge(sd, jcr->sd_auth_key, tls_local_need, compatible);
212       if (!auth_success) {
213          Dmsg1(50, "cram_challenge failed for %s\n", sd->who);
214       }
215    }
216
217    /* Destroy session key */
218    memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
219
220    if (!auth_success) {
221       Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
222        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
223       goto auth_fatal;
224    }
225
226    /* Verify that the remote host is willing to meet our TLS requirements */
227    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
228       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" 
229            " advertise required TLS support.\n"));
230       auth_success = false;
231       goto auth_fatal;
232    }
233
234    /* Verify that we are willing to meet the remote host's 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 requires TLS.\n"));
237       auth_success = false;
238       goto auth_fatal;
239    }
240
241    if (have_tls && tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
242       /* Engage TLS! Full Speed Ahead! */
243       if (!bnet_tls_client(me->tls_ctx, sd)) {
244          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
245          auth_success = false;
246          goto auth_fatal;
247       }
248    }
249
250 auth_fatal:
251    stop_bsock_timer(tid);
252    /* Single thread all failures to avoid DOS */
253    if (!auth_success) {
254       P(mutex);
255       bmicrosleep(6, 0);
256       V(mutex);
257    }
258    return auth_success;
259 }