Botan
1.11.15
|
00001 /* 00002 * X509_DN 00003 * (C) 1999-2007 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/x509_dn.h> 00009 #include <botan/der_enc.h> 00010 #include <botan/ber_dec.h> 00011 #include <botan/parsing.h> 00012 #include <botan/internal/stl_util.h> 00013 #include <botan/oids.h> 00014 #include <ostream> 00015 00016 namespace Botan { 00017 00018 /* 00019 * Create an empty X509_DN 00020 */ 00021 X509_DN::X509_DN() 00022 { 00023 } 00024 00025 /* 00026 * Create an X509_DN 00027 */ 00028 X509_DN::X509_DN(const std::multimap<OID, std::string>& args) 00029 { 00030 for(auto i = args.begin(); i != args.end(); ++i) 00031 add_attribute(i->first, i->second); 00032 } 00033 00034 /* 00035 * Create an X509_DN 00036 */ 00037 X509_DN::X509_DN(const std::multimap<std::string, std::string>& args) 00038 { 00039 for(auto i = args.begin(); i != args.end(); ++i) 00040 add_attribute(OIDS::lookup(i->first), i->second); 00041 } 00042 00043 /* 00044 * Add an attribute to a X509_DN 00045 */ 00046 void X509_DN::add_attribute(const std::string& type, 00047 const std::string& str) 00048 { 00049 OID oid = OIDS::lookup(type); 00050 add_attribute(oid, str); 00051 } 00052 00053 /* 00054 * Add an attribute to a X509_DN 00055 */ 00056 void X509_DN::add_attribute(const OID& oid, const std::string& str) 00057 { 00058 if(str == "") 00059 return; 00060 00061 auto range = dn_info.equal_range(oid); 00062 for(auto i = range.first; i != range.second; ++i) 00063 if(i->second.value() == str) 00064 return; 00065 00066 multimap_insert(dn_info, oid, ASN1_String(str)); 00067 dn_bits.clear(); 00068 } 00069 00070 /* 00071 * Get the attributes of this X509_DN 00072 */ 00073 std::multimap<OID, std::string> X509_DN::get_attributes() const 00074 { 00075 std::multimap<OID, std::string> retval; 00076 for(auto i = dn_info.begin(); i != dn_info.end(); ++i) 00077 multimap_insert(retval, i->first, i->second.value()); 00078 return retval; 00079 } 00080 00081 /* 00082 * Get the contents of this X.500 Name 00083 */ 00084 std::multimap<std::string, std::string> X509_DN::contents() const 00085 { 00086 std::multimap<std::string, std::string> retval; 00087 for(auto i = dn_info.begin(); i != dn_info.end(); ++i) 00088 multimap_insert(retval, OIDS::lookup(i->first), i->second.value()); 00089 return retval; 00090 } 00091 00092 /* 00093 * Get a single attribute type 00094 */ 00095 std::vector<std::string> X509_DN::get_attribute(const std::string& attr) const 00096 { 00097 const OID oid = OIDS::lookup(deref_info_field(attr)); 00098 00099 auto range = dn_info.equal_range(oid); 00100 00101 std::vector<std::string> values; 00102 for(auto i = range.first; i != range.second; ++i) 00103 values.push_back(i->second.value()); 00104 return values; 00105 } 00106 00107 /* 00108 * Return the BER encoded data, if any 00109 */ 00110 std::vector<byte> X509_DN::get_bits() const 00111 { 00112 return dn_bits; 00113 } 00114 00115 /* 00116 * Deref aliases in a subject/issuer info request 00117 */ 00118 std::string X509_DN::deref_info_field(const std::string& info) 00119 { 00120 if(info == "Name" || info == "CommonName") return "X520.CommonName"; 00121 if(info == "SerialNumber") return "X520.SerialNumber"; 00122 if(info == "Country") return "X520.Country"; 00123 if(info == "Organization") return "X520.Organization"; 00124 if(info == "Organizational Unit" || info == "OrgUnit") 00125 return "X520.OrganizationalUnit"; 00126 if(info == "Locality") return "X520.Locality"; 00127 if(info == "State" || info == "Province") return "X520.State"; 00128 if(info == "Email") return "RFC822"; 00129 return info; 00130 } 00131 00132 /* 00133 * Compare two X509_DNs for equality 00134 */ 00135 bool operator==(const X509_DN& dn1, const X509_DN& dn2) 00136 { 00137 auto attr1 = dn1.get_attributes(); 00138 auto attr2 = dn2.get_attributes(); 00139 00140 if(attr1.size() != attr2.size()) return false; 00141 00142 auto p1 = attr1.begin(); 00143 auto p2 = attr2.begin(); 00144 00145 while(true) 00146 { 00147 if(p1 == attr1.end() && p2 == attr2.end()) 00148 break; 00149 if(p1 == attr1.end()) return false; 00150 if(p2 == attr2.end()) return false; 00151 if(p1->first != p2->first) return false; 00152 if(!x500_name_cmp(p1->second, p2->second)) 00153 return false; 00154 ++p1; 00155 ++p2; 00156 } 00157 return true; 00158 } 00159 00160 /* 00161 * Compare two X509_DNs for inequality 00162 */ 00163 bool operator!=(const X509_DN& dn1, const X509_DN& dn2) 00164 { 00165 return !(dn1 == dn2); 00166 } 00167 00168 /* 00169 * Induce an arbitrary ordering on DNs 00170 */ 00171 bool operator<(const X509_DN& dn1, const X509_DN& dn2) 00172 { 00173 auto attr1 = dn1.get_attributes(); 00174 auto attr2 = dn2.get_attributes(); 00175 00176 if(attr1.size() < attr2.size()) return true; 00177 if(attr1.size() > attr2.size()) return false; 00178 00179 for(auto p1 = attr1.begin(); p1 != attr1.end(); ++p1) 00180 { 00181 auto p2 = attr2.find(p1->first); 00182 if(p2 == attr2.end()) return false; 00183 if(p1->second > p2->second) return false; 00184 if(p1->second < p2->second) return true; 00185 } 00186 return false; 00187 } 00188 00189 namespace { 00190 00191 /* 00192 * DER encode a RelativeDistinguishedName 00193 */ 00194 void do_ava(DER_Encoder& encoder, 00195 const std::multimap<OID, std::string>& dn_info, 00196 ASN1_Tag string_type, const std::string& oid_str, 00197 bool must_exist = false) 00198 { 00199 const OID oid = OIDS::lookup(oid_str); 00200 const bool exists = (dn_info.find(oid) != dn_info.end()); 00201 00202 if(!exists && must_exist) 00203 throw Encoding_Error("X509_DN: No entry for " + oid_str); 00204 if(!exists) return; 00205 00206 auto range = dn_info.equal_range(oid); 00207 00208 for(auto i = range.first; i != range.second; ++i) 00209 { 00210 encoder.start_cons(SET) 00211 .start_cons(SEQUENCE) 00212 .encode(oid) 00213 .encode(ASN1_String(i->second, string_type)) 00214 .end_cons() 00215 .end_cons(); 00216 } 00217 } 00218 00219 } 00220 00221 /* 00222 * DER encode a DistinguishedName 00223 */ 00224 void X509_DN::encode_into(DER_Encoder& der) const 00225 { 00226 auto dn_info = get_attributes(); 00227 00228 der.start_cons(SEQUENCE); 00229 00230 if(!dn_bits.empty()) 00231 der.raw_bytes(dn_bits); 00232 else 00233 { 00234 do_ava(der, dn_info, PRINTABLE_STRING, "X520.Country"); 00235 do_ava(der, dn_info, DIRECTORY_STRING, "X520.State"); 00236 do_ava(der, dn_info, DIRECTORY_STRING, "X520.Locality"); 00237 do_ava(der, dn_info, DIRECTORY_STRING, "X520.Organization"); 00238 do_ava(der, dn_info, DIRECTORY_STRING, "X520.OrganizationalUnit"); 00239 do_ava(der, dn_info, DIRECTORY_STRING, "X520.CommonName"); 00240 do_ava(der, dn_info, PRINTABLE_STRING, "X520.SerialNumber"); 00241 } 00242 00243 der.end_cons(); 00244 } 00245 00246 /* 00247 * Decode a BER encoded DistinguishedName 00248 */ 00249 void X509_DN::decode_from(BER_Decoder& source) 00250 { 00251 std::vector<byte> bits; 00252 00253 source.start_cons(SEQUENCE) 00254 .raw_bytes(bits) 00255 .end_cons(); 00256 00257 BER_Decoder sequence(bits); 00258 00259 while(sequence.more_items()) 00260 { 00261 BER_Decoder rdn = sequence.start_cons(SET); 00262 00263 while(rdn.more_items()) 00264 { 00265 OID oid; 00266 ASN1_String str; 00267 00268 rdn.start_cons(SEQUENCE) 00269 .decode(oid) 00270 .decode(str) 00271 .verify_end() 00272 .end_cons(); 00273 00274 add_attribute(oid, str.value()); 00275 } 00276 } 00277 00278 dn_bits = bits; 00279 } 00280 00281 namespace { 00282 00283 std::string to_short_form(const std::string& long_id) 00284 { 00285 if(long_id == "X520.CommonName") 00286 return "CN"; 00287 00288 if(long_id == "X520.Organization") 00289 return "O"; 00290 00291 if(long_id == "X520.OrganizationalUnit") 00292 return "OU"; 00293 00294 return long_id; 00295 } 00296 00297 } 00298 00299 std::ostream& operator<<(std::ostream& out, const X509_DN& dn) 00300 { 00301 std::multimap<std::string, std::string> contents = dn.contents(); 00302 00303 for(std::multimap<std::string, std::string>::const_iterator i = contents.begin(); 00304 i != contents.end(); ++i) 00305 { 00306 out << to_short_form(i->first) << "=" << i->second << ' '; 00307 } 00308 return out; 00309 } 00310 00311 }