2 Bacula® - The Network Backup Solution
4 Copyright (C) 2001-2008 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
30 * Bacula Director -- authorize.c -- handles authorization of
31 * Storage and File daemons.
33 * Kern Sibbald, May MMI
35 * This routine runs as a thread and must be thread reentrant.
44 static const int dbglvl = 50;
46 extern DIRRES *director;
48 /* Commands sent to Storage daemon and File daemon and received
49 * from the User Agent */
50 static char hello[] = "Hello Director %s calling\n";
52 /* Response from Storage daemon */
53 static char OKhello[] = "3000 OK Hello\n";
54 static char FDOKhello[] = "2000 OK Hello\n";
55 static char FDOKnewHello[] = "2000 OK Hello %d\n";
57 /* Sent to User Agent */
58 static char Dir_sorry[] = "1999 You are not authorized.\n";
60 /* Forward referenced functions */
63 * Authenticate Storage daemon connection
65 bool authenticate_storage_daemon(JCR *jcr, STORE *store)
67 BSOCK *sd = jcr->store_bsock;
68 char dirname[MAX_NAME_LENGTH];
69 int tls_local_need = BNET_TLS_NONE;
70 int tls_remote_need = BNET_TLS_NONE;
71 int compatible = true;
72 bool auth_success = false;
75 * Send my name to the Storage daemon then do authentication
77 bstrncpy(dirname, director->hdr.name, sizeof(dirname));
79 /* Timeout Hello after 1 min */
80 btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
81 if (!sd->fsend(hello, dirname)) {
82 stop_bsock_timer(tid);
83 Dmsg1(dbglvl, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd));
84 Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd));
89 if (store->tls_enable) {
90 if (store->tls_require) {
91 tls_local_need = BNET_TLS_REQUIRED;
93 tls_local_need = BNET_TLS_OK;
97 if (store->tls_authenticate) {
98 tls_local_need = BNET_TLS_REQUIRED;
101 auth_success = cram_md5_respond(sd, store->password, &tls_remote_need, &compatible);
103 auth_success = cram_md5_challenge(sd, store->password, tls_local_need, compatible);
105 Dmsg1(dbglvl, "cram_challenge failed for %s\n", sd->who());
108 Dmsg1(dbglvl, "cram_respond failed for %s\n", sd->who());
112 stop_bsock_timer(tid);
113 Dmsg0(dbglvl, _("Director and Storage daemon passwords or names not the same.\n"));
114 Jmsg2(jcr, M_FATAL, 0,
115 _("Director unable to authenticate with Storage daemon at \"%s:%d\". Possible causes:\n"
116 "Passwords or names not the same or\n"
117 "Maximum Concurrent Jobs exceeded on the SD or\n"
118 "SD networking messed up (restart daemon).\n"
119 "Please see http://www.bacula.org/en/rel-manual/Bacula_Freque_Asked_Questi.html#SECTION003760000000000000000 for help.\n"),
120 sd->host(), sd->port());
124 /* Verify that the remote host is willing to meet our TLS requirements */
125 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
126 stop_bsock_timer(tid);
127 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not advertise required TLS support.\n"));
131 /* Verify that we are willing to meet the remote host's requirements */
132 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
133 stop_bsock_timer(tid);
134 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
138 /* Is TLS Enabled? */
139 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
140 /* Engage TLS! Full Speed Ahead! */
141 if (!bnet_tls_client(store->tls_ctx, sd, NULL)) {
142 stop_bsock_timer(tid);
143 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with SD at \"%s:%d\"\n"),
144 sd->host(), sd->port());
147 if (store->tls_authenticate) { /* authentication only? */
148 sd->free_tls(); /* yes, stop tls */
152 Dmsg1(116, ">stored: %s", sd->msg);
153 if (sd->recv() <= 0) {
154 stop_bsock_timer(tid);
155 Jmsg3(jcr, M_FATAL, 0, _("bdird<stored: \"%s:%s\" bad response to Hello command: ERR=%s\n"),
156 sd->who(), sd->host(), sd->bstrerror());
159 Dmsg1(110, "<stored: %s", sd->msg);
160 stop_bsock_timer(tid);
161 if (strncmp(sd->msg, OKhello, sizeof(OKhello)) != 0) {
162 Dmsg0(dbglvl, _("Storage daemon rejected Hello command\n"));
163 Jmsg2(jcr, M_FATAL, 0, _("Storage daemon at \"%s:%d\" rejected Hello command\n"),
164 sd->host(), sd->port());
171 * Authenticate File daemon connection
173 int authenticate_file_daemon(JCR *jcr)
175 BSOCK *fd = jcr->file_bsock;
176 CLIENT *client = jcr->client;
177 char dirname[MAX_NAME_LENGTH];
178 int tls_local_need = BNET_TLS_NONE;
179 int tls_remote_need = BNET_TLS_NONE;
180 int compatible = true;
181 bool auth_success = false;
184 * Send my name to the File daemon then do authentication
186 bstrncpy(dirname, director->name(), sizeof(dirname));
187 bash_spaces(dirname);
188 /* Timeout Hello after 1 min */
189 btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
190 if (!fd->fsend(hello, dirname)) {
191 stop_bsock_timer(tid);
192 Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to File daemon at \"%s:%d\". ERR=%s\n"),
193 fd->host(), fd->port(), fd->bstrerror());
196 Dmsg1(dbglvl, "Sent: %s", fd->msg);
198 /* TLS Requirement */
199 if (client->tls_enable) {
200 if (client->tls_require) {
201 tls_local_need = BNET_TLS_REQUIRED;
203 tls_local_need = BNET_TLS_OK;
207 if (client->tls_authenticate) {
208 tls_local_need = BNET_TLS_REQUIRED;
211 auth_success = cram_md5_respond(fd, client->password, &tls_remote_need, &compatible);
213 auth_success = cram_md5_challenge(fd, client->password, tls_local_need, compatible);
215 Dmsg1(dbglvl, "cram_auth failed for %s\n", fd->who());
218 Dmsg1(dbglvl, "cram_get_auth failed for %s\n", fd->who());
221 stop_bsock_timer(tid);
222 Dmsg0(dbglvl, _("Director and File daemon passwords or names not the same.\n"));
223 Jmsg(jcr, M_FATAL, 0,
224 _("Unable to authenticate with File daemon at \"%s:%d\". Possible causes:\n"
225 "Passwords or names not the same or\n"
226 "Maximum Concurrent Jobs exceeded on the FD or\n"
227 "FD networking messed up (restart daemon).\n"
228 "Please see http://www.bacula.org/en/rel-manual/Bacula_Freque_Asked_Questi.html#SECTION003760000000000000000 for help.\n"),
229 fd->host(), fd->port());
233 /* Verify that the remote host is willing to meet our TLS requirements */
234 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
235 stop_bsock_timer(tid);
236 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: FD \"%s:%s\" did not advertise required TLS support.\n"),
237 fd->who(), fd->host());
241 /* Verify that we are willing to meet the remote host's requirements */
242 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
243 stop_bsock_timer(tid);
244 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: FD at \"%s:%d\" requires TLS.\n"),
245 fd->host(), fd->port());
249 /* Is TLS Enabled? */
250 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
251 /* Engage TLS! Full Speed Ahead! */
252 if (!bnet_tls_client(client->tls_ctx, fd, client->tls_allowed_cns)) {
253 stop_bsock_timer(tid);
254 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with FD at \"%s:%d\".\n"),
255 fd->host(), fd->port());
258 if (client->tls_authenticate) { /* tls authentication only? */
259 fd->free_tls(); /* yes, shutdown tls */
263 Dmsg1(116, ">filed: %s", fd->msg);
264 if (fd->recv() <= 0) {
265 stop_bsock_timer(tid);
266 Dmsg1(dbglvl, _("Bad response from File daemon to Hello command: ERR=%s\n"),
268 Jmsg(jcr, M_FATAL, 0, _("Bad response from File daemon at \"%s:%d\" to Hello command: ERR=%s\n"),
269 fd->host(), fd->port(), fd->bstrerror());
272 Dmsg1(110, "<filed: %s", fd->msg);
273 stop_bsock_timer(tid);
275 if (strncmp(fd->msg, FDOKhello, sizeof(FDOKhello)) != 0 &&
276 sscanf(fd->msg, FDOKnewHello, &jcr->FDVersion) != 1) {
277 Dmsg0(dbglvl, _("File daemon rejected Hello command\n"));
278 Jmsg(jcr, M_FATAL, 0, _("File daemon at \"%s:%d\" rejected Hello command\n"),
279 fd->host(), fd->port());
285 /*********************************************************************
288 int authenticate_user_agent(UAContext *uac)
290 char name[MAX_NAME_LENGTH];
291 int tls_local_need = BNET_TLS_NONE;
292 int tls_remote_need = BNET_TLS_NONE;
294 bool tls_authenticate;
295 int compatible = true;
297 BSOCK *ua = uac->UA_sock;
298 bool auth_success = false;
299 TLS_CONTEXT *tls_ctx = NULL;
300 alist *verify_list = NULL;
302 if (ua->msglen < 16 || ua->msglen >= MAX_NAME_LENGTH + 15) {
303 Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Len=%d\n"), ua->who(),
304 ua->host(), ua->port(), ua->msglen);
308 if (sscanf(ua->msg, "Hello %127s calling\n", name) != 1) {
309 ua->msg[100] = 0; /* terminate string */
310 Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Got: %s\n"), ua->who(),
311 ua->host(), ua->port(), ua->msg);
315 name[sizeof(name)-1] = 0; /* terminate name */
316 if (strcmp(name, "*UserAgent*") == 0) { /* default console */
317 /* TLS Requirement */
318 if (director->tls_enable) {
319 if (director->tls_require) {
320 tls_local_need = BNET_TLS_REQUIRED;
322 tls_local_need = BNET_TLS_OK;
326 tls_authenticate = director->tls_authenticate;
327 need_tls = director->tls_enable || tls_authenticate;
329 if (tls_authenticate) {
330 tls_local_need = BNET_TLS_REQUIRED;
333 if (director->tls_verify_peer) {
334 verify_list = director->tls_allowed_cns;
337 auth_success = cram_md5_challenge(ua, director->password, tls_local_need,
339 cram_md5_respond(ua, director->password, &tls_remote_need, &compatible);
342 cons = (CONRES *)GetResWithName(R_CONSOLE, name);
344 /* TLS Requirement */
345 if (cons->tls_enable) {
346 if (cons->tls_require) {
347 tls_local_need = BNET_TLS_REQUIRED;
349 tls_local_need = BNET_TLS_OK;
353 tls_authenticate = cons->tls_authenticate;
354 need_tls = cons->tls_enable || tls_authenticate;
356 if (tls_authenticate) {
357 tls_local_need = BNET_TLS_REQUIRED;
360 if (cons->tls_verify_peer) {
361 verify_list = cons->tls_allowed_cns;
364 auth_success = cram_md5_challenge(ua, cons->password, tls_local_need,
366 cram_md5_respond(ua, cons->password, &tls_remote_need, &compatible);
369 uac->cons = cons; /* save console resource pointer */
372 auth_success = false;
378 /* Verify that the remote peer is willing to meet our TLS requirements */
379 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
380 Emsg0(M_FATAL, 0, _("Authorization problem:"
381 " Remote client did not advertise required TLS support.\n"));
382 auth_success = false;
386 /* Verify that we are willing to meet the peer's requirements */
387 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
388 Emsg0(M_FATAL, 0, _("Authorization problem:"
389 " Remote client requires TLS.\n"));
390 auth_success = false;
394 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
396 tls_ctx = cons->tls_ctx;
398 tls_ctx = director->tls_ctx;
401 /* Engage TLS! Full Speed Ahead! */
402 if (!bnet_tls_server(tls_ctx, ua, verify_list)) {
403 Emsg0(M_ERROR, 0, _("TLS negotiation failed.\n"));
404 auth_success = false;
407 if (tls_authenticate) { /* authentication only? */
408 ua->free_tls(); /* stop tls */
413 /* Authorization Completed */
416 ua->fsend("%s", _(Dir_sorry));
417 Emsg4(M_ERROR, 0, _("Unable to authenticate console \"%s\" at %s:%s:%d.\n"),
418 name, ua->who(), ua->host(), ua->port());
422 ua->fsend(_("1000 OK: %s Version: %s (%s)\n"), my_name, VERSION, BDATE);