From: Alain Spineux Date: Tue, 12 May 2020 20:37:14 +0000 (+0200) Subject: BEE Backport bacula/src/console/authenticate.c X-Git-Tag: Release-11.3.2~1592 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ea184c4a2eb28f55a7a4b1999bfd357489239d74;p=thirdparty%2Fbacula.git BEE Backport bacula/src/console/authenticate.c This commit is the result of the squash of the following main commits: Author: Eric Bollengier Date: Wed Mar 11 12:13:09 2020 +0100 Fix TLS/PSK requierement checks Author: Alain Spineux Date: Tue Apr 23 16:46:55 2019 +0200 PSK: make AuthenticateBase::CheckTLSRequirement() virtual - move the CheckTLSRequirement() aka "error handling" to the sub-class - cleanup a bit the not needed anymore "helper" Author: Alain Spineux Date: Mon Apr 8 14:56:45 2019 +0200 PSK: Modify authentication in each daemon to support PSK - use AuthenticateBase class Author: Alain Spineux Date: Thu Apr 19 17:33:55 2018 +0200 fix #3694 bconsole show message when MaximumConsoleConnections limit is reached - When the director reach the MaximumConsoleConnections limit, it queues the new bconsole connections until one bconsole disconnect. - Now, when bconsole timeout, it display an appropriate message - The time out entries in the queues look to be cleaned up in < 30s Author: Kern Sibbald Date: Wed May 17 13:57:59 2017 +0200 Add community daemon versions Author: Eric Bollengier Date: Mon Feb 29 16:12:21 2016 +0100 Allow bconsole to connect to FD Author: Kern Sibbald Date: Mon Oct 21 15:41:49 2013 +0200 Add code to turn off comm line compression --- diff --git a/bacula/src/console/authenticate.c b/bacula/src/console/authenticate.c index 5405220191..9331cd2de3 100644 --- a/bacula/src/console/authenticate.c +++ b/bacula/src/console/authenticate.c @@ -1,7 +1,7 @@ /* Bacula(R) - The Network Backup Solution - Copyright (C) 2000-2017 Kern Sibbald + Copyright (C) 2000-2020 Kern Sibbald The original author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -11,7 +11,7 @@ Public License, v3.0 ("AGPLv3") and some additional permissions and terms pursuant to its AGPLv3 Section 7. - This notice must be preserved when any source code is + This notice must be preserved when any source code is conveyed and/or propagated. Bacula(R) is a registered trademark of Kern Sibbald. @@ -40,111 +40,106 @@ * prior to 06Aug13 no version * 100 14Feb17 - added comm line compression */ -#define UA_VERSION 100 +#ifndef COMMUNITY +#define UA_VERSION 1 /* Enterprise */ +#else +#define UA_VERSION 100 /* Community */ +#endif void senditf(const char *fmt, ...); void sendit(const char *buf); /* Commands sent to Director */ -static char hello[] = "Hello %s calling %d\n"; +static char hello[] = "Hello %s calling %d tlspsk=%d\n"; /* Response from Director */ static char oldOKhello[] = "1000 OK:"; static char newOKhello[] = "1000 OK: %d"; -static char FDOKhello[] = "2000 OK Hello %d"; +static char FDOKhello[] = "2000 OK Hello %d"; -/* Forward referenced functions */ +class ConsoleAuthenticate: public AuthenticateBase +{ +public: + ConsoleAuthenticate(BSOCK *dir): + AuthenticateBase(NULL, dir, dtCli, dcCON, dcDIR) + { + } + virtual ~ConsoleAuthenticate() {}; + virtual void TLSFailure() { sendit(_("TLS negotiation failed\n")); } + virtual bool CheckTLSRequirement(); + + int authenticate_director(DIRRES *director, CONRES *cons); +}; + + +int authenticate_director(BSOCK *dir, DIRRES *director, CONRES *cons) +{ + ConsoleAuthenticate auth(dir); + return auth.authenticate_director(director, cons); +} + +bool ConsoleAuthenticate::CheckTLSRequirement() +{ + /* Verify that the connection is willing to meet our TLS requirements */ + switch (TestTLSRequirement()) { + case TLS_REQ_ERR_LOCAL: + sendit(_("Authorization problem:" + " Remote server requires TLS.\n")); + return false; + + case TLS_REQ_ERR_REMOTE: + sendit(_("Authorization problem:" + " Remote server did not advertise required TLS support.\n")); + return false; + case TLS_REQ_OK: + break; + } + return true; +} /* * Authenticate Director */ -int authenticate_director(BSOCK *dir, DIRRES *director, CONRES *cons) +int ConsoleAuthenticate::authenticate_director(DIRRES *director, CONRES *cons) { - int tls_local_need = BNET_TLS_NONE; - int tls_remote_need = BNET_TLS_NONE; - bool tls_authenticate; - int compatible = true; + BSOCK *dir = bsock; int dir_version = 0; - int fd_version = 0; char bashed_name[MAX_NAME_LENGTH]; - char *password; - TLS_CONTEXT *tls_ctx = NULL; - + bool skip_msg = false; /* * Send my name to the Director then do authentication */ if (cons) { bstrncpy(bashed_name, cons->hdr.name, sizeof(bashed_name)); bash_spaces(bashed_name); - password = cons->password; - /* TLS Requirement */ - if (cons->tls_enable) { - if (cons->tls_require) { - tls_local_need = BNET_TLS_REQUIRED; - } else { - tls_local_need = BNET_TLS_OK; - } - } - if (cons->tls_authenticate) { - tls_local_need = BNET_TLS_REQUIRED; - } - tls_authenticate = cons->tls_authenticate; - tls_ctx = cons->tls_ctx; + CalcLocalTLSNeedFromRes(cons->tls_enable, cons->tls_require, + cons->tls_authenticate, false, NULL, cons->tls_ctx, + cons->tls_psk_enable, cons->psk_ctx, cons->password); + } else { bstrncpy(bashed_name, "*UserAgent*", sizeof(bashed_name)); - password = director->password; - /* TLS Requirement */ - if (director->tls_enable) { - if (director->tls_require) { - tls_local_need = BNET_TLS_REQUIRED; - } else { - tls_local_need = BNET_TLS_OK; - } - } - - if (director->tls_authenticate) { - tls_local_need = BNET_TLS_REQUIRED; - } - tls_authenticate = director->tls_authenticate; - tls_ctx = director->tls_ctx; + CalcLocalTLSNeedFromRes(director->tls_enable, director->tls_require, + director->tls_authenticate, false, NULL, director->tls_ctx, + director->tls_psk_enable, director->psk_ctx, director->password); } - /* Timeout Hello after 15 secs */ - btimer_t *tid = start_bsock_timer(dir, 15); - dir->fsend(hello, bashed_name, UA_VERSION); + StartAuthTimeout(15); - if (!cram_md5_respond(dir, password, &tls_remote_need, &compatible) || - !cram_md5_challenge(dir, password, tls_local_need, compatible)) { - goto bail_out; - } + dir->fsend(hello, bashed_name, UA_VERSION, tlspsk_local_need); - /* Verify that the remote host is willing to meet our TLS requirements */ - if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) { - sendit(_("Authorization problem:" - " Remote server did not advertise required TLS support.\n")); + if (!ClientCramMD5Authenticate(password)) { + if (dir->is_timed_out()) { + sendit(_("The Director is busy or the MaximumConsoleConnections limit is reached.\n")); + skip_msg = true; + } goto bail_out; } - /* Verify that we are willing to meet the remote host's requirements */ - if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) { - sendit(_("Authorization problem:" - " Remote server requires TLS.\n")); + if (!HandleTLS()) { goto bail_out; } - /* Is TLS Enabled? */ - if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { - /* Engage TLS! Full Speed Ahead! */ - if (!bnet_tls_client(tls_ctx, dir, NULL)) { - sendit(_("TLS negotiation failed\n")); - goto bail_out; - } - if (tls_authenticate) { /* Authenticate only? */ - dir->free_tls(); /* yes, shutdown tls */ - } - } - /* * It's possible that the TLS connection will * be dropped here if an invalid client certificate was presented @@ -161,28 +156,30 @@ int authenticate_director(BSOCK *dir, DIRRES *director, CONRES *cons) /* If Dir version exists, get it */ sscanf(dir->msg, newOKhello, &dir_version); sendit(dir->msg); - /* Check for hello from FD */ - } else if (sscanf(dir->msg, FDOKhello, &fd_version) == 1) { + + /* We do not check the last %d */ + } else if (strncmp(dir->msg, FDOKhello, sizeof(FDOKhello)-3) == 0) { + sscanf(dir->msg, FDOKhello, &dir_version); sendit(dir->msg); + } else { sendit(_("Director rejected Hello command\n")); goto bail_out; } /* Turn on compression for newer Directors */ - if (dir_version >= 103 && (!cons || cons->comm_compression)) { + if (dir_version >= 1 && (!cons || cons->comm_compression)) { dir->set_compress(); } else { dir->clear_compress(); } - /* ***FIXME*** should turn on compression for FD if possible */ - stop_bsock_timer(tid); return 1; bail_out: - stop_bsock_timer(tid); - sendit( _("Director authorization problem.\n" + if (!skip_msg) { + sendit( _("Director authorization problem.\n" "Most likely the passwords do not agree.\n" "If you are using TLS, there may have been a certificate validation error during the TLS handshake.\n" "For help, please see " MANUAL_AUTH_URL "\n")); + } return 0; }