summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZbigniew Kurzynski <zbigniew.kurzynski@intel.com>2019-11-14 13:37:15 +0100
committerZbigniew Kurzynski <zbigniew.kurzynski@intel.com>2019-12-16 08:07:09 +0000
commit009c2a4d7ba310789487910cc06cb19c745c1c97 (patch)
tree073259a9b54beaf1edc7596db9e3462507e6cb18
parent97d57aaa0b95a110c71016d190f95f853051126a (diff)
downloadbmcweb-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.h61
-rw-r--r--include/sessions.hpp7
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()
OpenPOWER on IntegriCloud