diff options
Diffstat (limited to 'src/libimcv/imc')
-rw-r--r-- | src/libimcv/imc/imc_agent.c | 272 | ||||
-rw-r--r-- | src/libimcv/imc/imc_agent.h | 79 | ||||
-rw-r--r-- | src/libimcv/imc/imc_msg.c | 457 | ||||
-rw-r--r-- | src/libimcv/imc/imc_msg.h | 149 |
4 files changed, 706 insertions, 251 deletions
diff --git a/src/libimcv/imc/imc_agent.c b/src/libimcv/imc/imc_agent.c index 8d1e70716..161623477 100644 --- a/src/libimcv/imc/imc_agent.c +++ b/src/libimcv/imc/imc_agent.c @@ -18,7 +18,7 @@ #include <tncif_names.h> -#include <debug.h> +#include <utils/debug.h> #include <threading/rwlock.h> typedef struct private_imc_agent_t private_imc_agent_t; @@ -39,14 +39,14 @@ struct private_imc_agent_t { const char *name; /** - * message vendor ID of IMC + * message types registered by IMC */ - TNC_VendorID vendor_id; + pen_type_t *supported_types; /** - * message subtype of IMC + * number of message types registered by IMC */ - TNC_MessageSubtype subtype; + u_int32_t type_count; /** * ID of IMC as assigned by TNCC @@ -95,45 +95,6 @@ struct private_imc_agent_t { TNC_UInt32 type_count); /** - * Call when an IMC-IMC message is to be sent - * - * @param imc_id IMC ID assigned by TNCC - * @param connection_id network connection ID assigned by TNCC - * @param msg message to send - * @param msg_len message length in bytes - * @param msg_type message type - * @return TNC result code - */ - TNC_Result (*send_message)(TNC_IMCID imc_id, - TNC_ConnectionID connection_id, - TNC_BufferReference msg, - TNC_UInt32 msg_len, - TNC_MessageType msg_type); - - - /** - * Call when an IMC-IMC message is to be sent with long message types - * - * @param imc_id IMC ID assigned by TNCC - * @param connection_id network connection ID assigned by TNCC - * @param msg_flags message flags - * @param msg message to send - * @param msg_len message length in bytes - * @param msg_vid message vendor ID - * @param msg_subtype message subtype - * @param dst_imc_id destination IMV ID - * @return TNC result code - */ - TNC_Result (*send_message_long)(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 dst_imv_id); - - /** * Get the value of an attribute associated with a connection * or with the TNCC as a whole. * @@ -205,14 +166,14 @@ METHOD(imc_agent_t, bind_functions, TNC_Result, this->public.request_handshake_retry = NULL; } if (bind_function(this->id, "TNC_TNCC_SendMessage", - (void**)&this->send_message) != TNC_RESULT_SUCCESS) + (void**)&this->public.send_message) != TNC_RESULT_SUCCESS) { - this->send_message = NULL; + this->public.send_message = NULL; } if (bind_function(this->id, "TNC_TNCC_SendMessageLong", - (void**)&this->send_message_long) != TNC_RESULT_SUCCESS) + (void**)&this->public.send_message_long) != TNC_RESULT_SUCCESS) { - this->send_message_long = NULL; + this->public.send_message_long = NULL; } if (bind_function(this->id, "TNC_TNCC_GetAttribute", (void**)&this->get_attribute) != TNC_RESULT_SUCCESS) @@ -234,17 +195,37 @@ METHOD(imc_agent_t, bind_functions, TNC_Result, if (this->report_message_types_long) { - this->report_message_types_long(this->id, &this->vendor_id, - &this->subtype, 1); + TNC_VendorIDList vendor_id_list; + TNC_MessageSubtypeList subtype_list; + int i; + + vendor_id_list = malloc(this->type_count * sizeof(TNC_UInt32)); + subtype_list = malloc(this->type_count * sizeof(TNC_UInt32)); + + for (i = 0; i < this->type_count; i++) + { + vendor_id_list[i] = this->supported_types[i].vendor_id; + subtype_list[i] = this->supported_types[i].type; + } + this->report_message_types_long(this->id, vendor_id_list, subtype_list, + this->type_count); + free(vendor_id_list); + free(subtype_list); } - else if (this->report_message_types && - this->vendor_id <= TNC_VENDORID_ANY && - this->subtype <= TNC_SUBTYPE_ANY) + else if (this->report_message_types) { - TNC_MessageType type; + TNC_MessageTypeList type_list; + int i; + + type_list = malloc(this->type_count * sizeof(TNC_UInt32)); - type = (this->vendor_id << 8) | this->subtype; - this->report_message_types(this->id, &type, 1); + for (i = 0; i < this->type_count; i++) + { + type_list[i] = (this->supported_types[i].vendor_id << 8) | + (this->supported_types[i].type & 0xff); + } + this->report_message_types(this->id, type_list, this->type_count); + free(type_list); } return TNC_RESULT_SUCCESS; } @@ -372,7 +353,7 @@ METHOD(imc_agent_t, create_state, TNC_Result, has_long = get_bool_attribute(this, conn_id, TNC_ATTRIBUTEID_HAS_LONG_TYPES); has_excl = get_bool_attribute(this, conn_id, TNC_ATTRIBUTEID_HAS_EXCLUSIVE); has_soh = get_bool_attribute(this, conn_id, TNC_ATTRIBUTEID_HAS_SOH); - tnccs_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL); + tnccs_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL); tnccs_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFTNCCS_VERSION); t_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_PROTOCOL); t_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_VERSION); @@ -427,7 +408,7 @@ METHOD(imc_agent_t, change_state, TNC_Result, case TNC_CONNECTION_STATE_ACCESS_ISOLATED: case TNC_CONNECTION_STATE_ACCESS_NONE: state = find_connection(this, connection_id); - + if (!state) { DBG1(DBG_IMC, "IMC %u \"%s\" has no state for Connection ID %u", @@ -455,7 +436,7 @@ METHOD(imc_agent_t, change_state, TNC_Result, DBG1(DBG_IMC, "IMC %u \"%s\" was notified of unknown state %u " "for Connection ID %u", this->id, this->name, new_state, connection_id); - return TNC_RESULT_INVALID_PARAMETER; + return TNC_RESULT_INVALID_PARAMETER; } return TNC_RESULT_SUCCESS; } @@ -474,165 +455,16 @@ METHOD(imc_agent_t, get_state, bool, return TRUE; } -METHOD(imc_agent_t, send_message, TNC_Result, - private_imc_agent_t *this, TNC_ConnectionID connection_id, bool excl, - TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id, linked_list_t *attr_list) +METHOD(imc_agent_t, get_name, const char*, + private_imc_agent_t *this) { - TNC_MessageType type; - TNC_UInt32 msg_flags; - TNC_Result result = TNC_RESULT_FATAL; - imc_state_t *state; - pa_tnc_attr_t *attr; - pa_tnc_msg_t *pa_tnc_msg; - chunk_t msg; - enumerator_t *enumerator; - bool attr_added; - - state = find_connection(this, connection_id); - if (!state) - { - DBG1(DBG_IMV, "IMC %u \"%s\" has no state for Connection ID %u", - this->id, this->name, connection_id); - return TNC_RESULT_FATAL; - } - - while (attr_list->get_count(attr_list)) - { - pa_tnc_msg = pa_tnc_msg_create(state->get_max_msg_len(state)); - attr_added = FALSE; - - enumerator = attr_list->create_enumerator(attr_list); - while (enumerator->enumerate(enumerator, &attr)) - { - if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr)) - { - attr_added = TRUE; - } - else - { - if (attr_added) - { - break; - } - else - { - DBG1(DBG_IMC, "PA-TNC attribute too large to send, deleted"); - attr->destroy(attr); - } - } - attr_list->remove_at(attr_list, enumerator); - } - enumerator->destroy(enumerator); - - /* build and send the PA-TNC message via the IF-IMC interface */ - if (!pa_tnc_msg->build(pa_tnc_msg)) - { - pa_tnc_msg->destroy(pa_tnc_msg); - return TNC_RESULT_FATAL; - } - msg = pa_tnc_msg->get_encoding(pa_tnc_msg); - - if (state->has_long(state) && this->send_message_long) - { - if (!src_imc_id) - { - src_imc_id = this->id; - } - msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0; - - result = this->send_message_long(src_imc_id, connection_id, - msg_flags, msg.ptr, msg.len, this->vendor_id, - this->subtype, dst_imv_id); - } - else if (this->send_message) - { - type = (this->vendor_id << 8) | this->subtype; - - result = this->send_message(this->id, connection_id, msg.ptr, - msg.len, type); - } - - pa_tnc_msg->destroy(pa_tnc_msg); - - if (result != TNC_RESULT_SUCCESS) - { - break; - } - } - return result; + return this->name; } -METHOD(imc_agent_t, receive_message, TNC_Result, - private_imc_agent_t *this, imc_state_t *state, 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) +METHOD(imc_agent_t, get_id, TNC_IMCID, + private_imc_agent_t *this) { - pa_tnc_msg_t *pa_msg; - pa_tnc_attr_t *error_attr; - linked_list_t *error_attr_list; - enumerator_t *enumerator; - TNC_UInt32 src_imc_id, dst_imv_id; - TNC_ConnectionID connection_id; - TNC_Result result; - - connection_id = state->get_connection_id(state); - - if (state->has_long(state)) - { - if (dst_imc_id != TNC_IMCID_ANY) - { - DBG2(DBG_IMC, "IMC %u \"%s\" received message for Connection ID %u " - "from IMV %u to IMC %u", this->id, this->name, - connection_id, src_imv_id, dst_imc_id); - } - else - { - DBG2(DBG_IMC, "IMC %u \"%s\" received message for Connection ID %u " - "from IMV %u", this->id, this->name, connection_id, - src_imv_id); - } - } - else - { - DBG2(DBG_IMC, "IMC %u \"%s\" received message for Connection ID %u", - this->id, this->name, connection_id); - } - - *pa_tnc_msg = NULL; - pa_msg = pa_tnc_msg_create_from_data(msg); - - switch (pa_msg->process(pa_msg)) - { - case SUCCESS: - *pa_tnc_msg = pa_msg; - break; - case VERIFY_ERROR: - /* extract and copy by refence all error attributes */ - error_attr_list = linked_list_create(); - - enumerator = pa_msg->create_error_enumerator(pa_msg); - while (enumerator->enumerate(enumerator, &error_attr)) - { - error_attr_list->insert_last(error_attr_list, - error_attr->get_ref(error_attr)); - } - enumerator->destroy(enumerator); - - src_imc_id = (dst_imc_id == TNC_IMCID_ANY) ? this->id : dst_imc_id; - dst_imv_id = state->has_excl(state) ? src_imv_id : TNC_IMVID_ANY; - - result = send_message(this, connection_id, state->has_excl(state), - src_imc_id, dst_imv_id, error_attr_list); - - error_attr_list->destroy(error_attr_list); - pa_msg->destroy(pa_msg); - return result; - case FAILED: - default: - pa_msg->destroy(pa_msg); - return TNC_RESULT_FATAL; - } - return TNC_RESULT_SUCCESS; + return this->id; } METHOD(imc_agent_t, reserve_additional_ids, TNC_Result, @@ -697,7 +529,7 @@ METHOD(imc_agent_t, destroy, void, * Described in header. */ imc_agent_t *imc_agent_create(const char *name, - pen_t vendor_id, u_int32_t subtype, + pen_type_t *supported_types, u_int32_t type_count, TNC_IMCID id, TNC_Version *actual_version) { private_imc_agent_t *this; @@ -715,22 +547,22 @@ imc_agent_t *imc_agent_create(const char *name, .delete_state = _delete_state, .change_state = _change_state, .get_state = _get_state, - .send_message = _send_message, - .receive_message = _receive_message, + .get_name = _get_name, + .get_id = _get_id, .reserve_additional_ids = _reserve_additional_ids, .count_additional_ids = _count_additional_ids, .create_id_enumerator = _create_id_enumerator, .destroy = _destroy, }, .name = name, - .vendor_id = vendor_id, - .subtype = subtype, + .supported_types = supported_types, + .type_count = type_count, .id = id, .additional_ids = linked_list_create(), .connections = linked_list_create(), .connection_lock = rwlock_create(RWLOCK_TYPE_DEFAULT), ); - + *actual_version = TNC_IFIMC_VERSION_1; DBG1(DBG_IMC, "IMC %u \"%s\" initialized", this->id, this->name); diff --git a/src/libimcv/imc/imc_agent.h b/src/libimcv/imc/imc_agent.h index e87450aa6..aef10c0d7 100644 --- a/src/libimcv/imc/imc_agent.h +++ b/src/libimcv/imc/imc_agent.h @@ -27,7 +27,7 @@ #include <tncifimc.h> #include <pen/pen.h> -#include <utils/linked_list.h> +#include <collections/linked_list.h> #include <library.h> @@ -51,6 +51,44 @@ struct imc_agent_t { TNC_RetryReason reason); /** + * Call when an IMC-IMC message is to be sent + * + * @param imc_id IMC ID assigned by TNCC + * @param connection_id network connection ID assigned by TNCC + * @param msg message to send + * @param msg_len message length in bytes + * @param msg_type message type + * @return TNC result code + */ + TNC_Result (*send_message)(TNC_IMCID imc_id, + TNC_ConnectionID connection_id, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_MessageType msg_type); + + /** + * Call when an IMC-IMC message is to be sent with long message types + * + * @param imc_id IMC ID assigned by TNCC + * @param connection_id network connection ID assigned by TNCC + * @param msg_flags message flags + * @param msg message to send + * @param msg_len message length in bytes + * @param msg_vid message vendor ID + * @param msg_subtype message subtype + * @param dst_imc_id destination IMV ID + * @return TNC result code + */ + TNC_Result (*send_message_long)(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 dst_imv_id); + + /** * Bind TNCC functions * * @param bind_function function offered by the TNCC @@ -100,39 +138,18 @@ struct imc_agent_t { TNC_ConnectionID connection_id, imc_state_t **state); /** - * Call when an PA-TNC message is to be sent + * Get IMC name * - * @param connection_id network connection ID assigned by TNCC - * @param excl exclusive flag - * @param src_imc_id IMC ID to be set as source - * @param dst_imv_id IMV ID to be set as destination - * @param attr_list list of PA-TNC attributes to send - * @return TNC result code + * return IMC name */ - TNC_Result (*send_message)(imc_agent_t *this, - TNC_ConnectionID connection_id, bool excl, - TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id, - linked_list_t *attr_list); + const char* (*get_name)(imc_agent_t *this); /** - * Call when a PA-TNC message was received + * Get base IMC ID * - * @param state state for current connection - * @param msg received unparsed message - * @param msg_vid message vendorID of the received message - * @param msg_subtype message subtype of the received message - * @param src_imv_id source IMV ID - * @param dst_imc_id destination IMC ID - * @param pa_tnc_message parsed PA-TNC message or NULL if an error occurred - * @return TNC result code + * return base IMC ID */ - TNC_Result (*receive_message)(imc_agent_t *this, - imc_state_t *state, 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); + TNC_IMCID (*get_id)(imc_agent_t *this); /** * Reserve additional IMC IDs from TNCC @@ -164,14 +181,14 @@ struct imc_agent_t { * Create an imc_agent_t object * * @param name name of the IMC - * @param vendor_id vendor ID of the IMC - * @param subtype message subtype of the IMC + * @param supported_types list of message types registered by the IMC + * @param type_count number of registered message types * @param id ID of the IMC as assigned by the TNCS * @param actual_version actual version of the IF-IMC API * */ imc_agent_t *imc_agent_create(const char *name, - pen_t vendor_id, u_int32_t subtype, + pen_type_t *supported_types, u_int32_t type_count, TNC_IMCID id, TNC_Version *actual_version); #endif /** IMC_AGENT_H_ @}*/ diff --git a/src/libimcv/imc/imc_msg.c b/src/libimcv/imc/imc_msg.c new file mode 100644 index 000000000..050e63f32 --- /dev/null +++ b/src/libimcv/imc/imc_msg.c @@ -0,0 +1,457 @@ +/* + * 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_msg.h" + +#include "ietf/ietf_attr.h" +#include "ietf/ietf_attr_assess_result.h" +#include "ietf/ietf_attr_remediation_instr.h" + +#include <tncif_names.h> + +#include <pen/pen.h> +#include <collections/linked_list.h> +#include <utils/debug.h> + +typedef struct private_imc_msg_t private_imc_msg_t; + +/** + * Private data of a imc_msg_t object. + * + */ +struct private_imc_msg_t { + + /** + * Public imc_msg_t interface. + */ + imc_msg_t public; + + /** + * Connection ID + */ + TNC_ConnectionID connection_id; + + /** + * source ID + */ + TNC_UInt32 src_id; + + /** + * destination ID + */ + TNC_UInt32 dst_id; + + /** + * PA-TNC message type + */ + pen_type_t msg_type; + + /** + * List of PA-TNC attributes to be sent + */ + linked_list_t *attr_list; + + /** + * PA-TNC message + */ + pa_tnc_msg_t *pa_msg; + + /** + * Assigned IMC agent + */ + imc_agent_t *agent; + + /** + * Assigned IMC state + */ + imc_state_t *state; +}; + +METHOD(imc_msg_t, get_src_id, TNC_UInt32, + private_imc_msg_t *this) +{ + return this->src_id; +} + +METHOD(imc_msg_t, get_dst_id, TNC_UInt32, + private_imc_msg_t *this) +{ + return this->dst_id; +} + +METHOD(imc_msg_t, send_, TNC_Result, + private_imc_msg_t *this, bool excl) +{ + pa_tnc_msg_t *pa_tnc_msg; + pa_tnc_attr_t *attr; + TNC_UInt32 msg_flags; + TNC_MessageType msg_type; + bool attr_added; + chunk_t msg; + enumerator_t *enumerator; + TNC_Result result = TNC_RESULT_SUCCESS; + + while (this->attr_list->get_count(this->attr_list)) + { + pa_tnc_msg = pa_tnc_msg_create(this->state->get_max_msg_len(this->state)); + attr_added = FALSE; + + enumerator = this->attr_list->create_enumerator(this->attr_list); + while (enumerator->enumerate(enumerator, &attr)) + { + if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr)) + { + attr_added = TRUE; + } + else + { + if (attr_added) + { + break; + } + else + { + DBG1(DBG_IMC, "PA-TNC attribute too large to send, deleted"); + attr->destroy(attr); + } + } + this->attr_list->remove_at(this->attr_list, enumerator); + } + enumerator->destroy(enumerator); + + /* build and send the PA-TNC message via the IF-IMC interface */ + if (!pa_tnc_msg->build(pa_tnc_msg)) + { + pa_tnc_msg->destroy(pa_tnc_msg); + return TNC_RESULT_FATAL; + } + msg = pa_tnc_msg->get_encoding(pa_tnc_msg); + DBG3(DBG_IMC, "created PA-TNC message: %B", &msg); + + if (this->state->has_long(this->state) && this->agent->send_message_long) + { + excl = excl && this->state->has_excl(this->state) && + this->dst_id != TNC_IMVID_ANY; + msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0; + result = this->agent->send_message_long(this->src_id, + this->connection_id, msg_flags, msg.ptr, msg.len, + this->msg_type.vendor_id, this->msg_type.type, + this->dst_id); + } + else if (this->agent->send_message) + { + msg_type = (this->msg_type.vendor_id << 8) | + (this->msg_type.type & 0x000000ff); + result = this->agent->send_message(this->src_id, this->connection_id, + msg.ptr, msg.len, msg_type); + } + + pa_tnc_msg->destroy(pa_tnc_msg); + + if (result != TNC_RESULT_SUCCESS) + { + break; + } + } + return result; +} + +/** + * Print a clearly visible assessment header to the log + */ +static void print_assessment_header(const char *name, TNC_UInt32 id, bool *first) +{ + if (*first) + { + DBG1(DBG_IMC, "***** assessment of IMC %u \"%s\" *****", id, name); + *first = FALSE; + } +} + +/** + * Print a clearly visible assessment trailer to the log + */ +static void print_assessment_trailer(bool first) +{ + if (!first) + { + DBG1(DBG_IMC, "***** end of assessment *****"); + } +} + +METHOD(imc_msg_t, receive, TNC_Result, + private_imc_msg_t *this, bool *fatal_error) +{ + TNC_UInt32 target_imc_id; + enumerator_t *enumerator; + pa_tnc_attr_t *attr; + pen_type_t attr_type; + chunk_t msg; + bool first = TRUE; + + if (this->state->has_long(this->state)) + { + if (this->dst_id != TNC_IMCID_ANY) + { + DBG2(DBG_IMC, "IMC %u \"%s\" received message for Connection ID %u " + "from IMV %u to IMC %u", + this->agent->get_id(this->agent), + this->agent->get_name(this->agent), + this->connection_id, this->src_id, this->dst_id); + } + else + { + DBG2(DBG_IMC, "IMC %u \"%s\" received message for Connection ID %u " + "from IMV %u", this->agent->get_id(this->agent), + this->agent->get_name(this->agent), + this->connection_id, this->src_id); + } + } + else + { + DBG2(DBG_IMC, "IMC %u \"%s\" received message for Connection ID %u", + this->agent->get_id(this->agent), + this->agent->get_name(this->agent), + this->connection_id); + } + msg = this->pa_msg->get_encoding(this->pa_msg); + DBG3(DBG_IMC, "%B", &msg); + + switch (this->pa_msg->process(this->pa_msg)) + { + case SUCCESS: + break; + case VERIFY_ERROR: + { + imc_msg_t *error_msg; + TNC_Result result; + + error_msg = imc_msg_create_as_reply(&this->public); + + /* extract and copy by reference all error attributes */ + enumerator = this->pa_msg->create_error_enumerator(this->pa_msg); + while (enumerator->enumerate(enumerator, &attr)) + { + error_msg->add_attribute(error_msg, attr->get_ref(attr)); + } + enumerator->destroy(enumerator); + + /* + * send the PA-TNC message containing all error attributes + * with the excl flag set + */ + result = error_msg->send(error_msg, TRUE); + error_msg->destroy(error_msg); + return result; + } + case FAILED: + default: + return TNC_RESULT_FATAL; + } + + /* determine target IMC ID */ + target_imc_id = (this->dst_id != TNC_IMCID_ANY) ? + this->dst_id : this->agent->get_id(this->agent); + + /* preprocess any received IETF standard error attributes */ + *fatal_error = this->pa_msg->process_ietf_std_errors(this->pa_msg); + + /* preprocess any received IETF assessment result attribute */ + enumerator = this->pa_msg->create_attribute_enumerator(this->pa_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_ASSESSMENT_RESULT) + { + ietf_attr_assess_result_t *attr_cast; + TNC_IMV_Evaluation_Result result; + + attr_cast = (ietf_attr_assess_result_t*)attr; + result = attr_cast->get_result(attr_cast); + this->state->set_result(this->state, target_imc_id, result); + + print_assessment_header(this->agent->get_name(this->agent), + target_imc_id, &first); + DBG1(DBG_IMC, "assessment result is '%N'", + TNC_IMV_Evaluation_Result_names, result); + } + else if (attr_type.type == IETF_ATTR_REMEDIATION_INSTRUCTIONS) + { + ietf_attr_remediation_instr_t *attr_cast; + pen_type_t parameters_type; + chunk_t parameters, string, lang_code; + + attr_cast = (ietf_attr_remediation_instr_t*)attr; + parameters_type = attr_cast->get_parameters_type(attr_cast); + parameters = attr_cast->get_parameters(attr_cast); + + print_assessment_header(this->agent->get_name(this->agent), + target_imc_id, &first); + if (parameters_type.vendor_id == PEN_IETF) + { + switch (parameters_type.type) + { + case IETF_REMEDIATION_PARAMETERS_URI: + DBG1(DBG_IMC, "remediation uri: %.*s", + parameters.len, parameters.ptr); + break; + case IETF_REMEDIATION_PARAMETERS_STRING: + string = attr_cast->get_string(attr_cast, &lang_code); + DBG1(DBG_IMC, "remediation string: [%.*s]\n%.*s", + lang_code.len, lang_code.ptr, + string.len, string.ptr); + break; + default: + DBG1(DBG_IMC, "remediation parameters: %B", ¶meters); + } + } + else + { + DBG1(DBG_IMC, "remediation parameters: %B", ¶meters); + } + } + } + enumerator->destroy(enumerator); + + print_assessment_trailer(first); + + return TNC_RESULT_SUCCESS; +} + +METHOD(imc_msg_t, add_attribute, void, + private_imc_msg_t *this, pa_tnc_attr_t *attr) +{ + this->attr_list->insert_last(this->attr_list, attr); +} + +METHOD(imc_msg_t, create_attribute_enumerator, enumerator_t*, + private_imc_msg_t *this) +{ + return this->pa_msg->create_attribute_enumerator(this->pa_msg); +} + +METHOD(imc_msg_t, get_encoding, chunk_t, + private_imc_msg_t *this) +{ + if (this->pa_msg) + { + return this->pa_msg->get_encoding(this->pa_msg); + } + return chunk_empty; +} + +METHOD(imc_msg_t, destroy, void, + private_imc_msg_t *this) +{ + this->attr_list->destroy_offset(this->attr_list, + offsetof(pa_tnc_attr_t, destroy)); + DESTROY_IF(this->pa_msg); + free(this); +} + +/** + * See header + */ +imc_msg_t *imc_msg_create(imc_agent_t *agent, imc_state_t *state, + TNC_ConnectionID connection_id, + TNC_UInt32 src_id, TNC_UInt32 dst_id, + pen_type_t msg_type) +{ + private_imc_msg_t *this; + + INIT(this, + .public = { + .get_src_id = _get_src_id, + .get_dst_id = _get_dst_id, + .send = _send_, + .receive = _receive, + .add_attribute = _add_attribute, + .create_attribute_enumerator = _create_attribute_enumerator, + .get_encoding = _get_encoding, + .destroy = _destroy, + }, + .connection_id = connection_id, + .src_id = src_id, + .dst_id = dst_id, + .msg_type = msg_type, + .attr_list = linked_list_create(), + .agent = agent, + .state = state, + ); + + return &this->public; +} + +/** + * See header + */ +imc_msg_t* imc_msg_create_as_reply(imc_msg_t *msg) +{ + private_imc_msg_t *in; + TNC_UInt32 src_id; + + in = (private_imc_msg_t*)msg; + src_id = (in->dst_id != TNC_IMCID_ANY) ? + in->dst_id : in->agent->get_id(in->agent); + + return imc_msg_create(in->agent, in->state, in->connection_id, src_id, + in->src_id, in->msg_type); +} + +/** + * See header + */ +imc_msg_t *imc_msg_create_from_data(imc_agent_t *agent, imc_state_t *state, + TNC_ConnectionID connection_id, + TNC_MessageType msg_type, + chunk_t msg) +{ + TNC_VendorID msg_vid; + TNC_MessageSubtype msg_subtype; + + msg_vid = msg_type >> 8; + msg_subtype = msg_type & TNC_SUBTYPE_ANY; + + return imc_msg_create_from_long_data(agent, state, connection_id, + TNC_IMVID_ANY, agent->get_id(agent), + msg_vid, msg_subtype, msg); +} + +/** + * See header + */ +imc_msg_t *imc_msg_create_from_long_data(imc_agent_t *agent, imc_state_t *state, + TNC_ConnectionID connection_id, + TNC_UInt32 src_id, + TNC_UInt32 dst_id, + TNC_VendorID msg_vid, + TNC_MessageSubtype msg_subtype, + chunk_t msg) +{ + private_imc_msg_t *this; + + this = (private_imc_msg_t*)imc_msg_create(agent, state, + connection_id, src_id, dst_id, + pen_type_create(msg_vid, msg_subtype)); + this->pa_msg = pa_tnc_msg_create_from_data(msg); + + return &this->public; +} + diff --git a/src/libimcv/imc/imc_msg.h b/src/libimcv/imc/imc_msg.h new file mode 100644 index 000000000..6dd712e84 --- /dev/null +++ b/src/libimcv/imc/imc_msg.h @@ -0,0 +1,149 @@ +/* + * 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_msg imc_msg + * @{ @ingroup libimcv + */ + +#ifndef IMC_MSG_H_ +#define IMC_MSG_H_ + +#include <imc/imc_agent.h> + +typedef struct imc_msg_t imc_msg_t; + +#include <library.h> + +/** + * Interface for a PA-TNC message handled by an IMC. + * + */ +struct imc_msg_t { + + /** + * Get source ID of PA-TNC message + * + * @return src ID + */ + TNC_UInt32 (*get_src_id)(imc_msg_t *this); + + /** + * Get destination ID of PA-TNC message + * + * @return destination ID + */ + TNC_UInt32 (*get_dst_id)(imc_msg_t *this); + + /** + * Sends one or multiple PA-TNC messages + * + * @param excl set the excl message flag if supported + * @return TNC result code + */ + TNC_Result (*send)(imc_msg_t *this, bool excl); + + /** + * Processes a received PA-TNC message + * + * @param fatal_error TRUE if IMV sent a fatal error message + * @return TNC result code + */ + TNC_Result (*receive)(imc_msg_t *this, bool *fatal_error); + + /** + * Add a PA-TNC attribute to the send queue + * + * @param attr PA-TNC attribute to be added + */ + void (*add_attribute)(imc_msg_t *this, pa_tnc_attr_t *attr); + + /** + * Enumerator over PA-TNC attributes contained in the PA-TNC message + * + * @return PA-TNC attribute enumerator + */ + enumerator_t* (*create_attribute_enumerator)(imc_msg_t *this); + + /** + * Get the encoding of the IMC message. + * + * @return message encoding, internal data + */ + chunk_t (*get_encoding)(imc_msg_t *this); + + /** + * Destroys a imc_msg_t object. + */ + void (*destroy)(imc_msg_t *this); +}; + +/** + * Create a wrapper for an outbound message + * + * @param agent IMC agent responsible for the message + * @param state IMC state for the given connection ID + * @param connection_id connection ID + * @param src_id source IMC ID + * @param dst_id destination IMV ID + * @param msg_type PA-TNC message type + */ +imc_msg_t* imc_msg_create(imc_agent_t *agent, imc_state_t *state, + TNC_ConnectionID connection_id, + TNC_UInt32 src_id, TNC_UInt32 dst_id, + pen_type_t msg_type); + +/** + * Create a wrapper for an outbound message based on a received message + * + * @param msg received message the reply is based on + */ +imc_msg_t* imc_msg_create_as_reply(imc_msg_t *msg); + +/** + * Create a wrapper around message data received via the legacy IF-IMC interface + * + * @param agent IMC agent responsible for the message + * @param state IMC state for the given connection ID + * @param connection_id connection ID + * @param msg_type PA-TNC message type + * @param msg received PA-TNC message blob + */ +imc_msg_t* imc_msg_create_from_data(imc_agent_t *agent, imc_state_t *state, + TNC_ConnectionID connection_id, + TNC_MessageType msg_type, + chunk_t msg); + +/** + * Create a wrapper around message data received via the long IF-IMC interface + * + * @param agent IMC agent responsible for the message + * @param state IMC state for the given connection ID + * @param connection_id connection ID + * @param src_id source IMV ID + * @param dst_id destination IMC ID + * @param msg_flags PA-TNC message flags + * @param msg_vid PA-TNC message vendor ID + * @param msg_subtype PA-TNC subtype + * @param msg received PA-TNC message blob + */ +imc_msg_t* imc_msg_create_from_long_data(imc_agent_t *agent, imc_state_t *state, + TNC_ConnectionID connection_id, + TNC_UInt32 src_id, TNC_UInt32 dst_id, + TNC_VendorID msg_vid, + TNC_MessageSubtype msg_subtype, + chunk_t msg); + +#endif /** IMC_MSG_H_ @}*/ |