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