diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2012-10-10 21:54:05 +0200 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2012-10-10 21:54:21 +0200 |
commit | 6ab1502519025e2bd05d01d49fe3d0f1ce8d6bd6 (patch) | |
tree | b851d0b12249cefd3bdbec8efac1e0f8d5c4e175 | |
parent | 7f3bf2b12f81e85c9a0a66c6bcc5c2b44db66b49 (diff) | |
download | strongswan-6ab1502519025e2bd05d01d49fe3d0f1ce8d6bd6.tar.bz2 strongswan-6ab1502519025e2bd05d01d49fe3d0f1ce8d6bd6.tar.xz |
implemented os_info_t class
-rw-r--r-- | man/strongswan.conf.5.in | 12 | ||||
-rw-r--r-- | src/libimcv/Makefile.am | 1 | ||||
-rw-r--r-- | src/libimcv/ietf/ietf_attr_product_info.c | 20 | ||||
-rw-r--r-- | src/libimcv/ietf/ietf_attr_product_info.h | 6 | ||||
-rw-r--r-- | src/libimcv/os_info/os_info.c | 309 | ||||
-rw-r--r-- | src/libimcv/os_info/os_info.h | 65 | ||||
-rw-r--r-- | src/libimcv/plugins/imc_os/imc_os.c | 22 | ||||
-rw-r--r-- | src/libimcv/plugins/imv_os/imv_os.c | 32 | ||||
-rw-r--r-- | src/libimcv/plugins/imv_os/imv_os_state.c | 7 | ||||
-rw-r--r-- | src/libimcv/plugins/imv_os/imv_os_state.h | 2 | ||||
-rw-r--r-- | src/libpts/plugins/imc_attestation/imc_attestation.c | 51 | ||||
-rw-r--r-- | src/libpts/plugins/imc_attestation/imc_attestation_state.c | 8 | ||||
-rwxr-xr-x | src/libpts/plugins/imv_attestation/build-database.sh | 2 | ||||
-rw-r--r-- | src/libpts/plugins/imv_attestation/data.sql | 2 | ||||
-rw-r--r-- | src/libpts/plugins/imv_attestation/imv_attestation.c | 65 | ||||
-rw-r--r-- | src/libpts/plugins/imv_attestation/imv_attestation_state.c | 8 | ||||
-rw-r--r-- | src/libpts/pts/pts.c | 127 | ||||
-rw-r--r-- | src/libpts/pts/pts.h | 5 |
18 files changed, 519 insertions, 225 deletions
diff --git a/man/strongswan.conf.5.in b/man/strongswan.conf.5.in index 217d7d739..f7233c92c 100644 --- a/man/strongswan.conf.5.in +++ b/man/strongswan.conf.5.in @@ -764,10 +764,13 @@ Debug level for a stand-alone libimcv library .TP .BR libimcv.stderr_quiet " [no]" Disable output to stderr with a stand-alone libimcv library -.SS libimcv plugins section .TP -.BR libimcv.plugins.imc-attestation.platform_info -Information on operating system and hardware platform +.BR libimcv.os_info.name +Manually set the name of the client OS (e.g. Ubuntu) +.TP +.BR libimcv.os_info.version +Manually set the version of the client OS (e.g. 12.04 i686) +.SS libimcv plugins section .TP .BR libimcv.plugins.imc-attestation.aik_blob AIK encrypted private key blob file @@ -799,9 +802,6 @@ Preferred measurement hash algorithm .BR libimcv.plugins.imv-attestation.min_nonce_len " [0]" DH minimum nonce length .TP -.BR libimcv.plugins.imv-attestation.platform_info -Information on operating system and hardware platform -.TP .BR libimcv.plugins.imv-scanner.closed_port_policy " [yes]" By default all ports must be closed (yes) or can be open (no) .TP diff --git a/src/libimcv/Makefile.am b/src/libimcv/Makefile.am index 87e834729..d99ac1518 100644 --- a/src/libimcv/Makefile.am +++ b/src/libimcv/Makefile.am @@ -20,6 +20,7 @@ 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 \ + 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 \ pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c diff --git a/src/libimcv/ietf/ietf_attr_product_info.c b/src/libimcv/ietf/ietf_attr_product_info.c index 91bea8181..719619f99 100644 --- a/src/libimcv/ietf/ietf_attr_product_info.c +++ b/src/libimcv/ietf/ietf_attr_product_info.c @@ -73,7 +73,7 @@ struct private_ietf_attr_product_info_t { /** * Product Name */ - char *product_name; + chunk_t product_name; /** * Reference count @@ -109,18 +109,15 @@ METHOD(pa_tnc_attr_t, build, void, private_ietf_attr_product_info_t *this) { bio_writer_t *writer; - chunk_t product_name; if (this->value.ptr) { return; } - product_name = chunk_create(this->product_name, strlen(this->product_name)); - writer = bio_writer_create(PRODUCT_INFO_MIN_SIZE); writer->write_uint24(writer, this->product_vendor_id); writer->write_uint16(writer, this->product_id); - writer->write_data (writer, product_name); + writer->write_data (writer, this->product_name); this->value = chunk_clone(writer->get_buf(writer)); writer->destroy(writer); @@ -151,10 +148,7 @@ METHOD(pa_tnc_attr_t, process, status_t, *offset = 3; return FAILED; } - - this->product_name = malloc(product_name.len + 1); - memcpy(this->product_name, product_name.ptr, product_name.len); - this->product_name[product_name.len] = '\0'; + this->product_name = chunk_clone(product_name); return SUCCESS; } @@ -171,13 +165,13 @@ METHOD(pa_tnc_attr_t, destroy, void, { if (ref_put(&this->ref)) { - free(this->product_name); + free(this->product_name.ptr); free(this->value.ptr); free(this); } } -METHOD(ietf_attr_product_info_t, get_info, char*, +METHOD(ietf_attr_product_info_t, get_info, chunk_t, private_ietf_attr_product_info_t *this, pen_t *vendor_id, u_int16_t *id) { if (vendor_id) @@ -195,7 +189,7 @@ METHOD(ietf_attr_product_info_t, get_info, char*, * Described in header. */ pa_tnc_attr_t *ietf_attr_product_info_create(pen_t vendor_id, u_int16_t id, - char *name) + chunk_t name) { private_ietf_attr_product_info_t *this; @@ -216,7 +210,7 @@ pa_tnc_attr_t *ietf_attr_product_info_create(pen_t vendor_id, u_int16_t id, .type = { PEN_IETF, IETF_ATTR_PRODUCT_INFORMATION }, .product_vendor_id = vendor_id, .product_id = id, - .product_name = strdup(name), + .product_name = chunk_clone(name), .ref = 1, ); diff --git a/src/libimcv/ietf/ietf_attr_product_info.h b/src/libimcv/ietf/ietf_attr_product_info.h index f1dfc3e83..dfaa67d6c 100644 --- a/src/libimcv/ietf/ietf_attr_product_info.h +++ b/src/libimcv/ietf/ietf_attr_product_info.h @@ -45,8 +45,8 @@ struct ietf_attr_product_info_t { * @param id Product ID * @return Product Name */ - char* (*get_info)(ietf_attr_product_info_t *this, - pen_t *vendor_id, u_int16_t *id); + chunk_t (*get_info)(ietf_attr_product_info_t *this, + pen_t *vendor_id, u_int16_t *id); }; @@ -55,7 +55,7 @@ struct ietf_attr_product_info_t { * */ pa_tnc_attr_t* ietf_attr_product_info_create(pen_t vendor_id, u_int16_t id, - char *name); + chunk_t name); /** * Creates an ietf_attr_product_info_t object from received data diff --git a/src/libimcv/os_info/os_info.c b/src/libimcv/os_info/os_info.c new file mode 100644 index 000000000..4dbcee55f --- /dev/null +++ b/src/libimcv/os_info/os_info.c @@ -0,0 +1,309 @@ +/* + * 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 "os_info.h" + +#include <sys/utsname.h> + +#include <utils/linked_list.h> +#include <debug.h> + + +typedef struct private_os_info_t private_os_info_t; + + +/** + * Private data of an os_info_t object. + * + */ +struct private_os_info_t { + + /** + * Public os_info_t interface. + */ + os_info_t public; + + /** + * OS name + */ + chunk_t name; + + /** + * OS version + */ + chunk_t version; + +}; + +METHOD(os_info_t, get_name, chunk_t, + private_os_info_t *this) +{ + return this->name; +} + +METHOD(os_info_t, get_version, chunk_t, + private_os_info_t *this) +{ + return this->version; +} + +METHOD(os_info_t, create_package_enumerator, enumerator_t*, + private_os_info_t *this) +{ + /* TODO */ + return NULL; +} + + +METHOD(os_info_t, destroy, void, + private_os_info_t *this) +{ + free(this->name.ptr); + free(this->version.ptr); + free(this); +} + +#define RELEASE_LSB 0 +#define RELEASE_DEBIAN 1 + +/** + * Determine Linux distribution version and hardware platform + */ +static bool extract_platform_info(chunk_t *name, chunk_t *version) +{ + FILE *file; + u_char buf[BUF_LEN], *pos = buf; + int len = BUF_LEN - 1; + chunk_t os_name = chunk_empty; + chunk_t os_version = chunk_empty; + struct utsname uninfo; + int i; + + /* Linux/Unix distribution release info (from http://linuxmafia.com) */ + const char* releases[] = { + "/etc/lsb-release", "/etc/debian_version", + "/etc/SuSE-release", "/etc/novell-release", + "/etc/sles-release", "/etc/redhat-release", + "/etc/fedora-release", "/etc/gentoo-release", + "/etc/slackware-version", "/etc/annvix-release", + "/etc/arch-release", "/etc/arklinux-release", + "/etc/aurox-release", "/etc/blackcat-release", + "/etc/cobalt-release", "/etc/conectiva-release", + "/etc/debian_release", "/etc/immunix-release", + "/etc/lfs-release", "/etc/linuxppc-release", + "/etc/mandrake-release", "/etc/mandriva-release", + "/etc/mandrakelinux-release", "/etc/mklinux-release", + "/etc/pld-release", "/etc/redhat_version", + "/etc/slackware-release", "/etc/e-smith-release", + "/etc/release", "/etc/sun-release", + "/etc/tinysofa-release", "/etc/turbolinux-release", + "/etc/ultrapenguin-release", "/etc/UnitedLinux-release", + "/etc/va-release", "/etc/yellowdog-release" + }; + + const char lsb_distrib_id[] = "DISTRIB_ID="; + const char lsb_distrib_release[] = "DISTRIB_RELEASE="; + + for (i = 0; i < countof(releases); i++) + { + file = fopen(releases[i], "r"); + if (!file) + { + continue; + } + + /* read release file into buffer */ + fseek(file, 0, SEEK_END); + len = min(ftell(file), len); + rewind(file); + buf[len] = '\0'; + if (fread(buf, 1, len, file) != len) + { + DBG1(DBG_IMC, "failed to read file \"%s\"", releases[i]); + fclose(file); + return FALSE; + } + fclose(file); + + DBG1(DBG_IMC, "processing \"%s\" file", releases[i]); + + switch (i) + { + case RELEASE_LSB: + { + /* Determine Distribution ID */ + pos = strstr(buf, lsb_distrib_id); + if (!pos) + { + DBG1(DBG_IMC, "failed to find begin of DISTRIB_ID field"); + return FALSE; + } + pos += strlen(lsb_distrib_id); + + os_name.ptr = pos; + + pos = strchr(pos, '\n'); + if (!pos) + { + DBG1(DBG_IMC, "failed to find end of DISTRIB_ID field"); + return FALSE; + } + + os_name.len = pos - os_name.ptr; + + /* Determine Distribution Release */ + pos = strstr(buf, lsb_distrib_release); + if (!pos) + { + DBG1(DBG_IMC, "failed to find begin of DISTRIB_RELEASE field"); + return FALSE; + } + pos += strlen(lsb_distrib_release); + + os_version.ptr = pos; + + pos = strchr(pos, '\n'); + if (!pos) + { + DBG1(DBG_IMC, "failed to find end of DISTRIB_RELEASE field"); + return FALSE; + } + + os_version.len = pos - os_version.ptr; + + break; + } + case RELEASE_DEBIAN: + { + char str_debian[] = "Debian"; + + os_name = chunk_create(str_debian, strlen(str_debian)); + os_version.ptr = buf; + + pos = strchr(buf, '\n'); + if (!pos) + { + DBG1(DBG_PTS, "failed to find end of release string"); + return FALSE; + } + + os_version.len = pos - os_version.ptr; + + break; + } + default: + { + const char str_release[] = " release "; + + os_name.ptr = buf; + + pos = strstr(buf, str_release); + if (!pos) + { + DBG1(DBG_IMC, "failed to find release keyword"); + return FALSE; + } + + os_name.len = pos - os_name.ptr; + pos += strlen(str_release); + os_version.ptr = pos; + + pos = strchr(pos, '\n'); + if (!pos) + { + DBG1(DBG_IMC, "failed to find end of release string"); + return FALSE; + } + + os_version.len = pos - os_version.ptr; + + break; + } + } + break; + } + + if (!os_name.ptr) + { + DBG1(DBG_IMC, "no distribution release file found"); + return FALSE; + } + + if (uname(&uninfo) < 0) + { + DBG1(DBG_IMC, "could not retrieve machine architecture"); + return FALSE; + } + + /* copy OS name */ + *name = chunk_clone(os_name); + + /* copy OS version and machine architecture */ + *version = chunk_alloc(os_version.len + 1 + strlen(uninfo.machine)); + pos = version->ptr; + memcpy(pos, os_version.ptr, os_version.len); + pos += os_version.len; + *pos++ = ' '; + memcpy(pos, uninfo.machine, strlen(uninfo.machine)); + + return TRUE; +} + +/** + * See header + */ +os_info_t *os_info_create(void) +{ + private_os_info_t *this; + chunk_t name, version; + + /* As an opton OS name and OS version can be configured manually */ + name.ptr = lib->settings->get_str(lib->settings, + "libimcv.os_info.name", NULL); + version.ptr = lib->settings->get_str(lib->settings, + "libimcv.os_info.version", NULL); + if (name.ptr && version.ptr) + { + name.len = strlen(name.ptr); + name = chunk_clone(name); + + version.len = strlen(version.ptr); + version = chunk_clone(version); + } + else + { + if (!extract_platform_info(&name, &version)) + { + return NULL; + } + } + DBG1(DBG_IMC, "operating system name is '%.*s'", + name.len, name.ptr); + DBG1(DBG_IMC, "operating system version is '%.*s'", + version.len, version.ptr); + + INIT(this, + .public = { + .get_name = _get_name, + .get_version = _get_version, + .create_package_enumerator = _create_package_enumerator, + .destroy = _destroy, + }, + .name = name, + .version = version, + ); + + return &this->public; +} diff --git a/src/libimcv/os_info/os_info.h b/src/libimcv/os_info/os_info.h new file mode 100644 index 000000000..78d0509f4 --- /dev/null +++ b/src/libimcv/os_info/os_info.h @@ -0,0 +1,65 @@ +/* + * 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 os_info os_info + * @{ @ingroup libimcv + */ + +#ifndef OS_INFO_H_ +#define OS_INFO_H_ + +typedef struct os_info_t os_info_t; + +#include <library.h> + +/** + * Interface for the Operating System (OS) information module + */ +struct os_info_t { + + /** + * Get the OS product name or distribution + * + * @return OS name + */ + chunk_t (*get_name)(os_info_t *this); + + /** + * Get the OS version or release + * + * @return OS version + */ + chunk_t (*get_version)(os_info_t *this); + + /** + * Enumerates over all installed packages + * + * @return return package enumerator + */ + enumerator_t* (*create_package_enumerator)(os_info_t *this); + + /** + * Destroys an os_info_t object. + */ + void (*destroy)(os_info_t *this); +}; + +/** + * Create an os_info_t object + */ +os_info_t* os_info_create(void); + +#endif /** OS_INFO_H_ @}*/ diff --git a/src/libimcv/plugins/imc_os/imc_os.c b/src/libimcv/plugins/imc_os/imc_os.c index be6fb36ac..a397dfa5f 100644 --- a/src/libimcv/plugins/imc_os/imc_os.c +++ b/src/libimcv/plugins/imc_os/imc_os.c @@ -24,6 +24,7 @@ #include <ietf/ietf_attr_pa_tnc_error.h> #include <ietf/ietf_attr_product_info.h> #include <ietf/ietf_attr_string_version.h> +#include <os_info/os_info.h> #include <tncif_pa_subtypes.h> @@ -40,6 +41,7 @@ static const char imc_name[] = "OS"; #define IMC_SUBTYPE PA_SUBTYPE_IETF_OPERATING_SYSTEM static imc_agent_t *imc_os; +static os_info_t *os; /** * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3 @@ -60,6 +62,16 @@ TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id, { return TNC_RESULT_FATAL; } + + os = os_info_create(); + if (!os) + { + imc_os->destroy(imc_os); + imc_os = NULL; + + return TNC_RESULT_FATAL; + } + if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1) { DBG1(DBG_IMC, "no common IF-IMC version"); @@ -110,9 +122,8 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id, static void add_product_info(linked_list_t *attr_list) { pa_tnc_attr_t *attr; - char *os_name = "Ubuntu"; - attr = ietf_attr_product_info_create(PEN_IETF, 0, os_name); + attr = ietf_attr_product_info_create(PEN_IETF, 0, os->get_name(os)); attr_list->insert_last(attr_list, attr); } @@ -122,9 +133,9 @@ static void add_product_info(linked_list_t *attr_list) static void add_string_version(linked_list_t *attr_list) { pa_tnc_attr_t *attr; - chunk_t os_version = { "12.04", 5}; - attr = ietf_attr_string_version_create(os_version, chunk_empty, chunk_empty); + attr = ietf_attr_string_version_create(os->get_version(os), + chunk_empty, chunk_empty); attr_list->insert_last(attr_list, attr); } @@ -362,6 +373,9 @@ TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id) imc_os->destroy(imc_os); imc_os = NULL; + os->destroy(os); + os = NULL; + return TNC_RESULT_SUCCESS; } diff --git a/src/libimcv/plugins/imv_os/imv_os.c b/src/libimcv/plugins/imv_os/imv_os.c index c4e673719..52dcff024 100644 --- a/src/libimcv/plugins/imv_os/imv_os.c +++ b/src/libimcv/plugins/imv_os/imv_os.c @@ -112,7 +112,7 @@ static TNC_Result receive_message(TNC_IMVID imv_id, imv_os_state_t *os_state; enumerator_t *enumerator; TNC_Result result; - char *os_name = NULL; + chunk_t os_name = chunk_empty; chunk_t os_version = chunk_empty; bool fatal_error, assessment = FALSE; @@ -161,7 +161,8 @@ static TNC_Result receive_message(TNC_IMVID imv_id, attr_cast = (ietf_attr_product_info_t*)attr; os_name = attr_cast->get_info(attr_cast, NULL, NULL); - DBG1(DBG_IMV, "operating system name is '%s'", os_name); + DBG1(DBG_IMV, "operating system name is '%.*s'", + os_name.len, os_name.ptr); break; } case IETF_ATTR_STRING_VERSION: @@ -204,15 +205,30 @@ static TNC_Result receive_message(TNC_IMVID imv_id, } enumerator->destroy(enumerator); - if (os_name && os_version.len) + if (os_name.len && os_version.len) { + char *product_info; + os_state->set_info(os_state, os_name, os_version); + product_info = os_state->get_info(os_state); - DBG1(DBG_IMV, "requesting installed packages for '%s'", - os_state->get_info(os_state)); - attr = ietf_attr_attr_request_create(PEN_IETF, - IETF_ATTR_INSTALLED_PACKAGES); - attr_list->insert_last(attr_list, attr); + if (streq(product_info, "Windows 1.2.3")) + { + DBG1(DBG_IMV, "OS '%s' is not supported", product_info); + + state->set_recommendation(state, + TNC_IMV_ACTION_RECOMMENDATION_ISOLATE, + TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR); + assessment = TRUE; + } + else + { + DBG1(DBG_IMV, "requesting installed packages for '%s'", + product_info); + attr = ietf_attr_attr_request_create(PEN_IETF, + IETF_ATTR_INSTALLED_PACKAGES); + attr_list->insert_last(attr_list, attr); + } } pa_tnc_msg->destroy(pa_tnc_msg); diff --git a/src/libimcv/plugins/imv_os/imv_os_state.c b/src/libimcv/plugins/imv_os/imv_os_state.c index 65160b45e..1c5c78106 100644 --- a/src/libimcv/plugins/imv_os/imv_os_state.c +++ b/src/libimcv/plugins/imv_os/imv_os_state.c @@ -164,14 +164,15 @@ METHOD(imv_state_t, destroy, void, } METHOD(imv_os_state_t, set_info, void, - private_imv_os_state_t *this, char *name, chunk_t version) + private_imv_os_state_t *this, chunk_t name, chunk_t version) { - int len = strlen(name) + 1 + version.len + 1; + int len = name.len + 1 + version.len + 1; /* OS info is a concatenation of OS name and OS version */ free(this->info); this->info = malloc(len); - snprintf(this->info, len, "%s %.*s", name, version.len, version.ptr); + snprintf(this->info, len, "%.*s %.*s", name.len, name.ptr, + version.len, version.ptr); } METHOD(imv_os_state_t, get_info, char*, diff --git a/src/libimcv/plugins/imv_os/imv_os_state.h b/src/libimcv/plugins/imv_os/imv_os_state.h index 638219727..2d2069220 100644 --- a/src/libimcv/plugins/imv_os/imv_os_state.h +++ b/src/libimcv/plugins/imv_os/imv_os_state.h @@ -43,7 +43,7 @@ struct imv_os_state_t { * @param name OS name * @param version OS version */ - void (*set_info)(imv_os_state_t *this, char *name, chunk_t version); + void (*set_info)(imv_os_state_t *this, chunk_t name, chunk_t version); /** * Get OS Product Information diff --git a/src/libpts/plugins/imc_attestation/imc_attestation.c b/src/libpts/plugins/imc_attestation/imc_attestation.c index 7cb2a0671..3f13a8e05 100644 --- a/src/libpts/plugins/imc_attestation/imc_attestation.c +++ b/src/libpts/plugins/imc_attestation/imc_attestation.c @@ -22,6 +22,7 @@ #include <ietf/ietf_attr_pa_tnc_error.h> #include <ietf/ietf_attr_product_info.h> #include <ietf/ietf_attr_assess_result.h> +#include <os_info/os_info.h> #include <libpts.h> @@ -44,6 +45,7 @@ static const char imc_name[] = "Attestation"; #define IMC_SUBTYPE PA_SUBTYPE_TCG_PTS static imc_agent_t *imc_attestation; +static os_info_t *os; /** * Supported PTS measurement algorithms @@ -80,6 +82,15 @@ TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id, return TNC_RESULT_FATAL; } + os = os_info_create(); + if (!os) + { + imc_attestation->destroy(imc_attestation); + imc_attestation = NULL; + + return TNC_RESULT_FATAL; + } + libpts_init(); if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1) @@ -135,10 +146,9 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id, TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id, TNC_ConnectionID connection_id) { - imc_state_t *state; - imc_attestation_state_t *attestation_state; - pts_t *pts; - char *platform_info; + linked_list_t *attr_list; + pa_tnc_attr_t *attr; + chunk_t os_name, os_version; TNC_Result result = TNC_RESULT_SUCCESS; if (!imc_attestation) @@ -147,27 +157,15 @@ TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id, return TNC_RESULT_NOT_INITIALIZED; } - /* get current IMC state */ - if (!imc_attestation->get_state(imc_attestation, connection_id, &state)) - { - return TNC_RESULT_FATAL; - } - attestation_state = (imc_attestation_state_t*)state; - pts = attestation_state->get_pts(attestation_state); - - platform_info = pts->get_platform_info(pts); - if (platform_info) - { - linked_list_t *attr_list; - pa_tnc_attr_t *attr; - - attr_list = linked_list_create(); - attr = ietf_attr_product_info_create(0, 0, platform_info); - attr_list->insert_last(attr_list, attr); - result = imc_attestation->send_message(imc_attestation, connection_id, - FALSE, 0, TNC_IMVID_ANY, attr_list); - attr_list->destroy(attr_list); - } + attr_list = linked_list_create(); + attr = ietf_attr_product_info_create(0, 0, os->get_name(os)); + attr_list->insert_last(attr_list, attr); + attr = ietf_attr_string_version_create(os->get_version(os), + chunk_empty, chunk_empty); + attr_list->insert_last(attr_list, attr); + result = imc_attestation->send_message(imc_attestation, connection_id, + FALSE, 0, TNC_IMVID_ANY, attr_list); + attr_list->destroy(attr_list); return result; } @@ -348,6 +346,9 @@ TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id) imc_attestation->destroy(imc_attestation); imc_attestation = NULL; + os->destroy(os); + os = NULL; + return TNC_RESULT_SUCCESS; } diff --git a/src/libpts/plugins/imc_attestation/imc_attestation_state.c b/src/libpts/plugins/imc_attestation/imc_attestation_state.c index 8ebabafa2..23cbd84d8 100644 --- a/src/libpts/plugins/imc_attestation/imc_attestation_state.c +++ b/src/libpts/plugins/imc_attestation/imc_attestation_state.c @@ -212,7 +212,6 @@ METHOD(imc_attestation_state_t, next_evidence, bool, imc_state_t *imc_attestation_state_create(TNC_ConnectionID connection_id) { private_imc_attestation_state_t *this; - char *platform_info; INIT(this, .public = { @@ -240,13 +239,6 @@ imc_state_t *imc_attestation_state_create(TNC_ConnectionID connection_id) .components = linked_list_create(), .list = linked_list_create(), ); - - platform_info = lib->settings->get_str(lib->settings, - "libimcv.plugins.imc-attestation.platform_info", NULL); - if (platform_info) - { - this->pts->set_platform_info(this->pts, platform_info); - } return &this->public.interface; } diff --git a/src/libpts/plugins/imv_attestation/build-database.sh b/src/libpts/plugins/imv_attestation/build-database.sh index a89258e1d..be1024de0 100755 --- a/src/libpts/plugins/imv_attestation/build-database.sh +++ b/src/libpts/plugins/imv_attestation/build-database.sh @@ -1,6 +1,6 @@ #!/bin/sh -p="Ubuntu 12.04.1 LTS i686" +p="Ubuntu 12.04 i686" ipsec attest --add --product "$p" --sha1-ima --dir /sbin ipsec attest --add --product "$p" --sha1-ima --dir /usr/sbin diff --git a/src/libpts/plugins/imv_attestation/data.sql b/src/libpts/plugins/imv_attestation/data.sql index b1646b724..60c312e30 100644 --- a/src/libpts/plugins/imv_attestation/data.sql +++ b/src/libpts/plugins/imv_attestation/data.sql @@ -51,7 +51,7 @@ INSERT INTO products ( INSERT INTO products ( name ) VALUES ( - 'Ubuntu 12.04.1 LTS i686' + 'Ubuntu 12.04 i686' ); /* Files */ diff --git a/src/libpts/plugins/imv_attestation/imv_attestation.c b/src/libpts/plugins/imv_attestation/imv_attestation.c index 201496e8a..6cfff7f5f 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation.c +++ b/src/libpts/plugins/imv_attestation/imv_attestation.c @@ -22,6 +22,7 @@ #include <ietf/ietf_attr.h> #include <ietf/ietf_attr_pa_tnc_error.h> #include <ietf/ietf_attr_product_info.h> +#include <ietf/ietf_attr_string_version.h> #include <libpts.h> @@ -219,6 +220,8 @@ static TNC_Result receive_message(TNC_IMVID imv_id, imv_state_t *state; imv_attestation_state_t *attestation_state; pts_t *pts; + chunk_t os_name = chunk_empty; + chunk_t os_version = chunk_empty; enumerator_t *enumerator; TNC_Result result; @@ -228,7 +231,7 @@ static TNC_Result receive_message(TNC_IMVID imv_id, return TNC_RESULT_NOT_INITIALIZED; } - /* get current IMV state */ + /* get current IMV state */ if (!imv_attestation->get_state(imv_attestation, connection_id, &state)) { return TNC_RESULT_FATAL; @@ -260,34 +263,47 @@ static TNC_Result receive_message(TNC_IMVID imv_id, if (type.vendor_id == PEN_IETF) { - if (type.type == IETF_ATTR_PA_TNC_ERROR) + switch (type.type) { - ietf_attr_pa_tnc_error_t *error_attr; - pen_type_t error_code; - chunk_t msg_info; + case IETF_ATTR_PA_TNC_ERROR: + { + ietf_attr_pa_tnc_error_t *error_attr; + pen_type_t error_code; + chunk_t msg_info; - error_attr = (ietf_attr_pa_tnc_error_t*)attr; - error_code = error_attr->get_error_code(error_attr); + error_attr = (ietf_attr_pa_tnc_error_t*)attr; + error_code = error_attr->get_error_code(error_attr); - if (error_code.vendor_id == PEN_TCG) - { - msg_info = error_attr->get_msg_info(error_attr); + if (error_code.vendor_id == PEN_TCG) + { + msg_info = error_attr->get_msg_info(error_attr); - DBG1(DBG_IMV, "received TCG-PTS error '%N'", - pts_error_code_names, error_code.type); - DBG1(DBG_IMV, "error information: %B", &msg_info); + DBG1(DBG_IMV, "received TCG-PTS error '%N'", + pts_error_code_names, error_code.type); + DBG1(DBG_IMV, "error information: %B", &msg_info); - result = TNC_RESULT_FATAL; + result = TNC_RESULT_FATAL; + } + break; } - } - else if (type.type == IETF_ATTR_PRODUCT_INFORMATION) - { - ietf_attr_product_info_t *attr_cast; - char *platform_info; + case IETF_ATTR_PRODUCT_INFORMATION: + { + ietf_attr_product_info_t *attr_cast; - attr_cast = (ietf_attr_product_info_t*)attr; - platform_info = attr_cast->get_info(attr_cast, NULL, NULL); - pts->set_platform_info(pts, platform_info); + attr_cast = (ietf_attr_product_info_t*)attr; + os_name = attr_cast->get_info(attr_cast, NULL, NULL); + 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); + break; + } + default: + break; } } else if (type.vendor_id == PEN_TCG) @@ -301,6 +317,11 @@ static TNC_Result receive_message(TNC_IMVID imv_id, } } enumerator->destroy(enumerator); + + if (os_name.len && os_version.len) + { + pts->set_platform_info(pts, os_name, os_version); + } pa_tnc_msg->destroy(pa_tnc_msg); if (result != TNC_RESULT_SUCCESS) diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_state.c b/src/libpts/plugins/imv_attestation/imv_attestation_state.c index 1dbc88309..aa91bf215 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation_state.c +++ b/src/libpts/plugins/imv_attestation/imv_attestation_state.c @@ -436,7 +436,6 @@ METHOD(imv_attestation_state_t, components_finalized, bool, imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id) { private_imv_attestation_state_t *this; - char *platform_info; INIT(this, .public = { @@ -476,12 +475,5 @@ imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id) .pts = pts_create(FALSE), ); - platform_info = lib->settings->get_str(lib->settings, - "libimcv.plugins.imv-attestation.platform_info", NULL); - if (platform_info) - { - this->pts->set_platform_info(this->pts, platform_info); - } - return &this->public.interface; } diff --git a/src/libpts/pts/pts.c b/src/libpts/pts/pts.c index 4c6c5bc22..7d5c7b942 100644 --- a/src/libpts/pts/pts.c +++ b/src/libpts/pts/pts.c @@ -314,10 +314,15 @@ METHOD(pts_t, get_platform_info, char*, } METHOD(pts_t, set_platform_info, void, - private_pts_t *this, char *info) + private_pts_t *this, chunk_t name, chunk_t version) { + int len = name.len + 1 + version.len + 1; + + /* platform info is a concatenation of OS name and OS version */ free(this->platform_info); - this->platform_info = strdup(info); + this->platform_info = malloc(len); + snprintf(this->platform_info, len, "%.*s %.*s", name.len, name.ptr, + version.len, version.ptr); } METHOD(pts_t, get_tpm_version_info, bool, @@ -1047,122 +1052,6 @@ METHOD(pts_t, destroy, void, free(this); } -#define RELEASE_LSB 0 -#define RELEASE_DEBIAN 1 - -/** - * Determine Linux distribution and hardware platform - */ -static char* extract_platform_info(void) -{ - FILE *file; - char buf[BUF_LEN], *pos = buf, *value = NULL; - int i, len = BUF_LEN - 1; - struct utsname uninfo; - - /* Linux/Unix distribution release info (from http://linuxmafia.com) */ - const char* releases[] = { - "/etc/lsb-release", "/etc/debian_version", - "/etc/SuSE-release", "/etc/novell-release", - "/etc/sles-release", "/etc/redhat-release", - "/etc/fedora-release", "/etc/gentoo-release", - "/etc/slackware-version", "/etc/annvix-release", - "/etc/arch-release", "/etc/arklinux-release", - "/etc/aurox-release", "/etc/blackcat-release", - "/etc/cobalt-release", "/etc/conectiva-release", - "/etc/debian_release", "/etc/immunix-release", - "/etc/lfs-release", "/etc/linuxppc-release", - "/etc/mandrake-release", "/etc/mandriva-release", - "/etc/mandrakelinux-release", "/etc/mklinux-release", - "/etc/pld-release", "/etc/redhat_version", - "/etc/slackware-release", "/etc/e-smith-release", - "/etc/release", "/etc/sun-release", - "/etc/tinysofa-release", "/etc/turbolinux-release", - "/etc/ultrapenguin-release", "/etc/UnitedLinux-release", - "/etc/va-release", "/etc/yellowdog-release" - }; - - const char description[] = "DISTRIB_DESCRIPTION=\""; - const char str_debian[] = "Debian "; - - for (i = 0; i < countof(releases); i++) - { - file = fopen(releases[i], "r"); - if (!file) - { - continue; - } - - if (i == RELEASE_DEBIAN) - { - strcpy(buf, str_debian); - pos += strlen(str_debian); - len -= strlen(str_debian); - } - - fseek(file, 0, SEEK_END); - len = min(ftell(file), len); - rewind(file); - pos[len] = '\0'; - if (fread(pos, 1, len, file) != len) - { - DBG1(DBG_PTS, "failed to read file '%s'", releases[i]); - fclose(file); - return NULL; - } - fclose(file); - - if (i == RELEASE_LSB) - { - pos = strstr(buf, description); - if (!pos) - { - DBG1(DBG_PTS, "failed to find begin of lsb-release " - "DESCRIPTION field"); - return NULL; - } - value = pos + strlen(description); - pos = strchr(value, '"'); - if (!pos) - { - DBG1(DBG_PTS, "failed to find end of lsb-release " - "DESCRIPTION field"); - return NULL; - } - } - else - { - value = buf; - pos = strchr(pos, '\n'); - if (!pos) - { - DBG1(DBG_PTS, "failed to find end of release string"); - return NULL; - } - } - break; - } - - if (!value) - { - DBG1(DBG_PTS, "no distribution release file found"); - return NULL; - } - - if (uname(&uninfo) < 0) - { - DBG1(DBG_PTS, "could not retrieve machine architecture"); - return NULL; - } - - *pos++ = ' '; - len = sizeof(buf)-1 + (pos - buf); - strncpy(pos, uninfo.machine, len); - - DBG1(DBG_PTS, "platform is '%s'", value); - return strdup(value); -} - /** * Check for a TPM by querying for TPM Version Info */ @@ -1264,8 +1153,6 @@ pts_t *pts_create(bool is_imc) if (is_imc) { - this->platform_info = extract_platform_info(); - if (has_tpm(this)) { this->has_tpm = TRUE; diff --git a/src/libpts/pts/pts.h b/src/libpts/pts/pts.h index 5f88cd15c..aad73c4b6 100644 --- a/src/libpts/pts/pts.h +++ b/src/libpts/pts/pts.h @@ -171,9 +171,10 @@ struct pts_t { /** * Set Platform and OS Info * - * @param info Platform and OS info + * @param name OS name + * @param version OS version */ - void (*set_platform_info)(pts_t *this, char *info); + void (*set_platform_info)(pts_t *this, chunk_t name, chunk_t version); /** * Get TPM 1.2 Version Info |