xref: /openbmc/bmcweb/http/mutual_tls_meta.hpp (revision 504af5a0568171b72caf13234cc81380b261fa21)
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