summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libgnutls.map2
-rw-r--r--lib/x509/name_constraints.c214
-rw-r--r--lib/x509/x509_ext.c61
-rw-r--r--lib/x509/x509_int.h3
-rw-r--r--tests/Makefile.am10
-rw-r--r--tests/name-constraints-merge.c260
-rw-r--r--tests/test-chains.h87
7 files changed, 602 insertions, 35 deletions
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 4cccd3525a..1f266bc9d9 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1135,4 +1135,6 @@ GNUTLS_PRIVATE_3_4 {
_gnutls_bin2hex;
_gnutls_mac_to_entry;
_gnutls_resolve_priorities;
+ # Internal symbols needed by tests/name-constraints-merge:
+ _gnutls_x509_name_constraints_merge;
};
diff --git a/lib/x509/name_constraints.c b/lib/x509/name_constraints.c
index ca57561347..3c0c63cf2d 100644
--- a/lib/x509/name_constraints.c
+++ b/lib/x509/name_constraints.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2014 Free Software Foundation, Inc.
+ * Copyright (C) 2014-2016 Free Software Foundation, Inc.
+ * Copyright (C) 2016 Red Hat, Inc.
*
* This file is part of GnuTLS.
*
@@ -35,6 +36,9 @@
/* Name constraints is limited to DNS names.
*/
+static int name_constraints_match(name_constraints_node_st * nc1,
+ name_constraints_node_st * nc2);
+
static unsigned is_nc_empty(struct gnutls_name_constraints_st* nc, unsigned type)
{
name_constraints_node_st *t;
@@ -128,6 +132,128 @@ int _gnutls_extract_name_constraints(ASN1_TYPE c2, const char *vstr,
return ret;
}
+void
+_gnutls_name_constraints_node_free(name_constraints_node_st *node)
+{
+ name_constraints_node_st *next, *t;
+
+ t = node;
+ while (t != NULL) {
+ next = t->next;
+ gnutls_free(t->name.data);
+ gnutls_free(t);
+ t = next;
+ }
+}
+
+static
+int _gnutls_name_constraints_intersect(name_constraints_node_st ** _nc,
+ name_constraints_node_st * _nc2)
+{
+ name_constraints_node_st *nc, *nc2, *t, *dest = NULL, *prev = NULL;
+ int ret;
+
+ if (*_nc == NULL || _nc2 == NULL)
+ return 0;
+
+ /* For each name in _NC, if a _NC2 does not contain a name
+ * with the same type, preserve the original name. */
+ t = nc = *_nc;
+ while (t != NULL) {
+ name_constraints_node_st *next = t->next;
+ nc2 = _nc2;
+ while (nc2 != NULL) {
+ if (t->type == nc2->type)
+ break;
+ nc2 = nc2->next;
+ }
+ if (nc2 == NULL) {
+ /* move node from NC to DEST */
+ if (prev != NULL)
+ prev->next = next;
+ else
+ prev = nc = next;
+ t->next = dest;
+ dest = t;
+ } else {
+ prev = t;
+ }
+ t = next;
+ }
+
+ nc2 = _nc2;
+ while (nc2 != NULL) {
+ t = nc;
+ while (t != NULL) {
+ struct name_constraints_node_st *tmp;
+
+ if (!name_constraints_match(t, nc2)) {
+ t = t->next;
+ continue;
+ }
+
+ /* copy node at NC2 to DEST */
+ tmp = gnutls_malloc(sizeof(struct name_constraints_node_st));
+ if (tmp == NULL) {
+ _gnutls_name_constraints_node_free(dest);
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ }
+
+ tmp->type = nc2->type;
+ ret = _gnutls_set_datum(&tmp->name, nc2->name.data, nc2->name.size);
+ if (ret < 0) {
+ _gnutls_name_constraints_node_free(dest);
+ return gnutls_assert_val(ret);
+ }
+
+ tmp->next = dest;
+ dest = tmp;
+ t = t->next;
+ }
+ nc2 = nc2->next;
+ }
+
+ /* replace the original with the new */
+ _gnutls_name_constraints_node_free(nc);
+ *_nc = dest;
+ return 0;
+}
+
+static
+int _gnutls_name_constraints_append(name_constraints_node_st ** _nc,
+ name_constraints_node_st * _nc2)
+{
+ name_constraints_node_st *nc, *nc2;
+ struct name_constraints_node_st *tmp;
+ int ret;
+
+ if (_nc2 == NULL)
+ return 0;
+
+ nc2 = _nc2;
+ while (nc2) {
+ nc = *_nc;
+
+ tmp = gnutls_malloc(sizeof(struct name_constraints_node_st));
+ if (tmp == NULL) {
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ }
+
+ tmp->type = nc2->type;
+ ret = _gnutls_set_datum(&tmp->name, nc2->name.data, nc2->name.size);
+ if (ret < 0) {
+ return gnutls_assert_val(ret);
+ }
+
+ tmp->next = nc;
+ *_nc = tmp;
+
+ nc2 = nc2->next;
+ }
+
+ return 0;
+}
+
/**
* gnutls_x509_crt_get_name_constraints:
* @crt: should contain a #gnutls_x509_crt_t type
@@ -140,11 +266,13 @@ int _gnutls_extract_name_constraints(ASN1_TYPE c2, const char *vstr,
* structure can be used in combination with gnutls_x509_name_constraints_check()
* to verify whether a server's name is in accordance with the constraints.
*
- * When the @flags is set to %GNUTLS_NAME_CONSTRAINTS_FLAG_APPEND, then if
- * the @nc structure is empty
- * this function will behave identically as if the flag was not set.
- * Otherwise if there are elements in the @nc structure then only the
- * excluded constraints will be appended to the constraints.
+ * When the @flags is set to %GNUTLS_NAME_CONSTRAINTS_FLAG_APPEND,
+ * then if the @nc structure is empty this function will behave
+ * identically as if the flag was not set.
+ * Otherwise if there are elements in the @nc structure then the
+ * constraints will be merged with the existing constraints following
+ * RFC5280 p6.1.4 (excluded constraints will be appended, permitted
+ * will be intersected).
*
* Note that @nc must be initialized prior to calling this function.
*
@@ -200,23 +328,9 @@ int gnutls_x509_crt_get_name_constraints(gnutls_x509_crt_t crt,
**/
void gnutls_x509_name_constraints_deinit(gnutls_x509_name_constraints_t nc)
{
- name_constraints_node_st * next, *t;
-
- t = nc->permitted;
- while (t != NULL) {
- next = t->next;
- gnutls_free(t->name.data);
- gnutls_free(t);
- t = next;
- }
+ _gnutls_name_constraints_node_free(nc->permitted);
+ _gnutls_name_constraints_node_free(nc->excluded);
- t = nc->excluded;
- while (t != NULL) {
- next = t->next;
- gnutls_free(t->name.data);
- gnutls_free(t);
- t = next;
- }
gnutls_free(nc);
}
@@ -289,6 +403,46 @@ int name_constraints_add(gnutls_x509_name_constraints_t nc,
return 0;
}
+/*-
+ * _gnutls_x509_name_constraints_merge:
+ * @nc: The nameconstraints
+ * @nc2: The name constraints to be merged with
+ *
+ * This function will merge the provided name constraints structures
+ * as per RFC5280 p6.1.4. That is, the excluded constraints will be appended,
+ * and permitted will be intersected. The intersection assumes that @nc
+ * is the root CA constraints.
+ *
+ * The merged constraints will be placed in @nc.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
+ *
+ * Since: 3.5.0
+ -*/
+int _gnutls_x509_name_constraints_merge(gnutls_x509_name_constraints_t nc,
+ gnutls_x509_name_constraints_t nc2)
+{
+ int ret;
+
+ ret =
+ _gnutls_name_constraints_intersect(&nc->permitted,
+ nc2->permitted);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ ret =
+ _gnutls_name_constraints_append(&nc->excluded,
+ nc2->excluded);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ return 0;
+}
+
/**
* gnutls_x509_name_constraints_add_permitted:
* @nc: The nameconstraints
@@ -433,6 +587,22 @@ static unsigned email_matches(const gnutls_datum_t *name, const gnutls_datum_t *
return email_ends_with(name, suffix);
}
+static int
+name_constraints_match(name_constraints_node_st * nc1,
+ name_constraints_node_st * nc2)
+{
+ if (nc1->type != nc2->type)
+ return 0;
+ switch (nc1->type) {
+ case GNUTLS_SAN_DNSNAME:
+ return dnsname_matches(&nc2->name, &nc1->name);
+ case GNUTLS_SAN_RFC822NAME:
+ return email_matches(&nc2->name, &nc1->name);
+ default:
+ return 0;
+ }
+}
+
static
unsigned check_unsupported_constraint(gnutls_x509_name_constraints_t nc,
gnutls_x509_subject_alt_name_t type)
diff --git a/lib/x509/x509_ext.c b/lib/x509/x509_ext.c
index e16bf403b5..0933047145 100644
--- a/lib/x509/x509_ext.c
+++ b/lib/x509/x509_ext.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2014 Free Software Foundation
+ * Copyright (C) 2014-2016 Free Software Foundation, Inc.
+ * Copyright (C) 2016 Red Hat, Inc.
*
* This file is part of GnuTLS.
*
@@ -348,8 +349,10 @@ int gnutls_x509_ext_export_subject_alt_names(gnutls_subject_alt_names_t sans,
*
* When the @flags is set to %GNUTLS_NAME_CONSTRAINTS_FLAG_APPEND, then if
* the @nc type is empty this function will behave identically as if the flag was not set.
- * Otherwise if there are elements in the @nc type then only the
- * excluded constraints will be appended to the constraints.
+ * Otherwise if there are elements in the @nc structure then the
+ * constraints will be merged with the existing constraints following
+ * RFC5280 p6.1.4 (excluded constraints will be appended, permitted
+ * will be intersected).
*
* Note that @nc must be initialized prior to calling this function.
*
@@ -364,6 +367,7 @@ int gnutls_x509_ext_import_name_constraints(const gnutls_datum_t * ext,
{
int result, ret;
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+ gnutls_x509_name_constraints_t nc2 = NULL;
result = asn1_create_element
(_gnutls_get_pkix(), "PKIX1.NameConstraints", &c2);
@@ -379,8 +383,39 @@ int gnutls_x509_ext_import_name_constraints(const gnutls_datum_t * ext,
goto cleanup;
}
- if (!(flags & GNUTLS_NAME_CONSTRAINTS_FLAG_APPEND)
- || (nc->permitted == NULL && nc->excluded == NULL)) {
+ if (flags & GNUTLS_NAME_CONSTRAINTS_FLAG_APPEND &&
+ (nc->permitted != NULL || nc->excluded != NULL)) {
+ ret = gnutls_x509_name_constraints_init (&nc2);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret =
+ _gnutls_extract_name_constraints(c2, "permittedSubtrees",
+ &nc2->permitted);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret =
+ _gnutls_extract_name_constraints(c2, "excludedSubtrees",
+ &nc2->excluded);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = _gnutls_x509_name_constraints_merge(nc, nc2);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+ } else {
+ _gnutls_name_constraints_node_free(nc->permitted);
+ _gnutls_name_constraints_node_free(nc->excluded);
+
ret =
_gnutls_extract_name_constraints(c2, "permittedSubtrees",
&nc->permitted);
@@ -388,20 +423,22 @@ int gnutls_x509_ext_import_name_constraints(const gnutls_datum_t * ext,
gnutls_assert();
goto cleanup;
}
- }
- ret =
- _gnutls_extract_name_constraints(c2, "excludedSubtrees",
- &nc->excluded);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
+ ret =
+ _gnutls_extract_name_constraints(c2, "excludedSubtrees",
+ &nc->excluded);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
}
ret = 0;
cleanup:
asn1_delete_structure(&c2);
+ if (nc2)
+ gnutls_x509_name_constraints_deinit (nc2);
return ret;
}
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
index 3fce6ee7b9..782365d8c4 100644
--- a/lib/x509/x509_int.h
+++ b/lib/x509/x509_int.h
@@ -474,6 +474,9 @@ typedef struct name_constraints_node_st {
int _gnutls_extract_name_constraints(ASN1_TYPE c2, const char *vstr,
name_constraints_node_st ** _nc);
+void _gnutls_name_constraints_node_free (name_constraints_node_st *node);
+int _gnutls_x509_name_constraints_merge(gnutls_x509_name_constraints_t nc,
+ gnutls_x509_name_constraints_t nc2);
void _gnutls_x509_policies_erase(gnutls_x509_policies_t policies, unsigned int seq);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 7e96317173..432c1d54bc 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -98,7 +98,7 @@ ctests = mini-record-2 simple gc set_pkcs12_cred certder certuniqueid \
dtls-max-record tls-max-record alpn-server-prec ocsp-filename-memleak \
dh-params rehandshake-ext-secret pcert-list session-export-funcs \
handshake-false-start version-checks key-material-dtls key-material-set-dtls \
- system-prio-file
+ system-prio-file name-constraints-merge
if HAVE_SECCOMP_TESTS
ctests += dtls-with-seccomp tls-with-seccomp dtls-client-with-seccomp tls-client-with-seccomp
@@ -170,6 +170,14 @@ pkcs12_s2k_CPPFLAGS = $(CPPFLAGS) \
-I$(top_srcdir)/gl \
-I$(top_builddir)/gl
+name_constraints_merge_CPPFLAGS = $(CPPFLAGS) \
+ -I$(top_srcdir)/lib/includes \
+ -I$(top_builddir)/lib/includes \
+ -I$(top_srcdir)/lib/minitasn1 \
+ -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/gl \
+ -I$(top_builddir)/gl
+
check_PROGRAMS = $(ctests)
dist_check_SCRIPTS = rfc2253-escape-test
diff --git a/tests/name-constraints-merge.c b/tests/name-constraints-merge.c
new file mode 100644
index 0000000000..167b8aaebb
--- /dev/null
+++ b/tests/name-constraints-merge.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GnuTLS; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/* Parts copied from GnuTLS example programs. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "../lib/gnutls_int.h"
+#include "../lib/x509/x509_int.h"
+
+#include "utils.h"
+
+/* Test for name constraints PKIX extension.
+ */
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "<%d>| %s", level, str);
+}
+
+/* deny */
+const gnutls_datum_t example_com = { (void*)"example.com", sizeof("example.com")-1 };
+const gnutls_datum_t example_net = { (void*)"example.net", sizeof("example.net")-1 };
+
+/* allowed */
+const gnutls_datum_t org = { (void*)"org", sizeof("org")-1 };
+const gnutls_datum_t ccc_com = { (void*)"ccc.com", sizeof("ccc.com")-1 };
+const gnutls_datum_t aaa_bbb_ccc_com = { (void*)"aaa.bbb.ccc.com", sizeof("aaa.bbb.ccc.com")-1 };
+
+void doit(void)
+{
+ int ret;
+ gnutls_x509_name_constraints_t nc;
+ gnutls_x509_name_constraints_t nc2;
+ gnutls_datum_t name;
+
+ /* this must be called once in the program
+ */
+ global_init();
+
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(6);
+
+ /* 0: test the merge permitted */
+
+ ret = gnutls_x509_name_constraints_init(&nc);
+ if (ret < 0)
+ fail("error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+
+ ret = gnutls_x509_name_constraints_init(&nc2);
+ if (ret < 0)
+ fail("error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+
+
+ /* nc: dnsName: .org + ccc.com, rfc822Name: ccc.com */
+ ret = gnutls_x509_name_constraints_add_permitted(nc, GNUTLS_SAN_DNSNAME,
+ &org);
+ if (ret < 0)
+ fail("error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+
+ ret = gnutls_x509_name_constraints_add_permitted(nc, GNUTLS_SAN_DNSNAME,
+ &ccc_com);
+ if (ret < 0)
+ fail("error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+
+ ret = gnutls_x509_name_constraints_add_permitted(nc, GNUTLS_SAN_RFC822NAME,
+ &ccc_com);
+ if (ret < 0)
+ fail("error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+
+ /* nc2: dnsName: .org + aaa.bbb.ccc.com */
+ ret = gnutls_x509_name_constraints_add_permitted(nc2, GNUTLS_SAN_DNSNAME,
+ &org);
+ if (ret < 0)
+ fail("error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+
+ ret = gnutls_x509_name_constraints_add_permitted(nc2, GNUTLS_SAN_DNSNAME,
+ &aaa_bbb_ccc_com);
+ if (ret < 0)
+ fail("error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+
+ /* intersection: permit: aaa.bbb.ccc.com */
+ ret = _gnutls_x509_name_constraints_merge(nc, nc2);
+ if (ret < 0)
+ fail("error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+
+
+ /* unrelated */
+ name.data = (unsigned char*)"xxx.example.com";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
+ if (ret != 0)
+ fail("Checking domain should have failed\n");
+
+ name.data = (unsigned char*)"example.org";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
+ if (ret == 0)
+ fail("Checking %s should have succeeded\n", name.data);
+
+ name.data = (unsigned char*)"com";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
+ if (ret != 0)
+ fail("Checking %s should have failed\n", name.data);
+
+ name.data = (unsigned char*)"xxx.com";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
+ if (ret != 0)
+ fail("Checking %s should have failed\n", name.data);
+
+ name.data = (unsigned char*)"ccc.com";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
+ if (ret != 0)
+ fail("Checking %s should have failed\n", name.data);
+
+
+ /* check intersection of permitted */
+ name.data = (unsigned char*)"xxx.aaa.bbb.ccc.com";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
+ if (ret == 0)
+ fail("Checking %s should have succeeded\n", name.data);
+
+ name.data = (unsigned char*)"aaa.bbb.ccc.com";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
+ if (ret == 0)
+ fail("Checking %s should have succeeded\n", name.data);
+
+ name.data = (unsigned char*)"xxx.bbb.ccc.com";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
+ if (ret != 0)
+ fail("Checking %s should have failed\n", name.data);
+
+ name.data = (unsigned char*)"xxx.ccc.com";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
+ if (ret != 0)
+ fail("Checking %s should have failed\n", name.data);
+
+ name.data = (unsigned char*)"ccc.com";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
+ if (ret != 0)
+ fail("Checking %s should have failed\n", name.data);
+
+ name.data = (unsigned char*)"ccc.com";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_RFC822NAME, &name);
+ if (ret == 0)
+ fail("Checking %s should have succeeded\n", name.data);
+
+ name.data = (unsigned char*)"xxx.ccc.com";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_RFC822NAME, &name);
+ if (ret != 0)
+ fail("Checking %s should have failed\n", name.data);
+
+ gnutls_x509_name_constraints_deinit(nc);
+ gnutls_x509_name_constraints_deinit(nc2);
+
+ /* 1: test the merge of name constraints with excluded */
+
+ ret = gnutls_x509_name_constraints_init(&nc);
+ if (ret < 0)
+ fail("error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+
+ ret = gnutls_x509_name_constraints_init(&nc2);
+ if (ret < 0)
+ fail("error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+
+ ret = gnutls_x509_name_constraints_add_excluded(nc, GNUTLS_SAN_DNSNAME,
+ &example_com);
+ if (ret < 0)
+ fail("error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+
+ ret = gnutls_x509_name_constraints_add_excluded(nc2, GNUTLS_SAN_DNSNAME,
+ &example_net);
+ if (ret < 0)
+ fail("error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+
+
+ /* intersection: permit: example.com and example.net denied */
+ ret = _gnutls_x509_name_constraints_merge(nc, nc2);
+ if (ret < 0)
+ fail("error in %d: %s\n", __LINE__, gnutls_strerror(ret));
+
+
+ /* check the union */
+ name.data = (unsigned char*)"xxx.example.com";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
+ if (ret != 0)
+ fail("Checking domain should have failed\n");
+
+ name.data = (unsigned char*)"xxx.example.net";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
+ if (ret != 0)
+ fail("Checking domain should have failed\n");
+
+ name.data = (unsigned char*)"example.com";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
+ if (ret != 0)
+ fail("Checking domain should have failed\n");
+
+ name.data = (unsigned char*)"example.net";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
+ if (ret != 0)
+ fail("Checking domain should have failed\n");
+
+
+ /* check an allowed name */
+ name.data = (unsigned char*)"example.org";
+ name.size = strlen((char*)name.data);
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
+ if (ret == 0)
+ fail("Checking %s should have succeeded\n", name.data);
+
+ gnutls_x509_name_constraints_deinit(nc);
+ gnutls_x509_name_constraints_deinit(nc2);
+
+ gnutls_global_deinit();
+
+ if (debug)
+ success("success");
+}
diff --git a/tests/test-chains.h b/tests/test-chains.h
index 064a3905ee..cc3f108e04 100644
--- a/tests/test-chains.h
+++ b/tests/test-chains.h
@@ -539,6 +539,92 @@ static const char *nc_bad3[] = {
NULL
};
+static const char *nc_bad4[] = {
+/* DNSname: sub2.example.org */
+"-----BEGIN CERTIFICATE-----\n"
+"MIIDMjCCAhqgAwIBAgIBBzANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRDQS0y\n"
+"MCAXDTA0MDIyOTA3MjE0MloYDzk5OTkxMjMxMjM1OTU5WjARMQ8wDQYDVQQDEwZz\n"
+"ZXJ2ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtq4QWPb53ClQL\n"
+"hpCyCf2oX/WnrX2FaPv8m4J29fpkSTn7uuasEjLzwKvltXPJp5fE9jJnX2JyrS5z\n"
+"tBGcH7/OnxEOGtZN19gLQLRPqCjzGkez7moQEbpnO/M8xeUuil4CbuhcnTA93vjf\n"
+"i2mxQMgjS/Ffblbbv5QR6R97Eu01w2gbar7S0nj3ctl2lYiBWFIcBVbunVgtlC8L\n"
+"JgW6tv6jay/GZSUBTw8ijh0o0S1ZEVqoOBszDdLHFwO6m3XpMNocYKh2Eva9LcA+\n"
+"NmVWywaAk84RiMttMjlc+Y3Q3UhEemgh0RTE5oEIFjV9Am4uBM8LcwvmIat2oYtM\n"
+"rbhczTG9AgMBAAGjgZQwgZEwDAYDVR0TAQH/BAIwADAbBgNVHREEFDASghBzdWIy\n"
+"LmV4YW1wbGUub3JnMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdDwEB/wQFAwMH\n"
+"oAAwHQYDVR0OBBYEFM2roPUnRWzJSXG+5jGoBJDX5ZshMB8GA1UdIwQYMBaAFM2r\n"
+"oPUnRWzJSXG+5jGoBJDX5ZshMA0GCSqGSIb3DQEBCwUAA4IBAQARXEGjiewd62mb\n"
+"kiJ5ezzxgsnfLBlhBdrt6bTEWS1Ehnnx1HMfnerFuSmjk8SGsVXgHsqmzY5cg3Sy\n"
+"449+VqkMESOiQRmj4DmNNLu25ShLWlcfDPXBFZavPtNKUrBEWfthI7ZvHBeNe18O\n"
+"kkgYJGKLmMm5+Bz2uDOTBTPUmZkX98sUZgdcFyN8OI2q22MLWed0a+ZNZFRUN/Iw\n"
+"9gg6fzSmMBShAIxei04CZE2Wx32a9tr+mNqHa+Puch2s2EqlYJBlDGa2QgMWA8IP\n"
+"09CHQRxeICqV+cX6zJP4znQFqySX5rWWeD4FKkdQr8T1IX1bCcGKCkj1ulEntOjK\n"
+"8ZOkdWuv\n"
+"-----END CERTIFICATE-----\n",
+/* Name Constraints (critical):
+ Permitted: DNSname: sub1.example.org */
+"-----BEGIN CERTIFICATE-----\n"
+"MIIDQjCCAiqgAwIBAgIBBzANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRDQS0x\n"
+"MCAXDTA0MDIyOTA3MjE0MloYDzk5OTkxMjMxMjM1OTU5WjAPMQ0wCwYDVQQDEwRD\n"
+"QS0yMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArauEFj2+dwpUC4aQ\n"
+"sgn9qF/1p619hWj7/JuCdvX6ZEk5+7rmrBIy88Cr5bVzyaeXxPYyZ19icq0uc7QR\n"
+"nB+/zp8RDhrWTdfYC0C0T6go8xpHs+5qEBG6ZzvzPMXlLopeAm7oXJ0wPd7434tp\n"
+"sUDII0vxX25W27+UEekfexLtNcNoG2q+0tJ493LZdpWIgVhSHAVW7p1YLZQvCyYF\n"
+"urb+o2svxmUlAU8PIo4dKNEtWRFaqDgbMw3SxxcDupt16TDaHGCodhL2vS3APjZl\n"
+"VssGgJPOEYjLbTI5XPmN0N1IRHpoIdEUxOaBCBY1fQJuLgTPC3ML5iGrdqGLTK24\n"
+"XM0xvQIDAQABo4GmMIGjMA8GA1UdEwEB/wQFMAMBAf8wGwYDVR0RBBQwEoIQc3Vi\n"
+"MS5leGFtcGxlLm9yZzAiBgNVHR4BAf8EGDAWoBQwEoIQc3ViMS5leGFtcGxlLm9y\n"
+"ZzAPBgNVHQ8BAf8EBQMDBwQAMB0GA1UdDgQWBBTNq6D1J0VsyUlxvuYxqASQ1+Wb\n"
+"ITAfBgNVHSMEGDAWgBTNq6D1J0VsyUlxvuYxqASQ1+WbITANBgkqhkiG9w0BAQsF\n"
+"AAOCAQEAR8wKnufviUhLtx0og+P/F52BcdQGgVoBdIpix57DeBQTn9PXuF70hPjg\n"
+"a/ZeSR2b65JnyO49i9bBX8ctg/FR+LBHdxMRcIN+VxyKFBtyFc2cxW5a4BWaD9SG\n"
+"hW6gzWviV3XwTfTKuY8h710cEP73Yyu1FOuejI34Jiz0sNXqhPc+08k9maFicjfk\n"
+"Ftpft0y0YM1DJmUMDMQkpShb4kojLwsSYTxU8DTRHXvBHrAdH4Np50tm6FYIXUNS\n"
+"iXlrg/c4VPwEsf5/sR+Ga60LPejZsrvhtvimUsGdNNVVWRtsgcT2jHXxyR1N1vJx\n"
+"qPlLDNLLWp9nfCk/55QqSf34dcKomg==\n"
+"-----END CERTIFICATE-----\n",
+/* Name Constraints (critical):
+ Permitted: DNSname: example.org */
+"-----BEGIN CERTIFICATE-----\n"
+"MIIDIDCCAgigAwIBAgIBBzANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRDQS0w\n"
+"MCAXDTA0MDIyOTA3MjE0MloYDzk5OTkxMjMxMjM1OTU5WjAPMQ0wCwYDVQQDEwRD\n"
+"QS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArauEFj2+dwpUC4aQ\n"
+"sgn9qF/1p619hWj7/JuCdvX6ZEk5+7rmrBIy88Cr5bVzyaeXxPYyZ19icq0uc7QR\n"
+"nB+/zp8RDhrWTdfYC0C0T6go8xpHs+5qEBG6ZzvzPMXlLopeAm7oXJ0wPd7434tp\n"
+"sUDII0vxX25W27+UEekfexLtNcNoG2q+0tJ493LZdpWIgVhSHAVW7p1YLZQvCyYF\n"
+"urb+o2svxmUlAU8PIo4dKNEtWRFaqDgbMw3SxxcDupt16TDaHGCodhL2vS3APjZl\n"
+"VssGgJPOEYjLbTI5XPmN0N1IRHpoIdEUxOaBCBY1fQJuLgTPC3ML5iGrdqGLTK24\n"
+"XM0xvQIDAQABo4GEMIGBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0eAQH/BBMwEaAP\n"
+"MA2CC2V4YW1wbGUub3JnMA8GA1UdDwEB/wQFAwMHBAAwHQYDVR0OBBYEFM2roPUn\n"
+"RWzJSXG+5jGoBJDX5ZshMB8GA1UdIwQYMBaAFM2roPUnRWzJSXG+5jGoBJDX5Zsh\n"
+"MA0GCSqGSIb3DQEBCwUAA4IBAQBr5K+BzFT2skeVkZ0fR8g6KcevlvAP7sOm8Ktm\n"
+"nINBFi9ercrD4XAqkRTCYxDZ/6D9s10lf+CW4QLw2GOQer1D+znBzZZCqFfZ2+uL\n"
+"ibQ+pth5IgsSxkxctowv7x3Y4C95TNAcWs9bWIHKgLqXhotk6mccEvxkyaPIL5yX\n"
+"U2bs+tNpaqiwdCNjTJCo1+xdQwWZfk/oOMBn6Fihuc6eGP6L6Zj2J7TqO2hafrs4\n"
+"lg1rYDU+cTtDy/eVt2UoYXLDnIm2EPcnTAaR6K3cLlh1HbeaUTDU2nE04riE8ntA\n"
+"Mpu+t5TUUq+Zcx17zn54/W5oLC0wCGzzyLhh3/mLh6RLDYub\n"
+"-----END CERTIFICATE-----\n",
+"-----BEGIN CERTIFICATE-----\n"
+"MIIC3jCCAcagAwIBAgIBBzANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRDQS0w\n"
+"MCAXDTA0MDIyOTA3MjE0MloYDzk5OTkxMjMxMjM1OTU5WjAPMQ0wCwYDVQQDEwRD\n"
+"QS0wMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArauEFj2+dwpUC4aQ\n"
+"sgn9qF/1p619hWj7/JuCdvX6ZEk5+7rmrBIy88Cr5bVzyaeXxPYyZ19icq0uc7QR\n"
+"nB+/zp8RDhrWTdfYC0C0T6go8xpHs+5qEBG6ZzvzPMXlLopeAm7oXJ0wPd7434tp\n"
+"sUDII0vxX25W27+UEekfexLtNcNoG2q+0tJ493LZdpWIgVhSHAVW7p1YLZQvCyYF\n"
+"urb+o2svxmUlAU8PIo4dKNEtWRFaqDgbMw3SxxcDupt16TDaHGCodhL2vS3APjZl\n"
+"VssGgJPOEYjLbTI5XPmN0N1IRHpoIdEUxOaBCBY1fQJuLgTPC3ML5iGrdqGLTK24\n"
+"XM0xvQIDAQABo0MwQTAPBgNVHRMBAf8EBTADAQH/MA8GA1UdDwEB/wQFAwMHBAAw\n"
+"HQYDVR0OBBYEFM2roPUnRWzJSXG+5jGoBJDX5ZshMA0GCSqGSIb3DQEBCwUAA4IB\n"
+"AQBtm548YFAtyKUyUyfz/iDPwgFq3PtxN0gfA2ZgrHG0vXDq49eDv7sQueTjY21T\n"
+"GGkgyEEOlcbPzDC7hMrfaYSEGwrwbTkrWnrqk0rorFjjkjlKkx/9EuDQ/gjyQGrn\n"
+"EvnFWwmxq+vambeRGxPWFRR9r+ugbL/xciZfT6OyoU8SZY4EpFu3e4ydmskdkt7R\n"
+"qRPOpaHBuKygw4Uq5mhNaZDMy3FjtP+wt84UOOZbjqFQ8K8AZdAaDp3TDBtzoHED\n"
+"lgv+PQMzYNnSsPVdvBC2fkgIWzZlyjeGMMtkUp3E7FeyFU1302g3xINRBmUcoO0c\n"
+"jo6K7k6FZy3n6DsJ0q/os2wA\n"
+"-----END CERTIFICATE-----\n",
+NULL
+};
+
static const char *nc_good1[] = {
/* DNSname: www.example.com */
"-----BEGIN CERTIFICATE-----\n"
@@ -1793,6 +1879,7 @@ static struct
{ "name constraints chain bad1", nc_bad1, &nc_bad1[2], 0, GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE, NULL, 1412850586},
{ "name constraints chain bad2", nc_bad2, &nc_bad2[4], 0, GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE, NULL, 1412850586},
{ "name constraints chain bad3", nc_bad3, &nc_bad3[2], 0, GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE, NULL, 1412850586},
+ { "name constraints chain bad4", nc_bad4, &nc_bad4[3], 0, GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE, NULL, 1412850586},
{ "not-modified", modified2, &modified2[3], 0, 0, NULL, 1412850586},
{ "kp-interm", kp_fail1, &kp_fail1[3], 0, GNUTLS_CERT_INVALID | GNUTLS_CERT_PURPOSE_MISMATCH, GNUTLS_KP_TLS_WWW_SERVER, 1412850586},
{ "kp-fin", kp_fail2, &kp_fail2[3], 0, GNUTLS_CERT_INVALID | GNUTLS_CERT_PURPOSE_MISMATCH, GNUTLS_KP_TLS_WWW_SERVER, 1412850586},