summaryrefslogtreecommitdiff
path: root/src/libstrongswan/credentials/sets/mem_cred.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/credentials/sets/mem_cred.c')
-rw-r--r--src/libstrongswan/credentials/sets/mem_cred.c240
1 files changed, 221 insertions, 19 deletions
diff --git a/src/libstrongswan/credentials/sets/mem_cred.c b/src/libstrongswan/credentials/sets/mem_cred.c
index c29a99f1f..e023e8443 100644
--- a/src/libstrongswan/credentials/sets/mem_cred.c
+++ b/src/libstrongswan/credentials/sets/mem_cred.c
@@ -1,4 +1,6 @@
/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Hochschule fuer Technik Rapperwsil
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
*
@@ -54,6 +56,11 @@ struct private_mem_cred_t {
* List of shared keys, as shared_entry_t
*/
linked_list_t *shared;
+
+ /**
+ * List of CDPs, as cdp_t
+ */
+ linked_list_t *cdps;
};
/**
@@ -144,21 +151,104 @@ static bool certificate_equals(certificate_t *item, certificate_t *cert)
return item->equals(item, cert);
}
+/**
+ * Add a certificate the the cache. Returns a reference to "cert" or a
+ * previously cached certificate that equals "cert".
+ */
+static certificate_t *add_cert_internal(private_mem_cred_t *this, bool trusted,
+ certificate_t *cert)
+{
+ certificate_t *cached;
+ this->lock->write_lock(this->lock);
+ if (this->untrusted->find_first(this->untrusted,
+ (linked_list_match_t)certificate_equals,
+ (void**)&cached, cert) == SUCCESS)
+ {
+ cert->destroy(cert);
+ cert = cached->get_ref(cached);
+ }
+ else
+ {
+ if (trusted)
+ {
+ this->trusted->insert_first(this->trusted, cert->get_ref(cert));
+ }
+ this->untrusted->insert_first(this->untrusted, cert->get_ref(cert));
+ }
+ this->lock->unlock(this->lock);
+ return cert;
+}
+
METHOD(mem_cred_t, add_cert, void,
private_mem_cred_t *this, bool trusted, certificate_t *cert)
{
+ certificate_t *cached = add_cert_internal(this, trusted, cert);
+ cached->destroy(cached);
+}
+
+METHOD(mem_cred_t, add_cert_ref, certificate_t*,
+ private_mem_cred_t *this, bool trusted, certificate_t *cert)
+{
+ return add_cert_internal(this, trusted, cert);
+}
+
+METHOD(mem_cred_t, add_crl, bool,
+ private_mem_cred_t *this, crl_t *crl)
+{
+ certificate_t *current, *cert = &crl->certificate;
+ enumerator_t *enumerator;
+ bool new = TRUE;
+
this->lock->write_lock(this->lock);
- if (this->untrusted->find_last(this->untrusted,
- (linked_list_match_t)certificate_equals, NULL, cert) != SUCCESS)
+ enumerator = this->untrusted->create_enumerator(this->untrusted);
+ while (enumerator->enumerate(enumerator, (void**)&current))
{
- if (trusted)
+ if (current->get_type(current) == CERT_X509_CRL)
{
- this->trusted->insert_last(this->trusted, cert->get_ref(cert));
+ bool found = FALSE;
+ crl_t *crl_c = (crl_t*)current;
+ chunk_t authkey = crl->get_authKeyIdentifier(crl);
+ chunk_t authkey_c = crl_c->get_authKeyIdentifier(crl_c);
+
+ /* compare authorityKeyIdentifiers if available */
+ if (chunk_equals(authkey, authkey_c))
+ {
+ found = TRUE;
+ }
+ else
+ {
+ identification_t *issuer = cert->get_issuer(cert);
+ identification_t *issuer_c = current->get_issuer(current);
+
+ /* otherwise compare issuer distinguished names */
+ if (issuer->equals(issuer, issuer_c))
+ {
+ found = TRUE;
+ }
+ }
+ if (found)
+ {
+ new = crl_is_newer(crl, crl_c);
+ if (new)
+ {
+ this->untrusted->remove_at(this->untrusted, enumerator);
+ }
+ else
+ {
+ cert->destroy(cert);
+ }
+ break;
+ }
}
- this->untrusted->insert_last(this->untrusted, cert->get_ref(cert));
}
- cert->destroy(cert);
+ enumerator->destroy(enumerator);
+
+ if (new)
+ {
+ this->untrusted->insert_first(this->untrusted, cert);
+ }
this->lock->unlock(this->lock);
+ return new;
}
/**
@@ -218,7 +308,7 @@ METHOD(mem_cred_t, add_key, void,
private_mem_cred_t *this, private_key_t *key)
{
this->lock->write_lock(this->lock);
- this->keys->insert_last(this->keys, key);
+ this->keys->insert_first(this->keys, key);
this->lock->unlock(this->lock);
}
@@ -342,32 +432,137 @@ METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
(void*)shared_filter, data, (void*)shared_data_destroy);
}
-METHOD(mem_cred_t, add_shared, void,
- private_mem_cred_t *this, shared_key_t *shared, ...)
+METHOD(mem_cred_t, add_shared_list, void,
+ private_mem_cred_t *this, shared_key_t *shared, linked_list_t* owners)
{
shared_entry_t *entry;
- identification_t *id;
- va_list args;
INIT(entry,
.shared = shared,
- .owners = linked_list_create(),
+ .owners = owners,
);
+ this->lock->write_lock(this->lock);
+ this->shared->insert_first(this->shared, entry);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(mem_cred_t, add_shared, void,
+ private_mem_cred_t *this, shared_key_t *shared, ...)
+{
+ identification_t *id;
+ linked_list_t *owners = linked_list_create();
+ va_list args;
+
va_start(args, shared);
do
{
id = va_arg(args, identification_t*);
if (id)
{
- entry->owners->insert_last(entry->owners, id);
+ owners->insert_first(owners, id);
}
}
while (id);
va_end(args);
+ add_shared_list(this, shared, owners);
+}
+
+/**
+ * Certificate distribution point
+ */
+typedef struct {
+ certificate_type_t type;
+ identification_t *id;
+ char *uri;
+} cdp_t;
+
+/**
+ * Destroy a CDP entry
+ */
+static void cdp_destroy(cdp_t *this)
+{
+ this->id->destroy(this->id);
+ free(this->uri);
+ free(this);
+}
+
+METHOD(mem_cred_t, add_cdp, void,
+ private_mem_cred_t *this, certificate_type_t type,
+ identification_t *id, char *uri)
+{
+ cdp_t *cdp;
+
+ INIT(cdp,
+ .type = type,
+ .id = id->clone(id),
+ .uri = strdup(uri),
+ );
+ this->lock->write_lock(this->lock);
+ this->cdps->insert_last(this->cdps, cdp);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * CDP enumerator data
+ */
+typedef struct {
+ certificate_type_t type;
+ identification_t *id;
+ rwlock_t *lock;
+} cdp_data_t;
+
+/**
+ * Clean up CDP enumerator data
+ */
+static void cdp_data_destroy(cdp_data_t *data)
+{
+ data->lock->unlock(data->lock);
+ free(data);
+}
+
+/**
+ * CDP enumerator filter
+ */
+static bool cdp_filter(cdp_data_t *data, cdp_t **cdp, char **uri)
+{
+ if (data->type != CERT_ANY && data->type != (*cdp)->type)
+ {
+ return FALSE;
+ }
+ if (data->id && !(*cdp)->id->matches((*cdp)->id, data->id))
+ {
+ return FALSE;
+ }
+ *uri = (*cdp)->uri;
+ return TRUE;
+}
+
+METHOD(credential_set_t, create_cdp_enumerator, enumerator_t*,
+ private_mem_cred_t *this, certificate_type_t type, identification_t *id)
+{
+ cdp_data_t *data;
+
+ INIT(data,
+ .type = type,
+ .id = id,
+ .lock = this->lock,
+ );
+ this->lock->read_lock(this->lock);
+ return enumerator_create_filter(this->cdps->create_enumerator(this->cdps),
+ (void*)cdp_filter, data, (void*)cdp_data_destroy);
+
+}
+
+METHOD(mem_cred_t, clear_secrets, void,
+ private_mem_cred_t *this)
+{
this->lock->write_lock(this->lock);
- this->shared->insert_last(this->shared, entry);
+ 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();
this->lock->unlock(this->lock);
}
@@ -379,13 +574,13 @@ METHOD(mem_cred_t, clear_, void,
offsetof(certificate_t, destroy));
this->untrusted->destroy_offset(this->untrusted,
offsetof(certificate_t, destroy));
- this->keys->destroy_offset(this->keys, offsetof(private_key_t, destroy));
- this->shared->destroy_function(this->shared, (void*)shared_entry_destroy);
+ this->cdps->destroy_function(this->cdps, (void*)cdp_destroy);
this->trusted = linked_list_create();
this->untrusted = linked_list_create();
- this->keys = linked_list_create();
- this->shared = linked_list_create();
+ this->cdps = linked_list_create();
this->lock->unlock(this->lock);
+
+ clear_secrets(this);
}
METHOD(mem_cred_t, destroy, void,
@@ -396,6 +591,7 @@ METHOD(mem_cred_t, destroy, void,
this->untrusted->destroy(this->untrusted);
this->keys->destroy(this->keys);
this->shared->destroy(this->shared);
+ this->cdps->destroy(this->cdps);
this->lock->destroy(this->lock);
free(this);
}
@@ -413,19 +609,25 @@ mem_cred_t *mem_cred_create()
.create_shared_enumerator = _create_shared_enumerator,
.create_private_enumerator = _create_private_enumerator,
.create_cert_enumerator = _create_cert_enumerator,
- .create_cdp_enumerator = (void*)return_null,
+ .create_cdp_enumerator = _create_cdp_enumerator,
.cache_cert = (void*)nop,
},
.add_cert = _add_cert,
+ .add_cert_ref = _add_cert_ref,
+ .add_crl = _add_crl,
.add_key = _add_key,
.add_shared = _add_shared,
+ .add_shared_list = _add_shared_list,
+ .add_cdp = _add_cdp,
.clear = _clear_,
+ .clear_secrets = _clear_secrets,
.destroy = _destroy,
},
.trusted = linked_list_create(),
.untrusted = linked_list_create(),
.keys = linked_list_create(),
.shared = linked_list_create(),
+ .cdps = linked_list_create(),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
);