check installed packages in OS database
This commit is contained in:
@@ -9,7 +9,9 @@ imcv_LTLIBRARIES = imv-os.la
|
|||||||
imv_os_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
|
imv_os_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
|
||||||
$(top_builddir)/src/libstrongswan/libstrongswan.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
|
imv_os_la_LDFLAGS = -module -avoid-version
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "imv_os_state.h"
|
#include "imv_os_state.h"
|
||||||
|
#include "imv_os_database.h"
|
||||||
|
|
||||||
#include <imv/imv_agent.h>
|
#include <imv/imv_agent.h>
|
||||||
#include <imv/imv_msg.h>
|
#include <imv/imv_msg.h>
|
||||||
@@ -51,6 +52,11 @@ static pen_type_t msg_types[] = {
|
|||||||
|
|
||||||
static imv_agent_t *imv_os;
|
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
|
* 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 max_version,
|
||||||
TNC_Version *actual_version)
|
TNC_Version *actual_version)
|
||||||
{
|
{
|
||||||
|
char *uri;
|
||||||
|
|
||||||
if (imv_os)
|
if (imv_os)
|
||||||
{
|
{
|
||||||
DBG1(DBG_IMV, "IMV \"%s\" has already been initialized", imv_name);
|
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;
|
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;
|
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;
|
ietf_attr_installed_packages_t *attr_cast;
|
||||||
enumerator_t *e;
|
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))
|
|
||||||
{
|
|
||||||
DBG1(DBG_IMV, "package '%.*s' %.*s", name.len, name.ptr,
|
|
||||||
version.len, version.ptr);
|
|
||||||
}
|
|
||||||
e->destroy(e);
|
|
||||||
|
|
||||||
/* Received at least one Installed Packages attribute */
|
/* Received at least one Installed Packages attribute */
|
||||||
os_state->set_package_request(os_state, FALSE);
|
os_state->set_package_request(os_state, FALSE);
|
||||||
|
|
||||||
|
if (!os_db)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
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;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
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);
|
DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
|
||||||
return TNC_RESULT_NOT_INITIALIZED;
|
return TNC_RESULT_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
DESTROY_IF(os_db);
|
||||||
|
|
||||||
imv_os->destroy(imv_os);
|
imv_os->destroy(imv_os);
|
||||||
imv_os = NULL;
|
imv_os = NULL;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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_ @}*/
|
||||||
Reference in New Issue
Block a user