diff options
author | Zbigniew Kurzynski <zbigniew.kurzynski@intel.com> | 2019-11-14 13:37:15 +0100 |
---|---|---|
committer | Zbigniew Kurzynski <zbigniew.kurzynski@intel.com> | 2019-12-16 08:07:09 +0000 |
commit | 009c2a4d7ba310789487910cc06cb19c745c1c97 (patch) | |
tree | 073259a9b54beaf1edc7596db9e3462507e6cb18 | |
parent | 97d57aaa0b95a110c71016d190f95f853051126a (diff) | |
download | bmcweb-009c2a4d7ba310789487910cc06cb19c745c1c97.tar.gz bmcweb-009c2a4d7ba310789487910cc06cb19c745c1c97.zip |
Fixing mTLS switches
This commit is a fix for revert:
https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/27205
The mTLS will work only when:
* Compilation flag BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION is
enabled and,
* AccountService->Oem->OpenBMC->AuthMethods->TLS is set and,
* at least one certificate is uploaded to TrustStore.
To enforce a new mTLS settings after switching AuthMethods->TLS
all awaiting for acceptance connections are dropped.
In case of authorized mTLS requests a cookie with XSRF-TOKEN entry
and SESSION is added to response. It will force the X-XSRF-TOKEN
challenge in case of applications supporting cookies like web
browsers.
Also some minor log messages changes were made in this commit.
Tested:
validator_service run with status: 'Validation has succeeded'.
Tests were made with Chrome browser Version 78.0.3904.108.
The certificate popup appears only when mTLS is enabled in CMake,
the TLS option is set and at least one CA certificate is present.
In other cases mTLS is not active and there is no popup for certs.
Signed-off-by: Zbigniew Kurzynski <zbigniew.kurzynski@intel.com>
Change-Id: I778b848b767356b60386694f802a89b3c1f6cb14
-rw-r--r-- | http/http_connection.h | 61 | ||||
-rw-r--r-- | include/sessions.hpp | 7 |
2 files changed, 63 insertions, 5 deletions
diff --git a/http/http_connection.h b/http/http_connection.h index e64e76c..0b15616 100644 --- a/http/http_connection.h +++ b/http/http_connection.h @@ -265,6 +265,20 @@ class Connection req.emplace(parser->get()); #ifdef BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION + auto ca_available = !std::filesystem::is_empty( + std::filesystem::path(ensuressl::trustStorePath)); + if (ca_available && crow::persistent_data::SessionStore::getInstance() + .getAuthMethodsConfig() + .tls) + { + adaptor.set_verify_mode(boost::asio::ssl::verify_peer); + SSL_set_session_id_context( + adaptor.native_handle(), + reinterpret_cast<const unsigned char*>(serverName.c_str()), + serverName.length()); + BMCWEB_LOG_DEBUG << this << " TLS is enabled on this connection."; + } + adaptor.set_verify_callback([this]( bool preverified, boost::asio::ssl::verify_context& ctx) { @@ -280,12 +294,14 @@ class Connection // We always return true to allow full auth flow if (!preverified) { + BMCWEB_LOG_DEBUG << this << " TLS preverification failed."; return true; } X509_STORE_CTX* cts = ctx.native_handle(); if (cts == nullptr) { + BMCWEB_LOG_DEBUG << this << " Cannot get native TLS handle."; return true; } @@ -294,6 +310,8 @@ class Connection X509_STORE_CTX_get_current_cert(ctx.native_handle()); if (peerCert == nullptr) { + BMCWEB_LOG_DEBUG << this + << " Cannot get current TLS certificate."; return true; } @@ -301,6 +319,7 @@ class Connection int error = X509_STORE_CTX_get_error(cts); if (error != X509_V_OK) { + BMCWEB_LOG_INFO << this << " Last TLS error is: " << error; return true; } // Check that we have reached final certificate in chain @@ -326,6 +345,7 @@ class Connection if (usage == nullptr) { + BMCWEB_LOG_DEBUG << this << " TLS usage is null"; return true; } @@ -357,6 +377,7 @@ class Connection if (extUsage == nullptr) { + BMCWEB_LOG_DEBUG << this << " TLS extUsage is null"; return true; } @@ -390,12 +411,15 @@ class Connection if (status == -1) { + BMCWEB_LOG_DEBUG + << this << " TLS cannot get username to create session"; return true; } size_t lastChar = sslUser.find('\0'); if (lastChar == std::string::npos || lastChar == 0) { + BMCWEB_LOG_DEBUG << this << " Invalid TLS user name"; return true; } sslUser.resize(lastChar); @@ -404,7 +428,11 @@ class Connection .generateUserSession( sslUser, crow::persistent_data::PersistenceType::TIMEOUT); - + if (auto sp = session.lock()) + { + BMCWEB_LOG_DEBUG << this + << " Generating TLS session: " << sp->uniqueId; + } return true; }); #endif // BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION @@ -494,9 +522,31 @@ class Connection #ifdef BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION if (auto sp = session.lock()) { - BMCWEB_LOG_DEBUG << "TLS session: " << sp->uniqueId - << " will be used for this request."; - req->session = sp; + // set cookie only if this is req from the browser. + if (req->getHeaderValue("User-Agent").empty()) + { + BMCWEB_LOG_DEBUG << this << " TLS session: " << sp->uniqueId + << " will be used for this request."; + req->session = sp; + } + else + { + std::string_view cookieValue = + req->getHeaderValue("Cookie"); + if (cookieValue.empty() || + cookieValue.find("SESSION=") == std::string::npos) + { + res.addHeader("Set-Cookie", + "XSRF-TOKEN=" + sp->csrfToken + + "; Secure\r\nSet-Cookie: SESSION=" + + sp->sessionToken + + "; Secure; HttpOnly"); + BMCWEB_LOG_DEBUG + << this << " TLS session: " << sp->uniqueId + << " with cookie will be used for this request."; + req->session = sp; + } + } } #endif // BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION @@ -555,7 +605,8 @@ class Connection #ifdef BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION if (auto sp = session.lock()) { - BMCWEB_LOG_DEBUG << "Removing TLS session: " << sp->uniqueId; + BMCWEB_LOG_DEBUG << this + << " Removing TLS session: " << sp->uniqueId; persistent_data::SessionStore::getInstance().removeSession(sp); } #endif // BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION diff --git a/include/sessions.hpp b/include/sessions.hpp index 6e74f25..f461521 100644 --- a/include/sessions.hpp +++ b/include/sessions.hpp @@ -4,6 +4,7 @@ #include <boost/uuid/uuid.hpp> #include <boost/uuid/uuid_generators.hpp> #include <boost/uuid/uuid_io.hpp> +#include <csignal> #include <dbus_singleton.hpp> #include <nlohmann/json.hpp> #include <pam_authenticate.hpp> @@ -496,8 +497,14 @@ class SessionStore void updateAuthMethodsConfig(const AuthConfigMethods& config) { + bool isTLSchanged = (authMethodsConfig.tls != config.tls); authMethodsConfig = config; needWrite = true; + if (isTLSchanged) + { + // recreate socket connections with new settings + std::raise(SIGHUP); + } } AuthConfigMethods& getAuthMethodsConfig() |