aboutsummaryrefslogtreecommitdiffstats
path: root/src/libimcv
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 /src/libimcv
parent7f3bf2b12f81e85c9a0a66c6bcc5c2b44db66b49 (diff)
downloadstrongswan-6ab1502519025e2bd05d01d49fe3d0f1ce8d6bd6.tar.bz2
strongswan-6ab1502519025e2bd05d01d49fe3d0f1ce8d6bd6.tar.xz
implemented os_info_t class
Diffstat (limited to 'src/libimcv')
-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
9 files changed, 432 insertions, 32 deletions
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