Support for name constraints.
authorDr. Stephen Henson <steve@openssl.org>
Mon, 24 Mar 2003 17:04:44 +0000 (17:04 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 24 Mar 2003 17:04:44 +0000 (17:04 +0000)
CHANGES
crypto/stack/safestack.h
crypto/x509v3/Makefile.ssl
crypto/x509v3/ext_dat.h
crypto/x509v3/v3_alt.c
crypto/x509v3/v3_info.c
crypto/x509v3/v3_ncons.c [new file with mode: 0644]
crypto/x509v3/v3_utl.c
crypto/x509v3/v3err.c
crypto/x509v3/x509v3.h

diff --git a/CHANGES b/CHANGES
index 1cea496..719a7ff 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,9 @@
 
  Changes between 0.9.7a and 0.9.8  [xx XXX xxxx]
 
+  *) Support for nameConstraints certificate extension.
+     [Steve Henson]
+
   *) Support for policyConstraints certificate extension.
      [Steve Henson]
 
index 6ffb132..ecb2b8f 100644 (file)
@@ -544,6 +544,26 @@ STACK_OF(type) \
 #define sk_GENERAL_NAME_pop(st) SKM_sk_pop(GENERAL_NAME, (st))
 #define sk_GENERAL_NAME_sort(st) SKM_sk_sort(GENERAL_NAME, (st))
 
+#define sk_GENERAL_SUBTREE_new(st) SKM_sk_new(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_new_null() SKM_sk_new_null(GENERAL_SUBTREE)
+#define sk_GENERAL_SUBTREE_free(st) SKM_sk_free(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_num(st) SKM_sk_num(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_value(st, i) SKM_sk_value(GENERAL_SUBTREE, (st), (i))
+#define sk_GENERAL_SUBTREE_set(st, i, val) SKM_sk_set(GENERAL_SUBTREE, (st), (i), (val))
+#define sk_GENERAL_SUBTREE_zero(st) SKM_sk_zero(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_push(st, val) SKM_sk_push(GENERAL_SUBTREE, (st), (val))
+#define sk_GENERAL_SUBTREE_unshift(st, val) SKM_sk_unshift(GENERAL_SUBTREE, (st), (val))
+#define sk_GENERAL_SUBTREE_find(st, val) SKM_sk_find(GENERAL_SUBTREE, (st), (val))
+#define sk_GENERAL_SUBTREE_delete(st, i) SKM_sk_delete(GENERAL_SUBTREE, (st), (i))
+#define sk_GENERAL_SUBTREE_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_SUBTREE, (st), (ptr))
+#define sk_GENERAL_SUBTREE_insert(st, val, i) SKM_sk_insert(GENERAL_SUBTREE, (st), (val), (i))
+#define sk_GENERAL_SUBTREE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_SUBTREE, (st), (cmp))
+#define sk_GENERAL_SUBTREE_dup(st) SKM_sk_dup(GENERAL_SUBTREE, st)
+#define sk_GENERAL_SUBTREE_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_SUBTREE, (st), (free_func))
+#define sk_GENERAL_SUBTREE_shift(st) SKM_sk_shift(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_pop(st) SKM_sk_pop(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_sort(st) SKM_sk_sort(GENERAL_SUBTREE, (st))
+
 #define sk_KRB5_APREQBODY_new(st) SKM_sk_new(KRB5_APREQBODY, (st))
 #define sk_KRB5_APREQBODY_new_null() SKM_sk_new_null(KRB5_APREQBODY)
 #define sk_KRB5_APREQBODY_free(st) SKM_sk_free(KRB5_APREQBODY, (st))
index f719973..b7f1123 100644 (file)
@@ -26,11 +26,11 @@ LIB=$(TOP)/libcrypto.a
 LIBSRC=        v3_bcons.c v3_bitst.c v3_conf.c v3_extku.c v3_ia5.c v3_lib.c \
 v3_prn.c v3_utl.c v3err.c v3_genn.c v3_alt.c v3_skey.c v3_akey.c v3_pku.c \
 v3_int.c v3_enum.c v3_sxnet.c v3_cpols.c v3_crld.c v3_purp.c v3_info.c \
-v3_ocsp.c v3_akeya.c v3_pmaps.c v3_pcons.c
+v3_ocsp.c v3_akeya.c v3_pmaps.c v3_pcons.c v3_ncons.c
 LIBOBJ= v3_bcons.o v3_bitst.o v3_conf.o v3_extku.o v3_ia5.o v3_lib.o \
 v3_prn.o v3_utl.o v3err.o v3_genn.o v3_alt.o v3_skey.o v3_akey.o v3_pku.o \
 v3_int.o v3_enum.o v3_sxnet.o v3_cpols.o v3_crld.o v3_purp.o v3_info.o \
-v3_ocsp.o v3_akeya.o v3_pmaps.o v3_pcons.o
+v3_ocsp.o v3_akeya.o v3_pmaps.o v3_pcons.o v3_ncons.o
 
 SRC= $(LIBSRC)
 
index 1e005c2..0879ae5 100644 (file)
@@ -65,6 +65,7 @@ extern X509V3_EXT_METHOD v3_ocsp_nonce, v3_ocsp_accresp, v3_ocsp_acutoff;
 extern X509V3_EXT_METHOD v3_ocsp_crlid, v3_ocsp_nocheck, v3_ocsp_serviceloc;
 extern X509V3_EXT_METHOD v3_crl_hold;
 extern X509V3_EXT_METHOD v3_policy_mappings, v3_policy_constraints;
+extern X509V3_EXT_METHOD v3_name_constraints;
 
 /* This table will be searched using OBJ_bsearch so it *must* kept in
  * order of the ext_nid values.
@@ -109,7 +110,8 @@ static X509V3_EXT_METHOD *standard_exts[] = {
 #ifndef OPENSSL_NO_OCSP
 &v3_crl_hold,
 #endif
-&v3_policy_mappings
+&v3_policy_mappings,
+&v3_name_constraints
 };
 
 /* Number of standard extensions */
index 8642dd5..ad6cb08 100644 (file)
@@ -407,89 +407,126 @@ GENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method,
 
 GENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
                                                         CONF_VALUE *cnf)
-{
-char is_string = 0;
-int type;
-GENERAL_NAME *gen = NULL;
+       {
+       return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
+       }
 
-char *name, *value;
+GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
+                               X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+                                                CONF_VALUE *cnf, int is_nc)
+       {
+       char is_string = 0;
+       int type;
+       GENERAL_NAME *gen = NULL;
 
-name = cnf->name;
-value = cnf->value;
+       char *name, *value;
 
-if(!value) {
-       X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_MISSING_VALUE);
-       return NULL;
-}
+       name = cnf->name;
+       value = cnf->value;
 
-if(!(gen = GENERAL_NAME_new())) {
-       X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE);
-       return NULL;
-}
+       if(!value)
+               {
+               X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_MISSING_VALUE);
+               return NULL;
+               }
 
-if(!name_cmp(name, "email")) {
-       is_string = 1;
-       type = GEN_EMAIL;
-} else if(!name_cmp(name, "URI")) {
-       is_string = 1;
-       type = GEN_URI;
-} else if(!name_cmp(name, "DNS")) {
-       is_string = 1;
-       type = GEN_DNS;
-} else if(!name_cmp(name, "RID")) {
-       ASN1_OBJECT *obj;
-       if(!(obj = OBJ_txt2obj(value,0))) {
-               X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_OBJECT);
-               ERR_add_error_data(2, "value=", value);
-               goto err;
-       }
-       gen->d.rid = obj;
-       type = GEN_RID;
-} else if(!name_cmp(name, "IP")) {
-       if(!(gen->d.ip = a2i_IPADDRESS(value)))
+       if (out)
+               gen = out;
+       else
                {
-               X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_IP_ADDRESS);
-               ERR_add_error_data(2, "value=", value);
-               goto err;
+               gen = GENERAL_NAME_new();
+               if(gen == NULL)
+                       {
+                       X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE);
+                       return NULL;
+                       }
                }
-       type = GEN_IPADD;
-} else if(!name_cmp(name, "dirName")) {
-       type = GEN_DIRNAME;
-       if (!do_dirname(gen, value, ctx))
+
+       if(!name_cmp(name, "email"))
                {
-               X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_DIRNAME_ERROR);
-               goto err;
+               is_string = 1;
+               type = GEN_EMAIL;
+               }
+       else if(!name_cmp(name, "URI"))
+               {
+               is_string = 1;
+               type = GEN_URI;
+               }
+       else if(!name_cmp(name, "DNS"))
+               {
+               is_string = 1;
+               type = GEN_DNS;
+               }
+       else if(!name_cmp(name, "RID"))
+               {
+               ASN1_OBJECT *obj;
+               if(!(obj = OBJ_txt2obj(value,0)))
+                       {
+                       X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_OBJECT);
+                       ERR_add_error_data(2, "value=", value);
+                       goto err;
+                       }
+               gen->d.rid = obj;
+               type = GEN_RID;
+               }
+       else if(!name_cmp(name, "IP"))
+               {
+               if (is_nc)
+                       gen->d.ip = a2i_IPADDRESS_NC(value);
+               else
+                       gen->d.ip = a2i_IPADDRESS(value);
+               if(gen->d.ip == NULL)
+                       {
+                       X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_IP_ADDRESS);
+                       ERR_add_error_data(2, "value=", value);
+                       goto err;
+                       }
+               type = GEN_IPADD;
+               }
+       else if(!name_cmp(name, "dirName"))
+               {
+               type = GEN_DIRNAME;
+               if (!do_dirname(gen, value, ctx))
+                       {
+                       X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_DIRNAME_ERROR);
+                       goto err;
+                       }
+               }
+       else if(!name_cmp(name, "otherName"))
+               {
+               if (!do_othername(gen, value, ctx))
+                       {
+                       X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_OTHERNAME_ERROR);
+                       goto err;
+                       }
+               type = GEN_OTHERNAME;
                }
-} else if(!name_cmp(name, "otherName")) {
-       if (!do_othername(gen, value, ctx))
+       else
                {
-               X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_OTHERNAME_ERROR);
+               X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_UNSUPPORTED_OPTION);
+               ERR_add_error_data(2, "name=", name);
                goto err;
                }
-       type = GEN_OTHERNAME;
-} else {
-       X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_UNSUPPORTED_OPTION);
-       ERR_add_error_data(2, "name=", name);
-       goto err;
-}
 
-if(is_string) {
-       if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
-                     !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value,
-                                      strlen(value))) {
-               X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE);
-               goto err;
-       }
-}
+       if(is_string)
+               {
+               if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
+                             !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value,
+                                              strlen(value)))
+                       {
+                       X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE);
+                       goto err;
+                       }
+               }
 
-gen->type = type;
+       gen->type = type;
 
-return gen;
+       return gen;
 
-err:
-GENERAL_NAME_free(gen);
-return NULL;
-}
+       err:
+       GENERAL_NAME_free(gen);
+       return NULL;
+       }
 
 static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
        {
index e269df1..4e1a1f3 100644 (file)
@@ -158,8 +158,7 @@ static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *metho
                objlen = ptmp - cnf->name;
                ctmp.name = ptmp + 1;
                ctmp.value = cnf->value;
-               GENERAL_NAME_free(acc->location);
-               if(!(acc->location = v2i_GENERAL_NAME(method, ctx, &ctmp)))
+               if(!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0))
                                                                 goto err; 
                if(!(objtmp = OPENSSL_malloc(objlen + 1))) {
                        X509V3err(X509V3_F_V2I_ACCESS_DESCRIPTION,ERR_R_MALLOC_FAILURE);
diff --git a/crypto/x509v3/v3_ncons.c b/crypto/x509v3/v3_ncons.c
new file mode 100644 (file)
index 0000000..5fded69
--- /dev/null
@@ -0,0 +1,220 @@
+/* v3_ncons.c */
+/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2003 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+
+#include <stdio.h>
+#include "cryptlib.h"
+#include <openssl/asn1t.h>
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+
+static void *v2i_NAME_CONSTRAINTS(X509V3_EXT_METHOD *method,
+                               X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+static int i2r_NAME_CONSTRAINTS(X509V3_EXT_METHOD *method, 
+                               void *a, BIO *bp, int ind);
+static int do_i2r_name_constraints(X509V3_EXT_METHOD *method,
+                               STACK_OF(GENERAL_SUBTREE) *trees,
+                                       BIO *bp, int ind, char *name);
+static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip);
+
+X509V3_EXT_METHOD v3_name_constraints = {
+       NID_name_constraints, 0,
+       ASN1_ITEM_ref(NAME_CONSTRAINTS),
+       0,0,0,0,
+       0,0,
+       0, v2i_NAME_CONSTRAINTS,
+       i2r_NAME_CONSTRAINTS,0,
+       NULL
+};
+
+ASN1_SEQUENCE(GENERAL_SUBTREE) = {
+       ASN1_SIMPLE(GENERAL_SUBTREE, base, GENERAL_NAME),
+       ASN1_IMP_OPT(GENERAL_SUBTREE, minimum, ASN1_INTEGER, 0),
+       ASN1_IMP_OPT(GENERAL_SUBTREE, maximum, ASN1_INTEGER, 1)
+} ASN1_SEQUENCE_END(GENERAL_SUBTREE)
+
+ASN1_SEQUENCE(NAME_CONSTRAINTS) = {
+       ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, permittedSubtrees,
+                                                       GENERAL_SUBTREE, 0),
+       ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, excludedSubtrees,
+                                                       GENERAL_SUBTREE, 1),
+} ASN1_SEQUENCE_END(NAME_CONSTRAINTS)
+       
+
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
+
+static void *v2i_NAME_CONSTRAINTS(X509V3_EXT_METHOD *method,
+                               X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+       {
+       int i;
+       CONF_VALUE tval, *val;
+       STACK_OF(GENERAL_SUBTREE) **ptree = NULL;
+       NAME_CONSTRAINTS *ncons = NULL;
+       GENERAL_SUBTREE *sub = NULL;
+       ncons = NAME_CONSTRAINTS_new();
+       if (!ncons)
+               goto memerr;
+       for(i = 0; i < sk_CONF_VALUE_num(nval); i++)
+               {
+               val = sk_CONF_VALUE_value(nval, i);
+               if (!strncmp(val->name, "permitted", 9) && val->name[9])
+                       {
+                       ptree = &ncons->permittedSubtrees;
+                       tval.name = val->name + 10;
+                       }
+               else if (!strncmp(val->name, "excluded", 8) && val->name[8])
+                       {
+                       ptree = &ncons->excludedSubtrees;
+                       tval.name = val->name + 9;
+                       }
+               else
+                       {
+                       X509V3err(X509V3_F_V2I_NAME_CONSTRAINTS, X509V3_R_INVALID_SYNTAX);
+                       goto err;
+                       }
+               tval.value = val->value;
+               sub = GENERAL_SUBTREE_new();
+               if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1))
+                       goto err;
+               if (!*ptree)
+                       *ptree = sk_GENERAL_SUBTREE_new_null();
+               if (!*ptree || !sk_GENERAL_SUBTREE_push(*ptree, sub))
+                       goto memerr;
+               sub = NULL;
+               }
+
+       return ncons;
+
+       memerr:
+       X509V3err(X509V3_F_V2I_NAME_CONSTRAINTS, ERR_R_MALLOC_FAILURE);
+       err:
+       if (ncons)
+               NAME_CONSTRAINTS_free(ncons);
+       if (sub)
+               GENERAL_SUBTREE_free(sub);
+
+       return NULL;
+       }
+                       
+
+       
+
+static int i2r_NAME_CONSTRAINTS(X509V3_EXT_METHOD *method,
+                               void *a, BIO *bp, int ind)
+       {
+       NAME_CONSTRAINTS *ncons = a;
+       do_i2r_name_constraints(method, ncons->permittedSubtrees,
+                                       bp, ind, "Permitted");
+       do_i2r_name_constraints(method, ncons->excludedSubtrees,
+                                       bp, ind, "Excluded");
+       return 1;
+       }
+
+static int do_i2r_name_constraints(X509V3_EXT_METHOD *method,
+                               STACK_OF(GENERAL_SUBTREE) *trees,
+                                       BIO *bp, int ind, char *name)
+       {
+       GENERAL_SUBTREE *tree;
+       int i;
+       if (sk_GENERAL_SUBTREE_num(trees) > 0)
+               BIO_printf(bp, "%*s%s:\n", ind, "", name);
+       for(i = 0; i < sk_GENERAL_SUBTREE_num(trees); i++)
+               {
+               tree = sk_GENERAL_SUBTREE_value(trees, i);
+               BIO_printf(bp, "%*s", ind + 2, "");
+               if (tree->base->type == GEN_IPADD)
+                       print_nc_ipadd(bp, tree->base->d.ip);
+               else
+                       GENERAL_NAME_print(bp, tree->base);
+               tree = sk_GENERAL_SUBTREE_value(trees, i);
+               BIO_puts(bp, "\n");
+               }
+       return 1;
+       }
+
+static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip)
+       {
+       int i, len;
+       unsigned char *p;
+       p = ip->data;
+       len = ip->length;
+       BIO_puts(bp, "IP:");
+       if(len == 8)
+               {
+               BIO_printf(bp, "%d.%d.%d.%d/%d.%d.%d.%d",
+                               p[0], p[1], p[2], p[3],
+                               p[4], p[5], p[6], p[7]);
+               }
+       else if(len == 32)
+               {
+               for (i = 0; i < 16; i++)
+                       {
+                       BIO_printf(bp, "%X", p[0] << 8 | p[1]);
+                       p += 2;
+                       if (i == 7)
+                               BIO_puts(bp, "/");
+                       else if (i != 15)
+                               BIO_puts(bp, ":");
+                       }
+               }
+       else
+               BIO_printf(bp, "IP Address:<invalid>");
+       return 1;
+       }
+
index 2af05e5..9770b51 100644 (file)
@@ -70,6 +70,7 @@ static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens);
 static void str_free(void *str);
 static int append_ia5(STACK **sk, ASN1_IA5STRING *email);
 
+static int a2i_ipadd(unsigned char *ipout, const char *ipasc);
 static int ipv4_from_asc(unsigned char *v4, const char *in);
 static int ipv6_from_asc(unsigned char *v6, const char *in);
 static int ipv6_cb(const char *elem, int len, void *usr);
@@ -552,18 +553,10 @@ ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
 
        /* If string contains a ':' assume IPv6 */
 
-       if (strchr(ipasc, ':'))
-               {
-               if (!ipv6_from_asc(ipout, ipasc))
-                       return NULL;
-               iplen = 16;
-               }
-       else
-               {
-               if (!ipv4_from_asc(ipout, ipasc))
-                       return NULL;
-               iplen = 4;
-               }
+       iplen = a2i_ipadd(ipout, ipasc);
+
+       if (!iplen)
+               return NULL;
 
        ret = ASN1_OCTET_STRING_new();
        if (!ret)
@@ -576,6 +569,69 @@ ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
        return ret;
        }
 
+ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
+       {
+       ASN1_OCTET_STRING *ret = NULL;
+       unsigned char ipout[32];
+       char *iptmp = NULL, *p;
+       int iplen1, iplen2;
+       p = strchr(ipasc,'/');
+       if (!p)
+               return NULL;
+       iptmp = BUF_strdup(ipasc);
+       if (!iptmp)
+               return NULL;
+       p = iptmp + (p - ipasc);
+       *p++ = 0;
+
+       iplen1 = a2i_ipadd(ipout, iptmp);
+
+       if (!iplen1)
+               goto err;
+
+       iplen2 = a2i_ipadd(ipout + iplen1, p);
+
+       OPENSSL_free(iptmp);
+       iptmp = NULL;
+
+       if (!iplen2 || (iplen1 != iplen2))
+               goto err;
+
+       ret = ASN1_OCTET_STRING_new();
+       if (!ret)
+               goto err;
+       if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
+               goto err;
+
+       return ret;
+
+       err:
+       if (iptmp)
+               OPENSSL_free(iptmp);
+       if (ret)
+               ASN1_OCTET_STRING_free(ret);
+       return NULL;
+       }
+       
+
+static int a2i_ipadd(unsigned char *ipout, const char *ipasc)
+       {
+       /* If string contains a ':' assume IPv6 */
+
+       if (strchr(ipasc, ':'))
+               {
+               if (!ipv6_from_asc(ipout, ipasc))
+                       return 0;
+               return 16;
+               }
+       else
+               {
+               if (!ipv4_from_asc(ipout, ipasc))
+                       return 0;
+               return 4;
+               }
+       }
+
 static int ipv4_from_asc(unsigned char *v4, const char *in)
        {
        int a0, a1, a2, a3;
index a4c8e59..648ed35 100644 (file)
@@ -71,6 +71,7 @@ static ERR_STRING_DATA X509V3_str_functs[]=
 {ERR_PACK(0,X509V3_F_DO_DIRNAME,0),    "DO_DIRNAME"},
 {ERR_PACK(0,X509V3_F_DO_EXT_CONF,0),   "DO_EXT_CONF"},
 {ERR_PACK(0,X509V3_F_DO_EXT_I2D,0),    "DO_EXT_I2D"},
+{ERR_PACK(0,X509V3_F_DO_I2V_NAME_CONSTRAINTS,0),       "DO_I2V_NAME_CONSTRAINTS"},
 {ERR_PACK(0,X509V3_F_HEX_TO_STRING,0), "hex_to_string"},
 {ERR_PACK(0,X509V3_F_I2S_ASN1_ENUMERATED,0),   "i2s_ASN1_ENUMERATED"},
 {ERR_PACK(0,X509V3_F_I2S_ASN1_INTEGER,0),      "i2s_ASN1_INTEGER"},
@@ -98,6 +99,7 @@ static ERR_STRING_DATA X509V3_str_functs[]=
 {ERR_PACK(0,X509V3_F_V2I_EXT_KU,0),    "V2I_EXT_KU"},
 {ERR_PACK(0,X509V3_F_V2I_GENERAL_NAME,0),      "v2i_GENERAL_NAME"},
 {ERR_PACK(0,X509V3_F_V2I_GENERAL_NAMES,0),     "v2i_GENERAL_NAMES"},
+{ERR_PACK(0,X509V3_F_V2I_NAME_CONSTRAINTS,0),  "V2I_NAME_CONSTRAINTS"},
 {ERR_PACK(0,X509V3_F_V2I_POLICY_CONSTRAINTS,0),        "V2I_POLICY_CONSTRAINTS"},
 {ERR_PACK(0,X509V3_F_V2I_POLICY_MAPPINGS,0),   "V2I_POLICY_MAPPINGS"},
 {ERR_PACK(0,X509V3_F_V3_GENERIC_EXTENSION,0),  "V3_GENERIC_EXTENSION"},
index 65c74cb..25b049b 100644 (file)
@@ -295,6 +295,19 @@ DECLARE_STACK_OF(POLICY_MAPPING)
 
 typedef STACK_OF(POLICY_MAPPING) POLICY_MAPPINGS;
 
+typedef struct GENERAL_SUBTREE_st {
+       GENERAL_NAME *base;
+       ASN1_INTEGER *minimum;
+       ASN1_INTEGER *maximum;
+} GENERAL_SUBTREE;
+
+DECLARE_STACK_OF(GENERAL_SUBTREE)
+
+typedef struct NAME_CONSTRAINTS_st {
+       STACK_OF(GENERAL_SUBTREE) *permittedSubtrees;
+       STACK_OF(GENERAL_SUBTREE) *excludedSubtrees;
+} NAME_CONSTRAINTS;
+
 typedef struct POLICY_CONSTRAINTS_st {
        ASN1_INTEGER *requireExplicitPolicy;
        ASN1_INTEGER *inhibitPolicyMapping;
@@ -473,11 +486,20 @@ DECLARE_ASN1_ITEM(POLICY_MAPPING)
 DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING)
 DECLARE_ASN1_ITEM(POLICY_MAPPINGS)
 
+DECLARE_ASN1_ITEM(GENERAL_SUBTREE)
+DECLARE_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
+
+DECLARE_ASN1_ITEM(NAME_CONSTRAINTS)
+DECLARE_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
+
 DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS)
 DECLARE_ASN1_ITEM(POLICY_CONSTRAINTS)
 
 #ifdef HEADER_CONF_H
-GENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, CONF_VALUE *cnf);
+GENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+                                                       CONF_VALUE *cnf);
+GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, X509V3_EXT_METHOD *method,
+                               X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc);
 void X509V3_conf_free(CONF_VALUE *val);
 
 X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, char *value);
@@ -569,6 +591,7 @@ STACK *X509_REQ_get1_email(X509_REQ *x);
 void X509_email_free(STACK *sk);
 
 ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc);
+ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc);
 int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
                                                unsigned long chtype);
 
@@ -586,6 +609,7 @@ void ERR_load_X509V3_strings(void);
 #define X509V3_F_DO_DIRNAME                             144
 #define X509V3_F_DO_EXT_CONF                            124
 #define X509V3_F_DO_EXT_I2D                             135
+#define X509V3_F_DO_I2V_NAME_CONSTRAINTS                148
 #define X509V3_F_HEX_TO_STRING                          111
 #define X509V3_F_I2S_ASN1_ENUMERATED                    121
 #define X509V3_F_I2S_ASN1_INTEGER                       120
@@ -613,6 +637,7 @@ void ERR_load_X509V3_strings(void);
 #define X509V3_F_V2I_EXT_KU                             103
 #define X509V3_F_V2I_GENERAL_NAME                       117
 #define X509V3_F_V2I_GENERAL_NAMES                      118
+#define X509V3_F_V2I_NAME_CONSTRAINTS                   147
 #define X509V3_F_V2I_POLICY_CONSTRAINTS                         146
 #define X509V3_F_V2I_POLICY_MAPPINGS                    145
 #define X509V3_F_V3_GENERIC_EXTENSION                   116