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 * Send my name to the Storage daemon then do authentication
73 bstrncpy(dirname, director->hdr.name, sizeof(dirname));
75 /* Timeout Hello after 1 min */
76 btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
77 /* Sent Hello SD: Bacula Director <dirname> calling <version> */
78 if (!sd->fsend(hello, "SD: Bacula ", dirname, DIR_VERSION)) {
79 stop_bsock_timer(tid);
80 Dmsg1(dbglvl, _("Error sending Hello to Storage daemon. ERR=%s\n"), sd->bstrerror());
81 Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to Storage daemon. ERR=%s\n"), sd->bstrerror());
86 if (store->tls_enable) {
87 if (store->tls_require) {
88 tls_local_need = BNET_TLS_REQUIRED;
90 tls_local_need = BNET_TLS_OK;
94 if (store->tls_authenticate) {
95 tls_local_need = BNET_TLS_REQUIRED;
98 auth_success = cram_md5_respond(sd, store->password, &tls_remote_need, &compatible);
100 auth_success = cram_md5_challenge(sd, store->password, tls_local_need, compatible);
102 Dmsg1(dbglvl, "cram_challenge failed for %s\n", sd->who());
105 Dmsg1(dbglvl, "cram_respond failed for %s\n", sd->who());
109 stop_bsock_timer(tid);
110 Dmsg0(dbglvl, _("Director and Storage daemon passwords or names not the same.\n"));
111 Jmsg2(jcr, M_FATAL, 0,
112 _("Director unable to authenticate with Storage daemon at \"%s:%d\". Possible causes:\n"
113 "Passwords or names not the same or\n"
114 "Maximum Concurrent Jobs exceeded on the SD or\n"
115 "SD networking messed up (restart daemon).\n"
116 "For help, please see: " MANUAL_AUTH_URL "\n"),
117 sd->host(), sd->port());
121 /* Verify that the remote host is willing to meet our TLS requirements */
122 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
123 stop_bsock_timer(tid);
124 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not advertise required TLS support.\n"));
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 stop_bsock_timer(tid);
131 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
135 /* Is TLS Enabled? */
136 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
137 /* Engage TLS! Full Speed Ahead! */
138 if (!bnet_tls_client(store->tls_ctx, sd, NULL)) {
139 stop_bsock_timer(tid);
140 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with SD at \"%s:%d\"\n"),
141 sd->host(), sd->port());
144 if (store->tls_authenticate) { /* authentication only? */
145 sd->free_tls(); /* yes, stop tls */
149 Dmsg1(116, ">stored: %s", sd->msg);
150 if (sd->recv() <= 0) {
151 stop_bsock_timer(tid);
152 Jmsg3(jcr, M_FATAL, 0, _("bdird<stored: \"%s:%s\" bad response to Hello command: ERR=%s\n"),
153 sd->who(), sd->host(), sd->bstrerror());
156 Dmsg1(110, "<stored: %s", sd->msg);
157 stop_bsock_timer(tid);
159 if (sscanf(sd->msg, SDOKnewHello, &jcr->SDVersion) != 1 &&
160 strncmp(sd->msg, OKhello, sizeof(OKhello)) != 0) {
161 Dmsg0(dbglvl, _("Storage daemon rejected Hello command\n"));
162 Jmsg2(jcr, M_FATAL, 0, _("Storage daemon at \"%s:%d\" rejected Hello command\n"),
163 sd->host(), sd->port());
166 if (jcr->SDVersion < 305) {
167 Jmsg2(jcr, M_FATAL, 0, _("Older Storage daemon at \"%s:%d\" incompatible with this Director.\n"),
168 sd->host(), sd->port());
175 * Authenticate File daemon connection
177 int authenticate_file_daemon(JCR *jcr)
179 BSOCK *fd = jcr->file_bsock;
180 CLIENT *client = jcr->client;
181 char dirname[MAX_NAME_LENGTH];
182 int tls_local_need = BNET_TLS_NONE;
183 int tls_remote_need = BNET_TLS_NONE;
184 int compatible = true;
185 bool auth_success = false;
188 * Send my name to the File daemon then do authentication
190 bstrncpy(dirname, director->name(), sizeof(dirname));
191 bash_spaces(dirname);
192 /* Timeout Hello after 1 min */
193 btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
194 if (!fd->fsend(hello, "", dirname, DIR_VERSION)) {
195 stop_bsock_timer(tid);
196 Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to File daemon at \"%s:%d\". ERR=%s\n"),
197 fd->host(), fd->port(), fd->bstrerror());
198 Dmsg3(50, _("Error sending Hello to File daemon at \"%s:%d\". ERR=%s\n"),
199 fd->host(), fd->port(), fd->bstrerror());
202 Dmsg1(dbglvl, "Sent: %s", fd->msg);
204 /* TLS Requirement */
205 if (client->tls_enable) {
206 if (client->tls_require) {
207 tls_local_need = BNET_TLS_REQUIRED;
209 tls_local_need = BNET_TLS_OK;
213 if (client->tls_authenticate) {
214 tls_local_need = BNET_TLS_REQUIRED;
217 auth_success = cram_md5_respond(fd, client->password, &tls_remote_need, &compatible);
219 auth_success = cram_md5_challenge(fd, client->password, tls_local_need, compatible);
221 Dmsg1(dbglvl, "cram_auth failed for %s\n", fd->who());
224 Dmsg1(dbglvl, "cram_get_auth failed for %s\n", fd->who());
227 stop_bsock_timer(tid);
228 Dmsg0(dbglvl, _("Director and File daemon passwords or names not the same.\n"));
229 Jmsg(jcr, M_FATAL, 0,
230 _("Unable to authenticate with File daemon at \"%s:%d\". Possible causes:\n"
231 "Passwords or names not the same or\n"
232 "Maximum Concurrent Jobs exceeded on the FD or\n"
233 "FD networking messed up (restart daemon).\n"
234 "For help, please see: " MANUAL_AUTH_URL "\n"),
235 fd->host(), fd->port());
239 /* Verify that the remote host is willing to meet our TLS requirements */
240 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
241 stop_bsock_timer(tid);
242 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: FD \"%s:%s\" did not advertise required TLS support.\n"),
243 fd->who(), fd->host());
247 /* Verify that we are willing to meet the remote host's requirements */
248 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
249 stop_bsock_timer(tid);
250 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: FD at \"%s:%d\" requires TLS.\n"),
251 fd->host(), fd->port());
255 /* Is TLS Enabled? */
256 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
257 /* Engage TLS! Full Speed Ahead! */
258 if (!bnet_tls_client(client->tls_ctx, fd, client->tls_allowed_cns)) {
259 stop_bsock_timer(tid);
260 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with FD at \"%s:%d\".\n"),
261 fd->host(), fd->port());
264 if (client->tls_authenticate) { /* tls authentication only? */
265 fd->free_tls(); /* yes, shutdown tls */
269 Dmsg1(116, ">filed: %s", fd->msg);
270 if (fd->recv() <= 0) {
271 stop_bsock_timer(tid);
272 Dmsg1(dbglvl, _("Bad response from File daemon to Hello command: ERR=%s\n"),
274 Jmsg(jcr, M_FATAL, 0, _("Bad response from File daemon at \"%s:%d\" to Hello command: ERR=%s\n"),
275 fd->host(), fd->port(), fd->bstrerror());
278 Dmsg1(110, "<filed: %s", fd->msg);
279 stop_bsock_timer(tid);
281 if (strncmp(fd->msg, FDOKhello, sizeof(FDOKhello)) != 0 &&
282 sscanf(fd->msg, FDOKnewHello, &jcr->FDVersion) != 1) {
283 Dmsg0(dbglvl, _("File daemon rejected Hello command\n"));
284 Jmsg(jcr, M_FATAL, 0, _("File daemon at \"%s:%d\" rejected Hello command\n"),
285 fd->host(), fd->port());
291 /*********************************************************************
294 int authenticate_user_agent(UAContext *uac)
296 char name[MAX_NAME_LENGTH];
297 int tls_local_need = BNET_TLS_NONE;
298 int tls_remote_need = BNET_TLS_NONE;
299 bool tls_authenticate;
300 int compatible = true;
302 BSOCK *ua = uac->UA_sock;
303 bool auth_success = false;
304 TLS_CONTEXT *tls_ctx = NULL;
305 alist *verify_list = NULL;
308 if (ua->msglen < 16 || ua->msglen >= MAX_NAME_LENGTH + 15) {
309 Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Len=%d\n"), ua->who(),
310 ua->host(), ua->port(), ua->msglen);
314 if (sscanf(ua->msg, "Hello %127s calling %d", name, &ua_version) != 2 &&
315 sscanf(ua->msg, "Hello %127s calling", name) != 1) {
316 ua->msg[100] = 0; /* terminate string */
317 Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Got: %s\n"), ua->who(),
318 ua->host(), ua->port(), ua->msg);
322 name[sizeof(name)-1] = 0; /* terminate name */
323 if (strcmp(name, "*UserAgent*") == 0) { /* default console */
324 /* TLS Requirement */
325 if (director->tls_enable) {
326 if (director->tls_require) {
327 tls_local_need = BNET_TLS_REQUIRED;
329 tls_local_need = BNET_TLS_OK;
333 tls_authenticate = director->tls_authenticate;
335 if (tls_authenticate) {
336 tls_local_need = BNET_TLS_REQUIRED;
339 if (director->tls_verify_peer) {
340 verify_list = director->tls_allowed_cns;
343 auth_success = cram_md5_challenge(ua, director->password, tls_local_need,
345 cram_md5_respond(ua, director->password, &tls_remote_need, &compatible);
348 cons = (CONRES *)GetResWithName(R_CONSOLE, name);
350 /* TLS Requirement */
351 if (cons->tls_enable) {
352 if (cons->tls_require) {
353 tls_local_need = BNET_TLS_REQUIRED;
355 tls_local_need = BNET_TLS_OK;
359 tls_authenticate = cons->tls_authenticate;
361 if (tls_authenticate) {
362 tls_local_need = BNET_TLS_REQUIRED;
365 if (cons->tls_verify_peer) {
366 verify_list = cons->tls_allowed_cns;
369 auth_success = cram_md5_challenge(ua, cons->password, tls_local_need,
371 cram_md5_respond(ua, cons->password, &tls_remote_need, &compatible);
374 uac->cons = cons; /* save console resource pointer */
377 auth_success = false;
383 /* Verify that the remote peer is willing to meet our TLS requirements */
384 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
385 Emsg0(M_FATAL, 0, _("Authorization problem:"
386 " Remote client did not advertise required TLS support.\n"));
387 auth_success = false;
391 /* Verify that we are willing to meet the peer's requirements */
392 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
393 Emsg0(M_FATAL, 0, _("Authorization problem:"
394 " Remote client requires TLS.\n"));
395 auth_success = false;
399 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
401 tls_ctx = cons->tls_ctx;
403 tls_ctx = director->tls_ctx;
406 /* Engage TLS! Full Speed Ahead! */
407 if (!bnet_tls_server(tls_ctx, ua, verify_list)) {
408 Emsg0(M_ERROR, 0, _("TLS negotiation failed.\n"));
409 auth_success = false;
412 if (tls_authenticate) { /* authentication only? */
413 ua->free_tls(); /* stop tls */
418 /* Authorization Completed */
421 ua->fsend("%s", _(Dir_sorry));
422 Emsg4(M_ERROR, 0, _("Unable to authenticate console \"%s\" at %s:%s:%d.\n"),
423 name, ua->who(), ua->host(), ua->port());
427 ua->fsend(_("1000 OK: %d %s %sVersion: %s (%s)\n"),
428 DIR_VERSION, my_name, "", VERSION, BDATE);