From db15c6dac159017c5cfd36f8227225ff261883ae Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Sat, 10 Nov 2012 21:35:46 +0100 Subject: [PATCH] implement a preferred language enumerator --- src/libimcv/imv/imv_agent.c | 188 +++++++++++++----- src/libimcv/imv/imv_agent.h | 24 ++- src/libimcv/imv/imv_state.h | 7 +- src/libimcv/plugins/imv_os/imv_os_state.c | 10 +- .../plugins/imv_scanner/imv_scanner_state.c | 67 +++---- src/libimcv/plugins/imv_test/imv_test_state.c | 47 ++--- .../imv_attestation/imv_attestation_state.c | 47 ++--- 7 files changed, 226 insertions(+), 164 deletions(-) diff --git a/src/libimcv/imv/imv_agent.c b/src/libimcv/imv/imv_agent.c index d664dc9c1..2a678751e 100644 --- a/src/libimcv/imv/imv_agent.c +++ b/src/libimcv/imv/imv_agent.c @@ -474,50 +474,6 @@ METHOD(imv_agent_t, get_state, bool, return TRUE; } -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; - TNC_UInt32 lang_len; - char buf[BUF_LEN]; - chunk_t pref_lang = { buf, 0 }, reason_string, reason_lang; - - 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) - { - /* 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); - } - } - return this->provide_recommendation(this->id, connection_id, rec, eval); -} - METHOD(imv_agent_t, get_name, const char*, private_imv_agent_t *this) { @@ -575,6 +531,147 @@ 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 + { + pos = this->lang_pos + len; + len = this->lang_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'; + DBG1(DBG_IMV, "current language = '%s'", cur_lang); + + 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); + + 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) + { + free(e); + return NULL; + } + e->public.enumerate = (void*)language_enumerator_enumerate; + e->public.destroy = (void*)language_enumerator_destroy; + 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; + char *reason_string, *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, + strlen(reason_string), reason_string); + 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) { @@ -611,12 +708,13 @@ imv_agent_t *imv_agent_create(const char *name, .delete_state = _delete_state, .change_state = _change_state, .get_state = _get_state, - .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, diff --git a/src/libimcv/imv/imv_agent.h b/src/libimcv/imv/imv_agent.h index 0ef784094..5b2cffefe 100644 --- a/src/libimcv/imv/imv_agent.h +++ b/src/libimcv/imv/imv_agent.h @@ -137,14 +137,6 @@ struct imv_agent_t { bool (*get_state)(imv_agent_t *this, TNC_ConnectionID connection_id, 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); - /** * Get IMV name * @@ -179,6 +171,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 */ diff --git a/src/libimcv/imv/imv_state.h b/src/libimcv/imv/imv_state.h index 1b0845b84..2fd5959b4 100644 --- a/src/libimcv/imv/imv_state.h +++ b/src/libimcv/imv/imv_state.h @@ -109,13 +109,14 @@ 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 * @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, + char **reason_string, char **language_code); /** * Destroys an imv_state_t object diff --git a/src/libimcv/plugins/imv_os/imv_os_state.c b/src/libimcv/plugins/imv_os/imv_os_state.c index d4721038d..4981024e5 100644 --- a/src/libimcv/plugins/imv_os/imv_os_state.c +++ b/src/libimcv/plugins/imv_os/imv_os_state.c @@ -191,8 +191,8 @@ METHOD(imv_state_t, set_recommendation, void, } METHOD(imv_state_t, get_reason_string, bool, - private_imv_os_state_t *this, chunk_t preferred_language, - chunk_t *reason_string, chunk_t *reason_language) + private_imv_os_state_t *this, enumerator_t *language_enumerator, + char **reason_string, char **reason_language) { return FALSE; } @@ -265,12 +265,6 @@ METHOD(imv_os_state_t, get_count, void, } } -METHOD(imv_os_state_t, get_type, os_type_t, - private_imv_os_state_t *this) -{ - return this->type; -} - METHOD(imv_os_state_t, set_package_request, void, private_imv_os_state_t *this, bool set) { diff --git a/src/libimcv/plugins/imv_scanner/imv_scanner_state.c b/src/libimcv/plugins/imv_scanner/imv_scanner_state.c index fbb70d73e..362fb6e66 100644 --- a/src/libimcv/plugins/imv_scanner/imv_scanner_state.c +++ b/src/libimcv/plugins/imv_scanner/imv_scanner_state.c @@ -73,7 +73,7 @@ struct private_imv_scanner_state_t { /** * Local copy of the reason string */ - chunk_t reason_string; + char *reason_string; }; typedef struct entry_t entry_t; @@ -91,7 +91,7 @@ struct entry_t { */ static entry_t reasons[] = { { "en", "The following ports are open:" }, - { "de", "Die folgenden Ports sind offen" }, + { "de", "Die folgenden Ports sind offen:" }, { "fr", "Les ports suivants sont ouverts:" }, { "pl", "Następujące porty sa otwarte:" } }; @@ -156,60 +156,43 @@ METHOD(imv_state_t, set_recommendation, void, } METHOD(imv_state_t, get_reason_string, bool, - private_imv_scanner_state_t *this, chunk_t preferred_language, - chunk_t *reason_string, chunk_t *reason_language) + private_imv_scanner_state_t *this, enumerator_t *language_enumerator, + char **reason_string, char **reason_language) { - chunk_t pref_lang, lang; - u_char *pos; + bool match = FALSE; + char *lang; int i; if (!this->violating_ports) { return FALSE; } + /* set the default language */ + *reason_language = reasons[0].lang; + *reason_string = reasons[0].string; - while (eat_whitespace(&preferred_language)) + while (language_enumerator->enumerate(language_enumerator, &lang)) { - if (!extract_token(&pref_lang, ',', &preferred_language)) + for (i = 0; i < countof(reasons); i++) { - /* last entry in a comma-separated list or single entry */ - pref_lang = preferred_language; - } - - /* eat trailing whitespace */ - pos = pref_lang.ptr + pref_lang.len - 1; - while (pref_lang.len && *pos-- == ' ') - { - pref_lang.len--; - } - - for (i = 0 ; i < countof(reasons); i++) - { - lang = chunk_create(reasons[i].lang, strlen(reasons[i].lang)); - if (chunk_equals(lang, pref_lang)) + if (streq(lang, reasons[i].lang)) { - this->reason_string = chunk_cat("cc", - chunk_create(reasons[i].string, - strlen(reasons[i].string)), - chunk_create(this->violating_ports, - strlen(this->violating_ports))); - *reason_string = this->reason_string; - *reason_language = lang; - return TRUE; + match = TRUE; + *reason_language = reasons[i].lang; + *reason_string = reasons[i].string; + break; } } + if (match) + { + break; + } } - - /* no preferred language match found - use the default language */ - - this->reason_string = chunk_cat("cc", - chunk_create(reasons[0].string, - strlen(reasons[0].string)), - chunk_create(this->violating_ports, - strlen(this->violating_ports))); + this->reason_string = malloc(strlen(*reason_string) + + strlen(this->violating_ports + 1)); + sprintf(this->reason_string, "%s%s", *reason_string, this->violating_ports); *reason_string = this->reason_string; - *reason_language = chunk_create(reasons[0].lang, - strlen(reasons[0].lang)); + return TRUE; } @@ -217,7 +200,7 @@ METHOD(imv_state_t, destroy, void, private_imv_scanner_state_t *this) { free(this->violating_ports); - free(this->reason_string.ptr); + free(this->reason_string); free(this); } diff --git a/src/libimcv/plugins/imv_test/imv_test_state.c b/src/libimcv/plugins/imv_test/imv_test_state.c index 1fb6df859..1db6bb513 100644 --- a/src/libimcv/plugins/imv_test/imv_test_state.c +++ b/src/libimcv/plugins/imv_test/imv_test_state.c @@ -163,46 +163,35 @@ METHOD(imv_state_t, set_recommendation, void, } METHOD(imv_state_t, get_reason_string, bool, - private_imv_test_state_t *this, chunk_t preferred_language, - chunk_t *reason_string, chunk_t *reason_language) + private_imv_test_state_t *this, enumerator_t *language_enumerator, + char **reason_string, char **reason_language) { - chunk_t pref_lang, lang; - u_char *pos; + bool match = FALSE; + char *lang; int i; - while (eat_whitespace(&preferred_language)) + /* set the default language */ + *reason_language = reasons[0].lang; + *reason_string = reasons[0].string; + + while (language_enumerator->enumerate(language_enumerator, &lang)) { - if (!extract_token(&pref_lang, ',', &preferred_language)) - { - /* last entry in a comma-separated list or single entry */ - pref_lang = preferred_language; - } - - /* eat trailing whitespace */ - pos = pref_lang.ptr + pref_lang.len - 1; - while (pref_lang.len && *pos-- == ' ') - { - pref_lang.len--; - } - for (i = 0 ; i < countof(reasons); i++) { - lang = chunk_create(reasons[i].lang, strlen(reasons[i].lang)); - if (chunk_equals(lang, pref_lang)) + if (streq(lang, reasons[i].lang)) { - *reason_language = lang; - *reason_string = chunk_create(reasons[i].string, - strlen(reasons[i].string)); - return TRUE; + match = TRUE; + *reason_language = reasons[i].lang; + *reason_string = reasons[i].string; + break; } } + if (match) + { + break; + } } - /* no preferred language match found - use the default language */ - *reason_string = chunk_create(reasons[0].string, - strlen(reasons[0].string)); - *reason_language = chunk_create(reasons[0].lang, - strlen(reasons[0].lang)); return TRUE; } diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_state.c b/src/libpts/plugins/imv_attestation/imv_attestation_state.c index 1c40f3ffa..c1d83511d 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation_state.c +++ b/src/libpts/plugins/imv_attestation/imv_attestation_state.c @@ -210,46 +210,35 @@ METHOD(imv_state_t, set_recommendation, void, } METHOD(imv_state_t, get_reason_string, bool, - private_imv_attestation_state_t *this, chunk_t preferred_language, - chunk_t *reason_string, chunk_t *reason_language) + private_imv_attestation_state_t *this, enumerator_t *language_enumerator, + char **reason_string, char **reason_language) { - chunk_t pref_lang, lang; - u_char *pos; + bool match = FALSE; + char *lang; int i; - while (eat_whitespace(&preferred_language)) + /* set the default language */ + *reason_language = reasons[0].lang; + *reason_string = reasons[0].string; + + while (language_enumerator->enumerate(language_enumerator, &lang)) { - if (!extract_token(&pref_lang, ',', &preferred_language)) - { - /* last entry in a comma-separated list or single entry */ - pref_lang = preferred_language; - } - - /* eat trailing whitespace */ - pos = pref_lang.ptr + pref_lang.len - 1; - while (pref_lang.len && *pos-- == ' ') - { - pref_lang.len--; - } - for (i = 0 ; i < countof(reasons); i++) { - lang = chunk_create(reasons[i].lang, strlen(reasons[i].lang)); - if (chunk_equals(lang, pref_lang)) + if (streq(lang, reasons[i].lang)) { - *reason_language = lang; - *reason_string = chunk_create(reasons[i].string, - strlen(reasons[i].string)); - return TRUE; + match = TRUE; + *reason_language = reasons[i].lang; + *reason_string = reasons[i].string; + break; } } + if (match) + { + break; + } } - /* no preferred language match found - use the default language */ - *reason_string = chunk_create(reasons[0].string, - strlen(reasons[0].string)); - *reason_language = chunk_create(reasons[0].lang, - strlen(reasons[0].lang)); return TRUE; }