diff options
Diffstat (limited to 'http')
-rw-r--r-- | http/mutual_tls.hpp | 14 | ||||
-rw-r--r-- | http/mutual_tls_meta.hpp | 73 |
2 files changed, 87 insertions, 0 deletions
diff --git a/http/mutual_tls.hpp b/http/mutual_tls.hpp index 64bcd490d4..1620054e1c 100644 --- a/http/mutual_tls.hpp +++ b/http/mutual_tls.hpp @@ -1,6 +1,7 @@ #pragma once #include "logging.hpp" +#include "mutual_tls_meta.hpp" #include "persistent_data.hpp" #include <openssl/crypto.h> @@ -88,6 +89,19 @@ inline std::shared_ptr<persistent_data::UserSession> return nullptr; } sslUser.resize(lastChar); + + // Meta Inc. CommonName parsing + if (bmcwebMTLSCommonNameParsingMeta) + { + std::optional<std::string_view> sslUserMeta = + mtlsMetaParseSslUser(sslUser); + if (!sslUserMeta) + { + return nullptr; + } + sslUser = *sslUserMeta; + } + std::string unsupportedClientId; return persistent_data::SessionStore::getInstance().generateUserSession( sslUser, clientIp, unsupportedClientId, diff --git a/http/mutual_tls_meta.hpp b/http/mutual_tls_meta.hpp new file mode 100644 index 0000000000..5e55db8e28 --- /dev/null +++ b/http/mutual_tls_meta.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include "logging.hpp" + +#include <format> +#include <optional> +#include <string> +#include <string_view> + +inline std::optional<std::string_view> + mtlsMetaParseSslUser(std::string_view sslUser) +{ + // Parses a Meta internal TLS client certificate Subject CN in + // '<entityType>:<entity>[/<hostname>]' format and returns the resulting + // POSIX-compatible local user name on success, null otherwise. + // + // Only entityType = "user" is supported for now. + // + // Example client subject CN -> local user name: + // "user:a_username/hostname" -> "a_username" + + // Parse entityType + size_t colonIndex = sslUser.find(':'); + if (colonIndex == std::string_view::npos) + { + BMCWEB_LOG_WARNING("Invalid Meta TLS client cert Subject CN: '{}'", + sslUser); + return std::nullopt; + } + + std::string_view entityType = sslUser.substr(0, colonIndex); + sslUser.remove_prefix(colonIndex + 1); + if (entityType != "user") + { + BMCWEB_LOG_WARNING( + "Invalid/unsupported entityType='{}' in Meta TLS client cert Subject CN: '{}'", + entityType, sslUser); + return std::nullopt; + } + + // Parse entity + size_t slashIndex = sslUser.find('/'); + std::string_view entity; + if (slashIndex == std::string_view::npos) + { + // No '/' character, Subject CN is just '<entityType>:<entity>' + entity = sslUser; + } + else + { + // Subject CN ends with /<hostname> + entity = sslUser.substr(0, slashIndex); + sslUser.remove_prefix(slashIndex + 1); + + if (entity.find_first_not_of( + "abcdefghijklmnopqrstuvwxyz0123456789_-.") != std::string::npos) + { + BMCWEB_LOG_WARNING( + "Invalid entity='{}' in Meta TLS client cert Subject CN: '{}'", + entity, sslUser); + return std::nullopt; + } + } + + if (entity.empty()) + { + BMCWEB_LOG_DEBUG("Invalid Meta TLS client cert Subject CN: '{}'", + sslUser); + return std::nullopt; + } + + return entity; +} |