From: Alain Spineux Date: Tue, 12 May 2020 16:37:15 +0000 (+0200) Subject: BEE Backport bacula/src/stored/authenticate.c X-Git-Tag: Release-11.3.2~1679 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f0795b245114fdc7c9cc0129ffd2609a79a0d665;p=thirdparty%2Fbacula.git BEE Backport bacula/src/stored/authenticate.c This commit is the result of the squash of the following main commits: Author: Alain Spineux Date: Fri Apr 12 04:55:10 2019 +0200 PSK: encrypt copy jobs (SD-SD ) 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: Eric Bollengier Date: Thu Mar 12 10:01:54 2015 +0100 Ensure that only one thread can use the auth code in the Storage Author: Kern Sibbald Date: Fri Jun 20 21:32:36 2014 +0200 Refactor the SD Hello code to put it all in hello.c --- diff --git a/bacula/src/stored/authenticate.c b/bacula/src/stored/authenticate.c index f2aace5ebd..83eb1b4182 100644 --- a/bacula/src/stored/authenticate.c +++ b/bacula/src/stored/authenticate.c @@ -20,6 +20,7 @@ * Authenticate caller * * Written by Kern Sibbald, October 2000 + * */ @@ -32,194 +33,83 @@ const int dbglvl = 50; static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -/* Version at end of Hello - * prior to 06Aug13 no version - * 1 06Aug13 - added comm line compression - * 2 13Dec13 - added api version to status command - */ -#define SD_VERSION 2 - +SDAuthenticateDIR::SDAuthenticateDIR(JCR *jcr): +AuthenticateBase(jcr, jcr->dir_bsock, dtSrv, dcSD, dcDIR) +{ +} /* * Authenticate the Director */ -bool authenticate_director(JCR* jcr) +bool SDAuthenticateDIR::authenticate_director() { - DIRRES *director = jcr->director; - int tls_local_need = BNET_TLS_NONE; - int tls_remote_need = BNET_TLS_NONE; - int compatible = true; /* require md5 compatible DIR */ - bool auth_success = false; - alist *verify_list = NULL; BSOCK *dir = jcr->dir_bsock; + DIRRES *director = jcr->director; - /* 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; - } + DecodeRemoteTLSPSKNeed(bsock->tlspsk_remote); - if (director->tls_verify_peer) { - verify_list = director->tls_allowed_cns; - } + /* TLS Requirement */ + CalcLocalTLSNeedFromRes(director->tls_enable, director->tls_require, + director->tls_authenticate, director->tls_verify_peer, + director->tls_allowed_cns, director->tls_ctx, + director->tls_psk_enable, director->psk_ctx, director->password); /* Timeout authentication after 10 mins */ - btimer_t *tid = start_bsock_timer(dir, AUTH_TIMEOUT); - auth_success = cram_md5_challenge(dir, director->password, tls_local_need, compatible); - if (auth_success) { - auth_success = cram_md5_respond(dir, director->password, &tls_remote_need, &compatible); - if (!auth_success) { - Dmsg1(dbglvl, "cram_get_auth respond failed with Director %s\n", dir->who()); - } - } else { - Dmsg1(dbglvl, "cram_auth challenge failed with Director %s\n", dir->who()); - } - - if (!auth_success) { - Jmsg0(jcr, M_FATAL, 0, _("Incorrect password given by Director.\n" - "For help, please see: " MANUAL_AUTH_URL "\n")); - auth_success = false; - goto auth_fatal; - } + StartAuthTimeout(); - /* 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) { - Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" - " advertize required TLS support.\n")); - Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); - auth_success = false; - goto auth_fatal; - } - - /* 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) { - Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n")); - Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); - auth_success = false; + /* Challenge the director */ + if (!ServerCramMD5Authenticate(password)) { goto auth_fatal; } - if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { - /* Engage TLS! Full Speed Ahead! */ - if (!bnet_tls_server(director->tls_ctx, dir, verify_list)) { - Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with DIR at \"%s:%d\"\n"), - dir->host(), dir->port()); - auth_success = false; - goto auth_fatal; - } - if (director->tls_authenticate) { /* authenticate with tls only? */ - dir->free_tls(); /* yes, shut it down */ - } - } + this->auth_success = HandleTLS(); auth_fatal: - stop_bsock_timer(tid); - jcr->director = director; if (auth_success) { return send_hello_ok(dir); } send_sorry(dir); - Dmsg1(dbglvl, "Unable to authenticate Director at %s.\n", dir->who()); - Jmsg1(jcr, M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who()); bmicrosleep(5, 0); return false; } - -int authenticate_filed(JCR *jcr, BSOCK *fd, int FDVersion) +class SDAuthenticateFD: public AuthenticateBase { - int tls_local_need = BNET_TLS_NONE; - int tls_remote_need = BNET_TLS_NONE; - int compatible = true; /* require md5 compatible FD */ - bool auth_success = false; - alist *verify_list = NULL; - - /* TLS Requirement */ - if (me->tls_enable) { - if (me->tls_require) { - tls_local_need = BNET_TLS_REQUIRED; - } else { - tls_local_need = BNET_TLS_OK; - } +public: + SDAuthenticateFD(JCR *jcr, BSOCK *bsock): + AuthenticateBase(jcr, bsock, dtSrv, dcSD, dcFD) + { } + virtual ~SDAuthenticateFD() {}; + int authenticate_filed(int FDVersion); +}; - if (me->tls_authenticate) { - tls_local_need = BNET_TLS_REQUIRED; - } - - if (me->tls_verify_peer) { - verify_list = me->tls_allowed_cns; - } +int authenticate_filed(JCR *jcr, BSOCK *fd, int FDVersion) +{ + return SDAuthenticateFD(jcr, fd).authenticate_filed(FDVersion); +} - /* Timeout authentication after 5 mins */ - btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT); - /* Challenge FD */ - Dmsg0(050, "Challenge FD\n"); - auth_success = cram_md5_challenge(fd, jcr->sd_auth_key, tls_local_need, compatible); - if (auth_success) { - /* Respond to his challenge */ - Dmsg0(050, "Respond to FD challenge\n"); - auth_success = cram_md5_respond(fd, jcr->sd_auth_key, &tls_remote_need, &compatible); - if (!auth_success) { - Dmsg1(dbglvl, "Respond cram-get-auth respond failed with FD: %s\n", fd->who()); - } - } else { - Dmsg1(dbglvl, "Challenge cram-auth failed with FD: %s\n", fd->who()); - } +int SDAuthenticateFD::authenticate_filed(int FDVersion) +{ + BSOCK *fd = bsock; - if (!auth_success) { - Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n" - "For help, please see: " MANUAL_AUTH_URL "\n"), - fd->who()); - auth_success = false; - goto auth_fatal; - } + DecodeRemoteTLSPSKNeed(bsock->tlspsk_remote); + /* TLS Requirement */ + CalcLocalTLSNeedFromRes(me->tls_enable, me->tls_require, me->tls_authenticate, + me->tls_verify_peer, me->tls_allowed_cns, me->tls_ctx, + me->tls_psk_enable, me->psk_ctx, jcr->sd_auth_key); - /* 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) { - Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" - " advertize required TLS support.\n")); - Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); - auth_success = false; - goto auth_fatal; - } + /* Timeout authentication after 10 mins */ + StartAuthTimeout(); - /* 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) { - Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n")); - Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); - auth_success = false; + /* Challenge the FD */ + if (!ServerCramMD5Authenticate(jcr->sd_auth_key)) { goto auth_fatal; } - if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { - /* Engage TLS! Full Speed Ahead! */ - if (!bnet_tls_server(me->tls_ctx, fd, verify_list)) { - Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with FD at \"%s:%d\"\n"), - fd->host(), fd->port()); - auth_success = false; - goto auth_fatal; - } - if (me->tls_authenticate) { /* tls authenticate only? */ - fd->free_tls(); /* yes, shut it down */ - } - } + this->auth_success = HandleTLS(); auth_fatal: - stop_bsock_timer(tid); - if (!auth_success) { - Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n" - "For help, please see: " MANUAL_AUTH_URL "\n"), - fd->who()); - } - /* Version 5 of the protocol is a bit special, it is used by both 6.0.0 * Enterprise version and 7.0.x Community version, but do not support the * same level of features. As nobody is using the 6.0.0 release, we can @@ -231,93 +121,54 @@ auth_fatal: return auth_success; } +class SDAuthenticateSD: public AuthenticateBase +{ +public: + SDAuthenticateSD(JCR *jcr): + AuthenticateBase(jcr, jcr->store_bsock, dtCli, dcSD, dcSD) { + /* TLS Requirement */ + CalcLocalTLSNeedFromRes(me->tls_enable, me->tls_require, me->tls_authenticate, + me->tls_verify_peer, me->tls_allowed_cns, me->tls_ctx, + me->tls_psk_enable, me->psk_ctx, jcr->sd_auth_key); + } + virtual ~SDAuthenticateSD() {}; + bool authenticate_storagedaemon(); +}; + + +bool send_hello_and_authenticate_sd(JCR *jcr, char *Job) +{ + SDAuthenticateSD auth(jcr); + /* TODO disable PSK/TLS when the SD talk to itself */ + if (!send_hello_sd(jcr, Job, auth.GetTLSPSKLocalNeed())) { + return false; + } + return auth.authenticate_storagedaemon(); +} + /* * First prove our identity to the Storage daemon, then * make him prove his identity. */ -bool authenticate_storagedaemon(JCR *jcr) +bool SDAuthenticateSD::authenticate_storagedaemon() { BSOCK *sd = jcr->store_bsock; - int tls_local_need = BNET_TLS_NONE; - int tls_remote_need = BNET_TLS_NONE; - int compatible = true; - bool auth_success = false; int sd_version = 0; - btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT); - - /* TLS Requirement */ - if (have_tls && me->tls_enable) { - if (me->tls_require) { - tls_local_need = BNET_TLS_REQUIRED; - } else { - tls_local_need = BNET_TLS_OK; - } - } - - if (me->tls_authenticate) { - tls_local_need = BNET_TLS_REQUIRED; - } + /* Timeout authentication after 10 mins */ + StartAuthTimeout(); - if (job_canceled(jcr)) { - auth_success = false; /* force quick exit */ + /* Challenge the FD */ + if (!ClientCramMD5Authenticate(jcr->sd_auth_key)) { goto auth_fatal; } - /* Respond to SD challenge */ - Dmsg0(050, "Respond to SD challenge\n"); - auth_success = cram_md5_respond(sd, jcr->sd_auth_key, &tls_remote_need, &compatible); - if (job_canceled(jcr)) { - auth_success = false; /* force quick exit */ - goto auth_fatal; - } - if (!auth_success) { - Dmsg1(dbglvl, "cram_respond failed for SD: %s\n", sd->who()); - } else { - /* Now challenge him */ - Dmsg0(050, "Challenge SD\n"); - auth_success = cram_md5_challenge(sd, jcr->sd_auth_key, tls_local_need, compatible); - if (!auth_success) { - Dmsg1(dbglvl, "cram_challenge failed for SD: %s\n", sd->who()); - } - } + this->auth_success = HandleTLS(); if (!auth_success) { - Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n" - "Please see " MANUAL_AUTH_URL " for help.\n")); - goto auth_fatal; - } else { - Dmsg0(050, "Authorization with SD is OK\n"); - } - - /* 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) { - Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" - " advertize required TLS support.\n")); - Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); - auth_success = false; goto auth_fatal; } - /* 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) { - Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n")); - Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need); - auth_success = false; - goto auth_fatal; - } - - if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) { - /* Engage TLS! Full Speed Ahead! */ - if (!bnet_tls_client(me->tls_ctx, sd, NULL)) { - Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n")); - auth_success = false; - goto auth_fatal; - } - if (me->tls_authenticate) { /* tls authentication only? */ - sd->free_tls(); /* yes, shutdown tls */ - } - } if (sd->recv() <= 0) { auth_success = false; goto auth_fatal; @@ -335,7 +186,6 @@ bool authenticate_storagedaemon(JCR *jcr) auth_fatal: /* Destroy session key */ memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key)); - stop_bsock_timer(tid); /* Single thread all failures to avoid DOS */ if (!auth_success) { P(mutex);