implemented ITA Get Settings and ITA Settings attributes
authorAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 1 Nov 2012 17:00:40 +0000 (18:00 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 1 Nov 2012 17:00:40 +0000 (18:00 +0100)
src/libimcv/Makefile.am
src/libimcv/ita/ita_attr.c
src/libimcv/ita/ita_attr.h
src/libimcv/ita/ita_attr_get_settings.c [new file with mode: 0644]
src/libimcv/ita/ita_attr_get_settings.h [new file with mode: 0644]
src/libimcv/ita/ita_attr_settings.c [new file with mode: 0644]
src/libimcv/ita/ita_attr_settings.h [new file with mode: 0644]
src/libimcv/os_info/os_info.c
src/libimcv/os_info/os_info.h
src/libimcv/plugins/imc_os/imc_os.c
src/libimcv/plugins/imv_os/imv_os.c

index d8c3e96..4f0e000 100644 (file)
@@ -27,6 +27,8 @@ libimcv_la_SOURCES = \
        ita/ita_attr.h ita/ita_attr.c \
        ita/ita_attr_command.h ita/ita_attr_command.c \
        ita/ita_attr_dummy.h ita/ita_attr_dummy.c \
+       ita/ita_attr_get_settings.h ita/ita_attr_get_settings.c \
+       ita/ita_attr_settings.h ita/ita_attr_settings.c \
        os_info/os_info.h os_info/os_info.c \
        pa_tnc/pa_tnc_attr.h \
        pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
index 0ea799c..cc5f648 100644 (file)
 #include "ita_attr.h"
 #include "ita/ita_attr_command.h"
 #include "ita/ita_attr_dummy.h"
+#include "ita/ita_attr_get_settings.h"
+#include "ita/ita_attr_settings.h"
 
-ENUM(ita_attr_names, ITA_ATTR_COMMAND, ITA_ATTR_DUMMY,
+ENUM(ita_attr_names, ITA_ATTR_COMMAND, ITA_ATTR_SETTINGS,
        "Command",
        "Dummy",
+       "Get Settings",
+       "Settings"
 );
 
 /**
@@ -33,6 +37,10 @@ pa_tnc_attr_t* ita_attr_create_from_data(u_int32_t type, chunk_t value)
                        return ita_attr_command_create_from_data(value);
                case ITA_ATTR_DUMMY:
                        return ita_attr_dummy_create_from_data(value);
+               case ITA_ATTR_GET_SETTINGS:
+                       return ita_attr_get_settings_create_from_data(value);
+               case ITA_ATTR_SETTINGS:
+                       return ita_attr_settings_create_from_data(value);
                default:
                        return NULL;
        }
index 3baf0e3..ae964a2 100644 (file)
@@ -33,6 +33,8 @@ typedef enum ita_attr_t ita_attr_t;
 enum ita_attr_t {
        ITA_ATTR_COMMAND =      1,
        ITA_ATTR_DUMMY = 2,
+       ITA_ATTR_GET_SETTINGS = 3,
+       ITA_ATTR_SETTINGS = 4,
 };
 
 /**
diff --git a/src/libimcv/ita/ita_attr_get_settings.c b/src/libimcv/ita/ita_attr_get_settings.c
new file mode 100644 (file)
index 0000000..c19a8bf
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * 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 "ita_attr.h"
+#include "ita_attr_get_settings.h"
+
+#include <bio/bio_reader.h>
+#include <bio/bio_writer.h>
+#include <collections/linked_list.h>
+#include <pen/pen.h>
+#include <utils/debug.h>
+
+typedef struct private_ita_attr_get_settings_t private_ita_attr_get_settings_t;
+
+/**
+ * ITA Get Settings
+ *
+ *                                        1                               2                               3
+ *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |                         Settings Count                        |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |        Name Length            |  Name (Variable Length)       ~
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  ~                      Name (Variable Length)                   ~
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |        Name Length            |  Name (Variable Length)       ~
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  ~                      Name (Variable Length)                   ~
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *                                      ...........................
+ */
+
+#define ITA_GET_SETTINGS_MIN_SIZE      4
+
+/**
+ * Private data of an ita_attr_get_settings_t object.
+ */
+struct private_ita_attr_get_settings_t {
+
+       /**
+        * Public members of ita_attr_get_settings_t
+        */
+       ita_attr_get_settings_t public;
+
+       /**
+        * Vendor-specific attribute type
+        */
+       pen_type_t type;
+
+       /**
+        * Attribute value
+        */
+       chunk_t value;
+
+       /**
+        * Noskip flag
+        */
+       bool noskip_flag;
+
+       /**
+        * List of requested settings
+        */
+       linked_list_t *list;
+
+       /**
+        * Reference count
+        */
+       refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+       private_ita_attr_get_settings_t *this)
+{
+       return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+       private_ita_attr_get_settings_t *this)
+{
+       return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+       private_ita_attr_get_settings_t *this)
+{
+       return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+       private_ita_attr_get_settings_t *this, bool noskip)
+{
+       this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+       private_ita_attr_get_settings_t *this)
+{
+       bio_writer_t *writer;
+       enumerator_t *enumerator;
+       char *name;
+
+       if (this->value.ptr)
+       {
+               return;
+       }
+       writer = bio_writer_create(ITA_GET_SETTINGS_MIN_SIZE);
+       writer->write_uint32(writer, this->list->get_count(this->list));
+
+       enumerator = this->list->create_enumerator(this->list);
+       while (enumerator->enumerate(enumerator, &name))
+       {
+               writer->write_data16(writer, chunk_create(name, strlen(name)));
+       }
+       enumerator->destroy(enumerator);
+
+       this->value = chunk_clone(writer->get_buf(writer));
+       writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+       private_ita_attr_get_settings_t *this, u_int32_t *offset)
+{
+       bio_reader_t *reader;
+       u_int32_t count;
+       char *name_str;
+       chunk_t name;
+       status_t status = FAILED;
+
+       if (this->value.len < ITA_GET_SETTINGS_MIN_SIZE)
+       {
+               DBG1(DBG_TNC, "insufficient data for ITA Get Settings attribute");
+               *offset = 0;
+               return FAILED;
+       }
+
+       reader = bio_reader_create(this->value);
+       reader->read_uint32(reader, &count);
+
+       *offset = ITA_GET_SETTINGS_MIN_SIZE;
+
+       while (count--)
+       {
+               if (!reader->read_data16(reader, &name))
+               {
+                       DBG1(DBG_TNC, "insufficient data for setting name");
+                       goto end;
+               }
+               *offset += 2 + name.len;
+
+               name_str = malloc(name.len + 1);
+               memcpy(name_str, name.ptr, name.len);
+               name_str[name.len] = '\0';
+               this->list->insert_last(this->list, name_str);
+       }
+       status = SUCCESS;
+
+end:
+       reader->destroy(reader);        
+       return status;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+       private_ita_attr_get_settings_t *this)
+{
+       ref_get(&this->ref);
+       return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+       private_ita_attr_get_settings_t *this)
+{
+       if (ref_put(&this->ref))
+       {
+               this->list->destroy_function(this->list, free); 
+               free(this->value.ptr);
+               free(this);
+       }
+}
+
+METHOD(ita_attr_get_settings_t, add, void,
+       private_ita_attr_get_settings_t *this, char *name)
+{
+       this->list->insert_last(this->list, strdup(name));
+}
+
+METHOD(ita_attr_get_settings_t, create_enumerator, enumerator_t*,
+       private_ita_attr_get_settings_t *this)
+{
+       return this->list->create_enumerator(this->list);
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ita_attr_get_settings_create(void)
+{
+       private_ita_attr_get_settings_t *this;
+
+       INIT(this,
+               .public = {
+                       .pa_tnc_attribute = {
+                               .get_type = _get_type,
+                               .get_value = _get_value,
+                               .get_noskip_flag = _get_noskip_flag,
+                               .set_noskip_flag = _set_noskip_flag,
+                               .build = _build,
+                               .process = _process,
+                               .get_ref = _get_ref,
+                               .destroy = _destroy,
+                       },
+                       .add = _add,
+                       .create_enumerator = _create_enumerator,
+               },
+               .type = { PEN_ITA, ITA_ATTR_GET_SETTINGS },
+               .list = linked_list_create(),
+               .ref = 1,
+       );
+
+       return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ita_attr_get_settings_create_from_data(chunk_t data)
+{
+       private_ita_attr_get_settings_t *this;
+
+       INIT(this,
+               .public = {
+                       .pa_tnc_attribute = {
+                               .get_type = _get_type,
+                               .get_value = _get_value,
+                               .get_noskip_flag = _get_noskip_flag,
+                               .set_noskip_flag = _set_noskip_flag,
+                               .build = _build,
+                               .process = _process,
+                               .get_ref = _get_ref,
+                               .destroy = _destroy,
+                       },
+                       .add = _add,
+                       .create_enumerator = _create_enumerator,
+               },
+               .type = { PEN_ITA, ITA_ATTR_GET_SETTINGS },
+               .value = chunk_clone(data),
+               .list = linked_list_create(),
+               .ref = 1,
+       );
+
+       return &this->public.pa_tnc_attribute;
+}
+
+
diff --git a/src/libimcv/ita/ita_attr_get_settings.h b/src/libimcv/ita/ita_attr_get_settings.h
new file mode 100644 (file)
index 0000000..cc5c181
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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 ita_attr_get_settingst ita_attr_get_settings
+ * @{ @ingroup ita_attr_get_settings
+ */
+
+#ifndef ITA_ATTR_GET_SETTINGS_H_
+#define ITA_ATTR_GET_SETTINGS_H_
+
+typedef struct ita_attr_get_settings_t ita_attr_get_settings_t;
+
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing the ITA Get Settings PA-TNC attribute.
+ *
+ */
+struct ita_attr_get_settings_t {
+
+       /**
+        * Public PA-TNC attribute interface
+        */
+       pa_tnc_attr_t pa_tnc_attribute;
+
+       /**
+        * Add a setting request to the list
+        *
+        * @param name                  name of the requested setting
+        */
+       void (*add)(ita_attr_get_settings_t *this, char *name);
+
+       /**
+        * Return an enumerator over all requested settings
+        *
+        * @return                              enumerator returns char *name
+        */
+       enumerator_t* (*create_enumerator)(ita_attr_get_settings_t *this);
+};
+
+/**
+ * Creates an ita_attr_get_settings_t object with an empty settings list
+ */
+pa_tnc_attr_t* ita_attr_get_settings_create(void);
+
+/**
+ * Creates an ita_attr_get_settings_t object from received data
+ *
+ * @param value                                binary value blob
+ */
+pa_tnc_attr_t* ita_attr_get_settings_create_from_data(chunk_t value);
+
+#endif /** ITA_ATTR_GET_SETTINGS_H_ @}*/
diff --git a/src/libimcv/ita/ita_attr_settings.c b/src/libimcv/ita/ita_attr_settings.c
new file mode 100644 (file)
index 0000000..9f65768
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ * 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 "ita_attr.h"
+#include "ita_attr_settings.h"
+
+#include <bio/bio_reader.h>
+#include <bio/bio_writer.h>
+#include <collections/linked_list.h>
+#include <pen/pen.h>
+#include <utils/debug.h>
+
+typedef struct private_ita_attr_settings_t private_ita_attr_settings_t;
+typedef struct entry_t entry_t;
+
+/**
+ * Contains a settins name/value pair
+ */
+struct entry_t {
+       char *name;
+       chunk_t value;
+};
+
+/**
+ * Free an entry_t object
+ */
+static void free_entry(entry_t *this)
+{
+       free(this->name);
+       free(this->value.ptr);
+       free(this);
+}
+
+/**
+ * ITA Settings
+ *
+ *                                        1                               2                               3
+ *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |                         Settings Count                        |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |        Name Length            |  Name (Variable Length)       ~
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  ~                      Name (Variable Length)                   ~
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |        Value Length           |  Value (Variable Length)      ~
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  ~                      Value (Variable Length)                  ~
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |        Name Length            |  Name (Variable Length)       ~
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  ~                      Name (Variable Length)                   ~
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |        Value Length           |  Value (Variable Length)      ~
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  ~                      Value (Variable Length)                  ~
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *                                      ...........................
+ */
+
+#define ITA_SETTINGS_MIN_SIZE  4
+
+/**
+ * Private data of an ita_attr_settings_t object.
+ */
+struct private_ita_attr_settings_t {
+
+       /**
+        * Public members of ita_attr_settings_t
+        */
+       ita_attr_settings_t public;
+
+       /**
+        * Vendor-specific attribute type
+        */
+       pen_type_t type;
+
+       /**
+        * Attribute value
+        */
+       chunk_t value;
+
+       /**
+        * Noskip flag
+        */
+       bool noskip_flag;
+
+       /**
+        * List of settings
+        */
+       linked_list_t *list;
+
+       /**
+        * Reference count
+        */
+       refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+       private_ita_attr_settings_t *this)
+{
+       return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+       private_ita_attr_settings_t *this)
+{
+       return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+       private_ita_attr_settings_t *this)
+{
+       return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+       private_ita_attr_settings_t *this, bool noskip)
+{
+       this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+       private_ita_attr_settings_t *this)
+{
+       bio_writer_t *writer;
+       enumerator_t *enumerator;
+       entry_t *entry;
+
+       if (this->value.ptr)
+       {
+               return;
+       }
+       writer = bio_writer_create(ITA_SETTINGS_MIN_SIZE);
+       writer->write_uint32(writer, this->list->get_count(this->list));
+
+       enumerator = this->list->create_enumerator(this->list);
+       while (enumerator->enumerate(enumerator, &entry))
+       {
+               writer->write_data16(writer, chunk_create(entry->name,
+                                                                                                 strlen(entry->name)));
+               writer->write_data16(writer, entry->value);
+       }
+       enumerator->destroy(enumerator);
+
+       this->value = chunk_clone(writer->get_buf(writer));
+       writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+       private_ita_attr_settings_t *this, u_int32_t *offset)
+{
+       bio_reader_t *reader;
+       u_int32_t count;
+       chunk_t name, value;
+       entry_t *entry;
+       status_t status = FAILED;
+
+       if (this->value.len < ITA_SETTINGS_MIN_SIZE)
+       {
+               DBG1(DBG_TNC, "insufficient data for ITA Settings attribute");
+               *offset = 0;
+               return FAILED;
+       }
+
+       reader = bio_reader_create(this->value);
+       reader->read_uint32(reader, &count);
+
+       *offset = ITA_SETTINGS_MIN_SIZE;
+
+       while (count--)
+       {
+               if (!reader->read_data16(reader, &name))
+               {
+                       DBG1(DBG_TNC, "insufficient data for setting name");
+                       goto end;
+               }
+               *offset += 2 + name.len;
+
+               if (!reader->read_data16(reader, &value))
+               {
+                       DBG1(DBG_TNC, "insufficient data for setting value");
+                       goto end;
+               }
+               *offset += 2 + value.len;
+
+               entry = malloc_thing(entry_t);
+               entry->name = malloc(name.len + 1);
+               memcpy(entry->name, name.ptr, name.len);
+               entry->name[name.len] = '\0';
+               entry->value = chunk_clone(value);
+               this->list->insert_last(this->list, entry);
+       }
+       status = SUCCESS;
+
+end:
+       reader->destroy(reader);        
+       return status;
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+       private_ita_attr_settings_t *this)
+{
+       ref_get(&this->ref);
+       return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+       private_ita_attr_settings_t *this)
+{
+       if (ref_put(&this->ref))
+       {
+               this->list->destroy_function(this->list, (void*)free_entry);    
+               free(this->value.ptr);
+               free(this);
+       }
+}
+
+METHOD(ita_attr_settings_t, add, void,
+       private_ita_attr_settings_t *this, char *name, chunk_t value)
+{
+       entry_t *entry;
+
+       entry = malloc_thing(entry_t);
+       entry->name = strdup(name);
+       entry->value = chunk_clone(value);
+       this->list->insert_last(this->list, entry);
+}
+
+/**
+ * Enumerate name/value pairs
+ */
+static bool entry_filter(void *null, entry_t **entry, char **name,
+                                                void *i2, chunk_t *value)
+{
+       *name = (*entry)->name;
+       *value = (*entry)->value;
+       return TRUE;
+}
+
+METHOD(ita_attr_settings_t, create_enumerator, enumerator_t*,
+       private_ita_attr_settings_t *this)
+{
+       return enumerator_create_filter(this->list->create_enumerator(this->list),
+                                                                  (void*)entry_filter, NULL, NULL);
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ita_attr_settings_create(void)
+{
+       private_ita_attr_settings_t *this;
+
+       INIT(this,
+               .public = {
+                       .pa_tnc_attribute = {
+                               .get_type = _get_type,
+                               .get_value = _get_value,
+                               .get_noskip_flag = _get_noskip_flag,
+                               .set_noskip_flag = _set_noskip_flag,
+                               .build = _build,
+                               .process = _process,
+                               .get_ref = _get_ref,
+                               .destroy = _destroy,
+                       },
+                       .add = _add,
+                       .create_enumerator = _create_enumerator,
+               },
+               .type = { PEN_ITA, ITA_ATTR_SETTINGS },
+               .list = linked_list_create(),
+               .ref = 1,
+       );
+
+       return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ita_attr_settings_create_from_data(chunk_t data)
+{
+       private_ita_attr_settings_t *this;
+
+       INIT(this,
+               .public = {
+                       .pa_tnc_attribute = {
+                               .get_type = _get_type,
+                               .get_value = _get_value,
+                               .get_noskip_flag = _get_noskip_flag,
+                               .set_noskip_flag = _set_noskip_flag,
+                               .build = _build,
+                               .process = _process,
+                               .get_ref = _get_ref,
+                               .destroy = _destroy,
+                       },
+                       .add = _add,
+                       .create_enumerator = _create_enumerator,
+               },
+               .type = { PEN_ITA, ITA_ATTR_SETTINGS },
+               .value = chunk_clone(data),
+               .list = linked_list_create(),
+               .ref = 1,
+       );
+
+       return &this->public.pa_tnc_attribute;
+}
+
+
diff --git a/src/libimcv/ita/ita_attr_settings.h b/src/libimcv/ita/ita_attr_settings.h
new file mode 100644 (file)
index 0000000..f3d1fd4
--- /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 ita_attr_settingst ita_attr_settings
+ * @{ @ingroup ita_attr_settings
+ */
+
+#ifndef ITA_ATTR_SETTINGS_H_
+#define ITA_ATTR_SETTINGS_H_
+
+typedef struct ita_attr_settings_t ita_attr_settings_t;
+
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing the ITA Settings PA-TNC attribute.
+ *
+ */
+struct ita_attr_settings_t {
+
+       /**
+        * Public PA-TNC attribute interface
+        */
+       pa_tnc_attr_t pa_tnc_attribute;
+
+       /**
+        * Add a setting to the list
+        *
+        * @param name                  name of the setting
+        * @param value                 value of the setting
+        */
+       void (*add)(ita_attr_settings_t *this, char *name, chunk_t value);
+
+       /**
+        * Return an enumerator over all name/value pairs
+        *
+        * @return                              enumerator returns char **name, chunk_t *value
+        */
+       enumerator_t* (*create_enumerator)(ita_attr_settings_t *this);
+};
+
+/**
+ * Creates an ita_attr_settings_t object with an empty settings list
+ */
+pa_tnc_attr_t* ita_attr_settings_create(void);
+
+/**
+ * Creates an ita_attr_settings_t object from received data
+ *
+ * @param value                                binary value blob
+ */
+pa_tnc_attr_t* ita_attr_settings_create_from_data(chunk_t value);
+
+#endif /** ITA_ATTR_SETTINGS_H_ @}*/
index c0661dc..05e335f 100644 (file)
@@ -144,6 +144,36 @@ METHOD(os_info_t, get_uptime, time_t,
        return uptime;
 }
 
+METHOD(os_info_t, get_setting, chunk_t,
+       private_os_info_t *this, char *name)
+{
+       FILE *file;
+       u_char buf[2048];
+       size_t i = 0;
+       chunk_t value;
+
+       if (!strneq(name, "/etc/", 5) && !strneq(name, "/proc/", 6) &&
+               !strneq(name, "/sys/", 5))
+       {
+               /**
+                * In order to guarantee privacy, only settings from the
+                * /etc/, /proc/ and /sys/ directories can be retrieved
+                */
+               return chunk_empty;
+       }
+
+       file = fopen(name, "r");
+       while (i < sizeof(buf) && fread(buf + i, 1, 1, file) == 1)
+       {
+               i++;
+       }
+       fclose(file);
+
+       value = chunk_create(buf, i);
+
+       return chunk_clone(value);
+}
+
 METHOD(os_info_t, create_package_enumerator, enumerator_t*,
        private_os_info_t *this)
 {
@@ -387,6 +417,7 @@ os_info_t *os_info_create(void)
                        .get_version = _get_version,
                        .get_fwd_status = _get_fwd_status,
                        .get_uptime = _get_uptime,
+                       .get_setting = _get_setting,
                        .create_package_enumerator = _create_package_enumerator,
                        .destroy = _destroy,
                },
index 12ff979..6a477ca 100644 (file)
@@ -82,6 +82,14 @@ struct os_info_t {
        time_t (*get_uptime)(os_info_t *this);
 
        /**
+        * Get an OS setting (restricted to /proc, /sys, and /etc)
+        *
+        * @param name                          name of OS setting
+        * @return                                      value of OS setting
+        */
+       chunk_t (*get_setting)(os_info_t *this, char *name);
+
+       /**
         * Enumerates over all installed packages
         *
         * @return                              return package enumerator
index e011c2b..7510b26 100644 (file)
@@ -27,6 +27,9 @@
 #include <ietf/ietf_attr_product_info.h>
 #include <ietf/ietf_attr_remediation_instr.h>
 #include <ietf/ietf_attr_string_version.h>
+#include <ita/ita_attr.h>
+#include <ita/ita_attr_get_settings.h>
+#include <ita/ita_attr_settings.h>
 #include <os_info/os_info.h>
 
 #include <tncif_pa_subtypes.h>
@@ -247,6 +250,43 @@ static void add_installed_packages(imc_msg_t *msg)
 }
 
 /**
+ * Add ITA Settings attribute to the send queue
+ */
+static void add_settings(enumerator_t *enumerator, imc_msg_t *msg)
+{
+       pa_tnc_attr_t *attr = NULL;
+       ita_attr_settings_t *attr_cast;
+       chunk_t value;
+       char *name;
+       bool first = TRUE;
+
+       while (enumerator->enumerate(enumerator, &name))
+       {
+               DBG1(DBG_IMC, "setting '%s'", name);
+
+               value = os->get_setting(os, name);
+               if (!value.ptr)
+               {
+                       DBG1(DBG_IMC, "  failed to get setting");
+                       continue;
+               }
+               if (first)
+               {
+                       attr = ita_attr_settings_create();
+                       first = FALSE;
+               }
+               attr_cast = (ita_attr_settings_t*)attr;
+               attr_cast->add(attr_cast, name, value);
+               chunk_free(&value);
+       }
+
+       if (attr)
+       {
+               msg->add_attribute(msg, attr);
+       }
+}
+
+/**
  * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
  */
 TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
@@ -290,7 +330,7 @@ static TNC_Result receive_message(imc_msg_t *in_msg)
        imc_msg_t *out_msg;
        enumerator_t *enumerator;
        pa_tnc_attr_t *attr;
-       pen_type_t attr_type;
+       pen_type_t type;
        TNC_Result result;
        bool fatal_error = FALSE;
 
@@ -306,89 +346,99 @@ static TNC_Result receive_message(imc_msg_t *in_msg)
        enumerator = in_msg->create_attribute_enumerator(in_msg);
        while (enumerator->enumerate(enumerator, &attr))
        {
-               attr_type = attr->get_type(attr);
+               type = attr->get_type(attr);
 
-               if (attr_type.vendor_id != PEN_IETF)
-               {
-                       continue;
-               }
-               if (attr_type.type == IETF_ATTR_ATTRIBUTE_REQUEST)
+               if (type.vendor_id == PEN_IETF)
                {
-                       ietf_attr_attr_request_t *attr_cast;
-                       pen_type_t *entry;
-                       enumerator_t *e;
+                       if (type.type == IETF_ATTR_ATTRIBUTE_REQUEST)
+                       {
+                               ietf_attr_attr_request_t *attr_cast;
+                               pen_type_t *entry;
+                               enumerator_t *e;
 
-                       attr_cast = (ietf_attr_attr_request_t*)attr;
+                               attr_cast = (ietf_attr_attr_request_t*)attr;
 
-                       e = attr_cast->create_enumerator(attr_cast);
-                       while (e->enumerate(e, &entry))
+                               e = attr_cast->create_enumerator(attr_cast);
+                               while (e->enumerate(e, &entry))
+                               {
+                                       if (entry->vendor_id != PEN_IETF)
+                                       {
+                                               continue;
+                                       }
+                                       switch (entry->type)
+                                       {
+                                               case IETF_ATTR_PRODUCT_INFORMATION:
+                                                       add_product_info(out_msg);
+                                                       break;
+                                               case IETF_ATTR_STRING_VERSION:
+                                                       add_string_version(out_msg);
+                                                       break;
+                                               case IETF_ATTR_NUMERIC_VERSION:
+                                                       add_numeric_version(out_msg);
+                                                       break;
+                                               case IETF_ATTR_OPERATIONAL_STATUS:
+                                                       add_op_status(out_msg);
+                                                       break;
+                                               case IETF_ATTR_FORWARDING_ENABLED:
+                                                       add_fwd_enabled(out_msg);
+                                                       break;
+                                               case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED:
+                                                       add_default_pwd_enabled(out_msg);
+                                                       break;
+                                               case IETF_ATTR_INSTALLED_PACKAGES:
+                                                       add_installed_packages(out_msg);
+                                                       break;
+                                               default:
+                                                       break;
+                                       }
+                               }
+                               e->destroy(e);
+                       }
+                       else if (type.type == IETF_ATTR_REMEDIATION_INSTRUCTIONS)
                        {
-                               if (entry->vendor_id != PEN_IETF)
+                               ietf_attr_remediation_instr_t *attr_cast;
+                               pen_type_t parameters_type;
+                               chunk_t parameters, string, lang_code;
+
+                               attr_cast = (ietf_attr_remediation_instr_t*)attr;
+                               parameters_type = attr_cast->get_parameters_type(attr_cast);
+                               parameters = attr_cast->get_parameters(attr_cast);
+
+                               if (parameters_type.vendor_id == PEN_IETF)
                                {
-                                       continue;
+                                       switch (parameters_type.type)
+                                       {
+                                               case IETF_REMEDIATION_PARAMETERS_URI:
+                                                       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);
+                                                       break;
+                                               default:
+                                                       DBG1(DBG_IMC, "remediation parameters %B", &parameters);
+                                       }
                                }
-                               switch (entry->type)
+                               else
                                {
-                                       case IETF_ATTR_PRODUCT_INFORMATION:
-                                               add_product_info(out_msg);
-                                               break;
-                                       case IETF_ATTR_STRING_VERSION:
-                                               add_string_version(out_msg);
-                                               break;
-                                       case IETF_ATTR_NUMERIC_VERSION:
-                                               add_numeric_version(out_msg);
-                                               break;
-                                       case IETF_ATTR_OPERATIONAL_STATUS:
-                                               add_op_status(out_msg);
-                                               break;
-                                       case IETF_ATTR_FORWARDING_ENABLED:
-                                               add_fwd_enabled(out_msg);
-                                               break;
-                                       case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED:
-                                               add_default_pwd_enabled(out_msg);
-                                               break;
-                                       case IETF_ATTR_INSTALLED_PACKAGES:
-                                               add_installed_packages(out_msg);
-                                               break;
-                                       default:
-                                               break;
+                                       DBG1(DBG_IMC, "remediation parameters %B", &parameters);
                                }
                        }
-                       e->destroy(e);
                }
-               else if (attr_type.type == IETF_ATTR_REMEDIATION_INSTRUCTIONS)
+               else if (type.vendor_id == PEN_ITA && type.type == ITA_ATTR_GET_SETTINGS)
                {
-                       ietf_attr_remediation_instr_t *attr_cast;
-                       pen_type_t parameters_type;
-                       chunk_t parameters, string, lang_code;
+                       ita_attr_get_settings_t *attr_cast;
+                       enumerator_t *e;
 
-                       attr_cast = (ietf_attr_remediation_instr_t*)attr;
-                       parameters_type = attr_cast->get_parameters_type(attr_cast);
-                       parameters = attr_cast->get_parameters(attr_cast);
+                       attr_cast = (ita_attr_get_settings_t*)attr;
 
-                       if (parameters_type.vendor_id == PEN_IETF)
-                       {
-                               switch (parameters_type.type)
-                               {
-                                       case IETF_REMEDIATION_PARAMETERS_URI:
-                                               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);
-                                               break;
-                                       default:
-                                               DBG1(DBG_IMC, "remediation parameters %B", &parameters);
-                               }                                               
-                       }
-                       else
-                       {
-                               DBG1(DBG_IMC, "remediation parameters %B", &parameters);
-                       }
-               }       
+                       e = attr_cast->create_enumerator(attr_cast);
+                       add_settings(e, out_msg);
+                       e->destroy(e);
+               }
        }
        enumerator->destroy(enumerator);
 
index 487c9a9..663914b 100644 (file)
@@ -28,7 +28,9 @@
 #include <ietf/ietf_attr_product_info.h>
 #include <ietf/ietf_attr_remediation_instr.h>
 #include <ietf/ietf_attr_string_version.h>
-#include <os_info/os_info.h>
+#include <ita/ita_attr.h>
+#include <ita/ita_attr_get_settings.h>
+#include <ita/ita_attr_settings.h>
 
 #include <tncif_names.h>
 #include <tncif_pa_subtypes.h>
@@ -36,6 +38,7 @@
 #include <pen/pen.h>
 #include <collections/linked_list.h>
 #include <utils/debug.h>
+#include <utils/lexparser.h>
 
 /* IMV definitions */
 
@@ -102,6 +105,23 @@ TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
        }
 }
 
+/**
+ * print multi-line values to debug output
+ */
+static void dbg_imv_multi_line(chunk_t value)
+{
+       chunk_t line;
+
+       while (extract_token(&line, '\n', &value))
+       {
+               DBG2(DBG_IMV, "  %.*s", line.len, line.ptr);
+       }
+       if (value.len)
+       {
+               DBG2(DBG_IMV, "  %.*s", value.len, value.ptr);
+       }
+}
+
 static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg)
 {
        imv_msg_t *out_msg;
@@ -130,117 +150,132 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg)
        {
                type = attr->get_type(attr);
 
-               if (type.vendor_id != PEN_IETF)
-               {
-                       continue;
-               }
-               switch (type.type)
+               if (type.vendor_id == PEN_IETF)
                {
-                       case IETF_ATTR_PRODUCT_INFORMATION:
+                       switch (type.type)
                        {
-                               ietf_attr_product_info_t *attr_cast;
-                               pen_t vendor_id;
-
-                               attr_cast = (ietf_attr_product_info_t*)attr;
-                               os_name = attr_cast->get_info(attr_cast, &vendor_id, NULL);
-                               if (vendor_id != PEN_IETF)
+                               case IETF_ATTR_PRODUCT_INFORMATION:
                                {
-                                       DBG1(DBG_IMV, "operating system name is '%.*s' "
-                                                                 "from vendor %N", os_name.len, os_name.ptr,
-                                                                  pen_names, vendor_id);
+                                       ietf_attr_product_info_t *attr_cast;
+                                       pen_t vendor_id;
+
+                                       attr_cast = (ietf_attr_product_info_t*)attr;
+                                       os_name = attr_cast->get_info(attr_cast, &vendor_id, NULL);
+                                       if (vendor_id != PEN_IETF)
+                                       {
+                                               DBG1(DBG_IMV, "operating system name is '%.*s' "
+                                                                         "from vendor %N", os_name.len, os_name.ptr,
+                                                                          pen_names, vendor_id);
+                                       }
+                                       else
+                                       {
+                                               DBG1(DBG_IMV, "operating system name is '%.*s'",
+                                                                          os_name.len, os_name.ptr);
+                                       }
+                                       break;
                                }
-                               else
+                               case IETF_ATTR_STRING_VERSION:
                                {
-                                       DBG1(DBG_IMV, "operating system name is '%.*s'",
-                                                                  os_name.len, os_name.ptr);
+                                       ietf_attr_string_version_t *attr_cast;
+
+                                       attr_cast = (ietf_attr_string_version_t*)attr;
+                                       os_version = attr_cast->get_version(attr_cast, NULL, NULL);
+                                       if (os_version.len)
+                                       {
+                                               DBG1(DBG_IMV, "operating system version is '%.*s'",
+                                                                          os_version.len, os_version.ptr);
+                                       }
+                                       break;
                                }
-                               break;
-                       }
-                       case IETF_ATTR_STRING_VERSION:
-                       {
-                               ietf_attr_string_version_t *attr_cast;
-
-                               attr_cast = (ietf_attr_string_version_t*)attr;
-                               os_version = attr_cast->get_version(attr_cast, NULL, NULL);
-                               if (os_version.len)
+                               case IETF_ATTR_NUMERIC_VERSION:
                                {
-                                       DBG1(DBG_IMV, "operating system version is '%.*s'",
-                                                                  os_version.len, os_version.ptr);
+                                       ietf_attr_numeric_version_t *attr_cast;
+                                       u_int32_t major, minor;
+
+                                       attr_cast = (ietf_attr_numeric_version_t*)attr;
+                                       attr_cast->get_version(attr_cast, &major, &minor);
+                                       DBG1(DBG_IMV, "operating system numeric version is %d.%d",
+                                                                  major, minor);
+                                       break;
                                }
-                               break;
-                       }
-                       case IETF_ATTR_NUMERIC_VERSION:
-                       {
-                               ietf_attr_numeric_version_t *attr_cast;
-                               u_int32_t major, minor;
-
-                               attr_cast = (ietf_attr_numeric_version_t*)attr;
-                               attr_cast->get_version(attr_cast, &major, &minor);
-                               DBG1(DBG_IMV, "operating system numeric version is %d.%d",
-                                                          major, minor);
-                               break;
-                       }
-                       case IETF_ATTR_OPERATIONAL_STATUS:
-                       {
-                               ietf_attr_op_status_t *attr_cast;
-                               op_status_t op_status;
-                               op_result_t op_result;
-                               time_t last_boot;
-
-                               attr_cast = (ietf_attr_op_status_t*)attr;
-                               op_status = attr_cast->get_status(attr_cast);
-                               op_result = attr_cast->get_result(attr_cast);
-                               last_boot = attr_cast->get_last_use(attr_cast);
-                               DBG1(DBG_IMV, "operational status: %N, result: %N",
-                                        op_status_names, op_status, op_result_names, op_result);
-                               DBG1(DBG_IMV, "last boot: %T", &last_boot, TRUE);
-                               break;
-                       }
-                       case IETF_ATTR_FORWARDING_ENABLED:
-                       {
-                               ietf_attr_fwd_enabled_t *attr_cast;
-                               os_fwd_status_t fwd_status;
-
-                               attr_cast = (ietf_attr_fwd_enabled_t*)attr;
-                               fwd_status = attr_cast->get_status(attr_cast);
-                               DBG1(DBG_IMV, "IPv4 forwarding status: %N",
-                                                          os_fwd_status_names, fwd_status);
-                               break;
-                       }
-                       case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED:
-                       {
-                               ietf_attr_default_pwd_enabled_t *attr_cast;
-                               bool default_pwd_status;
-
-                               attr_cast = (ietf_attr_default_pwd_enabled_t*)attr;
-                               default_pwd_status = attr_cast->get_status(attr_cast);
-                               DBG1(DBG_IMV, "factory default password: %sabled",
-                                                          default_pwd_status ? "en":"dis");
-                               break;
-                       }
-                       case IETF_ATTR_INSTALLED_PACKAGES:
-                       {
-                               ietf_attr_installed_packages_t *attr_cast;
-                               enumerator_t *e;
-                               chunk_t name, version;
-
-                               attr_cast = (ietf_attr_installed_packages_t*)attr;
-                               e = attr_cast->create_enumerator(attr_cast);
-                               while (e->enumerate(e, &name, &version))
+                               case IETF_ATTR_OPERATIONAL_STATUS:
                                {
-                                       DBG1(DBG_IMV, "package '%.*s' %.*s", name.len, name.ptr,
-                                                                  version.len, version.ptr);
+                                       ietf_attr_op_status_t *attr_cast;
+                                       op_status_t op_status;
+                                       op_result_t op_result;
+                                       time_t last_boot;
+
+                                       attr_cast = (ietf_attr_op_status_t*)attr;
+                                       op_status = attr_cast->get_status(attr_cast);
+                                       op_result = attr_cast->get_result(attr_cast);
+                                       last_boot = attr_cast->get_last_use(attr_cast);
+                                       DBG1(DBG_IMV, "operational status: %N, result: %N",
+                                                op_status_names, op_status, op_result_names, op_result);
+                                       DBG1(DBG_IMV, "last boot: %T", &last_boot, TRUE);
+                                       break;
                                }
-                               e->destroy(e);
-
-                               state->set_recommendation(state,
-                                                                         TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
-                                                                         TNC_IMV_EVALUATION_RESULT_COMPLIANT);
-                               assessment = TRUE;
-                               break;
+                               case IETF_ATTR_FORWARDING_ENABLED:
+                               {
+                                       ietf_attr_fwd_enabled_t *attr_cast;
+                                       os_fwd_status_t fwd_status;
+
+                                       attr_cast = (ietf_attr_fwd_enabled_t*)attr;
+                                       fwd_status = attr_cast->get_status(attr_cast);
+                                       DBG1(DBG_IMV, "IPv4 forwarding status: %N",
+                                                                  os_fwd_status_names, fwd_status);
+                                       break;
+                               }
+                               case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED:
+                               {
+                                       ietf_attr_default_pwd_enabled_t *attr_cast;
+                                       bool default_pwd_status;
+
+                                       attr_cast = (ietf_attr_default_pwd_enabled_t*)attr;
+                                       default_pwd_status = attr_cast->get_status(attr_cast);
+                                       DBG1(DBG_IMV, "factory default password: %sabled",
+                                                                  default_pwd_status ? "en":"dis");
+                                       break;
+                               }
+                               case IETF_ATTR_INSTALLED_PACKAGES:
+                               {
+                                       ietf_attr_installed_packages_t *attr_cast;
+                                       enumerator_t *e;
+                                       chunk_t name, version;
+
+                                       attr_cast = (ietf_attr_installed_packages_t*)attr;
+                                       e = attr_cast->create_enumerator(attr_cast);
+                                       while (e->enumerate(e, &name, &version))
+                                       {
+                                               DBG1(DBG_IMV, "package '%.*s' %.*s", name.len, name.ptr,
+                                                                          version.len, version.ptr);
+                                       }
+                                       e->destroy(e);
+
+                                       state->set_recommendation(state,
+                                                                                 TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
+                                                                                 TNC_IMV_EVALUATION_RESULT_COMPLIANT);
+                                       assessment = TRUE;
+                                       break;
+                               }
+                               default:
+                                       break;
                        }
-                       default:
-                               break;
+               }
+               else if (type.vendor_id == PEN_ITA && type.type == ITA_ATTR_SETTINGS)
+               {
+                       ita_attr_settings_t *attr_cast;
+                       enumerator_t *e;
+                       char *name;
+                       chunk_t value;
+
+                       attr_cast = (ita_attr_settings_t*)attr;
+                       e = attr_cast->create_enumerator(attr_cast);
+                       while (e->enumerate(e, &name, &value))
+                       {
+                               DBG1(DBG_IMV, "setting '%s'", name);
+                               dbg_imv_multi_line(value);
+                       }
+                       e->destroy(e);
                }
        }
        enumerator->destroy(enumerator);
@@ -275,11 +310,29 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg)
                }
                else
                {
+                       ita_attr_get_settings_t *attr_cast;
+
                        DBG1(DBG_IMV, "requesting installed packages for '%s'",
                                                   product_info);
                        attr = ietf_attr_attr_request_create(PEN_IETF,
                                                                IETF_ATTR_INSTALLED_PACKAGES);
                        out_msg->add_attribute(out_msg, attr);
+
+                       /* requesting Android or Linux settings */
+                       attr = ita_attr_get_settings_create();
+                       attr_cast = (ita_attr_get_settings_t*)attr;
+
+                       if (chunk_equals(os_name, chunk_create("Android", 7)))
+                       {
+                               attr_cast->add(attr_cast, "android_id");
+                               attr_cast->add(attr_cast, "install_non_market_apps");
+                       }
+                       else
+                       {
+                               attr_cast->add(attr_cast, "/proc/sys/kernel/random/boot_id");
+                               attr_cast->add(attr_cast, "/proc/sys/kernel/tainted");
+                       }
+                       out_msg->add_attribute(out_msg, attr);
                }
        }