Botan 1.10.17
x509_dn.cpp
Go to the documentation of this file.
1/*
2* X509_DN
3* (C) 1999-2007 Jack Lloyd
4*
5* Distributed under the terms of the Botan license
6*/
7
8#include <botan/x509_dn.h>
9#include <botan/der_enc.h>
10#include <botan/ber_dec.h>
11#include <botan/parsing.h>
12#include <botan/internal/stl_util.h>
13#include <botan/oids.h>
14
15namespace Botan {
16
17/*
18* Create an empty X509_DN
19*/
21 {
22 }
23
24/*
25* Create an X509_DN
26*/
27X509_DN::X509_DN(const std::multimap<OID, std::string>& args)
28 {
29 std::multimap<OID, std::string>::const_iterator j;
30 for(j = args.begin(); j != args.end(); ++j)
31 add_attribute(j->first, j->second);
32 }
33
34/*
35* Create an X509_DN
36*/
37X509_DN::X509_DN(const std::multimap<std::string, std::string>& args)
38 {
39 std::multimap<std::string, std::string>::const_iterator j;
40 for(j = args.begin(); j != args.end(); ++j)
41 add_attribute(OIDS::lookup(j->first), j->second);
42 }
43
44/*
45* Add an attribute to a X509_DN
46*/
47void X509_DN::add_attribute(const std::string& type,
48 const std::string& str)
49 {
50 OID oid = OIDS::lookup(type);
51 add_attribute(oid, str);
52 }
53
54/*
55* Add an attribute to a X509_DN
56*/
57void X509_DN::add_attribute(const OID& oid, const std::string& str)
58 {
59 if(str == "")
60 return;
61
62 typedef std::multimap<OID, ASN1_String>::iterator rdn_iter;
63
64 std::pair<rdn_iter, rdn_iter> range = dn_info.equal_range(oid);
65 for(rdn_iter j = range.first; j != range.second; ++j)
66 if(j->second.value() == str)
67 return;
68
69 multimap_insert(dn_info, oid, ASN1_String(str));
70 dn_bits.clear();
71 }
72
73/*
74* Get the attributes of this X509_DN
75*/
76std::multimap<OID, std::string> X509_DN::get_attributes() const
77 {
78 typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter;
79
80 std::multimap<OID, std::string> retval;
81 for(rdn_iter j = dn_info.begin(); j != dn_info.end(); ++j)
82 multimap_insert(retval, j->first, j->second.value());
83 return retval;
84 }
85
86/*
87* Get the contents of this X.500 Name
88*/
89std::multimap<std::string, std::string> X509_DN::contents() const
90 {
91 typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter;
92
93 std::multimap<std::string, std::string> retval;
94 for(rdn_iter j = dn_info.begin(); j != dn_info.end(); ++j)
95 multimap_insert(retval, OIDS::lookup(j->first), j->second.value());
96 return retval;
97 }
98
99/*
100* Get a single attribute type
101*/
102std::vector<std::string> X509_DN::get_attribute(const std::string& attr) const
103 {
104 typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter;
105
106 const OID oid = OIDS::lookup(deref_info_field(attr));
107 std::pair<rdn_iter, rdn_iter> range = dn_info.equal_range(oid);
108
109 std::vector<std::string> values;
110 for(rdn_iter j = range.first; j != range.second; ++j)
111 values.push_back(j->second.value());
112 return values;
113 }
114
115/*
116* Return the BER encoded data, if any
117*/
119 {
120 return dn_bits;
121 }
122
123/*
124* Deref aliases in a subject/issuer info request
125*/
126std::string X509_DN::deref_info_field(const std::string& info)
127 {
128 if(info == "Name" || info == "CommonName") return "X520.CommonName";
129 if(info == "SerialNumber") return "X520.SerialNumber";
130 if(info == "Country") return "X520.Country";
131 if(info == "Organization") return "X520.Organization";
132 if(info == "Organizational Unit" || info == "OrgUnit")
133 return "X520.OrganizationalUnit";
134 if(info == "Locality") return "X520.Locality";
135 if(info == "State" || info == "Province") return "X520.State";
136 if(info == "Email") return "RFC822";
137 return info;
138 }
139
140/*
141* Compare two X509_DNs for equality
142*/
143bool operator==(const X509_DN& dn1, const X509_DN& dn2)
144 {
145 typedef std::multimap<OID, std::string>::const_iterator rdn_iter;
146
147 std::multimap<OID, std::string> attr1 = dn1.get_attributes();
148 std::multimap<OID, std::string> attr2 = dn2.get_attributes();
149
150 if(attr1.size() != attr2.size()) return false;
151
152 rdn_iter p1 = attr1.begin();
153 rdn_iter p2 = attr2.begin();
154
155 while(true)
156 {
157 if(p1 == attr1.end() && p2 == attr2.end())
158 break;
159 if(p1 == attr1.end()) return false;
160 if(p2 == attr2.end()) return false;
161 if(p1->first != p2->first) return false;
162 if(!x500_name_cmp(p1->second, p2->second))
163 return false;
164 ++p1;
165 ++p2;
166 }
167 return true;
168 }
169
170/*
171* Compare two X509_DNs for inequality
172*/
173bool operator!=(const X509_DN& dn1, const X509_DN& dn2)
174 {
175 return !(dn1 == dn2);
176 }
177
178/*
179* Compare two X509_DNs
180*/
181bool operator<(const X509_DN& dn1, const X509_DN& dn2)
182 {
183 typedef std::multimap<OID, std::string>::const_iterator rdn_iter;
184
185 std::multimap<OID, std::string> attr1 = dn1.get_attributes();
186 std::multimap<OID, std::string> attr2 = dn2.get_attributes();
187
188 if(attr1.size() < attr2.size()) return true;
189 if(attr1.size() > attr2.size()) return false;
190
191 for(rdn_iter p1 = attr1.begin(); p1 != attr1.end(); ++p1)
192 {
193 std::multimap<OID, std::string>::const_iterator p2;
194 p2 = attr2.find(p1->first);
195 if(p2 == attr2.end()) return false;
196 if(p1->second > p2->second) return false;
197 if(p1->second < p2->second) return true;
198 }
199 return false;
200 }
201
202namespace {
203
204/*
205* DER encode a RelativeDistinguishedName
206*/
207void do_ava(DER_Encoder& encoder,
208 const std::multimap<OID, std::string>& dn_info,
209 ASN1_Tag string_type, const std::string& oid_str,
210 bool must_exist = false)
211 {
212 typedef std::multimap<OID, std::string>::const_iterator rdn_iter;
213
214 const OID oid = OIDS::lookup(oid_str);
215 const bool exists = (dn_info.find(oid) != dn_info.end());
216
217 if(!exists && must_exist)
218 throw Encoding_Error("X509_DN: No entry for " + oid_str);
219 if(!exists) return;
220
221 std::pair<rdn_iter, rdn_iter> range = dn_info.equal_range(oid);
222
223 for(rdn_iter j = range.first; j != range.second; ++j)
224 {
225 encoder.start_cons(SET)
226 .start_cons(SEQUENCE)
227 .encode(oid)
228 .encode(ASN1_String(j->second, string_type))
229 .end_cons()
230 .end_cons();
231 }
232 }
233
234}
235
236/*
237* DER encode a DistinguishedName
238*/
240 {
241 std::multimap<OID, std::string> dn_info = get_attributes();
242
243 der.start_cons(SEQUENCE);
244
245 if(!dn_bits.empty())
246 der.raw_bytes(dn_bits);
247 else
248 {
249 do_ava(der, dn_info, PRINTABLE_STRING, "X520.Country");
250 do_ava(der, dn_info, DIRECTORY_STRING, "X520.State");
251 do_ava(der, dn_info, DIRECTORY_STRING, "X520.Locality");
252 do_ava(der, dn_info, DIRECTORY_STRING, "X520.Organization");
253 do_ava(der, dn_info, DIRECTORY_STRING, "X520.OrganizationalUnit");
254 do_ava(der, dn_info, DIRECTORY_STRING, "X520.CommonName");
255 do_ava(der, dn_info, PRINTABLE_STRING, "X520.SerialNumber");
256 }
257
258 der.end_cons();
259 }
260
261/*
262* Decode a BER encoded DistinguishedName
263*/
265 {
267
268 source.start_cons(SEQUENCE)
269 .raw_bytes(bits)
270 .end_cons();
271
272 BER_Decoder sequence(bits);
273
274 while(sequence.more_items())
275 {
276 BER_Decoder rdn = sequence.start_cons(SET);
277
278 while(rdn.more_items())
279 {
280 OID oid;
281 ASN1_String str;
282
284 .decode(oid)
285 .decode(str)
286 .verify_end()
287 .end_cons();
288
289 add_attribute(oid, str.value());
290 }
291 }
292
293 dn_bits = bits;
294 }
295
296}
ASN1_String(const std::string &="")
Definition asn1_str.cpp:86
std::string value() const
Definition asn1_str.cpp:103
BER_Decoder start_cons(ASN1_Tag, ASN1_Tag=UNIVERSAL)
Definition ber_dec.cpp:238
bool more_items() const
Definition ber_dec.cpp:153
BER_Decoder & raw_bytes(MemoryRegion< byte > &)
Definition ber_dec.cpp:173
BER_Decoder & decode(bool &)
Definition ber_dec.cpp:344
BER_Decoder & verify_end()
Definition ber_dec.cpp:163
BER_Decoder & end_cons()
Definition ber_dec.cpp:252
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition der_enc.cpp:135
DER_Encoder & raw_bytes(const byte val[], size_t len)
Definition der_enc.cpp:188
DER_Encoder & end_cons()
Definition der_enc.cpp:145
static std::string deref_info_field(const std::string &)
Definition x509_dn.cpp:126
void decode_from(class BER_Decoder &)
Definition x509_dn.cpp:264
std::multimap< std::string, std::string > contents() const
Definition x509_dn.cpp:89
void add_attribute(const std::string &, const std::string &)
Definition x509_dn.cpp:47
std::multimap< OID, std::string > get_attributes() const
Definition x509_dn.cpp:76
MemoryVector< byte > get_bits() const
Definition x509_dn.cpp:118
std::vector< std::string > get_attribute(const std::string &) const
Definition x509_dn.cpp:102
void encode_into(class DER_Encoder &) const
Definition x509_dn.cpp:239
std::string lookup(const OID &oid)
Definition oids.cpp:31
bool BOTAN_DLL operator<(const X509_Time &, const X509_Time &)
Definition asn1_tm.cpp:286
bool x500_name_cmp(const std::string &name1, const std::string &name2)
Definition parsing.cpp:213
bool operator!=(const OctetString &s1, const OctetString &s2)
Definition symkey.cpp:106
ASN1_Tag
Definition asn1_int.h:19
@ DIRECTORY_STRING
Definition asn1_int.h:50
@ PRINTABLE_STRING
Definition asn1_int.h:40
@ SEQUENCE
Definition asn1_int.h:35
@ SET
Definition asn1_int.h:36
void multimap_insert(std::multimap< K, V > &multimap, const K &key, const V &value)
Definition stl_util.h:76
bool operator==(const OctetString &s1, const OctetString &s2)
Definition symkey.cpp:98
Encoding_Error(const std::string &name)
Definition exceptn.h:131