diff options
Diffstat (limited to 'src/libstrongswan/credentials/credential_factory.c')
-rw-r--r-- | src/libstrongswan/credentials/credential_factory.c | 159 |
1 files changed, 54 insertions, 105 deletions
diff --git a/src/libstrongswan/credentials/credential_factory.c b/src/libstrongswan/credentials/credential_factory.c index e55df0398..5139ad504 100644 --- a/src/libstrongswan/credentials/credential_factory.c +++ b/src/libstrongswan/credentials/credential_factory.c @@ -13,17 +13,21 @@ * for more details. */ +#include <stdint.h> + #include "credential_factory.h" #include <debug.h> #include <utils/linked_list.h> -#include <utils/mutex.h> +#include <threading/thread_value.h> +#include <threading/rwlock.h> #include <credentials/certificates/x509.h> ENUM(credential_type_names, CRED_PRIVATE_KEY, CRED_CERTIFICATE, "CRED_PRIVATE_KEY", "CRED_PUBLIC_KEY", "CRED_CERTIFICATE", + "CRED_PLUTO_CERT", ); typedef struct private_credential_factory_t private_credential_factory_t; @@ -37,12 +41,17 @@ struct private_credential_factory_t { * public functions */ credential_factory_t public; - + /** * list with entry_t */ linked_list_t *constructors; - + + /** + * Thread specific recursiveness counter + */ + thread_value_t *recursive; + /** * lock access to builders */ @@ -55,52 +64,19 @@ struct entry_t { credential_type_t type; /** subtype of credential, e.g. certificate_type_t */ int subtype; - /** builder construction function */ - builder_constructor_t constructor; + /** builder function */ + builder_function_t constructor; }; /** - * type/subtype filter function for builder_enumerator - */ -static bool builder_filter(entry_t *data, entry_t **in, builder_t **out) -{ - if (data->type == (*in)->type && - data->subtype == (*in)->subtype) - { - *out = (*in)->constructor(data->subtype); - return TRUE; - } - return FALSE; -} - -/** - * Implementation of credential_factory_t.create_builder_enumerator. - */ -static enumerator_t* create_builder_enumerator( - private_credential_factory_t *this, credential_type_t type, int subtype) -{ - entry_t *data = malloc_thing(entry_t); - - data->type = type; - data->subtype = subtype; - - this->lock->read_lock(this->lock); - return enumerator_create_cleaner( - enumerator_create_filter( - this->constructors->create_enumerator(this->constructors), - (void*)builder_filter, data, free), - (void*)this->lock->unlock, this->lock); -} - -/** * Implementation of credential_factory_t.add_builder_constructor. */ static void add_builder(private_credential_factory_t *this, credential_type_t type, int subtype, - builder_constructor_t constructor) + builder_function_t constructor) { entry_t *entry = malloc_thing(entry_t); - + entry->type = type; entry->subtype = subtype; entry->constructor = constructor; @@ -113,11 +89,11 @@ static void add_builder(private_credential_factory_t *this, * Implementation of credential_factory_t.remove_builder. */ static void remove_builder(private_credential_factory_t *this, - builder_constructor_t constructor) + builder_function_t constructor) { enumerator_t *enumerator; entry_t *entry; - + this->lock->write_lock(this->lock); enumerator = this->constructors->create_enumerator(this->constructors); while (enumerator->enumerate(enumerator, &entry)) @@ -139,73 +115,46 @@ static void* create(private_credential_factory_t *this, credential_type_t type, int subtype, ...) { enumerator_t *enumerator; - builder_t *builder; - builder_part_t part; + entry_t *entry; va_list args; - void* construct = NULL; - - enumerator = create_builder_enumerator(this, type, subtype); - while (enumerator->enumerate(enumerator, &builder)) + void *construct = NULL; + int failures = 0; + uintptr_t level; + + level = (uintptr_t)this->recursive->get(this->recursive); + this->recursive->set(this->recursive, (void*)level + 1); + + this->lock->read_lock(this->lock); + enumerator = this->constructors->create_enumerator(this->constructors); + while (enumerator->enumerate(enumerator, &entry)) { - va_start(args, subtype); - while (TRUE) + if (entry->type == type && entry->subtype == subtype) { - part = va_arg(args, builder_part_t); - switch (part) + va_start(args, subtype); + construct = entry->constructor(subtype, args); + va_end(args); + if (construct) { - case BUILD_END: - break; - case BUILD_BLOB_ASN1_DER: - case BUILD_BLOB_PGP: - case BUILD_BLOB_RFC_3110: - case BUILD_SERIAL: - builder->add(builder, part, va_arg(args, chunk_t)); - continue; - case BUILD_X509_FLAG: - builder->add(builder, part, va_arg(args, x509_flag_t)); - continue; - case BUILD_KEY_SIZE: - builder->add(builder, part, va_arg(args, u_int)); - continue; - case BUILD_NOT_BEFORE_TIME: - case BUILD_NOT_AFTER_TIME: - builder->add(builder, part, va_arg(args, time_t)); - continue; - case BUILD_BLOB_ASN1_PEM: - case BUILD_FROM_FILE: - case BUILD_AGENT_SOCKET: - case BUILD_SIGNING_KEY: - case BUILD_PUBLIC_KEY: - case BUILD_SUBJECT: - case BUILD_SUBJECT_ALTNAME: - case BUILD_ISSUER: - case BUILD_ISSUER_ALTNAME: - case BUILD_SIGNING_CERT: - case BUILD_CA_CERT: - case BUILD_CERT: - case BUILD_IETF_GROUP_ATTR: - case BUILD_SMARTCARD_KEYID: - case BUILD_SMARTCARD_PIN: - builder->add(builder, part, va_arg(args, void*)); - continue; - /* no default to get a compiler warning */ + break; } - break; - } - va_end(args); - - construct = builder->build(builder); - if (construct) - { - break; + failures++; } } enumerator->destroy(enumerator); - if (!construct) + this->lock->unlock(this->lock); + + if (!construct && !level) { - DBG1("failed to create a builder for credential type %N," - " subtype (%d)", credential_type_names, type, subtype); + enum_name_t *names = key_type_names; + + if (type == CRED_CERTIFICATE) + { + names = certificate_type_names; + } + DBG1("building %N - %N failed, tried %d builders", + credential_type_names, type, names, subtype, failures); } + this->recursive->set(this->recursive, (void*)level); return construct; } @@ -215,6 +164,7 @@ static void* create(private_credential_factory_t *this, credential_type_t type, static void destroy(private_credential_factory_t *this) { this->constructors->destroy_function(this->constructors, free); + this->recursive->destroy(this->recursive); this->lock->destroy(this->lock); free(this); } @@ -227,15 +177,14 @@ credential_factory_t *credential_factory_create() private_credential_factory_t *this = malloc_thing(private_credential_factory_t); this->public.create = (void*(*)(credential_factory_t*, credential_type_t type, int subtype, ...))create; - this->public.create_builder_enumerator = (enumerator_t*(*)(credential_factory_t*, credential_type_t type, int subtype))create_builder_enumerator; - this->public.add_builder = (void(*)(credential_factory_t*,credential_type_t type, int subtype, builder_constructor_t constructor))add_builder; - this->public.remove_builder = (void(*)(credential_factory_t*,builder_constructor_t constructor))remove_builder; + this->public.add_builder = (void(*)(credential_factory_t*,credential_type_t type, int subtype, builder_function_t constructor))add_builder; + this->public.remove_builder = (void(*)(credential_factory_t*,builder_function_t constructor))remove_builder; this->public.destroy = (void(*)(credential_factory_t*))destroy; - + this->constructors = linked_list_create(); - + this->recursive = thread_value_create(NULL); this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT); - + return &this->public; } |