summaryrefslogtreecommitdiff
path: root/http/mutual_tls_meta.hpp
blob: 5e55db8e280d6d1cf60f9a3cb1e79d5ecf9656fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#pragma once

#include "logging.hpp"

#include <format>
#include <optional>
#include <string>
#include <string_view>

inline std::optional<std::string_view>
    mtlsMetaParseSslUser(std::string_view sslUser)
{
    // Parses a Meta internal TLS client certificate Subject CN in
    // '<entityType>:<entity>[/<hostname>]' format and returns the resulting
    // POSIX-compatible local user name on success, null otherwise.
    //
    // Only entityType = "user" is supported for now.
    //
    // Example client subject CN -> local user name:
    // "user:a_username/hostname" -> "a_username"

    // Parse entityType
    size_t colonIndex = sslUser.find(':');
    if (colonIndex == std::string_view::npos)
    {
        BMCWEB_LOG_WARNING("Invalid Meta TLS client cert Subject CN: '{}'",
                           sslUser);
        return std::nullopt;
    }

    std::string_view entityType = sslUser.substr(0, colonIndex);
    sslUser.remove_prefix(colonIndex + 1);
    if (entityType != "user")
    {
        BMCWEB_LOG_WARNING(
            "Invalid/unsupported entityType='{}' in Meta TLS client cert Subject CN: '{}'",
            entityType, sslUser);
        return std::nullopt;
    }

    // Parse entity
    size_t slashIndex = sslUser.find('/');
    std::string_view entity;
    if (slashIndex == std::string_view::npos)
    {
        // No '/' character, Subject CN is just '<entityType>:<entity>'
        entity = sslUser;
    }
    else
    {
        // Subject CN ends with /<hostname>
        entity = sslUser.substr(0, slashIndex);
        sslUser.remove_prefix(slashIndex + 1);

        if (entity.find_first_not_of(
                "abcdefghijklmnopqrstuvwxyz0123456789_-.") != std::string::npos)
        {
            BMCWEB_LOG_WARNING(
                "Invalid entity='{}' in Meta TLS client cert Subject CN: '{}'",
                entity, sslUser);
            return std::nullopt;
        }
    }

    if (entity.empty())
    {
        BMCWEB_LOG_DEBUG("Invalid Meta TLS client cert Subject CN: '{}'",
                         sslUser);
        return std::nullopt;
    }

    return entity;
}