Cache trustchain lifetimes for export

This commit is contained in:
Martin Willi
2011-08-22 18:42:33 +02:00
parent b274f20a1d
commit f4bdc6a3aa
6 changed files with 299 additions and 6 deletions
+2 -1
View File
@@ -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
@@ -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;
}
@@ -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_ @}*/
@@ -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;
@@ -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_ @}*/
@@ -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;