implement a preferred language enumerator

This commit is contained in:
Andreas Steffen
2012-11-10 21:35:46 +01:00
parent 4ccc4fd97c
commit db15c6dac1
7 changed files with 226 additions and 164 deletions
+143 -45
View File
@@ -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,
+16 -8
View File
@@ -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
*/
+4 -3
View File
@@ -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
+2 -8
View File
@@ -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)
{
@@ -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);
}
+18 -29
View File
@@ -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;
}
@@ -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;
}