diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2013-02-07 13:27:27 +0100 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2013-02-07 13:27:27 +0100 |
commit | 7585facf05d927eb6df3929ce09ed5e60d905437 (patch) | |
tree | e4d14b4dc180db20356b6b01ce0112f3a2d7897e /src/libimcv/imv | |
parent | c1343b3278cdf99533b7902744d15969f9d6fdc1 (diff) | |
download | vyos-strongswan-7585facf05d927eb6df3929ce09ed5e60d905437.tar.gz vyos-strongswan-7585facf05d927eb6df3929ce09ed5e60d905437.zip |
Imported Upstream version 5.0.2
Diffstat (limited to 'src/libimcv/imv')
-rw-r--r-- | src/libimcv/imv/imv_agent.c | 506 | ||||
-rw-r--r-- | src/libimcv/imv/imv_agent.h | 119 | ||||
-rw-r--r-- | src/libimcv/imv/imv_lang_string.c | 73 | ||||
-rw-r--r-- | src/libimcv/imv/imv_lang_string.h | 67 | ||||
-rw-r--r-- | src/libimcv/imv/imv_msg.c | 429 | ||||
-rw-r--r-- | src/libimcv/imv/imv_msg.h | 163 | ||||
-rw-r--r-- | src/libimcv/imv/imv_reason_string.c | 95 | ||||
-rw-r--r-- | src/libimcv/imv/imv_reason_string.h | 64 | ||||
-rw-r--r-- | src/libimcv/imv/imv_remediation_string.c | 209 | ||||
-rw-r--r-- | src/libimcv/imv/imv_remediation_string.h | 72 | ||||
-rw-r--r-- | src/libimcv/imv/imv_state.h | 23 |
11 files changed, 1445 insertions, 375 deletions
diff --git a/src/libimcv/imv/imv_agent.c b/src/libimcv/imv/imv_agent.c index fa04e0237..6a33e396c 100644 --- a/src/libimcv/imv/imv_agent.c +++ b/src/libimcv/imv/imv_agent.c @@ -19,7 +19,7 @@ #include <tncif_names.h> -#include <debug.h> +#include <utils/debug.h> #include <threading/rwlock.h> typedef struct private_imv_agent_t private_imv_agent_t; @@ -40,19 +40,14 @@ struct private_imv_agent_t { const char *name; /** - * message vendor ID of IMV + * message types registered by IMV */ - TNC_VendorID vendor_id; + pen_type_t *supported_types; /** - * message subtype of IMV + * number of message types registered by IMV */ - TNC_MessageSubtype subtype; - - /** - * Maximum PA-TNC Message size - */ - size_t max_msg_len; + u_int32_t type_count; /** * ID of IMV as assigned by TNCS @@ -101,44 +96,6 @@ struct private_imv_agent_t { TNC_UInt32 type_count); /** - * Call when an IMV-IMC message is to be sent - * - * @param imv_id IMV ID assigned by TNCS - * @param connection_id network connection ID assigned by TNCS - * @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_IMVID imv_id, - TNC_ConnectionID connection_id, - TNC_BufferReference msg, - TNC_UInt32 msg_len, - TNC_MessageType msg_type); - - /** - * Call when an IMV-IMC message is to be sent with long message types - * - * @param imv_id IMV ID assigned by TNCS - * @param connection_id network connection ID assigned by TNCS - * @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 IMC ID - * @return TNC result code - */ - TNC_Result (*send_message_long)(TNC_IMVID imv_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_imc_id); - - /** * Deliver IMV Action Recommendation and IMV Evaluation Results to the TNCS * * @param imv_id IMV ID assigned by TNCS @@ -224,14 +181,14 @@ METHOD(imv_agent_t, bind_functions, TNC_Result, this->public.request_handshake_retry = NULL; } if (bind_function(this->id, "TNC_TNCS_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_TNCS_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_TNCS_ProvideRecommendation", (void**)&this->provide_recommendation) != TNC_RESULT_SUCCESS) @@ -258,17 +215,37 @@ METHOD(imv_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 = (this->vendor_id << 8) | this->subtype; - this->report_message_types(this->id, &type, 1); + type_list = malloc(this->type_count * sizeof(TNC_UInt32)); + + 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; } @@ -497,258 +474,16 @@ METHOD(imv_agent_t, get_state, bool, return TRUE; } -METHOD(imv_agent_t, send_message, TNC_Result, - private_imv_agent_t *this, TNC_ConnectionID connection_id, bool excl, - TNC_UInt32 src_imv_id, TNC_UInt32 dst_imc_id, linked_list_t *attr_list) -{ - TNC_MessageType type; - TNC_UInt32 msg_flags; - TNC_Result result = TNC_RESULT_FATAL; - imv_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, "IMV %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(this->max_msg_len); - 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_IMV, "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-IMV 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_imv_id) - { - src_imv_id = this->id; - } - msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0; - - result = this->send_message_long(src_imv_id, connection_id, - msg_flags, msg.ptr, msg.len, this->vendor_id, - this->subtype, dst_imc_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; -} - -METHOD(imv_agent_t, set_recommendation, TNC_Result, - private_imv_agent_t *this, TNC_ConnectionID connection_id, - TNC_IMV_Action_Recommendation rec, - TNC_IMV_Evaluation_Result eval) -{ - imv_state_t *state; - - state = find_connection(this, connection_id); - if (!state) - { - DBG1(DBG_IMV, "IMV %u \"%s\" has no state for Connection ID %u", - this->id, this->name, connection_id); - return TNC_RESULT_FATAL; - } - - state->set_recommendation(state, rec, eval); - return this->provide_recommendation(this->id, connection_id, rec, eval); -} - -METHOD(imv_agent_t, receive_message, TNC_Result, - private_imv_agent_t *this, imv_state_t *state, chunk_t msg, - TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype, - TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id, pa_tnc_msg_t **pa_tnc_msg) +METHOD(imv_agent_t, get_name, const char*, + private_imv_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_imv_id, dst_imc_id; - TNC_ConnectionID connection_id; - TNC_Result result; - - connection_id = state->get_connection_id(state); - - if (state->has_long(state)) - { - if (dst_imv_id != TNC_IMVID_ANY) - { - DBG2(DBG_IMV, "IMV %u \"%s\" received message for Connection ID %u " - "from IMC %u to IMV %u", this->id, this->name, - connection_id, src_imc_id, dst_imv_id); - } - else - { - DBG2(DBG_IMV, "IMV %u \"%s\" received message for Connection ID %u " - "from IMC %u", this->id, this->name, connection_id, - src_imc_id); - } - } - else - { - DBG2(DBG_IMV, "IMV %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_imv_id = (dst_imv_id == TNC_IMVID_ANY) ? this->id : dst_imv_id; - dst_imc_id = state->has_excl(state) ? src_imc_id : TNC_IMCID_ANY; - - result = send_message(this, connection_id, state->has_excl(state), - src_imv_id, dst_imc_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); - state->set_recommendation(state, - TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, - TNC_IMV_EVALUATION_RESULT_ERROR); - return this->provide_recommendation(this->id, connection_id, - TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, - TNC_IMV_EVALUATION_RESULT_ERROR); - } - return TNC_RESULT_SUCCESS; + return this->name; } -METHOD(imv_agent_t, provide_recommendation, TNC_Result, - private_imv_agent_t *this, TNC_ConnectionID connection_id, - TNC_UInt32 dst_imc_id) +METHOD(imv_agent_t, get_id, TNC_IMVID, + private_imv_agent_t *this) { - imv_state_t *state; - linked_list_t *attr_list; - pa_tnc_attr_t *attr; - TNC_Result result; - TNC_IMV_Action_Recommendation rec; - TNC_IMV_Evaluation_Result eval; - TNC_UInt32 lang_len; - char buf[BUF_LEN]; - chunk_t pref_lang = { buf, 0 }, reason_string, reason_lang; - - state = find_connection(this, connection_id); - if (!state) - { - DBG1(DBG_IMV, "IMV %u \"%s\" has no state for Connection ID %u", - this->id, this->name, connection_id); - return TNC_RESULT_FATAL; - } - state->get_recommendation(state, &rec, &eval); - - /* send a reason string if action recommendation is not allow */ - if (rec != TNC_IMV_ACTION_RECOMMENDATION_ALLOW) - { - /* check if there a preferred language has been requested */ - if (this->get_attribute && - this->get_attribute(this->id, connection_id, - TNC_ATTRIBUTEID_PREFERRED_LANGUAGE, BUF_LEN, - buf, &lang_len) == TNC_RESULT_SUCCESS && - lang_len <= BUF_LEN) - { - pref_lang.len = lang_len; - DBG2(DBG_IMV, "preferred language is '%.*s'", (int)pref_lang.len, - pref_lang.ptr); - } - - /* find a reason string for the preferred or default language and set it */ - if (this->set_attribute && - state->get_reason_string(state, pref_lang, &reason_string, - &reason_lang)) - { - this->set_attribute(this->id, connection_id, - TNC_ATTRIBUTEID_REASON_STRING, - reason_string.len, reason_string.ptr); - this->set_attribute(this->id, connection_id, - TNC_ATTRIBUTEID_REASON_LANGUAGE, - reason_lang.len, reason_lang.ptr); - } - } - - /* Send an IETF Assessment Result attribute if enabled */ - if (lib->settings->get_bool(lib->settings, "libimcv.assessment_result", TRUE)) - { - attr = ietf_attr_assess_result_create(eval); - attr_list = linked_list_create(); - attr_list->insert_last(attr_list, attr); - result = send_message(this, connection_id, FALSE, this->id, dst_imc_id, - attr_list); - attr_list->destroy(attr_list); - if (result != TNC_RESULT_SUCCESS) - { - return result; - } - } - return this->provide_recommendation(this->id, connection_id, rec, eval); + return this->id; } METHOD(imv_agent_t, reserve_additional_ids, TNC_Result, @@ -796,6 +531,146 @@ METHOD(imv_agent_t, create_id_enumerator, enumerator_t*, return this->additional_ids->create_enumerator(this->additional_ids); } +typedef struct { + /** + * implements enumerator_t + */ + enumerator_t public; + + /** + * language length + */ + TNC_UInt32 lang_len; + + /** + * language buffer + */ + char lang_buf[BUF_LEN]; + + /** + * position pointer into language buffer + */ + char *lang_pos; + +} language_enumerator_t; + +/** + * Implementation of language_enumerator.destroy. + */ +static void language_enumerator_destroy(language_enumerator_t *this) +{ + free(this); +} + +/** + * Implementation of language_enumerator.enumerate + */ +static bool language_enumerator_enumerate(language_enumerator_t *this, ...) +{ + char *pos, *cur_lang, **lang; + TNC_UInt32 len; + va_list args; + + if (!this->lang_len) + { + return FALSE; + } + cur_lang = this->lang_pos; + pos = strchr(this->lang_pos, ','); + if (pos) + { + len = pos - this->lang_pos; + this->lang_pos += len + 1, + this->lang_len -= len + 1; + } + else + { + len = this->lang_len; + pos = this->lang_pos + len; + this->lang_pos = NULL; + this->lang_len = 0; + } + + /* remove preceding whitespace */ + while (*cur_lang == ' ' && len--) + { + cur_lang++; + } + + /* remove trailing whitespace */ + while (len && *(--pos) == ' ') + { + len--; + } + cur_lang[len] = '\0'; + + va_start(args, this); + lang = va_arg(args, char**); + *lang = cur_lang; + va_end(args); + + return TRUE; +} + +METHOD(imv_agent_t, create_language_enumerator, enumerator_t*, + private_imv_agent_t *this, imv_state_t *state) +{ + language_enumerator_t *e; + + /* Create a language enumerator instance */ + e = malloc_thing(language_enumerator_t); + e->public.enumerate = (void*)language_enumerator_enumerate; + e->public.destroy = (void*)language_enumerator_destroy; + + if (!this->get_attribute || + !this->get_attribute(this->id, state->get_connection_id(state), + TNC_ATTRIBUTEID_PREFERRED_LANGUAGE, BUF_LEN, + e->lang_buf, &e->lang_len) == TNC_RESULT_SUCCESS || + e->lang_len >= BUF_LEN) + { + e->lang_len = 0; + } + e->lang_buf[e->lang_len] = '\0'; + e->lang_pos = e->lang_buf; + + return (enumerator_t*)e; +} + +METHOD(imv_agent_t, provide_recommendation, TNC_Result, + private_imv_agent_t *this, imv_state_t *state) +{ + TNC_IMV_Action_Recommendation rec; + TNC_IMV_Evaluation_Result eval; + TNC_ConnectionID connection_id; + chunk_t reason_string; + char *reason_lang; + enumerator_t *e; + + state->get_recommendation(state, &rec, &eval); + connection_id = state->get_connection_id(state); + + /* send a reason string if action recommendation is not allow */ + if (rec != TNC_IMV_ACTION_RECOMMENDATION_ALLOW) + { + /* find a reason string for the preferred language and set it */ + if (this->set_attribute) + { + e = create_language_enumerator(this, state); + if (state->get_reason_string(state, e, &reason_string, &reason_lang)) + { + this->set_attribute(this->id, connection_id, + TNC_ATTRIBUTEID_REASON_STRING, + reason_string.len, reason_string.ptr); + this->set_attribute(this->id, connection_id, + TNC_ATTRIBUTEID_REASON_LANGUAGE, + strlen(reason_lang), reason_lang); + } + e->destroy(e); + } + } + return this->provide_recommendation(this->id, connection_id, rec, eval); +} + METHOD(imv_agent_t, destroy, void, private_imv_agent_t *this) { @@ -814,7 +689,7 @@ METHOD(imv_agent_t, destroy, void, * Described in header. */ imv_agent_t *imv_agent_create(const char *name, - pen_t vendor_id, u_int32_t subtype, + pen_type_t *supported_types, u_int32_t type_count, TNC_IMVID id, TNC_Version *actual_version) { private_imv_agent_t *this; @@ -832,19 +707,18 @@ imv_agent_t *imv_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, - .set_recommendation = _set_recommendation, - .provide_recommendation = _provide_recommendation, + .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, + .create_language_enumerator = _create_language_enumerator, + .provide_recommendation = _provide_recommendation, .destroy = _destroy, }, .name = name, - .vendor_id = vendor_id, - .subtype = subtype, - .max_msg_len = 65490, + .supported_types = supported_types, + .type_count = type_count, .id = id, .additional_ids = linked_list_create(), .connections = linked_list_create(), diff --git a/src/libimcv/imv/imv_agent.h b/src/libimcv/imv/imv_agent.h index 34ac3c109..5b2cffefe 100644 --- a/src/libimcv/imv/imv_agent.h +++ b/src/libimcv/imv/imv_agent.h @@ -27,7 +27,7 @@ #include <tncifimv.h> #include <pen/pen.h> -#include <utils/linked_list.h> +#include <collections/linked_list.h> #include <library.h> @@ -51,6 +51,44 @@ struct imv_agent_t { TNC_RetryReason reason); /** + * Call when an IMV-IMC message is to be sent + * + * @param imv_id IMV ID assigned by TNCS + * @param connection_id network connection ID assigned by TNCS + * @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_IMVID imv_id, + TNC_ConnectionID connection_id, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_MessageType msg_type); + + /** + * Call when an IMV-IMC message is to be sent with long message types + * + * @param imv_id IMV ID assigned by TNCS + * @param connection_id network connection ID assigned by TNCS + * @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 IMC ID + * @return TNC result code + */ + TNC_Result (*send_message_long)(TNC_IMVID imv_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_imc_id); + + /** * Bind TNCS functions * * @param bind_function function offered by the TNCS @@ -100,63 +138,18 @@ struct imv_agent_t { TNC_ConnectionID connection_id, imv_state_t **state); /** - * Call when a PA-TNC message is to be sent + * Get IMV name * - * @param connection_id network connection ID assigned by TNCS - * @param excl exclusive flag - * @param src_imv_id IMV ID to be set as source - * @param dst_imc_id IMD ID to be set as destination - * @param attr_list list of PA-TNC attributes to send - * @return TNC result code + * return IMV name */ - TNC_Result (*send_message)(imv_agent_t *this, - TNC_ConnectionID connection_id, bool excl, - TNC_UInt32 src_imv_id, TNC_UInt32 dst_imc_id, - linked_list_t *attr_list); + const char* (*get_name)(imv_agent_t *this); /** - * Call when a PA-TNC message was received + * Get base IMV 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_imc_id source IMC ID - * @param dst_imv_id destination IMV ID - * @param pa_tnc_message parsed PA-TNC message or NULL if an error occurred - * @return TNC result code + * return base IMV ID */ - TNC_Result (*receive_message)(imv_agent_t *this, - imv_state_t *state, chunk_t msg, - TNC_VendorID msg_vid, - TNC_MessageSubtype msg_subtype, - TNC_UInt32 src_imc_id, - TNC_UInt32 dst_imv_id, - pa_tnc_msg_t **pa_tnc_msg); - - /** - * Set Action Recommendation and Evaluation Result in the IMV state - * - * @param connection_id network connection ID assigned by TNCS - * @param rec IMV action recommendation - * @param eval IMV evaluation result - * @return TNC result code - */ - TNC_Result (*set_recommendation)(imv_agent_t *this, - TNC_ConnectionID connection_id, - TNC_IMV_Action_Recommendation rec, - TNC_IMV_Evaluation_Result eval); - - /** - * Deliver IMV Action Recommendation and IMV Evaluation Result to the TNCS - * - * @param connection_id network connection ID assigned by TNCS - * @param dst_imc_id IMD ID to be set as destination - * @return TNC result code - */ - TNC_Result (*provide_recommendation)(imv_agent_t *this, - TNC_ConnectionID connection_id, - TNC_UInt32 dst_imc_id); + TNC_IMVID (*get_id)(imv_agent_t *this); /** * Reserve additional IMV IDs from TNCS @@ -179,6 +172,22 @@ struct imv_agent_t { enumerator_t* (*create_id_enumerator)(imv_agent_t *this); /** + * Create a preferred languages enumerator + * + * @param state of TNCCS connection + */ + enumerator_t* (*create_language_enumerator)(imv_agent_t *this, + imv_state_t *state); + + /** + * Deliver IMV Action Recommendation and IMV Evaluation Result to the TNCS + * + * @param state state bound to a connection ID + * @return TNC result code + */ + TNC_Result (*provide_recommendation)(imv_agent_t *this, imv_state_t* state); + + /** * Destroys an imv_agent_t object */ void (*destroy)(imv_agent_t *this); @@ -188,14 +197,14 @@ struct imv_agent_t { * Create an imv_agent_t object * * @param name name of the IMV - * @param vendor_id vendor ID of the IMV - * @param subtype message subtype of the IMV + * @param supported_types list of message types registered by the IMV + * @param type_count number of registered message types * @param id ID of the IMV as assigned by the TNCS * @param actual_version actual version of the IF-IMV API * */ imv_agent_t *imv_agent_create(const char *name, - pen_t vendor_id, u_int32_t subtype, + pen_type_t *supported_types, u_int32_t type_count, TNC_IMVID id, TNC_Version *actual_version); #endif /** IMV_AGENT_H_ @}*/ diff --git a/src/libimcv/imv/imv_lang_string.c b/src/libimcv/imv/imv_lang_string.c new file mode 100644 index 000000000..c86fc5cd7 --- /dev/null +++ b/src/libimcv/imv/imv_lang_string.c @@ -0,0 +1,73 @@ +/* + * 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 "imv_lang_string.h" + +#include <utils/debug.h> + +/** + * Described in header. + */ +char* imv_lang_string_select_lang(enumerator_t *language_enumerator, + char* languages[], int lang_count) +{ + bool match = FALSE; + char *lang; + int i, i_chosen = 0; + + while (language_enumerator->enumerate(language_enumerator, &lang)) + { + for (i = 0; i < lang_count; i++) + { + if (streq(lang, languages[i])) + { + match = TRUE; + i_chosen = i; + break; + } + } + if (match) + { + break; + } + } + return languages[i_chosen]; +} + +/** + * Described in header. + */ +char* imv_lang_string_select_string(imv_lang_string_t lang_string[], char *lang) +{ + char *string; + int i = 0; + + if (!lang_string) + { + return NULL; + } + + string = lang_string[0].string; + while (lang_string[i].lang) + { + if (streq(lang, lang_string[i].lang)) + { + string = lang_string[i].string; + break; + } + i++; + } + return string; +} diff --git a/src/libimcv/imv/imv_lang_string.h b/src/libimcv/imv/imv_lang_string.h new file mode 100644 index 000000000..90a66db76 --- /dev/null +++ b/src/libimcv/imv/imv_lang_string.h @@ -0,0 +1,67 @@ +/* + * 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 imv_lang_string_t imv_lang_string + * @{ @ingroup imv_lang_string + */ + +#ifndef IMV_LANG_STRING_H_ +#define IMV_LANG_STRING_H_ + +#include <library.h> +#include <collections/enumerator.h> + +typedef struct imv_lang_string_t imv_lang_string_t; + +/** + * Define a language string entry + */ +struct imv_lang_string_t { + + /** + * language code + */ + char *lang; + + /** + * UTF-8 string in the corresponding language + */ + char *string; + +}; + +/** + * Select the preferred language + * + * @param language_enumerator enumerator over user preferred languages + * @param languages string array of available languages + * @param lang_count number of available languages + * @return selected language as a language code + */ +char* imv_lang_string_select_lang(enumerator_t *language_enumerator, + char* languages[], int lang_count); + +/** + * Select the preferred language string + * + * @param lang_string multi-lingual array of strings + * @param lang language code of preferred language + * @return selected string + */ +char* imv_lang_string_select_string(imv_lang_string_t lang_string[], char *lang); + +#endif /** IMV_LANG_STRING_H_ @}*/ diff --git a/src/libimcv/imv/imv_msg.c b/src/libimcv/imv/imv_msg.c new file mode 100644 index 000000000..4ed19dd13 --- /dev/null +++ b/src/libimcv/imv/imv_msg.c @@ -0,0 +1,429 @@ +/* + * 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 "imv_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_imv_msg_t private_imv_msg_t; + +/** + * Private data of a imv_msg_t object. + * + */ +struct private_imv_msg_t { + + /** + * Public imv_msg_t interface. + */ + imv_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 IMV agent + */ + imv_agent_t *agent; + + /** + * Assigned IMV state + */ + imv_state_t *state; +}; + +METHOD(imv_msg_t, get_src_id, TNC_UInt32, + private_imv_msg_t *this) +{ + return this->src_id; +} + +METHOD(imv_msg_t, get_dst_id, TNC_UInt32, + private_imv_msg_t *this) +{ + return this->dst_id; +} + +METHOD(imv_msg_t, set_msg_type, void, + private_imv_msg_t *this, pen_type_t msg_type) +{ + if (msg_type.vendor_id != this->msg_type.vendor_id || + msg_type.type != this->msg_type.type) + { + this->msg_type = msg_type; + this->dst_id = TNC_IMCID_ANY; + } +} + +METHOD(imv_msg_t, add_attribute, void, + private_imv_msg_t *this, pa_tnc_attr_t *attr) +{ + this->attr_list->insert_last(this->attr_list, attr); +} + +METHOD(imv_msg_t, send_, TNC_Result, + private_imv_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_IMV, "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-IMV 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_IMV, "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_IMCID_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; +} + +METHOD(imv_msg_t, send_assessment, TNC_Result, + private_imv_msg_t *this) +{ + TNC_IMV_Action_Recommendation rec; + TNC_IMV_Evaluation_Result eval; + pa_tnc_attr_t *attr; + chunk_t string = chunk_empty; + char *lang_code = NULL, *uri = NULL; + enumerator_t *e; + + /* Remove any attributes that have already been constructed */ + while (this->attr_list->remove_last(this->attr_list, (void**)&attr) == SUCCESS) + { + attr->destroy(attr); + } + + /* Send an IETF Assessment Result attribute if enabled */ + if (lib->settings->get_bool(lib->settings, "libimcv.assessment_result", + TRUE)) + { + this->state->get_recommendation(this->state, &rec, &eval); + attr = ietf_attr_assess_result_create(eval); + add_attribute(this, attr); + + /* Send IETF Remediation Instructions if available */ + if (eval != TNC_IMV_EVALUATION_RESULT_COMPLIANT) + { + e = this->agent->create_language_enumerator(this->agent, + this->state); + if (this->state->get_remediation_instructions(this->state, + e, &string, &lang_code, &uri)) + { + if (string.len && lang_code) + { + attr = ietf_attr_remediation_instr_create_from_string(string, + chunk_create(lang_code, strlen(lang_code))); + add_attribute(this, attr); + } + if (uri) + { + attr = ietf_attr_remediation_instr_create_from_uri( + chunk_create(uri, strlen(uri))); + add_attribute(this, attr); + } + } + e->destroy(e); + } + + /* send PA-TNC message with the excl flag set */ + return send_(this, TRUE); + } + return TNC_RESULT_SUCCESS; +} + +METHOD(imv_msg_t, receive, TNC_Result, + private_imv_msg_t *this, bool *fatal_error) +{ + enumerator_t *enumerator; + pa_tnc_attr_t *attr; + chunk_t msg; + + if (this->state->has_long(this->state)) + { + if (this->dst_id != TNC_IMVID_ANY) + { + DBG2(DBG_IMV, "IMV %u \"%s\" received message for Connection ID %u " + "from IMC %u to IMV %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_IMV, "IMV %u \"%s\" received message for Connection ID %u " + "from IMC %u", this->agent->get_id(this->agent), + this->agent->get_name(this->agent), + this->connection_id, this->src_id); + } + } + else + { + DBG2(DBG_IMV, "IMV %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_IMV, "%B", &msg); + + switch (this->pa_msg->process(this->pa_msg)) + { + case SUCCESS: + break; + case VERIFY_ERROR: + { + imv_msg_t *error_msg; + TNC_Result result; + + error_msg = imv_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; + } + + /* preprocess any received IETF standard error attributes */ + *fatal_error = this->pa_msg->process_ietf_std_errors(this->pa_msg); + + return TNC_RESULT_SUCCESS; +} + +METHOD(imv_msg_t, create_attribute_enumerator, enumerator_t*, + private_imv_msg_t *this) +{ + return this->pa_msg->create_attribute_enumerator(this->pa_msg); +} + +METHOD(imv_msg_t, get_encoding, chunk_t, + private_imv_msg_t *this) +{ + if (this->pa_msg) + { + return this->pa_msg->get_encoding(this->pa_msg); + } + return chunk_empty; +} + +METHOD(imv_msg_t, destroy, void, + private_imv_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 + */ +imv_msg_t *imv_msg_create(imv_agent_t *agent, imv_state_t *state, + TNC_ConnectionID connection_id, + TNC_UInt32 src_id, TNC_UInt32 dst_id, + pen_type_t msg_type) +{ + private_imv_msg_t *this; + + INIT(this, + .public = { + .get_src_id = _get_src_id, + .get_dst_id = _get_dst_id, + .set_msg_type = _set_msg_type, + .send = _send_, + .send_assessment = _send_assessment, + .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 + */ +imv_msg_t* imv_msg_create_as_reply(imv_msg_t *msg) +{ + private_imv_msg_t *in; + TNC_UInt32 src_id; + + in = (private_imv_msg_t*)msg; + src_id = (in->dst_id != TNC_IMVID_ANY) ? + in->dst_id : in->agent->get_id(in->agent); + + return imv_msg_create(in->agent, in->state, in->connection_id, src_id, + in->src_id, in->msg_type); +} + +/** + * See header + */ +imv_msg_t *imv_msg_create_from_data(imv_agent_t *agent, imv_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 imv_msg_create_from_long_data(agent, state, connection_id, + TNC_IMCID_ANY, agent->get_id(agent), + msg_vid, msg_subtype, msg); +} + +/** + * See header + */ +imv_msg_t *imv_msg_create_from_long_data(imv_agent_t *agent, imv_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_imv_msg_t *this; + + this = (private_imv_msg_t*)imv_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/imv/imv_msg.h b/src/libimcv/imv/imv_msg.h new file mode 100644 index 000000000..b639712e8 --- /dev/null +++ b/src/libimcv/imv/imv_msg.h @@ -0,0 +1,163 @@ +/* + * 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 imv_msg imv_msg + * @{ @ingroup libimcv + */ + +#ifndef IMV_MSG_H_ +#define IMV_MSG_H_ + +#include <imv/imv_agent.h> + +typedef struct imv_msg_t imv_msg_t; + +#include <library.h> + +/** + * Interface for a PA-TNC message handled by an IMV. + * + */ +struct imv_msg_t { + + /** + * Get source ID of PA-TNC message + * + * @return src ID + */ + TNC_UInt32 (*get_src_id)(imv_msg_t *this); + + /** + * Get destination ID of PA-TNC message + * + * @return destination ID + */ + TNC_UInt32 (*get_dst_id)(imv_msg_t *this); + + /** + * Set the type of a PA-TNC message + * + * @param msg_type message type + */ + void (*set_msg_type)(imv_msg_t *this, pen_type_t msg_type); + + /** + * Sends one or multiple PA-TNC messages + * + * @param excl set the excl message flag if supported + * @return TNC result code + */ + TNC_Result (*send)(imv_msg_t *this, bool excl); + + /** + * Send a PA-TNC message containing an IETF Assessment Result attribute + * + * @return TNC result code + */ + TNC_Result (*send_assessment)(imv_msg_t *this); + + /** + * Processes a received PA-TNC message + * + * @param fatal_error TRUE if IMC sent a fatal error message + * @return TNC result code + */ + TNC_Result (*receive)(imv_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)(imv_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)(imv_msg_t *this); + + /** + * Get the full encoding of an IMV message. + * + * @return message encoding, internal data + */ + chunk_t (*get_encoding)(imv_msg_t *this); + + /** + * Destroys a imv_msg_t object. + */ + void (*destroy)(imv_msg_t *this); +}; + +/** + * Create a wrapper for an outbound message + * + * @param agent IMV agent responsible for the message + * @param state IMV 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_type PA-TNC message type + */ +imv_msg_t* imv_msg_create(imv_agent_t *agent, imv_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 + */ +imv_msg_t* imv_msg_create_as_reply(imv_msg_t *msg); + +/** + * Create a wrapper around message data received via the legacy IF-IMV interface + * + * @param agent IMV agent responsible for the message + * @param state IMV 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 + */ +imv_msg_t* imv_msg_create_from_data(imv_agent_t *agent, imv_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-IMV interface + * + * @param agent IMV agent responsible for the message + * @param state IMV 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_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 + */ +imv_msg_t* imv_msg_create_from_long_data(imv_agent_t *agent, imv_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 /** IMV_MSG_H_ @}*/ diff --git a/src/libimcv/imv/imv_reason_string.c b/src/libimcv/imv/imv_reason_string.c new file mode 100644 index 000000000..18eade01b --- /dev/null +++ b/src/libimcv/imv/imv_reason_string.c @@ -0,0 +1,95 @@ +/* + * 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 "imv_reason_string.h" + +#include <utils/debug.h> + +typedef struct private_imv_reason_string_t private_imv_reason_string_t; + +/** + * Private data of an imv_reason_string_t object. + */ +struct private_imv_reason_string_t { + + /** + * Public members of imv_reason_string_t + */ + imv_reason_string_t public; + + /** + * Preferred language + */ + char *lang; + + /** + * Contains the concatenated reasons + */ + chunk_t reasons; + +}; + +METHOD(imv_reason_string_t, add_reason, void, + private_imv_reason_string_t *this, imv_lang_string_t reason[]) +{ + char *s_reason; + + s_reason = imv_lang_string_select_string(reason, this->lang); + + if (this->reasons.len) + { + /* append any further reasons */ + this->reasons = chunk_cat("cm", this->reasons, chunk_from_chars('\n'), + chunk_create(s_reason, strlen(s_reason))); + } + else + { + /* add the first reason */ + this->reasons = chunk_clone(chunk_create(s_reason, strlen(s_reason))); + } +} + +METHOD(imv_reason_string_t, get_encoding, chunk_t, + private_imv_reason_string_t *this) +{ + return this->reasons; +} + +METHOD(imv_reason_string_t, destroy, void, + private_imv_reason_string_t *this) +{ + free(this->reasons.ptr); + free(this); +} + +/** + * Described in header. + */ +imv_reason_string_t *imv_reason_string_create(char *lang) +{ + private_imv_reason_string_t *this; + + INIT(this, + .public = { + .add_reason = _add_reason, + .get_encoding = _get_encoding, + .destroy = _destroy, + }, + .lang = lang, + ); + + return &this->public; +} + diff --git a/src/libimcv/imv/imv_reason_string.h b/src/libimcv/imv/imv_reason_string.h new file mode 100644 index 000000000..320b2476a --- /dev/null +++ b/src/libimcv/imv/imv_reason_string.h @@ -0,0 +1,64 @@ +/* + * 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 imv_reason_string_t imv_reason_string + * @{ @ingroup imv_reason_string + */ + +#ifndef IMV_REASON_STRING_H_ +#define IMV_REASON_STRING_H_ + +#include "imv_lang_string.h" + +#include <library.h> +#include <collections/linked_list.h> + +typedef struct imv_reason_string_t imv_reason_string_t; + +/** + * Defines and builds a TNC Reason String + */ +struct imv_reason_string_t { + + /** + * Add an individual remediation instruction to the string + * + * @param reason Multi-lingual reason string + */ + void (*add_reason)(imv_reason_string_t *this, imv_lang_string_t reason[]); + + /** + * Gets encoding of the reason string + * + * @return TNC reason string + */ + chunk_t (*get_encoding)(imv_reason_string_t *this); + + /** + * Destroys an imv_reason_string_t object + */ + void (*destroy)(imv_reason_string_t *this); +}; + +/** + * Creates an Reason String object + * + * @param lang Preferred language + */ + imv_reason_string_t* imv_reason_string_create(char *lang); + +#endif /** IMV_REASON_STRING_H_ @}*/ diff --git a/src/libimcv/imv/imv_remediation_string.c b/src/libimcv/imv/imv_remediation_string.c new file mode 100644 index 000000000..af82e1cdd --- /dev/null +++ b/src/libimcv/imv/imv_remediation_string.c @@ -0,0 +1,209 @@ +/* + * 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 "imv_remediation_string.h" + +#include <utils/debug.h> + +typedef struct private_imv_remediation_string_t private_imv_remediation_string_t; + +/** + * Private data of an imv_remediation_string_t object. + */ +struct private_imv_remediation_string_t { + + /** + * Public members of imv_remediation_string_t + */ + imv_remediation_string_t public; + + /** + * XML or plaintext encoding + */ + bool as_xml; + + /** + * Preferred language + */ + char *lang; + + /** + * Contains the concatenated remediation instructions + */ + chunk_t instructions; + +}; + +METHOD(imv_remediation_string_t, add_instruction, void, + private_imv_remediation_string_t *this, imv_lang_string_t title[], + imv_lang_string_t description[], imv_lang_string_t itemsheader[], + linked_list_t *item_list) +{ + char xml_format[] = " <instruction>\n" + " <title>%s</title>\n" + " <description>%s</description>\n" + "%s%s" + " </instruction>\n"; + char *instruction, *format, *item, *pos, *header, *items; + char *s_title, *s_description, *s_itemsheader; + size_t len; + + s_title = imv_lang_string_select_string(title, this->lang); + s_description = imv_lang_string_select_string(description, this->lang); + s_itemsheader = imv_lang_string_select_string(itemsheader, this->lang); + header = NULL; + items = NULL; + + if (s_itemsheader) + { + int header_len = strlen(s_itemsheader); + char *header_format; + + if (this->as_xml) + { + header_format = " <itemsheader>%s</itemsheader>\n"; + header_len += strlen(header_format) - 2; + } + else + { + header_format = "\n %s"; + header_len += 3; + } + header = malloc(header_len + 1); + sprintf(header, header_format, s_itemsheader); + } + + if (item_list && item_list->get_count(item_list)) + { + enumerator_t *enumerator; + int items_len = 0; + + /* compute total length of all items */ + enumerator = item_list->create_enumerator(item_list); + while (enumerator->enumerate(enumerator, &item)) + { + items_len += strlen(item); + } + enumerator->destroy(enumerator); + + if (this->as_xml) + { + items_len += 12 + 20 * item_list->get_count(item_list) + 13; + + pos = items = malloc(items_len + 1); + pos += sprintf(pos, " <items>\n"); + + enumerator = item_list->create_enumerator(item_list); + while (enumerator->enumerate(enumerator, &item)) + { + pos += sprintf(pos, " <item>%s</item>\n", item); + } + enumerator->destroy(enumerator); + + pos += sprintf(pos, " </items>\n"); + } + else + { + items_len += 5 * item_list->get_count(item_list); + + pos = items = malloc(items_len + 1); + + enumerator = item_list->create_enumerator(item_list); + while (enumerator->enumerate(enumerator, &item)) + { + pos += sprintf(pos, "\n %s", item); + } + enumerator->destroy(enumerator); + } + } + + len = strlen(s_title) + strlen(s_description); + if (header) + { + len += strlen(header); + } + if (items) + { + len += strlen(items); + } + + if (this->as_xml) + { + format = xml_format; + len += strlen(xml_format) - 8; + } + else + { + format = this->instructions.len ? "\n%s\n %s%s%s" : "%s\n %s%s%s"; + len += 4; + } + instruction = malloc(len + 1); + sprintf(instruction, format, s_title, s_description, header ? header : "", + items ? items : ""); + free(header); + free(items); + this->instructions = chunk_cat("mm", this->instructions, + chunk_create(instruction, strlen(instruction))); +} + +METHOD(imv_remediation_string_t, get_encoding, chunk_t, + private_imv_remediation_string_t *this) +{ + char xml_header[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<remediationinstructions>\n"; + char xml_trailer[] = "</remediationinstructions>"; + + if (!this->instructions.len) + { + return chunk_empty; + } + if (this->as_xml) + { + this->instructions = chunk_cat("cmc", + chunk_create(xml_header, strlen(xml_header)), + this->instructions, + chunk_create(xml_trailer, strlen(xml_trailer)) + ); + } + return this->instructions; +} + +METHOD(imv_remediation_string_t, destroy, void, + private_imv_remediation_string_t *this) +{ + free(this->instructions.ptr); + free(this); +} + +/** + * Described in header. + */ +imv_remediation_string_t *imv_remediation_string_create(bool as_xml, char *lang) +{ + private_imv_remediation_string_t *this; + + INIT(this, + .public = { + .add_instruction = _add_instruction, + .get_encoding = _get_encoding, + .destroy = _destroy, + }, + .as_xml = as_xml, + .lang = lang, + ); + + return &this->public; +} + diff --git a/src/libimcv/imv/imv_remediation_string.h b/src/libimcv/imv/imv_remediation_string.h new file mode 100644 index 000000000..9249c2aab --- /dev/null +++ b/src/libimcv/imv/imv_remediation_string.h @@ -0,0 +1,72 @@ +/* + * 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 imv_remediation_string_t imv_remediation_string + * @{ @ingroup imv_remediation_string + */ + +#ifndef IMV_REMEDIATION_STRING_H_ +#define IMV_REMEDIATION_STRING_H_ + +#include "imv_lang_string.h" + +#include <library.h> +#include <collections/linked_list.h> + +typedef struct imv_remediation_string_t imv_remediation_string_t; + +/** + * Defines and builds an IETF Remediation Instructions String + */ +struct imv_remediation_string_t { + + /** + * Add an individual remediation instruction to the string + * + * @param title instruction title + * @param description instruction description + * @param itemsheader optional items header or NULL + * @param items optional items list or NULL + */ + void (*add_instruction)(imv_remediation_string_t *this, + imv_lang_string_t title[], + imv_lang_string_t description[], + imv_lang_string_t itemsheader[], + linked_list_t *items); + + /** + * Gets the plaintext or XML encoding of the remediation instructions + * + * @return remediation instructions string + */ + chunk_t (*get_encoding)(imv_remediation_string_t *this); + + /** + * Destroys an imv_remediation_string_t object + */ + void (*destroy)(imv_remediation_string_t *this); +}; + +/** + * Creates an IETF Remediation Instructions String object + * + * @param as_xml XML encoding if TRUE, plaintext otherwise + * @param lang Preferred language + */ + imv_remediation_string_t* imv_remediation_string_create(bool as_xml, char *lang); + +#endif /** IMV_REMEDIATION_STRING_H_ @}*/ diff --git a/src/libimcv/imv/imv_state.h b/src/libimcv/imv/imv_state.h index 1b0845b84..f40402e2b 100644 --- a/src/libimcv/imv/imv_state.h +++ b/src/libimcv/imv/imv_state.h @@ -109,13 +109,28 @@ struct imv_state_t { /** * Get reason string based on the preferred language * - * @param preferred_language preferred language + * @param language_enumerator language enumerator * @param reason_string reason string - * @param language code language of the returned reason string + * @param reason_language language of the returned reason string * @return TRUE if a reason string was found */ - bool (*get_reason_string)(imv_state_t *this, chunk_t preferred_language, - chunk_t *reason_string, chunk_t *language_code); + bool (*get_reason_string)(imv_state_t *this, + enumerator_t *language_enumerator, + chunk_t *reason_string, char **reason_language); + + /** + * Get remediation instructions based on the preferred language + * + * @param language_enumerator language enumerator + * @param string remediation instruction string + * @param lang_code language of the remediation instructions + * @param uri remediation URI + * @return TRUE if remediation instructions were found + */ + bool (*get_remediation_instructions)(imv_state_t *this, + enumerator_t *language_enumerator, + chunk_t *string, char **lang_code, + char **uri); /** * Destroys an imv_state_t object |