2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2016 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
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.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
22 * Written by Kern Sibbald, October 2000
30 extern STORES *me; /* our Global resource */
32 const int dbglvl = 50;
34 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
37 * Authenticate the Director
39 bool authenticate_director(JCR* jcr)
41 DIRRES *director = jcr->director;
42 int tls_local_need = BNET_TLS_NONE;
43 int tls_remote_need = BNET_TLS_NONE;
44 int compatible = true; /* require md5 compatible DIR */
45 bool auth_success = false;
46 alist *verify_list = NULL;
47 BSOCK *dir = jcr->dir_bsock;
50 if (director->tls_enable) {
51 if (director->tls_require) {
52 tls_local_need = BNET_TLS_REQUIRED;
54 tls_local_need = BNET_TLS_OK;
58 if (director->tls_authenticate) {
59 tls_local_need = BNET_TLS_REQUIRED;
62 if (director->tls_verify_peer) {
63 verify_list = director->tls_allowed_cns;
66 /* Timeout authentication after 10 mins */
67 btimer_t *tid = start_bsock_timer(dir, AUTH_TIMEOUT);
68 auth_success = cram_md5_challenge(dir, director->password, tls_local_need, compatible);
70 auth_success = cram_md5_respond(dir, director->password, &tls_remote_need, &compatible);
72 Dmsg1(dbglvl, "cram_get_auth respond failed with Director %s\n", dir->who());
75 Dmsg1(dbglvl, "cram_auth challenge failed with Director %s\n", dir->who());
79 Jmsg0(jcr, M_FATAL, 0, _("Incorrect password given by Director.\n"
80 "For help, please see: " MANUAL_AUTH_URL "\n"));
85 /* Verify that the remote host is willing to meet our TLS requirements */
86 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
87 Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
88 " advertize required TLS support.\n"));
89 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
94 /* Verify that we are willing to meet the remote host's requirements */
95 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
96 Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
97 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
102 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
103 /* Engage TLS! Full Speed Ahead! */
104 if (!bnet_tls_server(director->tls_ctx, dir, verify_list)) {
105 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with DIR at \"%s:%d\"\n"),
106 dir->host(), dir->port());
107 auth_success = false;
110 if (director->tls_authenticate) { /* authenticate with tls only? */
111 dir->free_tls(); /* yes, shut it down */
116 stop_bsock_timer(tid);
117 jcr->director = director;
119 return send_hello_ok(dir);
122 Dmsg1(dbglvl, "Unable to authenticate Director at %s.\n", dir->who());
123 Jmsg1(jcr, M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who());
129 int authenticate_filed(JCR *jcr, BSOCK *fd, int FDVersion)
131 int tls_local_need = BNET_TLS_NONE;
132 int tls_remote_need = BNET_TLS_NONE;
133 int compatible = true; /* require md5 compatible FD */
134 bool auth_success = false;
135 alist *verify_list = NULL;
137 /* TLS Requirement */
138 if (me->tls_enable) {
139 if (me->tls_require) {
140 tls_local_need = BNET_TLS_REQUIRED;
142 tls_local_need = BNET_TLS_OK;
146 if (me->tls_authenticate) {
147 tls_local_need = BNET_TLS_REQUIRED;
150 if (me->tls_verify_peer) {
151 verify_list = me->tls_allowed_cns;
154 /* Timeout authentication after 5 mins */
155 btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
157 Dmsg0(050, "Challenge FD\n");
158 auth_success = cram_md5_challenge(fd, jcr->sd_auth_key, tls_local_need, compatible);
160 /* Respond to his challenge */
161 Dmsg0(050, "Respond to FD challenge\n");
162 auth_success = cram_md5_respond(fd, jcr->sd_auth_key, &tls_remote_need, &compatible);
164 Dmsg1(dbglvl, "Respond cram-get-auth respond failed with FD: %s\n", fd->who());
167 Dmsg1(dbglvl, "Challenge cram-auth failed with FD: %s\n", fd->who());
171 Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
172 "For help, please see: " MANUAL_AUTH_URL "\n"),
174 auth_success = false;
178 /* Verify that the remote host is willing to meet our TLS requirements */
179 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
180 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
181 " advertize required TLS support.\n"));
182 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
183 auth_success = false;
187 /* Verify that we are willing to meet the remote host's requirements */
188 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
189 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
190 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
191 auth_success = false;
195 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
196 /* Engage TLS! Full Speed Ahead! */
197 if (!bnet_tls_server(me->tls_ctx, fd, verify_list)) {
198 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with FD at \"%s:%d\"\n"),
199 fd->host(), fd->port());
200 auth_success = false;
203 if (me->tls_authenticate) { /* tls authenticate only? */
204 fd->free_tls(); /* yes, shut it down */
209 stop_bsock_timer(tid);
211 Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
212 "For help, please see: " MANUAL_AUTH_URL "\n"),
216 /* Version 5 of the protocol is a bit special, it is used by both 6.0.0
217 * Enterprise version and 7.0.x Community version, but do not support the
218 * same level of features. As nobody is using the 6.0.0 release, we can
219 * be pretty sure that the FD in version 5 is a community FD.
221 if (auth_success && (FDVersion >= 9 || FDVersion == 5)) {
228 * First prove our identity to the Storage daemon, then
229 * make him prove his identity.
231 bool authenticate_storagedaemon(JCR *jcr)
233 BSOCK *sd = jcr->store_bsock;
234 int tls_local_need = BNET_TLS_NONE;
235 int tls_remote_need = BNET_TLS_NONE;
236 int compatible = true;
237 bool auth_success = false;
240 btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
242 /* TLS Requirement */
243 if (have_tls && me->tls_enable) {
244 if (me->tls_require) {
245 tls_local_need = BNET_TLS_REQUIRED;
247 tls_local_need = BNET_TLS_OK;
251 if (me->tls_authenticate) {
252 tls_local_need = BNET_TLS_REQUIRED;
255 if (job_canceled(jcr)) {
256 auth_success = false; /* force quick exit */
260 /* Respond to SD challenge */
261 Dmsg0(050, "Respond to SD challenge\n");
262 auth_success = cram_md5_respond(sd, jcr->sd_auth_key, &tls_remote_need, &compatible);
263 if (job_canceled(jcr)) {
264 auth_success = false; /* force quick exit */
268 Dmsg1(dbglvl, "cram_respond failed for SD: %s\n", sd->who());
270 /* Now challenge him */
271 Dmsg0(050, "Challenge SD\n");
272 auth_success = cram_md5_challenge(sd, jcr->sd_auth_key, tls_local_need, compatible);
274 Dmsg1(dbglvl, "cram_challenge failed for SD: %s\n", sd->who());
279 Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
280 "Please see " MANUAL_AUTH_URL " for help.\n"));
283 Dmsg0(050, "Authorization with SD is OK\n");
286 /* Verify that the remote host is willing to meet our TLS requirements */
287 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
288 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
289 " advertize required TLS support.\n"));
290 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
291 auth_success = false;
295 /* Verify that we are willing to meet the remote host's requirements */
296 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
297 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
298 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
299 auth_success = false;
303 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
304 /* Engage TLS! Full Speed Ahead! */
305 if (!bnet_tls_client(me->tls_ctx, sd, NULL)) {
306 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
307 auth_success = false;
310 if (me->tls_authenticate) { /* tls authentication only? */
311 sd->free_tls(); /* yes, shutdown tls */
314 if (sd->recv() <= 0) {
315 auth_success = false;
318 sscanf(sd->msg, "3000 OK Hello %d", &sd_version);
319 /* At this point, we have successfully connected */
322 /* Destroy session key */
323 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
324 stop_bsock_timer(tid);
325 /* Single thread all failures to avoid DOS */