implement a preferred language enumerator
This commit is contained in:
+143
-45
@@ -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,
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user