2 * Authenticate Director who is attempting to connect.
4 * Kern Sibbald, October 2000
10 Bacula® - The Network Backup Solution
12 Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
14 The main author of Bacula is Kern Sibbald, with contributions from
15 many others, a complete list can be found in the file AUTHORS.
16 This program is Free Software; you can redistribute it and/or
17 modify it under the terms of version two of the GNU General Public
18 License as published by the Free Software Foundation plus additions
19 that are listed in the file LICENSE.
21 This program is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
31 Bacula® is a registered trademark of John Walker.
32 The licensor of Bacula is the Free Software Foundation Europe
33 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
34 Switzerland, email:ftf@fsfeurope.org.
40 static char OK_hello[] = "2000 OK Hello\n";
41 static char Dir_sorry[] = "2999 No go\n";
42 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
44 /*********************************************************************
47 static bool authenticate(int rcode, BSOCK *bs, JCR* jcr)
49 POOLMEM *dirname = get_pool_memory(PM_MESSAGE);
50 DIRRES *director = NULL;
51 int tls_local_need = BNET_TLS_NONE;
52 int tls_remote_need = BNET_TLS_NONE;
53 int compatible = true; /* Want md5 compatible DIR */
54 bool auth_success = false;
55 alist *verify_list = NULL;
58 if (rcode != R_DIRECTOR) {
59 Dmsg1(50, "I only authenticate directors, not %d\n", rcode);
60 Emsg1(M_FATAL, 0, _("I only authenticate directors, not %d\n"), rcode);
63 if (bs->msglen < 25 || bs->msglen > 500) {
64 Dmsg2(50, "Bad Hello command from Director at %s. Len=%d.\n",
65 bs->who(), bs->msglen);
67 char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
68 Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
72 dirname = check_pool_memory_size(dirname, bs->msglen);
74 if (sscanf(bs->msg, "Hello Director %s calling", dirname) != 1) {
76 char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
78 Dmsg2(50, "Bad Hello command from Director at %s: %s\n",
80 Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
84 unbash_spaces(dirname);
85 foreach_res(director, R_DIRECTOR) {
86 if (strcmp(director->hdr.name, dirname) == 0)
91 char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
92 Emsg2(M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"),
99 if (director->tls_enable) {
100 if (director->tls_require) {
101 tls_local_need = BNET_TLS_REQUIRED;
103 tls_local_need = BNET_TLS_OK;
107 if (director->tls_verify_peer) {
108 verify_list = director->tls_allowed_cns;
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 */
120 auth_success = cram_md5_respond(bs, director->password, &tls_remote_need, &compatible);
123 char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
124 Dmsg1(50, "cram_get_auth failed for %s\n", who);
128 char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who() : addr;
129 Dmsg1(50, "cram_auth failed for %s\n", who);
132 Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"),
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 Emsg0(M_FATAL, 0, _("Authorization problem: Remote server did not"
140 " advertize required TLS support.\n"));
141 auth_success = false;
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 Emsg0(M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
148 auth_success = false;
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 Emsg0(M_FATAL, 0, _("TLS negotiation failed.\n"));
157 auth_success = false;
165 stop_bsock_timer(tid);
168 free_pool_memory(dirname);
169 jcr->director = director;
170 /* Single thread all failures to avoid DOS */
180 * Inititiate the communications with the Director.
181 * He has made a connection to our server.
183 * Basic tasks done here:
184 * We read Director's initial message and authorize him.
187 int authenticate_director(JCR *jcr)
189 BSOCK *dir = jcr->dir_bsock;
191 if (!authenticate(R_DIRECTOR, dir, jcr)) {
192 bnet_fsend(dir, "%s", Dir_sorry);
193 Emsg0(M_FATAL, 0, _("Unable to authenticate Director\n"));
196 return bnet_fsend(dir, "%s", OK_hello);
200 * First prove our identity to the Storage daemon, then
201 * make him prove his identity.
203 int authenticate_storagedaemon(JCR *jcr)
205 BSOCK *sd = jcr->store_bsock;
206 int tls_local_need = BNET_TLS_NONE;
207 int tls_remote_need = BNET_TLS_NONE;
208 int compatible = true;
209 bool auth_success = false;
211 btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
213 /* TLS Requirement */
214 if (have_tls && me->tls_enable) {
215 if (me->tls_require) {
216 tls_local_need = BNET_TLS_REQUIRED;
218 tls_local_need = BNET_TLS_OK;
222 if (job_canceled(jcr)) {
223 auth_success = false; /* force quick exit */
227 /* Respond to SD challenge */
228 auth_success = cram_md5_respond(sd, jcr->sd_auth_key, &tls_remote_need, &compatible);
229 if (job_canceled(jcr)) {
230 auth_success = false; /* force quick exit */
234 Dmsg1(50, "cram_respond failed for %s\n", sd->who());
236 /* Now challenge him */
237 auth_success = cram_md5_challenge(sd, jcr->sd_auth_key, tls_local_need, compatible);
239 Dmsg1(50, "cram_challenge failed for %s\n", sd->who());
244 Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
245 "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
249 /* Verify that the remote host is willing to meet our TLS requirements */
250 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
251 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
252 " advertise required TLS support.\n"));
253 auth_success = false;
257 /* Verify that we are willing to meet the remote host's requirements */
258 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
259 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
260 auth_success = false;
264 if (have_tls && tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
265 /* Engage TLS! Full Speed Ahead! */
266 if (!bnet_tls_client(me->tls_ctx, sd, NULL)) {
267 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
268 auth_success = false;
274 /* Destroy session key */
275 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
276 stop_bsock_timer(tid);
277 /* Single thread all failures to avoid DOS */