1724985ffSEd Tanous #include "mutual_tls.hpp" 2724985ffSEd Tanous 3724985ffSEd Tanous extern "C" 4724985ffSEd Tanous { 5724985ffSEd Tanous #include <openssl/x509_vfy.h> 6724985ffSEd Tanous } 7724985ffSEd Tanous 8724985ffSEd Tanous #include "logging.hpp" 9724985ffSEd Tanous #include "mutual_tls_meta.hpp" 10724985ffSEd Tanous #include "persistent_data.hpp" 11724985ffSEd Tanous 12724985ffSEd Tanous #include <boost/asio/ip/address.hpp> 13724985ffSEd Tanous #include <boost/asio/ssl/verify_context.hpp> 14724985ffSEd Tanous 15724985ffSEd Tanous #include <memory> 16724985ffSEd Tanous #include <string_view> 17724985ffSEd Tanous 18724985ffSEd Tanous std::string getUsernameFromCommonName(std::string_view commonName) 19724985ffSEd Tanous { 20724985ffSEd Tanous const persistent_data::AuthConfigMethods& authMethodsConfig = 21724985ffSEd Tanous persistent_data::SessionStore::getInstance().getAuthMethodsConfig(); 22724985ffSEd Tanous switch (authMethodsConfig.mTLSCommonNameParsingMode) 23724985ffSEd Tanous { 24724985ffSEd Tanous case persistent_data::MTLSCommonNameParseMode::Invalid: 25724985ffSEd Tanous case persistent_data::MTLSCommonNameParseMode::Whole: 26724985ffSEd Tanous case persistent_data::MTLSCommonNameParseMode::UserPrincipalName: 27724985ffSEd Tanous { 28724985ffSEd Tanous // Not yet supported 29724985ffSEd Tanous return ""; 30724985ffSEd Tanous } 31724985ffSEd Tanous case persistent_data::MTLSCommonNameParseMode::CommonName: 32724985ffSEd Tanous { 33724985ffSEd Tanous return std::string{commonName}; 34724985ffSEd Tanous } 35724985ffSEd Tanous case persistent_data::MTLSCommonNameParseMode::Meta: 36724985ffSEd Tanous { 37724985ffSEd Tanous // Meta Inc. CommonName parsing 38724985ffSEd Tanous std::optional<std::string_view> sslUserMeta = 39724985ffSEd Tanous mtlsMetaParseSslUser(commonName); 40724985ffSEd Tanous if (!sslUserMeta) 41724985ffSEd Tanous { 42724985ffSEd Tanous return ""; 43724985ffSEd Tanous } 44724985ffSEd Tanous return std::string{*sslUserMeta}; 45724985ffSEd Tanous } 464f467963SEd Tanous default: 474f467963SEd Tanous { 48724985ffSEd Tanous return ""; 49724985ffSEd Tanous } 504f467963SEd Tanous } 514f467963SEd Tanous } 52724985ffSEd Tanous 53724985ffSEd Tanous std::shared_ptr<persistent_data::UserSession> 54724985ffSEd Tanous verifyMtlsUser(const boost::asio::ip::address& clientIp, 55724985ffSEd Tanous boost::asio::ssl::verify_context& ctx) 56724985ffSEd Tanous { 57724985ffSEd Tanous // do nothing if TLS is disabled 58724985ffSEd Tanous if (!persistent_data::SessionStore::getInstance() 59724985ffSEd Tanous .getAuthMethodsConfig() 60724985ffSEd Tanous .tls) 61724985ffSEd Tanous { 62724985ffSEd Tanous BMCWEB_LOG_DEBUG("TLS auth_config is disabled"); 63724985ffSEd Tanous return nullptr; 64724985ffSEd Tanous } 65724985ffSEd Tanous 66724985ffSEd Tanous X509_STORE_CTX* cts = ctx.native_handle(); 67724985ffSEd Tanous if (cts == nullptr) 68724985ffSEd Tanous { 69724985ffSEd Tanous BMCWEB_LOG_DEBUG("Cannot get native TLS handle."); 70724985ffSEd Tanous return nullptr; 71724985ffSEd Tanous } 72724985ffSEd Tanous 73724985ffSEd Tanous // Get certificate 74724985ffSEd Tanous X509* peerCert = X509_STORE_CTX_get_current_cert(ctx.native_handle()); 75724985ffSEd Tanous if (peerCert == nullptr) 76724985ffSEd Tanous { 77724985ffSEd Tanous BMCWEB_LOG_DEBUG("Cannot get current TLS certificate."); 78724985ffSEd Tanous return nullptr; 79724985ffSEd Tanous } 80724985ffSEd Tanous 81724985ffSEd Tanous // Check if certificate is OK 82724985ffSEd Tanous int ctxError = X509_STORE_CTX_get_error(cts); 83724985ffSEd Tanous if (ctxError != X509_V_OK) 84724985ffSEd Tanous { 85724985ffSEd Tanous BMCWEB_LOG_INFO("Last TLS error is: {}", ctxError); 86724985ffSEd Tanous return nullptr; 87724985ffSEd Tanous } 88724985ffSEd Tanous 89724985ffSEd Tanous // Check that we have reached final certificate in chain 90724985ffSEd Tanous int32_t depth = X509_STORE_CTX_get_error_depth(cts); 91724985ffSEd Tanous if (depth != 0) 92724985ffSEd Tanous { 93724985ffSEd Tanous BMCWEB_LOG_DEBUG( 94724985ffSEd Tanous "Certificate verification in progress (depth {}), waiting to reach final depth", 95724985ffSEd Tanous depth); 96724985ffSEd Tanous return nullptr; 97724985ffSEd Tanous } 98724985ffSEd Tanous 99724985ffSEd Tanous BMCWEB_LOG_DEBUG("Certificate verification of final depth"); 100724985ffSEd Tanous 101724985ffSEd Tanous if (X509_check_purpose(peerCert, X509_PURPOSE_SSL_CLIENT, 0) != 1) 102724985ffSEd Tanous { 103724985ffSEd Tanous BMCWEB_LOG_DEBUG( 104724985ffSEd Tanous "Chain does not allow certificate to be used for SSL client authentication"); 105724985ffSEd Tanous return nullptr; 106724985ffSEd Tanous } 107724985ffSEd Tanous 108724985ffSEd Tanous std::string commonName; 109724985ffSEd Tanous // Extract username contained in CommonName 110724985ffSEd Tanous commonName.resize(256, '\0'); 111724985ffSEd Tanous 112*bd79bce8SPatrick Williams int length = X509_NAME_get_text_by_NID( 113*bd79bce8SPatrick Williams X509_get_subject_name(peerCert), NID_commonName, commonName.data(), 114724985ffSEd Tanous static_cast<int>(commonName.size())); 115724985ffSEd Tanous if (length <= 0) 116724985ffSEd Tanous { 117724985ffSEd Tanous BMCWEB_LOG_DEBUG("TLS cannot get common name to create session"); 118724985ffSEd Tanous return nullptr; 119724985ffSEd Tanous } 120724985ffSEd Tanous 121724985ffSEd Tanous commonName.resize(static_cast<size_t>(length)); 122724985ffSEd Tanous std::string sslUser = getUsernameFromCommonName(commonName); 123724985ffSEd Tanous if (sslUser.empty()) 124724985ffSEd Tanous { 125724985ffSEd Tanous BMCWEB_LOG_WARNING("Failed to get user from common name {}", 126724985ffSEd Tanous commonName); 127724985ffSEd Tanous return nullptr; 128724985ffSEd Tanous } 129724985ffSEd Tanous 130724985ffSEd Tanous std::string unsupportedClientId; 131724985ffSEd Tanous return persistent_data::SessionStore::getInstance().generateUserSession( 132724985ffSEd Tanous sslUser, clientIp, unsupportedClientId, 133724985ffSEd Tanous persistent_data::SessionType::MutualTLS); 134724985ffSEd Tanous } 135