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