diff options
author | Jack Lloyd <[email protected]> | 2017-11-14 14:03:16 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-11-14 16:35:24 -0500 |
commit | 50ebb336e119eacfacd20c4b005295cac986cdf2 (patch) | |
tree | f45feddffad600bd4e1cd7e205abcd855495d0aa | |
parent | cd7866e3ec00beff057228cf3fb87b72df02f88f (diff) |
Fix PKCS10 subject alt name usage
GH #1010
-rw-r--r-- | src/lib/x509/asn1_alt_name.cpp | 9 | ||||
-rw-r--r-- | src/lib/x509/asn1_alt_name.h | 2 | ||||
-rw-r--r-- | src/lib/x509/pkcs10.cpp | 15 | ||||
-rw-r--r-- | src/lib/x509/x509_dn.cpp | 7 | ||||
-rw-r--r-- | src/tests/unit_x509.cpp | 5 |
5 files changed, 31 insertions, 7 deletions
diff --git a/src/lib/x509/asn1_alt_name.cpp b/src/lib/x509/asn1_alt_name.cpp index 8b3d2d6e9..04e11bbcd 100644 --- a/src/lib/x509/asn1_alt_name.cpp +++ b/src/lib/x509/asn1_alt_name.cpp @@ -98,6 +98,15 @@ bool AlternativeName::has_field(const std::string& attr) const return (range.first != range.second); } +std::string AlternativeName::get_first_attribute(const std::string& attr) const + { + auto i = m_alt_info.lower_bound(attr); + if(i != m_alt_info.end() && i->first == attr) + return i->second; + + return ""; + } + std::vector<std::string> AlternativeName::get_attribute(const std::string& attr) const { std::vector<std::string> results; diff --git a/src/lib/x509/asn1_alt_name.h b/src/lib/x509/asn1_alt_name.h index 81f933ea0..83ac215ba 100644 --- a/src/lib/x509/asn1_alt_name.h +++ b/src/lib/x509/asn1_alt_name.h @@ -29,6 +29,8 @@ class BOTAN_PUBLIC_API(2,0) AlternativeName final : public ASN1_Object bool has_field(const std::string& attr) const; std::vector<std::string> get_attribute(const std::string& attr) const; + std::string get_first_attribute(const std::string& attr) const; + void add_attribute(const std::string& type, const std::string& value); void add_othername(const OID& oid, const std::string& value, ASN1_Tag type); diff --git a/src/lib/x509/pkcs10.cpp b/src/lib/x509/pkcs10.cpp index cdcb5e985..82ef0945d 100644 --- a/src/lib/x509/pkcs10.cpp +++ b/src/lib/x509/pkcs10.cpp @@ -80,6 +80,8 @@ std::unique_ptr<PKCS10_Data> decode_pkcs10(const std::vector<uint8_t>& body) BER_Object attr_bits = cert_req_info.get_next_object(); + std::set<std::string> pkcs9_email; + if(attr_bits.type_tag == 0 && attr_bits.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) { @@ -94,7 +96,7 @@ std::unique_ptr<PKCS10_Data> decode_pkcs10(const std::vector<uint8_t>& body) { ASN1_String email; value.decode(email); - data->m_alt_name.add_attribute("RFC822", email.value()); + pkcs9_email.insert(email.value()); } else if(attr.oid == OIDS::lookup("PKCS9.ChallengePassword")) { @@ -115,9 +117,16 @@ std::unique_ptr<PKCS10_Data> decode_pkcs10(const std::vector<uint8_t>& body) cert_req_info.verify_end(); - // TODO pull AlternativeName out of extensions and merge with m_alt_name + if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::Subject_Alternative_Name>()) + { + data->m_alt_name = ext->get_alt_name(); + } + + for(std::string email : pkcs9_email) + { + data->m_alt_name.add_attribute("RFC882", email); + } - return data; } diff --git a/src/lib/x509/x509_dn.cpp b/src/lib/x509/x509_dn.cpp index e705fe74d..d07344aae 100644 --- a/src/lib/x509/x509_dn.cpp +++ b/src/lib/x509/x509_dn.cpp @@ -100,10 +100,9 @@ std::string X509_DN::get_first_attribute(const std::string& attr) const { const OID oid = OIDS::lookup(deref_info_field(attr)); - auto range = m_dn_info.equal_range(oid); - - if(range.first != m_dn_info.end()) - return range.first->second.value(); + auto i = m_dn_info.lower_bound(oid); + if(i != m_dn_info.end() && i->first == oid) + return i->second.value(); return ""; } diff --git a/src/tests/unit_x509.cpp b/src/tests/unit_x509.cpp index da60348c8..d2156cf60 100644 --- a/src/tests/unit_x509.cpp +++ b/src/tests/unit_x509.cpp @@ -538,6 +538,11 @@ Test::Result test_x509_cert(const std::string& sig_algo, const std::string& hash result.test_eq("issuer info Orga", user1_issuer_dn.get_first_attribute("O"), ca_opts().organization); result.test_eq("issuer info OrgaUnit", user1_issuer_dn.get_first_attribute("OU"), ca_opts().org_unit); + const Botan::AlternativeName& user1_altname = user1_cert.subject_alt_name(); + result.test_eq("subject alt email", user1_altname.get_first_attribute("RFC822"), "[email protected]"); + result.test_eq("subject alt email", user1_altname.get_first_attribute("DNS"), "botan.randombit.net"); + result.test_eq("subject alt email", user1_altname.get_first_attribute("URI"), "https://botan.randombit.net"); + const Botan::X509_CRL crl1 = ca.new_crl(Test::rng()); /* Verify the certs */ |