From efe0d5478f16fa7f65b7bccbc018bc115b72c50d Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Thu, 1 Nov 2012 18:00:40 +0100 Subject: [PATCH] implemented ITA Get Settings and ITA Settings attributes --- src/libimcv/Makefile.am | 2 + src/libimcv/ita/ita_attr.c | 10 +- src/libimcv/ita/ita_attr.h | 2 + src/libimcv/ita/ita_attr_get_settings.c | 266 ++++++++++++++++++++++++++ src/libimcv/ita/ita_attr_get_settings.h | 66 +++++++ src/libimcv/ita/ita_attr_settings.c | 321 ++++++++++++++++++++++++++++++++ src/libimcv/ita/ita_attr_settings.h | 67 +++++++ src/libimcv/os_info/os_info.c | 31 +++ src/libimcv/os_info/os_info.h | 8 + src/libimcv/plugins/imc_os/imc_os.c | 190 ++++++++++++------- src/libimcv/plugins/imv_os/imv_os.c | 255 +++++++++++++++---------- 11 files changed, 1046 insertions(+), 172 deletions(-) create mode 100644 src/libimcv/ita/ita_attr_get_settings.c create mode 100644 src/libimcv/ita/ita_attr_get_settings.h create mode 100644 src/libimcv/ita/ita_attr_settings.c create mode 100644 src/libimcv/ita/ita_attr_settings.h diff --git a/src/libimcv/Makefile.am b/src/libimcv/Makefile.am index d8c3e96..4f0e000 100644 --- a/src/libimcv/Makefile.am +++ b/src/libimcv/Makefile.am @@ -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 \ diff --git a/src/libimcv/ita/ita_attr.c b/src/libimcv/ita/ita_attr.c index 0ea799c..cc5f648 100644 --- a/src/libimcv/ita/ita_attr.c +++ b/src/libimcv/ita/ita_attr.c @@ -16,10 +16,14 @@ #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; } diff --git a/src/libimcv/ita/ita_attr.h b/src/libimcv/ita/ita_attr.h index 3baf0e3..ae964a2 100644 --- a/src/libimcv/ita/ita_attr.h +++ b/src/libimcv/ita/ita_attr.h @@ -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 index 0000000..c19a8bf --- /dev/null +++ b/src/libimcv/ita/ita_attr_get_settings.c @@ -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 . + * + * 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 +#include +#include +#include +#include + +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 index 0000000..cc5c181 --- /dev/null +++ b/src/libimcv/ita/ita_attr_get_settings.h @@ -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 . + * + * 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 index 0000000..9f65768 --- /dev/null +++ b/src/libimcv/ita/ita_attr_settings.c @@ -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 . + * + * 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 +#include +#include +#include +#include + +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 index 0000000..f3d1fd4 --- /dev/null +++ b/src/libimcv/ita/ita_attr_settings.h @@ -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 . + * + * 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_ @}*/ diff --git a/src/libimcv/os_info/os_info.c b/src/libimcv/os_info/os_info.c index c0661dc..05e335f 100644 --- a/src/libimcv/os_info/os_info.c +++ b/src/libimcv/os_info/os_info.c @@ -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, }, diff --git a/src/libimcv/os_info/os_info.h b/src/libimcv/os_info/os_info.h index 12ff979..6a477ca 100644 --- a/src/libimcv/os_info/os_info.h +++ b/src/libimcv/os_info/os_info.h @@ -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 diff --git a/src/libimcv/plugins/imc_os/imc_os.c b/src/libimcv/plugins/imc_os/imc_os.c index e011c2b..7510b26 100644 --- a/src/libimcv/plugins/imc_os/imc_os.c +++ b/src/libimcv/plugins/imc_os/imc_os.c @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include #include #include @@ -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", ¶meters); + } } - 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", ¶meters); } } - 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", ¶meters); - } - } - else - { - DBG1(DBG_IMC, "remediation parameters %B", ¶meters); - } - } + e = attr_cast->create_enumerator(attr_cast); + add_settings(e, out_msg); + e->destroy(e); + } } enumerator->destroy(enumerator); diff --git a/src/libimcv/plugins/imv_os/imv_os.c b/src/libimcv/plugins/imv_os/imv_os.c index 487c9a9..663914b 100644 --- a/src/libimcv/plugins/imv_os/imv_os.c +++ b/src/libimcv/plugins/imv_os/imv_os.c @@ -28,7 +28,9 @@ #include #include #include -#include +#include +#include +#include #include #include @@ -36,6 +38,7 @@ #include #include #include +#include /* 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); } } -- 2.7.4