summaryrefslogtreecommitdiff
path: root/src/libstrongswan/credentials
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2013-04-26 14:57:47 +0200
committerYves-Alexis Perez <corsac@debian.org>2013-04-26 14:57:47 +0200
commit10e5fb2b9b2f27c83b3e5a1d048b158d5cf42a43 (patch)
treebf1d05a2e37dbd1911b86fcc026fbe49b0239c71 /src/libstrongswan/credentials
parent7585facf05d927eb6df3929ce09ed5e60d905437 (diff)
downloadvyos-strongswan-10e5fb2b9b2f27c83b3e5a1d048b158d5cf42a43.tar.gz
vyos-strongswan-10e5fb2b9b2f27c83b3e5a1d048b158d5cf42a43.zip
Imported Upstream version 5.0.3
Diffstat (limited to 'src/libstrongswan/credentials')
-rw-r--r--src/libstrongswan/credentials/auth_cfg.c56
-rw-r--r--src/libstrongswan/credentials/cert_validator.h17
-rw-r--r--src/libstrongswan/credentials/cred_encoding.h2
-rw-r--r--src/libstrongswan/credentials/credential_manager.c116
-rw-r--r--src/libstrongswan/credentials/sets/mem_cred.c61
-rw-r--r--src/libstrongswan/credentials/sets/mem_cred.h12
6 files changed, 227 insertions, 37 deletions
diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c
index a718de3dc..d2d0a7d72 100644
--- a/src/libstrongswan/credentials/auth_cfg.c
+++ b/src/libstrongswan/credentials/auth_cfg.c
@@ -76,7 +76,6 @@ static inline bool is_multi_value_rule(auth_rule_t type)
case AUTH_RULE_AAA_IDENTITY:
case AUTH_RULE_XAUTH_IDENTITY:
case AUTH_RULE_XAUTH_BACKEND:
- case AUTH_RULE_SUBJECT_CERT:
case AUTH_HELPER_SUBJECT_CERT:
case AUTH_HELPER_SUBJECT_HASH_URL:
case AUTH_RULE_MAX:
@@ -84,6 +83,7 @@ static inline bool is_multi_value_rule(auth_rule_t type)
case AUTH_RULE_OCSP_VALIDATION:
case AUTH_RULE_CRL_VALIDATION:
case AUTH_RULE_GROUP:
+ case AUTH_RULE_SUBJECT_CERT:
case AUTH_RULE_CA_CERT:
case AUTH_RULE_IM_CERT:
case AUTH_RULE_CERT_POLICY:
@@ -503,8 +503,9 @@ METHOD(auth_cfg_t, complies, bool,
private_auth_cfg_t *this, auth_cfg_t *constraints, bool log_error)
{
enumerator_t *e1, *e2;
- bool success = TRUE, group_match = FALSE;
+ bool success = TRUE, group_match = FALSE, cert_match = FALSE;
identification_t *require_group = NULL;
+ certificate_t *require_cert = NULL;
signature_scheme_t scheme = SIGN_UNKNOWN;
u_int strength = 0;
auth_rule_t t1, t2;
@@ -542,20 +543,21 @@ METHOD(auth_cfg_t, complies, bool,
}
case AUTH_RULE_SUBJECT_CERT:
{
- certificate_t *c1, *c2;
+ certificate_t *cert;
- c1 = (certificate_t*)value;
- c2 = get(this, AUTH_RULE_SUBJECT_CERT);
- if (!c2 || !c1->equals(c1, c2))
+ /* for certs, a match of a single cert is sufficient */
+ require_cert = (certificate_t*)value;
+
+ e2 = create_enumerator(this);
+ while (e2->enumerate(e2, &t2, &cert))
{
- success = FALSE;
- if (log_error)
+ if (t2 == AUTH_RULE_SUBJECT_CERT &&
+ cert->equals(cert, require_cert))
{
- DBG1(DBG_CFG, "constraint check failed: peer not "
- "authenticated with peer cert '%Y'.",
- c1->get_subject(c1));
+ cert_match = TRUE;
}
}
+ e2->destroy(e2);
break;
}
case AUTH_RULE_CRL_VALIDATION:
@@ -828,6 +830,17 @@ METHOD(auth_cfg_t, complies, bool,
}
return FALSE;
}
+
+ if (require_cert && !cert_match)
+ {
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint check failed: peer not "
+ "authenticated with peer cert '%Y'.",
+ require_cert->get_subject(require_cert));
+ }
+ return FALSE;
+ }
return success;
}
@@ -999,14 +1012,15 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
{
enumerator_t *enumerator;
auth_cfg_t *clone;
- entry_t *entry;
+ auth_rule_t type;
+ void *value;
clone = auth_cfg_create();
/* this enumerator skips duplicates for rules we expect only once */
- enumerator = this->entries->create_enumerator(this->entries);
- while (enumerator->enumerate(enumerator, &entry))
+ enumerator = create_enumerator(this);
+ while (enumerator->enumerate(enumerator, &type, &value))
{
- switch (entry->type)
+ switch (type)
{
case AUTH_RULE_IDENTITY:
case AUTH_RULE_EAP_IDENTITY:
@@ -1014,8 +1028,8 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
case AUTH_RULE_GROUP:
case AUTH_RULE_XAUTH_IDENTITY:
{
- identification_t *id = (identification_t*)entry->value;
- clone->add(clone, entry->type, id->clone(id));
+ identification_t *id = (identification_t*)value;
+ clone->add(clone, type, id->clone(id));
break;
}
case AUTH_RULE_CA_CERT:
@@ -1025,8 +1039,8 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
case AUTH_HELPER_SUBJECT_CERT:
case AUTH_HELPER_REVOCATION_CERT:
{
- certificate_t *cert = (certificate_t*)entry->value;
- clone->add(clone, entry->type, cert->get_ref(cert));
+ certificate_t *cert = (certificate_t*)value;
+ clone->add(clone, type, cert->get_ref(cert));
break;
}
case AUTH_RULE_XAUTH_BACKEND:
@@ -1034,7 +1048,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
case AUTH_HELPER_IM_HASH_URL:
case AUTH_HELPER_SUBJECT_HASH_URL:
{
- clone->add(clone, entry->type, strdup(entry->value));
+ clone->add(clone, type, strdup(value));
break;
}
case AUTH_RULE_IDENTITY_LOOSE:
@@ -1046,7 +1060,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
case AUTH_RULE_RSA_STRENGTH:
case AUTH_RULE_ECDSA_STRENGTH:
case AUTH_RULE_SIGNATURE_SCHEME:
- clone->add(clone, entry->type, (uintptr_t)entry->value);
+ clone->add(clone, type, (uintptr_t)value);
break;
case AUTH_RULE_MAX:
break;
diff --git a/src/libstrongswan/credentials/cert_validator.h b/src/libstrongswan/credentials/cert_validator.h
index 00e30d7a0..325fa0af3 100644
--- a/src/libstrongswan/credentials/cert_validator.h
+++ b/src/libstrongswan/credentials/cert_validator.h
@@ -35,6 +35,22 @@ typedef struct cert_validator_t cert_validator_t;
struct cert_validator_t {
/**
+ * Check the lifetime of a certificate.
+ *
+ * If this function returns SUCCESS or FAILED, the certificate lifetime is
+ * considered definitely (in-)valid, without asking other validators.
+ * If all registered validaters return NEED_MORE, the default
+ * lifetime check is performed.
+ *
+ * @param cert certificate to check lifetime
+ * @param pathlen the current length of the path bottom-up
+ * @param anchor is certificate trusted root anchor?
+ * @param auth container for resulting authentication info
+ * @return SUCCESS, FAILED or NEED_MORE to ask next validator
+ */
+ status_t (*check_lifetime)(cert_validator_t *this, certificate_t *cert,
+ int pathlen, bool anchor, auth_cfg_t *auth);
+ /**
* Validate a subject certificate in relation to its issuer.
*
* @param subject subject certificate to check
@@ -43,6 +59,7 @@ struct cert_validator_t {
* @param pathlen the current length of the path bottom-up
* @param anchor is issuer trusted root anchor
* @param auth container for resulting authentication info
+ * @return TRUE if subject certificate valid
*/
bool (*validate)(cert_validator_t *this, certificate_t *subject,
certificate_t *issuer, bool online, u_int pathlen,
diff --git a/src/libstrongswan/credentials/cred_encoding.h b/src/libstrongswan/credentials/cred_encoding.h
index b029fe2ac..41481f376 100644
--- a/src/libstrongswan/credentials/cred_encoding.h
+++ b/src/libstrongswan/credentials/cred_encoding.h
@@ -85,6 +85,8 @@ enum cred_encoding_type_t {
/** PGP key encoding */
PUBKEY_PGP,
PRIVKEY_PGP,
+ /** DNSKEY encoding */
+ PUBKEY_DNSKEY,
/** ASN.1 DER encoded certificate */
CERT_ASN1_DER,
diff --git a/src/libstrongswan/credentials/credential_manager.c b/src/libstrongswan/credentials/credential_manager.c
index 9e40c5a10..f4cd9b9e6 100644
--- a/src/libstrongswan/credentials/credential_manager.c
+++ b/src/libstrongswan/credentials/credential_manager.c
@@ -515,32 +515,74 @@ static void cache_queue(private_credential_manager_t *this)
}
/**
+ * Use validators to check the lifetime of certificates
+ */
+static bool check_lifetime(private_credential_manager_t *this,
+ certificate_t *cert, char *label,
+ int pathlen, bool trusted, auth_cfg_t *auth)
+{
+ time_t not_before, not_after;
+ cert_validator_t *validator;
+ enumerator_t *enumerator;
+ status_t status = NEED_MORE;
+
+ enumerator = this->validators->create_enumerator(this->validators);
+ while (enumerator->enumerate(enumerator, &validator))
+ {
+ if (!validator->check_lifetime)
+ {
+ continue;
+ }
+ status = validator->check_lifetime(validator, cert,
+ pathlen, trusted, auth);
+ if (status != NEED_MORE)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ switch (status)
+ {
+ case NEED_MORE:
+ if (!cert->get_validity(cert, NULL, &not_before, &not_after))
+ {
+ DBG1(DBG_CFG, "%s certificate invalid (valid from %T to %T)",
+ label, &not_before, FALSE, &not_after, FALSE);
+ return FALSE;
+ }
+ return TRUE;
+ case SUCCESS:
+ return TRUE;
+ case FAILED:
+ default:
+ return FALSE;
+ }
+}
+
+/**
* check a certificate for its lifetime
*/
static bool check_certificate(private_credential_manager_t *this,
certificate_t *subject, certificate_t *issuer, bool online,
int pathlen, bool trusted, auth_cfg_t *auth)
{
- time_t not_before, not_after;
cert_validator_t *validator;
enumerator_t *enumerator;
- if (!subject->get_validity(subject, NULL, &not_before, &not_after))
+ if (!check_lifetime(this, subject, "subject", pathlen, FALSE, auth) ||
+ !check_lifetime(this, issuer, "issuer", pathlen + 1, trusted, auth))
{
- DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)",
- &not_before, FALSE, &not_after, FALSE);
- return FALSE;
- }
- if (!issuer->get_validity(issuer, NULL, &not_before, &not_after))
- {
- DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)",
- &not_before, FALSE, &not_after, FALSE);
return FALSE;
}
enumerator = this->validators->create_enumerator(this->validators);
while (enumerator->enumerate(enumerator, &validator))
{
+ if (!validator->validate)
+ {
+ continue;
+ }
if (!validator->validate(validator, subject, issuer,
online, pathlen, trusted, auth))
{
@@ -1041,6 +1083,29 @@ static private_key_t *get_private_by_cert(private_credential_manager_t *this,
return private;
}
+/**
+ * Move the actually used certificate to front, so it gets returned with get()
+ */
+static void prefer_cert(auth_cfg_t *auth, certificate_t *cert)
+{
+ enumerator_t *enumerator;
+ auth_rule_t rule;
+ certificate_t *current;
+
+ enumerator = auth->create_enumerator(auth);
+ while (enumerator->enumerate(enumerator, &rule, &current))
+ {
+ if (rule == AUTH_RULE_SUBJECT_CERT)
+ {
+ current->get_ref(current);
+ auth->replace(auth, enumerator, AUTH_RULE_SUBJECT_CERT, cert);
+ cert = current;
+ }
+ }
+ enumerator->destroy(enumerator);
+ auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert);
+}
+
METHOD(credential_manager_t, get_private, private_key_t*,
private_credential_manager_t *this, key_type_t type, identification_t *id,
auth_cfg_t *auth)
@@ -1049,6 +1114,7 @@ METHOD(credential_manager_t, get_private, private_key_t*,
certificate_t *cert;
private_key_t *private = NULL;
auth_cfg_t *trustchain;
+ auth_rule_t rule;
/* check if this is a lookup by key ID, and do it if so */
if (id && id->get_type(id) == ID_KEY_ID)
@@ -1062,7 +1128,35 @@ METHOD(credential_manager_t, get_private, private_key_t*,
if (auth)
{
- /* if a specific certificate is preferred, check for a matching key */
+ /* try to find a trustchain with one of the configured subject certs */
+ enumerator = auth->create_enumerator(auth);
+ while (enumerator->enumerate(enumerator, &rule, &cert))
+ {
+ if (rule == AUTH_RULE_SUBJECT_CERT)
+ {
+ private = get_private_by_cert(this, cert, type);
+ if (private)
+ {
+ trustchain = build_trustchain(this, cert, auth);
+ if (trustchain)
+ {
+ auth->merge(auth, trustchain, FALSE);
+ prefer_cert(auth, cert->get_ref(cert));
+ trustchain->destroy(trustchain);
+ break;
+ }
+ private->destroy(private);
+ private = NULL;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (private)
+ {
+ return private;
+ }
+
+ /* if none yielded a trustchain, enforce the first configured cert */
cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
if (cert)
{
diff --git a/src/libstrongswan/credentials/sets/mem_cred.c b/src/libstrongswan/credentials/sets/mem_cred.c
index d697a56ef..b8da3f620 100644
--- a/src/libstrongswan/credentials/sets/mem_cred.c
+++ b/src/libstrongswan/credentials/sets/mem_cred.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Tobias Brunner
+ * Copyright (C) 2010-2013 Tobias Brunner
* Hochschule fuer Technik Rapperwsil
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
@@ -555,14 +555,66 @@ METHOD(credential_set_t, create_cdp_enumerator, enumerator_t*,
}
-METHOD(mem_cred_t, clear_secrets, void,
- private_mem_cred_t *this)
+static void reset_secrets(private_mem_cred_t *this)
{
- this->lock->write_lock(this->lock);
this->keys->destroy_offset(this->keys, offsetof(private_key_t, destroy));
this->shared->destroy_function(this->shared, (void*)shared_entry_destroy);
this->keys = linked_list_create();
this->shared = linked_list_create();
+}
+
+METHOD(mem_cred_t, replace_secrets, void,
+ private_mem_cred_t *this, mem_cred_t *other_set, bool clone)
+{
+ private_mem_cred_t *other = (private_mem_cred_t*)other_set;
+ enumerator_t *enumerator;
+ shared_entry_t *entry, *new_entry;
+ private_key_t *key;
+
+ this->lock->write_lock(this->lock);
+
+ reset_secrets(this);
+
+ if (clone)
+ {
+ enumerator = other->keys->create_enumerator(other->keys);
+ while (enumerator->enumerate(enumerator, &key))
+ {
+ this->keys->insert_last(this->keys, key->get_ref(key));
+ }
+ enumerator->destroy(enumerator);
+ enumerator = other->shared->create_enumerator(other->shared);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ INIT(new_entry,
+ .shared = entry->shared->get_ref(entry->shared),
+ .owners = entry->owners->clone_offset(entry->owners,
+ offsetof(identification_t, clone)),
+ );
+ this->shared->insert_last(this->shared, new_entry);
+ }
+ enumerator->destroy(enumerator);
+ }
+ else
+ {
+ while (other->keys->remove_first(other->keys, (void**)&key) == SUCCESS)
+ {
+ this->keys->insert_last(this->keys, key);
+ }
+ while (other->shared->remove_first(other->shared,
+ (void**)&entry) == SUCCESS)
+ {
+ this->shared->insert_last(this->shared, entry);
+ }
+ }
+ this->lock->unlock(this->lock);
+}
+
+METHOD(mem_cred_t, clear_secrets, void,
+ private_mem_cred_t *this)
+{
+ this->lock->write_lock(this->lock);
+ reset_secrets(this);
this->lock->unlock(this->lock);
}
@@ -619,6 +671,7 @@ mem_cred_t *mem_cred_create()
.add_shared = _add_shared,
.add_shared_list = _add_shared_list,
.add_cdp = _add_cdp,
+ .replace_secrets = _replace_secrets,
.clear = _clear_,
.clear_secrets = _clear_secrets,
.destroy = _destroy,
diff --git a/src/libstrongswan/credentials/sets/mem_cred.h b/src/libstrongswan/credentials/sets/mem_cred.h
index 20447207c..d0dd51da1 100644
--- a/src/libstrongswan/credentials/sets/mem_cred.h
+++ b/src/libstrongswan/credentials/sets/mem_cred.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Tobias Brunner
+ * Copyright (C) 2010-2013 Tobias Brunner
* Hochschule fuer Technik Rapperswil
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
@@ -101,6 +101,16 @@ struct mem_cred_t {
identification_t *id, char *uri);
/**
+ * Replace all secrets (private and shared keys) in this credential set
+ * with those of another.
+ *
+ * @param other credential set to get secrets from
+ * @param clone TRUE to clone secrets, FALSE to adopt them (they
+ * get removed from the other set)
+ */
+ void (*replace_secrets)(mem_cred_t *this, mem_cred_t *other, bool clone);
+
+ /**
* Clear all credentials from the credential set.
*/
void (*clear)(mem_cred_t *this);