Cache trustchain lifetimes for export
This commit is contained in:
@@ -12,6 +12,7 @@ plugin_LTLIBRARIES = libstrongswan-certexpire.la
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
libstrongswan_certexpire_la_SOURCES = certexpire_plugin.h certexpire_plugin.c \
|
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
|
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.
|
* Public certexpire_listener_t interface.
|
||||||
*/
|
*/
|
||||||
certexpire_listener_t public;
|
certexpire_listener_t public;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export facility
|
||||||
|
*/
|
||||||
|
certexpire_export_t *export;
|
||||||
};
|
};
|
||||||
|
|
||||||
METHOD(listener_t, authorize, bool,
|
METHOD(listener_t, authorize, bool,
|
||||||
@@ -80,7 +85,7 @@ METHOD(listener_t, authorize, bool,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
rounds->destroy(rounds);
|
rounds->destroy(rounds);
|
||||||
/* TODO: handle trustchain expiry information */
|
this->export->add(this->export, trustchain, TRUE);
|
||||||
trustchain->destroy(trustchain);
|
trustchain->destroy(trustchain);
|
||||||
|
|
||||||
/* collect remote certificates */
|
/* collect remote certificates */
|
||||||
@@ -111,7 +116,7 @@ METHOD(listener_t, authorize, bool,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
rounds->destroy(rounds);
|
rounds->destroy(rounds);
|
||||||
/* TODO: handle trustchain expiry information */
|
this->export->add(this->export, trustchain, FALSE);
|
||||||
trustchain->destroy(trustchain);
|
trustchain->destroy(trustchain);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -125,7 +130,7 @@ METHOD(certexpire_listener_t, destroy, void,
|
|||||||
/**
|
/**
|
||||||
* See header
|
* See header
|
||||||
*/
|
*/
|
||||||
certexpire_listener_t *certexpire_listener_create()
|
certexpire_listener_t *certexpire_listener_create(certexpire_export_t *export)
|
||||||
{
|
{
|
||||||
private_certexpire_listener_t *this;
|
private_certexpire_listener_t *this;
|
||||||
|
|
||||||
@@ -136,6 +141,7 @@ certexpire_listener_t *certexpire_listener_create()
|
|||||||
},
|
},
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
|
.export = export,
|
||||||
);
|
);
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
|
|||||||
@@ -23,6 +23,8 @@
|
|||||||
|
|
||||||
#include <bus/listeners/listener.h>
|
#include <bus/listeners/listener.h>
|
||||||
|
|
||||||
|
#include "certexpire_export.h"
|
||||||
|
|
||||||
typedef struct certexpire_listener_t certexpire_listener_t;
|
typedef struct certexpire_listener_t certexpire_listener_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,7 +45,10 @@ struct certexpire_listener_t {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a certexpire_listener instance.
|
* 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_ @}*/
|
#endif /** CERTEXPIRE_LISTENER_H_ @}*/
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "certexpire_plugin.h"
|
#include "certexpire_plugin.h"
|
||||||
|
|
||||||
#include "certexpire_listener.h"
|
#include "certexpire_listener.h"
|
||||||
|
#include "certexpire_export.h"
|
||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
|
|
||||||
@@ -35,6 +36,11 @@ struct private_certexpire_plugin_t {
|
|||||||
* Listener collecting expire information
|
* Listener collecting expire information
|
||||||
*/
|
*/
|
||||||
certexpire_listener_t *listener;
|
certexpire_listener_t *listener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache and export trustchain expire information
|
||||||
|
*/
|
||||||
|
certexpire_export_t *export;
|
||||||
};
|
};
|
||||||
|
|
||||||
METHOD(plugin_t, get_name, char*,
|
METHOD(plugin_t, get_name, char*,
|
||||||
@@ -48,6 +54,7 @@ METHOD(plugin_t, destroy, void,
|
|||||||
{
|
{
|
||||||
charon->bus->remove_listener(charon->bus, &this->listener->listener);
|
charon->bus->remove_listener(charon->bus, &this->listener->listener);
|
||||||
this->listener->destroy(this->listener);
|
this->listener->destroy(this->listener);
|
||||||
|
this->export->destroy(this->export);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,8 +73,9 @@ plugin_t *certexpire_plugin_create()
|
|||||||
.destroy = _destroy,
|
.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);
|
charon->bus->add_listener(charon->bus, &this->listener->listener);
|
||||||
|
|
||||||
return &this->public.plugin;
|
return &this->public.plugin;
|
||||||
|
|||||||
Reference in New Issue
Block a user