refactored measurement verification
authorAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 7 Sep 2011 22:49:19 +0000 (00:49 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 8 Sep 2011 10:20:57 +0000 (12:20 +0200)
src/libimcv/plugins/imv_attestation/imv_attestation.c
src/libimcv/tcg/pts/pts_database.c
src/libimcv/tcg/pts/pts_database.h
src/libimcv/tcg/pts/pts_file_meas.c
src/libimcv/tcg/pts/pts_file_meas.h

index 4a87e87..de93b9c 100644 (file)
@@ -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;
                                        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;
                                        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)
                                        {
                                        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;
                                        }
                                                DBG1(DBG_IMV, "  no entry found for this request"); 
                                                break;
                                        }
-                                       if (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);
-                                       }
-                                       
-                                       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))
+                                       /* 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))
                                        {
                                        {
-                                               DBG3(DBG_IMV, "recevied all expected file measurements for request: %d", request_id);
+                                               DBG1(DBG_IMV, "  measurement error occured"); 
+                                               measurement_error = TRUE;
                                        }
                                        }
-
-                                       files_in_dir_with_meas->destroy_function(files_in_dir_with_meas, free);
-                                       e_meas->destroy(e_meas);
+                                       e_hash->destroy(e_hash);
                                        break;
                                }
        
                                        break;
                                }
        
index f38e5dd..594ddd0 100644 (file)
@@ -54,68 +54,33 @@ METHOD(pts_database_t, create_file_enumerator, enumerator_t*,
        return e;
 }
 
        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;
 
 {
        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);
-       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 "
+       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 "
                                "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;
+                               "WHERE p.name = ? AND fh.directory = ? AND fh.algo = ?",
+                               DB_TEXT, product, DB_INT, id, DB_INT, algo, DB_TEXT, DB_BLOB);
        }
        }
-       if (!e->enumerate(e, &db_measurement))
+       else
        {
        {
-               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;
+               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);
        }
        }
-
-       DBG1(DBG_IMV, " %#B for '%s' does not match %#B",
-                                       &received_hash, file_name, &db_measurement);
-       return FALSE;
+       return e;
 }
 
 }
 
-
 METHOD(pts_database_t, destroy, void,
        private_pts_database_t *this)
 {
 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,
        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),
                        .destroy = _destroy,
                },
                .db = lib->db->create(lib->db, uri),
index d69b0c1..f2a6854 100644 (file)
@@ -35,33 +35,23 @@ struct pts_database_t {
        /**
        * Get files to be measured by PTS
        *
        /**
        * 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);
 
        /**
        */
        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.
 
        /**
        * Destroys a pts_database_t object.
index 70bd503..8208949 100644 (file)
@@ -16,6 +16,7 @@
 #include "pts_file_meas.h"
 
 #include <utils/linked_list.h>
 #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;
 
 
 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);
 }
 
                                                                   (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)
 {
 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,
                        .get_file_count = _get_file_count,
                        .add = _add,
                        .create_enumerator = _create_enumerator,
+                       .verify = _verify,
                        .destroy = _destroy,
                },
                .request_id = request_id,
                        .destroy = _destroy,
                },
                .request_id = request_id,
index fabd08b..3ebb5c2 100644 (file)
@@ -53,11 +53,20 @@ struct pts_file_meas_t {
        void (*add)(pts_file_meas_t *this, char *filename, chunk_t measurement);
 
        /**
        void (*add)(pts_file_meas_t *this, char *filename, chunk_t measurement);
 
        /**
-        * Create a PTS File Measurement enumerator
+         * 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
         *
         *
-        * @return                              Enumerator returning filename and measurement
+        * @param e_hash                Hash enumerator
+        * @paraem is_dir               TRUE for directory contents hashes
+        * @return                              TRUE if all hashes match a measurement
         */
         */
-       enumerator_t* (*create_enumerator)(pts_file_meas_t *this);
+       bool (*verify)(pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir);
 
        /**
         * Destroys a pts_file_meas_t object.
 
        /**
         * Destroys a pts_file_meas_t object.