aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-11-14 14:03:16 -0500
committerJack Lloyd <[email protected]>2017-11-14 16:35:24 -0500
commit50ebb336e119eacfacd20c4b005295cac986cdf2 (patch)
treef45feddffad600bd4e1cd7e205abcd855495d0aa
parentcd7866e3ec00beff057228cf3fb87b72df02f88f (diff)
Fix PKCS10 subject alt name usage
GH #1010
-rw-r--r--src/lib/x509/asn1_alt_name.cpp9
-rw-r--r--src/lib/x509/asn1_alt_name.h2
-rw-r--r--src/lib/x509/pkcs10.cpp15
-rw-r--r--src/lib/x509/x509_dn.cpp7
-rw-r--r--src/tests/unit_x509.cpp5
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 */