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