From 05ddd767992d68bb38c7f16ece142e8c2e9ae016 Mon Sep 17 00:00:00 2001 From: Yves-Alexis Perez Date: Sat, 1 Apr 2017 16:26:44 +0200 Subject: New upstream version 5.5.2 --- src/libstrongswan/credentials/sets/cert_cache.c | 41 ++++++++- src/libstrongswan/credentials/sets/mem_cred.c | 113 ++++++++++++++++++++++-- src/libstrongswan/credentials/sets/mem_cred.h | 40 ++++++++- 3 files changed, 185 insertions(+), 9 deletions(-) (limited to 'src/libstrongswan/credentials/sets') diff --git a/src/libstrongswan/credentials/sets/cert_cache.c b/src/libstrongswan/credentials/sets/cert_cache.c index 60720dc57..24fdb194b 100644 --- a/src/libstrongswan/credentials/sets/cert_cache.c +++ b/src/libstrongswan/credentials/sets/cert_cache.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2008 Martin Willi - * Hochschule fuer Technik Rapperswil + * Copyright (C) 2016 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -20,6 +21,7 @@ #include #include #include +#include /** cache size, a power of 2 for fast modulo */ #define CACHE_SIZE 32 @@ -88,6 +90,43 @@ static void cache(private_cert_cache_t *this, int i, offset, try; u_int total_hits = 0; + /* cache a CRL by replacing a previous CRL cache entry if present */ + if (subject->get_type(subject) == CERT_X509_CRL) + { + crl_t *crl, *cached_crl; + + /* cache a delta CRL ? */ + crl = (crl_t*)subject; + + for (i = 0; i < CACHE_SIZE; i++) + { + rel = &this->relations[i]; + + if (rel->subject && + rel->subject->get_type(rel->subject) == CERT_X509_CRL && + rel->lock->try_write_lock(rel->lock)) + { + /* double-check having lock */ + if (rel->subject->get_type(rel->subject) == CERT_X509_CRL && + rel->issuer->equals(rel->issuer, issuer)) + { + cached_crl = (crl_t*)rel->subject; + + if (cached_crl->is_delta_crl(cached_crl, NULL) == + crl->is_delta_crl(crl, NULL) && + crl_is_newer(crl, cached_crl)) + { + rel->subject->destroy(rel->subject); + rel->subject = subject->get_ref(subject); + rel->scheme = scheme; + return rel->lock->unlock(rel->lock); + } + } + rel->lock->unlock(rel->lock); + } + } + } + /* check for a unused relation slot first */ for (i = 0; i < CACHE_SIZE; i++) { diff --git a/src/libstrongswan/credentials/sets/mem_cred.c b/src/libstrongswan/credentials/sets/mem_cred.c index 0f8bff23f..53e035f98 100644 --- a/src/libstrongswan/credentials/sets/mem_cred.c +++ b/src/libstrongswan/credentials/sets/mem_cred.c @@ -370,14 +370,42 @@ METHOD(mem_cred_t, add_key, void, this->lock->unlock(this->lock); } +METHOD(mem_cred_t, remove_key, bool, + private_mem_cred_t *this, chunk_t fp) +{ + enumerator_t *enumerator; + private_key_t *current; + bool found = FALSE; + + this->lock->write_lock(this->lock); + + enumerator = this->keys->create_enumerator(this->keys); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (current->has_fingerprint(current, fp)) + { + this->keys->remove_at(this->keys, enumerator); + current->destroy(current); + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + this->lock->unlock(this->lock); + return found; +} + /** * Shared key entry */ typedef struct { - /* shared key */ + /** shared key */ shared_key_t *shared; - /* list of owners, identification_t */ + /** list of owners, identification_t */ linked_list_t *owners; + /** optional unique identifier */ + char *id; } shared_entry_t; /** @@ -388,11 +416,12 @@ static void shared_entry_destroy(shared_entry_t *entry) entry->owners->destroy_offset(entry->owners, offsetof(identification_t, destroy)); entry->shared->destroy(entry->shared); + free(entry->id); free(entry); } /** - * Check if two shared key entries equal + * Check if two shared key entries are equal (ignoring the unique identifier) */ static bool shared_entry_equals(shared_entry_t *a, shared_entry_t *b) { @@ -528,8 +557,9 @@ METHOD(credential_set_t, create_shared_enumerator, enumerator_t*, (void*)shared_filter, data, (void*)shared_data_destroy); } -METHOD(mem_cred_t, add_shared_list, void, - private_mem_cred_t *this, shared_key_t *shared, linked_list_t* owners) +METHOD(mem_cred_t, add_shared_unique, void, + private_mem_cred_t *this, char *id, shared_key_t *shared, + linked_list_t* owners) { shared_entry_t *current, *new; enumerator_t *enumerator; @@ -537,6 +567,7 @@ METHOD(mem_cred_t, add_shared_list, void, INIT(new, .shared = shared, .owners = owners, + .id = strdupnull(id), ); this->lock->write_lock(this->lock); @@ -544,7 +575,10 @@ METHOD(mem_cred_t, add_shared_list, void, enumerator = this->shared->create_enumerator(this->shared); while (enumerator->enumerate(enumerator, ¤t)) { - if (shared_entry_equals(current, new)) + /* always replace keys with the same unique identifier, only compare + * them if both have no unique id assigned */ + if ((id && streq(id, current->id)) || + (!id && !current->id && shared_entry_equals(current, new))) { this->shared->remove_at(this->shared, enumerator); shared_entry_destroy(current); @@ -558,6 +592,12 @@ METHOD(mem_cred_t, add_shared_list, void, this->lock->unlock(this->lock); } +METHOD(mem_cred_t, add_shared_list, void, + private_mem_cred_t *this, shared_key_t *shared, linked_list_t* owners) +{ + add_shared_unique(this, NULL, shared, owners); +} + METHOD(mem_cred_t, add_shared, void, private_mem_cred_t *this, shared_key_t *shared, ...) { @@ -580,6 +620,63 @@ METHOD(mem_cred_t, add_shared, void, add_shared_list(this, shared, owners); } +METHOD(mem_cred_t, remove_shared_unique, void, + private_mem_cred_t *this, char *id) +{ + enumerator_t *enumerator; + shared_entry_t *current; + + if (!id) + { + return; + } + + this->lock->write_lock(this->lock); + + enumerator = this->shared->create_enumerator(this->shared); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (streq(id, current->id)) + { + this->shared->remove_at(this->shared, enumerator); + shared_entry_destroy(current); + break; + } + } + enumerator->destroy(enumerator); + + this->lock->unlock(this->lock); +} + +/** + * Filter unique ids of shared keys (ingore secrets without unique id) + */ +static bool unique_filter(void *unused, + shared_entry_t **in, char **id) +{ + shared_entry_t *entry = *in; + + if (!entry->id) + { + return FALSE; + } + if (id) + { + *id = entry->id; + } + return TRUE; +} + +METHOD(mem_cred_t, create_unique_shared_enumerator, enumerator_t*, + private_mem_cred_t *this) +{ + this->lock->read_lock(this->lock); + return enumerator_create_filter( + this->shared->create_enumerator(this->shared), + (void*)unique_filter, this->lock, + (void*)this->lock->unlock); +} + /** * Certificate distribution point */ @@ -817,8 +914,12 @@ mem_cred_t *mem_cred_create() .get_cert_ref = _get_cert_ref, .add_crl = _add_crl, .add_key = _add_key, + .remove_key = _remove_key, .add_shared = _add_shared, .add_shared_list = _add_shared_list, + .add_shared_unique = _add_shared_unique, + .remove_shared_unique = _remove_shared_unique, + .create_unique_shared_enumerator = _create_unique_shared_enumerator, .add_cdp = _add_cdp, .replace_certs = _replace_certs, .replace_secrets = _replace_secrets, diff --git a/src/libstrongswan/credentials/sets/mem_cred.h b/src/libstrongswan/credentials/sets/mem_cred.h index 51f0b8c30..135515260 100644 --- a/src/libstrongswan/credentials/sets/mem_cred.h +++ b/src/libstrongswan/credentials/sets/mem_cred.h @@ -1,6 +1,7 @@ /* - * Copyright (C) 2010-2015 Tobias Brunner - * Hochschule fuer Technik Rapperswil + * Copyright (C) 2010-2016 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG * @@ -86,6 +87,14 @@ struct mem_cred_t { */ void (*add_key)(mem_cred_t *this, private_key_t *key); + /** + * Remove a private key from the credential set. + * + * @param fp fingerprint of the key to remove + * @return TRUE if the key was found and removed + */ + bool (*remove_key)(mem_cred_t *this, chunk_t fp); + /** * Add a shared key to the credential set. * @@ -103,6 +112,33 @@ struct mem_cred_t { void (*add_shared_list)(mem_cred_t *this, shared_key_t *shared, linked_list_t *owners); + /** + * Add a shared key to the credential set, associated with the given unique + * identifier. + * + * If a shared key with the same id already exists it is replaced. + * + * @param id unique identifier of this key (cloned) + * @param shared shared key to add, gets owned by set + * @param ... NULL terminated list of owners (identification_t*) + */ + void (*add_shared_unique)(mem_cred_t *this, char *id, shared_key_t *shared, + linked_list_t *owners); + + /** + * Remove a shared key by its unique identifier. + * + * @param id unique identifier of this key + */ + void (*remove_shared_unique)(mem_cred_t *this, char *id); + + /** + * Create an enumerator over the unique identifiers of shared keys. + * + * @return enumerator over char* + */ + enumerator_t *(*create_unique_shared_enumerator)(mem_cred_t *this); + /** * Add a certificate distribution point to the set. * -- cgit v1.2.3