implement a preferred language enumerator
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 10 Nov 2012 20:35:46 +0000 (21:35 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 10 Nov 2012 20:35:46 +0000 (21:35 +0100)
src/libimcv/imv/imv_agent.c
src/libimcv/imv/imv_agent.h
src/libimcv/imv/imv_state.h
src/libimcv/plugins/imv_os/imv_os_state.c
src/libimcv/plugins/imv_scanner/imv_scanner_state.c
src/libimcv/plugins/imv_test/imv_test_state.c
src/libpts/plugins/imv_attestation/imv_attestation_state.c

index d664dc9..2a67875 100644 (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,
index 0ef7840..5b2cffe 100644 (file)
@@ -138,14 +138,6 @@ struct imv_agent_t {
                                          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
         *
         * return                                       IMV name
@@ -180,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);
index 1b0845b..2fd5959 100644 (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
index d472103..4981024 100644 (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)
 {
index fbb70d7..362fb6e 100644 (file)
@@ -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))
-               {
-                       /* 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++)
+               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);
 }
 
index 1fb6df8..1db6bb5 100644 (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))
-       {
-               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--;
-               }
+       /* set the default language */
+       *reason_language = reasons[0].lang;
+       *reason_string   = reasons[0].string;
 
+       while (language_enumerator->enumerate(language_enumerator, &lang))
+       {
                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;
 }
 
index 1c40f3f..c1d8351 100644 (file)
@@ -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))
-       {
-               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--;
-               }
+       /* set the default language */
+       *reason_language = reasons[0].lang;
+       *reason_string   = reasons[0].string;
 
+       while (language_enumerator->enumerate(language_enumerator, &lang))
+       {
                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;
 }