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/imv_agent.c | |
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/imv_agent.c')
-rw-r--r-- | src/libimcv/imv/imv_agent.c | 506 |
1 files changed, 190 insertions, 316 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(), |