diff options
-rw-r--r-- | lib/libgnutls.map | 2 | ||||
-rw-r--r-- | lib/x509/name_constraints.c | 214 | ||||
-rw-r--r-- | lib/x509/x509_ext.c | 61 | ||||
-rw-r--r-- | lib/x509/x509_int.h | 3 | ||||
-rw-r--r-- | tests/Makefile.am | 10 | ||||
-rw-r--r-- | tests/name-constraints-merge.c | 260 | ||||
-rw-r--r-- | tests/test-chains.h | 87 |
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}, |