Botan 3.13.0
Crypto and TLS for C&
dns_name.h
Go to the documentation of this file.
1/*
2* (C) 2026 Jack Lloyd
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#ifndef BOTAN_DNS_NAME_H_
8#define BOTAN_DNS_NAME_H_
9
10#include <botan/types.h>
11#include <optional>
12#include <string>
13#include <string_view>
14
15namespace Botan {
16
17/**
18* A DNS name (host name or wildcard pattern) in canonical form.
19*
20* Construction validates that the input conforms to the Preferred Name
21* Syntax (RFC 1035 / RFC 1123 LDH labels, length limits, no leading or
22* trailing dot). Entirely numeric names (`"1.2.3.4"`) are rejected. The
23* stored form is lowercased ASCII.
24*/
25class BOTAN_PUBLIC_API(3, 13) DNSName final {
26 public:
27 /**
28 * Parse and canonicalize a literal hostname. Returns nullopt if the
29 * input is not a valid DNS name per RFC 1035 / 1123, or if it
30 * contains a `"*"` label (use `from_san_string` for that).
31 */
32 static std::optional<DNSName> from_string(std::string_view name);
33
34 /**
35 * Like `from_string`, but additionally accepts the RFC 6125 6.4.3
36 * wildcard form: a single `"*"` anywhere within the leftmost label
37 * of an otherwise-valid DNS name (e.g. `"*.example.com"`,
38 * `"foo*.example.com"`). Shapes that could never produce a match -
39 * multiple `"*"` (`"*.*.example.com"`), `"*"` outside the leftmost label
40 * (`"foo.*.example.com"`), or patterns with fewer than three labels
41 * (`"*"`, `"*.com"`) - are rejected, as are wildcards embedded within
42 * an IDNA A-label (`"xn--f*.example.com"`). Intended for parsing
43 * X.509 SAN dnsName entries.
44 */
45 static std::optional<DNSName> from_san_string(std::string_view name);
46
47 /**
48 * Access the canonicalized name
49 * @return the lowercased ASCII form of the name
50 */
51 const std::string& to_string() const { return m_name; }
52
53 /**
54 * Access the canonicalized name
55 * @return the lowercased ASCII form of the name
56 */
57 const std::string& name() const { return m_name; }
58
59 /**
60 * True if this name is a wildcard pattern: a single `"*"` somewhere
61 * in the leftmost label, per RFC 6125 6.4.3 (which permits
62 * in-label partial wildcards like `"foo*.example.com"` as well as
63 * the complete-leftmost-label `"*.example.com"` form). Shapes
64 * outside this form - multiple `"*"` or `"*"` not in the leftmost
65 * label - are rejected at construction by `from_san_string`, so
66 * any stored `"*"` is already in the leftmost label.
67 *
68 * TODO(Botan4) when RFC 9525 wildcards are used, this fn can change
69 * to just looking at the first character of m_name.
70 */
71 bool is_wildcard() const { return m_name.find('*') != std::string::npos; }
72
73 /**
74 * Test whether this name matches a wildcard pattern (e.g. "*.example.com").
75 * The wildcard label must be the leftmost label. Comparison is
76 * case-insensitive.
77 */
78 bool matches_wildcard(std::string_view wildcard) const;
79
80 /**
81 * Order two names by their canonicalized form
82 * @return the ordering of this name relative to the other
83 */
84 auto operator<=>(const DNSName&) const = default;
85
86 /**
87 * Compare two names by their canonicalized form
88 * @return true if the two names are equal
89 */
90 bool operator==(const DNSName&) const = default;
91
92 /**
93 * Test if the issued name (which might be a wildcard pattern) can match the host,
94 * which should be a complete and valid DNS name.
95 *
96 * Returns false if either the pattern or the host seem invalid
97 */
98 static bool host_wildcard_match(std::string_view issued, std::string_view host);
99
100 private:
101 explicit DNSName(std::string canonical) : m_name(std::move(canonical)) {}
102
103 std::string m_name;
104};
105
106} // namespace Botan
107
108#endif
#define BOTAN_PUBLIC_API(maj, min)
Definition api.h:21
auto operator<=>(const DNSName &) const =default
const std::string & to_string() const
Definition dns_name.h:51
static bool host_wildcard_match(std::string_view issued, std::string_view host)
Definition dns_name.cpp:191
bool operator==(const DNSName &) const =default
static std::optional< DNSName > from_san_string(std::string_view name)
Definition dns_name.cpp:149
bool is_wildcard() const
Definition dns_name.h:71
static std::optional< DNSName > from_string(std::string_view name)
Definition dns_name.cpp:136
const std::string & name() const
Definition dns_name.h:57