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
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 @@
         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 @@
             // 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 @@
                 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 @@
             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 @@
 
             if (usage == nullptr)
             {
+                BMCWEB_LOG_DEBUG << this << " TLS usage is null";
                 return true;
             }
 
@@ -357,6 +377,7 @@
 
             if (extUsage == nullptr)
             {
+                BMCWEB_LOG_DEBUG << this << " TLS extUsage is null";
                 return true;
             }
 
@@ -390,12 +411,15 @@
 
             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 @@
                           .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 @@
 #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 @@
 #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