monotone

monotone Mtn Source Tree

Root/botan/asn1_dn.cpp

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

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status