implemented os_info_t class
authorAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 10 Oct 2012 19:54:05 +0000 (21:54 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 10 Oct 2012 19:54:21 +0000 (21:54 +0200)
18 files changed:
man/strongswan.conf.5.in
src/libimcv/Makefile.am
src/libimcv/ietf/ietf_attr_product_info.c
src/libimcv/ietf/ietf_attr_product_info.h
src/libimcv/os_info/os_info.c [new file with mode: 0644]
src/libimcv/os_info/os_info.h [new file with mode: 0644]
src/libimcv/plugins/imc_os/imc_os.c
src/libimcv/plugins/imv_os/imv_os.c
src/libimcv/plugins/imv_os/imv_os_state.c
src/libimcv/plugins/imv_os/imv_os_state.h
src/libpts/plugins/imc_attestation/imc_attestation.c
src/libpts/plugins/imc_attestation/imc_attestation_state.c
src/libpts/plugins/imv_attestation/build-database.sh
src/libpts/plugins/imv_attestation/data.sql
src/libpts/plugins/imv_attestation/imv_attestation.c
src/libpts/plugins/imv_attestation/imv_attestation_state.c
src/libpts/pts/pts.c
src/libpts/pts/pts.h

index 217d7d7..f7233c9 100644 (file)
@@ -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
index 87e8347..d99ac15 100644 (file)
@@ -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
index 91bea81..719619f 100644 (file)
@@ -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,
        );
 
index f1dfc3e..dfaa67d 100644 (file)
@@ -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 (file)
index 0000000..4dbcee5
--- /dev/null
@@ -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 (file)
index 0000000..78d0509
--- /dev/null
@@ -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_ @}*/
index be6fb36..a397dfa 100644 (file)
@@ -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;
 }
 
index c4e6737..52dcff0 100644 (file)
@@ -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);
 
index 65160b4..1c5c781 100644 (file)
@@ -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*,
index 6382197..2d20692 100644 (file)
@@ -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
index 7cb2a06..3f13a8e 100644 (file)
@@ -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;
 }
 
index 8ebabaf..23cbd84 100644 (file)
@@ -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;
 }
index a89258e..be1024d 100755 (executable)
@@ -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
index b1646b7..60c312e 100644 (file)
@@ -51,7 +51,7 @@ INSERT INTO products (
 INSERT INTO products (
   name
 ) VALUES (
- 'Ubuntu 12.04.1 LTS i686'
+ 'Ubuntu 12.04 i686'
 );
 
 /* Files */
index 201496e..6cfff7f 100644 (file)
@@ -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)
index 1dbc883..aa91bf2 100644 (file)
@@ -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;
 }
index 4c6c5bc..7d5c7b9 100644 (file)
@@ -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;
index 5f88cd1..aad73c4 100644 (file)
@@ -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