refactored measurement verification
This commit is contained in:
@@ -488,13 +488,10 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
|
||||
int file_count;
|
||||
pts_meas_algorithms_t algo;
|
||||
pts_file_meas_t *measurements;
|
||||
chunk_t measurement;
|
||||
char *platform_info, *filename;
|
||||
enumerator_t *e_meas;
|
||||
char *platform_info;
|
||||
enumerator_t *e_hash;
|
||||
bool is_dir;
|
||||
linked_list_t *files_in_dir_with_meas;
|
||||
|
||||
files_in_dir_with_meas = linked_list_create();
|
||||
platform_info = pts->get_platform_info(pts);
|
||||
if (!pts_db || !platform_info)
|
||||
{
|
||||
@@ -516,51 +513,16 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
|
||||
DBG1(DBG_IMV, " no entry found for this request");
|
||||
break;
|
||||
}
|
||||
if (is_dir)
|
||||
|
||||
/* check hashes from database against measurements */
|
||||
e_hash = pts_db->create_hash_enumerator(pts_db,
|
||||
platform_info, algo, request_id, is_dir);
|
||||
if (!measurements->verify(measurements, e_hash, is_dir))
|
||||
{
|
||||
enumerator_t *e;
|
||||
char *file;
|
||||
|
||||
e = pts_db->create_files_in_dir_enumerator(pts_db, request_id);
|
||||
while (e->enumerate(e, &file))
|
||||
{
|
||||
char *file_copy = (char *)malloc(strlen(file) * sizeof(char));
|
||||
strcpy(file_copy, file);
|
||||
|
||||
files_in_dir_with_meas->insert_last(files_in_dir_with_meas, file_copy);
|
||||
DBG3(DBG_IMV, "expecting measurement for: %s with request_id: %d", file_copy, request_id);
|
||||
}
|
||||
e->destroy(e);
|
||||
DBG1(DBG_IMV, " measurement error occured");
|
||||
measurement_error = TRUE;
|
||||
}
|
||||
|
||||
e_meas = measurements->create_enumerator(measurements);
|
||||
while (e_meas->enumerate(e_meas, &filename, &measurement))
|
||||
{
|
||||
bool hash_match;
|
||||
|
||||
hash_match = pts_db->check_measurement(pts_db, measurement,
|
||||
platform_info, request_id, filename, algo, is_dir);
|
||||
|
||||
if (!hash_match)
|
||||
{
|
||||
measurement_error = TRUE;
|
||||
}
|
||||
|
||||
if (is_dir && files_in_dir_with_meas->remove(files_in_dir_with_meas,
|
||||
filename, (bool (*)(void*,void*))string_equals))
|
||||
{
|
||||
DBG3(DBG_IMV, "Removed %s from expected files list", filename);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_dir &&
|
||||
!files_in_dir_with_meas->get_count(files_in_dir_with_meas))
|
||||
{
|
||||
DBG3(DBG_IMV, "recevied all expected file measurements for request: %d", request_id);
|
||||
}
|
||||
|
||||
files_in_dir_with_meas->destroy_function(files_in_dir_with_meas, free);
|
||||
e_meas->destroy(e_meas);
|
||||
e_hash->destroy(e_hash);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,68 +54,33 @@ METHOD(pts_database_t, create_file_enumerator, enumerator_t*,
|
||||
return e;
|
||||
}
|
||||
|
||||
METHOD(pts_database_t, create_files_in_dir_enumerator, enumerator_t*,
|
||||
private_pts_database_t *this, int id)
|
||||
METHOD(pts_database_t, create_hash_enumerator, enumerator_t*,
|
||||
private_pts_database_t *this, char *product, pts_meas_algorithms_t algo,
|
||||
int id, bool is_dir)
|
||||
{
|
||||
enumerator_t *e;
|
||||
|
||||
/* look for all entries in file_hashes belonging to a same directory*/
|
||||
e = this->db->query(this->db,
|
||||
"SELECT DISTINCT f.path FROM files AS f "
|
||||
"JOIN file_hashes AS fh ON f.id = fh.file "
|
||||
"WHERE fh.directory = ?",
|
||||
DB_INT, id, DB_TEXT);
|
||||
if (is_dir)
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT f.path, fh.hash FROM file_hashes AS fh "
|
||||
"JOIN files AS f ON fh.file = f.id "
|
||||
"JOIN products AS p ON fh.product = p.id "
|
||||
"WHERE p.name = ? AND fh.directory = ? AND fh.algo = ?",
|
||||
DB_TEXT, product, DB_INT, id, DB_INT, algo, DB_TEXT, DB_BLOB);
|
||||
}
|
||||
else
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT f.path, fh.hash FROM file_hashes AS fh "
|
||||
"JOIN files AS f ON fh.file = f.id "
|
||||
"JOIN products AS p ON fh.product = p.id "
|
||||
"WHERE p.name = ? AND fh.file = ? AND fh.algo = ?",
|
||||
DB_TEXT, product, DB_INT, id, DB_INT, algo, DB_TEXT, DB_BLOB);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
METHOD(pts_database_t, check_measurement, bool,
|
||||
private_pts_database_t *this, chunk_t received_hash, char *product, int id, char *file_name, pts_meas_algorithms_t algorithm, bool is_dir)
|
||||
{
|
||||
enumerator_t *e;
|
||||
chunk_t db_measurement;
|
||||
|
||||
/* look for all entries belonging to a product, file and directory in file_hashes table */
|
||||
|
||||
e = (is_dir) ? this->db->query(this->db,
|
||||
"SELECT fh.hash FROM file_hashes AS fh "
|
||||
"JOIN files AS f ON fh.file = f.id "
|
||||
"JOIN products AS p ON fh.product = p.id "
|
||||
"WHERE f.path = ? AND p.name = ? AND fh.directory = ? AND fh.algo = ?",
|
||||
DB_TEXT, file_name, DB_TEXT, product, DB_INT, id, DB_INT, algorithm, DB_BLOB) :
|
||||
|
||||
this->db->query(this->db,
|
||||
"SELECT fh.hash FROM file_hashes AS fh "
|
||||
"JOIN files AS f ON fh.file = f.id "
|
||||
"JOIN products AS p ON fh.product = p.id "
|
||||
"WHERE p.name = ? AND f.id = ? AND fh.algo = ?",
|
||||
DB_TEXT, product, DB_INT, id, DB_INT, algorithm, DB_BLOB);
|
||||
|
||||
if (!e)
|
||||
{
|
||||
DBG1(DBG_TNC, " database enumerator failed");
|
||||
return FALSE;
|
||||
}
|
||||
if (!e->enumerate(e, &db_measurement))
|
||||
{
|
||||
DBG2(DBG_TNC, " measurement for '%s' not found"
|
||||
" in database", file_name);
|
||||
e->destroy(e);
|
||||
/* Ignore the measurements for which we do not have the hash saved in database */
|
||||
return TRUE;
|
||||
}
|
||||
if (chunk_equals(db_measurement, received_hash))
|
||||
{
|
||||
DBG2(DBG_TNC, " %#B for '%s' is ok",
|
||||
&received_hash, file_name);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DBG1(DBG_IMV, " %#B for '%s' does not match %#B",
|
||||
&received_hash, file_name, &db_measurement);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
METHOD(pts_database_t, destroy, void,
|
||||
private_pts_database_t *this)
|
||||
{
|
||||
@@ -133,8 +98,7 @@ pts_database_t *pts_database_create(char *uri)
|
||||
INIT(this,
|
||||
.public = {
|
||||
.create_file_enumerator = _create_file_enumerator,
|
||||
.create_files_in_dir_enumerator = _create_files_in_dir_enumerator,
|
||||
.check_measurement = _check_measurement,
|
||||
.create_hash_enumerator = _create_hash_enumerator,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.db = lib->db->create(lib->db, uri),
|
||||
|
||||
@@ -35,33 +35,23 @@ struct pts_database_t {
|
||||
/**
|
||||
* Get files to be measured by PTS
|
||||
*
|
||||
* @product software product (os, vpn client, etc.)
|
||||
* @return enumerator over all files matching a given release
|
||||
* @param product software product (os, vpn client, etc.)
|
||||
* @return enumerator over all matching files
|
||||
*/
|
||||
enumerator_t* (*create_file_enumerator)(pts_database_t *this, char *product);
|
||||
|
||||
/**
|
||||
* Get Enumerator over files in a given directory with measurements
|
||||
* Get stored measurement hash for single file or directory entries
|
||||
*
|
||||
* @id primary key in files table, directory column in file_hashes table
|
||||
* @return enumerator over all measurements matching a given release
|
||||
* @param product software product (os, vpn client, etc.)
|
||||
* @param algo hash algorithm used for measurement
|
||||
* @param id primary key of measured file/directory
|
||||
* @param is_dir TRUE if directory was measured
|
||||
* @return enumerator over all matching measurement hashes
|
||||
*/
|
||||
enumerator_t* (*create_files_in_dir_enumerator)(pts_database_t *this, int id);
|
||||
|
||||
/**
|
||||
* Get Hash measurement of a file in a folder with given id and hashing algorithm type
|
||||
*
|
||||
* @received_hash measurement of a file to match with database entry
|
||||
* @product software product (os, vpn client, etc.)
|
||||
* @id primary key in files table
|
||||
* @file_name path in files table, obligatory for the files in directory
|
||||
* @algorithm measurement algorithm type
|
||||
* @is_dir TRUE if file is requested as content in a directory
|
||||
* @return enumerator over all measurements matching a given release
|
||||
*/
|
||||
bool (*check_measurement)(pts_database_t *this, chunk_t received_hash,
|
||||
char *product, int id, char *file_name, pts_meas_algorithms_t algorithm, bool is_dir);
|
||||
|
||||
enumerator_t* (*create_hash_enumerator)(pts_database_t *this, char *product,
|
||||
pts_meas_algorithms_t algo,
|
||||
int id, bool is_dir);
|
||||
|
||||
/**
|
||||
* Destroys a pts_database_t object.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "pts_file_meas.h"
|
||||
|
||||
#include <utils/linked_list.h>
|
||||
#include <debug.h>
|
||||
|
||||
typedef struct private_pts_file_meas_t private_pts_file_meas_t;
|
||||
|
||||
@@ -106,6 +107,52 @@ METHOD(pts_file_meas_t, create_enumerator, enumerator_t*,
|
||||
(void*)entry_filter, NULL, NULL);
|
||||
}
|
||||
|
||||
METHOD(pts_file_meas_t, verify, bool,
|
||||
private_pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir)
|
||||
{
|
||||
char *filename;
|
||||
chunk_t measurement;
|
||||
entry_t *entry;
|
||||
enumerator_t *enumerator;
|
||||
bool found, success = TRUE;
|
||||
|
||||
while (e_hash->enumerate(e_hash, &filename, &measurement))
|
||||
{
|
||||
found = FALSE;
|
||||
|
||||
enumerator = this->list->create_enumerator(this->list);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
if (!is_dir || streq(filename, entry->filename))
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (!found)
|
||||
{
|
||||
DBG1(DBG_TNC, " no measurement found for '%s'", filename);
|
||||
success = FALSE;
|
||||
}
|
||||
if (chunk_equals(measurement, entry->measurement))
|
||||
{
|
||||
DBG2(DBG_TNC, " %#B for '%s' is ok", &measurement, filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_TNC, " %#B for '%s' is incorrect", &measurement, filename);
|
||||
success = FALSE;
|
||||
}
|
||||
if (!is_dir)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
METHOD(pts_file_meas_t, destroy, void,
|
||||
private_pts_file_meas_t *this)
|
||||
{
|
||||
@@ -126,6 +173,7 @@ pts_file_meas_t *pts_file_meas_create(u_int16_t request_id)
|
||||
.get_file_count = _get_file_count,
|
||||
.add = _add,
|
||||
.create_enumerator = _create_enumerator,
|
||||
.verify = _verify,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.request_id = request_id,
|
||||
|
||||
@@ -53,12 +53,21 @@ struct pts_file_meas_t {
|
||||
void (*add)(pts_file_meas_t *this, char *filename, chunk_t measurement);
|
||||
|
||||
/**
|
||||
* Create a PTS File Measurement enumerator
|
||||
*
|
||||
* @return Enumerator returning filename and measurement
|
||||
*/
|
||||
* Create a PTS File Measurement enumerator
|
||||
*
|
||||
* @return Enumerator returning filename and measurement
|
||||
*/
|
||||
enumerator_t* (*create_enumerator)(pts_file_meas_t *this);
|
||||
|
||||
/**
|
||||
* Verify stored hashes against PTS File Measurements
|
||||
*
|
||||
* @param e_hash Hash enumerator
|
||||
* @paraem is_dir TRUE for directory contents hashes
|
||||
* @return TRUE if all hashes match a measurement
|
||||
*/
|
||||
bool (*verify)(pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir);
|
||||
|
||||
/**
|
||||
* Destroys a pts_file_meas_t object.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user