/*
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.
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.
* 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
/* 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;
}