The unified diff between revisions [372a601d..] and [6827a75e..] is displayed below. It can also be downloaded as a raw diff.

#
#
# delete "src/asn1_alt.cpp"
#
# patch "include/asn1_obj.h"
#  from [da21ba3ef127a710bbcf34fe370d4943a49f19cb]
#    to [04f21d256c29ada5850ba1949e4703e3c6555ade]
#
# patch "include/pkcs10.h"
#  from [2963efb4b97a36cdcd1bb51941ab613f9058ceaa]
#    to [398469ee9df0cba36e4fa7c63c856dde07922557]
#
# patch "include/x509_ext.h"
#  from [6bde07d391500117c5bf7f17f72aecab7386e1f4]
#    to [9840fbe4f54c1291f35962313f64840b6a8f83f9]
#
# patch "include/x509cert.h"
#  from [361b75d7368d02b0de174bc2ec5a9884b27954af]
#    to [c9b0fbda426eec1b4d27e2c51748ac17646b107e]
#
# patch "src/pkcs10.cpp"
#  from [9c89f3e653afd0c819a468514a81de9fd2c23079]
#    to [dd665c65ec6dd01924b86b0c4d70b4dceb098b3f]
#
# patch "src/x509_ca.cpp"
#  from [c490baee785765f71c2de35c8e0596b8b284a07e]
#    to [c37b08f714a799aab61fbfe8f05c73e00eb896f5]
#
# patch "src/x509_ext.cpp"
#  from [11ffbaf80379a237ed47a9ba13091db6e84ce95b]
#    to [0feccd15d55ce133280824414556e19eaa14eff6]
#
# patch "src/x509cert.cpp"
#  from [f0061d4c02f30534521000d90299395feff1172f]
#    to [8a8430a1e6eadb9d26a32220625fc391e66e88d7]
#
# patch "src/x509self.cpp"
#  from [91acdb2db0e5bc5b678bf758ca05bfc385604b9a]
#    to [74002c261547e29f63bdffceae55ccdf23385523]
#
============================================================
--- include/asn1_obj.h	da21ba3ef127a710bbcf34fe370d4943a49f19cb
+++ include/asn1_obj.h	04f21d256c29ada5850ba1949e4703e3c6555ade
@@ -110,32 +110,6 @@ class X509_DN : public ASN1_Object
    };

 /*************************************************
-* Alternative Name                               *
-*************************************************/
-class AlternativeName : public ASN1_Object
-   {
-   public:
-      void encode_into(class DER_Encoder&) const;
-      void decode_from(class BER_Decoder&);
-
-      std::multimap<std::string, std::string> contents() const;
-
-      void add_attribute(const std::string&, const std::string&);
-      std::multimap<std::string, std::string> get_attributes() const;
-
-      void add_othername(const OID&, const std::string&, ASN1_Tag);
-      std::multimap<OID, ASN1_String> get_othernames() const;
-
-      bool has_items() const;
-
-      AlternativeName(const std::string& = "", const std::string& = "",
-                      const std::string& = "", const std::string& = "");
-   private:
-      std::multimap<std::string, std::string> alt_info;
-      std::multimap<OID, ASN1_String> othernames;
-   };
-
-/*************************************************
 * Comparison Operations                          *
 *************************************************/
 bool operator==(const AlgorithmIdentifier&, const AlgorithmIdentifier&);
============================================================
--- include/pkcs10.h	2963efb4b97a36cdcd1bb51941ab613f9058ceaa
+++ include/pkcs10.h	398469ee9df0cba36e4fa7c63c856dde07922557
@@ -7,6 +7,7 @@
 #define BOTAN_PKCS10_H__

 #include <botan/x509_obj.h>
+#include <botan/x509_ext.h>
 #include <botan/pkcs8.h>
 #include <botan/datastor.h>
 #include <vector>
@@ -23,7 +24,8 @@ class PKCS10_Request : public X509_Objec

       MemoryVector<byte> raw_public_key() const;
       X509_DN subject_dn() const;
-      AlternativeName subject_alt_name() const;
+
+      Cert_Extension::Subject_Alternative_Name subject_alt_name() const;
       Key_Constraints constraints() const;
       std::vector<OID> ex_constraints() const;

@@ -38,6 +40,7 @@ class PKCS10_Request : public X509_Objec
       void force_decode();
       void handle_attribute(const Attribute&);

+      Extensions extensions;
       Data_Store info;
    };

============================================================
--- include/x509_ext.h	6bde07d391500117c5bf7f17f72aecab7386e1f4
+++ include/x509_ext.h	9840fbe4f54c1291f35962313f64840b6a8f83f9
@@ -53,11 +53,11 @@ class Extensions : public ASN1_Object
       Extensions& operator=(const Extensions& e)
          { return copy_this(e); }

+      Extensions& copy_this(const Extensions&);
       Extensions(bool st = true) : should_throw(st) {}
       Extensions(const Extensions& e) : ASN1_Object() { copy_this(e); }
       ~Extensions();
-   private:
-      Extensions& copy_this(const Extensions&);
+
       std::vector<Certificate_Extension*> extensions;
       bool should_throw;
    };
@@ -167,24 +167,25 @@ class Alternative_Name : public Certific
 class Alternative_Name : public Certificate_Extension
    {
    public:
-      AlternativeName get_alt_name() const { return alt_name; }
+      std::multimap<std::string, std::string> contents() const;

-   protected:
-      Alternative_Name(const AlternativeName&,
-                       const std::string&, const std::string&);
+      void add_attribute(const std::string&, const std::string&);
+      void add_othername(const OID&, const std::string&, ASN1_Tag);

-      Alternative_Name(const std::string&, const std::string&);
-   private:
-      std::string config_id() const { return config_name_str; }
-      std::string oid_name() const { return oid_name_str; }
+      std::multimap<std::string, std::string> get_attributes() const
+         { return alt_info; }
+      std::multimap<OID, ASN1_String> get_othernames() const
+         { return othernames; }

-      bool should_encode() const { return alt_name.has_items(); }
+      bool has_items() const
+         { return (!alt_info.empty() || !othernames.empty()); }
+   private:
+      bool should_encode() const { return has_items(); }
       MemoryVector<byte> encode_inner() const;
       void decode_inner(const MemoryRegion<byte>&);
-      void contents_to(Data_Store&, Data_Store&) const;

-      std::string config_name_str, oid_name_str;
-      AlternativeName alt_name;
+      std::multimap<std::string, std::string> alt_info;
+      std::multimap<OID, ASN1_String> othernames;
    };

 /*************************************************
@@ -194,9 +195,16 @@ class Subject_Alternative_Name : public
    {
    public:
       Subject_Alternative_Name* copy() const
-         { return new Subject_Alternative_Name(get_alt_name()); }
+         { return new Subject_Alternative_Name(*this); }

-      Subject_Alternative_Name(const AlternativeName& = AlternativeName());
+      Subject_Alternative_Name(const std::string& = "",
+                               const std::string& = "",
+                               const std::string& = "",
+                               const std::string& = "");
+   private:
+      std::string config_id() const { return "subject_alternative_name"; }
+      std::string oid_name() const { return "X509v3.SubjectAlternativeName"; }
+      void contents_to(Data_Store&, Data_Store&) const;
    };

 /*************************************************
@@ -206,9 +214,16 @@ class Issuer_Alternative_Name : public A
    {
    public:
       Issuer_Alternative_Name* copy() const
-         { return new Issuer_Alternative_Name(get_alt_name()); }
+         { return new Issuer_Alternative_Name(*this); }

-      Issuer_Alternative_Name(const AlternativeName& = AlternativeName());
+      Issuer_Alternative_Name(const std::string& = "",
+                              const std::string& = "",
+                              const std::string& = "",
+                              const std::string& = "");
+   private:
+      std::string config_id() const { return "issuer_alternative_name"; }
+      std::string oid_name() const { return "X509v3.IssuerAlternativeName"; }
+      void contents_to(Data_Store&, Data_Store&) const;
    };

 /*************************************************
============================================================
--- include/x509cert.h	361b75d7368d02b0de174bc2ec5a9884b27954af
+++ include/x509cert.h	c9b0fbda426eec1b4d27e2c51748ac17646b107e
@@ -65,7 +65,6 @@ X509_DN create_dn(const Data_Store&);
 * Data Store Extraction Operations               *
 *************************************************/
 X509_DN create_dn(const Data_Store&);
-AlternativeName create_alt_name(const Data_Store&);

 }

============================================================
--- src/pkcs10.cpp	9c89f3e653afd0c819a468514a81de9fd2c23079
+++ src/pkcs10.cpp	dd665c65ec6dd01924b86b0c4d70b4dceb098b3f
@@ -108,11 +108,10 @@ void PKCS10_Request::handle_attribute(co
       }
    else if(attr.oid == OIDS::lookup("PKCS9.ExtensionRequest"))
       {
-      Extensions extensions;
       value.decode(extensions).verify_end();

-      Data_Store issuer_info;
-      extensions.contents_to(info, issuer_info);
+      Data_Store unused_issuer_info;
+      extensions.contents_to(info, unused_issuer_info);
       }
    }

@@ -153,9 +152,58 @@ Public_Key* PKCS10_Request::subject_publ
 /*************************************************
 * Return the alternative names of the requestor  *
 *************************************************/
-AlternativeName PKCS10_Request::subject_alt_name() const
+Cert_Extension::Subject_Alternative_Name
+PKCS10_Request::subject_alt_name() const
    {
-   return create_alt_name(info);
+   std::vector<Certificate_Extensions*>::iterator i =
+      std::find_if(extensions.extensions.begin(),
+                   extensions.extensions.end(),
+                   std::bind2nd(std::equals<OID>(),
+                                OIDS::lookup("X509v3.SubjectAlternativeName")));
+
+   if(i != ext.end())
+      return j->
+      {
+      alt_name
+
+      }
+
+   Cert_Extension::Subject_Alternative_Name alt_name;
+   return alt_name;
+
+   class AltName_Matcher : public Data_Store::Matcher
+      {
+      public:
+         bool operator()(const std::string& key, const std::string&) const
+            {
+            for(u32bit j = 0; j != matches.size(); ++j)
+               if(key.compare(matches[j]) == 0)
+                  {
+                  printf("match for %s\n", key.c_str());
+                  return true;
+                  }
+            printf("no match for %s\n", key.c_str());
+            return false;
+            }
+
+         AltName_Matcher(const std::string& match_any_of)
+            {
+            matches = split_on(match_any_of, '/');
+            }
+      private:
+         std::vector<std::string> matches;
+      };
+
+   std::multimap<std::string, std::string> names =
+      info.search_with(AltName_Matcher("RFC822/DNS/URI/IP/PKIX.XMPPAddr"));
+
+   Cert_Extension::Subject_Alternative_Name alt_name;
+
+   std::multimap<std::string, std::string>::iterator j;
+   for(j = names.begin(); j != names.end(); ++j)
+      alt_name.add_attribute(j->first, j->second);
+
+   return alt_name;
    }

 /*************************************************
============================================================
--- src/x509_ca.cpp	c490baee785765f71c2de35c8e0596b8b284a07e
+++ src/x509_ca.cpp	c37b08f714a799aab61fbfe8f05c73e00eb896f5
@@ -57,24 +57,36 @@ X509_Certificate X509_CA::sign_request(c

    Extensions extensions;

-   extensions.add(new Cert_Extension::Authority_Key_ID(cert.subject_key_id()));
-   extensions.add(new Cert_Extension::Subject_Key_ID(req.raw_public_key()));
+   extensions.add(
+      new Cert_Extension::Authority_Key_ID(cert.subject_key_id())
+      );

    extensions.add(
-      new Cert_Extension::Basic_Constraints(req.is_CA(), req.path_limit()));
+      new Cert_Extension::Subject_Key_ID(req.raw_public_key())
+      );

-   extensions.add(new Cert_Extension::Key_Usage(constraints));
    extensions.add(
-      new Cert_Extension::Extended_Key_Usage(req.ex_constraints()));
+      new Cert_Extension::Basic_Constraints(req.is_CA(), req.path_limit())
+      );

    extensions.add(
-      new Cert_Extension::Subject_Alternative_Name(req.subject_alt_name()));
+      new Cert_Extension::Key_Usage(constraints)
+      );

-   /*
    extensions.add(
-      new Cert_Extension::Issuer_Alternative_Name(issuer_alt));
-   */
+      new Cert_Extension::Extended_Key_Usage(req.ex_constraints())
+      );

+   extensions.add(
+      new Cert_Extension::Subject_Alternative_Name(req.subject_alt_name())
+      );
+
+#if 0
+   extensions.add(
+      new Cert_Extension::Issuer_Alternative_Name(cert.subject_alt_name())
+      );
+#endif
+
    if(expire_time == 0)
       expire_time = global_config().option_as_time("x509/ca/default_expire");

============================================================
--- src/x509_ext.cpp	11ffbaf80379a237ed47a9ba13091db6e84ce95b
+++ src/x509_ext.cpp	0feccd15d55ce133280824414556e19eaa14eff6
@@ -9,9 +9,13 @@
 #include <botan/der_enc.h>
 #include <botan/ber_dec.h>
 #include <botan/lookup.h>
+#include <botan/parsing.h>
 #include <botan/oids.h>
 #include <botan/config.h>
 #include <botan/bit_ops.h>
+#include <botan/loadstor.h>
+#include <botan/stl_util.h>
+#include <botan/charset.h>
 #include <algorithm>
 #include <memory>

@@ -74,16 +78,20 @@ void Extensions::decode_from(BER_Decoder
    while(sequence.more_items())
       {
       OID oid;
-      MemoryVector<byte> value;
+      MemoryVector<byte> contents;
       bool critical;

       sequence.start_cons(SEQUENCE)
             .decode(oid)
             .decode_optional(critical, BOOLEAN, UNIVERSAL, false)
-            .decode(value, OCTET_STRING)
+            .decode(contents, OCTET_STRING)
             .verify_end()
          .end_cons();

+      printf("saw extension oid %s (%s)\n",
+             oid.as_string().c_str(),
+             OIDS::lookup(oid).c_str());
+
       Certificate_Extension* ext =
          global_state().x509_state().get_extension(oid);

@@ -96,7 +104,7 @@ void Extensions::decode_from(BER_Decoder
                               "as critical; OID = " + oid.as_string());
          }

-      ext->decode_inner(value);
+      ext->decode_inner(contents);

       extensions.push_back(ext);
       }
@@ -182,7 +190,7 @@ void Basic_Constraints::decode_inner(con
    }

 /*************************************************
-* Return a textual representation                *
+* Write the extensions to an info store          *
 *************************************************/
 void Basic_Constraints::contents_to(Data_Store& subject, Data_Store&) const
    {
@@ -240,7 +248,7 @@ void Key_Usage::decode_inner(const Memor
    }

 /*************************************************
-* Return a textual representation                *
+* Write the extensions to an info store          *
 *************************************************/
 void Key_Usage::contents_to(Data_Store& subject, Data_Store&) const
    {
@@ -264,7 +272,7 @@ void Subject_Key_ID::decode_inner(const
    }

 /*************************************************
-* Return a textual representation                *
+* Write the extensions to an info store          *
 *************************************************/
 void Subject_Key_ID::contents_to(Data_Store& subject, Data_Store&) const
    {
@@ -303,7 +311,7 @@ void Authority_Key_ID::decode_inner(cons
    }

 /*************************************************
-* Return a textual representation                *
+* Write the extensions to an info store          *
 *************************************************/
 void Authority_Key_ID::contents_to(Data_Store&, Data_Store& issuer) const
    {
@@ -311,12 +319,66 @@ void Authority_Key_ID::contents_to(Data_
       issuer.add("X509v3.AuthorityKeyIdentifier", key_id);
    }

+namespace {
+
 /*************************************************
+* DER encode an Alternative_Name entry           *
+*************************************************/
+void encode_entries(DER_Encoder& encoder,
+                    const std::multimap<std::string, std::string>& attr,
+                    const std::string& type, ASN1_Tag tagging)
+   {
+   typedef std::multimap<std::string, std::string>::const_iterator iter;
+
+   std::pair<iter, iter> range = attr.equal_range(type);
+   for(iter j = range.first; j != range.second; ++j)
+      {
+      printf("type = %s, 1=%s 2=%s", type.c_str(), j->first.c_str(), j->second.c_str());
+
+      if(type == "RFC822" || type == "DNS" || type == "URI")
+         {
+         ASN1_String asn1_string(j->second, IA5_STRING);
+         encoder.add_object(tagging, CONTEXT_SPECIFIC, asn1_string.iso_8859());
+         }
+      else if(type == "IP")
+         {
+         u32bit ip = string_to_ipv4(j->second);
+         byte ip_buf[4] = { 0 };
+         store_be(ip, ip_buf);
+         encoder.add_object(tagging, CONTEXT_SPECIFIC, ip_buf, 4);
+         }
+      }
+   }
+
+}
+
+/*************************************************
 * Encode the extension                           *
 *************************************************/
 MemoryVector<byte> Alternative_Name::encode_inner() const
    {
-   return DER_Encoder().encode(alt_name).get_contents();
+   DER_Encoder der;
+   der.start_cons(SEQUENCE);
+
+   encode_entries(der, alt_info, "RFC822", ASN1_Tag(1));
+   encode_entries(der, alt_info, "DNS", ASN1_Tag(2));
+   encode_entries(der, alt_info, "URI", ASN1_Tag(6));
+   encode_entries(der, alt_info, "IP", ASN1_Tag(7));
+
+   std::multimap<OID, ASN1_String>::const_iterator i;
+   for(i = othernames.begin(); i != othernames.end(); ++i)
+      {
+      der.start_explicit(0)
+         .encode(i->first)
+         .start_explicit(0)
+            .encode(i->second)
+         .end_explicit()
+      .end_explicit();
+      }
+
+   der.end_cons();
+
+   return der.get_contents();
    }

 /*************************************************
@@ -324,60 +386,176 @@ void Alternative_Name::decode_inner(cons
 *************************************************/
 void Alternative_Name::decode_inner(const MemoryRegion<byte>& in)
    {
-   BER_Decoder(in).decode(alt_name);
+   BER_Decoder source(in);
+
+   BER_Decoder names = source.start_cons(SEQUENCE);
+
+   while(names.more_items())
+      {
+      BER_Object obj = names.get_next_object();
+      if((obj.class_tag != CONTEXT_SPECIFIC) &&
+         (obj.class_tag != (CONTEXT_SPECIFIC | CONSTRUCTED)))
+         continue;
+
+      ASN1_Tag tag = obj.type_tag;
+
+      if(tag == 0)
+         {
+         BER_Decoder othername(obj.value);
+
+         OID oid;
+         othername.decode(oid);
+         if(othername.more_items())
+            {
+            BER_Object othername_value_outer = othername.get_next_object();
+            othername.verify_end();
+
+            if(othername_value_outer.type_tag != ASN1_Tag(0) ||
+               othername_value_outer.class_tag !=
+                   (CONTEXT_SPECIFIC | CONSTRUCTED)
+               )
+               throw Decoding_Error("Invalid tags on otherName value");
+
+            BER_Decoder othername_value_inner(othername_value_outer.value);
+
+            BER_Object value = othername_value_inner.get_next_object();
+            othername_value_inner.verify_end();
+
+            ASN1_Tag value_type = value.type_tag;
+
+            if(is_string_type(value_type) && value.class_tag == UNIVERSAL)
+               add_othername(oid, ASN1::to_string(value), value_type);
+            }
+         }
+      else if(tag == 1 || tag == 2 || tag == 6)
+         {
+         const std::string value = Charset::transcode(ASN1::to_string(obj),
+                                                      LATIN1_CHARSET,
+                                                      LOCAL_CHARSET);
+
+         printf("decoded tag = %d, value = %s\n", tag, value.c_str());
+
+         if(tag == 1) add_attribute("RFC822", value);
+         if(tag == 2) add_attribute("DNS", value);
+         if(tag == 6) add_attribute("URI", value);
+         }
+      else if(tag == 7)
+         {
+         if(obj.value.size() == 4)
+            {
+            u32bit ip = load_be<u32bit>(obj.value.begin(), 0);
+            add_attribute("IP", ipv4_to_string(ip));
+            }
+         }
+      }
    }

 /*************************************************
-* Return a textual representation                *
+* Add an attribute to an alternative name        *
 *************************************************/
-void Alternative_Name::contents_to(Data_Store& subject_info,
-                                   Data_Store& issuer_info) const
+void Alternative_Name::add_attribute(const std::string& type,
+                                     const std::string& str)
    {
-   std::multimap<std::string, std::string> contents =
-      get_alt_name().contents();
+   if(type == "" || str == "")
+      return;

-   if(oid_name_str == "X509v3.SubjectAlternativeName")
-      subject_info.add(contents);
-   else if(oid_name_str == "X509v3.IssuerAlternativeName")
-      issuer_info.add(contents);
-   else
-      throw Internal_Error("In Alternative_Name, unknown type " +
-                           oid_name_str);
+   typedef std::multimap<std::string, std::string>::iterator iter;
+   std::pair<iter, iter> range = alt_info.equal_range(type);
+   for(iter j = range.first; j != range.second; ++j)
+      if(j->second == str)
+         return;
+
+   printf("%p adding %s, %s\n", this, type.c_str(), str.c_str());
+   multimap_insert(alt_info, type, str);
    }

 /*************************************************
-* Alternative_Name Constructor                   *
+* Add an OtherName field                         *
 *************************************************/
-Alternative_Name::Alternative_Name(const AlternativeName& alt_name,
-                                   const std::string& oid_name_str,
-                                   const std::string& config_name_str)
+void Alternative_Name::add_othername(const OID& oid, const std::string& value,
+                                    ASN1_Tag type)
    {
-   this->alt_name = alt_name;
-   this->oid_name_str = oid_name_str;
-   this->config_name_str = config_name_str;
+   if(value != "")
+      multimap_insert(othernames, oid, ASN1_String(value, type));
    }

 /*************************************************
+* Return all of the alternative names            *
+*************************************************/
+std::multimap<std::string, std::string> Alternative_Name::contents() const
+   {
+   std::multimap<std::string, std::string> names;
+
+   typedef std::multimap<std::string, std::string>::const_iterator rdn_iter;
+   for(rdn_iter j = alt_info.begin(); j != alt_info.end(); ++j)
+      multimap_insert(names, j->first, j->second);
+
+   typedef std::multimap<OID, ASN1_String>::const_iterator on_iter;
+   for(on_iter j = othernames.begin(); j != othernames.end(); ++j)
+      multimap_insert(names, OIDS::lookup(j->first), j->second.value());
+
+   return names;
+   }
+
+/*************************************************
 * Subject_Alternative_Name Constructor           *
 *************************************************/
-Subject_Alternative_Name::Subject_Alternative_Name(
-   const AlternativeName& name) :
+Subject_Alternative_Name::Subject_Alternative_Name(const std::string& email,
+                                                   const std::string& uri,
+                                                   const std::string& dns,
+                                                   const std::string& ip)
+   {
+   add_attribute("RFC822", email);
+   add_attribute("DNS", dns);
+   add_attribute("URI", uri);
+   add_attribute("IP", ip);
+   }

-   Alternative_Name(name, "X509v3.SubjectAlternativeName",
-                    "subject_alternative_name")
+/*************************************************
+* Write the extensions to an info store          *
+*************************************************/
+void Subject_Alternative_Name::contents_to(Data_Store& subject_info,
+                                           Data_Store&) const
    {
+   printf("%p adding subject info contents to %p\n", this, &subject_info);
+
+   std::multimap<std::string, std::string> names = contents();
+   std::multimap<std::string, std::string>::iterator i = names.begin();
+   while(i != names.end())
+      {
+      printf("i->first = %s i->second = %s\n",
+             i->first.c_str(),
+             i->second.c_str());
+      ++i;
+      }
+   printf("done\n");
+
+   subject_info.add(contents());
    }

 /*************************************************
-* Issuer_Alternative_Name Constructor           *
+* Issuer_Alternative_Name Constructor            *
 *************************************************/
-Issuer_Alternative_Name::Issuer_Alternative_Name(const AlternativeName& name) :
-   Alternative_Name(name, "X509v3.IssuerAlternativeName",
-                    "issuer_alternative_name")
+Issuer_Alternative_Name::Issuer_Alternative_Name(const std::string& email,
+                                                 const std::string& uri,
+                                                 const std::string& dns,
+                                                 const std::string& ip)
    {
+   add_attribute("RFC822", email);
+   add_attribute("DNS", dns);
+   add_attribute("URI", uri);
+   add_attribute("IP", ip);
    }

 /*************************************************
+* Write the extensions to an info store          *
+*************************************************/
+void Issuer_Alternative_Name::contents_to(Data_Store&, Data_Store& issuer_info) const
+   {
+   issuer_info.add(contents());
+   }
+
+/*************************************************
 * Encode the extension                           *
 *************************************************/
 MemoryVector<byte> Extended_Key_Usage::encode_inner() const
@@ -401,7 +579,7 @@ void Extended_Key_Usage::decode_inner(co
    }

 /*************************************************
-* Return a textual representation                *
+* Write the extensions to an info store          *
 *************************************************/
 void Extended_Key_Usage::contents_to(Data_Store& subject, Data_Store&) const
    {
@@ -467,7 +645,7 @@ void Certificate_Policies::decode_inner(
    }

 /*************************************************
-* Return a textual representation                *
+* Write the extensions to an info store          *
 *************************************************/
 void Certificate_Policies::contents_to(Data_Store& info, Data_Store&) const
    {
@@ -512,11 +690,11 @@ void CRL_Number::decode_inner(const Memo
    }

 /*************************************************
-* Return a textual representation                *
+* Write the extensions to an info store          *
 *************************************************/
-void CRL_Number::contents_to(Data_Store& info, Data_Store&) const
+void CRL_Number::contents_to(Data_Store& subject_info, Data_Store&) const
    {
-   info.add("X509v3.CRLNumber", crl_number);
+   subject_info.add("X509v3.CRLNumber", crl_number);
    }

 /*************************************************
@@ -540,11 +718,11 @@ void CRL_ReasonCode::decode_inner(const
    }

 /*************************************************
-* Return a textual representation                *
+* Write the extensions to an info store          *
 *************************************************/
-void CRL_ReasonCode::contents_to(Data_Store& info, Data_Store&) const
+void CRL_ReasonCode::contents_to(Data_Store& subject_info, Data_Store&) const
    {
-   info.add("X509v3.CRLReasonCode", reason);
+   subject_info.add("X509v3.CRLReasonCode", reason);
    }

 }
============================================================
--- src/x509cert.cpp	f0061d4c02f30534521000d90299395feff1172f
+++ src/x509cert.cpp	8a8430a1e6eadb9d26a32220625fc391e66e88d7
@@ -325,40 +325,4 @@ X509_DN create_dn(const Data_Store& info
    return dn;
    }

-/*************************************************
-* Create and populate an AlternativeName         *
-*************************************************/
-AlternativeName create_alt_name(const Data_Store& info)
-   {
-   class AltName_Matcher : public Data_Store::Matcher
-      {
-      public:
-         bool operator()(const std::string& key, const std::string&) const
-            {
-            for(u32bit j = 0; j != matches.size(); ++j)
-               if(key.compare(matches[j]) == 0)
-                  return true;
-            return false;
-            }
-
-         AltName_Matcher(const std::string& match_any_of)
-            {
-            matches = split_on(match_any_of, '/');
-            }
-      private:
-         std::vector<std::string> matches;
-      };
-
-   std::multimap<std::string, std::string> names =
-      info.search_with(AltName_Matcher("RFC822/DNS/URI/IP"));
-
-   AlternativeName alt_name;
-
-   std::multimap<std::string, std::string>::iterator j;
-   for(j = names.begin(); j != names.end(); ++j)
-      alt_name.add_attribute(j->first, j->second);
-
-   return alt_name;
-   }
-
 }
============================================================
--- src/x509self.cpp	91acdb2db0e5bc5b678bf758ca05bfc385604b9a
+++ src/x509self.cpp	74002c261547e29f63bdffceae55ccdf23385523
@@ -37,24 +37,38 @@ MemoryVector<byte> shared_setup(const X5
    return key_encoder.read_all();
    }

-/*************************************************
-* Load information from the X509_Cert_Options    *
-*************************************************/
-void load_info(const X509_Cert_Options& opts, X509_DN& subject_dn,
-               AlternativeName& subject_alt)
+X509_DN make_dn(const X509_Cert_Options& opts)
    {
-   subject_dn.add_attribute("X520.CommonName", opts.common_name);
-   subject_dn.add_attribute("X520.Country", opts.country);
-   subject_dn.add_attribute("X520.State", opts.state);
-   subject_dn.add_attribute("X520.Locality", opts.locality);
-   subject_dn.add_attribute("X520.Organization", opts.organization);
-   subject_dn.add_attribute("X520.OrganizationalUnit", opts.org_unit);
-   subject_dn.add_attribute("X520.SerialNumber", opts.serial_number);
-   subject_alt = AlternativeName(opts.email, opts.uri, opts.dns, opts.ip);
-   subject_alt.add_othername(OIDS::lookup("PKIX.XMPPAddr"),
-                             opts.xmpp, UTF8_STRING);
+   X509_DN dn;
+
+   dn.add_attribute("X520.CommonName", opts.common_name);
+   dn.add_attribute("X520.Country", opts.country);
+   dn.add_attribute("X520.State", opts.state);
+   dn.add_attribute("X520.Locality", opts.locality);
+   dn.add_attribute("X520.Organization", opts.organization);
+   dn.add_attribute("X520.OrganizationalUnit", opts.org_unit);
+   dn.add_attribute("X520.SerialNumber", opts.serial_number);
+
+   return dn;
    }

+Cert_Extension::Subject_Alternative_Name*
+make_alt_name(const X509_Cert_Options& opts)
+   {
+   Cert_Extension::Subject_Alternative_Name* alt_name =
+      new Cert_Extension::Subject_Alternative_Name();
+
+   alt_name->add_attribute("RFC822", opts.email);
+   alt_name->add_attribute("DNS", opts.dns);
+   alt_name->add_attribute("URI", opts.uri);
+   alt_name->add_attribute("IP", opts.ip);
+
+   alt_name->add_othername(OIDS::lookup("PKIX.XMPPAddr"),
+                           opts.xmpp, UTF8_STRING);
+
+   return alt_name;
+   }
+
 }

 namespace X509 {
@@ -65,13 +79,9 @@ X509_Certificate create_self_signed_cert
 X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts,
                                          const Private_Key& key)
    {
-   AlgorithmIdentifier sig_algo;
-   X509_DN subject_dn;
-   AlternativeName subject_alt;
+   MemoryVector<byte> pub_key = shared_setup(opts, key);

-   MemoryVector<byte> pub_key = shared_setup(opts, key);
-   std::auto_ptr<PK_Signer> signer(choose_sig_format(key, sig_algo));
-   load_info(opts, subject_dn, subject_alt);
+   X509_DN subject_dn = make_dn(opts);

    Key_Constraints constraints;
    if(opts.is_CA)
@@ -85,11 +95,16 @@ X509_Certificate create_self_signed_cert
    extensions.add(new Cert_Extension::Key_Usage(constraints));
    extensions.add(
       new Cert_Extension::Extended_Key_Usage(opts.ex_constraints));
+
+   extensions.add(make_alt_name(opts));
+
    extensions.add(
-      new Cert_Extension::Subject_Alternative_Name(subject_alt));
-   extensions.add(
       new Cert_Extension::Basic_Constraints(opts.is_CA, opts.path_limit));

+   AlgorithmIdentifier sig_algo;
+
+   std::auto_ptr<PK_Signer> signer(choose_sig_format(key, sig_algo));
+
    return X509_CA::make_cert(signer.get(), sig_algo, pub_key,
                              opts.start, opts.end,
                              subject_dn, subject_dn,
@@ -102,13 +117,9 @@ PKCS10_Request create_cert_req(const X50
 PKCS10_Request create_cert_req(const X509_Cert_Options& opts,
                                const Private_Key& key)
    {
-   AlgorithmIdentifier sig_algo;
-   X509_DN subject_dn;
-   AlternativeName subject_alt;
+   MemoryVector<byte> pub_key = shared_setup(opts, key);

-   MemoryVector<byte> pub_key = shared_setup(opts, key);
-   std::auto_ptr<PK_Signer> signer(choose_sig_format(key, sig_algo));
-   load_info(opts, subject_dn, subject_alt);
+   X509_DN subject_dn = make_dn(opts);

    const u32bit PKCS10_VERSION = 0;

@@ -124,8 +135,7 @@ PKCS10_Request create_cert_req(const X50
       );
    extensions.add(
       new Cert_Extension::Extended_Key_Usage(opts.ex_constraints));
-   extensions.add(
-      new Cert_Extension::Subject_Alternative_Name(subject_alt));
+   extensions.add(make_alt_name(opts));

    DER_Encoder tbs_req;

@@ -158,6 +168,10 @@ PKCS10_Request create_cert_req(const X50
       .end_explicit()
       .end_cons();

+   AlgorithmIdentifier sig_algo;
+
+   std::auto_ptr<PK_Signer> signer(choose_sig_format(key, sig_algo));
+
    DataSource_Memory source(
       X509_Object::make_signed(signer.get(), sig_algo,
                                tbs_req.get_contents())