aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Steffen <andreas.steffen@strongswan.org>2012-10-10 21:54:05 +0200
committerAndreas Steffen <andreas.steffen@strongswan.org>2012-10-10 21:54:21 +0200
commit6ab1502519025e2bd05d01d49fe3d0f1ce8d6bd6 (patch)
treeb851d0b12249cefd3bdbec8efac1e0f8d5c4e175
parent7f3bf2b12f81e85c9a0a66c6bcc5c2b44db66b49 (diff)
downloadstrongswan-6ab1502519025e2bd05d01d49fe3d0f1ce8d6bd6.tar.bz2
strongswan-6ab1502519025e2bd05d01d49fe3d0f1ce8d6bd6.tar.xz
implemented os_info_t class
-rw-r--r--man/strongswan.conf.5.in12
-rw-r--r--src/libimcv/Makefile.am1
-rw-r--r--src/libimcv/ietf/ietf_attr_product_info.c20
-rw-r--r--src/libimcv/ietf/ietf_attr_product_info.h6
-rw-r--r--src/libimcv/os_info/os_info.c309
-rw-r--r--src/libimcv/os_info/os_info.h65
-rw-r--r--src/libimcv/plugins/imc_os/imc_os.c22
-rw-r--r--src/libimcv/plugins/imv_os/imv_os.c32
-rw-r--r--src/libimcv/plugins/imv_os/imv_os_state.c7
-rw-r--r--src/libimcv/plugins/imv_os/imv_os_state.h2
-rw-r--r--src/libpts/plugins/imc_attestation/imc_attestation.c51
-rw-r--r--src/libpts/plugins/imc_attestation/imc_attestation_state.c8
-rwxr-xr-xsrc/libpts/plugins/imv_attestation/build-database.sh2
-rw-r--r--src/libpts/plugins/imv_attestation/data.sql2
-rw-r--r--src/libpts/plugins/imv_attestation/imv_attestation.c65
-rw-r--r--src/libpts/plugins/imv_attestation/imv_attestation_state.c8
-rw-r--r--src/libpts/pts/pts.c127
-rw-r--r--src/libpts/pts/pts.h5
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