3 * Bacula Director -- authorize.c -- handles authorization of
4 * Storage and File daemons.
6 * Kern Sibbald, May MMI
8 * This routine runs as a thread and must be thread reentrant.
14 Copyright (C) 2001-2006 Kern Sibbald
16 This program is free software; you can redistribute it and/or
17 modify it under the terms of the GNU General Public License
18 version 2 as amended with additional clauses defined in the
19 file LICENSE in the main source directory.
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 the file LICENSE for additional details.
31 extern DIRRES *director;
33 /* Commands sent to Storage daemon and File daemon and received
34 * from the User Agent */
35 static char hello[] = "Hello Director %s calling\n";
37 /* Response from Storage daemon */
38 static char OKhello[] = "3000 OK Hello\n";
39 static char FDOKhello[] = "2000 OK Hello\n";
41 /* Sent to User Agent */
42 static char Dir_sorry[] = "1999 You are not authorized.\n";
44 /* Forward referenced functions */
47 * Authenticate Storage daemon connection
49 bool authenticate_storage_daemon(JCR *jcr, STORE *store)
51 BSOCK *sd = jcr->store_bsock;
52 char dirname[MAX_NAME_LENGTH];
53 int tls_local_need = BNET_TLS_NONE;
54 int tls_remote_need = BNET_TLS_NONE;
55 bool auth_success = false;
58 * Send my name to the Storage daemon then do authentication
60 bstrncpy(dirname, director->hdr.name, sizeof(dirname));
62 /* Timeout Hello after 1 min */
63 btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
64 if (!bnet_fsend(sd, hello, dirname)) {
65 stop_bsock_timer(tid);
66 Dmsg1(50, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd));
67 Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd));
72 if (store->tls_enable) {
73 if (store->tls_require) {
74 tls_local_need = BNET_TLS_REQUIRED;
76 tls_local_need = BNET_TLS_OK;
80 auth_success = cram_md5_get_auth(sd, store->password, &tls_remote_need);
82 auth_success = cram_md5_auth(sd, store->password, tls_local_need);
84 Dmsg1(50, "cram_auth failed for %s\n", sd->who);
87 Dmsg1(50, "cram_get_auth failed for %s\n", sd->who);
91 stop_bsock_timer(tid);
92 Dmsg0(50, _("Director and Storage daemon passwords or names not the same.\n"));
93 Jmsg0(jcr, M_FATAL, 0,
94 _("Director unable to authenticate with Storage daemon. Possible causes:\n"
95 "Passwords or names not the same or\n"
96 "Maximum Concurrent Jobs exceeded on the SD or\n"
97 "SD networking messed up (restart daemon).\n"
98 "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
102 /* Verify that the remote host is willing to meet our TLS requirements */
103 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
104 stop_bsock_timer(tid);
105 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not advertise required TLS support.\n"));
109 /* Verify that we are willing to meet the remote host's requirements */
110 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
111 stop_bsock_timer(tid);
112 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
117 /* Is TLS Enabled? */
118 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
119 /* Engage TLS! Full Speed Ahead! */
120 if (!bnet_tls_client(store->tls_ctx, sd)) {
121 stop_bsock_timer(tid);
122 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
128 Dmsg1(116, ">stored: %s", sd->msg);
129 if (bnet_recv(sd) <= 0) {
130 stop_bsock_timer(tid);
131 Jmsg1(jcr, M_FATAL, 0, _("bdird<stored: bad response to Hello command: ERR=%s\n"),
135 Dmsg1(110, "<stored: %s", sd->msg);
136 stop_bsock_timer(tid);
137 if (strncmp(sd->msg, OKhello, sizeof(OKhello)) != 0) {
138 Dmsg0(50, _("Storage daemon rejected Hello command\n"));
139 Jmsg0(jcr, M_FATAL, 0, _("Storage daemon rejected Hello command\n"));
146 * Authenticate File daemon connection
148 int authenticate_file_daemon(JCR *jcr)
150 BSOCK *fd = jcr->file_bsock;
151 CLIENT *client = jcr->client;
152 char dirname[MAX_NAME_LENGTH];
153 int tls_local_need = BNET_TLS_NONE;
154 int tls_remote_need = BNET_TLS_NONE;
155 bool auth_success = false;
158 * Send my name to the File daemon then do authentication
160 bstrncpy(dirname, director->hdr.name, sizeof(dirname));
161 bash_spaces(dirname);
162 /* Timeout Hello after 10 mins */
163 btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
164 if (!bnet_fsend(fd, hello, dirname)) {
165 stop_bsock_timer(tid);
166 Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to File daemon. ERR=%s\n"), bnet_strerror(fd));
171 /* TLS Requirement */
172 if (client->tls_enable) {
173 if (client->tls_require) {
174 tls_local_need = BNET_TLS_REQUIRED;
176 tls_local_need = BNET_TLS_OK;
181 auth_success = cram_md5_get_auth(fd, client->password, &tls_remote_need);
183 auth_success = cram_md5_auth(fd, client->password, tls_local_need);
185 Dmsg1(50, "cram_auth failed for %s\n", fd->who);
188 Dmsg1(50, "cram_get_auth failed for %s\n", fd->who);
191 stop_bsock_timer(tid);
192 Dmsg0(50, _("Director and File daemon passwords or names not the same.\n"));
193 Jmsg(jcr, M_FATAL, 0,
194 _("Unable to authenticate with File daemon. Possible causes:\n"
195 "Passwords or names not the same or\n"
196 "Maximum Concurrent Jobs exceeded on the FD or\n"
197 "FD networking messed up (restart daemon).\n"
198 "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
202 /* Verify that the remote host is willing to meet our TLS requirements */
203 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
204 stop_bsock_timer(tid);
205 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not advertise required TLS support.\n"));
209 /* Verify that we are willing to meet the remote host's requirements */
210 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
211 stop_bsock_timer(tid);
212 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
217 /* Is TLS Enabled? */
218 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
219 /* Engage TLS! Full Speed Ahead! */
220 if (!bnet_tls_client(client->tls_ctx, fd)) {
221 stop_bsock_timer(tid);
222 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
228 Dmsg1(116, ">filed: %s", fd->msg);
229 if (bnet_recv(fd) <= 0) {
230 stop_bsock_timer(tid);
231 Dmsg1(50, _("Bad response from File daemon to Hello command: ERR=%s\n"),
233 Jmsg(jcr, M_FATAL, 0, _("Bad response from File daemon to Hello command: ERR=%s\n"),
237 Dmsg1(110, "<stored: %s", fd->msg);
238 stop_bsock_timer(tid);
239 if (strncmp(fd->msg, FDOKhello, sizeof(FDOKhello)) != 0) {
240 Dmsg0(50, _("File daemon rejected Hello command\n"));
241 Jmsg(jcr, M_FATAL, 0, _("File daemon rejected Hello command\n"));
247 /*********************************************************************
250 int authenticate_user_agent(UAContext *uac)
252 char name[MAX_NAME_LENGTH];
253 int tls_local_need = BNET_TLS_NONE;
254 int tls_remote_need = BNET_TLS_NONE;
256 BSOCK *ua = uac->UA_sock;
257 bool auth_success = false;
259 TLS_CONTEXT *tls_ctx = NULL;
260 alist *verify_list = NULL;
261 #endif /* HAVE_TLS */
264 // Emsg4(M_INFO, 0, _("UA Hello from %s:%s:%d is invalid. Len=%d\n"), ua->who,
265 // ua->host, ua->port, ua->msglen);
266 if (ua->msglen < 16 || ua->msglen >= MAX_NAME_LENGTH + 15) {
267 Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Len=%d\n"), ua->who,
268 ua->host, ua->port, ua->msglen);
272 if (sscanf(ua->msg, "Hello %127s calling\n", name) != 1) {
273 ua->msg[100] = 0; /* terminate string */
274 Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Got: %s\n"), ua->who,
275 ua->host, ua->port, ua->msg);
279 name[sizeof(name)-1] = 0; /* terminate name */
280 if (strcmp(name, "*UserAgent*") == 0) { /* default console */
282 /* TLS Requirement */
283 if (director->tls_enable) {
284 if (director->tls_require) {
285 tls_local_need = BNET_TLS_REQUIRED;
287 tls_local_need = BNET_TLS_OK;
291 if (director->tls_verify_peer) {
292 verify_list = director->tls_allowed_cns;
294 #endif /* HAVE_TLS */
296 auth_success = cram_md5_auth(ua, director->password, tls_local_need) &&
297 cram_md5_get_auth(ua, director->password, &tls_remote_need);
300 cons = (CONRES *)GetResWithName(R_CONSOLE, name);
303 /* TLS Requirement */
304 if (cons->tls_enable) {
305 if (cons->tls_require) {
306 tls_local_need = BNET_TLS_REQUIRED;
308 tls_local_need = BNET_TLS_OK;
312 if (cons->tls_verify_peer) {
313 verify_list = cons->tls_allowed_cns;
315 #endif /* HAVE_TLS */
317 auth_success = cram_md5_auth(ua, cons->password, tls_local_need) &&
318 cram_md5_get_auth(ua, cons->password, &tls_remote_need);
321 uac->cons = cons; /* save console resource pointer */
324 auth_success = false;
329 /* Verify that the remote peer is willing to meet our TLS requirements */
330 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
331 Emsg0(M_FATAL, 0, _("Authorization problem:"
332 " Remote client did not advertise required TLS support.\n"));
333 auth_success = false;
337 /* Verify that we are willing to meet the peer's requirements */
338 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
339 Emsg0(M_FATAL, 0, _("Authorization problem:"
340 " Remote client requires TLS.\n"));
341 auth_success = false;
346 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
348 tls_ctx = cons->tls_ctx;
350 tls_ctx = director->tls_ctx;
353 /* Engage TLS! Full Speed Ahead! */
354 if (!bnet_tls_server(tls_ctx, ua, verify_list)) {
355 Emsg0(M_ERROR, 0, _("TLS negotiation failed.\n"));
356 auth_success = false;
360 #endif /* HAVE_TLS */
363 /* Authorization Completed */
366 bnet_fsend(ua, "%s", _(Dir_sorry));
367 Emsg4(M_ERROR, 0, _("Unable to authenticate console \"%s\" at %s:%s:%d.\n"),
368 name, ua->who, ua->host, ua->port);
372 bnet_fsend(ua, _("1000 OK: %s Version: %s (%s)\n"), my_name, VERSION, BDATE);