implemented IMV session control

This commit is contained in:
Andreas Steffen
2013-06-21 23:25:21 +02:00
parent 1f179c63b3
commit b8db66de15
21 changed files with 978 additions and 454 deletions
+1
View File
@@ -10,6 +10,7 @@ libimcv_la_SOURCES = \
imc/imc_agent.h imc/imc_agent.c imc/imc_state.h \
imc/imc_msg.h imc/imc_msg.c \
imv/imv_agent.h imv/imv_agent.c imv/imv_state.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_reason_string.h imv/imv_reason_string.c \
+47 -2
View File
@@ -62,6 +62,11 @@ struct private_imv_agent_t {
*/
linked_list_t *additional_ids;
/**
* IMV database
*/
imv_database_t *db;
/**
* list of TNCS connection entries
*/
@@ -402,11 +407,14 @@ METHOD(imv_agent_t, create_state, TNC_Result,
{
TNC_ConnectionID conn_id;
char *tnccs_p = NULL, *tnccs_v = NULL, *t_p = NULL, *t_v = NULL;
bool has_long = FALSE, has_excl = FALSE, has_soh = FALSE;
bool has_long = FALSE, has_excl = FALSE, has_soh = FALSE, first = TRUE;
linked_list_t *ar_identities;
enumerator_t *enumerator;
tncif_identity_t *tnc_id;
int session_id;
u_int32_t max_msg_len;
u_int32_t ar_id_type = TNC_ID_UNKNOWN;
chunk_t ar_id_value = chunk_empty;
conn_id = state->get_connection_id(state);
if (find_connection(this, conn_id))
@@ -462,10 +470,31 @@ METHOD(imv_agent_t, create_state, TNC_Result,
TNC_Subject_names, tcg_subject_type,
id_value.len, id_value.ptr,
TNC_Authentication_names, tcg_auth_type);
state->set_ar_id(state, tcg_id_type, id_value);
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 (this->db)
{
session_id = this->db->get_session_id(this->db, conn_id,
ar_id_type, ar_id_value);
if (session_id)
{
DBG2(DBG_IMV, " assigned session ID %d", session_id);
state->set_session_id(state, session_id);
}
else
{
DBG1(DBG_IMV, " no session ID assigned");
}
}
ar_identities->destroy_offset(ar_identities,
offsetof(tncif_identity_t, destroy));
free(tnccs_p);
@@ -553,6 +582,12 @@ METHOD(imv_agent_t, get_state, bool,
return TRUE;
}
METHOD(imv_agent_t, get_database, imv_database_t*,
private_imv_agent_t *this)
{
return this->db;
}
METHOD(imv_agent_t, get_name, const char*,
private_imv_agent_t *this)
{
@@ -754,6 +789,7 @@ METHOD(imv_agent_t, destroy, void,
private_imv_agent_t *this)
{
DBG1(DBG_IMV, "IMV %u \"%s\" terminated", this->id, this->name);
DESTROY_IF(this->db);
this->additional_ids->destroy(this->additional_ids);
this->connections->destroy_offset(this->connections,
offsetof(imv_state_t, destroy));
@@ -772,6 +808,7 @@ imv_agent_t *imv_agent_create(const char *name,
TNC_IMVID id, TNC_Version *actual_version)
{
private_imv_agent_t *this;
char *uri;
/* initialize or increase the reference count */
if (!libimcv_init())
@@ -786,6 +823,7 @@ imv_agent_t *imv_agent_create(const char *name,
.delete_state = _delete_state,
.change_state = _change_state,
.get_state = _get_state,
.get_database = _get_database,
.get_name = _get_name,
.get_id = _get_id,
.reserve_additional_ids = _reserve_additional_ids,
@@ -804,6 +842,13 @@ imv_agent_t *imv_agent_create(const char *name,
.connection_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
);
/* attach IMV database */
uri = lib->settings->get_str(lib->settings, "libimcv.database", NULL);
if (uri)
{
this->db = imv_database_create(uri);
}
*actual_version = TNC_IFIMV_VERSION_1;
DBG1(DBG_IMV, "IMV %u \"%s\" initialized", this->id, this->name);
+8
View File
@@ -23,6 +23,7 @@
#define IMV_AGENT_H_
#include "imv_state.h"
#include "imv_database.h"
#include "pa_tnc/pa_tnc_msg.h"
#include <tncifimv.h>
@@ -137,6 +138,13 @@ struct imv_agent_t {
bool (*get_state)(imv_agent_t *this,
TNC_ConnectionID connection_id, imv_state_t **state);
/**
* Get IMV database
*
* @return IMV database if it exists, NULL otherwise
*/
imv_database_t* (*get_database)(imv_agent_t *this);
/**
* Get IMV name
*
+209
View File
@@ -0,0 +1,209 @@
/*
* Copyright (C) 2013 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_database.h"
#include <utils/debug.h>
#include <string.h>
#include <time.h>
typedef struct private_imv_database_t private_imv_database_t;
#define SESSION_TIME_DELTA_MAX 2 /* seconds */
/**
* Private data of a imv_database_t object.
*
*/
struct private_imv_database_t {
/**
* Public imv_database_t interface.
*/
imv_database_t public;
/**
* database instance
*/
database_t *db;
};
METHOD(imv_database_t, get_session_id, int,
private_imv_database_t *this, TNC_ConnectionID id, u_int32_t ar_id_type,
chunk_t ar_id_value)
{
enumerator_t *e;
int ar_id = 0, session_id = 0;
u_int created;
time_t now;
/* get most recent session for a given connection ID if available */
e = this->db->query(this->db,
"SELECT id, time FROM sessions WHERE connection = ? "
"ORDER BY time DESC", DB_INT, id, DB_INT, DB_UINT);
if (e)
{
e->enumerate(e, &session_id, &created);
e->destroy(e);
}
/* get current time */
now = time(NULL);
/* check if a new session has already been created by another IMV */
if (session_id && (now - created) <= SESSION_TIME_DELTA_MAX)
{
return session_id;
}
if (ar_id_value.len)
{
/* get primary key of AR identity if it exists */
e = this->db->query(this->db,
"SELECT id FROM identities WHERE type = ? AND value = ?",
DB_INT, ar_id_type, DB_BLOB, ar_id_value, DB_INT);
if (e)
{
e->enumerate(e, &ar_id);
e->destroy(e);
}
/* if AR identity has not been found - register it */
if (!ar_id)
{
this->db->execute(this->db, &ar_id,
"INSERT INTO identities (type, value) VALUES (?, ?)",
DB_INT, ar_id_type, DB_BLOB, ar_id_value);
}
}
/* create a new session ID */
this->db->execute(this->db, &session_id,
"INSERT INTO sessions (time, connection, identity) "
"VALUES (?, ?, ?)", DB_UINT, now, DB_INT, id, DB_INT, ar_id);
return session_id;
}
METHOD(imv_database_t, add_product, int,
private_imv_database_t *this, int session_id, char *product)
{
enumerator_t *e;
int pid = 0;
/* get primary key of product info string if it exists */
e = this->db->query(this->db,
"SELECT id FROM products WHERE name = ?", DB_TEXT, product, DB_INT);
if (e)
{
e->enumerate(e, &pid);
e->destroy(e);
}
/* if product info string has not been found - register it */
if (!pid)
{
this->db->execute(this->db, &pid,
"INSERT INTO products (name) VALUES (?)", DB_TEXT, product);
}
/* add product reference to session */
if (pid)
{
this->db->execute(this->db, NULL,
"UPDATE sessions SET product = ? WHERE id = ?",
DB_INT, pid, DB_INT, session_id);
}
return pid;
}
METHOD(imv_database_t, add_device, int,
private_imv_database_t *this, int session_id, chunk_t device)
{
enumerator_t *e;
int did = 0;
/* get primary key of device identification if it exists */
e = this->db->query(this->db,
"SELECT id FROM devices WHERE value = ?", DB_BLOB, device, DB_INT);
if (e)
{
e->enumerate(e, &did);
e->destroy(e);
}
/* if device identification has not been found - register it */
if (!did)
{
this->db->execute(this->db, &did,
"INSERT INTO devices (value) VALUES (?)", DB_BLOB, device);
}
/* add device reference to session */
if (did)
{
this->db->execute(this->db, NULL,
"UPDATE sessions SET device = ? WHERE id = ?",
DB_INT, did, DB_INT, session_id);
}
return did;
}
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)
{
this->db->destroy(this->db);
free(this);
}
/**
* See header
*/
imv_database_t *imv_database_create(char *uri)
{
private_imv_database_t *this;
INIT(this,
.public = {
.get_session_id = _get_session_id,
.add_product = _add_product,
.add_device = _add_device,
.get_database = _get_database,
.destroy = _destroy,
},
.db = lib->db->create(lib->db, uri),
);
if (!this->db)
{
DBG1(DBG_IMV,
"failed to connect to IMV database '%s'", uri);
free(this);
return NULL;
}
return &this->public;
}
+85
View File
@@ -0,0 +1,85 @@
/*
* Copyright (C) 2013 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_database_t imv_database
* @{ @ingroup libimcv_imv
*/
#ifndef IMV_DATABASE_H_
#define IMV_DATABASE_H_
#include <tncif.h>
#include <library.h>
typedef struct imv_database_t imv_database_t;
/**
* IMV database interface
*/
struct imv_database_t {
/**
* Register or get a unique session ID using the TNCCS connection ID
*
* @param id TNCCS Connection ID
* @param ar_id_type Access Requestor identity type
* @param ar_id_value Access Requestor identity value
* @return Session ID or 0 if not available
*/
int (*get_session_id)(imv_database_t *this, TNC_ConnectionID id,
u_int32_t ar_id_type, chunk_t ar_id_value);
/**
* Add product information string to a session
*
* @param session_id Session ID
* @param product Product information string
* @return Product ID or 0 if not available
*/
int (*add_product)(imv_database_t *this, int session_id, char *product);
/**
* Add device identification to a session
*
* @param session_id Sessiion ID
* @param device Device identification
* @return Device ID or 0 if not available
*/
int (*add_device)(imv_database_t *this, int session_id, chunk_t device);
/**
* Get database handle
*
* @return Database handle
*/
database_t* (*get_database)(imv_database_t *this);
/**
* Destroys an imv_database_t object
*/
void (*destroy)(imv_database_t *this);
};
/**
* Create an imv_database_t instance
*
* @param uri database uri
*/
imv_database_t* imv_database_create(char *uri);
#endif /** IMV_DATABASE_H_ @}*/
+14
View File
@@ -94,6 +94,20 @@ struct imv_state_t {
*/
chunk_t (*get_ar_id)(imv_state_t *this, u_int32_t *id_type);
/**
* Set unique session ID
*
* @param session_id Unique session ID
*/
void (*set_session_id)(imv_state_t *this, int session_id);
/**
* Get unique session_id
*
* @return Unique session ID
*/
int (*get_session_id)(imv_state_t *this);
/**
* Change the connection state
*
+24 -20
View File
@@ -65,8 +65,6 @@ 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);
@@ -84,13 +82,8 @@ 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);
}
/* attach OS database co-located with IMV database */
os_db = imv_os_database_create(imv_os->get_database(imv_os));
return TNC_RESULT_SUCCESS;
}
@@ -289,7 +282,9 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg)
case ITA_ATTR_SETTINGS:
{
ita_attr_settings_t *attr_cast;
imv_database_t *imv_db;
enumerator_t *e;
int did;
char *name;
chunk_t value;
@@ -306,8 +301,13 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg)
else if ((streq(name, android_id_str) ||
streq(name, machine_id_str)) && os_db)
{
os_state->set_device_id(os_state,
os_db->get_device_id(os_db, value));
imv_db = imv_os->get_database(imv_os);
if (imv_db)
{
did = imv_db->add_device(imv_db,
state->get_session_id(state), value);
os_state->set_device_id(os_state, did);
}
}
DBG1(DBG_IMV, "setting '%s'\n %.*s",
name, value.len, value.ptr);
@@ -332,11 +332,19 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg)
{
os_type_t os_type;
ita_attr_get_settings_t *attr_cast;
imv_database_t *imv_db;
/* 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);
imv_db = imv_os->get_database(imv_os);
if (imv_db)
{
imv_db->add_product(imv_db, state->get_session_id(state),
os_state->get_info(os_state, NULL, NULL, NULL));
}
/* requesting installed packages */
os_state->set_package_request(os_state, TRUE);
attr = ietf_attr_attr_request_create(PEN_IETF,
@@ -376,10 +384,8 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg)
!os_state->get_angel_count(os_state) &&
os_state->get_info(os_state, NULL, NULL, NULL))
{
int device_id, count, count_update, count_blacklist, count_ok;
int count, count_update, count_blacklist, count_ok;
u_int os_settings;
u_int32_t id_type;
chunk_t id_value;
os_settings = os_state->get_os_settings(os_state);
os_state->get_count(os_state, &count, &count_update, &count_blacklist,
@@ -389,13 +395,10 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg)
count_ok, count - count_update - count_blacklist - count_ok);
/* Store device information in database */
device_id = os_state->get_device_id(os_state);
id_value = state->get_ar_id(state, &id_type);
if (os_db && device_id)
if (os_db)
{
os_db->set_device_info(os_db, device_id, id_type, id_value,
os_state->get_info(os_state, NULL, NULL, NULL),
count, count_update, count_blacklist, os_settings);
os_db->set_device_info(os_db, state->get_session_id(state),
count, count_update, count_blacklist, os_settings);
}
if (count_update || count_blacklist || os_settings)
@@ -589,6 +592,7 @@ TNC_Result TNC_IMV_Terminate(TNC_IMVID imv_id)
return TNC_RESULT_NOT_INITIALIZED;
}
DESTROY_IF(os_db);
os_db = NULL;
imv_os->destroy(imv_os);
imv_os = NULL;
+14 -116
View File
@@ -187,148 +187,46 @@ METHOD(imv_os_database_t, check_packages, status_t,
return status;
}
METHOD(imv_os_database_t, get_device_id, int,
private_imv_os_database_t *this, chunk_t value)
{
enumerator_t *e;
int id;
/* get primary key of device ID */
e = this->db->query(this->db, "SELECT id FROM devices WHERE value = ?",
DB_BLOB, value, DB_INT);
if (!e)
{
return 0;
}
if (e->enumerate(e, &id))
{
/* device ID already exists in database - return primary key */
e->destroy(e);
return id;
}
e->destroy(e);
/* register new device ID in database and return primary key */
return (this->db->execute(this->db, &id,
"INSERT INTO devices (value) VALUES (?)", DB_BLOB, value) == 1) ?
id : 0;
}
METHOD(imv_os_database_t, set_device_info, void,
private_imv_os_database_t *this, int device_id, u_int32_t ar_id_type,
chunk_t ar_id_value, char *os_info, int count, int count_update,
int count_blacklist, u_int flags)
private_imv_os_database_t *this, int session_id, int count,
int count_update, int count_blacklist, u_int flags)
{
enumerator_t *e;
time_t last_time;
int pid = 0, last_pid = 0, iid = 0, last_iid;
int last_count_update = 0, last_count_blacklist = 0;
u_int last_flags;
bool found = FALSE;
/* get primary key of OS info string if it exists */
e = this->db->query(this->db,
"SELECT id FROM products WHERE name = ?", DB_TEXT, os_info,
DB_INT);
if (e)
{
e->enumerate(e, &pid);
e->destroy(e);
}
/* if OS info string has not been found - register it */
if (!pid)
{
this->db->execute(this->db, &pid,
"INSERT INTO products (name) VALUES (?)", DB_TEXT, os_info);
}
/* get primary key of AR identity if it exists */
e = this->db->query(this->db,
"SELECT id FROM identities WHERE type = ? AND data = ?",
DB_INT, ar_id_type, DB_BLOB, ar_id_value, DB_INT);
if (e)
{
e->enumerate(e, &iid);
e->destroy(e);
}
/* if AR identity has not been found - register it */
if (!iid)
{
this->db->execute(this->db, &iid,
"INSERT INTO identities (type, data) VALUES (?, ?)",
DB_INT, ar_id_type, DB_BLOB, ar_id_value);
}
/* get latest device info record if it exists */
e = this->db->query(this->db,
"SELECT time, ar_id, product, count_update, count_blacklist, flags "
"FROM device_infos WHERE device = ? ORDER BY time DESC",
DB_INT, device_id, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, DB_UINT);
if (e)
{
found = e->enumerate(e, &last_time, &last_iid, &last_pid,
&last_count_update, &last_count_blacklist,
&last_flags);
e->destroy(e);
}
if (found && !last_count_update && !last_count_blacklist && !last_flags &&
iid == last_iid && pid == last_pid)
{
/* update device info */
this->db->execute(this->db, NULL,
"UPDATE device_infos SET time = ?, count = ?, count_update = ?, "
"count_blacklist = ?, flags = ? WHERE device = ? AND time = ?",
DB_UINT, time(NULL), DB_INT, count, DB_INT, count_update,
DB_INT, count_blacklist, DB_UINT, flags,
DB_INT, device_id, DB_UINT, last_time);
}
else
{
/* insert device info */
this->db->execute(this->db, NULL,
"INSERT INTO device_infos (device, time, ar_id, product, count, "
"count_update, count_blacklist, flags) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
DB_INT, device_id, DB_UINT, time(NULL), DB_INT, iid, DB_INT, pid,
DB_INT, count, DB_INT, count_update, DB_INT, count_blacklist,
DB_UINT, flags);
}
this->db->execute(this->db, NULL,
"INSERT INTO device_infos (session, count, count_update, "
"count_blacklist, flags) VALUES (?, ?, ?, ?, ?)",
DB_INT, session_id, DB_INT, count, DB_INT, count_update,
DB_INT, count_blacklist, DB_UINT, flags);
}
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)
imv_os_database_t *imv_os_database_create(imv_database_t *imv_db)
{
private_imv_os_database_t *this;
if (!imv_db)
{
return NULL;
}
INIT(this,
.public = {
.check_packages = _check_packages,
.get_device_id = _get_device_id,
.set_device_info = _set_device_info,
.destroy = _destroy,
},
.db = lib->db->create(lib->db, uri),
.db = imv_db->get_database(imv_db),
);
if (!this->db)
{
DBG1(DBG_IMV,
"failed to connect to OS database '%s'", uri);
free(this);
return NULL;
}
return &this->public;
}
+15 -26
View File
@@ -22,6 +22,7 @@
#define IMV_OS_DATABASE_H_
#include "imv_os_state.h"
#include "imv/imv_database.h"
#include <library.h>
@@ -42,32 +43,20 @@ struct imv_os_database_t {
enumerator_t *package_enumerator);
/**
* Get the primary database key of the device ID
*
* @param value Device ID value
*/
int (*get_device_id)(imv_os_database_t *this, chunk_t value);
* Set health infos for a given device
*
* @param sesson_id Session ID
* @param count Number of installed packages
* @param count_update Number of packages to be updated
* @param count_blacklist Number of blacklisted packages
* @param flags Various flags, e.g. illegal OS settings
*/
void (*set_device_info)(imv_os_database_t *this, int session_id, int count,
int count_update, int count_blacklist, u_int flags);
/**
* Set health infos for a given device
*
* @param device_id Device ID primary key
* @param ar_id_type Access Requestor ID Type
* @param ar_id_value Access Requestor ID Value
* @param os_info OS info string
* @param count Number of installed packages
* @param count_update Number of packages to be updated
* @param count_blacklist Number of blacklisted packages
* @param flags Various flags, e.g. illegal OS settings
*/
void (*set_device_info)(imv_os_database_t *this, int device_id,
u_int32_t ar_id_type, chunk_t ar_id_value,
char *os_info, int count, int count_update,
int count_blacklist, u_int flags);
/**
* Destroys an imv_os_database_t object.
*/
* Destroys an imv_os_database_t object.
*/
void (*destroy)(imv_os_database_t *this);
};
@@ -75,8 +64,8 @@ struct imv_os_database_t {
/**
* Create an imv_os_database_t instance
*
* @param uri database uri
* @param imv_db Already attached IMV database
*/
imv_os_database_t* imv_os_database_create(char *uri);
imv_os_database_t* imv_os_database_create(imv_database_t *imv_db);
#endif /** IMV_OS_DATABASE_H_ @}*/
+19
View File
@@ -71,6 +71,11 @@ struct private_imv_os_state_t {
*/
chunk_t ar_id_value;
/**
* Unique session ID
*/
int session_id;
/**
* IMV action recommendation
*/
@@ -346,6 +351,18 @@ METHOD(imv_state_t, get_ar_id, chunk_t,
return this->ar_id_value;
}
METHOD(imv_state_t, set_session_id, void,
private_imv_os_state_t *this, int session_id)
{
this->session_id = session_id;
}
METHOD(imv_state_t, get_session_id, int,
private_imv_os_state_t *this)
{
return this->session_id;
}
METHOD(imv_state_t, change_state, void,
private_imv_os_state_t *this, TNC_ConnectionState new_state)
{
@@ -633,6 +650,8 @@ imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id)
.get_max_msg_len = _get_max_msg_len,
.set_ar_id = _set_ar_id,
.get_ar_id = _get_ar_id,
.set_session_id = _set_session_id,
.get_session_id = _get_session_id,
.change_state = _change_state,
.get_recommendation = _get_recommendation,
.set_recommendation = _set_recommendation,
@@ -68,6 +68,11 @@ struct private_imv_scanner_state_t {
*/
chunk_t ar_id_value;
/**
* Unique session ID
*/
int session_id;
/**
* IMV action recommendation
*/
@@ -182,6 +187,18 @@ METHOD(imv_state_t, set_ar_id, void,
this->ar_id_value = chunk_clone(id_value);
}
METHOD(imv_state_t, set_session_id, void,
private_imv_scanner_state_t *this, int session_id)
{
this->session_id = session_id;
}
METHOD(imv_state_t, get_session_id, int,
private_imv_scanner_state_t *this)
{
return this->session_id;
}
METHOD(imv_state_t, get_ar_id, chunk_t,
private_imv_scanner_state_t *this, u_int32_t *id_type)
{
@@ -296,6 +313,8 @@ imv_state_t *imv_scanner_state_create(TNC_ConnectionID connection_id)
.get_max_msg_len = _get_max_msg_len,
.set_ar_id = _set_ar_id,
.get_ar_id = _get_ar_id,
.set_session_id = _set_session_id,
.get_session_id = _get_session_id,
.change_state = _change_state,
.get_recommendation = _get_recommendation,
.set_recommendation = _set_recommendation,
@@ -68,6 +68,11 @@ struct private_imv_test_state_t {
*/
chunk_t ar_id_value;
/**
* Unique session ID
*/
int session_id;
/**
* IMV action recommendation
*/
@@ -170,6 +175,18 @@ METHOD(imv_state_t, get_ar_id, chunk_t,
return this->ar_id_value;
}
METHOD(imv_state_t, set_session_id, void,
private_imv_test_state_t *this, int session_id)
{
this->session_id = session_id;
}
METHOD(imv_state_t, get_session_id, int,
private_imv_test_state_t *this)
{
return this->session_id;
}
METHOD(imv_state_t, change_state, void,
private_imv_test_state_t *this, TNC_ConnectionState new_state)
{
@@ -307,6 +324,8 @@ imv_state_t *imv_test_state_create(TNC_ConnectionID connection_id)
.get_max_msg_len = _get_max_msg_len,
.set_ar_id = _set_ar_id,
.get_ar_id = _get_ar_id,
.set_session_id = _set_session_id,
.get_session_id = _get_session_id,
.change_state = _change_state,
.get_recommendation = _get_recommendation,
.set_recommendation = _set_recommendation,
+4 -1
View File
@@ -1,5 +1,8 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libimcv
INCLUDES = \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libtncif \
-I$(top_srcdir)/src/libimcv
ipseclib_LTLIBRARIES = libpts.la
@@ -108,6 +108,7 @@ static void do_args(int argc, char *argv[])
OP_MEASUREMENTS,
OP_PACKAGES,
OP_PRODUCTS,
OP_SESSIONS,
OP_ADD,
OP_DEL,
} op = OP_UNDEF;
@@ -131,6 +132,7 @@ static void do_args(int argc, char *argv[])
{ "products", no_argument, NULL, 'p' },
{ "hashes", no_argument, NULL, 'H' },
{ "measurements", no_argument, NULL, 'm' },
{ "sessions", no_argument, NULL, 's' },
{ "add", no_argument, NULL, 'a' },
{ "delete", no_argument, NULL, 'r' },
{ "del", no_argument, NULL, 'r' },
@@ -201,6 +203,9 @@ static void do_args(int argc, char *argv[])
case 'm':
op = OP_MEASUREMENTS;
continue;
case 's':
op = OP_SESSIONS;
continue;
case 'a':
op = OP_ADD;
continue;
@@ -408,6 +413,9 @@ static void do_args(int argc, char *argv[])
case OP_MEASUREMENTS:
attest->list_measurements(attest);
break;
case OP_SESSIONS:
attest->list_sessions(attest);
break;
case OP_ADD:
attest->add(attest);
break;
+425 -260
View File
@@ -13,16 +13,18 @@
* for more details.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <libgen.h>
#include <time.h>
#include "attest_db.h"
#include "libpts.h"
#include "pts/pts_meas_algo.h"
#include "pts/pts_file_meas.h"
#include "pts/components/pts_comp_func_name.h"
#include <libgen.h>
#include <time.h>
#define IMA_MAX_NAME_LEN 255
typedef struct private_attest_db_t private_attest_db_t;
@@ -815,18 +817,19 @@ METHOD(attest_db_t, list_devices, void,
u_int tstamp, flags = 0;
e = this->db->query(this->db,
"SELECT d.id, d.value, i.time, i.count, i.count_update, "
"i.count_blacklist, i.flags, i.ar_id, p.name FROM devices AS d "
"JOIN device_infos AS i ON d.id = i.device "
"JOIN products AS p ON p.id = i.product "
"ORDER BY d.value, i.time DESC",
DB_INT, DB_BLOB, DB_UINT, DB_INT, DB_INT, DB_INT, DB_UINT,
DB_INT, DB_TEXT);
"SELECT d.id, d.value, s.time, s.identity, p.name, "
"i.count, i.count_update, i.count_blacklist, i.flags "
"FROM devices AS d "
"JOIN sessions AS s ON d.id = s.device "
"JOIN products AS p ON p.id = s.product "
"JOIN device_infos AS i ON i.session = s.id "
"ORDER BY d.value, s.time DESC", DB_INT, DB_BLOB, DB_UINT,
DB_INT, DB_TEXT, DB_INT, DB_INT, DB_INT, DB_UINT);
if (e)
{
while (e->enumerate(e, &id, &value, &tstamp, &count, &count_update,
&count_blacklist, &flags, &ar_id, &product))
while (e->enumerate(e, &id, &value, &tstamp, &ar_id, &product,
&count, &count_update, &count_blacklist, &flags))
{
if (id != last_id)
{
@@ -843,7 +846,7 @@ METHOD(attest_db_t, list_devices, void,
{
chunk_free(&ar_id_value);
e_ar = this->db->query(this->db,
"SELECT type, data FROM identities "
"SELECT type, value FROM identities "
"WHERE id = ?", DB_INT, ar_id, DB_INT, DB_BLOB);
if (e_ar)
{
@@ -1124,67 +1127,28 @@ METHOD(attest_db_t, list_products, void,
printf("\n");
}
/**
* get the directory if there is one from the files tables
*/
static void get_directory(private_attest_db_t *this, int did, char **directory)
{
enumerator_t *e;
char *dir;
free(*directory);
*directory = strdup("");
if (did)
{
e = this->db->query(this->db,
"SELECT path from files WHERE id = ?",
DB_UINT, did, DB_TEXT);
if (e)
{
if (e->enumerate(e, &dir))
{
free(*directory);
*directory = strdup(dir);
}
e->destroy(e);
}
}
}
static bool slash(char *directory, char *file)
{
return *file != '/' && directory[max(0, strlen(directory)-1)] != '/';
}
METHOD(attest_db_t, list_hashes, void,
private_attest_db_t *this)
{
enumerator_t *e;
chunk_t hash;
char *file, *dir, *product;
int fid, fid_old = 0, did, did_old = 0, count = 0;
int id, fid, fid_old = 0, did, did_old = 0, pid, pid_old = 0, count = 0;
dir = strdup("");
if (this->pid && this->fid & this->did)
if (this->pid && this->fid && this->did)
{
printf("%4d: %s\n", this->did, this->dir);
printf("%4d: %s\n", this->fid, this->file);
e = this->db->query(this->db,
"SELECT hash FROM file_hashes "
"WHERE algo = ? AND file = ? AND directory = ? AND product = ?",
DB_INT, this->algo, DB_INT, this->fid, DB_INT, this->did,
DB_INT, this->pid, DB_BLOB);
"SELECT id, hash FROM file_hashes "
"WHERE algo = ? AND file = ? AND product = ?",
DB_INT, this->algo, DB_INT, this->fid, DB_INT, this->pid,
DB_INT, DB_BLOB);
if (e)
{
while (e->enumerate(e, &hash))
while (e->enumerate(e, &id, &hash))
{
if (this->fid != fid_old)
{
printf("%4d: %s%s%s\n", this->fid, this->dir,
slash(this->dir, this->file) ? "/" : "", this->file);
fid_old = this->fid;
}
printf(" %#B\n", &hash);
printf("%4d: %#B\n", id, &hash);
count++;
}
e->destroy(e);
@@ -1194,22 +1158,62 @@ METHOD(attest_db_t, list_hashes, void,
(count == 1) ? "" : "s", this->product);
}
}
else if (this->pid && this->fid)
else if (this->pid && this->file)
{
e = this->db->query(this->db,
"SELECT f.path, fh.hash FROM file_hashes AS fh "
"JOIN files AS f ON f.id = fh.file "
"WHERE algo = ? AND file = ? AND product = ?",
DB_INT, this->algo, DB_INT, this->fid, DB_INT, this->pid,
DB_TEXT, DB_BLOB);
"SELECT h.id, h.hash, f.id, d.id, d.path "
"FROM file_hashes AS h "
"JOIN files AS f ON h.file = f.id "
"JOIN directories AS d ON f.dir = d.id "
"WHERE h.algo = ? AND h.product = ? AND f.name = ? "
"ORDER BY d.path, f.name, h.hash",
DB_INT, this->algo, DB_INT, this->pid, DB_TEXT, this->file,
DB_INT, DB_BLOB, DB_INT, DB_INT, DB_TEXT);
if (e)
{
free(dir);
while (e->enumerate(e, &dir, &hash))
while (e->enumerate(e, &id, &hash, &fid, &did, &dir))
{
printf("%4d: %s%s%s\n", this->fid, dir,
slash(dir, this->file) ? "/" : "", this->file);
printf(" %#B\n", &hash);
if (did != did_old)
{
printf("%4d: %s\n", did, dir);
did_old = did;
}
if (fid != fid_old)
{
printf("%4d: %s\n", fid, this->file);
fid_old = fid;
}
printf("%4d: %#B\n", id, &hash);
count++;
}
e->destroy(e);
printf("%d %N value%s found for product '%s'\n", count,
pts_meas_algorithm_names, this->algo,
(count == 1) ? "" : "s", this->product);
}
}
else if (this->pid && this->did)
{
printf("%4d: %s\n", this->did, this->dir);
e = this->db->query(this->db,
"SELECT h.id, h.hash, f.id, f.name "
"FROM file_hashes AS h "
"JOIN files AS f ON h.file = f.id "
"WHERE h.algo = ? AND h.product = ? AND f.dir = ? "
"ORDER BY f.name, h.hash",
DB_INT, this->algo, DB_INT, this->pid, DB_INT, this->did,
DB_INT, DB_BLOB, DB_INT, DB_TEXT);
if (e)
{
while (e->enumerate(e, &id, &hash, &fid, &file))
{
if (fid != fid_old)
{
printf("%4d: %s\n", fid, file);
fid_old = fid;
}
printf("%4d: %#B\n", id, &hash);
count++;
}
e->destroy(e);
@@ -1217,35 +1221,34 @@ METHOD(attest_db_t, list_hashes, void,
printf("%d %N value%s found for product '%s'\n", count,
pts_meas_algorithm_names, this->algo,
(count == 1) ? "" : "s", this->product);
dir = NULL;
}
}
else if (this->pid)
{
e = this->db->query(this->db,
"SELECT f.id, f. f.path, fh.hash, fh.directory "
"FROM file_hashes AS fh "
"JOIN files AS f ON f.id = fh.file "
"WHERE fh.algo = ? AND fh.product = ? "
"ORDER BY fh.directory, f.path",
DB_INT, this->algo, DB_UINT, this->pid,
DB_INT, DB_TEXT, DB_BLOB, DB_INT);
"SELECT h.id, h.hash, f.id, f.name, d.id, d.path "
"FROM file_hashes AS h "
"JOIN files AS f ON h.file = f.id "
"JOIN directories AS d ON f.dir = d.id "
"WHERE h.algo = ? AND h.product = ? "
"ORDER BY d.path, f.name, h.hash",
DB_INT, this->algo, DB_INT, this->pid,
DB_INT, DB_BLOB, DB_INT, DB_TEXT, DB_INT, DB_TEXT);
if (e)
{
while (e->enumerate(e, &fid, &file, &hash, &did))
while (e->enumerate(e, &id, &hash, &fid, &file, &did, &dir))
{
if (fid != fid_old || did != did_old)
if (did != did_old)
{
if (did != did_old)
{
get_directory(this, did, &dir);
}
printf("%4d: %s%s%s\n", fid,
dir, slash(dir, file) ? "/" : "", file);
fid_old = fid;
printf("%4d: %s\n", did, dir);
did_old = did;
}
printf(" %#B\n", &hash);
if (fid != fid_old)
{
printf("%4d: %s\n", fid, file);
fid_old = fid;
}
printf("%4d: %#B\n", id, &hash);
count++;
}
e->destroy(e);
@@ -1255,58 +1258,147 @@ METHOD(attest_db_t, list_hashes, void,
(count == 1) ? "" : "s", this->product);
}
}
else if (this->fid)
else if (this->fid && this->did)
{
e = this->db->query(this->db,
"SELECT p.name, fh.hash, fh.directory "
"FROM file_hashes AS fh "
"JOIN products AS p ON p.id = fh.product "
"WHERE fh.algo = ? AND fh.file = ? AND fh.directory = ?"
"ORDER BY p.name",
DB_INT, this->algo, DB_UINT, this->fid, DB_UINT, this->did,
DB_TEXT, DB_BLOB, DB_INT);
"SELECT h.id, h.hash, p.id, p.name FROM file_hashes AS h "
"JOIN products AS p ON h.product = p.id "
"WHERE h.algo = ? AND h.file = ? "
"ORDER BY p.name, h.hash",
DB_INT, this->algo, DB_INT, this->fid,
DB_INT, DB_BLOB, DB_INT, DB_TEXT);
if (e)
{
while (e->enumerate(e, &product, &hash, &did))
while (e->enumerate(e, &id, &hash, &pid, &product))
{
printf("%#B '%s'\n", &hash, product);
if (pid != pid_old)
{
printf("%4d: %s\n", pid, product);
pid_old = pid;
}
printf("%4d: %#B\n", id, &hash);
count++;
}
e->destroy(e);
printf("%d %N value%s found for file '%s%s%s'\n",
count, pts_meas_algorithm_names, this->algo,
printf("%d %N value%s found for file '%s%s%s'\n", count,
pts_meas_algorithm_names, this->algo,
(count == 1) ? "" : "s", this->dir,
slash(this->dir, this->file) ? "/" : "", this->file);
streq(this->dir, "/") ? "" : "/", this->file);
}
}
else if (this->file)
{
e = this->db->query(this->db,
"SELECT h.id, h.hash, f.id, d.id, d.path, p.id, p.name "
"FROM file_hashes AS h "
"JOIN files AS f ON h.file = f.id "
"JOIN directories AS d ON f.dir = d.id "
"JOIN products AS p ON h.product = p.id "
"WHERE h.algo = ? AND f.name = ? "
"ORDER BY d.path, f.name, p.name, h.hash",
DB_INT, this->algo, DB_TEXT, this->file,
DB_INT, DB_BLOB, DB_INT, DB_INT, DB_TEXT, DB_INT, DB_TEXT);
if (e)
{
while (e->enumerate(e, &id, &hash, &fid, &did, &dir, &pid, &product))
{
if (did != did_old)
{
printf("%4d: %s\n", did, dir);
did_old = did;
}
if (fid != fid_old)
{
printf("%4d: %s\n", fid, this->file);
fid_old = fid;
pid_old = 0;
}
if (pid != pid_old)
{
printf("%4d: %s\n", pid, product);
pid_old = pid;
}
printf("%4d: %#B\n", id, &hash);
count++;
}
e->destroy(e);
printf("%d %N value%s found\n", count, pts_meas_algorithm_names,
this->algo, (count == 1) ? "" : "s");
}
}
else if (this->did)
{
e = this->db->query(this->db,
"SELECT h.id, h.hash, f.id, f.name, p.id, p.name "
"FROM file_hashes AS h "
"JOIN files AS f ON h.file = f.id "
"JOIN products AS p ON h.product = p.id "
"WHERE h.algo = ? AND f.dir = ? "
"ORDER BY f.name, p.name, h.hash",
DB_INT, this->algo, DB_INT, this->did,
DB_INT, DB_BLOB, DB_INT, DB_TEXT, DB_INT, DB_TEXT);
if (e)
{
while (e->enumerate(e, &id, &hash, &fid, &file, &pid, &product))
{
if (fid != fid_old)
{
printf("%4d: %s\n", fid, file);
fid_old = fid;
pid_old = 0;
}
if (pid != pid_old)
{
printf("%4d: %s\n", pid, product);
pid_old = pid;
}
printf("%4d: %#B\n", id, &hash);
count++;
}
e->destroy(e);
printf("%d %N value%s found for directory '%s'\n", count,
pts_meas_algorithm_names, this->algo,
(count == 1) ? "" : "s", this->dir);
}
}
else
{
e = this->db->query(this->db,
"SELECT f.id, f.path, p.name, fh.hash, fh.directory "
"FROM file_hashes AS fh "
"JOIN files AS f ON f.id = fh.file "
"JOIN products AS p ON p.id = fh.product "
"WHERE fh.algo = ? "
"ORDER BY fh.directory, f.path, p.name",
DB_INT, this->algo,
DB_INT, DB_TEXT, DB_TEXT, DB_BLOB, DB_INT);
"SELECT h.id, h.hash, f.id, f.name, d.id, d.path, p.id, p.name "
"FROM file_hashes AS h "
"JOIN files AS f ON h.file = f.id "
"JOIN directories AS d ON f.dir = d.id "
"JOIN products AS p on h.product = p.id "
"WHERE h.algo = ? "
"ORDER BY d.path, f.name, p.name, h.hash",
DB_INT, this->algo, DB_INT, DB_BLOB, DB_INT, DB_TEXT,
DB_INT, DB_TEXT, DB_INT, DB_TEXT);
if (e)
{
while (e->enumerate(e, &fid, &file, &product, &hash, &did))
while (e->enumerate(e, &id, &hash, &fid, &file, &did, &dir, &pid,
&product))
{
if (fid != fid_old || did != did_old)
if (did != did_old)
{
if (did != did_old)
{
get_directory(this, did, &dir);
did_old = did;
}
printf("%4d: %s%s%s\n", fid,
dir, slash(dir, file) ? "/" : "", file);
fid_old = fid;
printf("%4d: %s\n", did, dir);
did_old = did;
}
printf(" %#B '%s'\n", &hash, product);
if (fid != fid_old)
{
printf("%4d: %s\n", fid, file);
fid_old = fid;
pid_old = 0;
}
if (pid != pid_old)
{
printf("%4d: %s\n", pid, product);
pid_old = pid;
}
printf("%4d: %#B\n", id, &hash);
count++;
}
e->destroy(e);
@@ -1315,7 +1407,6 @@ METHOD(attest_db_t, list_hashes, void,
this->algo, (count == 1) ? "" : "s");
}
}
free(dir);
}
METHOD(attest_db_t, list_measurements, void,
@@ -1422,9 +1513,49 @@ METHOD(attest_db_t, list_measurements, void,
}
}
bool insert_file_hash(private_attest_db_t *this, pts_meas_algorithms_t algo,
chunk_t measurement, int fid, int did, bool ima,
int *hashes_added, int *hashes_updated)
METHOD(attest_db_t, list_sessions, void,
private_attest_db_t *this)
{
enumerator_t *e;
chunk_t device, identity;
char *product;
int session_id, conn_id;
time_t created;
u_int t;
e = this->db->query(this->db,
"SELECT s.id, s.time, s.connection, p.name, d.value, i.value "
"FROM sessions AS s "
"LEFT JOIN products AS p ON s.product = p.id "
"LEFT JOIN devices AS d ON s.device = d.id "
"LEFT JOIN identities AS i ON s.identity = i.id "
"ORDER BY s.time DESC",
DB_INT, DB_UINT, DB_INT, DB_TEXT, DB_BLOB, DB_BLOB);
if (e)
{
while (e->enumerate(e, &session_id, &t, &conn_id, &product, &device,
&identity))
{
created = t;
product = product ? product : "-";
device = device.len ? device : chunk_from_str("-");
device.len = min(device.len, 20);
identity = identity.len ? identity : chunk_from_str("-");
printf("%4d: %T %2d %-20s %.*s%*s %.*s\n", session_id, &created,
FALSE, conn_id, product, device.len, device.ptr,
20-device.len, " ", identity.len, identity.ptr);
}
e->destroy(e);
}
}
/**
* Insert a file hash into the database
*/
static bool insert_file_hash(private_attest_db_t *this,
pts_meas_algorithms_t algo,
chunk_t measurement, int fid, bool ima,
int *hashes_added, int *hashes_updated)
{
enumerator_t *e;
chunk_t hash;
@@ -1434,8 +1565,8 @@ bool insert_file_hash(private_attest_db_t *this, pts_meas_algorithms_t algo,
e = this->db->query(this->db,
"SELECT hash FROM file_hashes WHERE algo = ? "
"AND file = ? AND directory = ? AND product = ? and key = 0",
DB_INT, algo, DB_UINT, fid, DB_UINT, did, DB_UINT, this->pid, DB_BLOB);
"AND file = ? AND product = ? AND device = 0",
DB_INT, algo, DB_UINT, fid, DB_UINT, this->pid, DB_BLOB);
if (!e)
{
printf("file_hashes query failed\n");
@@ -1451,8 +1582,8 @@ bool insert_file_hash(private_attest_db_t *this, pts_meas_algorithms_t algo,
{
if (this->db->execute(this->db, NULL,
"UPDATE file_hashes SET hash = ? WHERE algo = ? "
"AND file = ? AND directory = ? AND product = ? and key = 0",
DB_BLOB, measurement, DB_INT, algo, DB_UINT, fid, DB_UINT, did,
"AND file = ? AND product = ? and device = 0",
DB_BLOB, measurement, DB_INT, algo, DB_UINT, fid,
DB_UINT, this->pid) == 1)
{
label = "updated";
@@ -1464,9 +1595,9 @@ bool insert_file_hash(private_attest_db_t *this, pts_meas_algorithms_t algo,
{
if (this->db->execute(this->db, NULL,
"INSERT INTO file_hashes "
"(file, directory, product, key, algo, hash) "
"VALUES (?, ?, ?, 0, ?, ?)",
DB_UINT, fid, DB_UINT, did, DB_UINT, this->pid,
"(file, product, device, algo, hash) "
"VALUES (?, ?, 0, ?, ?)",
DB_UINT, fid, DB_UINT, this->pid,
DB_INT, algo, DB_BLOB, measurement) == 1)
{
label = "created";
@@ -1479,6 +1610,157 @@ bool insert_file_hash(private_attest_db_t *this, pts_meas_algorithms_t algo,
return TRUE;
}
/**
* Add hash measurement for a single file or all files in a directory
*/
static bool add_hash(private_attest_db_t *this)
{
char *pathname, *filename, *sep, *label, *pos;
char ima_buffer[IMA_MAX_NAME_LEN + 1];
chunk_t measurement, ima_template;
pts_file_meas_t *measurements;
hasher_t *hasher = NULL;
bool ima = FALSE;
int fid, files_added = 0, hashes_added = 0, hashes_updated = 0;
int len, ima_hashes_added = 0, ima_hashes_updated = 0;
enumerator_t *enumerator, *e;
if (this->algo == PTS_MEAS_ALGO_SHA1_IMA)
{
ima = TRUE;
this->algo = PTS_MEAS_ALGO_SHA1;
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (!hasher)
{
printf("could not create hasher\n");
return FALSE;
}
}
sep = streq(this->dir, "/") ? "" : "/";
if (this->fid)
{
/* build pathname from directory path and relative filename */
if (asprintf(&pathname, "%s%s%s", this->dir, sep, this->file) == -1)
{
return FALSE;
}
measurements = pts_file_meas_create_from_path(0, pathname, FALSE,
TRUE, this->algo);
free(pathname);
}
else
{
measurements = pts_file_meas_create_from_path(0, pathname, TRUE,
TRUE, this->algo);
}
if (!measurements)
{
printf("file measurement failed\n");
DESTROY_IF(hasher);
return FALSE;
}
enumerator = measurements->create_enumerator(measurements);
while (enumerator->enumerate(enumerator, &filename, &measurement))
{
if (this->fid)
{
/* a single file already exists */
filename = this->file;
fid = this->fid;
label = "exists";
}
else
{
/* retrieve or create filename */
label = "could not be created";
e = this->db->query(this->db,
"SELECT id FROM files WHERE name = ? AND dir = ?",
DB_TEXT, filename, DB_INT, this->did, DB_INT);
if (!e)
{
printf("files query failed\n");
break;
}
if (e->enumerate(e, &fid))
{
label = "exists";
}
else
{
if (this->db->execute(this->db, &fid,
"INSERT INTO files (name, dir) VALUES (?, ?)",
DB_TEXT, filename, DB_INT, this->did) == 1)
{
label = "created";
files_added++;
}
}
e->destroy(e);
}
printf("%4d: %s - %s\n", fid, filename, label);
/* compute file measurement hash */
if (!insert_file_hash(this, this->algo, measurement, fid, FALSE,
&hashes_added, &hashes_updated))
{
break;
}
if (!ima)
{
continue;
}
/* compute IMA template hash */
pos = ima_buffer;
len = IMA_MAX_NAME_LEN;
if (!this->relative)
{
strncpy(pos, this->dir, len);
len = max(0, len - strlen(this->dir));
pos = ima_buffer + IMA_MAX_NAME_LEN - len;
strncpy(pos, sep, len);
len = max(0, len - strlen(sep));
pos = ima_buffer + IMA_MAX_NAME_LEN - len;
}
strncpy(pos, filename, len);
ima_buffer[IMA_MAX_NAME_LEN] = '\0';
ima_template = chunk_create(ima_buffer, sizeof(ima_buffer));
if (!hasher->get_hash(hasher, measurement, NULL) ||
!hasher->get_hash(hasher, ima_template, measurement.ptr))
{
printf("could not compute IMA template hash\n");
break;
}
if (!insert_file_hash(this, PTS_MEAS_ALGO_SHA1_IMA, measurement, fid,
TRUE, &ima_hashes_added, &ima_hashes_updated))
{
break;
}
}
enumerator->destroy(enumerator);
printf("%d measurements, added %d new files, %d file hashes",
measurements->get_file_count(measurements), files_added,
hashes_added);
if (ima)
{
printf(", %d ima hashes", ima_hashes_added);
hasher->destroy(hasher);
}
printf(", updated %d file hashes", hashes_updated);
if (ima)
{
printf(", %d ima hashes", ima_hashes_updated);
}
printf("\n");
measurements->destroy(measurements);
return TRUE;
}
METHOD(attest_db_t, add, bool,
private_attest_db_t *this)
{
@@ -1500,127 +1782,10 @@ METHOD(attest_db_t, add, bool,
return success;
}
/* add directory or file measurement for a given product */
if ((this->did || this->fid) && this->pid)
/* add directory or file hash measurement for a given product */
if (this->did && this->pid)
{
char *pathname, *filename, *label;
char ima_buffer[IMA_MAX_NAME_LEN + 1];
chunk_t measurement, ima_template;
pts_file_meas_t *measurements;
hasher_t *hasher = NULL;
bool ima = FALSE;
int fid, did;
int files_added = 0, hashes_added = 0, hashes_updated = 0;
int ima_hashes_added = 0, ima_hashes_updated = 0;
enumerator_t *enumerator, *e;
if (this->algo == PTS_MEAS_ALGO_SHA1_IMA)
{
ima = TRUE;
this->algo = PTS_MEAS_ALGO_SHA1;
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (!hasher)
{
printf("could not create hasher\n");
return FALSE;
}
}
pathname = this->did ? this->dir : this->file;
measurements = pts_file_meas_create_from_path(0, pathname, this->did,
this->relative, this->algo);
if (!measurements)
{
printf("file measurement failed\n");
DESTROY_IF(hasher);
return FALSE;
}
if (this->fid && this->relative)
{
set_directory(this, dirname(pathname), TRUE);
}
did = this->relative ? this->did : 0;
enumerator = measurements->create_enumerator(measurements);
while (enumerator->enumerate(enumerator, &filename, &measurement))
{
/* retrieve or create filename */
label = "could not be created";
e = this->db->query(this->db,
"SELECT id FROM files WHERE path = ?",
DB_TEXT, filename, DB_INT);
if (!e)
{
printf("files query failed\n");
break;
}
if (e->enumerate(e, &fid))
{
label = "exists";
}
else
{
if (this->db->execute(this->db, &fid,
"INSERT INTO files (type, path) VALUES (0, ?)",
DB_TEXT, filename) == 1)
{
label = "created";
files_added++;
}
}
e->destroy(e);
printf("%4d: %s - %s\n", fid, filename, label);
/* compute file measurement hash */
if (!insert_file_hash(this, this->algo, measurement,
fid, did, FALSE,
&hashes_added, &hashes_updated))
{
break;
}
if (!ima)
{
continue;
}
/* compute IMA template hash */
strncpy(ima_buffer, filename, IMA_MAX_NAME_LEN);
ima_buffer[IMA_MAX_NAME_LEN] = '\0';
ima_template = chunk_create(ima_buffer, sizeof(ima_buffer));
if (!hasher->get_hash(hasher, measurement, NULL) ||
!hasher->get_hash(hasher, ima_template, measurement.ptr))
{
printf("could not compute IMA template hash\n");
break;
}
if (!insert_file_hash(this, PTS_MEAS_ALGO_SHA1_IMA, measurement,
fid, did, TRUE,
&ima_hashes_added, &ima_hashes_updated))
{
break;
}
}
enumerator->destroy(enumerator);
printf("%d measurements, added %d new files, %d file hashes",
measurements->get_file_count(measurements), files_added,
hashes_added);
if (ima)
{
printf(", %d ima hashes", ima_hashes_added);
hasher->destroy(hasher);
}
printf(", updated %d file hashes", hashes_updated);
if (ima)
{
printf(", %d ima hashes", ima_hashes_updated);
}
printf("\n");
measurements->destroy(measurements);
success = TRUE;
return add_hash(this);
}
/* insert package version */
@@ -1656,13 +1821,12 @@ METHOD(attest_db_t, delete, bool,
{
success = this->db->execute(this->db, NULL,
"DELETE FROM file_hashes "
"WHERE algo = ? AND product = ? "
"AND file = ? AND directory = ?",
"WHERE algo = ? AND product = ? AND file = ?",
DB_UINT, this->algo, DB_UINT, this->pid,
DB_UINT, this->fid, DB_UINT, this->did) > 0;
DB_UINT, this->fid) > 0;
printf("%4d: %s%s%s\n", this->fid, this->dir, this->did ? "/":"",
this->file);
printf("%4d: %s%s%s\n", this->fid, this->dir,
streq(this->dir, "/") ? "" : "/", this->file);
printf("%N value for product '%s' %sdeleted from database\n",
pts_meas_algorithm_names, this->algo, this->product,
success ? "" : "could not be ");
@@ -1829,6 +1993,7 @@ attest_db_t *attest_db_create(char *uri)
.list_keys = _list_keys,
.list_hashes = _list_hashes,
.list_measurements = _list_measurements,
.list_sessions = _list_sessions,
.add = _add,
.delete = _delete,
.destroy = _destroy,
@@ -227,6 +227,11 @@ struct attest_db_t {
*/
void (*list_measurements)(attest_db_t *this);
/**
* List sessions stored in the database
*/
void (*list_sessions)(attest_db_t *this);
/**
* Add an entry to the database
*/
@@ -83,7 +83,7 @@ TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id,
TNC_Version max_version,
TNC_Version *actual_version)
{
char *hash_alg, *dh_group, *uri, *cadir;
char *hash_alg, *dh_group, *cadir;
if (imv_attestation)
{
@@ -133,10 +133,8 @@ TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id,
pts_credmgr->add_set(pts_credmgr, pts_creds->get_set(pts_creds));
}
/* attach file measurement database */
uri = lib->settings->get_str(lib->settings,
"libimcv.plugins.imv-attestation.database", NULL);
pts_db = pts_database_create(uri);
/* attach PTS database co-located with IMV database */
pts_db = pts_database_create(imv_attestation->get_database(imv_attestation));
return TNC_RESULT_SUCCESS;
}
@@ -473,7 +471,9 @@ TNC_Result TNC_IMV_Terminate(TNC_IMVID imv_id)
pts_creds->destroy(pts_creds);
}
DESTROY_IF(pts_db);
pts_db = NULL;
DESTROY_IF(pts_credmgr);
pts_credmgr = NULL;
libpts_deinit();
@@ -73,6 +73,11 @@ struct private_imv_attestation_state_t {
*/
chunk_t ar_id_value;
/**
* Unique session ID
*/
int session_id;
/**
* IMV Attestation handshake state
*/
@@ -243,6 +248,18 @@ METHOD(imv_state_t, get_ar_id, chunk_t,
return this->ar_id_value;
}
METHOD(imv_state_t, set_session_id, void,
private_imv_attestation_state_t *this, int session_id)
{
this->session_id = session_id;
}
METHOD(imv_state_t, get_session_id, int,
private_imv_attestation_state_t *this)
{
return this->session_id;
}
METHOD(imv_state_t, change_state, void,
private_imv_attestation_state_t *this, TNC_ConnectionState new_state)
{
@@ -510,6 +527,8 @@ imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id)
.get_max_msg_len = _get_max_msg_len,
.set_ar_id = _set_ar_id,
.get_ar_id = _get_ar_id,
.set_session_id = _set_session_id,
.get_session_id = _get_session_id,
.change_state = _change_state,
.get_recommendation = _get_recommendation,
.set_recommendation = _set_recommendation,
+27 -11
View File
@@ -13,7 +13,7 @@ CREATE INDEX directories_path ON directories (
DROP TABLE IF EXISTS files;
CREATE TABLE files (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
dir INTEGER DEFAULT 0,
dir INTEGER DEFAULT 0 REFERENCES directories(id),
name TEXT NOT NULL
);
DROP INDEX IF EXISTS files_name;
@@ -31,22 +31,41 @@ CREATE INDEX products_name ON products (
name
);
DROP TABLE IF EXISTS product_file;
CREATE TABLE product_file (
product INTEGER NOT NULL REFERENCES products(id),
file INTEGER NOT NULL REFERENCES files(id),
measurement INTEGER DEFAULT 0,
metadata INTEGER DEFAULT 0,
PRIMARY KEY (product, file)
);
DROP TABLE IF EXISTS algorithms;
CREATE TABLE algorithms (
id INTEGER PRIMARY KEY,
name TEXT not NULL
name VARCHAR(20) not NULL
);
DROP TABLE IF EXISTS file_hashes;
CREATE TABLE file_hashes (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
file INTEGER NOT NULL,
product INTEGER NOT NULL,
file INTEGER NOT NULL REFERENCES files(id),
product INTEGER NOT NULL REFERENCES products(id),
device INTEGER DEFAULT 0,
algo INTEGER NOT NULL,
algo INTEGER NOT NULL REFERENCES algorithms(id),
hash BLOB NOT NULL
);
DROP TABLE IF EXISTS sessions;
CREATE TABLE sessions (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
time INTEGER NOT NULL,
connection INTEGER NOT NULL,
identity INTEGER DEFAULT 0 REFERENCES identities(id),
device INTEGER DEFAULT 0 REFERENCES devices(id),
product INTEGER DEFAULT 0 REFERENCES products(id)
);
DROP TABLE IF EXISTS components;
CREATE TABLE components (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
@@ -118,10 +137,7 @@ CREATE INDEX devices_value ON devices (
DROP TABLE IF EXISTS device_infos;
CREATE TABLE device_infos (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
device INTEGER NOT NULL,
time INTEGER NOT NULL,
ar_id INTEGER DEFAULT 0,
product INTEGER DEFAULT 0,
session INTEGER NOT NULL REFERENCES sessions(id),
count INTEGER DEFAULT 0,
count_update INTEGER DEFAULT 0,
count_blacklist INTEGER DEFAULT 0,
@@ -132,6 +148,6 @@ DROP TABLE IF EXISTS identities;
CREATE TABLE identities (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
type INTEGER NOT NULL,
data BLOB NOT NULL,
UNIQUE (type, data)
value BLOB NOT NULL,
UNIQUE (type, value)
);
+7 -11
View File
@@ -308,17 +308,21 @@ METHOD(pts_database_t, get_comp_measurement_count, status_t,
METHOD(pts_database_t, destroy, void,
private_pts_database_t *this)
{
this->db->destroy(this->db);
free(this);
}
/**
* See header
*/
pts_database_t *pts_database_create(char *uri)
pts_database_t *pts_database_create(imv_database_t *imv_db)
{
private_pts_database_t *this;
if (!imv_db)
{
return NULL;
}
INIT(this,
.public = {
.create_file_meas_enumerator = _create_file_meas_enumerator,
@@ -333,17 +337,9 @@ pts_database_t *pts_database_create(char *uri)
.get_comp_measurement_count = _get_comp_measurement_count,
.destroy = _destroy,
},
.db = lib->db->create(lib->db, uri),
.db = imv_db->get_database(imv_db),
);
if (!this->db)
{
DBG1(DBG_PTS,
"failed to connect to PTS file measurement database '%s'", uri);
free(this);
return NULL;
}
return &this->public;
}
+4 -2
View File
@@ -25,6 +25,8 @@ typedef struct pts_database_t pts_database_t;
#include "pts_meas_algo.h"
#include "components/pts_comp_func_name.h"
#include <imv/imv_database.h>
#include <library.h>
/**
@@ -159,8 +161,8 @@ struct pts_database_t {
/**
* Creates an pts_database_t object
*
* @param uri database uri
* @param imv_db Already attached IMV database
*/
pts_database_t* pts_database_create(char *uri);
pts_database_t* pts_database_create(imv_database_t *imv_db);
#endif /** PTS_DATABASE_H_ @}*/