diff options
Diffstat (limited to 'src')
6 files changed, 299 insertions, 6 deletions
diff --git a/src/libcharon/plugins/certexpire/Makefile.am b/src/libcharon/plugins/certexpire/Makefile.am index af20490ad..9aac70835 100644 --- a/src/libcharon/plugins/certexpire/Makefile.am +++ b/src/libcharon/plugins/certexpire/Makefile.am @@ -12,6 +12,7 @@ plugin_LTLIBRARIES = libstrongswan-certexpire.la endif libstrongswan_certexpire_la_SOURCES = certexpire_plugin.h certexpire_plugin.c \ - certexpire_listener.h certexpire_listener.c + certexpire_listener.h certexpire_listener.c \ + certexpire_export.h certexpire_export.c libstrongswan_certexpire_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/certexpire/certexpire_export.c b/src/libcharon/plugins/certexpire/certexpire_export.c new file mode 100644 index 000000000..d9b49075f --- /dev/null +++ b/src/libcharon/plugins/certexpire/certexpire_export.c @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * 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 + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "certexpire_export.h" + +#include <debug.h> +#include <utils/hashtable.h> +#include <threading/mutex.h> +#include <credentials/certificates/x509.h> + +typedef struct private_certexpire_export_t private_certexpire_export_t; + +/** + * Private data of an certexpire_export_t object. + */ +struct private_certexpire_export_t { + + /** + * Public certexpire_export_t interface. + */ + certexpire_export_t public; + + /** + * hashtable caching local trustchains, mapping entry_t => entry_t + */ + hashtable_t *local; + + /** + * hashtable caching remote trustchains, mapping entry_t => entry_t + */ + hashtable_t *remote; + + /** + * Mutex to lock hashtables + */ + mutex_t *mutex; +}; + +/** + * Maximum number of expiration dates we store (for subject + IM CAs + CA) + */ +#define MAX_TRUSTCHAIN_LENGTH 7 + +/** + * Hashtable entry + */ +typedef struct { + /** certificate subject as subjectAltName or CN of a DN */ + char id[128]; + /** list of expiration dates, 0 if no certificate */ + time_t expire[MAX_TRUSTCHAIN_LENGTH]; +} entry_t; + +/** + * Hashtable hash function + */ +static u_int hash(entry_t *key) +{ + return chunk_hash(chunk_create(key->id, strlen(key->id))); +} + +/** + * Hashtable equals function + */ +static bool equals(entry_t *a, entry_t *b) +{ + return streq(a->id, b->id); +} + +METHOD(certexpire_export_t, add, void, + private_certexpire_export_t *this, linked_list_t *trustchain, bool local) +{ + enumerator_t *enumerator; + certificate_t *cert; + int count; + + count = min(trustchain->get_count(trustchain), MAX_TRUSTCHAIN_LENGTH) - 1; + + enumerator = trustchain->create_enumerator(trustchain); + /* get subject cert */ + if (enumerator->enumerate(enumerator, &cert)) + { + identification_t *id; + entry_t *entry; + int i; + + INIT(entry); + + /* prefer FQDN subjectAltName... */ + if (cert->get_type(cert) == CERT_X509) + { + x509_t *x509 = (x509_t*)cert; + enumerator_t *sans; + + sans = x509->create_subjectAltName_enumerator(x509); + while (sans->enumerate(sans, &id)) + { + if (id->get_type(id) == ID_FQDN) + { + snprintf(entry->id, sizeof(entry->id), "%Y", id); + break; + } + } + sans->destroy(sans); + } + /* fallback to CN of DN */ + if (!entry->id[0]) + { + enumerator_t *parts; + id_part_t part; + chunk_t data; + + id = cert->get_subject(cert); + parts = id->create_part_enumerator(id); + while (parts->enumerate(parts, &part, &data)) + { + if (part == ID_PART_RDN_CN) + { + snprintf(entry->id, sizeof(entry->id), "%.*s", + (int)data.len, data.ptr); + break; + } + } + parts->destroy(parts); + } + /* no usable identity? skip */ + if (!entry->id[0]) + { + enumerator->destroy(enumerator); + free(entry); + return; + } + + /* get intermediate CA expiration dates */ + cert->get_validity(cert, NULL, NULL, &entry->expire[0]); + for (i = 1; i < count && enumerator->enumerate(enumerator, &cert); i++) + { + cert->get_validity(cert, NULL, NULL, &entry->expire[i]); + } + /* get CA expiration date, as last array entry */ + if (enumerator->enumerate(enumerator, &cert)) + { + cert->get_validity(cert, NULL, NULL, + &entry->expire[MAX_TRUSTCHAIN_LENGTH - 1]); + } + this->mutex->lock(this->mutex); + if (local) + { + entry = this->local->put(this->local, entry, entry); + } + else + { + entry = this->remote->put(this->remote, entry, entry); + } + this->mutex->unlock(this->mutex); + if (entry) + { + free(entry); + } + } + enumerator->destroy(enumerator); +} + +METHOD(certexpire_export_t, destroy, void, + private_certexpire_export_t *this) +{ + entry_t *key, *value; + enumerator_t *enumerator; + + enumerator = this->local->create_enumerator(this->local); + while (enumerator->enumerate(enumerator, &key, &value)) + { + free(value); + } + enumerator->destroy(enumerator); + enumerator = this->remote->create_enumerator(this->remote); + while (enumerator->enumerate(enumerator, &key, &value)) + { + free(value); + } + enumerator->destroy(enumerator); + + this->local->destroy(this->local); + this->remote->destroy(this->remote); + this->mutex->destroy(this->mutex); + free(this); +} + +/** + * See header + */ +certexpire_export_t *certexpire_export_create() +{ + private_certexpire_export_t *this; + + INIT(this, + .public = { + .add = _add, + .destroy = _destroy, + }, + .local = hashtable_create((hashtable_hash_t)hash, + (hashtable_equals_t)equals, 4), + .remote = hashtable_create((hashtable_hash_t)hash, + (hashtable_equals_t)equals, 32), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/certexpire/certexpire_export.h b/src/libcharon/plugins/certexpire/certexpire_export.h new file mode 100644 index 000000000..64281d0bd --- /dev/null +++ b/src/libcharon/plugins/certexpire/certexpire_export.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * 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 + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup certexpire_export certexpire_export + * @{ @ingroup certexpire + */ + +#ifndef CERTEXPIRE_EXPORT_H_ +#define CERTEXPIRE_EXPORT_H_ + +typedef struct certexpire_export_t certexpire_export_t; + +#include <utils/linked_list.h> + +/** + * Caches and exports trustchain information to CSV files. + */ +struct certexpire_export_t { + + /** + * Add trustchain to cache for export. + * + * @param trustchain trustchain, sorted list of certificate_t + * @param local TRUE for own chain, FALSE for remote chain + */ + void (*add)(certexpire_export_t *this, linked_list_t *trustchain, bool local); + + /** + * Destroy a certexpire_export_t. + */ + void (*destroy)(certexpire_export_t *this); +}; + +/** + * Create a certexpire_export instance. + */ +certexpire_export_t *certexpire_export_create(); + +#endif /** CERTEXPIRE_EXPORT_H_ @}*/ diff --git a/src/libcharon/plugins/certexpire/certexpire_listener.c b/src/libcharon/plugins/certexpire/certexpire_listener.c index 67a9a650b..4c9c6ff3b 100644 --- a/src/libcharon/plugins/certexpire/certexpire_listener.c +++ b/src/libcharon/plugins/certexpire/certexpire_listener.c @@ -28,6 +28,11 @@ struct private_certexpire_listener_t { * Public certexpire_listener_t interface. */ certexpire_listener_t public; + + /** + * Export facility + */ + certexpire_export_t *export; }; METHOD(listener_t, authorize, bool, @@ -80,7 +85,7 @@ METHOD(listener_t, authorize, bool, } } rounds->destroy(rounds); - /* TODO: handle trustchain expiry information */ + this->export->add(this->export, trustchain, TRUE); trustchain->destroy(trustchain); /* collect remote certificates */ @@ -111,7 +116,7 @@ METHOD(listener_t, authorize, bool, } } rounds->destroy(rounds); - /* TODO: handle trustchain expiry information */ + this->export->add(this->export, trustchain, FALSE); trustchain->destroy(trustchain); return TRUE; } @@ -125,7 +130,7 @@ METHOD(certexpire_listener_t, destroy, void, /** * See header */ -certexpire_listener_t *certexpire_listener_create() +certexpire_listener_t *certexpire_listener_create(certexpire_export_t *export) { private_certexpire_listener_t *this; @@ -136,6 +141,7 @@ certexpire_listener_t *certexpire_listener_create() }, .destroy = _destroy, }, + .export = export, ); return &this->public; diff --git a/src/libcharon/plugins/certexpire/certexpire_listener.h b/src/libcharon/plugins/certexpire/certexpire_listener.h index 718743503..8601ff585 100644 --- a/src/libcharon/plugins/certexpire/certexpire_listener.h +++ b/src/libcharon/plugins/certexpire/certexpire_listener.h @@ -23,6 +23,8 @@ #include <bus/listeners/listener.h> +#include "certexpire_export.h" + typedef struct certexpire_listener_t certexpire_listener_t; /** @@ -43,7 +45,10 @@ struct certexpire_listener_t { /** * Create a certexpire_listener instance. + * + * @param export facility exporting collected trustchains + * @return listener instance */ -certexpire_listener_t *certexpire_listener_create(); +certexpire_listener_t *certexpire_listener_create(certexpire_export_t *export); #endif /** CERTEXPIRE_LISTENER_H_ @}*/ diff --git a/src/libcharon/plugins/certexpire/certexpire_plugin.c b/src/libcharon/plugins/certexpire/certexpire_plugin.c index 795e8a13d..2b4c0b68b 100644 --- a/src/libcharon/plugins/certexpire/certexpire_plugin.c +++ b/src/libcharon/plugins/certexpire/certexpire_plugin.c @@ -16,6 +16,7 @@ #include "certexpire_plugin.h" #include "certexpire_listener.h" +#include "certexpire_export.h" #include <daemon.h> @@ -35,6 +36,11 @@ struct private_certexpire_plugin_t { * Listener collecting expire information */ certexpire_listener_t *listener; + + /** + * Cache and export trustchain expire information + */ + certexpire_export_t *export; }; METHOD(plugin_t, get_name, char*, @@ -48,6 +54,7 @@ METHOD(plugin_t, destroy, void, { charon->bus->remove_listener(charon->bus, &this->listener->listener); this->listener->destroy(this->listener); + this->export->destroy(this->export); free(this); } @@ -66,8 +73,9 @@ plugin_t *certexpire_plugin_create() .destroy = _destroy, }, }, - .listener = certexpire_listener_create(), + .export = certexpire_export_create(), ); + this->listener = certexpire_listener_create(this->export), charon->bus->add_listener(charon->bus, &this->listener->listener); return &this->public.plugin; |