summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2003-03-24 17:04:44 +0000
committerDr. Stephen Henson <steve@openssl.org>2003-03-24 17:04:44 +0000
commit520b76ffd95cb27839471055fa4950ff9bf50be2 (patch)
tree5060348afed5bf7b4c5d5aac068ea9410f5cc69b
parent1c2d14123887c54b1a0111b3f2bcb75ec72f82ca (diff)
Support for name constraints.
-rw-r--r--CHANGES3
-rw-r--r--crypto/stack/safestack.h20
-rw-r--r--crypto/x509v3/Makefile.ssl4
-rw-r--r--crypto/x509v3/ext_dat.h4
-rw-r--r--crypto/x509v3/v3_alt.c171
-rw-r--r--crypto/x509v3/v3_info.c3
-rw-r--r--crypto/x509v3/v3_ncons.c220
-rw-r--r--crypto/x509v3/v3_utl.c80
-rw-r--r--crypto/x509v3/v3err.c2
-rw-r--r--crypto/x509v3/x509v3.h27
10 files changed, 449 insertions, 85 deletions
diff --git a/CHANGES b/CHANGES
index 1cea4962c9..719a7ff22b 100644
--- 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]
diff --git a/crypto/stack/safestack.h b/crypto/stack/safestack.h
index 6ffb132be6..ecb2b8ffed 100644
--- a/crypto/stack/safestack.h
+++ b/crypto/stack/safestack.h
@@ -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))
diff --git a/crypto/x509v3/Makefile.ssl b/crypto/x509v3/Makefile.ssl
index f719973feb..b7f1123fee 100644
--- a/crypto/x509v3/Makefile.ssl
+++ b/crypto/x509v3/Makefile.ssl
@@ -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)
diff --git a/crypto/x509v3/ext_dat.h b/crypto/x509v3/ext_dat.h
index 1e005c229c..0879ae5ddc 100644
--- a/crypto/x509v3/ext_dat.h
+++ b/crypto/x509v3/ext_dat.h
@@ -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 */
diff --git a/crypto/x509v3/v3_alt.c b/crypto/x509v3/v3_alt.c
index 8642dd5104..ad6cb08e20 100644
--- a/crypto/x509v3/v3_alt.c
+++ b/crypto/x509v3/v3_alt.c
@@ -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)
{
diff --git a/crypto/x509v3/v3_info.c b/crypto/x509v3/v3_info.c
index e269df1373..4e1a1f3a4d 100644
--- a/crypto/x509v3/v3_info.c
+++ b/crypto/x509v3/v3_info.c
@@ -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
index 0000000000..5fded6910e
--- /dev/null
+++ b/crypto/x509v3/v3_ncons.c
@@ -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;
+ }
+
diff --git a/crypto/x509v3/v3_utl.c b/crypto/x509v3/v3_utl.c
index 2af05e555b..9770b51677 100644
--- a/crypto/x509v3/v3_utl.c
+++ b/crypto/x509v3/v3_utl.c
@@ -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;
diff --git a/crypto/x509v3/v3err.c b/crypto/x509v3/v3err.c
index a4c8e59ef1..648ed3562c 100644
--- a/crypto/x509v3/v3err.c
+++ b/crypto/x509v3/v3err.c
@@ -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"},
diff --git a/crypto/x509v3/x509v3.h b/crypto/x509v3/x509v3.h
index 65c74cbff7..25b049bfbb 100644
--- a/crypto/x509v3/x509v3.h
+++ b/crypto/x509v3/x509v3.h
@@ -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