diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2011-10-25 01:10:02 +0200 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2011-10-25 01:10:16 +0200 |
commit | f0a8bf47f7d01ded310e60b3ec1e7204284dd7f7 (patch) | |
tree | f0d3b416d4a0db79f38c75e632f0a62475d3bf5c /src/libcharon/plugins/tnc_tnccs | |
parent | c008d2cc4618ff5afcb8ea8b8ff7e756545e4c47 (diff) | |
download | strongswan-f0a8bf47f7d01ded310e60b3ec1e7204284dd7f7.tar.bz2 strongswan-f0a8bf47f7d01ded310e60b3ec1e7204284dd7f7.tar.xz |
refactored TNC framework
Diffstat (limited to 'src/libcharon/plugins/tnc_tnccs')
-rw-r--r-- | src/libcharon/plugins/tnc_tnccs/Makefile.am | 22 | ||||
-rw-r--r-- | src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c | 507 | ||||
-rw-r--r-- | src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.h | 32 | ||||
-rw-r--r-- | src/libcharon/plugins/tnc_tnccs/tnc_tnccs_plugin.c | 81 | ||||
-rw-r--r-- | src/libcharon/plugins/tnc_tnccs/tnc_tnccs_plugin.h | 42 |
5 files changed, 684 insertions, 0 deletions
diff --git a/src/libcharon/plugins/tnc_tnccs/Makefile.am b/src/libcharon/plugins/tnc_tnccs/Makefile.am new file mode 100644 index 000000000..c7fc02f7c --- /dev/null +++ b/src/libcharon/plugins/tnc_tnccs/Makefile.am @@ -0,0 +1,22 @@ + +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtnccs + +AM_CFLAGS = -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-tnc-tnccs.la +else +plugin_LTLIBRARIES = libstrongswan-tnc-tnccs.la +libstrongswan_tnc_tnccs_la_LIBADD = \ + $(top_builddir)/src/libtncif/libtncif.la \ + $(top_builddir)/src/libtnccs/libtnccs.la +endif + +libstrongswan_tnc_tnccs_la_SOURCES = \ + tnc_tnccs_plugin.h tnc_tnccs_plugin.c \ + tnc_tnccs_manager.h tnc_tnccs_manager.c + +libstrongswan_tnc_tnccs_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c new file mode 100644 index 000000000..f007ce19f --- /dev/null +++ b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c @@ -0,0 +1,507 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * 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 "tnc_tnccs_manager.h" + +#include <tnc/tnc.h> +#include <tnc/imv/imv_manager.h> +#include <tnc/imc/imc_manager.h> +#include <tnc/imv/imv_manager.h> + +#include <debug.h> +#include <utils/linked_list.h> +#include <threading/rwlock.h> + +typedef struct private_tnc_tnccs_manager_t private_tnc_tnccs_manager_t; +typedef struct tnccs_entry_t tnccs_entry_t; +typedef struct tnccs_connection_entry_t tnccs_connection_entry_t; + +/** + * TNCCS constructor entry + */ +struct tnccs_entry_t { + + /** + * TNCCS protocol type + */ + tnccs_type_t type; + + /** + * constructor function to create instance + */ + tnccs_constructor_t constructor; +}; + +/** + * TNCCS connection entry + */ +struct tnccs_connection_entry_t { + + /** + * TNCCS connection ID + */ + TNC_ConnectionID id; + + /** + * TNCCS instance + */ + tnccs_t *tnccs; + + /** + * TNCCS send message function + */ + tnccs_send_message_t send_message; + + /** + * TNCCS request handshake retry flag + */ + bool *request_handshake_retry; + + /** + * collection of IMV recommendations + */ + recommendations_t *recs; +}; + +/** + * private data of tnc_tnccs_manager + */ +struct private_tnc_tnccs_manager_t { + + /** + * public functions + */ + tnccs_manager_t public; + + /** + * list of TNCCS protocol entries + */ + linked_list_t *protocols; + + /** + * rwlock to lock the TNCCS protocol entries + */ + rwlock_t *protocol_lock; + + /** + * connection ID counter + */ + TNC_ConnectionID connection_id; + + /** + * list of TNCCS connection entries + */ + linked_list_t *connections; + + /** + * rwlock to lock TNCCS connection entries + */ + rwlock_t *connection_lock; + +}; + +METHOD(tnccs_manager_t, add_method, void, + private_tnc_tnccs_manager_t *this, tnccs_type_t type, + tnccs_constructor_t constructor) +{ + tnccs_entry_t *entry; + + entry = malloc_thing(tnccs_entry_t); + entry->type = type; + entry->constructor = constructor; + + this->protocol_lock->write_lock(this->protocol_lock); + this->protocols->insert_last(this->protocols, entry); + this->protocol_lock->unlock(this->protocol_lock); +} + +METHOD(tnccs_manager_t, remove_method, void, + private_tnc_tnccs_manager_t *this, tnccs_constructor_t constructor) +{ + enumerator_t *enumerator; + tnccs_entry_t *entry; + + this->protocol_lock->write_lock(this->protocol_lock); + enumerator = this->protocols->create_enumerator(this->protocols); + while (enumerator->enumerate(enumerator, &entry)) + { + if (constructor == entry->constructor) + { + this->protocols->remove_at(this->protocols, enumerator); + free(entry); + } + } + enumerator->destroy(enumerator); + this->protocol_lock->unlock(this->protocol_lock); +} + +METHOD(tnccs_manager_t, create_instance, tnccs_t*, + private_tnc_tnccs_manager_t *this, tnccs_type_t type, bool is_server) +{ + enumerator_t *enumerator; + tnccs_entry_t *entry; + tnccs_t *protocol = NULL; + + this->protocol_lock->read_lock(this->protocol_lock); + enumerator = this->protocols->create_enumerator(this->protocols); + while (enumerator->enumerate(enumerator, &entry)) + { + if (type == entry->type) + { + protocol = entry->constructor(is_server); + if (protocol) + { + break; + } + } + } + enumerator->destroy(enumerator); + this->protocol_lock->unlock(this->protocol_lock); + + return protocol; +} + +METHOD(tnccs_manager_t, create_connection, TNC_ConnectionID, + private_tnc_tnccs_manager_t *this, tnccs_t *tnccs, + tnccs_send_message_t send_message, bool* request_handshake_retry, + recommendations_t **recs) +{ + tnccs_connection_entry_t *entry; + + entry = malloc_thing(tnccs_connection_entry_t); + entry->tnccs = tnccs; + entry->send_message = send_message; + entry->request_handshake_retry = request_handshake_retry; + if (recs) + { + /* we assume a TNC Server needing recommendations from IMVs */ + if (!tnc->imvs) + { + DBG1(DBG_TNC, "no IMV manager available!"); + free(entry); + return 0; + } + entry->recs = tnc->imvs->create_recommendations(tnc->imvs); + *recs = entry->recs; + } + else + { + /* we assume a TNC Client */ + if (!tnc->imcs) + { + DBG1(DBG_TNC, "no IMC manager available!"); + free(entry); + return 0; + } + entry->recs = NULL; + } + this->connection_lock->write_lock(this->connection_lock); + entry->id = ++this->connection_id; + this->connections->insert_last(this->connections, entry); + this->connection_lock->unlock(this->connection_lock); + + DBG1(DBG_TNC, "assigned TNCCS Connection ID %u", entry->id); + return entry->id; +} + +METHOD(tnccs_manager_t, remove_connection, void, + private_tnc_tnccs_manager_t *this, TNC_ConnectionID id, bool is_server) +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + + if (is_server) + { + if (tnc->imvs) + { + tnc->imvs->notify_connection_change(tnc->imvs, id, + TNC_CONNECTION_STATE_DELETE); + } + } + else + { + if (tnc->imcs) + { + tnc->imcs->notify_connection_change(tnc->imcs, id, + TNC_CONNECTION_STATE_DELETE); + } + } + + this->connection_lock->write_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == entry->id) + { + this->connections->remove_at(this->connections, enumerator); + if (entry->recs) + { + entry->recs->destroy(entry->recs); + } + free(entry); + DBG1(DBG_TNC, "removed TNCCS Connection ID %u", id); + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); +} + +METHOD(tnccs_manager_t, request_handshake_retry, TNC_Result, + private_tnc_tnccs_manager_t *this, bool is_imc, TNC_UInt32 imcv_id, + TNC_ConnectionID id, + TNC_RetryReason reason) +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + + if (id == TNC_CONNECTIONID_ANY) + { + DBG2(DBG_TNC, "%s %u requests handshake retry for all connections " + "(reason: %u)", is_imc ? "IMC":"IMV", reason); + } + else + { + DBG2(DBG_TNC, "%s %u requests handshake retry for Connection ID %u " + "(reason: %u)", is_imc ? "IMC":"IMV", imcv_id, id, reason); + } + this->connection_lock->read_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == TNC_CONNECTIONID_ANY || id == entry->id) + { + *entry->request_handshake_retry = TRUE; + break; + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); + + return TNC_RESULT_SUCCESS; +} + +METHOD(tnccs_manager_t, send_message, TNC_Result, + private_tnc_tnccs_manager_t *this, TNC_IMCID imc_id, TNC_IMVID imv_id, + TNC_ConnectionID id, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_MessageType msg_type) + +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + tnccs_send_message_t send_message = NULL; + tnccs_t *tnccs = NULL; + TNC_VendorID msg_vid; + TNC_MessageSubtype msg_subtype; + + msg_vid = (msg_type >> 8) & TNC_VENDORID_ANY; + msg_subtype = msg_type & TNC_SUBTYPE_ANY; + + if (msg_vid == TNC_VENDORID_ANY || msg_subtype == TNC_SUBTYPE_ANY) + { + DBG1(DBG_TNC, "not sending message of invalid type 0x%08x", msg_type); + return TNC_RESULT_INVALID_PARAMETER; + } + + this->connection_lock->read_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == entry->id) + { + tnccs = entry->tnccs; + send_message = entry->send_message; + break; + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); + + if (tnccs && send_message) + { + return send_message(tnccs, imc_id, imv_id, msg, msg_len, msg_type); + } + return TNC_RESULT_FATAL; +} + +METHOD(tnccs_manager_t, provide_recommendation, TNC_Result, + private_tnc_tnccs_manager_t *this, TNC_IMVID imv_id, + TNC_ConnectionID id, + TNC_IMV_Action_Recommendation rec, + TNC_IMV_Evaluation_Result eval) +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + recommendations_t *recs = NULL; + + this->connection_lock->read_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == entry->id) + { + recs = entry->recs; + break; + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); + + if (recs) + { + recs->provide_recommendation(recs, imv_id, rec, eval); + return TNC_RESULT_SUCCESS; + } + return TNC_RESULT_FATAL; +} + +METHOD(tnccs_manager_t, get_attribute, TNC_Result, + private_tnc_tnccs_manager_t *this, TNC_IMVID imv_id, + TNC_ConnectionID id, + TNC_AttributeID attribute_id, + TNC_UInt32 buffer_len, + TNC_BufferReference buffer, + TNC_UInt32 *out_value_len) +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + recommendations_t *recs = NULL; + + if (id == TNC_CONNECTIONID_ANY || + attribute_id != TNC_ATTRIBUTEID_PREFERRED_LANGUAGE) + { + return TNC_RESULT_INVALID_PARAMETER; + } + + this->connection_lock->read_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == entry->id) + { + recs = entry->recs; + break; + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); + + if (recs) + { + chunk_t pref_lang; + + pref_lang = recs->get_preferred_language(recs); + if (pref_lang.len == 0) + { + return TNC_RESULT_INVALID_PARAMETER; + } + *out_value_len = pref_lang.len; + if (buffer && buffer_len >= pref_lang.len) + { + memcpy(buffer, pref_lang.ptr, pref_lang.len); + } + return TNC_RESULT_SUCCESS; + } + return TNC_RESULT_INVALID_PARAMETER; +} + +METHOD(tnccs_manager_t, set_attribute, TNC_Result, + private_tnc_tnccs_manager_t *this, TNC_IMVID imv_id, + TNC_ConnectionID id, + TNC_AttributeID attribute_id, + TNC_UInt32 buffer_len, + TNC_BufferReference buffer) +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + recommendations_t *recs = NULL; + + if (id == TNC_CONNECTIONID_ANY || + (attribute_id != TNC_ATTRIBUTEID_REASON_STRING && + attribute_id != TNC_ATTRIBUTEID_REASON_LANGUAGE)) + { + return TNC_RESULT_INVALID_PARAMETER; + } + + this->connection_lock->read_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == entry->id) + { + recs = entry->recs; + break; + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); + + if (recs) + { + chunk_t attribute = { buffer, buffer_len }; + + if (attribute_id == TNC_ATTRIBUTEID_REASON_STRING) + { + return recs->set_reason_string(recs, imv_id, attribute); + } + else + { + return recs->set_reason_language(recs, imv_id, attribute); + } + } + return TNC_RESULT_INVALID_PARAMETER; +} + +METHOD(tnccs_manager_t, destroy, void, + private_tnc_tnccs_manager_t *this) +{ + this->protocols->destroy_function(this->protocols, free); + this->protocol_lock->destroy(this->protocol_lock); + this->connections->destroy_function(this->connections, free); + this->connection_lock->destroy(this->connection_lock); + free(this); +} + +/* + * See header + */ +tnccs_manager_t *tnc_tnccs_manager_create() +{ + private_tnc_tnccs_manager_t *this; + + INIT(this, + .public = { + .add_method = _add_method, + .remove_method = _remove_method, + .create_instance = _create_instance, + .create_connection = _create_connection, + .remove_connection = _remove_connection, + .request_handshake_retry = _request_handshake_retry, + .send_message = _send_message, + .provide_recommendation = _provide_recommendation, + .get_attribute = _get_attribute, + .set_attribute = _set_attribute, + .destroy = _destroy, + }, + .protocols = linked_list_create(), + .connections = linked_list_create(), + .protocol_lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + .connection_lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + ); + + return &this->public; +} + diff --git a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.h b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.h new file mode 100644 index 000000000..603973de9 --- /dev/null +++ b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * 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 tnc_tnccs_manager tnc_tnccs_manager + * @{ @ingroup tnc_tnccs + */ + +#ifndef TNC_TNCCS_MANAGER_H_ +#define TNC_TNCCS_MANAGER_H_ + +#include <tnc/tnccs/tnccs_manager.h> + +/** + * Create a TNCCS manager instance. + */ +tnccs_manager_t *tnc_tnccs_manager_create(); + +#endif /** TNC_TNCCS_MANAGER_H_ @}*/ diff --git a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_plugin.c b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_plugin.c new file mode 100644 index 000000000..777c33c51 --- /dev/null +++ b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_plugin.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * 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 "tnc_tnccs_plugin.h" +#include "tnc_tnccs_manager.h" + +#include <tnc/tnc.h> + +typedef struct private_tnc_tnccs_plugin_t private_tnc_tnccs_plugin_t; + +/** + * Private data of a tnc_tnccs_plugin_t object. + */ +struct private_tnc_tnccs_plugin_t { + + /** + * Public interface. + */ + tnc_tnccs_plugin_t public; + +}; + + +METHOD(plugin_t, get_name, char*, + private_tnc_tnccs_plugin_t *this) +{ + return "tnc-tnccs"; +} + +METHOD(plugin_t, get_features, int, + private_tnc_tnccs_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(tnc_manager_register, tnc_tnccs_manager_create), + PLUGIN_PROVIDE(CUSTOM, "tnccs-manager"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_tnc_tnccs_plugin_t *this) +{ + libtnccs_deinit(); + free(this); +} + +/* + * see header file + */ +plugin_t *tnc_tnccs_plugin_create(void) +{ + private_tnc_tnccs_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + }, + ); + + libtnccs_init(); + + return &this->public.plugin; +} + diff --git a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_plugin.h b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_plugin.h new file mode 100644 index 000000000..9afff7c97 --- /dev/null +++ b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * 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 tnccs tnccs + * @ingroup cplugins + * + * @defgroup tnc_tnccs_plugin tnc_tnccs_plugin + * @{ @ingroup tnccs + */ + +#ifndef TNC_TNCCS_PLUGIN_H_ +#define TNC_TNCCS_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct tnc_tnccs_plugin_t tnc_tnccs_plugin_t; + +/** + * TNCCS manager plugin + */ +struct tnc_tnccs_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** TNC_TNCCS_PLUGIN_H_ @}*/ |