Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

name_constraint.cpp
Go to the documentation of this file.
1 /*
2 * X.509 Name Constraint
3 * (C) 2015 Kai Michaelis
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7
8 #include <botan/name_constraint.h>
9 #include <botan/asn1_alt_name.h>
10 #include <botan/ber_dec.h>
11 #include <botan/loadstor.h>
12 #include <botan/x509_dn.h>
13 #include <botan/x509cert.h>
14 #include <botan/parsing.h>
15 #include <sstream>
16
17 namespace Botan {
18
19 class DER_Encoder;
20
21 GeneralName::GeneralName(const std::string& str) : GeneralName()
22 {
23 size_t p = str.find(':');
24
25 if(p != std::string::npos)
26 {
27 m_type = str.substr(0, p);
28 m_name = str.substr(p + 1, std::string::npos);
29 }
30 else
31 {
32 throw Invalid_Argument("Failed to decode Name Constraint");
33 }
34 }
35
36 void GeneralName::encode_into(DER_Encoder&) const
37 {
38 throw Not_Implemented("GeneralName encoding");
39 }
40
41 void GeneralName::decode_from(class BER_Decoder& ber)
42 {
43 BER_Object obj = ber.get_next_object();
44
45 if(obj.is_a(1, CONTEXT_SPECIFIC))
46 {
47 m_type = "RFC822";
48 m_name = ASN1::to_string(obj);
49 }
50 else if(obj.is_a(2, CONTEXT_SPECIFIC))
51 {
52 m_type = "DNS";
53 m_name = ASN1::to_string(obj);
54 }
55 else if(obj.is_a(6, CONTEXT_SPECIFIC))
56 {
57 m_type = "URI";
58 m_name = ASN1::to_string(obj);
59 }
60 else if(obj.is_a(4, ASN1_Tag(CONTEXT_SPECIFIC | CONSTRUCTED)))
61 {
62 m_type = "DN";
63 X509_DN dn;
64 BER_Decoder dec(obj);
65 std::stringstream ss;
66
67 dn.decode_from(dec);
68 ss << dn;
69
70 m_name = ss.str();
71 }
72 else if(obj.is_a(7, CONTEXT_SPECIFIC))
73 {
74 if(obj.length() == 8)
75 {
76 m_type = "IP";
77 m_name = ipv4_to_string(load_be<uint32_t>(obj.bits(), 0)) + "/" +
78 ipv4_to_string(load_be<uint32_t>(obj.bits(), 1));
79 }
80 else if(obj.length() == 32)
81 {
82 throw Decoding_Error("Unsupported IPv6 name constraint");
83 }
84 else
85 {
86 throw Decoding_Error("Invalid IP name constraint size " + std::to_string(obj.length()));
87 }
88 }
89 else
90 {
91 throw Decoding_Error("Found unknown GeneralName type");
92 }
93 }
94
95 GeneralName::MatchResult GeneralName::matches(const X509_Certificate& cert) const
96 {
97 std::vector<std::string> nam;
98 std::function<bool(const GeneralName*, const std::string&)> match_fn;
99
100 const X509_DN& dn = cert.subject_dn();
101 const AlternativeName& alt_name = cert.subject_alt_name();
102
103 if(type() == "DNS")
104 {
105 match_fn = std::mem_fn(&GeneralName::matches_dns);
106
107 nam = alt_name.get_attribute("DNS");
108
109 if(nam.empty())
110 {
111 nam = dn.get_attribute("CN");
112 }
113 }
114 else if(type() == "DN")
115 {
116 match_fn = std::mem_fn(&GeneralName::matches_dn);
117
118 std::stringstream ss;
119 ss << dn;
120 nam.push_back(ss.str());
121 }
122 else if(type() == "IP")
123 {
124 match_fn = std::mem_fn(&GeneralName::matches_ip);
125 nam = alt_name.get_attribute("IP");
126 }
127 else
128 {
129 return MatchResult::UnknownType;
130 }
131
132 if(nam.empty())
133 {
134 return MatchResult::NotFound;
135 }
136
137 bool some = false;
138 bool all = true;
139
140 for(const std::string& n: nam)
141 {
142 bool m = match_fn(this, n);
143
144 some |= m;
145 all &= m;
146 }
147
148 if(all)
149 {
150 return MatchResult::All;
151 }
152 else if(some)
153 {
154 return MatchResult::Some;
155 }
156 else
157 {
158 return MatchResult::None;
159 }
160 }
161
162 bool GeneralName::matches_dns(const std::string& nam) const
163 {
164 if(nam.size() == name().size())
165 {
166 return nam == name();
167 }
168 else if(name().size() > nam.size())
169 {
170 return false;
171 }
172 else // name.size() < nam.size()
173 {
174 std::string constr = name().front() == '.' ? name() : "." + name();
175 // constr is suffix of nam
176 return constr == nam.substr(nam.size() - constr.size(), constr.size());
177 }
178 }
179
180 bool GeneralName::matches_dn(const std::string& nam) const
181 {
182 std::stringstream ss(nam);
183 std::stringstream tt(name());
184 X509_DN nam_dn, my_dn;
185
186 ss >> nam_dn;
187 tt >> my_dn;
188
189 auto attr = nam_dn.get_attributes();
190 bool ret = true;
191 size_t trys = 0;
192
193 for(const auto& c: my_dn.dn_info())
194 {
195 auto i = attr.equal_range(c.first);
196
197 if(i.first != i.second)
198 {
199 trys += 1;
200 ret = ret && (i.first->second == c.second.value());
201 }
202 }
203
204 return trys > 0 && ret;
205 }
206
207 bool GeneralName::matches_ip(const std::string& nam) const
208 {
209 uint32_t ip = string_to_ipv4(nam);
210 std::vector<std::string> p = split_on(name(), '/');
211
212 if(p.size() != 2)
213 throw Decoding_Error("failed to parse IPv4 address");
214
215 uint32_t net = string_to_ipv4(p.at(0));
216 uint32_t mask = string_to_ipv4(p.at(1));
217
218 return (ip & mask) == net;
219 }
220
221 std::ostream& operator<<(std::ostream& os, const GeneralName& gn)
222 {
223 os << gn.type() << ":" << gn.name();
224 return os;
225 }
226
227 GeneralSubtree::GeneralSubtree(const std::string& str) : GeneralSubtree()
228 {
229 size_t p0, p1;
230 const auto min = std::stoull(str, &p0, 10);
231 const auto max = std::stoull(str.substr(p0 + 1), &p1, 10);
232 GeneralName gn(str.substr(p0 + p1 + 2));
233
234 if(p0 > 0 && p1 > 0)
235 {
236 m_minimum = static_cast<size_t>(min);
237 m_maximum = static_cast<size_t>(max);
238 m_base = gn;
239 }
240 else
241 {
242 throw Invalid_Argument("Failed to decode Name Constraint");
243 }
244 }
245
246 void GeneralSubtree::encode_into(DER_Encoder&) const
247 {
248 throw Not_Implemented("General Subtree encoding");
249 }
250
251 void GeneralSubtree::decode_from(class BER_Decoder& ber)
252 {
253 ber.start_cons(SEQUENCE)
254 .decode(m_base)
255 .decode_optional(m_minimum,ASN1_Tag(0), CONTEXT_SPECIFIC,size_t(0))
256 .end_cons();
257
258 if(m_minimum != 0)
259 throw Decoding_Error("GeneralSubtree minimum must be 0");
260
261 m_maximum = std::numeric_limits<std::size_t>::max();
262 }
263
264 std::ostream& operator<<(std::ostream& os, const GeneralSubtree& gs)
265 {
266 os << gs.minimum() << "," << gs.maximum() << "," << gs.base();
267 return os;
268 }
269 }
Botan::X509_Certificate::subject_alt_name
const AlternativeName & subject_alt_name() const
Definition: x509cert.cpp:593
Botan::Invalid_Argument
Definition: exceptn.h:136
Botan::GeneralSubtree::decode_from
void decode_from(BER_Decoder &) override
Definition: name_constraint.cpp:251
Botan::GeneralName::MatchResult
MatchResult
Definition: name_constraint.h:31
Botan::operator<<
int operator<<(int fd, Pipe &pipe)
Definition: fd_unix.cpp:17
m_name
std::string m_name
Definition: openssl_hash.cpp:97
Botan::GeneralName::matches
MatchResult matches(const X509_Certificate &cert) const
Definition: name_constraint.cpp:95
Botan::BER_Object::length
size_t length() const
Definition: asn1_obj.h:119
Botan::split_on
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:148
Botan::load_be< uint32_t >
uint32_t load_be< uint32_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:179
Botan::CONSTRUCTED
Definition: asn1_obj.h:28
Botan::Not_Implemented
Definition: exceptn.h:355
Botan::ASN1::to_string
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
Botan::ASN1_Tag
ASN1_Tag
Definition: asn1_obj.h:23
Botan::BER_Object::is_a
bool is_a(ASN1_Tag type_tag, ASN1_Tag class_tag) const
Definition: asn1_obj.cpp:71
Botan::BER_Decoder::decode
BER_Decoder & decode(bool &out)
Definition: ber_dec.h:170
Botan::Decoding_Error
Definition: exceptn.h:199
Botan::BER_Object::bits
const uint8_t * bits() const
Definition: asn1_obj.h:117
Botan::X509_DN::decode_from
void decode_from(class BER_Decoder &) override
Definition: x509_dn.cpp:272
Botan::BER_Decoder::decode_optional
BER_Decoder & decode_optional(T &out, ASN1_Tag type_tag, ASN1_Tag class_tag, const T &default_value=T())
Definition: ber_dec.h:337
Botan::SEQUENCE
Definition: asn1_obj.h:40
Botan::GeneralName::encode_into
void encode_into(DER_Encoder &) const override
Definition: name_constraint.cpp:36
Botan::DER_Encoder
Definition: der_enc.h:23
Botan::X509_Certificate
Definition: x509cert.h:40
Botan::GeneralSubtree::maximum
size_t maximum() const
Definition: name_constraint.h:132
Botan::BER_Decoder::end_cons
BER_Decoder & end_cons()
Definition: ber_dec.cpp:300
Botan::ipv4_to_string
std::string ipv4_to_string(uint32_t ip)
Definition: parsing.cpp:278
Botan::GeneralSubtree::encode_into
void encode_into(DER_Encoder &) const override
Definition: name_constraint.cpp:246
Botan::X509_DN
Definition: x509_dn.h:24
Botan::BER_Decoder::start_cons
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: ber_dec.cpp:290
Botan
Definition: alg_id.cpp:13
Botan::GeneralName
X.509 GeneralName Type.
Definition: name_constraint.h:28
Botan::string_to_ipv4
uint32_t string_to_ipv4(const std::string &str)
Definition: parsing.cpp:253
Botan::GeneralSubtree
A single Name Constraint.
Definition: name_constraint.h:90
Botan::X509_DN::get_attribute
std::vector< std::string > get_attribute(const std::string &attr) const
Definition: x509_dn.cpp:109
Botan::GeneralName::name
const std::string & name() const
Definition: name_constraint.h:63
Botan::GeneralName::decode_from
void decode_from(BER_Decoder &) override
Definition: name_constraint.cpp:41
Botan::BER_Decoder::get_next_object
BER_Object get_next_object()
Definition: ber_dec.cpp:237
Botan::GeneralName::GeneralName
GeneralName()=default
Botan::GeneralSubtree::base
const GeneralName & base() const
Definition: name_constraint.h:122
Botan::GeneralSubtree::minimum
size_t minimum() const
Definition: name_constraint.h:127
Botan::GeneralName::type
const std::string & type() const
Definition: name_constraint.h:58
Botan::GeneralSubtree::GeneralSubtree
GeneralSubtree()
Definition: name_constraint.h:96
Botan::CONTEXT_SPECIFIC
Definition: asn1_obj.h:26
Botan::X509_Certificate::subject_dn
const X509_DN & subject_dn() const
Definition: x509cert.cpp:438
Botan::BER_Decoder
Definition: ber_dec.h:21
Botan::BER_Object
Definition: asn1_obj.h:97
Botan::AlternativeName::get_attribute
std::vector< std::string > get_attribute(const std::string &attr) const
Definition: asn1_alt_name.cpp:99
Botan::AlternativeName
Definition: asn1_alt_name.h:21