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