From: Andreas Steffen Date: Fri, 4 Apr 2014 21:00:40 +0000 (+0200) Subject: Separated IMV session management from IMV policy database X-Git-Tag: 5.2.0dr1~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4894bfa2279c861b863464418cad66c07bfa13e2;p=thirdparty%2Fstrongswan.git Separated IMV session management from IMV policy database --- diff --git a/src/libimcv/Makefile.am b/src/libimcv/Makefile.am index 96e759724e..3732267ed4 100644 --- a/src/libimcv/Makefile.am +++ b/src/libimcv/Makefile.am @@ -15,14 +15,17 @@ libimcv_la_SOURCES = \ imcv.h imcv.c \ imc/imc_agent.h imc/imc_agent.c imc/imc_state.h \ imc/imc_msg.h imc/imc_msg.c \ + imc/imc_os_info.h imc/imc_os_info.c \ imv/imv_agent.h imv/imv_agent.c imv/imv_state.h \ imv/imv_agent_if.h imv/imv_if.h \ imv/imv_database.h imv/imv_database.c \ imv/imv_msg.h imv/imv_msg.c \ imv/imv_lang_string.h imv/imv_lang_string.c \ + imv/imv_os_info.h imv/imv_os_info.c \ imv/imv_reason_string.h imv/imv_reason_string.c \ imv/imv_remediation_string.h imv/imv_remediation_string.c \ imv/imv_session.h imv/imv_session.c \ + imv/imv_session_manager.h imv/imv_session_manager.c \ imv/imv_workitem.h imv/imv_workitem.c \ ietf/ietf_attr.h ietf/ietf_attr.c \ ietf/ietf_attr_assess_result.h ietf/ietf_attr_assess_result.c \ diff --git a/src/libimcv/imc/imc_os_info.c b/src/libimcv/imc/imc_os_info.c new file mode 100644 index 0000000000..86a7f82e21 --- /dev/null +++ b/src/libimcv/imc/imc_os_info.c @@ -0,0 +1,562 @@ +/* + * Copyright (C) 2012-2014 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "imc_os_info.h" + +#include +#include +#include + +#include +#include + +typedef struct private_imc_os_info_t private_imc_os_info_t; + +/** + * Private data of an imc_os_info_t object. + * + */ +struct private_imc_os_info_t { + + /** + * Public imc_os_info_t interface. + */ + imc_os_info_t public; + + /** + * OS type + */ + os_type_t type; + + /** + * OS name + */ + chunk_t name; + + /** + * OS version + */ + chunk_t version; + +}; + +METHOD(imc_os_info_t, get_type, os_type_t, + private_imc_os_info_t *this) +{ + return this->type; +} + +METHOD(imc_os_info_t, get_name, chunk_t, + private_imc_os_info_t *this) +{ + return this->name; +} + +METHOD(imc_os_info_t, get_numeric_version, void, + private_imc_os_info_t *this, u_int32_t *major, u_int32_t *minor) +{ + u_char *pos; + + if (major) + { + *major = atol(this->version.ptr); + } + pos = memchr(this->version.ptr, '.', this->version.len); + if (minor) + { + *minor = pos ? atol(pos + 1) : 0; + } +} + +METHOD(imc_os_info_t, get_version, chunk_t, + private_imc_os_info_t *this) +{ + return this->version; +} + +METHOD(imc_os_info_t, get_fwd_status, os_fwd_status_t, + private_imc_os_info_t *this) +{ + const char ip_forward[] = "/proc/sys/net/ipv4/ip_forward"; + char buf[2]; + FILE *file; + + os_fwd_status_t fwd_status = OS_FWD_UNKNOWN; + + file = fopen(ip_forward, "r"); + if (file) + { + if (fread(buf, 1, 1, file) == 1) + { + switch (buf[0]) + { + case '0': + fwd_status = OS_FWD_DISABLED; + break; + case '1': + fwd_status = OS_FWD_ENABLED; + break; + default: + DBG1(DBG_IMC, "\"%s\" returns invalid value ", ip_forward); + break; + } + } + else + { + DBG1(DBG_IMC, "could not read from \"%s\"", ip_forward); + } + fclose(file); + } + else + { + DBG1(DBG_IMC, "failed to open \"%s\"", ip_forward); + } + + return fwd_status; +} + +METHOD(imc_os_info_t, get_uptime, time_t, + private_imc_os_info_t *this) +{ + const char proc_uptime[] = "/proc/uptime"; + FILE *file; + u_int uptime; + + file = fopen(proc_uptime, "r"); + if (!file) + { + DBG1(DBG_IMC, "failed to open \"%s\"", proc_uptime); + return 0; + } + if (fscanf(file, "%u", &uptime) != 1) + { + DBG1(DBG_IMC, "failed to read file \"%s\"", proc_uptime); + uptime = 0; + } + fclose(file); + + return uptime; +} + +METHOD(imc_os_info_t, get_setting, chunk_t, + private_imc_os_info_t *this, char *name) +{ + FILE *file; + u_char buf[2048]; + size_t i = 0; + chunk_t value; + + if (!strpfx(name, "/etc/") && !strpfx(name, "/proc/") && + !strpfx(name, "/sys/") && !strpfx(name, "/var/")) + { + /** + * In order to guarantee privacy, only settings from the + * /etc/, /proc/ and /sys/ directories can be retrieved + */ + DBG1(DBG_IMC, "not allowed to access '%s'", name); + + return chunk_empty; + } + + file = fopen(name, "r"); + if (!file) + { + DBG1(DBG_IMC, "failed to open '%s'", name); + + return chunk_empty; + } + while (i < sizeof(buf) && fread(buf + i, 1, 1, file) == 1) + { + i++; + } + fclose(file); + + value = chunk_create(buf, i); + + return chunk_clone(value); +} + +typedef struct { + /** + * implements enumerator_t + */ + enumerator_t public; + + /** + * package info pipe stream + */ + FILE* file; + + /** + * line buffer + */ + u_char line[512]; + +} package_enumerator_t; + +/** + * Implementation of package_enumerator.destroy. + */ +static void package_enumerator_destroy(package_enumerator_t *this) +{ + pclose(this->file); + free(this); +} + +/** + * Implementation of package_enumerator.enumerate + */ +static bool package_enumerator_enumerate(package_enumerator_t *this, ...) +{ + chunk_t *name, *version; + u_char *pos; + va_list args; + + while (TRUE) + { + if (!fgets(this->line, sizeof(this->line), this->file)) + { + return FALSE; + } + + pos = strchr(this->line, '\t'); + if (!pos) + { + return FALSE; + } + *pos++ = '\0'; + + if (!streq(this->line, "install ok installed")) + { + continue; + } + va_start(args, this); + + name = va_arg(args, chunk_t*); + name->ptr = pos; + pos = strchr(pos, '\t'); + if (!pos) + { + va_end(args); + return FALSE; + } + name->len = pos++ - name->ptr; + + version = va_arg(args, chunk_t*); + version->ptr = pos; + version->len = strlen(pos) - 1; + + va_end(args); + return TRUE; + } +} + +METHOD(imc_os_info_t, create_package_enumerator, enumerator_t*, + private_imc_os_info_t *this) +{ + FILE *file; + const char command[] = "dpkg-query --show --showformat=" + "'${Status}\t${Package}\t${Version}\n'"; + package_enumerator_t *enumerator; + + /* Only Debian and Ubuntu package enumeration is currently supported */ + if (this->type != OS_TYPE_DEBIAN && this->type != OS_TYPE_UBUNTU) + { + return NULL; + } + + /* Open a pipe stream for reading the output of the dpkg-query commmand */ + file = popen(command, "r"); + if (!file) + { + DBG1(DBG_IMC, "failed to run dpkg command"); + return NULL; + } + + /* Create a package enumerator instance */ + enumerator = malloc_thing(package_enumerator_t); + enumerator->public.enumerate = (void*)package_enumerator_enumerate; + enumerator->public.destroy = (void*)package_enumerator_destroy; + enumerator->file = file; + + return (enumerator_t*)enumerator; +} + + +METHOD(imc_os_info_t, destroy, void, + private_imc_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(os_type_t *type, chunk_t *name, + chunk_t *version) +{ + FILE *file; + u_char buf[BUF_LEN], *pos = buf; + int len = BUF_LEN - 1; + os_type_t os_type = OS_TYPE_UNKNOWN; + chunk_t os_name = chunk_empty; + chunk_t os_version = chunk_empty; + char *os_str; + 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: + { + os_type = OS_TYPE_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_version.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; + } + + /* Try to find a matching OS type based on the OS name */ + if (os_type == OS_TYPE_UNKNOWN) + { + os_type = os_type_from_name(os_name); + } + + /* If known use the official OS name */ + if (os_type != OS_TYPE_UNKNOWN) + { + os_str = enum_to_name(os_type_names, os_type); + os_name = chunk_create(os_str, strlen(os_str)); + } + + /* copy OS type */ + *type = os_type; + + /* 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 + */ +imc_os_info_t *imc_os_info_create(void) +{ + private_imc_os_info_t *this; + chunk_t name, version; + os_type_t type; + + /* As an option OS name and OS version can be configured manually */ + name.ptr = lib->settings->get_str(lib->settings, + "%s.imcv.imc_os_info.name", NULL, lib->ns); + version.ptr = lib->settings->get_str(lib->settings, + "%s.imcv.imc_os_info.version", NULL, lib->ns); + if (name.ptr && version.ptr) + { + name.len = strlen(name.ptr); + name = chunk_clone(name); + + version.len = strlen(version.ptr); + version = chunk_clone(version); + + type = os_type_from_name(name); + } + else + { + if (!extract_platform_info(&type, &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_type = _get_type, + .get_name = _get_name, + .get_numeric_version = _get_numeric_version, + .get_version = _get_version, + .get_fwd_status = _get_fwd_status, + .get_uptime = _get_uptime, + .get_setting = _get_setting, + .create_package_enumerator = _create_package_enumerator, + .destroy = _destroy, + }, + .type = type, + .name = name, + .version = version, + ); + + return &this->public; +} diff --git a/src/libimcv/imc/imc_os_info.h b/src/libimcv/imc/imc_os_info.h new file mode 100644 index 0000000000..a6db443143 --- /dev/null +++ b/src/libimcv/imc/imc_os_info.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2012-2014 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup imc_os_info imc_os_info + * @{ @ingroup libimcv + */ + +#ifndef IMC_OS_INFO_H_ +#define IMC_OS_INFO_H_ + +typedef struct imc_os_info_t imc_os_info_t; + +#include "os_info/os_info.h" + +#include + +#include + +/** + * Interface for the IMC Operating System (OS) information module + */ +struct imc_os_info_t { + + /** + * Get the OS type if it can be determined + * + * @return OS type + */ + os_type_t (*get_type)(imc_os_info_t *this); + + /** + * Get the OS product name or distribution + * + * @return OS name + */ + chunk_t (*get_name)(imc_os_info_t *this); + + /** + * Get the numeric OS version or release + * + * @param major OS major version number + * @param minor OS minor version number + */ + void (*get_numeric_version)(imc_os_info_t *this, u_int32_t *major, + u_int32_t *minor); + + /** + * Get the OS version or release + * + * @return OS version + */ + chunk_t (*get_version)(imc_os_info_t *this); + + /** + * Get the OS IPv4 forwarding status + * + * @return IP forwarding status + */ + os_fwd_status_t (*get_fwd_status)(imc_os_info_t *this); + + /** + * Get the OS uptime in seconds + * + * @return OS uptime + */ + time_t (*get_uptime)(imc_os_info_t *this); + + /** + * Get an OS setting (restricted to /proc, /sys, and /etc) + * + * @param name name of OS setting + * @return value of OS setting + */ + chunk_t (*get_setting)(imc_os_info_t *this, char *name); + + /** + * Enumerates over all installed packages + * + * @return return package enumerator + */ + enumerator_t* (*create_package_enumerator)(imc_os_info_t *this); + + /** + * Destroys an imc_os_info_t object. + */ + void (*destroy)(imc_os_info_t *this); +}; + +/** + * Create an imc_os_info_t object + */ +imc_os_info_t* imc_os_info_create(void); + +#endif /** IMC_OS_INFO_H_ @}*/ diff --git a/src/libimcv/imcv.c b/src/libimcv/imcv.c index 2a4fd33dfe..86164486b4 100644 --- a/src/libimcv/imcv.c +++ b/src/libimcv/imcv.c @@ -31,6 +31,11 @@ */ pa_tnc_attr_manager_t *imcv_pa_tnc_attributes; +/** + * Global list of IMV sessions + */ +imv_session_manager_t *imcv_sessions; + /** * Global IMV database */ @@ -149,9 +154,12 @@ bool libimcv_init(bool is_imv) imcv_pa_tnc_attributes->add_vendor(imcv_pa_tnc_attributes, PEN_ITA, ita_attr_create_from_data, ita_attr_names); - /* attach global IMV database */ if (is_imv) { + /* instantiate global IMV session manager */ + imcv_sessions = imv_session_manager_create(); + + /* instantiate and attach global IMV database if URI is valid */ uri = lib->settings->get_str(lib->settings, "%s.imcv.database", NULL, lib->ns); script = lib->settings->get_str(lib->settings, @@ -181,6 +189,7 @@ void libimcv_deinit(void) DESTROY_IF(imcv_pa_tnc_attributes); imcv_pa_tnc_attributes = NULL; DESTROY_IF(imcv_db); + DESTROY_IF(imcv_sessions); DBG1(DBG_LIB, "libimcv terminated"); } if (ref_put(&libstrongswan_ref)) diff --git a/src/libimcv/imcv.h b/src/libimcv/imcv.h index 10c66e65a3..7710388036 100644 --- a/src/libimcv/imcv.h +++ b/src/libimcv/imcv.h @@ -36,6 +36,7 @@ #include "pa_tnc/pa_tnc_attr_manager.h" #include "imv/imv_database.h" +#include "imv/imv_session_manager.h" #include @@ -62,4 +63,9 @@ extern pa_tnc_attr_manager_t* imcv_pa_tnc_attributes; */ extern imv_database_t* imcv_db; +/** + * Global IMV session manager + */ +extern imv_session_manager_t* imcv_sessions; + #endif /** IMCV_H_ @}*/ diff --git a/src/libimcv/imv/imv_agent.c b/src/libimcv/imv/imv_agent.c index 435c25a3c2..5fc3f79c6b 100644 --- a/src/libimcv/imv/imv_agent.c +++ b/src/libimcv/imv/imv_agent.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2013 Andreas Steffen + * Copyright (C) 2011-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ struct private_imv_agent_t { /** * number of message types registered by IMV */ - u_int32_t type_count; + uint32_t type_count; /** * ID of IMV as assigned by TNCS @@ -296,10 +296,7 @@ static bool delete_connection(private_imv_agent_t *this, TNC_ConnectionID id) { found = TRUE; session = state->get_session(state); - if (session) - { - imcv_db->remove_session(imcv_db, session); - } + imcv_sessions->remove_session(imcv_sessions, session); state->destroy(state); this->connections->remove_at(this->connections, enumerator); break; @@ -346,7 +343,7 @@ static char* get_str_attribute(private_imv_agent_t *this, TNC_ConnectionID id, /** * Read an UInt32 attribute */ -static u_int32_t get_uint_attribute(private_imv_agent_t *this, TNC_ConnectionID id, +static uint32_t get_uint_attribute(private_imv_agent_t *this, TNC_ConnectionID id, TNC_AttributeID attribute_id) { TNC_UInt32 len; @@ -370,7 +367,7 @@ static linked_list_t* get_identity_attribute(private_imv_agent_t *this, { TNC_UInt32 len; char buf[2048]; - u_int32_t count; + uint32_t count; tncif_identity_t *tnc_id; bio_reader_t *reader; linked_list_t *list; @@ -415,8 +412,8 @@ METHOD(imv_agent_t, create_state, TNC_Result, enumerator_t *enumerator; tncif_identity_t *tnc_id; imv_session_t *session; - u_int32_t max_msg_len; - u_int32_t ar_id_type = TNC_ID_UNKNOWN; + uint32_t max_msg_len; + uint32_t ar_id_type = TNC_ID_UNKNOWN; chunk_t ar_id_value = chunk_empty; conn_id = state->get_connection_id(state); @@ -453,7 +450,7 @@ METHOD(imv_agent_t, create_state, TNC_Result, while (enumerator->enumerate(enumerator, &tnc_id)) { pen_type_t id_type, subject_type, auth_type; - u_int32_t tcg_id_type, tcg_subject_type, tcg_auth_type; + uint32_t tcg_id_type, tcg_subject_type, tcg_auth_type; chunk_t id_value; id_type = tnc_id->get_identity_type(tnc_id); @@ -474,30 +471,21 @@ METHOD(imv_agent_t, create_state, TNC_Result, id_value.len, id_value.ptr, TNC_Authentication_names, tcg_auth_type); + /* keep the first access requestor ID */ if (first) { ar_id_type = tcg_id_type; ar_id_value = id_value; - state->set_ar_id(state, ar_id_type, ar_id_value); first = FALSE; } } enumerator->destroy(enumerator); - if (imcv_db) - { - session = imcv_db->add_session(imcv_db, conn_id, ar_id_type, ar_id_value); - if (session) - { - DBG2(DBG_IMV, " assigned session ID %d", - session->get_session_id(session)); - state->set_session(state, session); - } - else - { - DBG1(DBG_IMV, " no session ID assigned"); - } - } + session = imcv_sessions->add_session(imcv_sessions, conn_id, + ar_id_type, ar_id_value); + state->set_session(state, session); + + /* clean up temporary variables */ ar_identities->destroy_offset(ar_identities, offsetof(tncif_identity_t, destroy)); free(tnccs_p); @@ -505,9 +493,11 @@ METHOD(imv_agent_t, create_state, TNC_Result, free(t_p); free(t_v); + /* insert state in connection list */ this->connection_lock->write_lock(this->connection_lock); this->connections->insert_last(this->connections, state); this->connection_lock->unlock(this->connection_lock); + return TNC_RESULT_SUCCESS; } @@ -800,7 +790,7 @@ METHOD(imv_agent_t, destroy, void, * Described in header. */ imv_agent_t *imv_agent_create(const char *name, - pen_type_t *supported_types, u_int32_t type_count, + pen_type_t *supported_types, uint32_t type_count, TNC_IMVID id, TNC_Version *actual_version) { private_imv_agent_t *this; diff --git a/src/libimcv/imv/imv_agent.h b/src/libimcv/imv/imv_agent.h index d58af260be..47ce770bc2 100644 --- a/src/libimcv/imv/imv_agent.h +++ b/src/libimcv/imv/imv_agent.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2013 Andreas Steffen + * Copyright (C) 2011-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -205,7 +205,7 @@ struct imv_agent_t { * */ imv_agent_t *imv_agent_create(const char *name, - pen_type_t *supported_types, u_int32_t type_count, + pen_type_t *supported_types, uint32_t type_count, TNC_IMVID id, TNC_Version *actual_version); #endif /** IMV_AGENT_H_ @}*/ diff --git a/src/libimcv/imv/imv_database.c b/src/libimcv/imv/imv_database.c index dc7edd7aa8..2edb4df04d 100644 --- a/src/libimcv/imv/imv_database.c +++ b/src/libimcv/imv/imv_database.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Andreas Steffen + * Copyright (C) 2013-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -47,48 +47,28 @@ struct private_imv_database_t { */ char *script; - /** - * Session list - */ - linked_list_t *sessions; - - /** - * mutex used to lock session list - */ - mutex_t *mutex; - }; -METHOD(imv_database_t, add_session, imv_session_t*, - private_imv_database_t *this, TNC_ConnectionID conn_id, - u_int32_t ar_id_type, chunk_t ar_id_value) +METHOD(imv_database_t, get_database, database_t*, + private_imv_database_t *this) { - enumerator_t *enumerator, *e; - imv_session_t *current, *session = NULL; - int ar_id = 0, session_id; - u_int created; - - this->mutex->lock(this->mutex); - - /* check if a session has already been assigned */ - enumerator = this->sessions->create_enumerator(this->sessions); - while (enumerator->enumerate(enumerator, ¤t)) - { - if (conn_id == current->get_connection_id(current)) - { - session = current; - break; - } - } - enumerator->destroy(enumerator); - - /* session already exists */ - if (session) - { - this->mutex->unlock(this->mutex); - return session->get_ref(session); - } + return this->db; +} +/** + * Create a session entry in the IMV database + */ +static bool create_session(private_imv_database_t *this, imv_session_t *session) +{ + enumerator_t *e; + imv_os_info_t *os_info; + chunk_t device_id, ar_id_value; + TNC_ConnectionID conn_id; + uint32_t ar_id_type; + char *product, *device; + int session_id = 0, ar_id = 0, pid = 0, did = 0, trusted = 0, created; + + ar_id_value = session->get_ar_id(session, &ar_id_type); if (ar_id_value.len) { /* get primary key of AR identity if it exists */ @@ -108,46 +88,22 @@ METHOD(imv_database_t, add_session, imv_session_t*, "INSERT INTO identities (type, value) VALUES (?, ?)", DB_INT, ar_id_type, DB_BLOB, ar_id_value); } - } - /* create a new session entry */ - created = time(NULL); - this->db->execute(this->db, &session_id, - "INSERT INTO sessions (time, connection, identity) " - "VALUES (?, ?, ?)", - DB_UINT, created, DB_INT, conn_id, DB_INT, ar_id); - session = imv_session_create(session_id, conn_id); - this->sessions->insert_last(this->sessions, session); - - this->mutex->unlock(this->mutex); - - return session; -} -METHOD(imv_database_t, remove_session, void, - private_imv_database_t *this, imv_session_t *session) -{ - enumerator_t *enumerator; - imv_session_t *current; - - this->mutex->lock(this->mutex); - enumerator = this->sessions->create_enumerator(this->sessions); - while (enumerator->enumerate(enumerator, ¤t)) - { - if (current == session) + if (!ar_id) { - this->sessions->remove_at(this->sessions, enumerator); - break; + DBG1(DBG_IMV, "imv_db: registering access requestor failed"); + return FALSE; } } - enumerator->destroy(enumerator); - this->mutex->unlock(this->mutex); -} -METHOD(imv_database_t, add_product, int, - private_imv_database_t *this, imv_session_t *session, char *product) -{ - enumerator_t *e; - int pid = 0; + /* get product info string */ + os_info = session->get_os_info(session); + product = os_info->get_info(os_info); + if (!product) + { + DBG1(DBG_IMV, "imv_db: product info is not available"); + return FALSE; + } /* get primary key of product info string if it exists */ e = this->db->query(this->db, @@ -164,92 +120,150 @@ METHOD(imv_database_t, add_product, int, this->db->execute(this->db, &pid, "INSERT INTO products (name) VALUES (?)", DB_TEXT, product); } + + if (!pid) + { + DBG1(DBG_IMV, "imv_db: registering product info failed"); + return FALSE; + } - /* add product reference to session */ - if (pid) + /* get device ID string */ + if (!session->get_device_id(session, &device_id)) { - this->db->execute(this->db, NULL, - "UPDATE sessions SET product = ? WHERE id = ?", - DB_INT, pid, DB_INT, session->get_session_id(session)); + DBG1(DBG_IMV, "imv_db: device ID is not available"); + return FALSE; } + device = strndup(device_id.ptr, device_id.len); - return pid; -} - -METHOD(imv_database_t, add_device, int, - private_imv_database_t *this, imv_session_t *session, chunk_t device) -{ - enumerator_t *e; - char *device_str; - int pid = 0, did = 0; - - /* get primary key of product from session */ + /* get primary key of device ID if it exists */ e = this->db->query(this->db, - "SELECT product FROM sessions WHERE id = ?", - DB_INT, session->get_session_id(session), DB_INT); + "SELECT id, trusted FROM devices WHERE value = ? AND product = ?", + DB_TEXT, device, DB_INT, pid, DB_INT, DB_INT); if (e) { - e->enumerate(e, &pid); + e->enumerate(e, &did, &trusted); e->destroy(e); } - /* some IMV policy manager expect a text string */ - device_str = strndup(device.ptr, device.len); - - /* get primary key of device identification if it exists */ - e = this->db->query(this->db, - "SELECT id FROM devices WHERE value = ? AND product = ?", - DB_TEXT, device_str, DB_INT, pid, DB_INT); - if (e) + /* if device ID is trusted, set trust in session */ + if (trusted) { - e->enumerate(e, &did); - e->destroy(e); + session->set_device_trust(session, TRUE); } - /* if device identification has not been found - register it */ + /* if device ID has not been found - register it */ if (!did) { this->db->execute(this->db, &did, "INSERT INTO devices (value, product) VALUES (?, ?)", - DB_TEXT, device_str, DB_INT, pid); + DB_TEXT, device, DB_INT, pid); } - free(device_str); - - /* add device reference to session */ - if (did) + free(device); + + if (!did) + { + DBG1(DBG_IMV, "imv_db: registering device ID failed"); + return FALSE; + } + + /* create a new session entry */ + created = session->get_creation_time(session); + conn_id = session->get_connection_id(session); + this->db->execute(this->db, &session_id, + "INSERT INTO sessions (time, connection, identity, product, device) " + "VALUES (?, ?, ?, ?, ?)", + DB_INT, created, DB_INT, conn_id, DB_INT, ar_id, + DB_INT, pid, DB_INT, did); + + if (session_id) + { + DBG2(DBG_IMV, "assigned session ID %d to Connection ID %d", + session_id, conn_id); + } + else + { + DBG1(DBG_IMV, "imv_db: registering session failed"); + return FALSE; + } + session->set_session_id(session, session_id, pid, did); + + return TRUE; +} + +static bool add_workitems(private_imv_database_t *this, imv_session_t *session) +{ + char *arg_str; + int id, arg_int, rec_fail, rec_noresult; + imv_workitem_t *workitem; + imv_workitem_type_t type; + enumerator_t *e; + + e = this->db->query(this->db, + "SELECT id, type, arg_str, arg_int, rec_fail, rec_noresult " + "FROM workitems WHERE session = ?", + DB_INT, session->get_session_id(session, NULL, NULL), + DB_INT, DB_INT, DB_TEXT, DB_INT,DB_INT, DB_INT); + if (!e) { - this->db->execute(this->db, NULL, - "UPDATE sessions SET device = ? WHERE id = ?", - DB_INT, did, DB_INT, session->get_session_id(session)); + DBG1(DBG_IMV, "imv_db: no workitem enumerator returned"); + return FALSE; + } + while (e->enumerate(e, &id, &type, &arg_str, &arg_int, &rec_fail, + &rec_noresult)) + { + DBG2(DBG_IMV, "%N workitem %d", imv_workitem_type_names, type, id); + workitem = imv_workitem_create(id, type, arg_str, arg_int, rec_fail, + rec_noresult); + session->insert_workitem(session, workitem); } + e->destroy(e); - return did; + return TRUE; } METHOD(imv_database_t, add_recommendation, void, private_imv_database_t *this, imv_session_t *session, TNC_IMV_Action_Recommendation rec) { - /* add final recommendation to session */ + /* add final recommendation to session DB entry */ this->db->execute(this->db, NULL, "UPDATE sessions SET rec = ? WHERE id = ?", - DB_INT, rec, DB_INT, session->get_session_id(session)); + DB_INT, rec, DB_INT, session->get_session_id(session, NULL, NULL)); } METHOD(imv_database_t, policy_script, bool, private_imv_database_t *this, imv_session_t *session, bool start) { - imv_workitem_t *workitem; - imv_workitem_type_t type; - int id, session_id, arg_int, rec_fail, rec_noresult; - enumerator_t *e; - char command[512], resp[128], *last, *arg_str; + char command[512], resp[128], *last; FILE *shell; - session_id = session->get_session_id(session); + if (start) + { + if (session->get_policy_started(session)) + { + DBG1(DBG_IMV, "policy script as already been started"); + return FALSE; + } + /* add product info and device ID to session DB entry */ + if (!create_session(this, session)) + { + return FALSE; + } + } + else + { + if (!session->get_policy_started(session)) + { + DBG1(DBG_IMV, "policy script as already been stopped"); + return FALSE; + } + } + + /* call the policy script */ snprintf(command, sizeof(command), "2>&1 TNC_SESSION_ID='%d' %s %s", - session_id, this->script, start ? "start" : "stop"); + session->get_session_id(session, NULL, NULL), this->script, + start ? "start" : "stop"); DBG3(DBG_IMV, "running policy script: %s", command); shell = popen(command, "r"); @@ -282,30 +296,16 @@ METHOD(imv_database_t, policy_script, bool, } pclose(shell); - if (start && !session->get_policy_started(session)) + if (start) { - /* get workitem list generated by policy manager */ - e = this->db->query(this->db, - "SELECT id, type, arg_str, arg_int, rec_fail, rec_noresult " - "FROM workitems WHERE session = ?", DB_INT, session_id, - DB_INT, DB_INT, DB_TEXT, DB_INT,DB_INT, DB_INT); - if (!e) + /* add workitem list generated by policy manager to session object */ + if (!add_workitems(this, session)) { - DBG1(DBG_IMV, "no workitem enumerator returned"); return FALSE; } - while (e->enumerate(e, &id, &type, &arg_str, &arg_int, &rec_fail, - &rec_noresult)) - { - workitem = imv_workitem_create(id, type, arg_str, arg_int, rec_fail, - rec_noresult); - session->insert_workitem(session, workitem); - } - e->destroy(e); - session->set_policy_started(session, TRUE); } - else if (!start && session->get_policy_started(session)) + else { session->set_policy_started(session, FALSE); } @@ -327,19 +327,10 @@ METHOD(imv_database_t, finalize_workitem, bool, DB_INT, workitem->get_id(workitem)) == 1; } -METHOD(imv_database_t, get_database, database_t*, - private_imv_database_t *this) -{ - return this->db; -} - METHOD(imv_database_t, destroy, void, private_imv_database_t *this) { DESTROY_IF(this->db); - this->sessions->destroy_offset(this->sessions, - offsetof(imv_session_t, destroy)); - this->mutex->destroy(this->mutex); free(this); } @@ -352,20 +343,14 @@ imv_database_t *imv_database_create(char *uri, char *script) INIT(this, .public = { - .add_session = _add_session, - .remove_session = _remove_session, - .add_product = _add_product, - .add_device = _add_device, - .add_recommendation = _add_recommendation, + .get_database = _get_database, .policy_script = _policy_script, .finalize_workitem = _finalize_workitem, - .get_database = _get_database, + .add_recommendation = _add_recommendation, .destroy = _destroy, }, .db = lib->db->create(lib->db, uri), .script = script, - .sessions = linked_list_create(), - .mutex = mutex_create(MUTEX_TYPE_DEFAULT), ); if (!this->db) diff --git a/src/libimcv/imv/imv_database.h b/src/libimcv/imv/imv_database.h index 48a3ded9e7..79551cc79c 100644 --- a/src/libimcv/imv/imv_database.h +++ b/src/libimcv/imv/imv_database.h @@ -55,26 +55,6 @@ struct imv_database_t { */ void (*remove_session)(imv_database_t *this, imv_session_t *session); - /** - * Add product information string to a session database entry - * - * @param session Session - * @param product Product information string - * @return Product ID - */ - int (*add_product)(imv_database_t *this, imv_session_t *session, - char *product); - - /** - * Add device identification to a session database entry - * - * @param session Session - * @param device Device identification - * @return Device ID - */ - int (*add_device)(imv_database_t *this, imv_session_t *session, - chunk_t device); - /** * Add final recommendation to a session database entry * diff --git a/src/libimcv/imv/imv_os_info.c b/src/libimcv/imv/imv_os_info.c new file mode 100644 index 0000000000..dfab194349 --- /dev/null +++ b/src/libimcv/imv/imv_os_info.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2014 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "imv_os_info.h" + +typedef struct private_imv_os_info_t private_imv_os_info_t; + +/** + * Private data of an imv_os_info_t object. + * + */ +struct private_imv_os_info_t { + + /** + * Public imv_os_info_t interface. + */ + imv_os_info_t public; + + /** + * OS type + */ + os_type_t type; + + /** + * OS name + */ + chunk_t name; + + /** + * OS version + */ + chunk_t version; + + /** + * This flag allows the OS version to be empty + */ + bool version_is_set; + + /** + * OS Product Information (OS Name | OS Version) + */ + char *info; + +}; + +METHOD(imv_os_info_t, get_type, os_type_t, + private_imv_os_info_t *this) +{ + return this->type; +} + +METHOD(imv_os_info_t, set_name, void, + private_imv_os_info_t *this, chunk_t name) +{ + /* Has the OS name already been set? */ + if (this->name.len) + { + if (chunk_equals(name, this->name)) + { + return; + } + free(this->name.ptr); + + /* Also clear the OS info string */ + free(this->info); + this->info = NULL; + } + this->name = chunk_clone(name); + this->type = os_type_from_name(name); +} + +METHOD(imv_os_info_t, get_name, chunk_t, + private_imv_os_info_t *this) +{ + return this->name; +} + +METHOD(imv_os_info_t, set_version, void, + private_imv_os_info_t *this, chunk_t version) +{ + /* Has the OS version already been set? */ + if (this->version_is_set) + { + if (chunk_equals(version, this->version)) + { + return; + } + free(this->version.ptr); + + /* Also clear the OS info string */ + free(this->info); + this->info = NULL; + } + this->version = chunk_clone(version); + this->version_is_set = TRUE; +} + +METHOD(imv_os_info_t, get_version, chunk_t, + private_imv_os_info_t *this) +{ + return this->version; +} + +METHOD(imv_os_info_t, get_info, char*, + private_imv_os_info_t *this) +{ + int len; + + if (!this->info) + { + /* Have both OS name and OS version been set? */ + if (this->name.len == 0 || !this->version_is_set) + { + return NULL; + } + + /* OS info is a concatenation of OS name and OS version */ + len = this->name.len + 1 + this->version.len + 1; + this->info = malloc(len); + snprintf(this->info, len, "%.*s %.*s", + (int)this->name.len, this->name.ptr, + (int)this->version.len, this->version.ptr); + } + return this->info; +} + +METHOD(imv_os_info_t, destroy, void, + private_imv_os_info_t *this) +{ + free(this->name.ptr); + free(this->version.ptr); + free(this->info); + free(this); +} + +/** + * See header + */ +imv_os_info_t *imv_os_info_create(void) +{ + private_imv_os_info_t *this; + + INIT(this, + .public = { + .get_type = _get_type, + .set_name = _set_name, + .get_name = _get_name, + .set_version = _set_version, + .get_version = _get_version, + .get_info = _get_info, + .destroy = _destroy, + }, + ); + + return &this->public; +} diff --git a/src/libimcv/imv/imv_os_info.h b/src/libimcv/imv/imv_os_info.h new file mode 100644 index 0000000000..b68a17ee75 --- /dev/null +++ b/src/libimcv/imv/imv_os_info.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2014 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup imv_os_info imv_os_info + * @{ @ingroup libimcv + */ + +#ifndef IMV_OS_INFO_H_ +#define IMV_OS_INFO_H_ + +typedef struct imv_os_info_t imv_os_info_t; + +#include "os_info/os_info.h" + +#include + +/** + * Interface for the IMV Operating System (OS) information module + */ +struct imv_os_info_t { + + /** + * Get the OS type + * + * @return OS type + */ + os_type_t (*get_type)(imv_os_info_t *this); + + /** + * Set the OS product name or distribution + * + * @param name OS name + */ + void (*set_name)(imv_os_info_t *this, chunk_t name); + + /** + * Get the OS product name or distribution + * + * @return OS name + */ + chunk_t (*get_name)(imv_os_info_t *this); + + /** + * Set the OS version or release + * + * @param version OS version + */ + void (*set_version)(imv_os_info_t *this, chunk_t version); + + /** + * Get the OS version or release + * + * @return OS version + */ + chunk_t (*get_version)(imv_os_info_t *this); + + /** + * Get the OS version or release + * + * @return OS name | OS version + */ + char* (*get_info)(imv_os_info_t *this); + + /** + * Destroys an imv_os_info_t object. + */ + void (*destroy)(imv_os_info_t *this); +}; + +/** + * Create an imv_os_info_t object + */ +imv_os_info_t* imv_os_info_create(void); + +#endif /** IMV_OS_INFO_H_ @}*/ diff --git a/src/libimcv/imv/imv_session.c b/src/libimcv/imv/imv_session.c index 754f1f74c6..14fea2b18a 100644 --- a/src/libimcv/imv/imv_session.c +++ b/src/libimcv/imv/imv_session.c @@ -34,11 +34,51 @@ struct private_imv_session_t { */ int session_id; + /** + * Unique Product ID + */ + int pid; + + /** + * Unique Device ID + */ + int did; + /** * TNCCS connection ID */ TNC_ConnectionID conn_id; + /** + * Session creation time + */ + time_t created; + + /** + * Access Requestor ID type + */ + uint32_t ar_id_type; + + /** + * Access Requestor ID value + */ + chunk_t ar_id_value; + + /** + * OS information + */ + imv_os_info_t *os_info; + + /** + * Device ID + */ + chunk_t device_id; + + /** + * Is Device ID trusted? + */ + bool trusted; + /** * Have the workitems been generated? */ @@ -56,9 +96,25 @@ struct private_imv_session_t { }; +METHOD(imv_session_t, set_session_id, void, + private_imv_session_t *this, int session_id, int pid, int did) +{ + this->session_id = session_id; + this->pid = pid; + this->did = did; +} + METHOD(imv_session_t, get_session_id, int, - private_imv_session_t *this) + private_imv_session_t *this, int *pid, int *did) { + if (pid) + { + *pid = this->pid; + } + if (did) + { + *did = this->did; + } return this->session_id; } @@ -68,6 +124,72 @@ METHOD(imv_session_t, get_connection_id, TNC_ConnectionID, return this->conn_id; } +METHOD(imv_session_t, get_creation_time, time_t, + private_imv_session_t *this) +{ + return this->created; +} + +METHOD(imv_session_t, get_ar_id, chunk_t, + private_imv_session_t *this, uint32_t *ar_id_type) +{ + if (ar_id_type) + { + *ar_id_type = this->ar_id_type; + } + return this->ar_id_value; +} + +METHOD(imv_session_t, get_os_info, imv_os_info_t*, + private_imv_session_t *this) +{ + return this->os_info; +} + +METHOD(imv_session_t, set_device_id, void, + private_imv_session_t *this, chunk_t device_id) +{ + if (device_id.len == 0) + { + device_id = chunk_from_str("unknown"); + } + if (this->device_id.len) + { + if (chunk_equals(device_id, this->device_id)) + { + return; + } + free(this->device_id.ptr); + } + this->device_id = chunk_clone(device_id); +} + +METHOD(imv_session_t, get_device_id, bool, + private_imv_session_t *this, chunk_t *device_id) +{ + if (this->device_id.len == 0) + { + return FALSE; + } + if (device_id) + { + *device_id = this->device_id; + } + return TRUE; +} + +METHOD(imv_session_t, set_device_trust, void, + private_imv_session_t *this, bool trusted) +{ + this->trusted = trusted; +} + +METHOD(imv_session_t, get_device_trust, bool, + private_imv_session_t *this) +{ + return this->trusted; +} + METHOD(imv_session_t, set_policy_started, void, private_imv_session_t *this, bool start) { @@ -137,6 +259,9 @@ METHOD(imv_session_t, destroy, void, { this->workitems->destroy_offset(this->workitems, offsetof(imv_workitem_t, destroy)); + this->os_info->destroy(this->os_info); + free(this->ar_id_value.ptr); + free(this->device_id.ptr); free(this); } } @@ -144,14 +269,23 @@ METHOD(imv_session_t, destroy, void, /** * See header */ -imv_session_t *imv_session_create(int session_id, TNC_ConnectionID conn_id) +imv_session_t *imv_session_create(TNC_ConnectionID conn_id, time_t created, + uint32_t ar_id_type, chunk_t ar_id_value) { private_imv_session_t *this; INIT(this, .public = { + .set_session_id = _set_session_id, .get_session_id = _get_session_id, .get_connection_id = _get_connection_id, + .get_creation_time = _get_creation_time, + .get_ar_id = _get_ar_id, + .get_os_info = _get_os_info, + .set_device_id = _set_device_id, + .get_device_id = _get_device_id, + .set_device_trust = _set_device_trust, + .get_device_trust = _get_device_trust, .set_policy_started = _set_policy_started, .get_policy_started = _get_policy_started, .insert_workitem = _insert_workitem, @@ -161,8 +295,11 @@ imv_session_t *imv_session_create(int session_id, TNC_ConnectionID conn_id) .get_ref = _get_ref, .destroy = _destroy, }, - .session_id = session_id, .conn_id = conn_id, + .created = created, + .ar_id_type = ar_id_type, + .ar_id_value = chunk_clone(ar_id_value), + .os_info = imv_os_info_create(), .workitems = linked_list_create(), .ref = 1, ); diff --git a/src/libimcv/imv/imv_session.h b/src/libimcv/imv/imv_session.h index 6b94523b8b..42b9118a6e 100644 --- a/src/libimcv/imv/imv_session.h +++ b/src/libimcv/imv/imv_session.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Andreas Steffen + * Copyright (C) 2013-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -23,11 +23,13 @@ #define IMV_SESSION_H_ #include "imv_workitem.h" +#include "imv_os_info.h" #include - #include +#include + typedef struct imv_session_t imv_session_t; /** @@ -35,12 +37,23 @@ typedef struct imv_session_t imv_session_t; */ struct imv_session_t { + /** + * Set unique session ID + * + * @param session_id primary key into sessions table + * @param pid primary key into products table + * @param did Primary key into devices table + */ + void (*set_session_id)(imv_session_t *this, int session_id, int pid, int did); + /** * Get unique session ID * - * @return Session ID + * @param pid primary key into products table + * @param did Primary key into devices table + * @return primary key into sessions table */ - int (*get_session_id)(imv_session_t *this); + int (*get_session_id)(imv_session_t *this, int *pid, int *did); /** * Get TNCCS Connection ID @@ -49,6 +62,58 @@ struct imv_session_t { */ TNC_ConnectionID (*get_connection_id)(imv_session_t *this); + /** + * Get session creation time + * + * @return Session creation time + */ + time_t (*get_creation_time)(imv_session_t *this); + + /** + * Get Access Requestor ID + * + * @param id_type Access Requestor TCG Standard ID Type + * @return Access Requestor TCG Standard ID Value + */ + chunk_t (*get_ar_id)(imv_session_t *this, uint32_t *id_type); + + /** + * Get OS Information + * + * @return OS info object + */ + imv_os_info_t* (*get_os_info)(imv_session_t *this); + + /** + * Set Device ID + * + * @param device_id Device ID + */ + void (*set_device_id)(imv_session_t *this, chunk_t device_id); + + /** + * Get Device ID + * + * @param device_id Device ID + * @return TRUE if Device ID has already been set + */ + bool (*get_device_id)(imv_session_t *this, chunk_t *device_id); + + /** + * Set trust into Device ID + * + * @param trusted TRUE if Device ID is trusted + */ + void (*set_device_trust)(imv_session_t *this, bool trusted); + + + /** + * Get device ID trust (needed for TPM-based attestation) + * + * @return TRUE if Device ID is trusted + */ + bool (*get_device_trust)(imv_session_t *this); + /** * Set policy_started status * @@ -105,9 +170,12 @@ struct imv_session_t { /** * Create an imv_session_t instance * - * @param session_id Unique Session ID * @param id Associated Connection ID + * @param created Session creation time + * @param ar_id_type Access Requestor ID type + * @param ar_id_value Access Requestor ID value */ -imv_session_t* imv_session_create(int session_id, TNC_ConnectionID id); +imv_session_t* imv_session_create(TNC_ConnectionID id, time_t created, + uint32_t ar_id_type, chunk_t ar_id_value); #endif /** IMV_SESSION_H_ @}*/ diff --git a/src/libimcv/imv/imv_session_manager.c b/src/libimcv/imv/imv_session_manager.c new file mode 100644 index 0000000000..0fb8de45ed --- /dev/null +++ b/src/libimcv/imv/imv_session_manager.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2014 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "imv_session_manager.h" + +#include + +typedef struct private_imv_session_manager_t private_imv_session_manager_t; + +/** + * Private data of a imv_session_manager_t object. + */ +struct private_imv_session_manager_t { + + /** + * Public imv_session_manager_t interface. + */ + imv_session_manager_t public; + + /** + * Session list + */ + linked_list_t *sessions; + + /** + * mutex used to lock session list + */ + mutex_t *mutex; + +}; + +METHOD(imv_session_manager_t, add_session, imv_session_t*, + private_imv_session_manager_t *this, TNC_ConnectionID conn_id, + uint32_t ar_id_type, chunk_t ar_id_value) +{ + enumerator_t *enumerator; + imv_session_t *current, *session = NULL; + time_t created; + + this->mutex->lock(this->mutex); + + /* check if a session has already been assigned */ + enumerator = this->sessions->create_enumerator(this->sessions); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (conn_id == current->get_connection_id(current)) + { + session = current; + break; + } + } + enumerator->destroy(enumerator); + + /* session already exists */ + if (session) + { + this->mutex->unlock(this->mutex); + return session->get_ref(session); + } + + /* create a new session entry */ + created = time(NULL); + session = imv_session_create(conn_id, created, ar_id_type, ar_id_value); + this->sessions->insert_last(this->sessions, session); + + this->mutex->unlock(this->mutex); + + return session; +} + +METHOD(imv_session_manager_t, remove_session, void, + private_imv_session_manager_t *this, imv_session_t *session) +{ + enumerator_t *enumerator; + imv_session_t *current; + + this->mutex->lock(this->mutex); + enumerator = this->sessions->create_enumerator(this->sessions); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (current == session) + { + this->sessions->remove_at(this->sessions, enumerator); + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +METHOD(imv_session_manager_t, destroy, void, + private_imv_session_manager_t *this) +{ + this->sessions->destroy_offset(this->sessions, + offsetof(imv_session_t, destroy)); + this->mutex->destroy(this->mutex); + free(this); +} + +/** + * See header + */ +imv_session_manager_t *imv_session_manager_create(void) +{ + private_imv_session_manager_t *this; + + INIT(this, + .public = { + .add_session = _add_session, + .remove_session = _remove_session, + .destroy = _destroy, + }, + .sessions = linked_list_create(), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + ); + + return &this->public; +} + diff --git a/src/libimcv/imv/imv_session_manager.h b/src/libimcv/imv/imv_session_manager.h new file mode 100644 index 0000000000..8a733accb4 --- /dev/null +++ b/src/libimcv/imv/imv_session_manager.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2014 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * + * @defgroup imv_session_manager_t imv_session_manager + * @{ @ingroup libimcv_imv + */ + +#ifndef IMV_SESSION_MANAGER_H_ +#define IMV_SESSION_MANAGER_H_ + +#include "imv_session.h" + +#include + +#include + +typedef struct imv_session_manager_t imv_session_manager_t; + +/** + * IMV session manager interface + */ +struct imv_session_manager_t { + + /** + * Create or get a session associated with a TNCCS connection + * + * @param conn_id TNCCS Connection ID + * @param ar_id_type Access Requestor identity type + * @param ar_id_value Access Requestor identity value + * @return Session associated with TNCCS Connection + */ + imv_session_t* (*add_session)(imv_session_manager_t *this, + TNC_ConnectionID conn_id, + uint32_t ar_id_type, chunk_t ar_id_value); + + /** + * Remove a session + * + * @param session Session + */ + void (*remove_session)(imv_session_manager_t *this, imv_session_t *session); + + + /** + * Destroys an imv_session_manager_t object + */ + void (*destroy)(imv_session_manager_t *this); +}; + +/** + * Create an imv_session_manager_t instance + */ +imv_session_manager_t* imv_session_manager_create(); + +#endif /** IMV_SESSION_MANAGER_H_ @}*/ diff --git a/src/libimcv/imv/imv_state.h b/src/libimcv/imv/imv_state.h index 791846bb1e..d11d15e0df 100644 --- a/src/libimcv/imv/imv_state.h +++ b/src/libimcv/imv/imv_state.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2013 Andreas Steffen + * Copyright (C) 2011-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -70,45 +70,28 @@ struct imv_state_t { * * @param max_msg_len maximum size of a PA-TNC message */ - void (*set_max_msg_len)(imv_state_t *this, u_int32_t max_msg_len); + void (*set_max_msg_len)(imv_state_t *this, uint32_t max_msg_len); /** * Get the maximum size of a PA-TNC message for this TNCCS connection * * @return maximum size of a PA-TNC message */ - u_int32_t (*get_max_msg_len)(imv_state_t *this); + uint32_t (*get_max_msg_len)(imv_state_t *this); /** * Set flags for completed actions * * @param flags Flags to be set */ - void (*set_action_flags)(imv_state_t *this, u_int32_t flags); + void (*set_action_flags)(imv_state_t *this, uint32_t flags); /** * Get flags set for completed actions * * @return Flags set for completed actions */ - u_int32_t (*get_action_flags)(imv_state_t *this); - - /** - * Set Access Requestor ID - * - * @param id_type Access Requestor TCG Standard ID Type - * @param id_value Access Requestor TCG Standard ID Value - * - */ - void (*set_ar_id)(imv_state_t *this, u_int32_t id_type, chunk_t id_value); - - /** - * Get Access Requestor ID - * - * @param id_type Access Requestor TCG Standard ID Type - * @return Access Requestor TCG Standard ID Value - */ - chunk_t (*get_ar_id)(imv_state_t *this, u_int32_t *id_type); + uint32_t (*get_action_flags)(imv_state_t *this); /** * Set session associated with TNCCS Connection diff --git a/src/libimcv/imv/tables.sql b/src/libimcv/imv/tables.sql index a0f3a4e8da..45ae78cc9d 100644 --- a/src/libimcv/imv/tables.sql +++ b/src/libimcv/imv/tables.sql @@ -42,27 +42,11 @@ CREATE TABLE file_hashes ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, file INTEGER NOT NULL REFERENCES files(id), product INTEGER NOT NULL REFERENCES products(id), - device INTEGER DEFAULT 0, - key INTEGER DEFAULT 0 REFERENCES keys(id), + device INTEGER DEFAULT 0 REFERENCES devices(id), algo INTEGER NOT NULL REFERENCES algorithms(id), hash BLOB NOT NULL ); -DROP TABLE IF EXISTS keys; -CREATE TABLE keys ( - id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - keyid BLOB NOT NULL, - owner TEXT NOT NULL -); -DROP INDEX IF EXISTS keys_keyid; -CREATE INDEX keys_keyid ON keys ( - keyid -); -DROP INDEX IF EXISTS keys_owner; -CREATE INDEX keys_owner ON keys ( - owner -); - DROP TABLE IF EXISTS groups; CREATE TABLE groups ( id INTEGER NOT NULL PRIMARY KEY, @@ -159,17 +143,6 @@ CREATE TABLE components ( qualifier INTEGER DEFAULT 0 ); - -DROP TABLE IF EXISTS key_component; -CREATE TABLE key_component ( - key INTEGER NOT NULL, - component INTEGER NOT NULL, - depth INTEGER DEFAULT 0, - seq_no INTEGER DEFAULT 0, - PRIMARY KEY (key, component) -); - - DROP TABLE IF EXISTS component_hashes; CREATE TABLE component_hashes ( component INTEGER NOT NULL, @@ -217,6 +190,7 @@ CREATE TABLE devices ( description TEXT DEFAULT '', value TEXT NOT NULL, product INTEGER REFERENCES products(id), + trusted INTEGER DEFAULT 0, created INTEGER ); DROP INDEX IF EXISTS devices_id; diff --git a/src/libimcv/os_info/os_info.c b/src/libimcv/os_info/os_info.c index 06427575c3..67b09cd2f0 100644 --- a/src/libimcv/os_info/os_info.c +++ b/src/libimcv/os_info/os_info.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Andreas Steffen + * Copyright (C) 2012-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -15,15 +15,6 @@ #include "os_info.h" -#include -#include -#include - -#include -#include - -typedef struct private_os_info_t private_os_info_t; - ENUM(os_type_names, OS_TYPE_UNKNOWN, OS_TYPE_ANDROID, "Unknown", "Debian", @@ -48,487 +39,6 @@ ENUM(os_package_state_names, OS_PACKAGE_STATE_UPDATE, OS_PACKAGE_STATE_BLACKLIST " [b]" ); -/** - * Private data of an os_info_t object. - * - */ -struct private_os_info_t { - - /** - * Public os_info_t interface. - */ - os_info_t public; - - /** - * OS type - */ - os_type_t type; - - /** - * OS name - */ - chunk_t name; - - /** - * OS version - */ - chunk_t version; - -}; - -METHOD(os_info_t, get_type, os_type_t, - private_os_info_t *this) -{ - return this->type; -} - -METHOD(os_info_t, get_name, chunk_t, - private_os_info_t *this) -{ - return this->name; -} - -METHOD(os_info_t, get_numeric_version, void, - private_os_info_t *this, u_int32_t *major, u_int32_t *minor) -{ - u_char *pos; - - if (major) - { - *major = atol(this->version.ptr); - } - pos = memchr(this->version.ptr, '.', this->version.len); - if (minor) - { - *minor = pos ? atol(pos + 1) : 0; - } -} - -METHOD(os_info_t, get_version, chunk_t, - private_os_info_t *this) -{ - return this->version; -} - -METHOD(os_info_t, get_fwd_status, os_fwd_status_t, - private_os_info_t *this) -{ - const char ip_forward[] = "/proc/sys/net/ipv4/ip_forward"; - char buf[2]; - FILE *file; - - os_fwd_status_t fwd_status = OS_FWD_UNKNOWN; - - file = fopen(ip_forward, "r"); - if (file) - { - if (fread(buf, 1, 1, file) == 1) - { - switch (buf[0]) - { - case '0': - fwd_status = OS_FWD_DISABLED; - break; - case '1': - fwd_status = OS_FWD_ENABLED; - break; - default: - DBG1(DBG_IMC, "\"%s\" returns invalid value ", ip_forward); - break; - } - } - else - { - DBG1(DBG_IMC, "could not read from \"%s\"", ip_forward); - } - fclose(file); - } - else - { - DBG1(DBG_IMC, "failed to open \"%s\"", ip_forward); - } - - return fwd_status; -} - -METHOD(os_info_t, get_uptime, time_t, - private_os_info_t *this) -{ - const char proc_uptime[] = "/proc/uptime"; - FILE *file; - u_int uptime; - - file = fopen(proc_uptime, "r"); - if (!file) - { - DBG1(DBG_IMC, "failed to open \"%s\"", proc_uptime); - return 0; - } - if (fscanf(file, "%u", &uptime) != 1) - { - DBG1(DBG_IMC, "failed to read file \"%s\"", proc_uptime); - uptime = 0; - } - fclose(file); - - return uptime; -} - -METHOD(os_info_t, get_setting, chunk_t, - private_os_info_t *this, char *name) -{ - FILE *file; - u_char buf[2048]; - size_t i = 0; - chunk_t value; - - if (!strpfx(name, "/etc/") && !strpfx(name, "/proc/") && - !strpfx(name, "/sys/") && !strpfx(name, "/var/")) - { - /** - * In order to guarantee privacy, only settings from the - * /etc/, /proc/ and /sys/ directories can be retrieved - */ - DBG1(DBG_IMC, "not allowed to access '%s'", name); - - return chunk_empty; - } - - file = fopen(name, "r"); - if (!file) - { - DBG1(DBG_IMC, "failed to open '%s'", name); - - return chunk_empty; - } - while (i < sizeof(buf) && fread(buf + i, 1, 1, file) == 1) - { - i++; - } - fclose(file); - - value = chunk_create(buf, i); - - return chunk_clone(value); -} - -typedef struct { - /** - * implements enumerator_t - */ - enumerator_t public; - - /** - * package info pipe stream - */ - FILE* file; - - /** - * line buffer - */ - u_char line[512]; - -} package_enumerator_t; - -/** - * Implementation of package_enumerator.destroy. - */ -static void package_enumerator_destroy(package_enumerator_t *this) -{ - pclose(this->file); - free(this); -} - -/** - * Implementation of package_enumerator.enumerate - */ -static bool package_enumerator_enumerate(package_enumerator_t *this, ...) -{ - chunk_t *name, *version; - u_char *pos; - va_list args; - - while (TRUE) - { - if (!fgets(this->line, sizeof(this->line), this->file)) - { - return FALSE; - } - - pos = strchr(this->line, '\t'); - if (!pos) - { - return FALSE; - } - *pos++ = '\0'; - - if (!streq(this->line, "install ok installed")) - { - continue; - } - va_start(args, this); - - name = va_arg(args, chunk_t*); - name->ptr = pos; - pos = strchr(pos, '\t'); - if (!pos) - { - va_end(args); - return FALSE; - } - name->len = pos++ - name->ptr; - - version = va_arg(args, chunk_t*); - version->ptr = pos; - version->len = strlen(pos) - 1; - - va_end(args); - return TRUE; - } -} - -METHOD(os_info_t, create_package_enumerator, enumerator_t*, - private_os_info_t *this) -{ - FILE *file; - const char command[] = "dpkg-query --show --showformat=" - "'${Status}\t${Package}\t${Version}\n'"; - package_enumerator_t *enumerator; - - /* Only Debian and Ubuntu package enumeration is currently supported */ - if (this->type != OS_TYPE_DEBIAN && this->type != OS_TYPE_UBUNTU) - { - return NULL; - } - - /* Open a pipe stream for reading the output of the dpkg-query commmand */ - file = popen(command, "r"); - if (!file) - { - DBG1(DBG_IMC, "failed to run dpkg command"); - return NULL; - } - - /* Create a package enumerator instance */ - enumerator = malloc_thing(package_enumerator_t); - enumerator->public.enumerate = (void*)package_enumerator_enumerate; - enumerator->public.destroy = (void*)package_enumerator_destroy; - enumerator->file = file; - - return (enumerator_t*)enumerator; -} - - -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(os_type_t *type, chunk_t *name, - chunk_t *version) -{ - FILE *file; - u_char buf[BUF_LEN], *pos = buf; - int len = BUF_LEN - 1; - os_type_t os_type = OS_TYPE_UNKNOWN; - chunk_t os_name = chunk_empty; - chunk_t os_version = chunk_empty; - char *os_str; - 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: - { - os_type = OS_TYPE_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_version.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; - } - - /* Try to find a matching OS type based on the OS name */ - if (os_type == OS_TYPE_UNKNOWN) - { - os_type = os_type_from_name(os_name); - } - - /* If known use the official OS name */ - if (os_type != OS_TYPE_UNKNOWN) - { - os_str = enum_to_name(os_type_names, os_type); - os_name = chunk_create(os_str, strlen(os_str)); - } - - /* copy OS type */ - *type = os_type; - - /* 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 */ @@ -548,59 +58,3 @@ os_type_t os_type_from_name(chunk_t name) } return OS_TYPE_UNKNOWN; } - -/** - * See header - */ -os_info_t *os_info_create(void) -{ - private_os_info_t *this; - chunk_t name, version; - os_type_t type; - - /* As an option OS name and OS version can be configured manually */ - name.ptr = lib->settings->get_str(lib->settings, - "%s.imcv.os_info.name", NULL, lib->ns); - version.ptr = lib->settings->get_str(lib->settings, - "%s.imcv.os_info.version", NULL, lib->ns); - if (name.ptr && version.ptr) - { - name.len = strlen(name.ptr); - name = chunk_clone(name); - - version.len = strlen(version.ptr); - version = chunk_clone(version); - - type = os_type_from_name(name); - } - else - { - if (!extract_platform_info(&type, &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_type = _get_type, - .get_name = _get_name, - .get_numeric_version = _get_numeric_version, - .get_version = _get_version, - .get_fwd_status = _get_fwd_status, - .get_uptime = _get_uptime, - .get_setting = _get_setting, - .create_package_enumerator = _create_package_enumerator, - .destroy = _destroy, - }, - .type = type, - .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 index f47460709e..e77d888a76 100644 --- a/src/libimcv/os_info/os_info.h +++ b/src/libimcv/os_info/os_info.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Andreas Steffen + * Copyright (C) 2012-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -67,87 +67,12 @@ enum os_fwd_status_t { extern enum_name_t *os_fwd_status_names; -/** - * Interface for the Operating System (OS) information module - */ -struct os_info_t { - - /** - * Get the OS type if it can be determined - * - * @return OS type - */ - os_type_t (*get_type)(os_info_t *this); - - /** - * Get the OS product name or distribution - * - * @return OS name - */ - chunk_t (*get_name)(os_info_t *this); - - /** - * Get the numeric OS version or release - * - * @param major OS major version number - * @param minor OS minor version number - */ - void (*get_numeric_version)(os_info_t *this, u_int32_t *major, - u_int32_t *minor); - - /** - * Get the OS version or release - * - * @return OS version - */ - chunk_t (*get_version)(os_info_t *this); - - /** - * Get the OS IPv4 forwarding status - * - * @return IP forwarding status - */ - os_fwd_status_t (*get_fwd_status)(os_info_t *this); - - /** - * Get the OS uptime in seconds - * - * @return OS uptime - */ - time_t (*get_uptime)(os_info_t *this); - - /** - * Get an OS setting (restricted to /proc, /sys, and /etc) - * - * @param name name of OS setting - * @return value of OS setting - */ - chunk_t (*get_setting)(os_info_t *this, char *name); - - /** - * Enumerates over all installed packages - * - * @return return package enumerator - */ - enumerator_t* (*create_package_enumerator)(os_info_t *this); - - /** - * Destroys an os_info_t object. - */ - void (*destroy)(os_info_t *this); -}; - /** * Convert an OS name into an OS enumeration type * - * @param name OS name - * @return OS enumeration type + * @param name OS name + * @return OS enumeration type */ os_type_t os_type_from_name(chunk_t name); -/** - * 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 1c7d589936..7d84249d0e 100644 --- a/src/libimcv/plugins/imc_os/imc_os.c +++ b/src/libimcv/plugins/imc_os/imc_os.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -31,7 +32,6 @@ #include #include #include -#include #include @@ -47,7 +47,7 @@ static pen_type_t msg_types[] = { }; static imc_agent_t *imc_os; -static os_info_t *os; +static imc_os_info_t *os; /** * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3 @@ -69,7 +69,7 @@ TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id, return TNC_RESULT_FATAL; } - os = os_info_create(); + os = imc_os_info_create(); if (!os) { imc_os->destroy(imc_os); diff --git a/src/libimcv/plugins/imv_os/imv_os_agent.c b/src/libimcv/plugins/imv_os/imv_os_agent.c index 84a24b48f8..874f0a5040 100644 --- a/src/libimcv/plugins/imv_os/imv_os_agent.c +++ b/src/libimcv/plugins/imv_os/imv_os_agent.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Andreas Steffen + * Copyright (C) 2013-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -134,7 +134,13 @@ METHOD(imv_agent_if_t, notify_connection_change, TNC_Result, } session = state->get_session(state); imcv_db->add_recommendation(imcv_db, session, rec); - imcv_db->policy_script(imcv_db, session, FALSE); + if (session->get_policy_started(session)) + { + if (!imcv_db->policy_script(imcv_db, session, FALSE)) + { + DBG1(DBG_IMV, "error in policy script stop"); + } + } } /* fall through to default state */ default: @@ -150,6 +156,8 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state, { imv_msg_t *out_msg; imv_os_state_t *os_state; + imv_session_t *session; + imv_os_info_t *os_info = NULL; enumerator_t *enumerator; pa_tnc_attr_t *attr; pen_type_t type; @@ -159,6 +167,8 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state, bool fatal_error = FALSE, assessment = FALSE; os_state = (imv_os_state_t*)state; + session = state->get_session(state); + os_info = session->get_os_info(session); /* parse received PA-TNC message and handle local and remote errors */ result = in_msg->receive(in_msg, &fatal_error); @@ -188,6 +198,8 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state, IMV_OS_ATTR_PRODUCT_INFORMATION); attr_cast = (ietf_attr_product_info_t*)attr; os_name = attr_cast->get_info(attr_cast, &vendor_id, NULL); + os_info->set_name(os_info, os_name); + if (vendor_id != PEN_IETF) { DBG1(DBG_IMV, "operating system name is '%.*s' " @@ -209,6 +221,8 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state, IMV_OS_ATTR_STRING_VERSION); attr_cast = (ietf_attr_string_version_t*)attr; os_version = attr_cast->get_version(attr_cast, NULL, NULL); + os_info->set_version(os_info, os_version); + if (os_version.len) { DBG1(DBG_IMV, "operating system version is '%.*s'", @@ -350,8 +364,8 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state, state->set_action_flags(state, IMV_OS_ATTR_DEVICE_ID); value = attr->get_value(attr); - os_state->set_device_id(os_state, value); DBG1(DBG_IMV, "device ID is %.*s", value.len, value.ptr); + session->set_device_id(session, value); break; } case ITA_ATTR_START_ANGEL: @@ -367,25 +381,6 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state, } enumerator->destroy(enumerator); - /** - * The IETF Product Information and String Version attributes - * are supposed to arrive in the same PA-TNC message - */ - if (os_name.len && os_version.len) - { - os_type_t os_type; - - /* set the OS type, name and version */ - os_type = os_type_from_name(os_name); - os_state->set_info(os_state,os_type, os_name, os_version); - - if (imcv_db) - { - imcv_db->add_product(imcv_db, state->get_session(state), - os_state->get_info(os_state, NULL, NULL, NULL)); - } - } - if (fatal_error) { state->set_recommendation(state, @@ -542,56 +537,69 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, if (handshake_state < IMV_OS_STATE_POLICY_START) { - if (((received & IMV_OS_ATTR_PRODUCT_INFORMATION) && - (received & IMV_OS_ATTR_STRING_VERSION)) && - ((received & IMV_OS_ATTR_DEVICE_ID) || - (handshake_state == IMV_OS_STATE_ATTR_REQ))) + if (session->get_policy_started(session)) + { + /* the policy script has already been started by another IMV */ + handshake_state = IMV_OS_STATE_POLICY_START; + } + else { - if (imcv_db) + if (((received & IMV_OS_ATTR_PRODUCT_INFORMATION) && + (received & IMV_OS_ATTR_STRING_VERSION)) && + ((received & IMV_OS_ATTR_DEVICE_ID) || + (handshake_state == IMV_OS_STATE_ATTR_REQ))) { - imcv_db->add_device(imcv_db, session, - os_state->get_device_id(os_state)); - - /* trigger the policy manager */ - imcv_db->policy_script(imcv_db, session, TRUE); + if (!session->get_device_id(session, NULL)) + { + session->set_device_id(session, chunk_empty); + } + if (imcv_db) + { + /* start the policy script */ + if (!imcv_db->policy_script(imcv_db, session, TRUE)) + { + DBG1(DBG_IMV, "error in policy script start"); + } + } + else + { + DBG2(DBG_IMV, "no workitems available - " + "no evaluation possible"); + state->set_recommendation(state, + TNC_IMV_ACTION_RECOMMENDATION_ALLOW, + TNC_IMV_EVALUATION_RESULT_DONT_KNOW); + } + handshake_state = IMV_OS_STATE_POLICY_START; } - else + else if (handshake_state == IMV_OS_STATE_ATTR_REQ) { - DBG2(DBG_IMV, "no workitems available - no evaluation possible"); + /** + * both the IETF Product Information and IETF String Version + * attribute should have been present + */ state->set_recommendation(state, - TNC_IMV_ACTION_RECOMMENDATION_ALLOW, - TNC_IMV_EVALUATION_RESULT_DONT_KNOW); - } - handshake_state = IMV_OS_STATE_POLICY_START; - } - else if (handshake_state == IMV_OS_STATE_ATTR_REQ) - { - /** - * both the IETF Product Information and IETF String Version - * attribute should have been present - */ - state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, TNC_IMV_EVALUATION_RESULT_ERROR); - /* send assessment */ - result = out_msg->send_assessment(out_msg); - out_msg->destroy(out_msg); + /* send assessment */ + result = out_msg->send_assessment(out_msg); + out_msg->destroy(out_msg); - if (result != TNC_RESULT_SUCCESS) + if (result != TNC_RESULT_SUCCESS) + { + return result; + } + return this->agent->provide_recommendation(this->agent, state); + } + else { - return result; - } - return this->agent->provide_recommendation(this->agent, state); - } - else - { - handshake_state = IMV_OS_STATE_ATTR_REQ; + handshake_state = IMV_OS_STATE_ATTR_REQ; + } } os_state->set_handshake_state(os_state, handshake_state); } - if (handshake_state == IMV_OS_STATE_POLICY_START && session) + if (handshake_state == IMV_OS_STATE_POLICY_START) { enumerator = session->create_workitem_enumerator(session); if (enumerator) @@ -638,7 +646,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, } } - if (handshake_state == IMV_OS_STATE_WORKITEMS && session) + if (handshake_state == IMV_OS_STATE_WORKITEMS) { TNC_IMV_Evaluation_Result eval; TNC_IMV_Action_Recommendation rec; diff --git a/src/libimcv/plugins/imv_os/imv_os_database.c b/src/libimcv/plugins/imv_os/imv_os_database.c index 12cf207d87..106d56a5cd 100644 --- a/src/libimcv/plugins/imv_os/imv_os_database.c +++ b/src/libimcv/plugins/imv_os/imv_os_database.c @@ -41,19 +41,26 @@ struct private_imv_os_database_t { }; METHOD(imv_os_database_t, check_packages, status_t, - private_imv_os_database_t *this, imv_os_state_t *state, + private_imv_os_database_t *this, imv_os_state_t *os_state, enumerator_t *package_enumerator) { + imv_state_t *state; + imv_session_t *session; + imv_os_info_t *os_info; + os_type_t os_type; char *product, *package, *release, *cur_release; chunk_t name, version; - os_type_t os_type; int pid, gid, security, blacklist; int count = 0, count_ok = 0, count_no_match = 0, count_blacklist = 0; enumerator_t *e; status_t status = SUCCESS; bool found, match; - product = state->get_info(state, &os_type, NULL, NULL); + state = &os_state->interface; + session = state->get_session(state); + os_info = session->get_os_info(session); + os_type = os_info->get_type(os_info); + product = os_info->get_info(os_info); if (os_type == OS_TYPE_ANDROID) { @@ -143,8 +150,8 @@ METHOD(imv_os_database_t, check_packages, status_t, DBG2(DBG_IMV, "package '%s' (%s) is blacklisted", package, release); count_blacklist++; - state->add_bad_package(state, package, - OS_PACKAGE_STATE_BLACKLIST); + os_state->add_bad_package(os_state, package, + OS_PACKAGE_STATE_BLACKLIST); } else { @@ -157,8 +164,8 @@ METHOD(imv_os_database_t, check_packages, status_t, { DBG1(DBG_IMV, "package '%s' (%s) no match", package, release); count_no_match++; - state->add_bad_package(state, package, - OS_PACKAGE_STATE_SECURITY); + os_state->add_bad_package(os_state, package, + OS_PACKAGE_STATE_SECURITY); } } else @@ -168,7 +175,8 @@ METHOD(imv_os_database_t, check_packages, status_t, free(package); free(release); } - state->set_count(state, count, count_no_match, count_blacklist, count_ok); + os_state->set_count(os_state, count, count_no_match, + count_blacklist, count_ok); return status; } diff --git a/src/libimcv/plugins/imv_os/imv_os_state.c b/src/libimcv/plugins/imv_os/imv_os_state.c index 4f5a4b0397..dc8474ac90 100644 --- a/src/libimcv/plugins/imv_os/imv_os_state.c +++ b/src/libimcv/plugins/imv_os/imv_os_state.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2013 Andreas Steffen + * Copyright (C) 2012-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -18,6 +18,7 @@ #include "imv/imv_lang_string.h" #include "imv/imv_reason_string.h" #include "imv/imv_remediation_string.h" +#include "imv/imv_os_info.h" #include @@ -62,22 +63,12 @@ struct private_imv_os_state_t { /** * Maximum PA-TNC message size for this TNCCS connection */ - u_int32_t max_msg_len; + uint32_t max_msg_len; /** * Flags set for completed actions */ - u_int32_t action_flags; - - /** - * Access Requestor ID Type - */ - u_int32_t ar_id_type; - - /** - * Access Requestor ID Value - */ - chunk_t ar_id_value; + uint32_t action_flags; /** * IMV database session associated with TNCCS connection @@ -99,33 +90,13 @@ struct private_imv_os_state_t { */ imv_os_handshake_state_t handshake_state; - /** - * OS Product Information (concatenation of OS Name and Version) - */ - char *info; - - /** - * OS Type - */ - os_type_t type; - - /** - * OS Name - */ - chunk_t name; - - /** - * OS Version - */ - chunk_t version; - /** * List of blacklisted packages to be removed */ linked_list_t *remove_packages; /** - * List of vulnerable packages to be updated + h* List of vulnerable packages to be updated */ linked_list_t *update_packages; @@ -139,11 +110,6 @@ struct private_imv_os_state_t { */ imv_remediation_string_t *remediation_string; - /** - * Dgevice ID - */ - chunk_t device_id; - /** * Number of processed packages */ @@ -326,46 +292,29 @@ METHOD(imv_state_t, set_flags, void, } METHOD(imv_state_t, set_max_msg_len, void, - private_imv_os_state_t *this, u_int32_t max_msg_len) + private_imv_os_state_t *this, uint32_t max_msg_len) { this->max_msg_len = max_msg_len; } -METHOD(imv_state_t, get_max_msg_len, u_int32_t, +METHOD(imv_state_t, get_max_msg_len, uint32_t, private_imv_os_state_t *this) { return this->max_msg_len; } METHOD(imv_state_t, set_action_flags, void, - private_imv_os_state_t *this, u_int32_t flags) + private_imv_os_state_t *this, uint32_t flags) { this->action_flags |= flags; } -METHOD(imv_state_t, get_action_flags, u_int32_t, +METHOD(imv_state_t, get_action_flags, uint32_t, private_imv_os_state_t *this) { return this->action_flags; } -METHOD(imv_state_t, set_ar_id, void, - private_imv_os_state_t *this, u_int32_t id_type, chunk_t id_value) -{ - this->ar_id_type = id_type; - this->ar_id_value = chunk_clone(id_value); -} - -METHOD(imv_state_t, get_ar_id, chunk_t, - private_imv_os_state_t *this, u_int32_t *id_type) -{ - if (id_type) - { - *id_type = this->ar_id_type; - } - return this->ar_id_value; -} - METHOD(imv_state_t, set_session, void, private_imv_os_state_t *this, imv_session_t *session) { @@ -440,6 +389,9 @@ METHOD(imv_state_t, get_remediation_instructions, bool, private_imv_os_state_t *this, enumerator_t *language_enumerator, chunk_t *string, char **lang_code, char **uri) { + imv_os_info_t *os_info; + bool as_xml = FALSE; + if (!this->count_update && !this->count_blacklist & !this->os_settings) { return FALSE; @@ -449,8 +401,12 @@ METHOD(imv_state_t, get_remediation_instructions, bool, /* Instantiate an IETF Remediation Instructions String object */ DESTROY_IF(this->remediation_string); - this->remediation_string = imv_remediation_string_create( - this->type == OS_TYPE_ANDROID, *lang_code); + if (this->session) + { + os_info = this->session->get_os_info(this->session); + as_xml = os_info->get_type(os_info) == OS_TYPE_ANDROID; + } + this->remediation_string = imv_remediation_string_create(as_xml, *lang_code); /* List of blacklisted packages to be removed, if any */ if (this->count_blacklist) @@ -507,11 +463,6 @@ METHOD(imv_state_t, destroy, void, DESTROY_IF(this->remediation_string); this->update_packages->destroy_function(this->update_packages, free); this->remove_packages->destroy_function(this->remove_packages, free); - free(this->info); - free(this->name.ptr); - free(this->version.ptr); - free(this->ar_id_value.ptr); - free(this->device_id.ptr); free(this); } @@ -527,39 +478,6 @@ METHOD(imv_os_state_t, get_handshake_state, imv_os_handshake_state_t, return this->handshake_state; } -METHOD(imv_os_state_t, set_info, void, - private_imv_os_state_t *this, os_type_t type, chunk_t name, chunk_t version) -{ - 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", (int)name.len, name.ptr, - (int)version.len, version.ptr); - this->type = type; - this->name = chunk_clone(name); - this->version = chunk_clone(version); -} - -METHOD(imv_os_state_t, get_info, char*, - private_imv_os_state_t *this, os_type_t *type, chunk_t *name, - chunk_t *version) -{ - if (type) - { - *type = this->type; - } - if (name) - { - *name = this->name; - } - if (version) - { - *version = this->version; - } - return this->info; -} METHOD(imv_os_state_t, set_count, void, private_imv_os_state_t *this, int count, int count_update, @@ -593,18 +511,6 @@ METHOD(imv_os_state_t, get_count, void, } } -METHOD(imv_os_state_t, set_device_id, void, - private_imv_os_state_t *this, chunk_t id) -{ - this->device_id = chunk_clone(id); -} - -METHOD(imv_os_state_t, get_device_id, chunk_t, - private_imv_os_state_t *this) -{ - return this->device_id; -} - METHOD(imv_os_state_t, set_os_settings, void, private_imv_os_state_t *this, u_int settings) { @@ -663,8 +569,6 @@ imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id) .get_max_msg_len = _get_max_msg_len, .set_action_flags = _set_action_flags, .get_action_flags = _get_action_flags, - .set_ar_id = _set_ar_id, - .get_ar_id = _get_ar_id, .set_session = _set_session, .get_session = _get_session, .change_state = _change_state, @@ -677,12 +581,8 @@ imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id) }, .set_handshake_state = _set_handshake_state, .get_handshake_state = _get_handshake_state, - .set_info = _set_info, - .get_info = _get_info, .set_count = _set_count, .get_count = _get_count, - .set_device_id = _set_device_id, - .get_device_id = _get_device_id, .set_os_settings = _set_os_settings, .get_os_settings = _get_os_settings, .set_angel_count = _set_angel_count, diff --git a/src/libimcv/plugins/imv_os/imv_os_state.h b/src/libimcv/plugins/imv_os/imv_os_state.h index 97f6953199..82ebb6cc9b 100644 --- a/src/libimcv/plugins/imv_os/imv_os_state.h +++ b/src/libimcv/plugins/imv_os/imv_os_state.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Andreas Steffen + * Copyright (C) 2012-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -77,27 +77,6 @@ struct imv_os_state_t { */ imv_os_handshake_state_t (*get_handshake_state)(imv_os_state_t *this); - /** - * Set OS Product Information - * - * @param type OS type (enumerated) - * @param name OS name (string) - * @param version OS version - */ - void (*set_info)(imv_os_state_t *this, os_type_t os_type, - chunk_t name, chunk_t version); - - /** - * Get OS Product Information - * - * @param type OS type (enumerated) - * @param name OS name (string) - * @param version OS version - * @return OS name & version as a concatenated string - */ - char* (*get_info)(imv_os_state_t *this, os_type_t *os_type, - chunk_t *name, chunk_t *version); - /** * Set [or with multiple attributes increment] package counters * @@ -120,20 +99,6 @@ struct imv_os_state_t { void (*get_count)(imv_os_state_t *this, int *count, int *count_update, int *count_blacklist, int *count_ok); - /** - * Set device ID - * - * @param device_id Device ID - */ - void (*set_device_id)(imv_os_state_t *this, chunk_t id); - - /** - * Get device ID - * - * @return Device ID - */ - chunk_t (*get_device_id)(imv_os_state_t *this); - /** * Set OS settings * diff --git a/src/libimcv/plugins/imv_scanner/imv_scanner_agent.c b/src/libimcv/plugins/imv_scanner/imv_scanner_agent.c index d1e0931376..85ef23b802 100644 --- a/src/libimcv/plugins/imv_scanner/imv_scanner_agent.c +++ b/src/libimcv/plugins/imv_scanner/imv_scanner_agent.c @@ -259,7 +259,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY, msg_types[0]); - if (!session) + if (!imcv_db) { DBG2(DBG_IMV, "no workitems available - no evaluation possible"); state->set_recommendation(state, @@ -276,7 +276,8 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, return this->agent->provide_recommendation(this->agent, state); } - if (handshake_state == IMV_SCANNER_STATE_INIT) + if (handshake_state == IMV_SCANNER_STATE_INIT && + session->get_policy_started(session)) { enumerator = session->create_workitem_enumerator(session); if (enumerator) diff --git a/src/libimcv/plugins/imv_scanner/imv_scanner_state.c b/src/libimcv/plugins/imv_scanner/imv_scanner_state.c index 90475d34d4..24a49a76c5 100644 --- a/src/libimcv/plugins/imv_scanner/imv_scanner_state.c +++ b/src/libimcv/plugins/imv_scanner/imv_scanner_state.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2013 Andreas Steffen + * Copyright (C) 2011-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -58,22 +58,12 @@ struct private_imv_scanner_state_t { /** * Maximum PA-TNC message size for this TNCCS connection */ - u_int32_t max_msg_len; + uint32_t max_msg_len; /** * Flags set for completed actions */ - u_int32_t action_flags; - - /** - * Access Requestor ID Type - */ - u_int32_t ar_id_type; - - /** - * Access Requestor ID Value - */ - chunk_t ar_id_value; + uint32_t action_flags; /** * IMV database session associatied with TNCCS connection @@ -186,46 +176,29 @@ METHOD(imv_state_t, set_flags, void, } METHOD(imv_state_t, set_max_msg_len, void, - private_imv_scanner_state_t *this, u_int32_t max_msg_len) + private_imv_scanner_state_t *this, uint32_t max_msg_len) { this->max_msg_len = max_msg_len; } -METHOD(imv_state_t, get_max_msg_len, u_int32_t, +METHOD(imv_state_t, get_max_msg_len, uint32_t, private_imv_scanner_state_t *this) { return this->max_msg_len; } METHOD(imv_state_t, set_action_flags, void, - private_imv_scanner_state_t *this, u_int32_t flags) + private_imv_scanner_state_t *this, uint32_t flags) { this->action_flags |= flags; } -METHOD(imv_state_t, get_action_flags, u_int32_t, +METHOD(imv_state_t, get_action_flags, uint32_t, private_imv_scanner_state_t *this) { return this->action_flags; } -METHOD(imv_state_t, set_ar_id, void, - private_imv_scanner_state_t *this, u_int32_t id_type, chunk_t id_value) -{ - this->ar_id_type = id_type; - this->ar_id_value = chunk_clone(id_value); -} - -METHOD(imv_state_t, get_ar_id, chunk_t, - private_imv_scanner_state_t *this, u_int32_t *id_type) -{ - if (id_type) - { - *id_type = this->ar_id_type; - } - return this->ar_id_value; -} - METHOD(imv_state_t, set_session, void, private_imv_scanner_state_t *this, imv_session_t *session) { @@ -327,7 +300,6 @@ METHOD(imv_state_t, destroy, void, DESTROY_IF(this->remediation_string); DESTROY_IF(&this->port_filter_attr->pa_tnc_attribute); this->violating_ports->destroy_function(this->violating_ports, free); - free(this->ar_id_value.ptr); free(this); } @@ -380,8 +352,6 @@ imv_state_t *imv_scanner_state_create(TNC_ConnectionID connection_id) .get_max_msg_len = _get_max_msg_len, .set_action_flags = _set_action_flags, .get_action_flags = _get_action_flags, - .set_ar_id = _set_ar_id, - .get_ar_id = _get_ar_id, .set_session = _set_session, .get_session= _get_session, .change_state = _change_state, diff --git a/src/libimcv/plugins/imv_test/imv_test_state.c b/src/libimcv/plugins/imv_test/imv_test_state.c index f05db80270..3564456a8d 100644 --- a/src/libimcv/plugins/imv_test/imv_test_state.c +++ b/src/libimcv/plugins/imv_test/imv_test_state.c @@ -58,17 +58,7 @@ struct private_imv_test_state_t { /** * Maximum PA-TNC message size for this TNCCS connection */ - u_int32_t max_msg_len; - - /** - * Access Requestor ID Type - */ - u_int32_t ar_id_type; - - /** - * Access Requestor ID Value - */ - chunk_t ar_id_value; + uint32_t max_msg_len; /** * IMV database session associated with TNCCS connection @@ -149,34 +139,17 @@ METHOD(imv_state_t, set_flags, void, } METHOD(imv_state_t, set_max_msg_len, void, - private_imv_test_state_t *this, u_int32_t max_msg_len) + private_imv_test_state_t *this, uint32_t max_msg_len) { this->max_msg_len = max_msg_len; } -METHOD(imv_state_t, get_max_msg_len, u_int32_t, +METHOD(imv_state_t, get_max_msg_len, uint32_t, private_imv_test_state_t *this) { return this->max_msg_len; } -METHOD(imv_state_t, set_ar_id, void, - private_imv_test_state_t *this, u_int32_t id_type, chunk_t id_value) -{ - this->ar_id_type = id_type; - this->ar_id_value = chunk_clone(id_value); -} - -METHOD(imv_state_t, get_ar_id, chunk_t, - private_imv_test_state_t *this, u_int32_t *id_type) -{ - if (id_type) - { - *id_type = this->ar_id_type; - } - return this->ar_id_value; -} - METHOD(imv_state_t, set_session, void, private_imv_test_state_t *this, imv_session_t *session) { @@ -248,7 +221,6 @@ METHOD(imv_state_t, destroy, void, DESTROY_IF(this->session); DESTROY_IF(this->reason_string); this->imcs->destroy_function(this->imcs, free); - free(this->ar_id_value.ptr); free(this); } @@ -333,8 +305,6 @@ imv_state_t *imv_test_state_create(TNC_ConnectionID connection_id) .set_flags = _set_flags, .set_max_msg_len = _set_max_msg_len, .get_max_msg_len = _get_max_msg_len, - .set_ar_id = _set_ar_id, - .get_ar_id = _get_ar_id, .set_session = _set_session, .get_session = _get_session, .change_state = _change_state, diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_agent.c b/src/libpts/plugins/imv_attestation/imv_attestation_agent.c index ae2660bae4..12013194c9 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation_agent.c +++ b/src/libpts/plugins/imv_attestation/imv_attestation_agent.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2011-2012 Sansar Choinyambuu - * Copyright (C) 2011-2013 Andreas Steffen + * Copyright (C) 2011-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -131,15 +133,14 @@ METHOD(imv_agent_if_t, notify_connection_change, TNC_Result, static TNC_Result receive_msg(private_imv_attestation_agent_t *this, imv_state_t *state, imv_msg_t *in_msg) { - imv_attestation_state_t *attestation_state; imv_msg_t *out_msg; + imv_session_t *session; + imv_os_info_t *os_info = NULL; enumerator_t *enumerator; pa_tnc_attr_t *attr; pen_type_t type; TNC_Result result; - pts_t *pts; - chunk_t os_name = chunk_empty; - chunk_t os_version = chunk_empty; + chunk_t os_name, os_version; bool fatal_error = FALSE; /* parse received PA-TNC message and handle local and remote errors */ @@ -149,8 +150,8 @@ static TNC_Result receive_msg(private_imv_attestation_agent_t *this, return result; } - attestation_state = (imv_attestation_state_t*)state; - pts = attestation_state->get_pts(attestation_state); + session = state->get_session(state); + os_info = session->get_os_info(session); out_msg = imv_msg_create_as_reply(in_msg); out_msg->set_msg_type(out_msg, msg_types[0]); @@ -189,16 +190,22 @@ static TNC_Result receive_msg(private_imv_attestation_agent_t *this, { ietf_attr_product_info_t *attr_cast; + state->set_action_flags(state, + IMV_ATTESTATION_ATTR_PRODUCT_INFO); attr_cast = (ietf_attr_product_info_t*)attr; os_name = attr_cast->get_info(attr_cast, NULL, NULL); + os_info->set_name(os_info, os_name); break; } case IETF_ATTR_STRING_VERSION: { ietf_attr_string_version_t *attr_cast; + state->set_action_flags(state, + IMV_ATTESTATION_ATTR_STRING_VERSION); attr_cast = (ietf_attr_string_version_t*)attr; os_version = attr_cast->get_version(attr_cast, NULL, NULL); + os_info->set_version(os_info, os_version); break; } default: @@ -218,15 +225,6 @@ static TNC_Result receive_msg(private_imv_attestation_agent_t *this, } enumerator->destroy(enumerator); - /** - * The IETF Product Information and String Version attributes - * are supposed to arrive in the same PA-TNC message - */ - if (os_name.len && os_version.len) - { - pts->set_platform_info(pts, os_name, os_version); - } - if (fatal_error || result != TNC_RESULT_SUCCESS) { state->set_recommendation(state, @@ -288,12 +286,39 @@ METHOD(imv_agent_if_t, receive_message_long, TNC_Result, return result; } +/** + * Build an IETF Attribute Request attribute for missing attributes + */ +static pa_tnc_attr_t* build_attr_request(u_int32_t received) +{ + pa_tnc_attr_t *attr; + ietf_attr_attr_request_t *attr_cast; + + attr = ietf_attr_attr_request_create(PEN_RESERVED, 0); + attr_cast = (ietf_attr_attr_request_t*)attr; + + if (!(received & IMV_ATTESTATION_ATTR_PRODUCT_INFO) || + !(received & IMV_ATTESTATION_ATTR_STRING_VERSION)) + { + attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_PRODUCT_INFORMATION); + attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_STRING_VERSION); + } +/* + if (!(received & IMV_ATTESTATION_ATTR_DEVICE_ID)) + { + attr_cast->add(attr_cast, PEN_ITA, ITA_ATTR_DEVICE_ID); + } +*/ + return attr; +} + METHOD(imv_agent_if_t, batch_ending, TNC_Result, private_imv_attestation_agent_t *this, TNC_ConnectionID id) { imv_msg_t *out_msg; imv_state_t *state; imv_session_t *session; + imv_os_info_t *os_info; imv_attestation_state_t *attestation_state; imv_attestation_handshake_state_t handshake_state; imv_workitem_t *workitem; @@ -302,7 +327,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, TNC_IMVID imv_id; TNC_Result result = TNC_RESULT_SUCCESS; pts_t *pts; - char *platform_info; + u_int32_t actions; enumerator_t *enumerator; if (!this->agent->get_state(this->agent, id, &state)) @@ -312,40 +337,36 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, attestation_state = (imv_attestation_state_t*)state; pts = attestation_state->get_pts(attestation_state); handshake_state = attestation_state->get_handshake_state(attestation_state); - platform_info = pts->get_platform_info(pts); + actions = state->get_action_flags(state); session = state->get_session(state); imv_id = this->agent->get_id(this->agent); /* exit if a recommendation has already been provided */ - if (state->get_action_flags(state) & IMV_ATTESTATION_FLAG_REC) + if (actions & IMV_ATTESTATION_REC) { return TNC_RESULT_SUCCESS; } /* send an IETF attribute request if no platform info was received */ - if (!platform_info && - !(state->get_action_flags(state) & IMV_ATTESTATION_FLAG_ATTR_REQ)) + if (!(actions & IMV_ATTESTATION_ATTR_REQ)) { - pa_tnc_attr_t *attr; - ietf_attr_attr_request_t *attr_cast; - imv_msg_t *os_msg; - - attr = ietf_attr_attr_request_create(PEN_IETF, - IETF_ATTR_PRODUCT_INFORMATION); - attr_cast = (ietf_attr_attr_request_t*)attr; - attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_STRING_VERSION); + if ((actions & IMV_ATTESTATION_ATTR_MUST) != IMV_ATTESTATION_ATTR_MUST) + { + imv_msg_t *os_msg; - os_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY, - msg_types[1]); - os_msg->add_attribute(os_msg, attr); - result = os_msg->send(os_msg, FALSE); - os_msg->destroy(os_msg); + /* create attribute request for missing mandatory attributes */ + os_msg = imv_msg_create(this->agent, state, id, imv_id, + TNC_IMCID_ANY, msg_types[1]); + os_msg->add_attribute(os_msg, build_attr_request(actions)); + result = os_msg->send(os_msg, FALSE); + os_msg->destroy(os_msg); - if (result != TNC_RESULT_SUCCESS) - { - return result; - } - state->set_action_flags(state, IMV_ATTESTATION_FLAG_ATTR_REQ); + if (result != TNC_RESULT_SUCCESS) + { + return result; + } + } + state->set_action_flags(state, IMV_ATTESTATION_ATTR_REQ); } if (handshake_state == IMV_ATTESTATION_STATE_INIT) @@ -378,18 +399,19 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, } /* exit if we are not ready yet for PTS measurements */ - if (!platform_info || !session || - !(state->get_action_flags(state) & IMV_ATTESTATION_FLAG_ALGO)) + if (!session->get_policy_started(session) || !(actions & IMV_ATTESTATION_ALGO)) { return TNC_RESULT_SUCCESS; } + os_info = session->get_os_info(session); + pts->set_platform_info(pts, os_info->get_info(os_info)); /* create an empty out message - we might need it */ out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY, msg_types[0]); /* establish the PTS measurements to be taken */ - if (!(state->get_action_flags(state) & IMV_ATTESTATION_FLAG_FILE_MEAS)) + if (!(actions & IMV_ATTESTATION_FILE_MEAS)) { bool is_dir, no_workitems = TRUE; u_int32_t delimiter = SOLIDUS_UTF; @@ -555,7 +577,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, enumerator->destroy(enumerator); /* sent all file and directory measurement and metadata requests */ - state->set_action_flags(state, IMV_ATTESTATION_FLAG_FILE_MEAS); + state->set_action_flags(state, IMV_ATTESTATION_FILE_MEAS); if (no_workitems) { @@ -600,14 +622,14 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, enumerator->destroy(enumerator); /* finalized all workitems? */ - if (session && session->get_policy_started(session) && + if (session->get_policy_started(session) && session->get_workitem_count(session, imv_id) == 0 && attestation_state->get_handshake_state(attestation_state) == IMV_ATTESTATION_STATE_END) { result = out_msg->send_assessment(out_msg); out_msg->destroy(out_msg); - state->set_action_flags(state, IMV_ATTESTATION_FLAG_REC); + state->set_action_flags(state, IMV_ATTESTATION_REC); if (result != TNC_RESULT_SUCCESS) { @@ -642,7 +664,7 @@ METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result, session = state->get_session(state); imv_id = this->agent->get_id(this->agent); - if (session) + if (imcv_db) { TNC_IMV_Evaluation_Result eval; TNC_IMV_Action_Recommendation rec; diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_build.c b/src/libpts/plugins/imv_attestation/imv_attestation_build.c index 84023c6c66..5688a7df52 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation_build.c +++ b/src/libpts/plugins/imv_attestation/imv_attestation_build.c @@ -90,7 +90,6 @@ bool imv_attestation_build(imv_msg_t *out_msg, imv_state_t *state, enumerator_t *enumerator; pts_comp_func_name_t *name; chunk_t keyid; - int kid; u_int8_t flags; u_int32_t depth; bool first_component = TRUE; @@ -98,8 +97,7 @@ bool imv_attestation_build(imv_msg_t *out_msg, imv_state_t *state, attestation_state->set_handshake_state(attestation_state, IMV_ATTESTATION_STATE_END); - if (!pts->get_aik_keyid(pts, &keyid) || - pts_db->check_aik_keyid(pts_db, keyid, &kid) != SUCCESS) + if (!pts->get_aik_keyid(pts, &keyid)) { attestation_state->set_measurement_error(attestation_state, IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK); diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_process.c b/src/libpts/plugins/imv_attestation/imv_attestation_process.c index e40c92a24b..92490587f2 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation_process.c +++ b/src/libpts/plugins/imv_attestation/imv_attestation_process.c @@ -46,10 +46,12 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg, pts_database_t *pts_db, credential_manager_t *pts_credmgr) { + imv_session_t *session; imv_attestation_state_t *attestation_state; pen_type_t attr_type; pts_t *pts; + session = state->get_session(state); attestation_state = (imv_attestation_state_t*)state; pts = attestation_state->get_pts(attestation_state); attr_type = attr->get_type(attr); @@ -80,7 +82,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg, return FALSE; } pts->set_meas_algorithm(pts, selected_algorithm); - state->set_action_flags(state, IMV_ATTESTATION_FLAG_ALGO); + state->set_action_flags(state, IMV_ATTESTATION_ALGO); break; } case TCG_PTS_DH_NONCE_PARAMS_RESP: @@ -157,9 +159,9 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg, tcg_pts_attr_aik_t *attr_cast; certificate_t *aik, *issuer; public_key_t *public; - chunk_t keyid; + chunk_t keyid, keyid_hex, device_id; enumerator_t *e; - bool trusted = FALSE; + bool trusted = FALSE, trusted_chain = FALSE; attr_cast = (tcg_pts_attr_aik_t*)attr; aik = attr_cast->get_aik(attr_cast); @@ -170,12 +172,27 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg, IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK); break; } + + /* check trust into public key as stored in the database */ + public = aik->get_public_key(aik); + public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid); + DBG1(DBG_IMV, "verifying AIK with keyid %#B", &keyid); + keyid_hex = chunk_to_hex(keyid, NULL, FALSE); + if (session->get_device_id(session, &device_id) && + chunk_equals(keyid_hex, device_id)) + { + trusted = session->get_device_trust(session); + } + else + { + DBG1(DBG_IMV, "device ID unknown or different from AIK keyid"); + } + DBG1(DBG_IMV, "AIK public key is %strusted", trusted ? "" : "not "); + public->destroy(public); + chunk_free(&keyid_hex); + if (aik->get_type(aik) == CERT_X509) { - public = aik->get_public_key(aik); - public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid); - DBG1(DBG_IMV, "verifying AIK certificate with keyid %#B", &keyid); - public->destroy(public); e = pts_credmgr->create_trusted_enumerator(pts_credmgr, KEY_ANY, aik->get_issuer(aik), FALSE); @@ -183,14 +200,14 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg, { if (aik->issued_by(aik, issuer, NULL)) { - trusted = TRUE; + trusted_chain = TRUE; break; } } e->destroy(e); DBG1(DBG_IMV, "AIK certificate is %strusted", - trusted ? "" : "not "); - if (!trusted) + trusted_chain ? "" : "not "); + if (!trusted || !trusted_chain) { attestation_state->set_measurement_error(attestation_state, IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK); diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_state.c b/src/libpts/plugins/imv_attestation/imv_attestation_state.c index 9304b9a13d..28ad8495c4 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation_state.c +++ b/src/libpts/plugins/imv_attestation/imv_attestation_state.c @@ -63,22 +63,12 @@ struct private_imv_attestation_state_t { /** * Maximum PA-TNC message size for this TNCCS connection */ - u_int32_t max_msg_len; + uint32_t max_msg_len; /** * Flags set for completed actions */ - u_int32_t action_flags; - - /** - * Access Requestor ID Type - */ - u_int32_t ar_id_type; - - /** - * Access Requestor ID Value - */ - chunk_t ar_id_value; + uint32_t action_flags; /** * IMV database session associated with TNCCS connection @@ -113,7 +103,7 @@ struct private_imv_attestation_state_t { /** * Measurement error flags */ - u_int32_t measurement_error; + uint32_t measurement_error; /** * TNC Reason String @@ -215,46 +205,29 @@ METHOD(imv_state_t, set_flags, void, } METHOD(imv_state_t, set_max_msg_len, void, - private_imv_attestation_state_t *this, u_int32_t max_msg_len) + private_imv_attestation_state_t *this, uint32_t max_msg_len) { this->max_msg_len = max_msg_len; } -METHOD(imv_state_t, get_max_msg_len, u_int32_t, +METHOD(imv_state_t, get_max_msg_len, uint32_t, private_imv_attestation_state_t *this) { return this->max_msg_len; } METHOD(imv_state_t, set_action_flags, void, - private_imv_attestation_state_t *this, u_int32_t flags) + private_imv_attestation_state_t *this, uint32_t flags) { this->action_flags |= flags; } -METHOD(imv_state_t, get_action_flags, u_int32_t, +METHOD(imv_state_t, get_action_flags, uint32_t, private_imv_attestation_state_t *this) { return this->action_flags; } -METHOD(imv_state_t, set_ar_id, void, - private_imv_attestation_state_t *this, u_int32_t id_type, chunk_t id_value) -{ - this->ar_id_type = id_type; - this->ar_id_value = chunk_clone(id_value); -} - -METHOD(imv_state_t, get_ar_id, chunk_t, - private_imv_attestation_state_t *this, u_int32_t *id_type) -{ - if (id_type) - { - *id_type = this->ar_id_type; - } - return this->ar_id_value; -} - METHOD(imv_state_t, set_session, void, private_imv_attestation_state_t *this, imv_session_t *session) { @@ -362,7 +335,6 @@ METHOD(imv_state_t, destroy, void, DESTROY_IF(this->reason_string); this->components->destroy_function(this->components, (void *)free_func_comp); this->pts->destroy(this->pts); - free(this->ar_id_value.ptr); free(this); } @@ -387,7 +359,7 @@ METHOD(imv_attestation_state_t, get_pts, pts_t*, METHOD(imv_attestation_state_t, create_component, pts_component_t*, private_imv_attestation_state_t *this, pts_comp_func_name_t *name, - u_int32_t depth, pts_database_t *pts_db) + uint32_t depth, pts_database_t *pts_db) { enumerator_t *enumerator; func_comp_t *entry, *new_entry; @@ -438,7 +410,7 @@ METHOD(imv_attestation_state_t, create_component, pts_component_t*, * Enumerate file measurement entries */ static bool entry_filter(void *null, func_comp_t **entry, u_int8_t *flags, - void *i2, u_int32_t *depth, + void *i2, uint32_t *depth, void *i3, pts_comp_func_name_t **comp_name) { pts_component_t *comp; @@ -482,14 +454,14 @@ METHOD(imv_attestation_state_t, get_component, pts_component_t*, return found; } -METHOD(imv_attestation_state_t, get_measurement_error, u_int32_t, +METHOD(imv_attestation_state_t, get_measurement_error, uint32_t, private_imv_attestation_state_t *this) { return this->measurement_error; } METHOD(imv_attestation_state_t, set_measurement_error, void, - private_imv_attestation_state_t *this, u_int32_t error) + private_imv_attestation_state_t *this, uint32_t error) { this->measurement_error |= error; } @@ -529,8 +501,6 @@ imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id) .get_max_msg_len = _get_max_msg_len, .set_action_flags = _set_action_flags, .get_action_flags = _get_action_flags, - .set_ar_id = _set_ar_id, - .get_ar_id = _get_ar_id, .set_session = _set_session, .get_session = _get_session, .change_state = _change_state, diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_state.h b/src/libpts/plugins/imv_attestation/imv_attestation_state.h index 9369d30a2f..2019a56b2d 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation_state.h +++ b/src/libpts/plugins/imv_attestation/imv_attestation_state.h @@ -40,10 +40,14 @@ typedef enum imv_meas_error_t imv_meas_error_t; * IMV Attestation Flags set for completed actions */ enum imv_attestation_flag_t { - IMV_ATTESTATION_FLAG_ATTR_REQ = (1<<0), - IMV_ATTESTATION_FLAG_ALGO = (1<<1), - IMV_ATTESTATION_FLAG_FILE_MEAS = (1<<2), - IMV_ATTESTATION_FLAG_REC = (1<<3) + IMV_ATTESTATION_ATTR_PRODUCT_INFO = (1<<0), + IMV_ATTESTATION_ATTR_STRING_VERSION = (1<<1), + IMV_ATTESTATION_ATTR_MUST = (1<<2)-1, + IMV_ATTESTATION_ATTR_DEVICE_ID = (1<<2), + IMV_ATTESTATION_ATTR_REQ = (1<<3), + IMV_ATTESTATION_ALGO = (1<<4), + IMV_ATTESTATION_FILE_MEAS = (1<<5), + IMV_ATTESTATION_REC = (1<<6) }; /** diff --git a/src/libpts/plugins/imv_swid/imv_swid_agent.c b/src/libpts/plugins/imv_swid/imv_swid_agent.c index a0326f88d6..743037ba5b 100644 --- a/src/libpts/plugins/imv_swid/imv_swid_agent.c +++ b/src/libpts/plugins/imv_swid/imv_swid_agent.c @@ -364,7 +364,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY, msg_types[0]); - if (!session) + if (!imcv_db) { DBG2(DBG_IMV, "no workitems available - no evaluation possible"); state->set_recommendation(state, @@ -381,7 +381,8 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result, return this->agent->provide_recommendation(this->agent, state); } - if (handshake_state == IMV_SWID_STATE_INIT) + if (handshake_state == IMV_SWID_STATE_INIT && + session->get_policy_started(session)) { enumerator = session->create_workitem_enumerator(session); if (enumerator) diff --git a/src/libpts/plugins/imv_swid/imv_swid_state.c b/src/libpts/plugins/imv_swid/imv_swid_state.c index 5be8c0254d..156a6bbe54 100644 --- a/src/libpts/plugins/imv_swid/imv_swid_state.c +++ b/src/libpts/plugins/imv_swid/imv_swid_state.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Andreas Steffen + * Copyright (C) 2013-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -58,22 +58,12 @@ struct private_imv_swid_state_t { /** * Maximum PA-TNC message size for this TNCCS connection */ - u_int32_t max_msg_len; + uint32_t max_msg_len; /** * Flags set for completed actions */ - u_int32_t action_flags; - - /** - * Access Requestor ID Type - */ - u_int32_t ar_id_type; - - /** - * Access Requestor ID Value - */ - chunk_t ar_id_value; + uint32_t action_flags; /** * IMV database session associatied with TNCCS connection @@ -133,46 +123,29 @@ METHOD(imv_state_t, set_flags, void, } METHOD(imv_state_t, set_max_msg_len, void, - private_imv_swid_state_t *this, u_int32_t max_msg_len) + private_imv_swid_state_t *this, uint32_t max_msg_len) { this->max_msg_len = max_msg_len; } -METHOD(imv_state_t, get_max_msg_len, u_int32_t, +METHOD(imv_state_t, get_max_msg_len, uint32_t, private_imv_swid_state_t *this) { return this->max_msg_len; } METHOD(imv_state_t, set_action_flags, void, - private_imv_swid_state_t *this, u_int32_t flags) + private_imv_swid_state_t *this, uint32_t flags) { this->action_flags |= flags; } -METHOD(imv_state_t, get_action_flags, u_int32_t, +METHOD(imv_state_t, get_action_flags, uint32_t, private_imv_swid_state_t *this) { return this->action_flags; } -METHOD(imv_state_t, set_ar_id, void, - private_imv_swid_state_t *this, u_int32_t id_type, chunk_t id_value) -{ - this->ar_id_type = id_type; - this->ar_id_value = chunk_clone(id_value); -} - -METHOD(imv_state_t, get_ar_id, chunk_t, - private_imv_swid_state_t *this, u_int32_t *id_type) -{ - if (id_type) - { - *id_type = this->ar_id_type; - } - return this->ar_id_value; -} - METHOD(imv_state_t, set_session, void, private_imv_swid_state_t *this, imv_session_t *session) { @@ -235,7 +208,6 @@ METHOD(imv_state_t, destroy, void, DESTROY_IF(this->session); DESTROY_IF(this->reason_string); DESTROY_IF(this->remediation_string); - free(this->ar_id_value.ptr); free(this); } @@ -269,8 +241,6 @@ imv_state_t *imv_swid_state_create(TNC_ConnectionID connection_id) .get_max_msg_len = _get_max_msg_len, .set_action_flags = _set_action_flags, .get_action_flags = _get_action_flags, - .set_ar_id = _set_ar_id, - .get_ar_id = _get_ar_id, .set_session = _set_session, .get_session= _get_session, .change_state = _change_state, diff --git a/src/libpts/pts/pts.c b/src/libpts/pts/pts.c index 178a6421f2..d155f2dcfc 100644 --- a/src/libpts/pts/pts.c +++ b/src/libpts/pts/pts.c @@ -337,15 +337,10 @@ METHOD(pts_t, get_platform_info, char*, } METHOD(pts_t, set_platform_info, void, - private_pts_t *this, chunk_t name, chunk_t version) + private_pts_t *this, char *info) { - 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 = malloc(len); - snprintf(this->platform_info, len, "%.*s %.*s", (int)name.len, name.ptr, - (int)version.len, version.ptr); + this->platform_info = strdup(info); } METHOD(pts_t, get_tpm_version_info, bool, diff --git a/src/libpts/pts/pts.h b/src/libpts/pts/pts.h index 11154aa385..bff1dba84e 100644 --- a/src/libpts/pts/pts.h +++ b/src/libpts/pts/pts.h @@ -174,7 +174,7 @@ struct pts_t { * @param name OS name * @param version OS version */ - void (*set_platform_info)(pts_t *this, chunk_t name, chunk_t version); + void (*set_platform_info)(pts_t *this, char *info); /** * Get TPM 1.2 Version Info diff --git a/src/libpts/pts/pts_database.c b/src/libpts/pts/pts_database.c index fda644a6ab..30002d7ef5 100644 --- a/src/libpts/pts/pts_database.c +++ b/src/libpts/pts/pts_database.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen + * Copyright (C) 2011-2012 Sansar Choinyambuu + * Copyright (C) 2012-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -114,10 +115,15 @@ METHOD(pts_database_t, check_aik_keyid, status_t, private_pts_database_t *this, chunk_t keyid, int *kid) { enumerator_t *e; + chunk_t keyid_hex; + + /* Convert keyid into a hex-encoded string */ + keyid_hex = chunk_to_hex(keyid, NULL, FALSE); /* If the AIK is registered get the primary key */ e = this->db->query(this->db, - "SELECT id FROM keys WHERE keyid = ?", DB_BLOB, keyid, DB_INT); + "SELECT id FROM devices WHERE name = ?", + DB_TEXT, keyid_hex.ptr, DB_INT); if (!e) { DBG1(DBG_PTS, "no database query enumerator returned"); @@ -497,7 +503,6 @@ pts_database_t *pts_database_create(imv_database_t *imv_db) .get_pathname = _get_pathname, .create_comp_evid_enumerator = _create_comp_evid_enumerator, .create_file_hash_enumerator = _create_file_hash_enumerator, - .check_aik_keyid = _check_aik_keyid, .add_file_measurement = _add_file_measurement, .check_file_measurement = _check_file_measurement, .check_comp_measurement = _check_comp_measurement, diff --git a/src/libpts/pts/pts_database.h b/src/libpts/pts/pts_database.h index eb8aca3469..323d1b8543 100644 --- a/src/libpts/pts/pts_database.h +++ b/src/libpts/pts/pts_database.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011-2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -61,7 +61,7 @@ struct pts_database_t { * Check if an AIK given by its keyid is registered in the database * * @param keyid AIK keyid (SHA-1 hash of the AIK public key info) - * @param kid Primary key of AIK entry in keys table + * @param kid Primary key of AIK entry in devices table * @return SUCCESS if AIK is present, FAILED otherwise */ status_t (*check_aik_keyid)(pts_database_t *this, chunk_t keyid, int *kid);