2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 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.
21 * Bacula Director -- authenticate.c -- handles authorization of
22 * Storage and File daemons.
24 * Written by: Kern Sibbald, May MMI
26 * This routine runs as a thread and must be thread reentrant.
33 static const int dbglvl = 50;
35 extern DIRRES *director;
37 /* Version at end of Hello
38 * prior to 06Aug13 no version
39 * 102 04Jun15 - added jobmedia change
41 #define DIR_VERSION 102
44 /* Command sent to SD */
45 static char hello[] = "Hello %sDirector %s calling %d\n";
47 /* Responses from Storage and File daemons */
48 static char OKhello[] = "3000 OK Hello";
49 static char SDOKnewHello[] = "3000 OK Hello %d";
50 static char FDOKhello[] = "2000 OK Hello";
51 static char FDOKnewHello[] = "2000 OK Hello %d";
53 /* Sent to User Agent */
54 static char Dir_sorry[] = "1999 You are not authorized.\n";
56 /* Forward referenced functions */
59 * Authenticate Storage daemon connection
61 bool authenticate_storage_daemon(JCR *jcr, STORE *store)
63 BSOCK *sd = jcr->store_bsock;
64 char dirname[MAX_NAME_LENGTH];
65 int tls_local_need = BNET_TLS_NONE;
66 int tls_remote_need = BNET_TLS_NONE;
67 int compatible = true;
68 bool auth_success = false;
71 Dmsg0(dbglvl, "Invalid bsock\n");
76 * Send my name to the Storage daemon then do authentication
78 bstrncpy(dirname, director->hdr.name, sizeof(dirname));
80 /* Timeout Hello after 1 min */
81 btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
82 /* Sent Hello SD: Bacula Director <dirname> calling <version> */
83 if (!sd->fsend(hello, "SD: Bacula ", dirname, DIR_VERSION)) {
84 stop_bsock_timer(tid);
85 Dmsg1(dbglvl, _("Error sending Hello to Storage daemon. ERR=%s\n"), sd->bstrerror());
86 Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to Storage daemon. ERR=%s\n"), sd->bstrerror());
91 if (store->tls_enable) {
92 if (store->tls_require) {
93 tls_local_need = BNET_TLS_REQUIRED;
95 tls_local_need = BNET_TLS_OK;
99 if (store->tls_authenticate) {
100 tls_local_need = BNET_TLS_REQUIRED;
103 auth_success = cram_md5_respond(sd, store->password, &tls_remote_need, &compatible);
105 auth_success = cram_md5_challenge(sd, store->password, tls_local_need, compatible);
107 Dmsg1(dbglvl, "cram_challenge failed for %s\n", sd->who());
110 Dmsg1(dbglvl, "cram_respond failed for %s\n", sd->who());
114 stop_bsock_timer(tid);
115 Dmsg0(dbglvl, _("Director and Storage daemon passwords or names not the same.\n"));
116 Jmsg2(jcr, M_FATAL, 0,
117 _("Director unable to authenticate with Storage daemon at \"%s:%d\". Possible causes:\n"
118 "Passwords or names not the same or\n"
119 "Maximum Concurrent Jobs exceeded on the SD or\n"
120 "SD networking messed up (restart daemon).\n"
121 "For help, please see: " MANUAL_AUTH_URL "\n"),
122 sd->host(), sd->port());
126 /* Verify that the remote host is willing to meet our TLS requirements */
127 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
128 stop_bsock_timer(tid);
129 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not advertise required TLS support.\n"));
133 /* Verify that we are willing to meet the remote host's requirements */
134 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
135 stop_bsock_timer(tid);
136 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
140 /* Is TLS Enabled? */
141 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
142 /* Engage TLS! Full Speed Ahead! */
143 if (!bnet_tls_client(store->tls_ctx, sd, NULL)) {
144 stop_bsock_timer(tid);
145 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with SD at \"%s:%d\"\n"),
146 sd->host(), sd->port());
149 if (store->tls_authenticate) { /* authentication only? */
150 sd->free_tls(); /* yes, stop tls */
154 Dmsg1(116, ">stored: %s", sd->msg);
155 if (sd->recv() <= 0) {
156 stop_bsock_timer(tid);
157 Jmsg3(jcr, M_FATAL, 0, _("bdird<stored: \"%s:%s\" bad response to Hello command: ERR=%s\n"),
158 sd->who(), sd->host(), sd->bstrerror());
161 Dmsg1(110, "<stored: %s", sd->msg);
162 stop_bsock_timer(tid);
164 if (sscanf(sd->msg, SDOKnewHello, &jcr->SDVersion) != 1 &&
165 strncmp(sd->msg, OKhello, sizeof(OKhello)) != 0) {
166 Dmsg0(dbglvl, _("Storage daemon rejected Hello command\n"));
167 Jmsg2(jcr, M_FATAL, 0, _("Storage daemon at \"%s:%d\" rejected Hello command\n"),
168 sd->host(), sd->port());
171 if (jcr->SDVersion < 305) {
172 Jmsg2(jcr, M_FATAL, 0, _("Older Storage daemon at \"%s:%d\" incompatible with this Director.\n"),
173 sd->host(), sd->port());
180 * Authenticate File daemon connection
182 int authenticate_file_daemon(JCR *jcr)
184 BSOCK *fd = jcr->file_bsock;
185 CLIENT *client = jcr->client;
186 char dirname[MAX_NAME_LENGTH];
187 int tls_local_need = BNET_TLS_NONE;
188 int tls_remote_need = BNET_TLS_NONE;
189 int compatible = true;
190 bool auth_success = false;
193 * Send my name to the File daemon then do authentication
195 bstrncpy(dirname, director->name(), sizeof(dirname));
196 bash_spaces(dirname);
197 /* Timeout Hello after 1 min */
198 btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
199 if (!fd->fsend(hello, "", dirname, DIR_VERSION)) {
200 stop_bsock_timer(tid);
201 Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to File daemon at \"%s:%d\". ERR=%s\n"),
202 fd->host(), fd->port(), fd->bstrerror());
203 Dmsg3(50, _("Error sending Hello to File daemon at \"%s:%d\". ERR=%s\n"),
204 fd->host(), fd->port(), fd->bstrerror());
207 Dmsg1(dbglvl, "Sent: %s", fd->msg);
209 /* TLS Requirement */
210 if (client->tls_enable) {
211 if (client->tls_require) {
212 tls_local_need = BNET_TLS_REQUIRED;
214 tls_local_need = BNET_TLS_OK;
218 if (client->tls_authenticate) {
219 tls_local_need = BNET_TLS_REQUIRED;
222 auth_success = cram_md5_respond(fd, client->password, &tls_remote_need, &compatible);
224 auth_success = cram_md5_challenge(fd, client->password, tls_local_need, compatible);
226 Dmsg1(dbglvl, "cram_auth failed for %s\n", fd->who());
229 Dmsg1(dbglvl, "cram_get_auth failed for %s\n", fd->who());
232 stop_bsock_timer(tid);
233 Dmsg0(dbglvl, _("Director and File daemon passwords or names not the same.\n"));
234 Jmsg(jcr, M_FATAL, 0,
235 _("Unable to authenticate with File daemon at \"%s:%d\". Possible causes:\n"
236 "Passwords or names not the same or\n"
237 "Maximum Concurrent Jobs exceeded on the FD or\n"
238 "FD networking messed up (restart daemon).\n"
239 "For help, please see: " MANUAL_AUTH_URL "\n"),
240 fd->host(), fd->port());
244 /* Verify that the remote host is willing to meet our TLS requirements */
245 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
246 stop_bsock_timer(tid);
247 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: FD \"%s:%s\" did not advertise required TLS support.\n"),
248 fd->who(), fd->host());
252 /* Verify that we are willing to meet the remote host's requirements */
253 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
254 stop_bsock_timer(tid);
255 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: FD at \"%s:%d\" requires TLS.\n"),
256 fd->host(), fd->port());
260 /* Is TLS Enabled? */
261 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
262 /* Engage TLS! Full Speed Ahead! */
263 if (!bnet_tls_client(client->tls_ctx, fd, client->tls_allowed_cns)) {
264 stop_bsock_timer(tid);
265 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with FD at \"%s:%d\".\n"),
266 fd->host(), fd->port());
269 if (client->tls_authenticate) { /* tls authentication only? */
270 fd->free_tls(); /* yes, shutdown tls */
274 Dmsg1(116, ">filed: %s", fd->msg);
275 if (fd->recv() <= 0) {
276 stop_bsock_timer(tid);
277 Dmsg1(dbglvl, _("Bad response from File daemon to Hello command: ERR=%s\n"),
279 Jmsg(jcr, M_FATAL, 0, _("Bad response from File daemon at \"%s:%d\" to Hello command: ERR=%s\n"),
280 fd->host(), fd->port(), fd->bstrerror());
283 Dmsg1(110, "<filed: %s", fd->msg);
284 stop_bsock_timer(tid);
286 if (strncmp(fd->msg, FDOKhello, sizeof(FDOKhello)) != 0 &&
287 sscanf(fd->msg, FDOKnewHello, &jcr->FDVersion) != 1) {
288 Dmsg0(dbglvl, _("File daemon rejected Hello command\n"));
289 Jmsg(jcr, M_FATAL, 0, _("File daemon at \"%s:%d\" rejected Hello command\n"),
290 fd->host(), fd->port());
296 /*********************************************************************
299 int authenticate_user_agent(UAContext *uac)
301 char name[MAX_NAME_LENGTH];
302 int tls_local_need = BNET_TLS_NONE;
303 int tls_remote_need = BNET_TLS_NONE;
304 bool tls_authenticate;
305 int compatible = true;
307 BSOCK *ua = uac->UA_sock;
308 bool auth_success = false;
309 TLS_CONTEXT *tls_ctx = NULL;
310 alist *verify_list = NULL;
313 if (ua->msglen < 16 || ua->msglen >= MAX_NAME_LENGTH + 15) {
314 Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Len=%d\n"), ua->who(),
315 ua->host(), ua->port(), ua->msglen);
319 if (sscanf(ua->msg, "Hello %127s calling %d", name, &ua_version) != 2 &&
320 sscanf(ua->msg, "Hello %127s calling", name) != 1) {
321 ua->msg[100] = 0; /* terminate string */
322 Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Got: %s\n"), ua->who(),
323 ua->host(), ua->port(), ua->msg);
327 name[sizeof(name)-1] = 0; /* terminate name */
328 if (strcmp(name, "*UserAgent*") == 0) { /* default console */
329 /* TLS Requirement */
330 if (director->tls_enable) {
331 if (director->tls_require) {
332 tls_local_need = BNET_TLS_REQUIRED;
334 tls_local_need = BNET_TLS_OK;
338 tls_authenticate = director->tls_authenticate;
340 if (tls_authenticate) {
341 tls_local_need = BNET_TLS_REQUIRED;
344 if (director->tls_verify_peer) {
345 verify_list = director->tls_allowed_cns;
348 auth_success = cram_md5_challenge(ua, director->password, tls_local_need,
350 cram_md5_respond(ua, director->password, &tls_remote_need, &compatible);
353 cons = (CONRES *)GetResWithName(R_CONSOLE, name);
355 /* TLS Requirement */
356 if (cons->tls_enable) {
357 if (cons->tls_require) {
358 tls_local_need = BNET_TLS_REQUIRED;
360 tls_local_need = BNET_TLS_OK;
364 tls_authenticate = cons->tls_authenticate;
366 if (tls_authenticate) {
367 tls_local_need = BNET_TLS_REQUIRED;
370 if (cons->tls_verify_peer) {
371 verify_list = cons->tls_allowed_cns;
374 auth_success = cram_md5_challenge(ua, cons->password, tls_local_need,
376 cram_md5_respond(ua, cons->password, &tls_remote_need, &compatible);
379 uac->cons = cons; /* save console resource pointer */
382 auth_success = false;
388 /* Verify that the remote peer is willing to meet our TLS requirements */
389 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
390 Emsg0(M_FATAL, 0, _("Authorization problem:"
391 " Remote client did not advertise required TLS support.\n"));
392 auth_success = false;
396 /* Verify that we are willing to meet the peer's requirements */
397 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
398 Emsg0(M_FATAL, 0, _("Authorization problem:"
399 " Remote client requires TLS.\n"));
400 auth_success = false;
404 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
406 tls_ctx = cons->tls_ctx;
408 tls_ctx = director->tls_ctx;
411 /* Engage TLS! Full Speed Ahead! */
412 if (!bnet_tls_server(tls_ctx, ua, verify_list)) {
413 Emsg0(M_ERROR, 0, _("TLS negotiation failed.\n"));
414 auth_success = false;
417 if (tls_authenticate) { /* authentication only? */
418 ua->free_tls(); /* stop tls */
423 /* Authorization Completed */
426 ua->fsend("%s", _(Dir_sorry));
427 Emsg4(M_ERROR, 0, _("Unable to authenticate console \"%s\" at %s:%s:%d.\n"),
428 name, ua->who(), ua->host(), ua->port());
432 ua->fsend(_("1000 OK: %d %s %sVersion: %s (%s)\n"),
433 DIR_VERSION, my_name, "", VERSION, BDATE);