Botan 3.12.0
Crypto and TLS for C&
Botan::GeneralName Class Referencefinal

X.509 GeneralName Type. More...

#include <pkix_types.h>

Inheritance diagram for Botan::GeneralName:
Botan::ASN1_Object

Public Types

enum  MatchResult : uint8_t {
  All , Some , None , NotFound ,
  UnknownType
}
enum class  NameType : uint8_t {
  Unknown = 0 , RFC822 = 1 , DNS = 2 , URI = 3 ,
  DN = 4 , IPv4 = 5 , IPv6 = 6 , Other = 7
}

Public Member Functions

std::vector< uint8_t > BER_encode () const
std::vector< uint8_t > binary_name () const
void decode_from (BER_Decoder &from) override
void encode_into (DER_Encoder &to) const override
 GeneralName ()=default
MatchResult matches (const X509_Certificate &cert) const
bool matches_dn (const X509_DN &dn) const
bool matches_dns (const std::string &dns_name) const
bool matches_ipv4 (IPv4Address ip) const
bool matches_ipv4 (uint32_t ip) const
bool matches_ipv6 (const IPv6Address &ip) const
std::string name () const
std::string type () const
NameType type_code () const

Static Public Member Functions

static GeneralName directory_name (Botan::X509_DN dn)
static GeneralName dns (std::string_view dns)
static GeneralName email (std::string_view email)
static GeneralName ipv4_address (const IPv4Subnet &subnet)
static GeneralName ipv4_address (IPv4Address ipv4)
static GeneralName ipv4_address (uint32_t ipv4)
static GeneralName ipv4_address (uint32_t ipv4, uint32_t mask)
static GeneralName ipv6_address (const IPv6Address &ipv6)
static GeneralName ipv6_address (const IPv6Subnet &subnet)
static GeneralName uri (std::string_view uri)

Friends

class NameConstraints

Detailed Description

X.509 GeneralName Type.

Handles parsing GeneralName types in their BER and canonical string encoding. Allows matching GeneralNames against each other using the rules laid out in the RFC 5280, sec. 4.2.1.10 (Name Constraints).

This entire class is deprecated and will be removed in a future major release

Definition at line 286 of file pkix_types.h.

Member Enumeration Documentation

◆ MatchResult

Enumerator
All 
Some 
None 
NotFound 
UnknownType 

Definition at line 288 of file pkix_types.h.

288 : uint8_t /* NOLINT(*-use-enum-class) */ {
289 All,
290 Some,
291 None,
292 NotFound,
294 };

◆ NameType

enum class Botan::GeneralName::NameType : uint8_t
strong
Enumerator
Unknown 
RFC822 
DNS 
URI 
DN 
IPv4 
IPv6 
Other 

Definition at line 296 of file pkix_types.h.

296 : uint8_t {
297 Unknown = 0,
298 RFC822 = 1,
299 DNS = 2,
300 URI = 3,
301 DN = 4,
302 IPv4 = 5,
303 IPv6 = 6,
304 Other = 7,
305 };

Constructor & Destructor Documentation

◆ GeneralName()

Member Function Documentation

◆ BER_encode()

std::vector< uint8_t > Botan::ASN1_Object::BER_encode ( ) const
inherited

Return the encoding of this object. This is a convenience method when just one object needs to be serialized. Use DER_Encoder for complicated encodings.

Definition at line 20 of file asn1_obj.cpp.

20 {
21 std::vector<uint8_t> output;
22 DER_Encoder der(output);
23 this->encode_into(der);
24 return output;
25}
virtual void encode_into(DER_Encoder &to) const =0

References encode_into().

Referenced by decode_from(), Botan::Certificate_Store_In_SQL::find_all_certs(), Botan::Certificate_Store_In_SQL::find_cert(), Botan::X509_Certificate::fingerprint(), Botan::Certificate_Store_In_SQL::insert_cert(), Botan::X509_Object::PEM_encode(), Botan::PSS_Params::PSS_Params(), and Botan::Certificate_Store_In_SQL::revoke_cert().

◆ binary_name()

std::vector< uint8_t > Botan::GeneralName::binary_name ( ) const
Returns
The name as binary string. Format depends on type.

Definition at line 123 of file name_constraint.cpp.

123 {
124 return std::visit(Botan::overloaded{
125 [](const Botan::X509_DN& dn) { return Botan::ASN1::put_in_sequence(dn.get_bits()); },
126 [](const IPv4Subnet& subnet) { return subnet.serialize(); },
127 [](const IPv6Subnet& subnet) { return subnet.serialize(); },
128 [](const auto&) -> std::vector<uint8_t> {
129 throw Invalid_State("Cannot convert GeneralName to binary string");
130 },
131 },
132 m_name);
133}
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition asn1_obj.cpp:177
overloaded(Ts...) -> overloaded< Ts... >

References Botan::ASN1::put_in_sequence().

Referenced by botan_x509_general_name_view_binary_value().

◆ decode_from()

void Botan::GeneralName::decode_from ( BER_Decoder & from)
overridevirtual

Decode whatever this object is from from

Parameters
fromthe BER_Decoder that will be read from

Implements Botan::ASN1_Object.

Definition at line 139 of file name_constraint.cpp.

139 {
140 const BER_Object obj = ber.get_next_object();
141
142 if(obj.is_a(0, ASN1_Class::ExplicitContextSpecific)) {
143 m_type = NameType::Other;
144 } else if(obj.is_a(1, ASN1_Class::ContextSpecific)) {
145 m_type = NameType::RFC822;
146 m_name.emplace<RFC822_IDX>(ASN1::to_string(obj));
147 } else if(obj.is_a(2, ASN1_Class::ContextSpecific)) {
148 // Store it in case insensitive form so we don't have to do it
149 // again while matching
150 auto dns = canonicalize_dns_name(ASN1::to_string(obj));
151 // An empty DNS subtree has no clear meaning, reject immediately
152 if(dns.empty()) {
153 throw Decoding_Error("Empty DNS name in GeneralName");
154 }
155 m_type = NameType::DNS;
156 m_name.emplace<DNS_IDX>(std::move(dns));
157 } else if(obj.is_a(6, ASN1_Class::ContextSpecific)) {
158 m_type = NameType::URI;
159 m_name.emplace<URI_IDX>(ASN1::to_string(obj));
160 } else if(obj.is_a(4, ASN1_Class::ContextSpecific | ASN1_Class::Constructed)) {
161 X509_DN dn;
162 BER_Decoder dec(obj, ber.limits());
163 dn.decode_from(dec);
164 m_type = NameType::DN;
165 m_name.emplace<DN_IDX>(dn);
166 } else if(obj.is_a(7, ASN1_Class::ContextSpecific)) {
167 if(obj.length() == 8) {
168 const auto addr_and_mask = std::span<const uint8_t, 8>{obj.bits(), 8};
169 auto subnet = IPv4Subnet::from_address_and_mask(addr_and_mask);
170 if(!subnet.has_value()) {
171 throw Decoding_Error("IPv4 name constraint mask is not a contiguous CIDR prefix");
172 }
173
174 m_type = NameType::IPv4;
175 m_name.emplace<IPV4_IDX>(*subnet);
176 } else if(obj.length() == 32) {
177 const auto addr_and_mask = std::span<const uint8_t, 32>{obj.bits(), 32};
178 auto subnet = IPv6Subnet::from_address_and_mask(addr_and_mask);
179 if(!subnet.has_value()) {
180 throw Decoding_Error("IPv6 name constraint mask is not a contiguous CIDR prefix");
181 }
182
183 m_type = NameType::IPv6;
184 m_name.emplace<IPV6_IDX>(*subnet);
185 } else {
186 throw Decoding_Error("Invalid IP name constraint size " + std::to_string(obj.length()));
187 }
188 } else {
189 m_type = NameType::Unknown;
190 }
191}
static GeneralName dns(std::string_view dns)
static std::optional< IPv4Subnet > from_address_and_mask(std::span< const uint8_t, 8 > addr_and_mask)
static std::optional< IPv6Subnet > from_address_and_mask(std::span< const uint8_t, 32 > addr_and_mask)
std::string to_string(const BER_Object &obj)
Definition asn1_obj.cpp:190

References Botan::BER_Object::bits(), Botan::Constructed, Botan::ContextSpecific, Botan::X509_DN::decode_from(), DN, DNS, dns(), Botan::ExplicitContextSpecific, Botan::IPv4Subnet::from_address_and_mask(), Botan::IPv6Subnet::from_address_and_mask(), Botan::BER_Decoder::get_next_object(), IPv4, IPv6, Botan::BER_Object::is_a(), Botan::BER_Object::length(), Botan::BER_Decoder::limits(), Other, RFC822, Botan::ASN1::to_string(), Unknown, and URI.

Referenced by GeneralName().

◆ directory_name()

GeneralName Botan::GeneralName::directory_name ( Botan::X509_DN dn)
static

Definition at line 69 of file name_constraint.cpp.

69 {
70 return GeneralName::make<DN_IDX>(std::move(dn));
71}

References GeneralName().

Referenced by GeneralName().

◆ dns()

GeneralName Botan::GeneralName::dns ( std::string_view dns)
static

Definition at line 61 of file name_constraint.cpp.

61 {
62 return GeneralName::make<DNS_IDX>(dns);
63}

References dns(), and GeneralName().

Referenced by decode_from(), dns(), GeneralName(), and matches().

◆ email()

GeneralName Botan::GeneralName::email ( std::string_view email)
static

Definition at line 57 of file name_constraint.cpp.

57 {
58 return GeneralName::make<RFC822_IDX>(email);
59}
static GeneralName email(std::string_view email)

References email(), and GeneralName().

Referenced by email(), and GeneralName().

◆ encode_into()

void Botan::GeneralName::encode_into ( DER_Encoder & to) const
overridevirtual

Encode whatever this object is into to

Parameters
tothe DER_Encoder that will be written to

Implements Botan::ASN1_Object.

Definition at line 135 of file name_constraint.cpp.

135 {
136 throw Not_Implemented("GeneralName encoding");
137}

Referenced by GeneralName().

◆ ipv4_address() [1/4]

GeneralName Botan::GeneralName::ipv4_address ( const IPv4Subnet & subnet)
static

Definition at line 89 of file name_constraint.cpp.

89 {
90 return GeneralName::make<IPV4_IDX>(subnet);
91}

References GeneralName().

◆ ipv4_address() [2/4]

GeneralName Botan::GeneralName::ipv4_address ( IPv4Address ipv4)
static

Definition at line 85 of file name_constraint.cpp.

85 {
86 return GeneralName::make<IPV4_IDX>(IPv4Subnet::host(ipv4));
87}
static IPv4Subnet host(IPv4Address address)

References GeneralName(), and Botan::IPv4Subnet::host().

◆ ipv4_address() [3/4]

GeneralName Botan::GeneralName::ipv4_address ( uint32_t ipv4)
static

Definition at line 73 of file name_constraint.cpp.

73 {
74 return GeneralName::ipv4_address(IPv4Address(ipv4));
75}
static GeneralName ipv4_address(uint32_t ipv4)

References GeneralName(), and ipv4_address().

Referenced by GeneralName(), and ipv4_address().

◆ ipv4_address() [4/4]

GeneralName Botan::GeneralName::ipv4_address ( uint32_t ipv4,
uint32_t mask )
static

Definition at line 77 of file name_constraint.cpp.

77 {
78 auto subnet = IPv4Subnet::from_address_and_mask(ipv4, mask);
79 if(!subnet.has_value()) {
80 throw Invalid_Argument("IPv4 subnet mask is not a contiguous CIDR prefix");
81 }
82 return GeneralName::make<IPV4_IDX>(*subnet);
83}

References Botan::IPv4Subnet::from_address_and_mask(), and GeneralName().

◆ ipv6_address() [1/2]

GeneralName Botan::GeneralName::ipv6_address ( const IPv6Address & ipv6)
static

Definition at line 93 of file name_constraint.cpp.

93 {
94 return GeneralName::make<IPV6_IDX>(IPv6Subnet::host(ipv6));
95}
static IPv6Subnet host(IPv6Address address)

References GeneralName(), and Botan::IPv6Subnet::host().

Referenced by GeneralName().

◆ ipv6_address() [2/2]

GeneralName Botan::GeneralName::ipv6_address ( const IPv6Subnet & subnet)
static

Definition at line 97 of file name_constraint.cpp.

97 {
98 return GeneralName::make<IPV6_IDX>(subnet);
99}

References GeneralName().

◆ matches()

GeneralName::MatchResult Botan::GeneralName::matches ( const X509_Certificate & cert) const

Checks whether a given certificate (partially) matches this name.

Parameters
certcertificate to be matched
Returns
the match result

Definition at line 223 of file name_constraint.cpp.

223 {
224 class MatchScore final {
225 public:
226 MatchScore() : m_any(false), m_some(false), m_all(true) {}
227
228 void add(bool m) {
229 m_any = true;
230 m_some |= m;
231 m_all &= m;
232 }
233
234 MatchResult result() const {
235 if(!m_any) {
236 return MatchResult::NotFound;
237 } else if(m_all) {
238 return MatchResult::All;
239 } else if(m_some) {
240 return MatchResult::Some;
241 } else {
242 return MatchResult::None;
243 }
244 }
245
246 private:
247 bool m_any;
248 bool m_some;
249 bool m_all;
250 };
251
252 const X509_DN& dn = cert.subject_dn();
253 const AlternativeName& alt_name = cert.subject_alt_name();
254
255 MatchScore score;
256
257 if(m_type == NameType::DNS) {
258 const auto& constraint = std::get<DNS_IDX>(m_name);
259
260 const auto& alt_names = alt_name.dns();
261
262 for(const std::string& dns : alt_names) {
263 score.add(matches_dns(dns, constraint));
264 }
265
266 if(alt_name.count() == 0) {
267 // Check CN instead...
268 for(const std::string& cn : dn.get_attribute("CN")) {
269 if(!string_to_ipv4(cn).has_value()) {
270 score.add(matches_dns(canonicalize_dns_name(cn), constraint));
271 }
272 }
273 }
274 } else if(m_type == NameType::DN) {
275 const X509_DN& constraint = std::get<DN_IDX>(m_name);
276 score.add(matches_dn(dn, constraint));
277
278 for(const auto& alt_dn : alt_name.directory_names()) {
279 score.add(matches_dn(alt_dn, constraint));
280 }
281 } else if(m_type == NameType::IPv4) {
282 const auto& subnet = std::get<IPV4_IDX>(m_name);
283
284 if(alt_name.count() == 0) {
285 // Check CN instead...
286 for(const std::string& cn : dn.get_attribute("CN")) {
287 if(auto ipv4 = string_to_ipv4(cn)) {
288 score.add(subnet.contains(IPv4Address(*ipv4)));
289 }
290 }
291 } else {
292 for(const uint32_t ipv4 : alt_name.ipv4_address()) {
293 score.add(subnet.contains(IPv4Address(ipv4)));
294 }
295 }
296 } else if(m_type == NameType::IPv6) {
297 for(const auto& ipv6 : alt_name.ipv6_address()) {
298 score.add(matches_ipv6(ipv6));
299 }
300 } else {
301 // URI and email name constraint matching not implemented
303 }
304
305 return score.result();
306}
bool matches_ipv6(const IPv6Address &ip) const
bool matches_dn(const X509_DN &dn) const
bool matches_dns(const std::string &dns_name) const
std::optional< uint32_t > string_to_ipv4(std::string_view str)
Definition parsing.cpp:155

References All, Botan::AlternativeName::count(), Botan::AlternativeName::directory_names(), DN, DNS, Botan::AlternativeName::dns(), dns(), Botan::X509_DN::get_attribute(), IPv4, Botan::AlternativeName::ipv4_address(), IPv6, Botan::AlternativeName::ipv6_address(), matches_dn(), matches_dns(), matches_ipv6(), None, NotFound, Some, Botan::string_to_ipv4(), Botan::X509_Certificate::subject_alt_name(), Botan::X509_Certificate::subject_dn(), and UnknownType.

◆ matches_dn()

bool Botan::GeneralName::matches_dn ( const X509_DN & dn) const

Definition at line 215 of file name_constraint.cpp.

215 {
216 if(m_type == NameType::DN) {
217 const X509_DN& constraint = std::get<DN_IDX>(m_name);
218 return matches_dn(dn, constraint);
219 }
220 return false;
221}

References DN, and matches_dn().

Referenced by matches(), and matches_dn().

◆ matches_dns()

bool Botan::GeneralName::matches_dns ( const std::string & dns_name) const

Definition at line 193 of file name_constraint.cpp.

193 {
194 if(m_type == NameType::DNS) {
195 const auto& constraint = std::get<DNS_IDX>(m_name);
196 return matches_dns(dns_name, constraint);
197 }
198 return false;
199}

References DNS, and matches_dns().

Referenced by matches(), and matches_dns().

◆ matches_ipv4() [1/2]

bool Botan::GeneralName::matches_ipv4 ( IPv4Address ip) const
inline

Definition at line 355 of file pkix_types.h.

355{ return matches_ipv4(ip.value()); }
bool matches_ipv4(uint32_t ip) const

References matches_ipv4(), and matches_ipv4().

Referenced by matches_ipv4().

◆ matches_ipv4() [2/2]

bool Botan::GeneralName::matches_ipv4 ( uint32_t ip) const

Definition at line 201 of file name_constraint.cpp.

201 {
202 if(m_type == NameType::IPv4) {
203 return std::get<IPV4_IDX>(m_name).contains(IPv4Address(ip));
204 }
205 return false;
206}

References IPv4.

Referenced by matches_ipv4().

◆ matches_ipv6()

bool Botan::GeneralName::matches_ipv6 ( const IPv6Address & ip) const

Definition at line 208 of file name_constraint.cpp.

208 {
209 if(m_type == NameType::IPv6) {
210 return std::get<IPV6_IDX>(m_name).contains(ip);
211 }
212 return false;
213}

References IPv6.

Referenced by matches().

◆ name()

std::string Botan::GeneralName::name ( ) const
Returns
The name as string. Format depends on type.

Definition at line 101 of file name_constraint.cpp.

101 {
102 const size_t index = m_name.index();
103
104 if(index == RFC822_IDX) {
105 return std::get<RFC822_IDX>(m_name);
106 } else if(index == DNS_IDX) {
107 return std::get<DNS_IDX>(m_name);
108 } else if(index == URI_IDX) {
109 return std::get<URI_IDX>(m_name);
110 } else if(index == DN_IDX) {
111 return std::get<DN_IDX>(m_name).to_string();
112 } else if(index == IPV4_IDX) {
113 const auto& subnet = std::get<IPV4_IDX>(m_name);
114 return subnet.is_host() ? subnet.address().to_string() : subnet.to_string();
115 } else if(index == IPV6_IDX) {
116 const auto& subnet = std::get<IPV6_IDX>(m_name);
117 return subnet.is_host() ? subnet.address().to_string() : subnet.to_string();
118 } else {
120 }
121}
#define BOTAN_ASSERT_UNREACHABLE()
Definition assert.h:163

References BOTAN_ASSERT_UNREACHABLE.

Referenced by botan_x509_general_name_view_string_value(), NameConstraints, and Botan::operator<<().

◆ type()

std::string Botan::GeneralName::type ( ) const
Returns
Type of the name. Can be DN, DNS, IP, RFC822 or URI.

Definition at line 34 of file name_constraint.cpp.

34 {
35 switch(m_type) {
37 throw Encoding_Error("Could not convert unknown NameType to string");
39 return "RFC822";
40 case NameType::DNS:
41 return "DNS";
42 case NameType::URI:
43 return "URI";
44 case NameType::DN:
45 return "DN";
46 case NameType::IPv4:
47 return "IP";
48 case NameType::IPv6:
49 return "IPv6";
50 case NameType::Other:
51 return "Other";
52 }
53
55}

References BOTAN_ASSERT_UNREACHABLE, DN, DNS, IPv4, IPv6, Other, RFC822, Unknown, and URI.

Referenced by NameConstraints, and Botan::operator<<().

◆ type_code()

NameType Botan::GeneralName::type_code ( ) const
inline
Returns
Type of the name expressed in this restriction

Definition at line 328 of file pkix_types.h.

328{ return m_type; }

References type_code().

Referenced by botan_x509_general_name_get_type(), botan_x509_general_name_view_binary_value(), botan_x509_general_name_view_string_value(), and type_code().

◆ uri()

GeneralName Botan::GeneralName::uri ( std::string_view uri)
static

Definition at line 65 of file name_constraint.cpp.

65 {
66 return GeneralName::make<URI_IDX>(uri);
67}
static GeneralName uri(std::string_view uri)

References GeneralName(), and uri().

Referenced by GeneralName(), and uri().

◆ NameConstraints

friend class NameConstraints
friend

Definition at line 361 of file pkix_types.h.

References GeneralName(), name(), NameConstraints, and type().

Referenced by NameConstraints.


The documentation for this class was generated from the following files: