diff options
author | lloyd <[email protected]> | 2006-05-18 18:33:19 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2006-05-18 18:33:19 +0000 |
commit | a2c99d3270eb73ef2db5704fc54356c6b75096f8 (patch) | |
tree | ad3d6c4fcc8dd0f403f8105598943616246fe172 /src/asn1_dn.cpp |
Initial checkin1.5.6
Diffstat (limited to 'src/asn1_dn.cpp')
-rw-r--r-- | src/asn1_dn.cpp | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/src/asn1_dn.cpp b/src/asn1_dn.cpp new file mode 100644 index 000000000..22ce980f6 --- /dev/null +++ b/src/asn1_dn.cpp @@ -0,0 +1,285 @@ +/************************************************* +* X509_DN Source File * +* (C) 1999-2006 The Botan Project * +*************************************************/ + +#include <botan/asn1_obj.h> +#include <botan/parsing.h> +#include <botan/stl_util.h> +#include <botan/oids.h> + +namespace Botan { + +/************************************************* +* Create an empty X509_DN * +*************************************************/ +X509_DN::X509_DN() + { + } + +/************************************************* +* Create an X509_DN * +*************************************************/ +X509_DN::X509_DN(const std::multimap<OID, std::string>& args) + { + std::multimap<OID, std::string>::const_iterator j; + for(j = args.begin(); j != args.end(); ++j) + add_attribute(j->first, j->second); + } + +/************************************************* +* Create an X509_DN * +*************************************************/ +X509_DN::X509_DN(const std::multimap<std::string, std::string>& args) + { + std::multimap<std::string, std::string>::const_iterator j; + for(j = args.begin(); j != args.end(); ++j) + add_attribute(OIDS::lookup(j->first), j->second); + } + +/************************************************* +* Add an attribute to a X509_DN * +*************************************************/ +void X509_DN::add_attribute(const std::string& type, + const std::string& str) + { + OID oid = OIDS::lookup(type); + add_attribute(oid, str); + } + +/************************************************* +* Add an attribute to a X509_DN * +*************************************************/ +void X509_DN::add_attribute(const OID& oid, const std::string& str) + { + if(str == "") + return; + + typedef std::multimap<OID, ASN1_String>::iterator rdn_iter; + + std::pair<rdn_iter, rdn_iter> range = dn_info.equal_range(oid); + for(rdn_iter j = range.first; j != range.second; ++j) + if(j->second.value() == str) + return; + + multimap_insert(dn_info, oid, ASN1_String(str)); + dn_bits.destroy(); + } + +/************************************************* +* Get the attributes of this X509_DN * +*************************************************/ +std::multimap<OID, std::string> X509_DN::get_attributes() const + { + typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter; + + std::multimap<OID, std::string> retval; + for(rdn_iter j = dn_info.begin(); j != dn_info.end(); ++j) + multimap_insert(retval, j->first, j->second.value()); + return retval; + } + +/************************************************* +* Get a single attribute type * +*************************************************/ +std::vector<std::string> X509_DN::get_attribute(const std::string& attr) const + { + typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter; + + const OID oid = OIDS::lookup(deref_info_field(attr)); + std::pair<rdn_iter, rdn_iter> range = dn_info.equal_range(oid); + + std::vector<std::string> values; + for(rdn_iter j = range.first; j != range.second; ++j) + values.push_back(j->second.value()); + return values; + } + +/************************************************* +* Handle the decoding operation of a DN * +*************************************************/ +void X509_DN::do_decode(const MemoryRegion<byte>& bits) + { + BER_Decoder sequence(bits); + + while(sequence.more_items()) + { + BER_Decoder rdn = BER::get_subset(sequence); + while(rdn.more_items()) + { + OID oid; + ASN1_String str; + + BER_Decoder ava = BER::get_subsequence(rdn); + BER::decode(ava, oid); + BER::decode(ava, str); + ava.verify_end(); + + add_attribute(oid, str.value()); + } + } + + dn_bits = bits; + } + +/************************************************* +* Return the BER encoded data, if any * +*************************************************/ +SecureVector<byte> X509_DN::get_bits() const + { + return dn_bits; + } + +/************************************************* +* Deref aliases in a subject/issuer info request * +*************************************************/ +std::string X509_DN::deref_info_field(const std::string& info) + { + if(info == "Name" || info == "CommonName") return "X520.CommonName"; + if(info == "SerialNumber") return "X520.SerialNumber"; + if(info == "Country") return "X520.Country"; + if(info == "Organization") return "X520.Organization"; + if(info == "Organizational Unit") return "X520.OrganizationalUnit"; + if(info == "Locality") return "X520.Locality"; + if(info == "State" || info == "Province") return "X520.State"; + if(info == "Email") return "RFC822"; + return info; + } + +/************************************************* +* Compare two X509_DNs for equality * +*************************************************/ +bool operator==(const X509_DN& dn1, const X509_DN& dn2) + { + typedef std::multimap<OID, std::string>::const_iterator rdn_iter; + + std::multimap<OID, std::string> attr1 = dn1.get_attributes(); + std::multimap<OID, std::string> attr2 = dn2.get_attributes(); + + if(attr1.size() != attr2.size()) return false; + + rdn_iter p1 = attr1.begin(); + rdn_iter p2 = attr2.begin(); + + while(true) + { + if(p1 == attr1.end() && p2 == attr2.end()) + break; + if(p1 == attr1.end()) return false; + if(p2 == attr2.end()) return false; + if(p1->first != p2->first) return false; + if(!x500_name_cmp(p1->second, p2->second)) + return false; + ++p1; + ++p2; + } + return true; + } + +/************************************************* +* Compare two X509_DNs for inequality * +*************************************************/ +bool operator!=(const X509_DN& dn1, const X509_DN& dn2) + { + return !(dn1 == dn2); + } + +/************************************************* +* Compare two X509_DNs * +*************************************************/ +bool operator<(const X509_DN& dn1, const X509_DN& dn2) + { + typedef std::multimap<OID, std::string>::const_iterator rdn_iter; + + std::multimap<OID, std::string> attr1 = dn1.get_attributes(); + std::multimap<OID, std::string> attr2 = dn2.get_attributes(); + + if(attr1.size() < attr2.size()) return true; + if(attr1.size() > attr2.size()) return false; + + for(rdn_iter p1 = attr1.begin(); p1 != attr1.end(); ++p1) + { + std::multimap<OID, std::string>::const_iterator p2; + p2 = attr2.find(p1->first); + if(p2 == attr2.end()) return false; + if(p1->second > p2->second) return false; + if(p1->second < p2->second) return true; + } + return false; + } + +namespace { + +/************************************************* +* DER encode a RelativeDistinguishedName * +*************************************************/ +void do_ava(DER_Encoder& encoder, + const std::multimap<OID, std::string>& dn_info, + ASN1_Tag string_type, const std::string& oid_str, + bool must_exist = false) + { + typedef std::multimap<OID, std::string>::const_iterator rdn_iter; + + const OID oid = OIDS::lookup(oid_str); + const bool exists = (dn_info.find(oid) != dn_info.end()); + + if(!exists && must_exist) + throw Encoding_Error("X509_DN: No entry for " + oid_str); + if(!exists) return; + + std::pair<rdn_iter, rdn_iter> range = dn_info.equal_range(oid); + + for(rdn_iter j = range.first; j != range.second; ++j) + { + encoder.start_set() + .start_sequence() + .encode(oid) + .encode(ASN1_String(j->second, string_type)) + .end_sequence() + .end_set(); + } + } + +} + +/************************************************* +* DER encode a DistinguishedName * +*************************************************/ +void X509_DN::encode_into(DER_Encoder& der) const + { + std::multimap<OID, std::string> dn_info = get_attributes(); + + der.start_sequence(); + + if(dn_bits.has_items()) + der.add_raw_octets(dn_bits); + else + { + do_ava(der, dn_info, PRINTABLE_STRING, "X520.Country", true); + do_ava(der, dn_info, DIRECTORY_STRING, "X520.State"); + do_ava(der, dn_info, DIRECTORY_STRING, "X520.Locality"); + do_ava(der, dn_info, DIRECTORY_STRING, "X520.Organization"); + do_ava(der, dn_info, DIRECTORY_STRING, "X520.OrganizationalUnit"); + do_ava(der, dn_info, DIRECTORY_STRING, "X520.CommonName", true); + do_ava(der, dn_info, PRINTABLE_STRING, "X520.SerialNumber"); + } + + der.end_sequence(); + } + +namespace BER { + +/************************************************* +* Decode a BER encoded DistinguishedName * +*************************************************/ +void decode(BER_Decoder& source, X509_DN& dn) + { + dn = X509_DN(); + BER_Decoder sequence = BER::get_subsequence(source); + SecureVector<byte> bits = sequence.get_remaining(); + dn.do_decode(bits); + } + +} + +} |