refactored reason string and remediation instructions framework
authorAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 23 Nov 2012 11:30:09 +0000 (12:30 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 23 Nov 2012 11:30:33 +0000 (12:30 +0100)
15 files changed:
src/libimcv/Makefile.am
src/libimcv/imc/imc_msg.c
src/libimcv/imv/imv_agent.c
src/libimcv/imv/imv_lang_string.c [new file with mode: 0644]
src/libimcv/imv/imv_lang_string.h [new file with mode: 0644]
src/libimcv/imv/imv_msg.c
src/libimcv/imv/imv_reason_string.c [new file with mode: 0644]
src/libimcv/imv/imv_reason_string.h [new file with mode: 0644]
src/libimcv/imv/imv_remediation_string.c [new file with mode: 0644]
src/libimcv/imv/imv_remediation_string.h [new file with mode: 0644]
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 39b6b1d..51a7be0 100644 (file)
@@ -11,6 +11,9 @@ libimcv_la_SOURCES = \
        imc/imc_msg.h imc/imc_msg.c \
        imv/imv_agent.h imv/imv_agent.c imv/imv_state.h \
        imv/imv_msg.h imv/imv_msg.c \
+       imv/imv_lang_string.h imv/imv_lang_string.c \
+       imv/imv_reason_string.h imv/imv_reason_string.c \
+       imv/imv_remediation_string.h imv/imv_remediation_string.c \
        ietf/ietf_attr.h ietf/ietf_attr.c \
        ietf/ietf_attr_assess_result.h ietf/ietf_attr_assess_result.c \
        ietf/ietf_attr_attr_request.h ietf/ietf_attr_attr_request.c \
index 788408c..e6b19f5 100644 (file)
@@ -309,22 +309,22 @@ METHOD(imc_msg_t, receive, TNC_Result,
                                switch (parameters_type.type)
                                {
                                        case IETF_REMEDIATION_PARAMETERS_URI:
-                                               DBG1(DBG_IMC, "remediation uri: '%.*s'",
+                                               DBG1(DBG_IMC, "remediation uri: %.*s",
                                                                           parameters.len, parameters.ptr);
                                                break;
                                        case IETF_REMEDIATION_PARAMETERS_STRING:
                                                string = attr_cast->get_string(attr_cast, &lang_code);
-                                               DBG1(DBG_IMC, "remediation string: '%.*s' [%.*s]",
-                                                                          string.len, string.ptr,
-                                                                          lang_code.len, lang_code.ptr);
+                                               DBG1(DBG_IMC, "remediation string: [%.*s]\n%.*s",
+                                                                          lang_code.len, lang_code.ptr,
+                                                                          string.len, string.ptr);
                                                break;
                                        default:
-                                               DBG1(DBG_IMC, "remediation parameters %B", &parameters);
+                                               DBG1(DBG_IMC, "remediation parameters: %B", &parameters);
                                }
                        }
                        else
                        {
-                               DBG1(DBG_IMC, "remediation parameters %B", &parameters);
+                               DBG1(DBG_IMC, "remediation parameters: %B", &parameters);
                        }
                }
        }
index 65438fc..6a33e39 100644 (file)
@@ -642,7 +642,8 @@ METHOD(imv_agent_t, provide_recommendation, TNC_Result,
        TNC_IMV_Action_Recommendation rec;
        TNC_IMV_Evaluation_Result eval;
        TNC_ConnectionID connection_id;
-       char *reason_string, *reason_lang;
+       chunk_t reason_string;
+       char *reason_lang;
        enumerator_t *e;
 
        state->get_recommendation(state, &rec, &eval);
@@ -659,7 +660,7 @@ METHOD(imv_agent_t, provide_recommendation, TNC_Result,
                        {
                                this->set_attribute(this->id, connection_id,
                                                                        TNC_ATTRIBUTEID_REASON_STRING,
-                                                                       strlen(reason_string), reason_string);
+                                                                       reason_string.len, reason_string.ptr);
                                this->set_attribute(this->id, connection_id,
                                                                        TNC_ATTRIBUTEID_REASON_LANGUAGE,
                                                                        strlen(reason_lang), reason_lang);
diff --git a/src/libimcv/imv/imv_lang_string.c b/src/libimcv/imv/imv_lang_string.c
new file mode 100644 (file)
index 0000000..c86fc5c
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "imv_lang_string.h"
+
+#include <utils/debug.h>
+
+/**
+ * Described in header.
+ */
+char* imv_lang_string_select_lang(enumerator_t *language_enumerator,
+                                                                 char* languages[], int lang_count)
+{
+       bool match = FALSE;
+       char *lang;
+       int i, i_chosen = 0;
+
+       while (language_enumerator->enumerate(language_enumerator, &lang))
+       {
+               for (i = 0; i < lang_count; i++)
+               {
+                       if (streq(lang, languages[i]))
+                       {
+                               match = TRUE;
+                               i_chosen = i;
+                               break;
+                       }
+               }
+               if (match)
+               {
+                       break;
+               }
+       }
+       return languages[i_chosen];
+}
+
+/**
+ * Described in header.
+ */
+char* imv_lang_string_select_string(imv_lang_string_t lang_string[], char *lang)
+{
+       char *string;
+       int i = 0;
+
+       if (!lang_string)
+       {
+               return NULL;
+       }
+
+       string = lang_string[0].string;
+       while (lang_string[i].lang)
+       {
+               if (streq(lang, lang_string[i].lang))
+               {
+                       string = lang_string[i].string;
+                       break;
+               }
+               i++;
+       }
+       return string;
+}
diff --git a/src/libimcv/imv/imv_lang_string.h b/src/libimcv/imv/imv_lang_string.h
new file mode 100644 (file)
index 0000000..90a66db
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ *
+ * @defgroup imv_lang_string_t imv_lang_string
+ * @{ @ingroup imv_lang_string
+ */
+
+#ifndef IMV_LANG_STRING_H_
+#define IMV_LANG_STRING_H_
+
+#include <library.h>
+#include <collections/enumerator.h>
+
+typedef struct imv_lang_string_t imv_lang_string_t;
+
+/**
+ * Define a language string entry
+ */
+struct imv_lang_string_t {
+
+       /**
+        * language code
+        */
+       char *lang;
+
+       /**
+        * UTF-8 string in the corresponding language
+        */
+       char *string;
+
+};
+
+/**
+ * Select the preferred language
+ *
+ * @param language_enumerator  enumerator over user preferred languages
+ * @param languages                            string array of available languages
+ * @param lang_count                   number of available languages
+ * @return                                             selected language as a language code
+ */
+char* imv_lang_string_select_lang(enumerator_t *language_enumerator,
+                                                                 char* languages[], int lang_count);
+
+/**
+ * Select the preferred language string
+ *
+ * @param lang_string                  multi-lingual array of strings
+ * @param lang                                 language code of preferred language
+ * @return                                             selected string
+ */
+char* imv_lang_string_select_string(imv_lang_string_t lang_string[], char *lang);
+
+#endif /** IMV_LANG_STRING_H_ @}*/
index b628c32..5636c9b 100644 (file)
@@ -191,7 +191,8 @@ METHOD(imv_msg_t, send_assessment, TNC_Result,
        TNC_IMV_Action_Recommendation rec;
        TNC_IMV_Evaluation_Result eval;
        pa_tnc_attr_t *attr;
-       char *string = NULL, *lang_code = NULL, *uri = NULL;
+       chunk_t string = chunk_empty;
+       char *lang_code = NULL, *uri = NULL;
        enumerator_t *e;
 
        /* Send an IETF Assessment Result attribute if enabled */
@@ -210,10 +211,9 @@ METHOD(imv_msg_t, send_assessment, TNC_Result,
                        if (this->state->get_remediation_instructions(this->state,
                                                                        e, &string, &lang_code, &uri))
                        {
-                               if (string && lang_code)
+                               if (string.len && lang_code)
                                {
-                                       attr = ietf_attr_remediation_instr_create_from_string(
-                                                                       chunk_create(string, strlen(string)),
+                                       attr = ietf_attr_remediation_instr_create_from_string(string,
                                                                        chunk_create(lang_code, strlen(lang_code)));
                                        add_attribute(this, attr);
                                }
diff --git a/src/libimcv/imv/imv_reason_string.c b/src/libimcv/imv/imv_reason_string.c
new file mode 100644 (file)
index 0000000..18eade0
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "imv_reason_string.h"
+
+#include <utils/debug.h>
+
+typedef struct private_imv_reason_string_t private_imv_reason_string_t;
+
+/**
+ * Private data of an imv_reason_string_t object.
+ */
+struct private_imv_reason_string_t {
+
+       /**
+        * Public members of imv_reason_string_t
+        */
+       imv_reason_string_t public;
+
+       /**
+        * Preferred language
+        */
+       char *lang;
+
+       /**
+        * Contains the concatenated reasons
+        */
+       chunk_t reasons;
+
+};
+
+METHOD(imv_reason_string_t, add_reason, void,
+       private_imv_reason_string_t *this, imv_lang_string_t reason[])
+{
+       char *s_reason;
+
+       s_reason = imv_lang_string_select_string(reason, this->lang);
+
+       if (this->reasons.len)
+       {
+               /* append any further reasons */
+               this->reasons = chunk_cat("cm", this->reasons, chunk_from_chars('\n'),
+                                                                 chunk_create(s_reason, strlen(s_reason)));
+       }
+       else
+       {
+               /* add the first reason */
+               this->reasons = chunk_clone(chunk_create(s_reason, strlen(s_reason)));
+       }
+}
+
+METHOD(imv_reason_string_t, get_encoding, chunk_t,
+       private_imv_reason_string_t *this)
+{
+       return this->reasons;
+}
+
+METHOD(imv_reason_string_t, destroy, void,
+       private_imv_reason_string_t *this)
+{
+       free(this->reasons.ptr);
+       free(this);
+}
+
+/**
+ * Described in header.
+ */
+imv_reason_string_t *imv_reason_string_create(char *lang)
+{
+       private_imv_reason_string_t *this;
+
+       INIT(this,
+               .public = {
+                       .add_reason = _add_reason,
+                       .get_encoding = _get_encoding,
+                       .destroy = _destroy,
+               },
+               .lang = lang,
+       );
+
+       return &this->public;
+}
+
diff --git a/src/libimcv/imv/imv_reason_string.h b/src/libimcv/imv/imv_reason_string.h
new file mode 100644 (file)
index 0000000..320b247
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ *
+ * @defgroup imv_reason_string_t imv_reason_string
+ * @{ @ingroup imv_reason_string
+ */
+
+#ifndef IMV_REASON_STRING_H_
+#define IMV_REASON_STRING_H_
+
+#include "imv_lang_string.h"
+
+#include <library.h>
+#include <collections/linked_list.h>
+
+typedef struct imv_reason_string_t imv_reason_string_t;
+
+/**
+ * Defines and builds a TNC Reason String
+ */
+struct imv_reason_string_t {
+
+       /**
+        * Add an individual remediation instruction to the string
+        *
+        * @param reason                Multi-lingual reason string
+        */
+        void (*add_reason)(imv_reason_string_t *this, imv_lang_string_t reason[]);
+
+       /**
+        * Gets  encoding of the reason string
+        *
+        * @return                              TNC reason string
+        */
+       chunk_t (*get_encoding)(imv_reason_string_t *this);
+
+       /**
+        * Destroys an imv_reason_string_t object
+        */
+       void (*destroy)(imv_reason_string_t *this);
+};
+
+/**
+ * Creates an Reason String object
+ *
+ * @param lang                         Preferred language
+ */
+ imv_reason_string_t* imv_reason_string_create(char *lang);
+
+#endif /** IMV_REASON_STRING_H_ @}*/
diff --git a/src/libimcv/imv/imv_remediation_string.c b/src/libimcv/imv/imv_remediation_string.c
new file mode 100644 (file)
index 0000000..75af831
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "imv_remediation_string.h"
+
+#include <utils/debug.h>
+
+typedef struct private_imv_remediation_string_t private_imv_remediation_string_t;
+
+/**
+ * Private data of an imv_remediation_string_t object.
+ */
+struct private_imv_remediation_string_t {
+
+       /**
+        * Public members of imv_remediation_string_t
+        */
+       imv_remediation_string_t public;
+
+       /**
+        * XML or plaintext encoding
+        */
+       bool as_xml;
+
+       /**
+        * Preferred language
+        */
+       char *lang;
+
+       /**
+        * Contains the concatenated remediation instructions
+        */
+       chunk_t instructions;
+
+};
+
+METHOD(imv_remediation_string_t, add_instruction, void,
+       private_imv_remediation_string_t *this, imv_lang_string_t title[],
+       imv_lang_string_t description[], imv_lang_string_t itemsheader[],
+       linked_list_t *items)
+{
+       char xml_format[] = "  <instruction>\n"
+                                               "    <title>%s</title>\n"
+                                               "    <description>%s</description>\n"
+                                               "%s%s"
+                                               "  </instruction>\n";
+       char *instruction, *format, *s_title, *s_description, *s_itemsheader;
+       size_t len;
+
+       s_title = imv_lang_string_select_string(title, this->lang);
+       s_description = imv_lang_string_select_string(description, this->lang);
+       s_itemsheader = imv_lang_string_select_string(itemsheader, this->lang);
+       len = strlen(s_title) + strlen(s_description);
+
+       if (this->as_xml)
+       {
+               format = xml_format;
+               len += strlen(xml_format) - 8;
+       }
+       else
+       {
+               format = this->instructions.len ? "\n%s\n%s%s%s" : "%s\n%s%s%s";
+               len += 2;
+       }
+       instruction = malloc(len + 1);
+       sprintf(instruction, format, s_title, s_description, "", "");
+       this->instructions = chunk_cat("mm", this->instructions, 
+                                                       chunk_create(instruction, strlen(instruction)));
+}
+
+METHOD(imv_remediation_string_t, get_encoding, chunk_t,
+       private_imv_remediation_string_t *this)
+{
+       char xml_header[]  = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+                                                "<remediationinstructions>\n";
+       char xml_trailer[] = "</remediationinstructions>";
+
+       if (!this->instructions.len)
+       {
+               return chunk_empty;
+       }
+       if (this->as_xml)
+       {
+               this->instructions = chunk_cat("cmc",
+                                                               chunk_create(xml_header, strlen(xml_header)),
+                                                               this->instructions,
+                                                               chunk_create(xml_trailer, strlen(xml_trailer))
+                                                        );
+       }
+       return this->instructions;
+}
+
+METHOD(imv_remediation_string_t, destroy, void,
+       private_imv_remediation_string_t *this)
+{
+       free(this->instructions.ptr);
+       free(this);
+}
+
+/**
+ * Described in header.
+ */
+imv_remediation_string_t *imv_remediation_string_create(bool as_xml, char *lang)
+{
+       private_imv_remediation_string_t *this;
+
+       INIT(this,
+               .public = {
+                       .add_instruction = _add_instruction,
+                       .get_encoding = _get_encoding,
+                       .destroy = _destroy,
+               },
+               .as_xml = as_xml,
+               .lang = lang,
+       );
+
+       return &this->public;
+}
+
diff --git a/src/libimcv/imv/imv_remediation_string.h b/src/libimcv/imv/imv_remediation_string.h
new file mode 100644 (file)
index 0000000..9249c2a
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ *
+ * @defgroup imv_remediation_string_t imv_remediation_string
+ * @{ @ingroup imv_remediation_string
+ */
+
+#ifndef IMV_REMEDIATION_STRING_H_
+#define IMV_REMEDIATION_STRING_H_
+
+#include "imv_lang_string.h"
+
+#include <library.h>
+#include <collections/linked_list.h>
+
+typedef struct imv_remediation_string_t imv_remediation_string_t;
+
+/**
+ * Defines and builds an IETF Remediation Instructions String
+ */
+struct imv_remediation_string_t {
+
+       /**
+        * Add an individual remediation instruction to the string
+        *
+        * @param title                 instruction title
+        * @param description   instruction description
+        * @param itemsheader   optional items header or NULL
+        * @param items                 optional items list or NULL
+        */
+        void (*add_instruction)(imv_remediation_string_t *this,
+                                                        imv_lang_string_t title[],
+                                                        imv_lang_string_t description[],
+                                                        imv_lang_string_t itemsheader[],
+                                                        linked_list_t *items);
+
+       /**
+        * Gets the plaintext or XML encoding of the remediation instructions
+        *
+        * @return                              remediation instructions string
+        */
+       chunk_t (*get_encoding)(imv_remediation_string_t *this);
+
+       /**
+        * Destroys an imv_remediation_string_t object
+        */
+       void (*destroy)(imv_remediation_string_t *this);
+};
+
+/**
+ * Creates an IETF Remediation Instructions String object
+ *
+ * @param as_xml                       XML encoding if TRUE, plaintext otherwise
+ * @param lang                         Preferred language
+ */
+ imv_remediation_string_t* imv_remediation_string_create(bool as_xml, char *lang);
+
+#endif /** IMV_REMEDIATION_STRING_H_ @}*/
index 6b9bbe7..f40402e 100644 (file)
@@ -116,7 +116,7 @@ struct imv_state_t {
         */
        bool (*get_reason_string)(imv_state_t *this,
                                                          enumerator_t *language_enumerator,
-                                                         char **reason_string, char **reason_language);
+                                                         chunk_t *reason_string, char **reason_language);
 
        /**
         * Get remediation instructions based on the preferred language
@@ -129,7 +129,7 @@ struct imv_state_t {
         */
        bool (*get_remediation_instructions)(imv_state_t *this,
                                                                                 enumerator_t *language_enumerator,
-                                                                                char **string, char **lang_code,
+                                                                                chunk_t *string, char **lang_code,
                                                                                 char **uri);
 
        /**
index 470acc5..3b5dac6 100644 (file)
@@ -14,6 +14,9 @@
  */
 
 #include "imv_os_state.h"
+#include "imv/imv_lang_string.h"
+#include "imv/imv_reason_string.h"
+#include "imv/imv_remediation_string.h"
 
 #include <utils/debug.h>
 #include <collections/linked_list.h>
@@ -89,19 +92,24 @@ struct private_imv_os_state_t {
        chunk_t version;
 
        /**
-        * List of vulnerable or blacklisted packages
+        * List of blacklisted packages to be removed
         */
-       linked_list_t *bad_packages;
+       linked_list_t *remove_packages;
 
        /**
-        * Local copy of the reason string
+        * List of vulnerable packages to be updated
         */
-       char *reasons;
+       linked_list_t *update_packages;
 
        /**
-        * Local copy of the remediation instruction string
+        * TNC Reason String
         */
-       char *instructions;
+       imv_reason_string_t *reason_string;
+
+       /**
+        * IETF Remediation Instructions String
+        */
+       imv_remediation_string_t *remediation_string;
 
        /**
         * Number of processed packages
@@ -141,89 +149,120 @@ struct private_imv_os_state_t {
 };
 
 /**
- * Store a bad package entry
+ * Supported languages
+ */
+static char* languages[] = { "en", "de", "pl" };
+
+/**
+ * Table of "OS settings" reason strings
  */
-struct package_entry_t {
-       char *name;
-       os_package_state_t state;
+static imv_lang_string_t reason_settings[] = {
+       { "en", "Improper OS settings were detected" },
+       { "de", "Unzulässige OS Einstellungen wurden festgestellt" },
+       { NULL, NULL }
 };
 
 /**
- * Free a bad package entry
+ * Table of "software packages" reason strings
  */
-static void free_package_entry(package_entry_t *this)
-{
-       free(this->name);
-       free(this);
-}
+static imv_lang_string_t reason_packages[] = {
+       { "en", "Vulnerable or blacklisted software packages were found" },
+       { "de", "Schwachstellenbehaftete oder gesperrte Softwarepakete wurden gefunden" },
+       { NULL, NULL }
+};
 
 /**
- * Define a language string entry
+ * Table of "software packages update" instruction title strings
  */
-struct entry_t {
-       char *lang;
-       char *string;
+static imv_lang_string_t instr_update_packages_title[] = {
+       { "en", "Software Security Updates" },
+       { "de", "Software Sicherheitsupdates" },
+       { "pl", "Software Security Updates" }, /* TODO */
+       { NULL, NULL }
 };
 
 /**
- * Table of multi-lingual improper settings reason string entries
+ * Table of "software packages update" instruction description strings
  */
-static entry_t settings_reasons[] = {
-       { "en", "Improper OS settings were detected" },
-       { "de", "Unzulässige OS Einstellungen wurden festgestellt" }
+static imv_lang_string_t instr_update_packages_descr[] = {
+       { "en", "Please update the following software packages" },
+       { "de", "Bitte updaten Sie die folgenden Softwarepakete" },
+       { "pl", "Proszę zaktualizować następujące pakiety" },
+       { NULL, NULL }
 };
 
 /**
- * Table of multi-lingual reason string entries
+ * Tables of "software package removal" instruction titlestrings
  */
-static entry_t reasons[] = {
-       { "en", "Vulnerable or blacklisted software packages were found" },
-       { "de", "Schwachstellenbehaftete oder gesperrte Softwarepakete wurden gefunden" }
+static imv_lang_string_t instr_remove_packages_title[] = {
+       { "en", "Blacklisted Software Packages" },
+       { "de", "Gesperrte Softwarepakete" },
+       { "pl", "Blacklisted Software Packages" }, /* TODO */
+       { NULL, NULL }
 };
 
 /**
- * Table of multi-lingual forwarding enable string entries
+ * Tables of "software package removal" instruction strings
  */
-static entry_t instruction_fwd_enabled[] = {
-       { "en", "Please disable IP forwarding" },
-       { "de", "Bitte deaktivieren Sie das IP Forwarding" }
+static imv_lang_string_t instr_remove_packages_descr[] = {
+       { "en", "Please remove the following software packages" },
+       { "de", "Bitte entfernen Sie die folgenden Softwarepakete" },
+       { "pl", "Proszę usunąć następujące pakiety" },
+       { NULL, NULL }
+}
+
+;/**
+ * Table of "forwarding enable" instruction title strings
+ */
+static imv_lang_string_t instr_fwd_enabled_title[] = {
+       { "en", "IP Packet Forwarding" },
+       { "de", "Weiterleitung von IP Paketen" },
+       { NULL, NULL }
 };
 
 /**
- * Table of multi-lingual default password enabled string entries
+ * Table of "forwarding enable" instruction description strings
  */
-static entry_t instruction_default_pwd_enabled[] = {
-       { "en", "Please change the default password" },
-       { "de", "Bitte ändern Sie das default Passwort" }
+static imv_lang_string_t instr_fwd_enabled_descr[] = {
+       { "en", "Please disable the forwarding of IP packets" },
+       { "de", "Bitte deaktivieren Sie das Forwarding von IP Paketen" },
+       { NULL, NULL }
 };
 
 /**
- * Table of multi-lingual defaul install non market apps string entries
+ * Table of "default password enabled" instruction title strings
  */
-static entry_t instruction_non_market_apps[] = {
-       { "en", "Do not allow the installation of apps from unknown sources" },
-       { "de", "Erlauben Sie nicht die Installation von Apps von unbekannten Quellen" }
+static imv_lang_string_t instr_default_pwd_enabled_title[] = {
+       { "en", "Default Password" },
+       { "de", "Default Passwort" },
+       { NULL, NULL }
 };
 
 /**
- * Define a remediation instruction string entry
+ * Table of "default password enabled" instruction description strings
  */
-struct instruction_entry_t {
-       char *lang;
-       char *update_string;
-       char *removal_string;
+static imv_lang_string_t instr_default_pwd_enabled_descr[] = {
+       { "en", "Please change the default password" },
+       { "de", "Bitte ändern Sie das Default Passwort" },
+       { NULL, NULL }
 };
 
 /**
- * Tables of multi-lingual remediation instruction string entries
+ * Table of "install non market apps" instruction title strings
  */
-static instruction_entry_t instructions [] = {
-       { "en", "Please update the following software packages:\n",
-                       "Please remove the following software packages:\n" },
-       { "de", "Bitte updaten Sie die folgenden Softwarepakete\n",
-                       "Bitte entfernen Sie die folgenden Softwarepakete\n" },
-       { "pl", "Proszę zaktualizować następujące pakiety:\n",
-                       "Proszę usunąć następujące pakiety:\n" }
+static imv_lang_string_t instr_non_market_apps_title[] = {
+       { "en", "Unknown Software Origin" },
+       { "de", "Unbekannte Softwareherkunft" },
+       { NULL, NULL }
+};
+
+/**
+ * Table of "install non market apps" instruction description strings
+ */
+static imv_lang_string_t instr_non_market_apps_descr[] = {
+       { "en", "Do not allow the installation of apps from unknown sources" },
+       { "de", "Erlauben Sie nicht die Installation von Apps von unbekannten Quellen" },
+       { NULL, NULL }
 };
 
 METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
@@ -287,204 +326,89 @@ METHOD(imv_state_t, set_recommendation, void,
 
 METHOD(imv_state_t, get_reason_string, bool,
        private_imv_os_state_t *this, enumerator_t *language_enumerator,
-       char **reason_string, char **reason_language)
+       chunk_t *reason_string, char **reason_language)
 {
-       bool match = FALSE;
-       char *lang, *pos;
-       int i, i_chosen = 0, len = 0, nr_of_reasons = 0;
-
        if (!this->count_update && !this->count_blacklist & !this->os_settings)
        {
                return FALSE;
        }
+       *reason_language = imv_lang_string_select_lang(language_enumerator,
+                                                                                         languages, countof(languages));
 
-       while (language_enumerator->enumerate(language_enumerator, &lang))
-       {
-               for (i = 0; i < countof(reasons); i++)
-               {
-                       if (streq(lang, reasons[i].lang))
-                       {
-                               match = TRUE;
-                               i_chosen = i;
-                               break;
-                       }
-               }
-               if (match)
-               {
-                       break;
-               }
-       }
-       *reason_language = reasons[i_chosen].lang;
-
-       if (this->count_update ||  this->count_blacklist)
-       {
-               len += strlen(reasons[i_chosen].string);
-               nr_of_reasons++;
-       }
-       if (this->os_settings)
-       {
-               len += strlen(settings_reasons[i_chosen].string);
-               nr_of_reasons++;
-       }
-
-       /* Allocate memory for the reason string */
-       pos = this->reasons = malloc(len + nr_of_reasons);
+       /* Instantiate a TNC Reason String object */
+       DESTROY_IF(this->reason_string);
+       this->reason_string = imv_reason_string_create(*reason_language);
 
-       if (this->count_update ||  this->count_blacklist)
+       if (this->count_update || this->count_blacklist)
        {
-               strcpy(pos, reasons[i_chosen].string);
-               pos += strlen(reasons[i_chosen].string);
-               if (--nr_of_reasons)
-               {
-                       *pos++ = '\n';
-               }
+               this->reason_string->add_reason(this->reason_string, reason_packages);
        }
        if (this->os_settings)
        {
-               strcpy(pos, settings_reasons[i_chosen].string);
-               pos += strlen(settings_reasons[i_chosen].string);
+               this->reason_string->add_reason(this->reason_string, reason_settings);
        }
-       *pos = '\0';
-       *reason_string = this->reasons;
+       *reason_string = this->reason_string->get_encoding(this->reason_string);
 
        return TRUE;
 }
 
 METHOD(imv_state_t, get_remediation_instructions, bool,
        private_imv_os_state_t *this, enumerator_t *language_enumerator,
-       char **string, char **lang_code, char **uri)
+       chunk_t *string, char **lang_code, char **uri)
 {
-       bool match = FALSE;
-       char *lang, *pos;
-       enumerator_t *enumerator;
-       package_entry_t *entry;
-       int i, i_chosen = 0, len = 0, nr_of_instructions = 0;
-
        if (!this->count_update && !this->count_blacklist & !this->os_settings)
        {
                return FALSE;
        }
+       *lang_code = imv_lang_string_select_lang(language_enumerator,
+                                                                               languages, countof(languages));
 
-       while (language_enumerator->enumerate(language_enumerator, &lang))
-       {
-               for (i = 0; i < countof(instructions); i++)
-               {
-                       if (streq(lang, instructions[i].lang))
-                       {
-                               match = TRUE;
-                               i_chosen = i;
-                               break;
-                       }
-               }
-               if (match)
-               {
-                       break;
-               }
-       }
-       *lang_code = instructions[i_chosen].lang;
+       /* Instantiate an IETF Remediation Instructions String object */
+       DESTROY_IF(this->remediation_string);
+       this->remediation_string = imv_remediation_string_create(
+                                                                       this->type == OS_TYPE_ANDROID, *lang_code);
 
-       /* Compute the size of the remediation string */
-       if (this->count_update)
-       {
-               len += strlen(instructions[i_chosen].update_string);
-       }
+       /* List of blacklisted packages to be removed, if any */
        if (this->count_blacklist)
        {
-               len += strlen(instructions[i_chosen].removal_string);
-       }
-       if (this->os_settings & OS_SETTINGS_FWD_ENABLED)
-       {
-               len += strlen(instruction_fwd_enabled[i_chosen].string);
-               nr_of_instructions++;
-       }
-       if (this->os_settings & OS_SETTINGS_DEFAULT_PWD_ENABLED)
-       {
-               len += strlen(instruction_default_pwd_enabled[i_chosen].string);
-               nr_of_instructions++;
-       }
-       if (this->os_settings & OS_SETTINGS_NON_MARKET_APPS)
-       {
-               len += strlen(instruction_non_market_apps[i_chosen].string);
-               nr_of_instructions++;
-       }
-
-       enumerator = this->bad_packages->create_enumerator(this->bad_packages);
-       while (enumerator->enumerate(enumerator, &entry))
-       {
-               len += strlen(entry->name) + 1;
-       }
-       enumerator->destroy(enumerator);
-
-       /* Allocate memory for the remediation instructions */
-       pos = this->instructions = malloc(len + nr_of_instructions + 1);
-
-       /* List of blacklisted packages, if any */
-       if (this->count_blacklist)
-       {
-               strcpy(pos, instructions[i_chosen].removal_string);
-               pos += strlen(instructions[i_chosen].removal_string);
-
-               enumerator = this->bad_packages->create_enumerator(this->bad_packages);
-               while (enumerator->enumerate(enumerator, &entry))
-               {
-                       if (entry->state == OS_PACKAGE_STATE_BLACKLIST)
-                       {
-                               strcpy(pos, entry->name);
-                               pos += strlen(entry->name);
-                               *pos++ = '\n';
-                       }
-               }
-               enumerator->destroy(enumerator);
+               this->remediation_string->add_instruction(this->remediation_string,
+                                               instr_remove_packages_title,
+                                               instr_remove_packages_descr, NULL,
+                                               this->remove_packages);
        }
 
        /* List of packages in need of an update, if any */
        if (this->count_update)
        {
-               strcpy(pos, instructions[i_chosen].update_string);
-               pos += strlen(instructions[i_chosen].update_string);
-
-               enumerator = this->bad_packages->create_enumerator(this->bad_packages);
-               while (enumerator->enumerate(enumerator, &entry))
-               {
-                       if (entry->state != OS_PACKAGE_STATE_BLACKLIST)
-                       {
-                               strcpy(pos, entry->name);
-                               pos += strlen(entry->name);
-                               *pos++ = '\n';
-                       }
-               }
-               enumerator->destroy(enumerator);
+               this->remediation_string->add_instruction(this->remediation_string,
+                                               instr_update_packages_title,
+                                               instr_update_packages_descr, NULL,
+                                               this->update_packages);
        }
 
        /* Add instructions concerning improper OS settings */
        if (this->os_settings & OS_SETTINGS_FWD_ENABLED)
        {
-               strcpy(pos, instruction_fwd_enabled[i_chosen].string);
-               pos += strlen(instruction_fwd_enabled[i_chosen].string);
-               if (--nr_of_instructions)
-               {
-                       *pos++ = '\n';
-               }
+               this->remediation_string->add_instruction(this->remediation_string,
+                                               instr_fwd_enabled_title,
+                                               instr_fwd_enabled_descr, NULL, NULL);
        }
        if (this->os_settings & OS_SETTINGS_DEFAULT_PWD_ENABLED)
        {
-               strcpy(pos, instruction_default_pwd_enabled[i_chosen].string);
-               pos += strlen(instruction_default_pwd_enabled[i_chosen].string);
-               if (--nr_of_instructions)
-               {
-                       *pos++ = '\n';
-               }
+               this->remediation_string->add_instruction(this->remediation_string,
+                                               instr_default_pwd_enabled_title,
+                                               instr_default_pwd_enabled_descr, NULL, NULL);
        }
        if (this->os_settings & OS_SETTINGS_NON_MARKET_APPS)
        {
-               strcpy(pos, instruction_non_market_apps[i_chosen].string);
-               pos += strlen(instruction_non_market_apps[i_chosen].string);
+               this->remediation_string->add_instruction(this->remediation_string,
+                                               instr_non_market_apps_title,
+                                               instr_non_market_apps_descr, NULL, NULL);
        }
 
-       *pos = '\0';
-       *string = this->instructions;
+       *string = this->remediation_string->get_encoding(this->remediation_string);
        *uri = lib->settings->get_str(lib->settings,
-                               "libimcv.plugins.imv-os.remediation_uri", NULL);
+                                               "libimcv.plugins.imv-os.remediation_uri", NULL);
 
        return TRUE;
 }
@@ -492,10 +416,10 @@ METHOD(imv_state_t, get_remediation_instructions, bool,
 METHOD(imv_state_t, destroy, void,
        private_imv_os_state_t *this)
 {
-       this->bad_packages->destroy_function(this->bad_packages,
-                                                                               (void*)free_package_entry);
-       free(this->reasons);
-       free(this->instructions);
+       DESTROY_IF(this->reason_string);
+       DESTROY_IF(this->remediation_string);
+       this->update_packages->destroy_function(this->update_packages, free);
+       this->remove_packages->destroy_function(this->remove_packages, free);
        free(this->info);
        free(this->name.ptr);
        free(this->version.ptr);
@@ -608,12 +532,16 @@ METHOD(imv_os_state_t, add_bad_package, void,
        private_imv_os_state_t *this, char *package,
        os_package_state_t package_state)
 {
-       package_entry_t *entry;
+       package = strdup(package);
 
-       entry = malloc_thing(package_entry_t);
-       entry->name = strdup(package);
-       entry->state = package_state;
-       this->bad_packages->insert_last(this->bad_packages, entry);
+       if (package_state == OS_PACKAGE_STATE_BLACKLIST)
+       {
+               this->remove_packages->insert_last(this->remove_packages, package);
+       }
+       else
+       {
+               this->update_packages->insert_last(this->update_packages, package);
+       }
 }
 
 /**
@@ -655,7 +583,8 @@ imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id)
                .rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
                .eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
                .connection_id = connection_id,
-               .bad_packages = linked_list_create(),
+               .update_packages = linked_list_create(),
+               .remove_packages = linked_list_create(),
        );
 
        return &this->public.interface;
index 60bdcc8..fba24f1 100644 (file)
@@ -14,6 +14,9 @@
  */
 
 #include "imv_scanner_state.h"
+#include "imv/imv_lang_string.h"
+#include "imv/imv_reason_string.h"
+#include "imv/imv_remediation_string.h"
 
 #include <utils/lexparser.h>
 #include <utils/debug.h>
@@ -71,39 +74,53 @@ struct private_imv_scanner_state_t {
        char *violating_ports;
 
        /**
-        * Local copy of the remediation instruction string
+        * TNC Reason String
         */
-       char *instructions;
-};
+       imv_reason_string_t *reason_string;
 
-typedef struct entry_t entry_t;
+       /**
+        * IETF Remediation Instructions String
+        */
+       imv_remediation_string_t *remediation_string;
+
+};
 
 /**
- * Define an internal reason string entry
+ * Supported languages
  */
-struct entry_t {
-       char *lang;
-       char *string;
-};
+static char* languages[] = { "en", "de", "fr", "pl" };
 
 /**
- * Table of multi-lingual reason string entries
+ * Table of reason strings
  */
-static entry_t reasons[] = {
+static imv_lang_string_t reasons[] = {
        { "en", "Open server ports were detected" },
        { "de", "Offene Serverports wurden festgestellt" },
        { "fr", "Il y a des ports du serveur ouverts" },
-       { "pl", "Są otwarte porty serwera" }
+       { "pl", "Są otwarte porty serwera" },
+       { NULL, NULL }
+};
+
+/**
+ * Table of "ports" remediation instruction title strings
+ */
+static imv_lang_string_t instr_ports_title[] = {
+       { "en", "Open Server Ports" },
+       { "de", "Offene Server Ports" },
+       { "fr", "Ports ouverts du serveur" },
+       { "pl", "Otwarte Porty Serwera" },
+       { NULL, NULL }
 };
 
 /**
- * Table of multi-lingual remediation instruction string entries
+ * Table of "ports" remediation instruction descriptions strings
  */
-static entry_t instructions [] = {
-       { "en", "Please close the following server ports:" },
-       { "de", "Bitte schliessen Sie die folgenden Serverports:" },
-       { "fr", "Fermez les ports du serveur suivants s'il vous plait:" },
-       { "pl", "Proszę zamknąć następujące porty serwera:" }
+static imv_lang_string_t instr_ports_descr[] = {
+       { "en", "Please close the following server ports" },
+       { "de", "Bitte schliessen Sie die folgenden Serverports" },
+       { "fr", "Fermez les ports du serveur suivants s'il vous plait" },
+       { "pl", "Proszę zamknąć następujące porty serwera" },
+       { NULL, NULL }
 };
 
 METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
@@ -167,80 +184,44 @@ METHOD(imv_state_t, set_recommendation, void,
 
 METHOD(imv_state_t, get_reason_string, bool,
        private_imv_scanner_state_t *this, enumerator_t *language_enumerator,
-       char **reason_string, char **reason_language)
+       chunk_t *reason_string, char **reason_language)
 {
-       bool match = FALSE;
-       char *lang;
-       int i;
-
        if (!this->violating_ports)
        {
                return FALSE;
        }
+       *reason_language = imv_lang_string_select_lang(language_enumerator,
+                                                                                         languages, countof(languages));
 
-       /* 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++)
-               {
-                       if (streq(lang, reasons[i].lang))
-                       {
-                               match = TRUE;
-                               *reason_language = reasons[i].lang;
-                               *reason_string   = reasons[i].string;
-                               break;
-                       }
-               }
-               if (match)
-               {
-                       break;
-               }
-       }
+       /* Instantiate a TNC Reason String object */
+       DESTROY_IF(this->reason_string);
+       this->reason_string = imv_reason_string_create(*reason_language);
+       this->reason_string->add_reason(this->reason_string, reasons);
+       *reason_string = this->reason_string->get_encoding(this->reason_string);
 
        return TRUE;
 }
 
 METHOD(imv_state_t, get_remediation_instructions, bool,
        private_imv_scanner_state_t *this, enumerator_t *language_enumerator,
-       char **string, char **lang_code, char **uri)
+       chunk_t *string, char **lang_code, char **uri)
 {
-       bool match = FALSE;
-       char *lang;
-       int i;
-
        if (!this->violating_ports)
        {
                return FALSE;
        }
+       *lang_code = imv_lang_string_select_lang(language_enumerator,
+                                                                               languages, countof(languages));
 
-       /* set the default language */
-       *lang_code = instructions[0].lang;
-       *string    = instructions[0].string;
+       /* Instantiate an IETF Remediation Instructions String object */
+       DESTROY_IF(this->remediation_string);
+       this->remediation_string = imv_remediation_string_create(
+                                                                       TRUE, *lang_code);      /* TODO get os_type */
 
-       while (language_enumerator->enumerate(language_enumerator, &lang))
-       {
-               for (i = 0; i < countof(instructions); i++)
-               {
-                       if (streq(lang, instructions[i].lang))
-                       {
-                               match = TRUE;
-                               *lang_code = instructions[i].lang;
-                               *string    = instructions[i].string;
-                               break;
-                       }
-               }
-               if (match)
-               {
-                       break;
-               }
-       }
-       this->instructions = malloc(strlen(*string) +
-                                                               strlen(this->violating_ports) + 1);
-       sprintf(this->instructions, "%s%s", *string, this->violating_ports);
-       *string = this->instructions;
+       this->remediation_string->add_instruction(this->remediation_string,
+                                               instr_ports_title, instr_ports_descr, NULL, NULL);
+
+       *string = this->remediation_string->get_encoding(this->remediation_string);
        *uri = lib->settings->get_str(lib->settings,
                                "libimcv.plugins.imv-scanner.remediation_uri", NULL);
 
@@ -250,8 +231,9 @@ METHOD(imv_state_t, get_remediation_instructions, bool,
 METHOD(imv_state_t, destroy, void,
        private_imv_scanner_state_t *this)
 {
+       DESTROY_IF(this->reason_string);
+       DESTROY_IF(this->remediation_string);
        free(this->violating_ports);
-       free(this->instructions);
        free(this);
 }
 
index 9b8635d..9b9344b 100644 (file)
@@ -14,6 +14,8 @@
  */
 
 #include "imv_test_state.h"
+#include "imv/imv_lang_string.h"
+#include "imv/imv_reason_string.h"
 
 #include <utils/lexparser.h>
 #include <collections/linked_list.h>
@@ -67,6 +69,11 @@ struct private_imv_test_state_t {
        TNC_IMV_Evaluation_Result eval;
 
        /**
+        * TNC Reason String
+        */
+       imv_reason_string_t *reason_string;
+
+       /**
         * List of IMCs
         */
        linked_list_t *imcs;
@@ -83,24 +90,20 @@ struct imc_entry_t {
        int rounds;
 };
 
-typedef struct entry_t entry_t;
-
 /**
- * Define an internal reason string entry
+ * Supported languages
  */
-struct entry_t {
-       char *lang;
-       char *string;
-};
+static char* languages[] = { "en", "de", "fr", "pl" };
 
 /**
- * Table of multi-lingual reason string entries
+ * Table of reason strings
  */
-static entry_t reasons[] = {
+static imv_lang_string_t reasons[] = {
        { "en", "IMC Test was not configured with \"command = allow\"" },
        { "de", "IMC Test wurde nicht mit \"command = allow\" konfiguriert" },
        { "fr", "IMC Test n'etait pas configuré avec \"command = allow\"" },
-       { "pl", "IMC Test nie zostało skonfigurowany z \"command = allow\"" }
+       { "pl", "IMC Test nie zostało skonfigurowany z \"command = allow\"" },
+       { NULL, NULL }
 };
 
 METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
@@ -164,40 +167,23 @@ METHOD(imv_state_t, set_recommendation, void,
 
 METHOD(imv_state_t, get_reason_string, bool,
        private_imv_test_state_t *this, enumerator_t *language_enumerator,
-       char **reason_string, char **reason_language)
+       chunk_t *reason_string, char **reason_language)
 {
-       bool match = FALSE;
-       char *lang;
-       int i;
-
-       /* set the default language */
-       *reason_language = reasons[0].lang;
-       *reason_string   = reasons[0].string;
+       *reason_language = imv_lang_string_select_lang(language_enumerator,
+                                                                                         languages, countof(languages));
 
-       while (language_enumerator->enumerate(language_enumerator, &lang))
-       {
-               for (i = 0 ; i < countof(reasons); i++)
-               {
-                       if (streq(lang, reasons[i].lang))
-                       {
-                               match = TRUE;
-                               *reason_language = reasons[i].lang;
-                               *reason_string   = reasons[i].string;
-                               break;
-                       }
-               }
-               if (match)
-               {
-                       break;
-               }
-       }
+       /* Instantiate a TNC Reason String object */
+       DESTROY_IF(this->reason_string);
+       this->reason_string = imv_reason_string_create(*reason_language);
+       this->reason_string->add_reason(this->reason_string, reasons);
+       *reason_string = this->reason_string->get_encoding(this->reason_string);
 
        return TRUE;
 }
 
 METHOD(imv_state_t, get_remediation_instructions, bool,
        private_imv_test_state_t *this, enumerator_t *language_enumerator,
-       char **string, char **lang_code, char **uri)
+       chunk_t *string, char **lang_code, char **uri)
 {
        return FALSE;
 }
@@ -205,6 +191,7 @@ METHOD(imv_state_t, get_remediation_instructions, bool,
 METHOD(imv_state_t, destroy, void,
        private_imv_test_state_t *this)
 {
+       DESTROY_IF(this->reason_string);
        this->imcs->destroy_function(this->imcs, free);
        free(this);
 }
index 4151ccb..e6cb113 100644 (file)
@@ -17,6 +17,9 @@
 
 #include <libpts.h>
 
+#include <imv/imv_lang_string.h>
+#include "imv/imv_reason_string.h"
+
 #include <utils/lexparser.h>
 #include <collections/linked_list.h>
 #include <utils/debug.h>
@@ -100,6 +103,11 @@ struct private_imv_attestation_state_t {
         */
        bool measurement_error;
 
+       /**
+        * TNC Reason String
+        */
+       imv_reason_string_t *reason_string;
+
 };
 
 /**
@@ -128,26 +136,22 @@ static void free_func_comp(func_comp_t *this)
        free(this);
 }
 
-typedef struct entry_t entry_t;
-
 /**
- * Define an internal reason string entry
+ * Supported languages
  */
-struct entry_t {
-       char *lang;
-       char *string;
-};
+static char* languages[] = { "en", "mn", "de" };
 
 /**
- * Table of multi-lingual reason string entries
+ * Table of reason strings
  */
-static entry_t reasons[] = {
+static imv_lang_string_t reasons[] = {
        { "en", "IMV Attestation: Incorrect/pending file measurement/component"
                        " evidence or invalid TPM Quote signature received" },
        { "mn", "IMV Attestation:  Буруу/хүлээгдэж байгаа файл/компонент хэмжилт "
                        "эсвэл буруу TPM Quote гарын үсэг" },
        { "de", "IMV Attestation: Falsche/Fehlende Dateimessung/Komponenten Beweis "
                        "oder ungültige TPM Quote Unterschrift ist erhalten" },
+       { NULL, NULL }
 };
 
 METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
@@ -211,40 +215,23 @@ METHOD(imv_state_t, set_recommendation, void,
 
 METHOD(imv_state_t, get_reason_string, bool,
        private_imv_attestation_state_t *this, enumerator_t *language_enumerator,
-       char **reason_string, char **reason_language)
+       chunk_t *reason_string, char **reason_language)
 {
-       bool match = FALSE;
-       char *lang;
-       int i;
-
-       /* set the default language */
-       *reason_language = reasons[0].lang;
-       *reason_string   = reasons[0].string;
+       *reason_language = imv_lang_string_select_lang(language_enumerator,
+                                                                                         languages, countof(languages));
 
-       while (language_enumerator->enumerate(language_enumerator, &lang))
-       {
-               for (i = 0 ; i < countof(reasons); i++)
-               {
-                       if (streq(lang, reasons[i].lang))
-                       {
-                               match = TRUE;
-                               *reason_language = reasons[i].lang;
-                               *reason_string   = reasons[i].string;
-                               break;
-                       }
-               }
-               if (match)
-               {
-                       break;
-               }
-       }
+       /* Instantiate a TNC Reason String object */
+       DESTROY_IF(this->reason_string);
+       this->reason_string = imv_reason_string_create(*reason_language);
+       this->reason_string->add_reason(this->reason_string, reasons);
+       *reason_string = this->reason_string->get_encoding(this->reason_string);
 
        return TRUE;
 }
 
 METHOD(imv_state_t, get_remediation_instructions, bool,
        private_imv_attestation_state_t *this, enumerator_t *language_enumerator,
-       char **string, char **lang_code, char **uri)
+       chunk_t *string, char **lang_code, char **uri)
 {
        return FALSE;
 }
@@ -252,6 +239,7 @@ METHOD(imv_state_t, get_remediation_instructions, bool,
 METHOD(imv_state_t, destroy, void,
        private_imv_attestation_state_t *this)
 {
+       DESTROY_IF(this->reason_string);
        this->file_meas_requests->destroy_function(this->file_meas_requests, free);
        this->components->destroy_function(this->components, (void *)free_func_comp);
        this->pts->destroy(this->pts);