Cache trustchain lifetimes for export
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user