refactored measurement verification

This commit is contained in:
Andreas Steffen
2011-09-08 12:20:57 +02:00
parent 925f54d36e
commit 582bda55dd
5 changed files with 104 additions and 131 deletions
@@ -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;
}
+22 -58
View File
@@ -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),
+11 -21
View File
@@ -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.
+48
View File
@@ -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,
+13 -4
View File
@@ -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.
*/