constraints: Properly validate name constraints according to RFC 5280
The previous code was in a way too simple which resulted in it being too strict. For instance, it enforced that intermediate CA certificates inherited the name constraints of their parents. That's not required by RFC 5280 and prevented e.g. adding constraints in an intermediate CA certificate that's followed by another that doesn't contain any name constraints. That's perfectly fine as the set of constraints specified by the parent continue to apply to that CA certificate and the children it issues. Name constraints were previously also applied to all identities of a matching type, which is way too strict except for some very simple cases. It basically prevented multiple constraints of the same type as e.g. an intermediate CA certificate that has permitted name constraints for example.org and example.com couldn't issue acceptable certificates because any SAN with one domain would get rejected by the other constraint. According to RFC 5280 matching one constraint is enough. Also fixed is an issue with name constraints for IP addresses which were previously only supported for a single level.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2023-2024 Tobias Brunner
|
||||||
* Copyright (C) 2010 Martin Willi
|
* Copyright (C) 2010 Martin Willi
|
||||||
*
|
*
|
||||||
* Copyright (C) secunet Security Networks AG
|
* Copyright (C) secunet Security Networks AG
|
||||||
@@ -18,6 +19,8 @@
|
|||||||
|
|
||||||
#include <utils/debug.h>
|
#include <utils/debug.h>
|
||||||
#include <asn1/asn1.h>
|
#include <asn1/asn1.h>
|
||||||
|
#include <collections/array.h>
|
||||||
|
#include <collections/hashtable.h>
|
||||||
#include <collections/linked_list.h>
|
#include <collections/linked_list.h>
|
||||||
#include <credentials/certificates/x509.h>
|
#include <credentials/certificates/x509.h>
|
||||||
|
|
||||||
@@ -101,10 +104,14 @@ static bool email_matches(identification_t *constraint, identification_t *id)
|
|||||||
return chunk_equals(c, i);
|
return chunk_equals(c, i);
|
||||||
}
|
}
|
||||||
diff = chunk_create(i.ptr, i.len - c.len);
|
diff = chunk_create(i.ptr, i.len - c.len);
|
||||||
if (!diff.len || !chunk_equals(c, chunk_skip(i, diff.len)))
|
if (!chunk_equals(c, chunk_skip(i, diff.len)))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
if (!diff.len)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
if (c.ptr[0] == '.')
|
if (c.ptr[0] == '.')
|
||||||
{ /* constraint is domain, suffix match */
|
{ /* constraint is domain, suffix match */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -144,51 +151,80 @@ static bool dn_matches(identification_t *constraint, identification_t *id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the given identity type matches the type of NameConstraint
|
* Check if a new permitted or excluded NameConstraint is matching an
|
||||||
|
* existing one
|
||||||
*/
|
*/
|
||||||
static bool type_matches(id_type_t constraint, id_type_t id)
|
static bool name_constraint_matches(identification_t *existing,
|
||||||
|
identification_t *new, bool permitted)
|
||||||
{
|
{
|
||||||
switch (constraint)
|
identification_t *a, *b;
|
||||||
|
bool matching = FALSE;
|
||||||
|
|
||||||
|
if (permitted)
|
||||||
|
{ /* permitted constraint can be narrowed */
|
||||||
|
a = existing;
|
||||||
|
b = new;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* excluded constraint can be widened */
|
||||||
|
a = new;
|
||||||
|
b = existing;
|
||||||
|
}
|
||||||
|
switch (existing->get_type(existing))
|
||||||
{
|
{
|
||||||
case ID_FQDN:
|
case ID_FQDN:
|
||||||
|
matching = fqdn_matches(a, b);
|
||||||
|
break;
|
||||||
case ID_RFC822_ADDR:
|
case ID_RFC822_ADDR:
|
||||||
|
matching = email_matches(a, b);
|
||||||
|
break;
|
||||||
case ID_DER_ASN1_DN:
|
case ID_DER_ASN1_DN:
|
||||||
return constraint == id;
|
matching = dn_matches(a, b);
|
||||||
|
break;
|
||||||
case ID_IPV4_ADDR_SUBNET:
|
case ID_IPV4_ADDR_SUBNET:
|
||||||
return id == ID_IPV4_ADDR;
|
|
||||||
case ID_IPV6_ADDR_SUBNET:
|
case ID_IPV6_ADDR_SUBNET:
|
||||||
return id == ID_IPV6_ADDR;
|
matching = b->matches(b, a);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
/* shouldn't happen */
|
||||||
|
matching = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return matching;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name constraint type from an identity type
|
||||||
|
*/
|
||||||
|
static id_type_t constraint_type_from_id(id_type_t id)
|
||||||
|
{
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case ID_IPV4_ADDR:
|
||||||
|
return ID_IPV4_ADDR_SUBNET;
|
||||||
|
case ID_IPV6_ADDR:
|
||||||
|
return ID_IPV6_ADDR_SUBNET;
|
||||||
|
default:
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a certificate matches to a NameConstraint
|
* Check if the given identity matches any of the given name constraints
|
||||||
*/
|
*/
|
||||||
static bool name_constraint_matches(identification_t *constraint,
|
static bool id_matches_constraints(certificate_t *cert, identification_t *id,
|
||||||
certificate_t *cert, bool permitted)
|
array_t *constraints, bool permitted)
|
||||||
{
|
{
|
||||||
x509_t *x509 = (x509_t*)cert;
|
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
identification_t *id;
|
identification_t *subject, *constraint;
|
||||||
id_type_t type;
|
id_type_t type;
|
||||||
bool matches = permitted;
|
bool matches = FALSE;
|
||||||
|
|
||||||
type = constraint->get_type(constraint);
|
subject = cert->get_subject(cert);
|
||||||
if (type == ID_DER_ASN1_DN)
|
type = id->get_type(id);
|
||||||
{
|
|
||||||
matches = dn_matches(constraint, cert->get_subject(cert));
|
|
||||||
if (matches != permitted)
|
|
||||||
{
|
|
||||||
return matches;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enumerator = x509->create_subjectAltName_enumerator(x509);
|
enumerator = array_create_enumerator(constraints);
|
||||||
while (enumerator->enumerate(enumerator, &id))
|
while (enumerator->enumerate(enumerator, &constraint))
|
||||||
{
|
|
||||||
if (type_matches(type, id->get_type(id)))
|
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
@@ -201,136 +237,388 @@ static bool name_constraint_matches(identification_t *constraint,
|
|||||||
case ID_DER_ASN1_DN:
|
case ID_DER_ASN1_DN:
|
||||||
matches = dn_matches(constraint, id);
|
matches = dn_matches(constraint, id);
|
||||||
break;
|
break;
|
||||||
case ID_IPV4_ADDR_SUBNET:
|
case ID_IPV4_ADDR:
|
||||||
case ID_IPV6_ADDR_SUBNET:
|
case ID_IPV6_ADDR:
|
||||||
matches = id->matches(id, constraint);
|
matches = id->matches(id, constraint);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DBG1(DBG_CFG, "%N NameConstraint matching not implemented",
|
/* shouldn't happen */
|
||||||
id_type_names, type);
|
break;
|
||||||
matches = FALSE;
|
}
|
||||||
|
if (matches)
|
||||||
|
{
|
||||||
|
if (!permitted)
|
||||||
|
{
|
||||||
|
if (id->equals(id, subject))
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "subject of certificate '%Y' matches excluded "
|
||||||
|
"name constraint '%Y'", subject, constraint);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "subject alternative name '%Y' of certificate "
|
||||||
|
"'%Y' matches excluded name constraint '%Y'",
|
||||||
|
id, subject, constraint);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
|
if (!matches && permitted)
|
||||||
|
{
|
||||||
|
if (id->equals(id, subject))
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "subject of certificate '%Y' does not match any "
|
||||||
|
"permitted name constraints", subject);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "subject alternative name '%Y' of certificate '%Y' "
|
||||||
|
"does not match any permitted name constraints", id, subject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a certificate matches the given permitted/excluded name constraints
|
||||||
|
*/
|
||||||
|
static bool cert_matches_constraints(x509_t *x509, hashtable_t *types,
|
||||||
|
bool permitted)
|
||||||
|
{
|
||||||
|
certificate_t *cert = (certificate_t*)x509;
|
||||||
|
array_t *constraints;
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
identification_t *id;
|
||||||
|
id_type_t type;
|
||||||
|
bool matches = permitted;
|
||||||
|
|
||||||
|
constraints = types->get(types, (void*)(uintptr_t)ID_DER_ASN1_DN);
|
||||||
|
if (constraints)
|
||||||
|
{
|
||||||
|
matches = id_matches_constraints(cert, cert->get_subject(cert),
|
||||||
|
constraints, permitted);
|
||||||
|
if (matches != permitted)
|
||||||
|
{
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enumerator = x509->create_subjectAltName_enumerator(x509);
|
||||||
|
while (enumerator->enumerate(enumerator, &id))
|
||||||
|
{
|
||||||
|
type = constraint_type_from_id(id->get_type(id));
|
||||||
|
constraints = types->get(types, (void*)(uintptr_t)type);
|
||||||
|
if (constraints)
|
||||||
|
{
|
||||||
|
matches = id_matches_constraints(cert, id, constraints, permitted);
|
||||||
if (matches != permitted)
|
if (matches != permitted)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a permitted or excluded NameConstraint has been inherited to sub-CA
|
* Validate the names in the given certificate against the current constraints
|
||||||
*/
|
*/
|
||||||
static bool name_constraint_inherited(identification_t *constraint,
|
static bool name_constraints_match(x509_t *x509, hashtable_t *permitted,
|
||||||
x509_t *x509, bool permitted)
|
hashtable_t *excluded)
|
||||||
{
|
{
|
||||||
enumerator_t *enumerator;
|
if (permitted && !cert_matches_constraints(x509, permitted, TRUE))
|
||||||
identification_t *id, *a, *b;
|
{
|
||||||
bool inherited = FALSE;
|
return FALSE;
|
||||||
id_type_t type;
|
}
|
||||||
|
if (excluded && cert_matches_constraints(x509, excluded, FALSE))
|
||||||
if (!(x509->get_flags(x509) & X509_CA))
|
{
|
||||||
{ /* not a sub-CA, not required */
|
return FALSE;
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
type = constraint->get_type(constraint);
|
/**
|
||||||
|
* Destroy name constraints (callback for hashtable_t::destroy_function())
|
||||||
|
*/
|
||||||
|
CALLBACK(destroy_constraints, void,
|
||||||
|
array_t *this, const void *key)
|
||||||
|
{
|
||||||
|
array_destroy(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hashtable hash function
|
||||||
|
*/
|
||||||
|
static u_int id_type_hash(const void *key)
|
||||||
|
{
|
||||||
|
uintptr_t id = (uintptr_t)key;
|
||||||
|
return chunk_hash(chunk_from_thing(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hashtable equals function
|
||||||
|
*/
|
||||||
|
static bool id_type_equals(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
return (uintptr_t)a == (uintptr_t)b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collect name constraints (permitted or excluded) of each supported type
|
||||||
|
* from the given certificate
|
||||||
|
*/
|
||||||
|
static bool collect_constraints(x509_t *x509, bool permitted, hashtable_t **out)
|
||||||
|
{
|
||||||
|
hashtable_t *collected;
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
identification_t *constraint;
|
||||||
|
array_t *constraints;
|
||||||
|
id_type_t type;
|
||||||
|
bool success = TRUE;
|
||||||
|
|
||||||
|
collected = hashtable_create(id_type_hash, id_type_equals, 8);
|
||||||
|
|
||||||
enumerator = x509->create_name_constraint_enumerator(x509, permitted);
|
enumerator = x509->create_name_constraint_enumerator(x509, permitted);
|
||||||
while (enumerator->enumerate(enumerator, &id))
|
while (enumerator->enumerate(enumerator, &constraint))
|
||||||
{
|
{
|
||||||
if (id->get_type(id) == type)
|
type = constraint->get_type(constraint);
|
||||||
{
|
|
||||||
if (permitted)
|
|
||||||
{ /* permitted constraint can be narrowed */
|
|
||||||
a = constraint;
|
|
||||||
b = id;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* excluded constraint can be widened */
|
|
||||||
a = id;
|
|
||||||
b = constraint;
|
|
||||||
}
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ID_FQDN:
|
case ID_FQDN:
|
||||||
inherited = fqdn_matches(a, b);
|
|
||||||
break;
|
|
||||||
case ID_RFC822_ADDR:
|
case ID_RFC822_ADDR:
|
||||||
inherited = email_matches(a, b);
|
|
||||||
break;
|
|
||||||
case ID_DER_ASN1_DN:
|
case ID_DER_ASN1_DN:
|
||||||
inherited = dn_matches(a, b);
|
case ID_IPV4_ADDR_SUBNET:
|
||||||
|
case ID_IPV6_ADDR_SUBNET:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DBG1(DBG_CFG, "%N NameConstraint matching not implemented",
|
DBG1(DBG_CFG, "%N NameConstraint not supported",
|
||||||
id_type_names, type);
|
id_type_names, type);
|
||||||
inherited = FALSE;
|
success = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
if (!success)
|
||||||
if (inherited)
|
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
constraints = collected->get(collected, (void*)(uintptr_t)type);
|
||||||
|
if (!constraints)
|
||||||
|
{
|
||||||
|
constraints = array_create(0, 8);
|
||||||
|
collected->put(collected, (void*)(uintptr_t)type, constraints);
|
||||||
|
}
|
||||||
|
array_insert(constraints, ARRAY_TAIL, constraint);
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
return inherited;
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
*out = collected;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
collected->destroy_function(collected, destroy_constraints);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge existing and new permitted/excluded name constraints
|
||||||
|
*/
|
||||||
|
static void merge_constraints(certificate_t *cert, array_t *existing_constraints,
|
||||||
|
array_t *new_constraints, bool permitted)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator, *new;
|
||||||
|
identification_t *constraint, *new_constraint;
|
||||||
|
|
||||||
|
if (permitted)
|
||||||
|
{
|
||||||
|
array_t *to_move = NULL;
|
||||||
|
|
||||||
|
enumerator = array_create_enumerator(existing_constraints);
|
||||||
|
while (enumerator->enumerate(enumerator, &constraint))
|
||||||
|
{
|
||||||
|
new = array_create_enumerator(new_constraints);
|
||||||
|
while (new->enumerate(new, &new_constraint))
|
||||||
|
{
|
||||||
|
if (name_constraint_matches(constraint, new_constraint, TRUE))
|
||||||
|
{
|
||||||
|
array_insert_create(&to_move, ARRAY_TAIL, new_constraint);
|
||||||
|
array_remove_at(new_constraints, new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new->destroy(new);
|
||||||
|
|
||||||
|
/* remove the existing constraint. if it was matched, it gets
|
||||||
|
* replaced by the moved equal/narrower constraints, if not, it's
|
||||||
|
* not permitted anymore */
|
||||||
|
array_remove_at(existing_constraints, enumerator);
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
|
if (to_move)
|
||||||
|
{
|
||||||
|
while (array_remove(to_move, ARRAY_HEAD, &new_constraint))
|
||||||
|
{
|
||||||
|
array_insert(existing_constraints, ARRAY_TAIL, new_constraint);
|
||||||
|
}
|
||||||
|
array_destroy(to_move);
|
||||||
|
}
|
||||||
|
/* report ignored constraints that would widen the permitted set */
|
||||||
|
while (array_remove(new_constraints, ARRAY_HEAD, &new_constraint))
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "ignoring name constraint '%Y' in certificate "
|
||||||
|
"'%Y' that's not permitted by parent CAs",
|
||||||
|
new_constraint, cert->get_subject(cert));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* this is simpler as we basically adopt all new constraints, we just
|
||||||
|
* check if we can remove a constraint that gets widened */
|
||||||
|
enumerator = array_create_enumerator(existing_constraints);
|
||||||
|
while (enumerator->enumerate(enumerator, &constraint))
|
||||||
|
{
|
||||||
|
new = array_create_enumerator(new_constraints);
|
||||||
|
while (new->enumerate(new, &new_constraint))
|
||||||
|
{
|
||||||
|
if (name_constraint_matches(constraint, new_constraint, FALSE))
|
||||||
|
{
|
||||||
|
/* remove the existing constraint if it is matched, it
|
||||||
|
* gets replaced by an equal/wider constraint */
|
||||||
|
array_remove_at(existing_constraints, enumerator);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new->destroy(new);
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
|
/* add all new constraints to the list */
|
||||||
|
while (array_remove(new_constraints, ARRAY_HEAD, &new_constraint))
|
||||||
|
{
|
||||||
|
array_insert(existing_constraints, ARRAY_TAIL, new_constraint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the set of permitted/excluded name constraints
|
||||||
|
*/
|
||||||
|
static bool update_name_constraints(x509_t *x509, hashtable_t **existing,
|
||||||
|
bool permitted)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
hashtable_t *collected;
|
||||||
|
array_t *existing_constraints, *new_constraints;
|
||||||
|
void *type;
|
||||||
|
|
||||||
|
if (!(x509->get_flags(x509) & X509_CA))
|
||||||
|
{
|
||||||
|
/* ignore end-entity certificates */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!collect_constraints(x509, permitted, &collected))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (collected->get_count(collected))
|
||||||
|
{
|
||||||
|
if (!*existing)
|
||||||
|
{
|
||||||
|
/* adopt all constraints if we haven't any yet */
|
||||||
|
*existing = collected;
|
||||||
|
collected = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* merge sets of constraints for each type */
|
||||||
|
enumerator = collected->create_enumerator(collected);
|
||||||
|
while (enumerator->enumerate(enumerator, &type, &new_constraints))
|
||||||
|
{
|
||||||
|
existing_constraints = (*existing)->get(*existing, type);
|
||||||
|
if (existing_constraints)
|
||||||
|
{
|
||||||
|
/* merge constraints of known types, either allowing them to
|
||||||
|
* get narrowed or widened */
|
||||||
|
merge_constraints((certificate_t*)x509, existing_constraints,
|
||||||
|
new_constraints, permitted);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* adopt constraints for new types */
|
||||||
|
collected->remove_at(collected, enumerator);
|
||||||
|
(*existing)->put(*existing, type, new_constraints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DESTROY_FUNCTION_IF(collected, destroy_constraints);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check name constraints
|
* Check name constraints
|
||||||
*/
|
*/
|
||||||
static bool check_name_constraints(certificate_t *subject, x509_t *issuer)
|
static bool check_name_constraints(x509_t *issuer, u_int pathlen,
|
||||||
|
auth_cfg_t *auth, certificate_t **violator)
|
||||||
{
|
{
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
identification_t *constraint;
|
linked_list_t *chain;
|
||||||
|
hashtable_t *permitted = NULL, *excluded = NULL;
|
||||||
|
certificate_t *subject, *cert;
|
||||||
|
auth_rule_t rule;
|
||||||
|
x509_t *x509;
|
||||||
|
int len = 0;
|
||||||
|
bool valid = TRUE;
|
||||||
|
|
||||||
enumerator = issuer->create_name_constraint_enumerator(issuer, TRUE);
|
subject = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
|
||||||
while (enumerator->enumerate(enumerator, &constraint))
|
if (!subject || subject->get_type(subject) != CERT_X509)
|
||||||
{
|
{
|
||||||
if (!name_constraint_matches(constraint, subject, TRUE))
|
|
||||||
{
|
|
||||||
DBG1(DBG_CFG, "certificate '%Y' does not match permitted name "
|
|
||||||
"constraint '%Y'", subject->get_subject(subject), constraint);
|
|
||||||
enumerator->destroy(enumerator);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (!name_constraint_inherited(constraint, (x509_t*)subject, TRUE))
|
|
||||||
{
|
|
||||||
DBG1(DBG_CFG, "intermediate CA '%Y' does not inherit permitted name "
|
|
||||||
"constraint '%Y'", subject->get_subject(subject), constraint);
|
|
||||||
enumerator->destroy(enumerator);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
enumerator->destroy(enumerator);
|
|
||||||
|
|
||||||
enumerator = issuer->create_name_constraint_enumerator(issuer, FALSE);
|
|
||||||
while (enumerator->enumerate(enumerator, &constraint))
|
|
||||||
{
|
|
||||||
if (name_constraint_matches(constraint, subject, FALSE))
|
|
||||||
{
|
|
||||||
DBG1(DBG_CFG, "certificate '%Y' matches excluded name "
|
|
||||||
"constraint '%Y'", subject->get_subject(subject), constraint);
|
|
||||||
enumerator->destroy(enumerator);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (!name_constraint_inherited(constraint, (x509_t*)subject, FALSE))
|
|
||||||
{
|
|
||||||
DBG1(DBG_CFG, "intermediate CA '%Y' does not inherit excluded name "
|
|
||||||
"constraint '%Y'", subject->get_subject(subject), constraint);
|
|
||||||
enumerator->destroy(enumerator);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
enumerator->destroy(enumerator);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* prepare trustchain to validate name constraints top-down */
|
||||||
|
chain = linked_list_create_with_items(subject, NULL);
|
||||||
|
enumerator = auth->create_enumerator(auth);
|
||||||
|
while (enumerator->enumerate(enumerator, &rule, &cert))
|
||||||
|
{
|
||||||
|
if (rule == AUTH_RULE_IM_CERT &&
|
||||||
|
cert->get_type(cert) == CERT_X509)
|
||||||
|
{
|
||||||
|
chain->insert_first(chain, cert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
chain->insert_first(chain, issuer);
|
||||||
|
|
||||||
|
enumerator = chain->create_enumerator(chain);
|
||||||
|
while (enumerator->enumerate(enumerator, &x509))
|
||||||
|
{
|
||||||
|
if ((len > 0 && !name_constraints_match(x509, permitted, excluded)) ||
|
||||||
|
!update_name_constraints(x509, &permitted, TRUE) ||
|
||||||
|
!update_name_constraints(x509, &excluded, FALSE))
|
||||||
|
{
|
||||||
|
valid = FALSE;
|
||||||
|
*violator = (certificate_t*)x509;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
|
DESTROY_FUNCTION_IF(permitted, destroy_constraints);
|
||||||
|
DESTROY_FUNCTION_IF(excluded, destroy_constraints);
|
||||||
|
chain->destroy(chain);
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special OID for anyPolicy
|
* Special OID for anyPolicy
|
||||||
*/
|
*/
|
||||||
@@ -690,14 +978,16 @@ METHOD(cert_validator_t, validate, bool,
|
|||||||
subject);
|
subject);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!check_name_constraints(subject, (x509_t*)issuer))
|
|
||||||
{
|
|
||||||
lib->credmgr->call_hook(lib->credmgr, CRED_HOOK_POLICY_VIOLATION,
|
|
||||||
subject);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (anchor)
|
if (anchor)
|
||||||
{
|
{
|
||||||
|
certificate_t *violator;
|
||||||
|
|
||||||
|
if (!check_name_constraints((x509_t*)issuer, pathlen, auth, &violator))
|
||||||
|
{
|
||||||
|
lib->credmgr->call_hook(lib->credmgr,
|
||||||
|
CRED_HOOK_POLICY_VIOLATION, violator);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
if (!check_policy_constraints((x509_t*)issuer, pathlen, auth))
|
if (!check_policy_constraints((x509_t*)issuer, pathlen, auth))
|
||||||
{
|
{
|
||||||
lib->credmgr->call_hook(lib->credmgr,
|
lib->credmgr->call_hook(lib->credmgr,
|
||||||
|
|||||||
@@ -68,15 +68,15 @@ static char keydata[] = {
|
|||||||
/**
|
/**
|
||||||
* Issue a certificate with permitted/excluded name constraints
|
* Issue a certificate with permitted/excluded name constraints
|
||||||
*/
|
*/
|
||||||
static certificate_t* create_cert(certificate_t *ca, char *subject, char *san,
|
static certificate_t* create_cert_lists(certificate_t *ca, char *subject,
|
||||||
x509_flag_t flags, identification_t *permitted,
|
linked_list_t *sans, x509_flag_t flags,
|
||||||
identification_t *excluded)
|
linked_list_t *permitted,
|
||||||
|
linked_list_t *excluded)
|
||||||
{
|
{
|
||||||
private_key_t *privkey;
|
private_key_t *privkey;
|
||||||
public_key_t *pubkey;
|
public_key_t *pubkey;
|
||||||
certificate_t *cert;
|
certificate_t *cert;
|
||||||
identification_t *id;
|
identification_t *id;
|
||||||
linked_list_t *plist, *elist, *sans;
|
|
||||||
|
|
||||||
privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
|
privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
|
||||||
BUILD_BLOB_ASN1_DER, chunk_from_thing(keydata),
|
BUILD_BLOB_ASN1_DER, chunk_from_thing(keydata),
|
||||||
@@ -84,6 +84,39 @@ static certificate_t* create_cert(certificate_t *ca, char *subject, char *san,
|
|||||||
ck_assert(privkey);
|
ck_assert(privkey);
|
||||||
pubkey = privkey->get_public_key(privkey);
|
pubkey = privkey->get_public_key(privkey);
|
||||||
ck_assert(pubkey);
|
ck_assert(pubkey);
|
||||||
|
|
||||||
|
id = identification_create_from_string(subject);
|
||||||
|
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||||
|
BUILD_SIGNING_KEY, privkey,
|
||||||
|
BUILD_PUBLIC_KEY, pubkey,
|
||||||
|
BUILD_SUBJECT, id,
|
||||||
|
BUILD_X509_FLAG, flags,
|
||||||
|
BUILD_SIGNING_CERT, ca,
|
||||||
|
BUILD_SUBJECT_ALTNAMES, sans,
|
||||||
|
BUILD_PERMITTED_NAME_CONSTRAINTS, permitted,
|
||||||
|
BUILD_EXCLUDED_NAME_CONSTRAINTS, excluded,
|
||||||
|
BUILD_END);
|
||||||
|
ck_assert(cert);
|
||||||
|
id->destroy(id);
|
||||||
|
sans->destroy_offset(sans, offsetof(identification_t, destroy));
|
||||||
|
permitted->destroy_offset(permitted, offsetof(identification_t, destroy));
|
||||||
|
excluded->destroy_offset(excluded, offsetof(identification_t, destroy));
|
||||||
|
privkey->destroy(privkey);
|
||||||
|
pubkey->destroy(pubkey);
|
||||||
|
|
||||||
|
return cert;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Issue a certificate with single values
|
||||||
|
*/
|
||||||
|
static certificate_t* create_cert(certificate_t *ca, char *subject, char *san,
|
||||||
|
x509_flag_t flags, identification_t *permitted,
|
||||||
|
identification_t *excluded)
|
||||||
|
{
|
||||||
|
linked_list_t *plist, *elist, *sans;
|
||||||
|
identification_t *id;
|
||||||
|
|
||||||
plist = linked_list_create();
|
plist = linked_list_create();
|
||||||
if (permitted)
|
if (permitted)
|
||||||
{
|
{
|
||||||
@@ -100,26 +133,7 @@ static certificate_t* create_cert(certificate_t *ca, char *subject, char *san,
|
|||||||
id = identification_create_from_string(san);
|
id = identification_create_from_string(san);
|
||||||
sans->insert_last(sans, id);
|
sans->insert_last(sans, id);
|
||||||
}
|
}
|
||||||
id = identification_create_from_string(subject);
|
return create_cert_lists(ca, subject, sans, flags, plist, elist);
|
||||||
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
|
||||||
BUILD_SIGNING_KEY, privkey,
|
|
||||||
BUILD_PUBLIC_KEY, pubkey,
|
|
||||||
BUILD_SUBJECT, id,
|
|
||||||
BUILD_X509_FLAG, flags,
|
|
||||||
BUILD_SIGNING_CERT, ca,
|
|
||||||
BUILD_SUBJECT_ALTNAMES, sans,
|
|
||||||
BUILD_PERMITTED_NAME_CONSTRAINTS, plist,
|
|
||||||
BUILD_EXCLUDED_NAME_CONSTRAINTS, elist,
|
|
||||||
BUILD_END);
|
|
||||||
ck_assert(cert);
|
|
||||||
id->destroy(id);
|
|
||||||
sans->destroy_offset(sans, offsetof(identification_t, destroy));
|
|
||||||
plist->destroy_offset(plist, offsetof(identification_t, destroy));
|
|
||||||
elist->destroy_offset(elist, offsetof(identification_t, destroy));
|
|
||||||
privkey->destroy(privkey);
|
|
||||||
pubkey->destroy(pubkey);
|
|
||||||
|
|
||||||
return cert;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -188,26 +202,29 @@ START_TEST(test_permitted_dn)
|
|||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
id_type_t ctype;
|
|
||||||
char *cdata;
|
char *cdata;
|
||||||
char *subject;
|
char *subject;
|
||||||
bool good;
|
bool good;
|
||||||
} permitted_san[] = {
|
} permitted_san[] = {
|
||||||
{ ID_FQDN, ".strongswan.org", "test.strongswan.org", TRUE },
|
{ ".strongswan.org", "test.strongswan.org", TRUE },
|
||||||
{ ID_FQDN, "strongswan.org", "test.strongswan.org", TRUE },
|
{ "strongswan.org", "test.strongswan.org", TRUE },
|
||||||
{ ID_FQDN, "a.b.c.strongswan.org", "d.a.b.c.strongswan.org", TRUE },
|
{ "a.b.c.strongswan.org", "d.a.b.c.strongswan.org", TRUE },
|
||||||
{ ID_FQDN, "a.b.c.strongswan.org", "a.b.c.d.strongswan.org", FALSE },
|
{ "a.b.c.strongswan.org", "a.b.c.d.strongswan.org", FALSE },
|
||||||
{ ID_FQDN, "strongswan.org", "strongswan.org.com", FALSE },
|
{ "strongswan.org", "strongswan.org.com", FALSE },
|
||||||
{ ID_FQDN, ".strongswan.org", "strongswan.org", FALSE },
|
{ ".strongswan.org", "strongswan.org", FALSE },
|
||||||
{ ID_FQDN, "strongswan.org", "nostrongswan.org", FALSE },
|
{ "strongswan.org", "nostrongswan.org", FALSE },
|
||||||
{ ID_FQDN, "strongswan.org", "swan.org", FALSE },
|
{ "strongswan.org", "swan.org", FALSE },
|
||||||
{ ID_FQDN, "strongswan.org", "swan.org", FALSE },
|
{ "strongswan.org", "swan.org", FALSE },
|
||||||
{ ID_RFC822_ADDR, "[email protected]", "[email protected]", TRUE },
|
{ "[email protected]", "[email protected]", TRUE },
|
||||||
{ ID_RFC822_ADDR, "[email protected]", "[email protected]", FALSE },
|
{ "[email protected]", "[email protected]", FALSE },
|
||||||
{ ID_RFC822_ADDR, "strongswan.org", "[email protected]", TRUE },
|
{ "email:strongswan.org", "[email protected]", TRUE },
|
||||||
{ ID_RFC822_ADDR, "strongswan.org", "[email protected]", FALSE },
|
{ "email:strongswan.org", "[email protected]", FALSE },
|
||||||
{ ID_RFC822_ADDR, ".strongswan.org", "[email protected]", TRUE },
|
{ "email:.strongswan.org", "[email protected]", TRUE },
|
||||||
{ ID_RFC822_ADDR, ".strongswan.org", "[email protected]", FALSE },
|
{ "email:.strongswan.org", "[email protected]", FALSE },
|
||||||
|
{ "192.168.1.0/24", "192.168.1.10", TRUE },
|
||||||
|
{ "192.168.1.0/24", "192.168.2.10", FALSE },
|
||||||
|
{ "fec0::/64", "fec0::10", TRUE },
|
||||||
|
{ "fec0::/64", "fec1::10", FALSE },
|
||||||
};
|
};
|
||||||
|
|
||||||
START_TEST(test_permitted_san)
|
START_TEST(test_permitted_san)
|
||||||
@@ -215,8 +232,7 @@ START_TEST(test_permitted_san)
|
|||||||
certificate_t *ca, *sj;
|
certificate_t *ca, *sj;
|
||||||
identification_t *id;
|
identification_t *id;
|
||||||
|
|
||||||
id = identification_create_from_encoding(permitted_san[_i].ctype,
|
id = identification_create_from_string(permitted_san[_i].cdata);
|
||||||
chunk_from_str(permitted_san[_i].cdata));
|
|
||||||
ca = create_cert(NULL, "CN=CA", NULL, X509_CA, id, NULL);
|
ca = create_cert(NULL, "CN=CA", NULL, X509_CA, id, NULL);
|
||||||
sj = create_cert(ca, "CN=SJ", permitted_san[_i].subject, 0, NULL, NULL);
|
sj = create_cert(ca, "CN=SJ", permitted_san[_i].subject, 0, NULL, NULL);
|
||||||
|
|
||||||
@@ -259,26 +275,29 @@ START_TEST(test_excluded_dn)
|
|||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
id_type_t ctype;
|
|
||||||
char *cdata;
|
char *cdata;
|
||||||
char *subject;
|
char *subject;
|
||||||
bool good;
|
bool good;
|
||||||
} excluded_san[] = {
|
} excluded_san[] = {
|
||||||
{ ID_FQDN, ".strongswan.org", "test.strongswan.org", FALSE },
|
{ ".strongswan.org", "test.strongswan.org", FALSE },
|
||||||
{ ID_FQDN, "strongswan.org", "test.strongswan.org", FALSE },
|
{ "strongswan.org", "test.strongswan.org", FALSE },
|
||||||
{ ID_FQDN, "a.b.c.strongswan.org", "d.a.b.c.strongswan.org", FALSE },
|
{ "a.b.c.strongswan.org", "d.a.b.c.strongswan.org", FALSE },
|
||||||
{ ID_FQDN, "a.b.c.strongswan.org", "a.b.c.d.strongswan.org", TRUE },
|
{ "a.b.c.strongswan.org", "a.b.c.d.strongswan.org", TRUE },
|
||||||
{ ID_FQDN, "strongswan.org", "strongswan.org.com", TRUE },
|
{ "strongswan.org", "strongswan.org.com", TRUE },
|
||||||
{ ID_FQDN, ".strongswan.org", "strongswan.org", TRUE },
|
{ ".strongswan.org", "strongswan.org", TRUE },
|
||||||
{ ID_FQDN, "strongswan.org", "nostrongswan.org", TRUE },
|
{ "strongswan.org", "nostrongswan.org", TRUE },
|
||||||
{ ID_FQDN, "strongswan.org", "swan.org", TRUE },
|
{ "strongswan.org", "swan.org", TRUE },
|
||||||
{ ID_FQDN, "strongswan.org", "swan.org", TRUE },
|
{ "strongswan.org", "swan.org", TRUE },
|
||||||
{ ID_RFC822_ADDR, "[email protected]", "[email protected]", FALSE },
|
{ "[email protected]", "[email protected]", FALSE },
|
||||||
{ ID_RFC822_ADDR, "[email protected]", "[email protected]", TRUE },
|
{ "[email protected]", "[email protected]", TRUE },
|
||||||
{ ID_RFC822_ADDR, "strongswan.org", "[email protected]", FALSE },
|
{ "email:strongswan.org", "[email protected]", FALSE },
|
||||||
{ ID_RFC822_ADDR, "strongswan.org", "[email protected]", TRUE },
|
{ "email:strongswan.org", "[email protected]", TRUE },
|
||||||
{ ID_RFC822_ADDR, ".strongswan.org", "[email protected]", FALSE },
|
{ "email:.strongswan.org", "[email protected]", FALSE },
|
||||||
{ ID_RFC822_ADDR, ".strongswan.org", "[email protected]", TRUE },
|
{ "email:.strongswan.org", "[email protected]", TRUE },
|
||||||
|
{ "192.168.1.0/24", "192.168.1.10", FALSE },
|
||||||
|
{ "192.168.1.0/24", "192.168.2.10", TRUE },
|
||||||
|
{ "fec0::/64", "fec0::10", FALSE },
|
||||||
|
{ "fec0::/64", "fec1::10", TRUE },
|
||||||
};
|
};
|
||||||
|
|
||||||
START_TEST(test_excluded_san)
|
START_TEST(test_excluded_san)
|
||||||
@@ -286,8 +305,7 @@ START_TEST(test_excluded_san)
|
|||||||
certificate_t *ca, *sj;
|
certificate_t *ca, *sj;
|
||||||
identification_t *id;
|
identification_t *id;
|
||||||
|
|
||||||
id = identification_create_from_encoding(excluded_san[_i].ctype,
|
id = identification_create_from_string(excluded_san[_i].cdata);
|
||||||
chunk_from_str(excluded_san[_i].cdata));
|
|
||||||
ca = create_cert(NULL, "CN=CA", NULL, X509_CA, NULL, id);
|
ca = create_cert(NULL, "CN=CA", NULL, X509_CA, NULL, id);
|
||||||
sj = create_cert(ca, "CN=SJ", excluded_san[_i].subject, 0, NULL, NULL);
|
sj = create_cert(ca, "CN=SJ", excluded_san[_i].subject, 0, NULL, NULL);
|
||||||
|
|
||||||
@@ -298,33 +316,45 @@ START_TEST(test_excluded_san)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an identity if the given string is not NULL
|
||||||
|
*/
|
||||||
|
static identification_t *create_test_id(char *id)
|
||||||
|
{
|
||||||
|
return id ? identification_create_from_string(id) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
char *caconst;
|
char *caconst;
|
||||||
char *imconst;
|
char *imconst;
|
||||||
char *subject;
|
char *subject;
|
||||||
bool good;
|
bool good;
|
||||||
} permitted_dninh[] = {
|
} permitted_dn_levels[] = {
|
||||||
{ "C=CH", "C=CH, O=strongSwan", "C=CH, O=strongSwan, CN=tester", TRUE },
|
{ "C=CH", "C=CH, O=strongSwan", "C=CH, O=strongSwan, CN=tester", TRUE },
|
||||||
|
{ "C=CH", NULL, "C=CH, O=strongSwan, CN=tester", TRUE },
|
||||||
|
{ NULL, "C=CH, O=strongSwan", "C=CH, O=strongSwan, CN=tester", TRUE },
|
||||||
{ "C=CH", "C=DE, O=strongSwan", "C=CH, O=strongSwan, CN=tester", FALSE },
|
{ "C=CH", "C=DE, O=strongSwan", "C=CH, O=strongSwan, CN=tester", FALSE },
|
||||||
|
{ "C=CH", "C=DE", "C=DE, O=strongSwan, CN=tester", FALSE },
|
||||||
{ "C=CH, O=strongSwan", "C=CH", "C=CH", FALSE },
|
{ "C=CH, O=strongSwan", "C=CH", "C=CH", FALSE },
|
||||||
|
{ "C=CH, O=strongSwan, CN=Intermediate", NULL, "C=CH", FALSE },
|
||||||
};
|
};
|
||||||
|
|
||||||
START_TEST(test_permitted_dninh)
|
START_TEST(test_permitted_dn_levels)
|
||||||
{
|
{
|
||||||
certificate_t *ca, *im, *sj;
|
certificate_t *ca, *im, *sj;
|
||||||
identification_t *id;
|
identification_t *id;
|
||||||
|
|
||||||
id = identification_create_from_string(permitted_dninh[_i].caconst);
|
id = create_test_id(permitted_dn_levels[_i].caconst);
|
||||||
ca = create_cert(NULL, "C=CH, O=strongSwan, CN=CA", NULL, X509_CA, id, NULL);
|
ca = create_cert(NULL, "C=CH, O=strongSwan, CN=CA", NULL, X509_CA, id, NULL);
|
||||||
id = identification_create_from_string(permitted_dninh[_i].imconst);
|
id = create_test_id(permitted_dn_levels[_i].imconst);
|
||||||
im = create_cert(ca, "C=CH, O=strongSwan, CN=IM", NULL, X509_CA, id, NULL);
|
im = create_cert(ca, "C=CH, O=strongSwan, CN=IM", NULL, X509_CA, id, NULL);
|
||||||
sj = create_cert(im, permitted_dninh[_i].subject, NULL, 0, NULL, NULL);
|
sj = create_cert(im, permitted_dn_levels[_i].subject, NULL, 0, NULL, NULL);
|
||||||
|
|
||||||
creds->add_cert(creds, TRUE, ca);
|
creds->add_cert(creds, TRUE, ca);
|
||||||
creds->add_cert(creds, FALSE, im);
|
creds->add_cert(creds, FALSE, im);
|
||||||
creds->add_cert(creds, FALSE, sj);
|
creds->add_cert(creds, FALSE, sj);
|
||||||
|
|
||||||
ck_assert(check_trust(sj->get_subject(sj)) == permitted_dninh[_i].good);
|
ck_assert(check_trust(sj->get_subject(sj)) == permitted_dn_levels[_i].good);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
@@ -333,28 +363,301 @@ static struct {
|
|||||||
char *imconst;
|
char *imconst;
|
||||||
char *subject;
|
char *subject;
|
||||||
bool good;
|
bool good;
|
||||||
} excluded_dninh[] = {
|
} permitted_san_levels[] = {
|
||||||
{ "C=CH, O=strongSwan", "C=CH", "C=DE", TRUE },
|
{ "strongswan.org", NULL, "strongswan.org", TRUE },
|
||||||
{ "C=CH, O=strongSwan", "C=DE", "C=CH", FALSE },
|
{ "strongswan.org", NULL, "vpn.strongswan.org", TRUE },
|
||||||
{ "C=CH", "C=CH, O=strongSwan", "C=CH, O=strongSwan, CN=tester", FALSE },
|
{ "strongswan.org", NULL, "strongswan.com", FALSE },
|
||||||
|
{ NULL, "strongswan.org", "strongswan.org", TRUE },
|
||||||
|
{ NULL, "strongswan.org", "strongswan.com", FALSE },
|
||||||
|
{ "strongswan.org", "strongswan.org", "strongswan.org", TRUE },
|
||||||
|
{ "strongswan.org", "strongswan.com", "strongswan.com", FALSE },
|
||||||
|
{ "strongswan.org", "vpn.strongswan.org", "strongswan.org", FALSE },
|
||||||
|
{ "strongswan.org", "vpn.strongswan.org", "vpn.strongswan.org", TRUE },
|
||||||
|
{ "strongswan.org", "vpn.strongswan.org", "a.vpn.strongswan.org", TRUE },
|
||||||
|
{ "strongswan.org", NULL, "[email protected]", TRUE },
|
||||||
|
{ "[email protected]", NULL, "[email protected]", TRUE },
|
||||||
|
{ "email:strongswan.org", NULL, "[email protected]", TRUE },
|
||||||
|
{ "email:strongswan.org", NULL, "[email protected]", FALSE },
|
||||||
|
{ "email:strongswan.org", "[email protected]", "[email protected]", TRUE },
|
||||||
|
{ "email:strongswan.org", "[email protected]", "[email protected]", FALSE },
|
||||||
|
{ "email:strongswan.org", "strongswan.org", "vpn.strongswan.org", TRUE },
|
||||||
|
{ "192.168.1.0/24", NULL, "192.168.1.10", TRUE },
|
||||||
|
{ "192.168.1.0/24", NULL, "192.168.2.10", FALSE },
|
||||||
|
{ "192.168.1.0/24", "192.168.2.0/24", "192.168.1.10", FALSE },
|
||||||
|
{ "192.168.1.0/24", "192.168.1.0/28", "192.168.1.10", TRUE },
|
||||||
|
{ "192.168.1.0/24", "192.168.1.16/28", "192.168.1.10", FALSE },
|
||||||
|
{ "fec0::/64", NULL, "fec0::10", TRUE },
|
||||||
|
{ "fec0::/64", NULL, "fec1::10", FALSE },
|
||||||
|
{ "fec0::/64", "fec1::/64", "fec1::10", FALSE },
|
||||||
|
{ "fec0::/64", "fec0::/123", "fec0::10", TRUE },
|
||||||
|
{ "fec0::/64", "fec0::20/123", "fec0::10", FALSE },
|
||||||
};
|
};
|
||||||
|
|
||||||
START_TEST(test_excluded_dninh)
|
START_TEST(test_permitted_san_levels)
|
||||||
{
|
{
|
||||||
certificate_t *ca, *im, *sj;
|
certificate_t *ca, *im, *sj;
|
||||||
identification_t *id;
|
identification_t *id;
|
||||||
|
|
||||||
id = identification_create_from_string(excluded_dninh[_i].caconst);
|
id = create_test_id(permitted_san_levels[_i].caconst);
|
||||||
ca = create_cert(NULL, "C=CH, O=strongSwan, CN=CA", NULL, X509_CA, NULL, id);
|
ca = create_cert(NULL, "CN=CA", NULL, X509_CA, id, NULL);
|
||||||
id = identification_create_from_string(excluded_dninh[_i].imconst);
|
id = create_test_id(permitted_san_levels[_i].imconst);
|
||||||
im = create_cert(ca, "C=DE, CN=IM", NULL, X509_CA, NULL, id);
|
im = create_cert(ca, "CN=IM", NULL, X509_CA, id, NULL);
|
||||||
sj = create_cert(im, excluded_dninh[_i].subject, NULL, 0, NULL, NULL);
|
sj = create_cert(im, "CN=EE", permitted_san_levels[_i].subject, 0, NULL, NULL);
|
||||||
|
|
||||||
creds->add_cert(creds, TRUE, ca);
|
creds->add_cert(creds, TRUE, ca);
|
||||||
creds->add_cert(creds, FALSE, im);
|
creds->add_cert(creds, FALSE, im);
|
||||||
creds->add_cert(creds, FALSE, sj);
|
creds->add_cert(creds, FALSE, sj);
|
||||||
|
|
||||||
ck_assert(check_trust(sj->get_subject(sj)) == excluded_dninh[_i].good);
|
ck_assert(check_trust(sj->get_subject(sj)) == permitted_san_levels[_i].good);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
char *caconst;
|
||||||
|
char *imconst;
|
||||||
|
char *subject;
|
||||||
|
bool good;
|
||||||
|
} excluded_dn_levels[] = {
|
||||||
|
{ "C=CH, O=strongSwan", "C=CH", "C=DE", TRUE },
|
||||||
|
{ "C=CH, O=strongSwan", "C=CH", "C=CH", FALSE },
|
||||||
|
{ "C=CH, O=strongSwan", "C=DE", "C=CH", TRUE },
|
||||||
|
{ "C=CH, O=strongSwan", "C=DE", "C=DE", FALSE },
|
||||||
|
{ "C=CH, O=strongSwan", "C=DE", "C=CH, O=strongSwan", FALSE },
|
||||||
|
{ NULL, "C=CH", "C=CH, O=strongSwan", FALSE },
|
||||||
|
{ "C=CH", NULL, "C=CH, O=strongSwan", FALSE },
|
||||||
|
{ "C=CH", "C=CH, O=strongSwan", "C=CH, O=strongSwan, CN=tester", FALSE },
|
||||||
|
{ "C=DE", NULL, "C=CH, O=strongSwan, CN=tester", FALSE },
|
||||||
|
};
|
||||||
|
|
||||||
|
START_TEST(test_excluded_dn_levels)
|
||||||
|
{
|
||||||
|
certificate_t *ca, *im, *sj;
|
||||||
|
identification_t *id;
|
||||||
|
|
||||||
|
id = create_test_id(excluded_dn_levels[_i].caconst);
|
||||||
|
ca = create_cert(NULL, "C=CH, O=strongSwan, CN=CA", NULL, X509_CA, NULL, id);
|
||||||
|
id = create_test_id(excluded_dn_levels[_i].imconst);
|
||||||
|
im = create_cert(ca, "C=DE, CN=IM", NULL, X509_CA, NULL, id);
|
||||||
|
sj = create_cert(im, excluded_dn_levels[_i].subject, NULL, 0, NULL, NULL);
|
||||||
|
|
||||||
|
creds->add_cert(creds, TRUE, ca);
|
||||||
|
creds->add_cert(creds, FALSE, im);
|
||||||
|
creds->add_cert(creds, FALSE, sj);
|
||||||
|
|
||||||
|
ck_assert(check_trust(sj->get_subject(sj)) == excluded_dn_levels[_i].good);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
char *caconst;
|
||||||
|
char *imconst;
|
||||||
|
char *subject;
|
||||||
|
bool good;
|
||||||
|
} excluded_san_levels[] = {
|
||||||
|
{ "strongswan.org", NULL, "strongswan.org", FALSE },
|
||||||
|
{ "strongswan.org", NULL, "strongswan.com", TRUE },
|
||||||
|
{ NULL, "strongswan.org", "strongswan.org", FALSE },
|
||||||
|
{ NULL, "strongswan.org", "strongswan.com", TRUE },
|
||||||
|
{ "strongswan.org", NULL, "test.strongswan.org", FALSE },
|
||||||
|
{ "test.strongswan.org", NULL, "test.strongswan.org", FALSE },
|
||||||
|
{ "test.strongswan.org", NULL, "strongswan.org", TRUE },
|
||||||
|
{ "test.strongswan.org", "strongswan.org", "strongswan.org", FALSE },
|
||||||
|
{ "test.strongswan.org", "strongswan.org", "test.strongswan.org", FALSE },
|
||||||
|
{ "test.strongswan.org", "test.strongswan.org", "test.strongswan.org", FALSE },
|
||||||
|
{ "strongswan.org", NULL, "[email protected]", TRUE },
|
||||||
|
{ "[email protected]", NULL, "[email protected]", FALSE },
|
||||||
|
{ "[email protected]", NULL, "[email protected]", TRUE },
|
||||||
|
{ "email:strongswan.org", NULL, "[email protected]", FALSE },
|
||||||
|
{ "email:strongswan.org", NULL, "[email protected]", TRUE },
|
||||||
|
{ "email:strongswan.org", "email:strongswan.com", "[email protected]", FALSE },
|
||||||
|
{ "email:strongswan.org", "email:strongswan.com", "[email protected]", FALSE },
|
||||||
|
{ "strongswan.org", "email:strongswan.com", "[email protected]", FALSE },
|
||||||
|
{ "192.168.1.0/24", NULL, "192.168.1.10", FALSE },
|
||||||
|
{ "192.168.1.0/24", NULL, "192.168.2.10", TRUE },
|
||||||
|
{ "192.168.1.0/24", "192.168.0.0/16", "192.168.2.10", FALSE },
|
||||||
|
{ "fec0::/64", NULL, "fec0::10", FALSE },
|
||||||
|
{ "fec0::/64", NULL, "fec1::10", TRUE },
|
||||||
|
{ "fec0::/64", "fec1::/12", "fec1::10", FALSE },
|
||||||
|
};
|
||||||
|
|
||||||
|
START_TEST(test_excluded_san_levels)
|
||||||
|
{
|
||||||
|
certificate_t *ca, *im, *sj;
|
||||||
|
identification_t *id;
|
||||||
|
|
||||||
|
id = create_test_id(excluded_san_levels[_i].caconst);
|
||||||
|
ca = create_cert(NULL, "CN=CA", NULL, X509_CA, NULL, id);
|
||||||
|
id = create_test_id(excluded_san_levels[_i].imconst);
|
||||||
|
im = create_cert(ca, "CN=IM", NULL, X509_CA, NULL, id);
|
||||||
|
sj = create_cert(im, "CN=EE", excluded_san_levels[_i].subject, 0, NULL, NULL);
|
||||||
|
|
||||||
|
creds->add_cert(creds, TRUE, ca);
|
||||||
|
creds->add_cert(creds, FALSE, im);
|
||||||
|
creds->add_cert(creds, FALSE, sj);
|
||||||
|
|
||||||
|
ck_assert(check_trust(sj->get_subject(sj)) == excluded_san_levels[_i].good);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an identity to the given list if not NULL
|
||||||
|
*/
|
||||||
|
static void add_identity_to_list(linked_list_t *list, char *idstr)
|
||||||
|
{
|
||||||
|
identification_t *id;
|
||||||
|
|
||||||
|
if (idstr)
|
||||||
|
{
|
||||||
|
id = identification_create_from_string(idstr);
|
||||||
|
list->insert_last(list, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a certificate with potentially multiple constraints/SANs
|
||||||
|
*/
|
||||||
|
static certificate_t *create_cert_multi(certificate_t *ca, char *subject,
|
||||||
|
x509_flag_t flags,
|
||||||
|
char *san1, char *san2,
|
||||||
|
char *pconst1, char *pconst2,
|
||||||
|
char *econst1, char *econst2)
|
||||||
|
{
|
||||||
|
linked_list_t *sans, *permitted, *excluded;
|
||||||
|
|
||||||
|
sans = linked_list_create();
|
||||||
|
add_identity_to_list(sans, san1);
|
||||||
|
add_identity_to_list(sans, san2);
|
||||||
|
|
||||||
|
permitted = linked_list_create();
|
||||||
|
add_identity_to_list(permitted, pconst1);
|
||||||
|
add_identity_to_list(permitted, pconst2);
|
||||||
|
|
||||||
|
excluded = linked_list_create();
|
||||||
|
add_identity_to_list(excluded, econst1);
|
||||||
|
add_identity_to_list(excluded, econst2);
|
||||||
|
|
||||||
|
return create_cert_lists(ca, subject, sans, flags, permitted, excluded);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
char *caconst1;
|
||||||
|
char *caconst2;
|
||||||
|
char *imconst1;
|
||||||
|
char *imconst2;
|
||||||
|
char *san1;
|
||||||
|
char *san2;
|
||||||
|
bool good;
|
||||||
|
} permitted_san_multi[] = {
|
||||||
|
{ "strongswan.org", "strongswan.com", NULL, NULL, "vpn.strongswan.org", NULL, TRUE },
|
||||||
|
{ "strongswan.org", "strongswan.com", NULL, NULL, "vpn.strongswan.com", NULL, TRUE },
|
||||||
|
{ "strongswan.org", "strongswan.com", NULL, NULL, "vpn.strongswan.org", "vpn.strongswan.com", TRUE },
|
||||||
|
{ NULL, NULL, "strongswan.org", "strongswan.com", "vpn.strongswan.org", NULL, TRUE },
|
||||||
|
{ NULL, NULL, "strongswan.org", "strongswan.com", "vpn.strongswan.com", NULL, TRUE },
|
||||||
|
{ NULL, NULL, "strongswan.org", "strongswan.com", "vpn.strongswan.org", "vpn.strongswan.com", TRUE },
|
||||||
|
{ "strongswan.org", "strongswan.com", "strongswan.org", NULL, "vpn.strongswan.org", NULL, TRUE },
|
||||||
|
{ "strongswan.org", "strongswan.com", "vpn.strongswan.org", NULL, "vpn.strongswan.org", NULL, TRUE },
|
||||||
|
{ "strongswan.org", "strongswan.com", "vpn.strongswan.org", NULL, "vpn.strongswan.org", NULL, TRUE },
|
||||||
|
{ "strongswan.org", "strongswan.com", "vpn.strongswan.org", NULL, "vpn.strongswan.org", "vpn.strongswan.com", FALSE },
|
||||||
|
{ "strongswan.org", "strongswan.com", "strongswan.com", NULL, "vpn.strongswan.org", "vpn.strongswan.com", FALSE },
|
||||||
|
{ "strongswan.org", "strongswan.com", "strongswan.org", NULL, "vpn.strongswan.com", NULL, FALSE },
|
||||||
|
{ "strongswan.org", "strongswan.com", "strongswan.com", NULL, "vpn.strongswan.org", NULL, FALSE },
|
||||||
|
{ "strongswan.org", "strongswan.com", "strongswan.com", NULL, "vpn.strongswan.com", NULL, TRUE },
|
||||||
|
{ "strongswan.org", "strongswan.com", "strongswan.net", NULL, "vpn.strongswan.com", NULL, FALSE },
|
||||||
|
{ "strongswan.org", "strongswan.com", "strongswan.net", NULL, "vpn.strongswan.org", NULL, FALSE },
|
||||||
|
{ "strongswan.org", "strongswan.com", "strongswan.net", NULL, "vpn.strongswan.net", NULL, FALSE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", NULL, NULL, "vpn.strongswan.org", NULL, TRUE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", NULL, NULL, "[email protected]", NULL, TRUE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", NULL, NULL, "vpn.strongswan.org", "[email protected]", TRUE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", "strongswan.org", NULL, "vpn.strongswan.org", NULL, TRUE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", "strongswan.org", NULL, "[email protected]", NULL, TRUE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", "strongswan.org", NULL, "vpn.strongswan.org", "[email protected]", TRUE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", "strongswan.org", "email:strongswan.com", "vpn.strongswan.org", NULL, TRUE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", "strongswan.org", "email:strongswan.com", "[email protected]", NULL, FALSE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", "strongswan.org", "email:strongswan.com", "vpn.strongswan.org", "[email protected]", FALSE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", "email:strongswan.org", NULL, "vpn.strongswan.org", NULL, TRUE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", "email:strongswan.org", NULL, "[email protected]", NULL, TRUE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", "email:strongswan.org", NULL, "vpn.strongswan.org", "[email protected]", TRUE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", "email:strongswan.org", "strongswan.com", "vpn.strongswan.org", NULL, FALSE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", "email:strongswan.org", "strongswan.com", "[email protected]", NULL, TRUE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", "email:strongswan.org", "strongswan.com", "vpn.strongswan.org", "[email protected]", FALSE },
|
||||||
|
};
|
||||||
|
|
||||||
|
START_TEST(test_permitted_san_multi)
|
||||||
|
{
|
||||||
|
certificate_t *ca, *im, *sj;
|
||||||
|
|
||||||
|
|
||||||
|
ca = create_cert_multi(NULL, "CN=CA", X509_CA, NULL, NULL,
|
||||||
|
permitted_san_multi[_i].caconst1,
|
||||||
|
permitted_san_multi[_i].caconst2, NULL, NULL);
|
||||||
|
im = create_cert_multi(ca, "CN=IM", X509_CA, NULL, NULL,
|
||||||
|
permitted_san_multi[_i].imconst1,
|
||||||
|
permitted_san_multi[_i].imconst2, NULL, NULL);
|
||||||
|
sj = create_cert_multi(im, "CN=EE", 0,
|
||||||
|
permitted_san_multi[_i].san1,
|
||||||
|
permitted_san_multi[_i].san2, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
creds->add_cert(creds, TRUE, ca);
|
||||||
|
creds->add_cert(creds, FALSE, im);
|
||||||
|
creds->add_cert(creds, FALSE, sj);
|
||||||
|
|
||||||
|
ck_assert(check_trust(sj->get_subject(sj)) == permitted_san_multi[_i].good);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
char *caconst1;
|
||||||
|
char *caconst2;
|
||||||
|
char *imconst1;
|
||||||
|
char *imconst2;
|
||||||
|
char *san1;
|
||||||
|
char *san2;
|
||||||
|
bool good;
|
||||||
|
} excluded_san_multi[] = {
|
||||||
|
{ "strongswan.org", "strongswan.com", NULL, NULL, "vpn.strongswan.org", NULL, FALSE },
|
||||||
|
{ "strongswan.org", "strongswan.com", NULL, NULL, "[email protected]", NULL, TRUE },
|
||||||
|
{ "strongswan.org", "strongswan.com", NULL, NULL, "vpn.strongswan.com", NULL, FALSE },
|
||||||
|
{ "strongswan.org", "strongswan.com", NULL, NULL, "vpn.strongswan.net", NULL, TRUE },
|
||||||
|
{ "strongswan.org", "strongswan.com", NULL, NULL, "vpn.strongswan.org", "vpn.strongswan.com", FALSE },
|
||||||
|
{ "strongswan.org", "strongswan.com", NULL, NULL, "vpn.strongswan.org", "vpn.strongswan.net", FALSE },
|
||||||
|
{ "strongswan.org", NULL, NULL, NULL, "vpn.strongswan.org", "vpn.strongswan.com", FALSE },
|
||||||
|
{ "strongswan.org", NULL, NULL, NULL, "vpn.strongswan.com", "vpn.strongswan.org", FALSE },
|
||||||
|
{ NULL, NULL, "strongswan.org", "strongswan.com", "vpn.strongswan.org", NULL, FALSE },
|
||||||
|
{ NULL, NULL, "strongswan.org", "strongswan.com", "vpn.strongswan.com", NULL, FALSE },
|
||||||
|
{ NULL, NULL, "strongswan.org", "strongswan.com", "vpn.strongswan.net", NULL, TRUE },
|
||||||
|
{ NULL, NULL, "strongswan.org", "strongswan.com", "vpn.strongswan.org", "vpn.strongswan.com", FALSE },
|
||||||
|
{ "strongswan.org", "strongswan.com", "strongswan.net", NULL, "vpn.strongswan.net", NULL, FALSE },
|
||||||
|
{ "strongswan.net", NULL, "strongswan.org", "strongswan.com", "vpn.strongswan.net", NULL, FALSE },
|
||||||
|
{ "strongswan.net", NULL, "strongswan.org", "strongswan.com", "vpn.strongswan.org", NULL, FALSE },
|
||||||
|
{ "strongswan.net", NULL, "strongswan.org", "strongswan.com", "vpn.strongswan.com", NULL, FALSE },
|
||||||
|
{ "vpn.strongswan.org", "vpn.strongswan.com", "strongswan.org", NULL, "a.strongswan.org", NULL, FALSE },
|
||||||
|
{ "vpn.strongswan.org", "vpn.strongswan.com", "strongswan.org", NULL, "vpn.strongswan.com", NULL, FALSE },
|
||||||
|
{ "vpn.strongswan.org", "vpn.strongswan.com", "strongswan.org", NULL, "a.strongswan.com", NULL, TRUE },
|
||||||
|
{ "vpn.strongswan.org", "vpn.strongswan.com", "strongswan.org", "strongswan.com", "a.strongswan.com", NULL, FALSE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", NULL, NULL, "vpn.strongswan.org", NULL, FALSE },
|
||||||
|
{ "strongswan.org", "email:strongswan.org", NULL, NULL, "[email protected]", NULL, FALSE },
|
||||||
|
};
|
||||||
|
|
||||||
|
START_TEST(test_excluded_san_multi)
|
||||||
|
{
|
||||||
|
certificate_t *ca, *im, *sj;
|
||||||
|
|
||||||
|
|
||||||
|
ca = create_cert_multi(NULL, "CN=CA", X509_CA, NULL, NULL, NULL, NULL,
|
||||||
|
excluded_san_multi[_i].caconst1,
|
||||||
|
excluded_san_multi[_i].caconst2);
|
||||||
|
im = create_cert_multi(ca, "CN=IM", X509_CA, NULL, NULL, NULL, NULL,
|
||||||
|
excluded_san_multi[_i].imconst1,
|
||||||
|
excluded_san_multi[_i].imconst2);
|
||||||
|
sj = create_cert_multi(im, "CN=EE", 0,
|
||||||
|
excluded_san_multi[_i].san1,
|
||||||
|
excluded_san_multi[_i].san2, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
creds->add_cert(creds, TRUE, ca);
|
||||||
|
creds->add_cert(creds, FALSE, im);
|
||||||
|
creds->add_cert(creds, FALSE, sj);
|
||||||
|
|
||||||
|
ck_assert(check_trust(sj->get_subject(sj)) == excluded_san_multi[_i].good);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
@@ -385,14 +688,34 @@ Suite *certnames_suite_create()
|
|||||||
tcase_add_loop_test(tc, test_excluded_san, 0, countof(excluded_san));
|
tcase_add_loop_test(tc, test_excluded_san, 0, countof(excluded_san));
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
tc = tcase_create("permitted DN name constraint inherit");
|
tc = tcase_create("permitted DN name constraints multilevel");
|
||||||
tcase_add_checked_fixture(tc, setup, teardown);
|
tcase_add_checked_fixture(tc, setup, teardown);
|
||||||
tcase_add_loop_test(tc, test_permitted_dninh, 0, countof(permitted_dninh));
|
tcase_add_loop_test(tc, test_permitted_dn_levels, 0, countof(permitted_dn_levels));
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
tc = tcase_create("excluded DN name constraint inherit");
|
tc = tcase_create("permitted subjectAltName constraints multilevel");
|
||||||
tcase_add_checked_fixture(tc, setup, teardown);
|
tcase_add_checked_fixture(tc, setup, teardown);
|
||||||
tcase_add_loop_test(tc, test_excluded_dninh, 0, countof(excluded_dninh));
|
tcase_add_loop_test(tc, test_permitted_san_levels, 0, countof(permitted_san_levels));
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
tc = tcase_create("excluded DN name constraints multilevel");
|
||||||
|
tcase_add_checked_fixture(tc, setup, teardown);
|
||||||
|
tcase_add_loop_test(tc, test_excluded_dn_levels, 0, countof(excluded_dn_levels));
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
tc = tcase_create("excluded subjectAltName constraints multilevel");
|
||||||
|
tcase_add_checked_fixture(tc, setup, teardown);
|
||||||
|
tcase_add_loop_test(tc, test_excluded_san_levels, 0, countof(excluded_san_levels));
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
tc = tcase_create("permitted subjectAltName constraints multivalue");
|
||||||
|
tcase_add_checked_fixture(tc, setup, teardown);
|
||||||
|
tcase_add_loop_test(tc, test_permitted_san_multi, 0, countof(permitted_san_multi));
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
tc = tcase_create("excluded subjectAltName constraints multivalue");
|
||||||
|
tcase_add_checked_fixture(tc, setup, teardown);
|
||||||
|
tcase_add_loop_test(tc, test_excluded_san_multi, 0, countof(excluded_san_multi));
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
|
|||||||
Reference in New Issue
Block a user