2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
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
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.
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
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.
29 * Authenticate Director who is attempting to connect.
31 * Kern Sibbald, October 2000
40 const int dbglvl = 50;
42 static char OK_hello[] = "2000 OK Hello\n";
43 static char Dir_sorry[] = "2999 No go\n";
44 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
46 /*********************************************************************
49 static bool authenticate(int rcode, BSOCK *bs, JCR* jcr)
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;
60 if (rcode != R_DIRECTOR) {
61 Dmsg1(dbglvl, "I only authenticate directors, not %d\n", rcode);
62 Jmsg1(jcr, M_FATAL, 0, _("I only authenticate directors, not %d\n"), rcode);
65 if (bs->msglen < 25 || bs->msglen > 500) {
66 Dmsg2(dbglvl, "Bad Hello command from Director at %s. Len=%d.\n",
67 bs->who(), bs->msglen);
69 char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
70 Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
74 dirname = check_pool_memory_size(dirname, bs->msglen);
76 if (sscanf(bs->msg, "Hello Director %s calling", dirname) != 1) {
78 char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
80 Dmsg2(dbglvl, "Bad Hello command from Director at %s: %s\n",
82 Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
86 unbash_spaces(dirname);
87 foreach_res(director, R_DIRECTOR) {
88 if (strcmp(director->hdr.name, dirname) == 0)
93 char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
94 Jmsg2(jcr, M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"),
100 /* TLS Requirement */
101 if (director->tls_enable) {
102 if (director->tls_require) {
103 tls_local_need = BNET_TLS_REQUIRED;
105 tls_local_need = BNET_TLS_OK;
109 if (director->tls_authenticate) {
110 tls_local_need = BNET_TLS_REQUIRED;
113 if (director->tls_verify_peer) {
114 verify_list = director->tls_allowed_cns;
118 tid = start_bsock_timer(bs, AUTH_TIMEOUT);
119 /* Challenge the director */
120 auth_success = cram_md5_challenge(bs, director->password, tls_local_need, compatible);
121 if (job_canceled(jcr)) {
122 auth_success = false;
123 goto auth_fatal; /* quick exit */
126 auth_success = cram_md5_respond(bs, director->password, &tls_remote_need, &compatible);
129 char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
130 Dmsg1(dbglvl, "cram_get_auth failed for %s\n", who);
134 char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
135 Dmsg1(dbglvl, "cram_auth failed for %s\n", who);
138 Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"),
143 /* Verify that the remote host is willing to meet our TLS requirements */
144 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
145 Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
146 " advertize required TLS support.\n"));
147 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
148 auth_success = false;
152 /* Verify that we are willing to meet the remote host's requirements */
153 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
154 Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
155 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
156 auth_success = false;
160 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
161 /* Engage TLS! Full Speed Ahead! */
162 if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) {
163 Jmsg0(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
164 auth_success = false;
167 if (director->tls_authenticate) { /* authentication only? */
168 bs->free_tls(); /* shutodown tls */
174 stop_bsock_timer(tid);
177 free_pool_memory(dirname);
178 jcr->director = director;
179 /* Single thread all failures to avoid DOS */
189 * Inititiate the communications with the Director.
190 * He has made a connection to our server.
192 * Basic tasks done here:
193 * We read Director's initial message and authorize him.
196 int authenticate_director(JCR *jcr)
198 BSOCK *dir = jcr->dir_bsock;
200 if (!authenticate(R_DIRECTOR, dir, jcr)) {
201 bnet_fsend(dir, "%s", Dir_sorry);
202 Emsg0(M_FATAL, 0, _("Unable to authenticate Director\n"));
205 return bnet_fsend(dir, "%s", OK_hello);
209 * First prove our identity to the Storage daemon, then
210 * make him prove his identity.
212 int authenticate_storagedaemon(JCR *jcr)
214 BSOCK *sd = jcr->store_bsock;
215 int tls_local_need = BNET_TLS_NONE;
216 int tls_remote_need = BNET_TLS_NONE;
217 int compatible = true;
218 bool auth_success = false;
220 btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
222 /* TLS Requirement */
223 if (have_tls && me->tls_enable) {
224 if (me->tls_require) {
225 tls_local_need = BNET_TLS_REQUIRED;
227 tls_local_need = BNET_TLS_OK;
231 if (me->tls_authenticate) {
232 tls_local_need = BNET_TLS_REQUIRED;
235 if (job_canceled(jcr)) {
236 auth_success = false; /* force quick exit */
240 /* Respond to SD challenge */
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 */
247 Dmsg1(dbglvl, "cram_respond failed for %s\n", sd->who());
249 /* Now challenge him */
250 auth_success = cram_md5_challenge(sd, jcr->sd_auth_key, tls_local_need, compatible);
252 Dmsg1(dbglvl, "cram_challenge failed for %s\n", sd->who());
257 Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
258 "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
262 /* Verify that the remote host is willing to meet our TLS requirements */
263 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
264 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
265 " advertize required TLS support.\n"));
266 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
267 auth_success = false;
271 /* Verify that we are willing to meet the remote host's requirements */
272 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
273 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
274 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
275 auth_success = false;
279 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
280 /* Engage TLS! Full Speed Ahead! */
281 if (!bnet_tls_client(me->tls_ctx, sd, NULL)) {
282 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
283 auth_success = false;
286 if (me->tls_authenticate) { /* tls authentication only? */
287 sd->free_tls(); /* yes, shutdown tls */
292 /* Destroy session key */
293 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
294 stop_bsock_timer(tid);
295 /* Single thread all failures to avoid DOS */