blob: 64bcd490d4de513fe0858cf2787b3180981998fc [file] [log] [blame]
Ed Tanous7c8e0642022-02-21 12:11:14 -08001#pragma once
2
3#include "logging.hpp"
4#include "persistent_data.hpp"
5
6#include <openssl/crypto.h>
7#include <openssl/ssl.h>
8
9#include <boost/asio/ip/address.hpp>
10#include <boost/asio/ssl/verify_context.hpp>
11
12#include <memory>
Patrick Williams3d7fc712023-05-10 20:03:19 -050013#include <span>
Ed Tanous7c8e0642022-02-21 12:11:14 -080014
15inline std::shared_ptr<persistent_data::UserSession>
16 verifyMtlsUser(const boost::asio::ip::address& clientIp,
17 boost::asio::ssl::verify_context& ctx)
18{
19 // do nothing if TLS is disabled
20 if (!persistent_data::SessionStore::getInstance()
21 .getAuthMethodsConfig()
22 .tls)
23 {
Ed Tanous62598e32023-07-17 17:06:25 -070024 BMCWEB_LOG_DEBUG("TLS auth_config is disabled");
Ed Tanous7c8e0642022-02-21 12:11:14 -080025 return nullptr;
26 }
27
28 X509_STORE_CTX* cts = ctx.native_handle();
29 if (cts == nullptr)
30 {
Ed Tanous62598e32023-07-17 17:06:25 -070031 BMCWEB_LOG_DEBUG("Cannot get native TLS handle.");
Ed Tanous7c8e0642022-02-21 12:11:14 -080032 return nullptr;
33 }
34
35 // Get certificate
36 X509* peerCert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
37 if (peerCert == nullptr)
38 {
Ed Tanous62598e32023-07-17 17:06:25 -070039 BMCWEB_LOG_DEBUG("Cannot get current TLS certificate.");
Ed Tanous7c8e0642022-02-21 12:11:14 -080040 return nullptr;
41 }
42
43 // Check if certificate is OK
44 int ctxError = X509_STORE_CTX_get_error(cts);
45 if (ctxError != X509_V_OK)
46 {
Ed Tanous62598e32023-07-17 17:06:25 -070047 BMCWEB_LOG_INFO("Last TLS error is: {}", ctxError);
Ed Tanous7c8e0642022-02-21 12:11:14 -080048 return nullptr;
49 }
Ed Tanous23f1c962023-12-05 15:57:46 -080050
Ed Tanous7c8e0642022-02-21 12:11:14 -080051 // Check that we have reached final certificate in chain
52 int32_t depth = X509_STORE_CTX_get_error_depth(cts);
53 if (depth != 0)
Ed Tanous7c8e0642022-02-21 12:11:14 -080054 {
Ed Tanous62598e32023-07-17 17:06:25 -070055 BMCWEB_LOG_DEBUG(
56 "Certificate verification in progress (depth {}), waiting to reach final depth",
57 depth);
Ed Tanous7c8e0642022-02-21 12:11:14 -080058 return nullptr;
59 }
60
Ed Tanous62598e32023-07-17 17:06:25 -070061 BMCWEB_LOG_DEBUG("Certificate verification of final depth");
Ed Tanous7c8e0642022-02-21 12:11:14 -080062
Ed Tanous23f1c962023-12-05 15:57:46 -080063 if (X509_check_purpose(peerCert, X509_PURPOSE_SSL_CLIENT, 0) != 1)
Ed Tanous7c8e0642022-02-21 12:11:14 -080064 {
Ed Tanous23f1c962023-12-05 15:57:46 -080065 BMCWEB_LOG_DEBUG(
66 "Chain does not allow certificate to be used for SSL client authentication");
Ed Tanous7c8e0642022-02-21 12:11:14 -080067 return nullptr;
68 }
69
Ed Tanous7c8e0642022-02-21 12:11:14 -080070 std::string sslUser;
71 // Extract username contained in CommonName
72 sslUser.resize(256, '\0');
73
74 int status = X509_NAME_get_text_by_NID(X509_get_subject_name(peerCert),
75 NID_commonName, sslUser.data(),
76 static_cast<int>(sslUser.size()));
77
78 if (status == -1)
79 {
Ed Tanous62598e32023-07-17 17:06:25 -070080 BMCWEB_LOG_DEBUG("TLS cannot get username to create session");
Ed Tanous7c8e0642022-02-21 12:11:14 -080081 return nullptr;
82 }
83
84 size_t lastChar = sslUser.find('\0');
85 if (lastChar == std::string::npos || lastChar == 0)
86 {
Ed Tanous62598e32023-07-17 17:06:25 -070087 BMCWEB_LOG_DEBUG("Invalid TLS user name");
Ed Tanous7c8e0642022-02-21 12:11:14 -080088 return nullptr;
89 }
90 sslUser.resize(lastChar);
91 std::string unsupportedClientId;
92 return persistent_data::SessionStore::getInstance().generateUserSession(
93 sslUser, clientIp, unsupportedClientId,
94 persistent_data::PersistenceType::TIMEOUT);
95}