/*
+ * Copyright (C) 2023-2024 Tobias Brunner
* Copyright (C) 2010 Martin Willi
*
* Copyright (C) secunet Security Networks AG
#include <utils/debug.h>
#include <asn1/asn1.h>
+#include <collections/array.h>
+#include <collections/hashtable.h>
#include <collections/linked_list.h>
#include <credentials/certificates/x509.h>
return chunk_equals(c, i);
}
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;
}
+ if (!diff.len)
+ {
+ return TRUE;
+ }
if (c.ptr[0] == '.')
{ /* constraint is domain, suffix match */
return TRUE;
}
/**
- * 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:
+ matching = fqdn_matches(a, b);
+ break;
case ID_RFC822_ADDR:
+ matching = email_matches(a, b);
+ break;
case ID_DER_ASN1_DN:
- return constraint == id;
+ matching = dn_matches(a, b);
+ break;
case ID_IPV4_ADDR_SUBNET:
- return id == ID_IPV4_ADDR;
case ID_IPV6_ADDR_SUBNET:
- return id == ID_IPV6_ADDR;
+ matching = b->matches(b, a);
+ break;
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 the given identity matches any of the given name constraints
+ */
+static bool id_matches_constraints(certificate_t *cert, identification_t *id,
+ array_t *constraints, bool permitted)
+{
+ enumerator_t *enumerator;
+ identification_t *subject, *constraint;
+ id_type_t type;
+ bool matches = FALSE;
+
+ subject = cert->get_subject(cert);
+ type = id->get_type(id);
+
+ enumerator = array_create_enumerator(constraints);
+ while (enumerator->enumerate(enumerator, &constraint))
+ {
+ switch (type)
+ {
+ case ID_FQDN:
+ matches = fqdn_matches(constraint, id);
+ break;
+ case ID_RFC822_ADDR:
+ matches = email_matches(constraint, id);
+ break;
+ case ID_DER_ASN1_DN:
+ matches = dn_matches(constraint, id);
+ break;
+ case ID_IPV4_ADDR:
+ case ID_IPV6_ADDR:
+ matches = id->matches(id, constraint);
+ break;
+ default:
+ /* shouldn't happen */
+ break;
+ }
+ 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;
+ }
+ }
+ 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 to a NameConstraint
+ * Check if a certificate matches the given permitted/excluded name constraints
*/
-static bool name_constraint_matches(identification_t *constraint,
- certificate_t *cert, bool permitted)
+static bool cert_matches_constraints(x509_t *x509, hashtable_t *types,
+ bool permitted)
{
- x509_t *x509 = (x509_t*)cert;
+ certificate_t *cert = (certificate_t*)x509;
+ array_t *constraints;
enumerator_t *enumerator;
identification_t *id;
id_type_t type;
bool matches = permitted;
- type = constraint->get_type(constraint);
- if (type == ID_DER_ASN1_DN)
+ constraints = types->get(types, (void*)(uintptr_t)ID_DER_ASN1_DN);
+ if (constraints)
{
- matches = dn_matches(constraint, cert->get_subject(cert));
+ 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))
{
- if (type_matches(type, id->get_type(id)))
+ type = constraint_type_from_id(id->get_type(id));
+ constraints = types->get(types, (void*)(uintptr_t)type);
+ if (constraints)
{
- switch (type)
+ matches = id_matches_constraints(cert, id, constraints, permitted);
+ if (matches != permitted)
{
- case ID_FQDN:
- matches = fqdn_matches(constraint, id);
- break;
- case ID_RFC822_ADDR:
- matches = email_matches(constraint, id);
- break;
- case ID_DER_ASN1_DN:
- matches = dn_matches(constraint, id);
- break;
- case ID_IPV4_ADDR_SUBNET:
- case ID_IPV6_ADDR_SUBNET:
- matches = id->matches(id, constraint);
- break;
- default:
- DBG1(DBG_CFG, "%N NameConstraint matching not implemented",
- id_type_names, type);
- matches = FALSE;
- break;
+ break;
}
}
- if (matches != permitted)
- {
- break;
- }
}
enumerator->destroy(enumerator);
}
/**
- * 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_constraints_match(x509_t *x509, hashtable_t *permitted,
+ hashtable_t *excluded)
+{
+ if (permitted && !cert_matches_constraints(x509, permitted, TRUE))
+ {
+ return FALSE;
+ }
+ if (excluded && cert_matches_constraints(x509, excluded, FALSE))
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * 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 name_constraint_inherited(identification_t *constraint,
- x509_t *x509, bool permitted)
+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 *id, *a, *b;
- bool inherited = FALSE;
+ identification_t *constraint;
+ array_t *constraints;
id_type_t type;
+ bool success = TRUE;
- if (!(x509->get_flags(x509) & X509_CA))
- { /* not a sub-CA, not required */
- return TRUE;
- }
+ collected = hashtable_create(id_type_hash, id_type_equals, 8);
- type = constraint->get_type(constraint);
enumerator = x509->create_name_constraint_enumerator(x509, permitted);
- while (enumerator->enumerate(enumerator, &id))
+ while (enumerator->enumerate(enumerator, &constraint))
+ {
+ type = constraint->get_type(constraint);
+ switch (type)
+ {
+ case ID_FQDN:
+ case ID_RFC822_ADDR:
+ case ID_DER_ASN1_DN:
+ case ID_IPV4_ADDR_SUBNET:
+ case ID_IPV6_ADDR_SUBNET:
+ break;
+ default:
+ DBG1(DBG_CFG, "%N NameConstraint not supported",
+ id_type_names, type);
+ success = FALSE;
+ break;
+ }
+ if (!success)
+ {
+ 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);
+
+ if (success)
+ {
+ *out = collected;
+ }
+ else
{
- if (id->get_type(id) == type)
+ 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))
{
- if (permitted)
- { /* permitted constraint can be narrowed */
- a = constraint;
- b = id;
+ 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);
+ }
}
- else
- { /* excluded constraint can be widened */
- a = id;
- b = constraint;
+ 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);
}
- switch (type)
+ 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))
{
- case ID_FQDN:
- inherited = fqdn_matches(a, b);
- break;
- case ID_RFC822_ADDR:
- inherited = email_matches(a, b);
- break;
- case ID_DER_ASN1_DN:
- inherited = dn_matches(a, b);
- break;
- default:
- DBG1(DBG_CFG, "%N NameConstraint matching not implemented",
- id_type_names, type);
- inherited = FALSE;
+ 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);
}
- if (inherited)
+ enumerator->destroy(enumerator);
+
+ /* add all new constraints to the list */
+ while (array_remove(new_constraints, ARRAY_HEAD, &new_constraint))
{
- break;
+ array_insert(existing_constraints, ARRAY_TAIL, new_constraint);
}
}
- enumerator->destroy(enumerator);
- return inherited;
}
/**
- * Check name constraints
+ * Update the set of permitted/excluded name constraints
*/
-static bool check_name_constraints(certificate_t *subject, x509_t *issuer)
+static bool update_name_constraints(x509_t *x509, hashtable_t **existing,
+ bool permitted)
{
enumerator_t *enumerator;
- identification_t *constraint;
+ hashtable_t *collected;
+ array_t *existing_constraints, *new_constraints;
+ void *type;
- enumerator = issuer->create_name_constraint_enumerator(issuer, TRUE);
- while (enumerator->enumerate(enumerator, &constraint))
+ if (!(x509->get_flags(x509) & X509_CA))
+ {
+ /* ignore end-entity certificates */
+ return TRUE;
+ }
+
+ if (!collect_constraints(x509, permitted, &collected))
{
- if (!name_constraint_matches(constraint, subject, TRUE))
+ return FALSE;
+ }
+ if (collected->get_count(collected))
+ {
+ if (!*existing)
{
- DBG1(DBG_CFG, "certificate '%Y' does not match permitted name "
- "constraint '%Y'", subject->get_subject(subject), constraint);
- enumerator->destroy(enumerator);
- return FALSE;
+ /* adopt all constraints if we haven't any yet */
+ *existing = collected;
+ collected = NULL;
}
- if (!name_constraint_inherited(constraint, (x509_t*)subject, TRUE))
+ else
{
- DBG1(DBG_CFG, "intermediate CA '%Y' does not inherit permitted name "
- "constraint '%Y'", subject->get_subject(subject), constraint);
+ /* 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);
- return FALSE;
}
}
- enumerator->destroy(enumerator);
+ DESTROY_FUNCTION_IF(collected, destroy_constraints);
+ return TRUE;
+}
- enumerator = issuer->create_name_constraint_enumerator(issuer, FALSE);
- while (enumerator->enumerate(enumerator, &constraint))
+/**
+ * Check name constraints
+ */
+static bool check_name_constraints(x509_t *issuer, u_int pathlen,
+ auth_cfg_t *auth, certificate_t **violator)
+{
+ enumerator_t *enumerator;
+ 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;
+
+ subject = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+ if (!subject || subject->get_type(subject) != CERT_X509)
+ {
+ 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 (name_constraint_matches(constraint, subject, FALSE))
+ if (rule == AUTH_RULE_IM_CERT &&
+ cert->get_type(cert) == CERT_X509)
{
- DBG1(DBG_CFG, "certificate '%Y' matches excluded name "
- "constraint '%Y'", subject->get_subject(subject), constraint);
- enumerator->destroy(enumerator);
- return FALSE;
+ chain->insert_first(chain, cert);
}
- if (!name_constraint_inherited(constraint, (x509_t*)subject, FALSE))
+ }
+ 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))
{
- DBG1(DBG_CFG, "intermediate CA '%Y' does not inherit excluded name "
- "constraint '%Y'", subject->get_subject(subject), constraint);
- enumerator->destroy(enumerator);
- return FALSE;
+ valid = FALSE;
+ *violator = (certificate_t*)x509;
+ break;
}
+ len++;
}
enumerator->destroy(enumerator);
- return TRUE;
+
+ DESTROY_FUNCTION_IF(permitted, destroy_constraints);
+ DESTROY_FUNCTION_IF(excluded, destroy_constraints);
+ chain->destroy(chain);
+ return valid;
}
/**
subject);
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)
{
+ 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))
{
lib->credmgr->call_hook(lib->credmgr,
/**
* Issue a certificate with permitted/excluded name constraints
*/
-static certificate_t* create_cert(certificate_t *ca, char *subject, char *san,
- x509_flag_t flags, identification_t *permitted,
- identification_t *excluded)
+static certificate_t* create_cert_lists(certificate_t *ca, char *subject,
+ linked_list_t *sans, x509_flag_t flags,
+ linked_list_t *permitted,
+ linked_list_t *excluded)
{
private_key_t *privkey;
public_key_t *pubkey;
certificate_t *cert;
identification_t *id;
- linked_list_t *plist, *elist, *sans;
privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
BUILD_BLOB_ASN1_DER, chunk_from_thing(keydata),
ck_assert(privkey);
pubkey = privkey->get_public_key(privkey);
ck_assert(pubkey);
- plist = linked_list_create();
- if (permitted)
- {
- plist->insert_last(plist, permitted);
- }
- elist = linked_list_create();
- if (excluded)
- {
- elist->insert_last(elist, excluded);
- }
- sans = linked_list_create();
- if (san)
- {
- id = identification_create_from_string(san);
- sans->insert_last(sans, id);
- }
+
id = identification_create_from_string(subject);
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_SIGNING_KEY, privkey,
BUILD_X509_FLAG, flags,
BUILD_SIGNING_CERT, ca,
BUILD_SUBJECT_ALTNAMES, sans,
- BUILD_PERMITTED_NAME_CONSTRAINTS, plist,
- BUILD_EXCLUDED_NAME_CONSTRAINTS, elist,
+ 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));
- plist->destroy_offset(plist, offsetof(identification_t, destroy));
- elist->destroy_offset(elist, 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();
+ if (permitted)
+ {
+ plist->insert_last(plist, permitted);
+ }
+ elist = linked_list_create();
+ if (excluded)
+ {
+ elist->insert_last(elist, excluded);
+ }
+ sans = linked_list_create();
+ if (san)
+ {
+ id = identification_create_from_string(san);
+ sans->insert_last(sans, id);
+ }
+ return create_cert_lists(ca, subject, sans, flags, plist, elist);
+}
+
/**
* Check if a certificate with given subject has a valid trustchain
*/
END_TEST
static struct {
- id_type_t ctype;
char *cdata;
char *subject;
bool good;
} permitted_san[] = {
- { ID_FQDN, ".strongswan.org", "test.strongswan.org", TRUE },
- { ID_FQDN, "strongswan.org", "test.strongswan.org", TRUE },
- { ID_FQDN, "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 },
- { ID_FQDN, "strongswan.org", "strongswan.org.com", FALSE },
- { ID_FQDN, ".strongswan.org", "strongswan.org", FALSE },
- { ID_FQDN, "strongswan.org", "nostrongswan.org", FALSE },
- { ID_FQDN, "strongswan.org", "swan.org", FALSE },
- { ID_FQDN, "strongswan.org", "swan.org", FALSE },
- { ID_RFC822_ADDR, "tester@strongswan.org", "tester@strongswan.org", TRUE },
- { ID_RFC822_ADDR, "tester@strongswan.org", "atester@strongswan.org", FALSE },
- { ID_RFC822_ADDR, "strongswan.org", "tester@strongswan.org", TRUE },
- { ID_RFC822_ADDR, "strongswan.org", "tester@test.strongswan.org", FALSE },
- { ID_RFC822_ADDR, ".strongswan.org", "tester@test.strongswan.org", TRUE },
- { ID_RFC822_ADDR, ".strongswan.org", "tester@strongswan.org", FALSE },
+ { ".strongswan.org", "test.strongswan.org", TRUE },
+ { "strongswan.org", "test.strongswan.org", TRUE },
+ { "a.b.c.strongswan.org", "d.a.b.c.strongswan.org", TRUE },
+ { "a.b.c.strongswan.org", "a.b.c.d.strongswan.org", FALSE },
+ { "strongswan.org", "strongswan.org.com", FALSE },
+ { ".strongswan.org", "strongswan.org", FALSE },
+ { "strongswan.org", "nostrongswan.org", FALSE },
+ { "strongswan.org", "swan.org", FALSE },
+ { "strongswan.org", "swan.org", FALSE },
+ { "tester@strongswan.org", "tester@strongswan.org", TRUE },
+ { "tester@strongswan.org", "atester@strongswan.org", FALSE },
+ { "email:strongswan.org", "tester@strongswan.org", TRUE },
+ { "email:strongswan.org", "tester@test.strongswan.org", FALSE },
+ { "email:.strongswan.org", "tester@test.strongswan.org", TRUE },
+ { "email:.strongswan.org", "tester@strongswan.org", 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)
certificate_t *ca, *sj;
identification_t *id;
- id = identification_create_from_encoding(permitted_san[_i].ctype,
- chunk_from_str(permitted_san[_i].cdata));
+ id = identification_create_from_string(permitted_san[_i].cdata);
ca = create_cert(NULL, "CN=CA", NULL, X509_CA, id, NULL);
sj = create_cert(ca, "CN=SJ", permitted_san[_i].subject, 0, NULL, NULL);
END_TEST
static struct {
- id_type_t ctype;
char *cdata;
char *subject;
bool good;
} excluded_san[] = {
- { ID_FQDN, ".strongswan.org", "test.strongswan.org", FALSE },
- { ID_FQDN, "strongswan.org", "test.strongswan.org", FALSE },
- { ID_FQDN, "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 },
- { ID_FQDN, "strongswan.org", "strongswan.org.com", TRUE },
- { ID_FQDN, ".strongswan.org", "strongswan.org", TRUE },
- { ID_FQDN, "strongswan.org", "nostrongswan.org", TRUE },
- { ID_FQDN, "strongswan.org", "swan.org", TRUE },
- { ID_FQDN, "strongswan.org", "swan.org", TRUE },
- { ID_RFC822_ADDR, "tester@strongswan.org", "tester@strongswan.org", FALSE },
- { ID_RFC822_ADDR, "tester@strongswan.org", "atester@strongswan.org", TRUE },
- { ID_RFC822_ADDR, "strongswan.org", "tester@strongswan.org", FALSE },
- { ID_RFC822_ADDR, "strongswan.org", "tester@test.strongswan.org", TRUE },
- { ID_RFC822_ADDR, ".strongswan.org", "tester@test.strongswan.org", FALSE },
- { ID_RFC822_ADDR, ".strongswan.org", "tester@strongswan.org", TRUE },
+ { ".strongswan.org", "test.strongswan.org", FALSE },
+ { "strongswan.org", "test.strongswan.org", FALSE },
+ { "a.b.c.strongswan.org", "d.a.b.c.strongswan.org", FALSE },
+ { "a.b.c.strongswan.org", "a.b.c.d.strongswan.org", TRUE },
+ { "strongswan.org", "strongswan.org.com", TRUE },
+ { ".strongswan.org", "strongswan.org", TRUE },
+ { "strongswan.org", "nostrongswan.org", TRUE },
+ { "strongswan.org", "swan.org", TRUE },
+ { "strongswan.org", "swan.org", TRUE },
+ { "tester@strongswan.org", "tester@strongswan.org", FALSE },
+ { "tester@strongswan.org", "atester@strongswan.org", TRUE },
+ { "email:strongswan.org", "tester@strongswan.org", FALSE },
+ { "email:strongswan.org", "tester@test.strongswan.org", TRUE },
+ { "email:.strongswan.org", "tester@test.strongswan.org", FALSE },
+ { "email:.strongswan.org", "tester@strongswan.org", 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)
certificate_t *ca, *sj;
identification_t *id;
- id = identification_create_from_encoding(excluded_san[_i].ctype,
- chunk_from_str(excluded_san[_i].cdata));
+ id = identification_create_from_string(excluded_san[_i].cdata);
ca = create_cert(NULL, "CN=CA", NULL, X509_CA, NULL, id);
sj = create_cert(ca, "CN=SJ", excluded_san[_i].subject, 0, NULL, NULL);
}
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 {
char *caconst;
char *imconst;
char *subject;
bool good;
-} permitted_dninh[] = {
+} permitted_dn_levels[] = {
{ "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", "C=DE, O=strongSwan, CN=tester", 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;
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);
- 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);
- 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, FALSE, im);
+ creds->add_cert(creds, FALSE, sj);
+
+ ck_assert(check_trust(sj->get_subject(sj)) == permitted_dn_levels[_i].good);
+}
+END_TEST
+
+static struct {
+ char *caconst;
+ char *imconst;
+ char *subject;
+ bool good;
+} permitted_san_levels[] = {
+ { "strongswan.org", NULL, "strongswan.org", TRUE },
+ { "strongswan.org", NULL, "vpn.strongswan.org", TRUE },
+ { "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, "tester@strongswan.org", TRUE },
+ { "tester@strongswan.org", NULL, "tester@strongswan.org", TRUE },
+ { "email:strongswan.org", NULL, "tester@strongswan.org", TRUE },
+ { "email:strongswan.org", NULL, "tester@strongswan.com", FALSE },
+ { "email:strongswan.org", "tester@strongswan.org", "tester@strongswan.org", TRUE },
+ { "email:strongswan.org", "tester@strongswan.org", "alice@strongswan.org", 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_permitted_san_levels)
+{
+ certificate_t *ca, *im, *sj;
+ identification_t *id;
+
+ id = create_test_id(permitted_san_levels[_i].caconst);
+ ca = create_cert(NULL, "CN=CA", NULL, X509_CA, id, NULL);
+ id = create_test_id(permitted_san_levels[_i].imconst);
+ im = create_cert(ca, "CN=IM", NULL, X509_CA, id, 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, FALSE, im);
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_san_levels[_i].good);
}
END_TEST
char *imconst;
char *subject;
bool good;
-} excluded_dninh[] = {
+} excluded_dn_levels[] = {
{ "C=CH, O=strongSwan", "C=CH", "C=DE", TRUE },
- { "C=CH, O=strongSwan", "C=DE", "C=CH", FALSE },
+ { "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_dninh)
+START_TEST(test_excluded_dn_levels)
{
certificate_t *ca, *im, *sj;
identification_t *id;
- id = identification_create_from_string(excluded_dninh[_i].caconst);
+ 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 = identification_create_from_string(excluded_dninh[_i].imconst);
+ 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_dninh[_i].subject, NULL, 0, NULL, NULL);
+ 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_dninh[_i].good);
+ 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, "tester@strongswan.org", TRUE },
+ { "tester@strongswan.org", NULL, "tester@strongswan.org", FALSE },
+ { "tester@strongswan.org", NULL, "alice@strongswan.org", TRUE },
+ { "email:strongswan.org", NULL, "tester@strongswan.org", FALSE },
+ { "email:strongswan.org", NULL, "tester@strongswan.com", TRUE },
+ { "email:strongswan.org", "email:strongswan.com", "tester@strongswan.org", FALSE },
+ { "email:strongswan.org", "email:strongswan.com", "tester@strongswan.com", FALSE },
+ { "strongswan.org", "email:strongswan.com", "tester@strongswan.com", 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, "tester@strongswan.org", NULL, TRUE },
+ { "strongswan.org", "email:strongswan.org", NULL, NULL, "vpn.strongswan.org", "tester@strongswan.org", TRUE },
+ { "strongswan.org", "email:strongswan.org", "strongswan.org", NULL, "vpn.strongswan.org", NULL, TRUE },
+ { "strongswan.org", "email:strongswan.org", "strongswan.org", NULL, "tester@strongswan.org", NULL, TRUE },
+ { "strongswan.org", "email:strongswan.org", "strongswan.org", NULL, "vpn.strongswan.org", "tester@strongswan.org", 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", "tester@strongswan.org", NULL, FALSE },
+ { "strongswan.org", "email:strongswan.org", "strongswan.org", "email:strongswan.com", "vpn.strongswan.org", "tester@strongswan.org", FALSE },
+ { "strongswan.org", "email:strongswan.org", "email:strongswan.org", NULL, "vpn.strongswan.org", NULL, TRUE },
+ { "strongswan.org", "email:strongswan.org", "email:strongswan.org", NULL, "tester@strongswan.org", NULL, TRUE },
+ { "strongswan.org", "email:strongswan.org", "email:strongswan.org", NULL, "vpn.strongswan.org", "tester@strongswan.org", 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", "tester@strongswan.org", NULL, TRUE },
+ { "strongswan.org", "email:strongswan.org", "email:strongswan.org", "strongswan.com", "vpn.strongswan.org", "tester@strongswan.org", 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, "tester@strongswan.org", 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, "tester@strongswan.org", 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
tcase_add_loop_test(tc, test_excluded_san, 0, countof(excluded_san));
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_loop_test(tc, test_permitted_dn_levels, 0, countof(permitted_dn_levels));
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("permitted subjectAltName constraints multilevel");
+ tcase_add_checked_fixture(tc, setup, teardown);
+ 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_dninh, 0, countof(permitted_dninh));
+ tcase_add_loop_test(tc, test_permitted_san_multi, 0, countof(permitted_san_multi));
suite_add_tcase(s, tc);
- tc = tcase_create("excluded DN name constraint inherit");
+ tc = tcase_create("excluded subjectAltName constraints multivalue");
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_excluded_san_multi, 0, countof(excluded_san_multi));
suite_add_tcase(s, tc);
return s;