Botan 3.10.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 , Other = 6
}

Public Member Functions

std::vector< uint8_t > BER_encode () 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 (uint32_t ip) const
std::string name () const
std::string type () const
NameType type_code () const

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 260 of file pkix_types.h.

Member Enumeration Documentation

◆ MatchResult

Enumerator
All 
Some 
None 
NotFound 
UnknownType 

Definition at line 262 of file pkix_types.h.

262 : uint8_t /* NOLINT(*-use-enum-class) */ {
263 All,
264 Some,
265 None,
266 NotFound,
268 };

◆ NameType

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

Definition at line 270 of file pkix_types.h.

270 : uint8_t {
271 Unknown = 0,
272 RFC822 = 1,
273 DNS = 2,
274 URI = 3,
275 DN = 4,
276 IPv4 = 5,
277 Other = 6,
278 };

Constructor & Destructor Documentation

◆ GeneralName()

Botan::GeneralName::GeneralName ( )
default

References decode_from(), encode_into(), and GeneralName().

Referenced by 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 19 of file asn1_obj.cpp.

19 {
20 std::vector<uint8_t> output;
21 DER_Encoder der(output);
22 this->encode_into(der);
23 return output;
24}
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::Certificate_Store_Windows::find_cert_by_issuer_dn_and_serial_number(), 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().

◆ 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 66 of file name_constraint.cpp.

66 {
67 BER_Object obj = ber.get_next_object();
68
70 m_type = NameType::Other;
71 } else if(obj.is_a(1, ASN1_Class::ContextSpecific)) {
72 m_type = NameType::RFC822;
73 m_name.emplace<RFC822_IDX>(ASN1::to_string(obj));
74 } else if(obj.is_a(2, ASN1_Class::ContextSpecific)) {
75 m_type = NameType::DNS;
76 // Store it in case insensitive form so we don't have to do it
77 // again while matching
78 m_name.emplace<DNS_IDX>(tolower_string(ASN1::to_string(obj)));
79 } else if(obj.is_a(6, ASN1_Class::ContextSpecific)) {
80 m_type = NameType::URI;
81 m_name.emplace<URI_IDX>(ASN1::to_string(obj));
83 X509_DN dn;
84 BER_Decoder dec(obj);
85 dn.decode_from(dec);
86 m_type = NameType::DN;
87 m_name.emplace<DN_IDX>(dn);
88 } else if(obj.is_a(7, ASN1_Class::ContextSpecific)) {
89 if(obj.length() == 8) {
90 const uint32_t net = load_be<uint32_t>(obj.bits(), 0);
91 const uint32_t mask = load_be<uint32_t>(obj.bits(), 1);
92
93 m_type = NameType::IPv4;
94 m_name.emplace<IPV4_IDX>(std::make_pair(net, mask));
95 } else if(obj.length() == 32) {
96 // IPv6 name constraints are not implemented
97 m_type = NameType::Unknown;
98 } else {
99 throw Decoding_Error("Invalid IP name constraint size " + std::to_string(obj.length()));
100 }
101 } else {
102 m_type = NameType::Unknown;
103 }
104}
std::string to_string(const BER_Object &obj)
Definition asn1_obj.cpp:185
std::string tolower_string(std::string_view in)
Definition parsing.cpp:241
constexpr auto load_be(ParamTs &&... params)
Definition loadstor.h:504

References Botan::BER_Object::bits(), Botan::Constructed, Botan::ContextSpecific, Botan::X509_DN::decode_from(), DN, DNS, Botan::ExplicitContextSpecific, Botan::BER_Decoder::get_next_object(), IPv4, Botan::BER_Object::is_a(), Botan::BER_Object::length(), Botan::load_be(), Other, RFC822, Botan::ASN1::to_string(), Botan::tolower_string(), Unknown, and URI.

Referenced by 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 62 of file name_constraint.cpp.

62 {
63 throw Not_Implemented("GeneralName encoding");
64}

Referenced by 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 130 of file name_constraint.cpp.

130 {
131 class MatchScore final {
132 public:
133 MatchScore() : m_any(false), m_some(false), m_all(true) {}
134
135 void add(bool m) {
136 m_any = true;
137 m_some |= m;
138 m_all &= m;
139 }
140
141 MatchResult result() const {
142 if(!m_any) {
143 return MatchResult::NotFound;
144 } else if(m_all) {
145 return MatchResult::All;
146 } else if(m_some) {
147 return MatchResult::Some;
148 } else {
149 return MatchResult::None;
150 }
151 }
152
153 private:
154 bool m_any;
155 bool m_some;
156 bool m_all;
157 };
158
159 const X509_DN& dn = cert.subject_dn();
160 const AlternativeName& alt_name = cert.subject_alt_name();
161
162 MatchScore score;
163
164 if(m_type == NameType::DNS) {
165 const auto& constraint = std::get<DNS_IDX>(m_name);
166
167 const auto& alt_names = alt_name.dns();
168
169 for(const std::string& dns : alt_names) {
170 score.add(matches_dns(dns, constraint));
171 }
172
173 if(alt_name.count() == 0) {
174 // Check CN instead...
175 for(const std::string& cn : dn.get_attribute("CN")) {
176 if(!string_to_ipv4(cn).has_value()) {
177 score.add(matches_dns(cn, constraint));
178 }
179 }
180 }
181 } else if(m_type == NameType::DN) {
182 const X509_DN& constraint = std::get<DN_IDX>(m_name);
183 score.add(matches_dn(dn, constraint));
184
185 for(const auto& alt_dn : alt_name.directory_names()) {
186 score.add(matches_dn(alt_dn, constraint));
187 }
188 } else if(m_type == NameType::IPv4) {
189 auto [net, mask] = std::get<IPV4_IDX>(m_name);
190
191 if(alt_name.count() == 0) {
192 // Check CN instead...
193 for(const std::string& cn : dn.get_attribute("CN")) {
194 if(auto ipv4 = string_to_ipv4(cn)) {
195 bool match = (ipv4.value() & mask) == net;
196 score.add(match);
197 }
198 }
199 } else {
200 for(uint32_t ipv4 : alt_name.ipv4_address()) {
201 bool match = (ipv4 & mask) == net;
202 score.add(match);
203 }
204 }
205 } else {
206 // URI and email name constraint matching not implemented
208 }
209
210 return score.result();
211}
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:156

References All, Botan::AlternativeName::count(), Botan::AlternativeName::directory_names(), DN, DNS, Botan::AlternativeName::dns(), Botan::X509_DN::get_attribute(), IPv4, Botan::AlternativeName::ipv4_address(), matches_dn(), matches_dns(), 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 122 of file name_constraint.cpp.

122 {
123 if(m_type == NameType::DN) {
124 const X509_DN& constraint = std::get<DN_IDX>(m_name);
125 return matches_dn(dn, constraint);
126 }
127 return false;
128}

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 106 of file name_constraint.cpp.

106 {
107 if(m_type == NameType::DNS) {
108 const auto& constraint = std::get<DNS_IDX>(m_name);
109 return matches_dns(dns_name, constraint);
110 }
111 return false;
112}

References DNS, and matches_dns().

Referenced by matches(), and matches_dns().

◆ matches_ipv4()

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

Definition at line 114 of file name_constraint.cpp.

114 {
115 if(m_type == NameType::IPv4) {
116 auto [net, mask] = std::get<IPV4_IDX>(m_name);
117 return (ip & mask) == net;
118 }
119 return false;
120}

References IPv4.

◆ name()

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

Definition at line 43 of file name_constraint.cpp.

43 {
44 const size_t index = m_name.index();
45
46 if(index == RFC822_IDX) {
47 return std::get<RFC822_IDX>(m_name);
48 } else if(index == DNS_IDX) {
49 return std::get<DNS_IDX>(m_name);
50 } else if(index == URI_IDX) {
51 return std::get<URI_IDX>(m_name);
52 } else if(index == DN_IDX) {
53 return std::get<DN_IDX>(m_name).to_string();
54 } else if(index == IPV4_IDX) {
55 auto [net, mask] = std::get<IPV4_IDX>(m_name);
56 return fmt("{}/{}", ipv4_to_string(net), ipv4_to_string(mask));
57 } else {
59 }
60}
#define BOTAN_ASSERT_UNREACHABLE()
Definition assert.h:163
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
std::string ipv4_to_string(uint32_t ip)
Definition parsing.cpp:225

References BOTAN_ASSERT_UNREACHABLE, Botan::fmt(), and Botan::ipv4_to_string().

Referenced by 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 22 of file name_constraint.cpp.

22 {
23 switch(m_type) {
25 throw Encoding_Error("Could not convert unknown NameType to string");
27 return "RFC822";
28 case NameType::DNS:
29 return "DNS";
30 case NameType::URI:
31 return "URI";
32 case NameType::DN:
33 return "DN";
34 case NameType::IPv4:
35 return "IP";
36 case NameType::Other:
37 return "Other";
38 }
39
41}

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

Referenced by Botan::operator<<().

◆ type_code()

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

Definition at line 290 of file pkix_types.h.

290{ return m_type; }

References type_code().

Referenced by type_code().


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