Botan  1.10.9
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 
15 namespace Botan {
16 
17 /*
18 * Create an empty X509_DN
19 */
21  {
22  }
23 
24 /*
25 * Create an X509_DN
26 */
27 X509_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 */
37 X509_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 */
47 void 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 */
57 void 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 */
76 std::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 */
89 std::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 */
102 std::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 */
126 std::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 */
143 bool 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 */
173 bool operator!=(const X509_DN& dn1, const X509_DN& dn2)
174  {
175  return !(dn1 == dn2);
176  }
177 
178 /*
179 * Compare two X509_DNs
180 */
181 bool 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 
202 namespace {
203 
204 /*
205 * DER encode a RelativeDistinguishedName
206 */
207 void 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  {
266  MemoryVector<byte> bits;
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 
283  rdn.start_cons(SEQUENCE)
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 }
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
std::string value() const
Definition: asn1_str.cpp:103
std::vector< std::string > get_attribute(const std::string &) const
Definition: x509_dn.cpp:102
DER_Encoder & raw_bytes(const byte val[], size_t len)
Definition: der_enc.cpp:188
BER_Decoder & decode(bool &)
Definition: ber_dec.cpp:338
bool operator==(const OctetString &s1, const OctetString &s2)
Definition: symkey.cpp:98
void add_attribute(const std::string &, const std::string &)
Definition: x509_dn.cpp:47
DER_Encoder & end_cons()
Definition: der_enc.cpp:145
BER_Decoder start_cons(ASN1_Tag, ASN1_Tag=UNIVERSAL)
Definition: ber_dec.cpp:232
BER_Decoder & end_cons()
Definition: ber_dec.cpp:246
bool more_items() const
Definition: ber_dec.cpp:150
std::string lookup(const OID &oid)
Definition: oids.cpp:31
bool empty() const
Definition: secmem.h:35
ASN1_Tag
Definition: asn1_int.h:19
void encode_into(class DER_Encoder &) const
Definition: x509_dn.cpp:239
BER_Decoder & raw_bytes(MemoryRegion< byte > &)
Definition: ber_dec.cpp:170
BER_Decoder & verify_end()
Definition: ber_dec.cpp:160
bool BOTAN_DLL operator<(const X509_Time &, const X509_Time &)
Definition: asn1_tm.cpp:286
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:135
static std::string deref_info_field(const std::string &)
Definition: x509_dn.cpp:126
std::multimap< OID, std::string > get_attributes() const
Definition: x509_dn.cpp:76
std::multimap< std::string, std::string > contents() const
Definition: x509_dn.cpp:89
MemoryVector< byte > get_bits() const
Definition: x509_dn.cpp:118
void multimap_insert(std::multimap< K, V > &multimap, const K &key, const V &value)
Definition: stl_util.h:76
void decode_from(class BER_Decoder &)
Definition: x509_dn.cpp:264
OID oid
Definition: x509_ext.cpp:446