*/
#include "imv_os_state.h"
+#include "imv_os_database.h"
#include <imv/imv_agent.h>
#include <imv/imv_msg.h>
static imv_agent_t *imv_os;
+/**
+ * IMV OS database
+ */
+static imv_os_database_t *os_db;
+
/*
* see section 3.8.1 of TCG TNC IF-IMV Specification 1.3
*/
TNC_Version max_version,
TNC_Version *actual_version)
{
+ char *uri;
+
if (imv_os)
{
DBG1(DBG_IMV, "IMV \"%s\" has already been initialized", imv_name);
return TNC_RESULT_NO_COMMON_VERSION;
}
+ /* attach OS database */
+ uri = lib->settings->get_str(lib->settings,
+ "libimcv.plugins.imv-os.database", NULL);
+ if (uri)
+ {
+ os_db = imv_os_database_create(uri);
+ }
+
return TNC_RESULT_SUCCESS;
}
{
ietf_attr_installed_packages_t *attr_cast;
enumerator_t *e;
- chunk_t name, version;
+ status_t status;
- attr_cast = (ietf_attr_installed_packages_t*)attr;
- e = attr_cast->create_enumerator(attr_cast);
- while (e->enumerate(e, &name, &version))
+ /* Received at least one Installed Packages attribute */
+ os_state->set_package_request(os_state, FALSE);
+
+ if (!os_db)
{
- DBG1(DBG_IMV, "package '%.*s' %.*s", name.len, name.ptr,
- version.len, version.ptr);
+ break;
}
+ attr_cast = (ietf_attr_installed_packages_t*)attr;
+
+ e = attr_cast->create_enumerator(attr_cast);
+ status = os_db->check_packages(os_db,
+ os_state->get_info(os_state), e);
e->destroy(e);
- /* Received at least one Installed Packages attribute */
- os_state->set_package_request(os_state, FALSE);
+ switch (status)
+ {
+ case VERIFY_ERROR:
+ state->set_recommendation(state,
+ TNC_IMV_ACTION_RECOMMENDATION_ISOLATE,
+ TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR);
+ assessment = TRUE;
+ break;
+ case FAILED:
+ state->set_recommendation(state,
+ TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
+ TNC_IMV_EVALUATION_RESULT_ERROR);
+ assessment = TRUE;
+ break;
+ default:
+ break;
+ }
break;
}
default:
DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
return TNC_RESULT_NOT_INITIALIZED;
}
+ DESTROY_IF(os_db);
+
imv_os->destroy(imv_os);
imv_os = NULL;
--- /dev/null
+/*
+ * Copyright (C) 2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "imv_os_database.h"
+
+#include <utils/debug.h>
+
+typedef struct private_imv_os_database_t private_imv_os_database_t;
+
+/**
+ * Private data of a imv_os_database_t object.
+ *
+ */
+struct private_imv_os_database_t {
+
+ /**
+ * Public imv_os_database_t interface.
+ */
+ imv_os_database_t public;
+
+ /**
+ * database instance
+ */
+ database_t *db;
+
+};
+
+METHOD(imv_os_database_t, check_packages, status_t,
+ private_imv_os_database_t *this, char *os_info,
+ enumerator_t *package_enumerator)
+{
+ char *product, *package, *release, *cur_release, *pos;
+ size_t len;
+ int pid, gid, security, i;
+ int count = 0, count_ok = 0, count_no_match = 0, count_not_found = 0;
+ enumerator_t *e;
+ chunk_t name, version;
+ status_t status = SUCCESS;
+ bool found, match;
+
+ char *platform[] = {
+ "i686",
+ "x86_64"
+ };
+
+ /* looking for appended platform info */
+ for (i = 0; i < countof(platform); i++)
+ {
+ pos = strstr(os_info, platform[i]);
+ if (pos)
+ {
+ break;
+ }
+ }
+ if (pos)
+ {
+ /* Remove platform info, leaving OS name and version only */
+ len = pos - os_info - 1;
+ product = malloc(len + 1);
+ memcpy(product, os_info, len);
+ product[len] = '\0';
+ }
+ else
+ {
+ product = strdup(os_info);
+ }
+
+ /* Get primary key of product */
+ e = this->db->query(this->db,
+ "SELECT id FROM products WHERE name = ?",
+ DB_TEXT, product, DB_INT);
+ if (!e)
+ {
+ free(product);
+ return FAILED;
+ }
+ if (!e->enumerate(e, &pid))
+ {
+ e->destroy(e);
+ free(product);
+ return NOT_FOUND;
+ }
+ e->destroy(e);
+
+ DBG1(DBG_IMV, "'%s': pid = %d", product, pid);
+
+ while (package_enumerator->enumerate(package_enumerator, &name, &version))
+ {
+ /* Convert package name chunk to a string */
+ package = malloc(name.len + 1);
+ memcpy(package, name.ptr, name.len);
+ package[name.len] = '\0';
+ count++;
+
+ /* Get primary key of package */
+ e = this->db->query(this->db,
+ "SELECT id FROM packages WHERE name = ?",
+ DB_TEXT, package, DB_INT);
+ if (!e)
+ {
+ free(product);
+ free(package);
+ return FAILED;
+ }
+ if (!e->enumerate(e, &gid))
+ {
+ /* not found in database vor any product - skip */
+ count_not_found++;
+ e->destroy(e);
+ continue;
+ }
+ e->destroy(e);
+
+ /* Convert package version chunk to a string */
+ release = malloc(version.len + 1);
+ memcpy(release, version.ptr, version.len);
+ release[version.len] = '\0';
+
+ /* Enumerate over all acceptable versions */
+ e = this->db->query(this->db,
+ "SELECT release, security FROM versions "
+ "WHERE product = ? AND package = ?",
+ DB_INT, pid, DB_INT, gid, DB_TEXT, DB_INT);
+ if (!e)
+ {
+ free(product);
+ free(package);
+ free(release);
+ return FAILED;
+ }
+ found = FALSE;
+ match = FALSE;
+
+ while (e->enumerate(e, &cur_release, &security))
+ {
+ found = TRUE;
+ if (streq(release, cur_release))
+ {
+ match = TRUE;
+ break;
+ }
+ }
+ e->destroy(e);
+
+ if (found)
+ {
+ if (match)
+ {
+ DBG2(DBG_IMV, "package '%s' (%s)%s is ok", package, release,
+ security ? " [s]" : "");
+ count_ok++;
+ }
+ else
+ {
+ DBG1(DBG_IMV, "package '%s' (%s) no match", package, release);
+ count_no_match++;
+ status = VERIFY_ERROR;
+ }
+ }
+ else
+ {
+ count_not_found++;
+ }
+ free(package);
+ free(release);
+ }
+ free(product);
+
+ DBG1(DBG_IMV, "processed %d packages: %d ok, %d no match, %d not found",
+ count, count_ok, count_no_match, count_not_found);
+
+ return status;
+}
+
+METHOD(imv_os_database_t, destroy, void,
+ private_imv_os_database_t *this)
+{
+ this->db->destroy(this->db);
+ free(this);
+}
+
+/**
+ * See header
+ */
+imv_os_database_t *imv_os_database_create(char *uri)
+{
+ private_imv_os_database_t *this;
+
+ INIT(this,
+ .public = {
+ .check_packages = _check_packages,
+ .destroy = _destroy,
+ },
+ .db = lib->db->create(lib->db, uri),
+ );
+
+ if (!this->db)
+ {
+ DBG1(DBG_IMV,
+ "failed to connect to OS database '%s'", uri);
+ free(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
+
--- /dev/null
+/*
+ * Copyright (C) 2012 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ *
+ * @defgroup imv_os_database_t imv_os_database
+ * @{ @ingroup imv_os_database
+ */
+
+#ifndef IMV_OS_DATABASE_H_
+#define IMV_OS_DATABASE_H_
+
+#include <library.h>
+
+typedef struct imv_os_database_t imv_os_database_t;
+
+/**
+ * Internal state of an imv_os_database_t instance
+ */
+struct imv_os_database_t {
+
+ /**
+ * Check Installed Packages for a given OS
+ *
+ * @param os_info OS name and version
+ * @param package_enumerator enumerates over installed packages
+ */
+ status_t (*check_packages)(imv_os_database_t *this, char* os_info,
+ enumerator_t *package_enumerator);
+
+ /**
+ * Destroys an imv_os_database_t object.
+ */
+ void (*destroy)(imv_os_database_t *this);
+
+};
+
+/**
+ * Create an imv_os_database_t instance
+ *
+ * @param uri database uri
+ */
+imv_os_database_t* imv_os_database_create(char *uri);
+
+#endif /** IMV_OS_DATABASE_H_ @}*/