1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3 #pragma once
4
5 #include "logging.hpp"
6
7 #include <cstddef>
8 #include <format>
9 #include <optional>
10 #include <string>
11 #include <string_view>
12
mtlsMetaParseSslUser(std::string_view sslUser)13 inline std::optional<std::string_view> mtlsMetaParseSslUser(
14 std::string_view sslUser)
15 {
16 // Parses a Meta internal TLS client certificate Subject CN in
17 // '<entityType>:<entity>[/<hostname>]' format and returns the resulting
18 // POSIX-compatible local user name on success, null otherwise.
19 //
20 // Only entityType = "user" is supported for now.
21 //
22 // Example client subject CN -> local user name:
23 // "user:a_username/hostname" -> "a_username"
24
25 // Parse entityType
26 size_t colonIndex = sslUser.find(':');
27 if (colonIndex == std::string_view::npos)
28 {
29 BMCWEB_LOG_WARNING("Invalid Meta TLS client cert Subject CN: '{}'",
30 sslUser);
31 return std::nullopt;
32 }
33
34 std::string_view entityType = sslUser.substr(0, colonIndex);
35 sslUser.remove_prefix(colonIndex + 1);
36 if (entityType != "user")
37 {
38 BMCWEB_LOG_WARNING(
39 "Invalid/unsupported entityType='{}' in Meta TLS client cert Subject CN: '{}'",
40 entityType, sslUser);
41 return std::nullopt;
42 }
43
44 // Parse entity
45 size_t slashIndex = sslUser.find('/');
46 std::string_view entity;
47 if (slashIndex == std::string_view::npos)
48 {
49 // No '/' character, Subject CN is just '<entityType>:<entity>'
50 entity = sslUser;
51 }
52 else
53 {
54 // Subject CN ends with /<hostname>
55 entity = sslUser.substr(0, slashIndex);
56 sslUser.remove_prefix(slashIndex + 1);
57
58 if (entity.find_first_not_of(
59 "abcdefghijklmnopqrstuvwxyz0123456789_-.") != std::string::npos)
60 {
61 BMCWEB_LOG_WARNING(
62 "Invalid entity='{}' in Meta TLS client cert Subject CN: '{}'",
63 entity, sslUser);
64 return std::nullopt;
65 }
66 }
67
68 if (entity.empty())
69 {
70 BMCWEB_LOG_DEBUG("Invalid Meta TLS client cert Subject CN: '{}'",
71 sslUser);
72 return std::nullopt;
73 }
74
75 return entity;
76 }
77