diff options
Diffstat (limited to 'src/libimcv/plugins/imc_os')
-rw-r--r-- | src/libimcv/plugins/imc_os/Makefile.am | 15 | ||||
-rw-r--r-- | src/libimcv/plugins/imc_os/imc_os.c | 362 | ||||
-rw-r--r-- | src/libimcv/plugins/imc_os/imc_os_state.c | 164 | ||||
-rw-r--r-- | src/libimcv/plugins/imc_os/imc_os_state.h | 48 |
4 files changed, 589 insertions, 0 deletions
diff --git a/src/libimcv/plugins/imc_os/Makefile.am b/src/libimcv/plugins/imc_os/Makefile.am new file mode 100644 index 000000000..0bfe776a5 --- /dev/null +++ b/src/libimcv/plugins/imc_os/Makefile.am @@ -0,0 +1,15 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libimcv + +AM_CFLAGS = -rdynamic + +imcv_LTLIBRARIES = imc-os.la + +imc_os_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \ + $(top_builddir)/src/libstrongswan/libstrongswan.la + +imc_os_la_SOURCES = imc_os.c imc_os_state.h imc_os_state.c + +imc_os_la_LDFLAGS = -module -avoid-version + diff --git a/src/libimcv/plugins/imc_os/imc_os.c b/src/libimcv/plugins/imc_os/imc_os.c new file mode 100644 index 000000000..8c0aadba2 --- /dev/null +++ b/src/libimcv/plugins/imc_os/imc_os.c @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2011-2012 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 "imc_os_state.h" + +#include <imc/imc_agent.h> +#include <pa_tnc/pa_tnc_msg.h> +#include <ietf/ietf_attr.h> +#include <ietf/ietf_attr_attr_request.h> +#include <ietf/ietf_attr_product_info.h> +#include <ietf/ietf_attr_installed_packages.h> +#include <ietf/ietf_attr_pa_tnc_error.h> +#include <ietf/ietf_attr_assess_result.h> + +#include <tncif_pa_subtypes.h> + +#include <pen/pen.h> +#include <debug.h> + +#include <stdio.h> + +/* IMC definitions */ + +static const char imc_name[] = "OS"; + +#define IMC_VENDOR_ID PEN_IETF +#define IMC_SUBTYPE PA_SUBTYPE_IETF_OPERATING_SYSTEM + +static imc_agent_t *imc_os; + +/** + * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3 + */ +TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id, + TNC_Version min_version, + TNC_Version max_version, + TNC_Version *actual_version) +{ + if (imc_os) + { + DBG1(DBG_IMC, "IMC \"%s\" has already been initialized", imc_name); + return TNC_RESULT_ALREADY_INITIALIZED; + } + imc_os = imc_agent_create(imc_name, IMC_VENDOR_ID, IMC_SUBTYPE, + imc_id, actual_version); + if (!imc_os) + { + return TNC_RESULT_FATAL; + } + if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1) + { + DBG1(DBG_IMC, "no common IF-IMC version"); + return TNC_RESULT_NO_COMMON_VERSION; + } + return TNC_RESULT_SUCCESS; +} + +/** + * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3 + */ +TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id, + TNC_ConnectionID connection_id, + TNC_ConnectionState new_state) +{ + imc_state_t *state; + + if (!imc_os) + { + DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); + return TNC_RESULT_NOT_INITIALIZED; + } + switch (new_state) + { + case TNC_CONNECTION_STATE_CREATE: + state = imc_os_state_create(connection_id); + return imc_os->create_state(imc_os, state); + case TNC_CONNECTION_STATE_HANDSHAKE: + if (imc_os->change_state(imc_os, connection_id, new_state, + &state) != TNC_RESULT_SUCCESS) + { + return TNC_RESULT_FATAL; + } + state->set_result(state, imc_id, + TNC_IMV_EVALUATION_RESULT_DONT_KNOW); + return TNC_RESULT_SUCCESS; + case TNC_CONNECTION_STATE_DELETE: + return imc_os->delete_state(imc_os, connection_id); + default: + return imc_os->change_state(imc_os, connection_id, + new_state, NULL); + } +} + +/** + * Add an IETF Product Information attribute to the send queue + */ +static void add_product_info(linked_list_t *attr_list) +{ + pa_tnc_attr_t *attr; + + attr = ietf_attr_product_info_create(PEN_IETF, 0, "Ubuntu 12.04 LTS i686"); + attr_list->insert_last(attr_list, attr); +} + +/** + * Add an IETF Installed Packages attribute to the send queue + */ +static void add_installed_packages(linked_list_t *attr_list) +{ + pa_tnc_attr_t *attr; + ietf_attr_installed_packages_t *attr_cast; + chunk_t libc_name = { "libc-bin", 8 }; + chunk_t libc_version = { "2.15-0ubuntu10.2", 16 }; + chunk_t selinux_name = { "selinux", 7 }; + chunk_t selinux_version = { "1:0.11", 6 }; + + attr = ietf_attr_installed_packages_create(); + attr_cast = (ietf_attr_installed_packages_t*)attr; + attr_cast->add(attr_cast, libc_name, libc_version); + attr_cast->add(attr_cast, selinux_name, selinux_version); + attr_list->insert_last(attr_list, attr); +} + +/** + * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3 + */ +TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id, + TNC_ConnectionID connection_id) +{ + TNC_Result result = TNC_RESULT_SUCCESS; + + if (!imc_os) + { + DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); + return TNC_RESULT_NOT_INITIALIZED; + } + + if (lib->settings->get_bool(lib->settings, + "libimcv.plugins.imc-os.send_product_info", TRUE)) + { + linked_list_t *attr_list; + + attr_list = linked_list_create(); + add_product_info(attr_list); + result = imc_os->send_message(imc_os, connection_id, FALSE, 0, + TNC_IMVID_ANY, attr_list); + attr_list->destroy(attr_list); + } + + return result; +} + +static TNC_Result receive_message(TNC_IMCID imc_id, + TNC_ConnectionID connection_id, + TNC_UInt32 msg_flags, + chunk_t msg, + TNC_VendorID msg_vid, + TNC_MessageSubtype msg_subtype, + TNC_UInt32 src_imv_id, + TNC_UInt32 dst_imc_id) +{ + pa_tnc_msg_t *pa_tnc_msg; + pa_tnc_attr_t *attr; + pen_type_t attr_type; + linked_list_t *attr_list; + imc_state_t *state; + enumerator_t *enumerator; + TNC_Result result; + TNC_UInt32 target_imc_id; + bool fatal_error; + + if (!imc_os) + { + DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); + return TNC_RESULT_NOT_INITIALIZED; + } + + /* get current IMC state */ + if (!imc_os->get_state(imc_os, connection_id, &state)) + { + return TNC_RESULT_FATAL; + } + + /* parse received PA-TNC message and automatically handle any errors */ + result = imc_os->receive_message(imc_os, state, msg, msg_vid, + msg_subtype, src_imv_id, dst_imc_id, &pa_tnc_msg); + + /* no parsed PA-TNC attributes available if an error occurred */ + if (!pa_tnc_msg) + { + return result; + } + target_imc_id = (dst_imc_id == TNC_IMCID_ANY) ? imc_id : dst_imc_id; + + /* preprocess any IETF standard error attributes */ + fatal_error = pa_tnc_msg->process_ietf_std_errors(pa_tnc_msg); + + /* analyze PA-TNC attributes */ + attr_list = linked_list_create(); + enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg); + while (enumerator->enumerate(enumerator, &attr)) + { + attr_type = attr->get_type(attr); + + if (attr_type.vendor_id != PEN_IETF) + { + continue; + } + if (attr_type.type == IETF_ATTR_ATTRIBUTE_REQUEST) + { + ietf_attr_attr_request_t *attr_cast; + pen_type_t *entry; + enumerator_t *e; + + attr_cast = (ietf_attr_attr_request_t*)attr; + + e = attr_cast->create_enumerator(attr_cast); + while (e->enumerate(e, &entry)) + { + if (entry->vendor_id != PEN_IETF) + { + continue; + } + switch (entry->type) + { + case IETF_ATTR_PRODUCT_INFORMATION: + add_product_info(attr_list); + break; + case IETF_ATTR_INSTALLED_PACKAGES: + add_installed_packages(attr_list); + break; + default: + break; + } + } + e->destroy(e); + } + else if (attr_type.type == IETF_ATTR_ASSESSMENT_RESULT) + { + ietf_attr_assess_result_t *attr_cast; + + attr_cast = (ietf_attr_assess_result_t*)attr; + state->set_result(state, target_imc_id, + attr_cast->get_result(attr_cast)); + } + } + enumerator->destroy(enumerator); + pa_tnc_msg->destroy(pa_tnc_msg); + + if (fatal_error) + { + attr_list->destroy_offset(attr_list, offsetof(pa_tnc_attr_t, destroy)); + return TNC_RESULT_FATAL; + } + + if (attr_list->get_count(attr_list)) + { + result = imc_os->send_message(imc_os, connection_id, TRUE, imc_id, + src_imv_id, attr_list); + } + else + { + result = TNC_RESULT_SUCCESS; + } + attr_list->destroy(attr_list); + + return result; +} + +/** + * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3 + + */ +TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id, + TNC_ConnectionID connection_id, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_MessageType msg_type) +{ + TNC_VendorID msg_vid; + TNC_MessageSubtype msg_subtype; + + msg_vid = msg_type >> 8; + msg_subtype = msg_type & TNC_SUBTYPE_ANY; + + return receive_message(imc_id, connection_id, 0, chunk_create(msg, msg_len), + msg_vid, msg_subtype, 0, TNC_IMCID_ANY); +} + +/** + * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3 + */ +TNC_Result TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id, + TNC_ConnectionID connection_id, + TNC_UInt32 msg_flags, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_VendorID msg_vid, + TNC_MessageSubtype msg_subtype, + TNC_UInt32 src_imv_id, + TNC_UInt32 dst_imc_id) +{ + return receive_message(imc_id, connection_id, msg_flags, + chunk_create(msg, msg_len), msg_vid, msg_subtype, + src_imv_id, dst_imc_id); +} + +/** + * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3 + */ +TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id, + TNC_ConnectionID connection_id) +{ + if (!imc_os) + { + DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); + return TNC_RESULT_NOT_INITIALIZED; + } + return TNC_RESULT_SUCCESS; +} + +/** + * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3 + */ +TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id) +{ + if (!imc_os) + { + DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); + return TNC_RESULT_NOT_INITIALIZED; + } + imc_os->destroy(imc_os); + imc_os = NULL; + + return TNC_RESULT_SUCCESS; +} + +/** + * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3 + */ +TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id, + TNC_TNCC_BindFunctionPointer bind_function) +{ + if (!imc_os) + { + DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name); + return TNC_RESULT_NOT_INITIALIZED; + } + return imc_os->bind_functions(imc_os, bind_function); +} diff --git a/src/libimcv/plugins/imc_os/imc_os_state.c b/src/libimcv/plugins/imc_os/imc_os_state.c new file mode 100644 index 000000000..5ad73790a --- /dev/null +++ b/src/libimcv/plugins/imc_os/imc_os_state.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2012 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 "imc_os_state.h" + +#include <tncif_names.h> + +#include <debug.h> + +typedef struct private_imc_os_state_t private_imc_os_state_t; + +/** + * Private data of an imc_os_state_t object. + */ +struct private_imc_os_state_t { + + /** + * Public members of imc_os_state_t + */ + imc_os_state_t public; + + /** + * TNCCS connection ID + */ + TNC_ConnectionID connection_id; + + /** + * TNCCS connection state + */ + TNC_ConnectionState state; + + /** + * Assessment/Evaluation Result + */ + TNC_IMV_Evaluation_Result result; + + /** + * Does the TNCCS connection support long message types? + */ + bool has_long; + + /** + * Does the TNCCS connection support exclusive delivery? + */ + bool has_excl; + + /** + * Maximum PA-TNC message size for this TNCCS connection + */ + u_int32_t max_msg_len; +}; + +METHOD(imc_state_t, get_connection_id, TNC_ConnectionID, + private_imc_os_state_t *this) +{ + return this->connection_id; +} + +METHOD(imc_state_t, has_long, bool, + private_imc_os_state_t *this) +{ + return this->has_long; +} + +METHOD(imc_state_t, has_excl, bool, + private_imc_os_state_t *this) +{ + return this->has_excl; +} + +METHOD(imc_state_t, set_flags, void, + private_imc_os_state_t *this, bool has_long, bool has_excl) +{ + this->has_long = has_long; + this->has_excl = has_excl; +} + +METHOD(imc_state_t, set_max_msg_len, void, + private_imc_os_state_t *this, u_int32_t max_msg_len) +{ + this->max_msg_len = max_msg_len; +} + +METHOD(imc_state_t, get_max_msg_len, u_int32_t, + private_imc_os_state_t *this) +{ + return this->max_msg_len; +} + +METHOD(imc_state_t, change_state, void, + private_imc_os_state_t *this, TNC_ConnectionState new_state) +{ + this->state = new_state; +} + +METHOD(imc_state_t, set_result, void, + private_imc_os_state_t *this, TNC_IMCID id, + TNC_IMV_Evaluation_Result result) +{ + DBG1(DBG_IMC, "set assessment result for IMC %u to '%N'", + id, TNC_IMV_Evaluation_Result_names, result); + this->result = result; +} + +METHOD(imc_state_t, get_result, bool, + private_imc_os_state_t *this, TNC_IMCID id, + TNC_IMV_Evaluation_Result *result) +{ + if (result) + { + *result = this->result; + } + return this->result != TNC_IMV_EVALUATION_RESULT_DONT_KNOW; +} + +METHOD(imc_state_t, destroy, void, + private_imc_os_state_t *this) +{ + free(this); +} + +/** + * Described in header. + */ +imc_state_t *imc_os_state_create(TNC_ConnectionID connection_id) +{ + private_imc_os_state_t *this; + + INIT(this, + .public = { + .interface = { + .get_connection_id = _get_connection_id, + .has_long = _has_long, + .has_excl = _has_excl, + .set_flags = _set_flags, + .set_max_msg_len = _set_max_msg_len, + .get_max_msg_len = _get_max_msg_len, + .change_state = _change_state, + .set_result = _set_result, + .get_result = _get_result, + .destroy = _destroy, + }, + }, + .state = TNC_CONNECTION_STATE_CREATE, + .result = TNC_IMV_EVALUATION_RESULT_DONT_KNOW, + .connection_id = connection_id, + ); + + return &this->public.interface; +} + + diff --git a/src/libimcv/plugins/imc_os/imc_os_state.h b/src/libimcv/plugins/imc_os/imc_os_state.h new file mode 100644 index 000000000..1fe23175a --- /dev/null +++ b/src/libimcv/plugins/imc_os/imc_os_state.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 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 imc_os_state_t imc_os_state + * @{ @ingroup imc_os_state + */ + +#ifndef IMC_OS_STATE_H_ +#define IMC_OS_STATE_H_ + +#include <imc/imc_state.h> +#include <library.h> + +typedef struct imc_os_state_t imc_os_state_t; + +/** + * Internal state of an imc_os_t connection instance + */ +struct imc_os_state_t { + + /** + * imc_state_t interface + */ + imc_state_t interface; +}; + +/** + * Create an imc_os_state_t instance + * + * @param id connection ID + */ +imc_state_t* imc_os_state_create(TNC_ConnectionID id); + +#endif /** IMC_OS_STATE_H_ @}*/ |