diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libimcv/plugins/imv_os/Makefile.am | 4 | ||||
-rw-r--r-- | src/libimcv/plugins/imv_os/imv_os.c | 54 | ||||
-rw-r--r-- | src/libimcv/plugins/imv_os/imv_os_database.c | 219 | ||||
-rw-r--r-- | src/libimcv/plugins/imv_os/imv_os_database.h | 57 |
4 files changed, 325 insertions, 9 deletions
diff --git a/src/libimcv/plugins/imv_os/Makefile.am b/src/libimcv/plugins/imv_os/Makefile.am index 195c458bc..e0a04af84 100644 --- a/src/libimcv/plugins/imv_os/Makefile.am +++ b/src/libimcv/plugins/imv_os/Makefile.am @@ -9,7 +9,9 @@ imcv_LTLIBRARIES = imv-os.la imv_os_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \ $(top_builddir)/src/libstrongswan/libstrongswan.la -imv_os_la_SOURCES = imv_os.c imv_os_state.h imv_os_state.c +imv_os_la_SOURCES = \ + imv_os.c imv_os_state.h imv_os_state.c \ + imv_os_database.c imv_os_database.h imv_os_la_LDFLAGS = -module -avoid-version diff --git a/src/libimcv/plugins/imv_os/imv_os.c b/src/libimcv/plugins/imv_os/imv_os.c index a9ba0f9af..f2e00da5a 100644 --- a/src/libimcv/plugins/imv_os/imv_os.c +++ b/src/libimcv/plugins/imv_os/imv_os.c @@ -14,6 +14,7 @@ */ #include "imv_os_state.h" +#include "imv_os_database.h" #include <imv/imv_agent.h> #include <imv/imv_msg.h> @@ -51,6 +52,11 @@ static pen_type_t msg_types[] = { 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 */ @@ -59,6 +65,8 @@ TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id, TNC_Version max_version, TNC_Version *actual_version) { + char *uri; + if (imv_os) { DBG1(DBG_IMV, "IMV \"%s\" has already been initialized", imv_name); @@ -76,6 +84,14 @@ TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id, 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; } @@ -242,19 +258,39 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) { 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: @@ -529,6 +565,8 @@ TNC_Result TNC_IMV_Terminate(TNC_IMVID imv_id) 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; diff --git a/src/libimcv/plugins/imv_os/imv_os_database.c b/src/libimcv/plugins/imv_os/imv_os_database.c new file mode 100644 index 000000000..a2be4330f --- /dev/null +++ b/src/libimcv/plugins/imv_os/imv_os_database.c @@ -0,0 +1,219 @@ +/* + * 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; +} + diff --git a/src/libimcv/plugins/imv_os/imv_os_database.h b/src/libimcv/plugins/imv_os/imv_os_database.h new file mode 100644 index 000000000..b1e6b90ea --- /dev/null +++ b/src/libimcv/plugins/imv_os/imv_os_database.h @@ -0,0 +1,57 @@ +/* + * 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_ @}*/ |