Added Check_Measurement function to pts_database instead of returning enumerator...
authorSansar Choinyambuu <schoinya@hsr.ch>
Wed, 7 Sep 2011 13:38:58 +0000 (15:38 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 8 Sep 2011 10:13:10 +0000 (12:13 +0200)
List of requested files/directories are kept within imv state now
Allocated memory for entries in files_in_dir_with_meas list

src/libimcv/plugins/imv_attestation/imv_attestation.c
src/libimcv/plugins/imv_attestation/imv_attestation_state.c
src/libimcv/plugins/imv_attestation/imv_attestation_state.h
src/libimcv/tcg/pts/pts_database.c
src/libimcv/tcg/pts/pts_database.h

index d32006f..12ce274 100644 (file)
@@ -43,7 +43,6 @@
 
 #include <pen/pen.h>
 #include <debug.h>
-#include <utils/linked_list.h>
 #include <credentials/credential_manager.h>
 
 /* IMV definitions */
@@ -82,11 +81,6 @@ static pts_creds_t *pts_creds;
 static credential_manager_t *pts_credmgr;
 
 /**
- * List of id's for the files that are requested for measurement
- */
-static linked_list_t *requested_files;
-
-/**
  * see section 3.7.1 of TCG TNC IF-IMV Specification 1.2
  */
 TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id,
@@ -282,7 +276,6 @@ static TNC_Result send_message(TNC_ConnectionID connection_id)
                                break;
                        }
                        
-                       requested_files = linked_list_create();
                        while (enumerator->enumerate(enumerator, &id, &type, &pathname))
                        {
                                is_directory = (type != 0);
@@ -292,7 +285,8 @@ static TNC_Result send_message(TNC_ConnectionID connection_id)
                                                                                                        delimiter, pathname);
                                attr->set_noskip_flag(attr, TRUE);
                                msg->add_attribute(msg, attr);
-                               requested_files->insert_last(requested_files, (void*)id);
+
+                               attestation_state->add_requested_file(attestation_state, id, type);
                        }
                        enumerator->destroy(enumerator);
 
@@ -320,6 +314,15 @@ static TNC_Result send_message(TNC_ConnectionID connection_id)
 }
 
 /**
+ * String matching function with boolean return value
+ * Used to remove an item from linked list of strings
+ */
+static bool string_cmp(char *a, char *b)
+{
+       return (strcmp(a,b) == 0) ? TRUE : FALSE;
+}
+
+/**
  * see section 3.7.3 of TCG TNC IF-IMV Specification 1.2
  */
 TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
@@ -518,15 +521,15 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
                                        DBG1(DBG_IMV, "measurement request %d returned %d file%s:",
                                                 request_id, file_count, (file_count == 1) ? "":"s");
 
-                                       if (!pts_db->is_directory(pts_db, request_id, &is_directory))
+                                       if (!attestation_state->is_request_dir(attestation_state, request_id, &is_directory))
                                        {
-                                               DBG1(DBG_IMV, "file entry with request id:%d not found", request_id);
+                                               DBG1(DBG_IMV, "received measurement with id: %d was not requested", request_id);
+                                               fatal_error = TRUE;
                                                break;
                                        }
-                                       
                                        if (!is_directory)
                                        {
-                                               requested_files->remove(requested_files, (void*)request_id, NULL);
+                                               attestation_state->remove_requested_file(attestation_state, request_id);
                                        }
                                        else
                                        {
@@ -536,61 +539,46 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
                                                e = pts_db->create_files_in_dir_enumerator(pts_db, request_id);
                                                while (e->enumerate(e, &file))
                                                {
-                                                       files_in_dir_with_meas->insert_last(files_in_dir_with_meas, file);
-                                                       DBG3(DBG_IMV, "expecting measurement for: %s with request_id: %d", file, request_id);
+                                                       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))
                                        {
-                                               enumerator_t *e;
-                                               chunk_t db_measurement;
-
-                                               e = (is_directory) ? pts_db->create_dir_meas_enumerator(pts_db,
-                                                                               platform_info, request_id, filename, algo) :
-                                                                               pts_db->create_file_meas_enumerator(pts_db,
-                                                                               platform_info, request_id, algo);
-                                               if (!e)
-                                               {
-                                                       DBG1(DBG_IMV, "  database enumerator failed");
-                                                       continue;
-                                               }
-                                               if (!e->enumerate(e, &db_measurement))
-                                               {
-                                                       DBG2(DBG_IMV, "  measurement for '%s' not found"
-                                                                                 " in database", filename);
-                                                       e->destroy(e);
-                                                       continue;
-                                               }
-                                               if (chunk_equals(db_measurement, measurement))
-                                               {
-                                                       DBG2(DBG_IMV, "  %#B for '%s' is ok",
-                                                                &measurement, filename);
-                                               }
-                                               else
+                                               bool hash_matched;
+                                               
+                                               hash_matched = pts_db->check_measurement(pts_db,
+                                                                                               measurement, platform_info,
+                                                                                               request_id, filename, algo, is_directory);
+                                               if (!hash_matched)
                                                {
-                                                       DBG1(DBG_IMV, " %#B for '%s' does not match %#B",
-                                                                &measurement, filename, &db_measurement);
                                                        measurement_error = TRUE;
                                                }
-
-                                               if (is_directory)
-                                               {
+                                               
+                                               if (is_directory &&
                                                        files_in_dir_with_meas->remove(files_in_dir_with_meas,
-                                                                               filename, (bool (*)(void*,void*))strcmp);
+                                                                               filename, (bool (*)(void*,void*))string_cmp))
+                                               {
+                                                       DBG3(DBG_IMV, "Removed %s from expected files list", filename);
                                                }
-                                               e->destroy(e);
                                        }
 
                                        if (is_directory && 
                                                !files_in_dir_with_meas->get_count(files_in_dir_with_meas))
                                        {
-                                               requested_files->remove(requested_files, (void*)request_id, NULL);
+                                               attestation_state->remove_requested_file(attestation_state, request_id);
+                                               DBG3(DBG_IMV, "Received all expected files measured for request: %d", request_id);
                                        }
 
-                                       files_in_dir_with_meas->destroy(files_in_dir_with_meas);
+                                       files_in_dir_with_meas->destroy_function(files_in_dir_with_meas, free);
                                        e_meas->destroy(e_meas);
+                                       
                                        break;
                                }
        
@@ -630,7 +618,6 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
        pa_tnc_msg->destroy(pa_tnc_msg);
        
 
-
        if (fatal_error)
        {
                state->set_recommendation(state,
@@ -642,19 +629,19 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
 
        if (attestation_state->get_handshake_state(attestation_state) &
                IMV_ATTESTATION_STATE_END)
-       {
-               if (measurement_error || requested_files->get_count(requested_files))
+       {       
+               if (measurement_error || attestation_state->get_requests_count(attestation_state))
                {
                        enumerator_t *e;
                        int request;
                        
-                       e  = requested_files->create_enumerator(requested_files);
+                       e = attestation_state->create_requests_enumerator(attestation_state);
                        while (e->enumerate(e, &request))
                        {
                                DBG1(DBG_IMV, "measurement/s not received for requests: %d", request);
                        }
-
                        e->destroy(e);
+                       
                        state->set_recommendation(state,
                                                                TNC_IMV_ACTION_RECOMMENDATION_ISOLATE,
                                                                TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR);
@@ -733,7 +720,6 @@ TNC_Result TNC_IMV_Terminate(TNC_IMVID imv_id)
        }
        DESTROY_IF(pts_db);
        pts_credmgr->destroy(pts_credmgr);
-       requested_files->destroy(requested_files);
        imv_attestation->destroy(imv_attestation);
        imv_attestation = NULL;
 
index e3165d0..00f8542 100644 (file)
@@ -60,6 +60,11 @@ struct private_imv_attestation_state_t {
         */
        pts_t *pts;
 
+       /**
+        * Requested files and directories
+        */
+       linked_list_t *requested_files;
+
 };
 
 typedef struct entry_t entry_t;
@@ -157,6 +162,7 @@ METHOD(imv_state_t, destroy, void,
        private_imv_attestation_state_t *this)
 {
        this->pts->destroy(this->pts);
+       this->requested_files->destroy_function(this->requested_files, free);
        free(this);
 }
 
@@ -178,6 +184,73 @@ METHOD(imv_attestation_state_t, get_pts, pts_t*,
        return this->pts;
 }
 
+METHOD(imv_attestation_state_t, create_requests_enumerator, enumerator_t*,
+       private_imv_attestation_state_t *this)
+{
+       enumerator_t *e;
+       e = this->requested_files->create_enumerator(this->requested_files);
+       return e;
+}
+
+METHOD(imv_attestation_state_t, get_requests_count, int,
+       private_imv_attestation_state_t *this)
+{
+       return this->requested_files->get_count(this->requested_files);
+}
+
+
+METHOD(imv_attestation_state_t, add_requested_file, void,
+       private_imv_attestation_state_t *this, int request_id, int is_dir)
+{
+       file_request_t *entry;
+
+       entry = malloc_thing(file_request_t);
+       entry->request_id = request_id;
+       entry->is_dir = is_dir;
+       this->requested_files->insert_last(this->requested_files, entry);
+}
+
+/**
+ * Comparison function to match an file request entry with its request_id
+ */
+static bool request_match(file_request_t *current_list_item, int request_id)
+{
+       return (current_list_item->request_id == request_id);
+}
+
+METHOD(imv_attestation_state_t, remove_requested_file, bool,
+       private_imv_attestation_state_t *this, int request_id)
+{
+       file_request_t *entry;
+
+       if (this->requested_files->find_first(this->requested_files,
+                       (linked_list_match_t)request_match, (void**)&entry, request_id) != SUCCESS)
+       {
+               DBG1(DBG_IMV, "request entry with id: %d not found", request_id);
+               return FALSE;
+       }
+
+       this->requested_files->remove(this->requested_files, entry, NULL);
+       return TRUE;
+}
+
+METHOD(imv_attestation_state_t, is_request_dir, bool,
+       private_imv_attestation_state_t *this, int request_id, bool *is_dir)
+{
+       file_request_t *entry;
+
+       if (this->requested_files->find_first(this->requested_files,
+                       (linked_list_match_t)request_match, (void**)&entry, request_id) != SUCCESS)
+       {
+               DBG1(DBG_IMV, "request entry with id: %d not found", request_id);
+               return FALSE;
+       }
+       
+       *is_dir = (entry->is_dir);
+       return TRUE;
+}
+
+
 /**
  * Described in header.
  */
@@ -199,6 +272,11 @@ imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id)
                        .get_handshake_state = _get_handshake_state,
                        .set_handshake_state = _set_handshake_state,
                        .get_pts = _get_pts,
+                       .create_requests_enumerator = _create_requests_enumerator,
+                       .get_requests_count = _get_requests_count,
+                       .add_requested_file = _add_requested_file,
+                       .remove_requested_file = _remove_requested_file,
+                       .is_request_dir = _is_request_dir,
                },
                .connection_id = connection_id,
                .state = TNC_CONNECTION_STATE_CREATE,
@@ -206,6 +284,7 @@ imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id)
                .rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
                .eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
                .pts = pts_create(FALSE),
+               .requested_files = linked_list_create(),
        );
 
        platform_info = lib->settings->get_str(lib->settings,
index 2e83e82..09bf04c 100644 (file)
 #include <imv/imv_state.h>
 #include <tcg/pts/pts.h>
 #include <library.h>
+#include <utils/linked_list.h>
 
 typedef struct imv_attestation_state_t imv_attestation_state_t;
 typedef enum imv_attestation_handshake_state_t imv_attestation_handshake_state_t;
+typedef struct file_request_t file_request_t;
 
 /**
  * IMV Attestation Handshake States (state machine)
@@ -41,6 +43,14 @@ enum imv_attestation_handshake_state_t {
 };
 
 /**
+ * Defines an structure to hold requested file/directory
+ */
+struct file_request_t {
+       int request_id;
+       int is_dir;
+};
+
+/**
  * Internal state of an imv_attestation_t connection instance
  */
 struct imv_attestation_state_t {
@@ -72,6 +82,43 @@ struct imv_attestation_state_t {
         */
        pts_t* (*get_pts)(imv_attestation_state_t *this);
 
+       /**
+        * Add an entry to list of requested files/directories
+        *
+        * @param request_id                            unique request id
+        * @param is_dir                                        0 for file and 1 for directory
+        */
+       void (*add_requested_file)(imv_attestation_state_t *this, int request_id, int is_dir);
+
+       /**
+        * Creates enumerator over the list of requested file/directories
+        *
+        * @return                                                      enumerator over requested files/directories list
+        */
+       enumerator_t* (*create_requests_enumerator)(imv_attestation_state_t *this);
+
+       /**
+        * Returns number of entries in the list of requested file/directories
+        *
+        * @return                                                      number of entries in the list of requested file/directories
+        */
+       int (*get_requests_count)(imv_attestation_state_t *this);
+
+       /**
+        * Removes an entry with matching request_id from list of requested files/directories
+        *
+        * @param request_id                            unique request id
+        * @return                                                      TRUE if request entry found, FALSE otherwise
+        */
+       bool (*remove_requested_file)(imv_attestation_state_t *this, int request_id);
+
+       /**
+        * Returns TRUE if entry with given ID is directory and FALSE otherwise
+        *
+        * @param request_id                            unique request id
+        * @return                                                      TRUE if request entry found, FALSE otherwise
+        */
+       bool (*is_request_dir)(imv_attestation_state_t *this, int request_id, bool *is_dir);
 };
 
 /**
index e256dc9..f38e5dd 100644 (file)
@@ -54,35 +54,6 @@ METHOD(pts_database_t, create_file_enumerator, enumerator_t*,
        return e;
 }
 
-METHOD(pts_database_t, is_directory, bool,
-       private_pts_database_t *this, int id, bool *is_directory)
-{
-       enumerator_t *e;
-       int is_dir;
-
-       /* look for a entry in files table with matching id */
-       e = this->db->query(this->db,
-                               "SELECT f.type FROM files AS f "
-                               "WHERE f.id = ?",
-                               DB_INT, id, DB_INT);
-
-       if (!e)
-       {
-               DBG1(DBG_TNC, "database enumerator failed", id);
-               return FALSE;
-       }
-       if (!e->enumerate(e, &is_dir))
-       {
-               e->destroy(e);
-               DBG1(DBG_TNC, "file entry with given id:%d not found", id);
-               return FALSE;
-       }
-
-       *is_directory = (is_dir == 1) ? TRUE : FALSE;
-       return TRUE;
-}
-
-
 METHOD(pts_database_t, create_files_in_dir_enumerator, enumerator_t*,
        private_pts_database_t *this, int id)
 {
@@ -97,36 +68,54 @@ METHOD(pts_database_t, create_files_in_dir_enumerator, enumerator_t*,
        return e;
 }
 
-METHOD(pts_database_t, create_file_meas_enumerator, enumerator_t*,
-       private_pts_database_t *this, char *product, int id, pts_meas_algorithms_t algorithm)
+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 */
        
-       /* look for all entries belonging to a product and file in file_hashes table */
-       e = this->db->query(this->db,
+       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 p.name = ? AND f.id = ? AND fh.algo = ?",
-                               DB_TEXT, product, DB_INT, id, DB_INT, algorithm, DB_BLOB);
-       return e;
-}
-
-METHOD(pts_database_t, create_dir_meas_enumerator, enumerator_t*,
-       private_pts_database_t *this, char *product, int id, char *file_name, pts_meas_algorithms_t algorithm)
-{
-       enumerator_t *e;
-
-       /* look for all entries belonging to a product, file and directory in file_hashes table */
-       e = this->db->query(this->db,
+                               "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 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);
-       return e;
+                               "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)
 {
@@ -144,10 +133,8 @@ pts_database_t *pts_database_create(char *uri)
        INIT(this,
                .public = {
                        .create_file_enumerator = _create_file_enumerator,
-                       .is_directory = _is_directory,
                        .create_files_in_dir_enumerator = _create_files_in_dir_enumerator,
-                       .create_file_meas_enumerator = _create_file_meas_enumerator,
-                       .create_dir_meas_enumerator = _create_dir_meas_enumerator,
+                       .check_measurement = _check_measurement,
                        .destroy = _destroy,
                },
                .db = lib->db->create(lib->db, uri),
index d4d595c..d69b0c1 100644 (file)
@@ -41,15 +41,6 @@ struct pts_database_t {
        enumerator_t* (*create_file_enumerator)(pts_database_t *this, char *product);
 
        /**
-       * Get if file with given id is directory
-       *
-       * @id                                   primary key in files table
-       * @is_directory                 TRUE if entry with given ID has type of directory
-       * @return                               TRUE if query is not failed
-       */
-       bool (*is_directory)(pts_database_t *this, int id, bool *is_directory);
-
-       /**
        * Get Enumerator over files in a given directory with measurements
        *
        * @id                                   primary key in files table, directory column in file_hashes table
@@ -58,26 +49,18 @@ struct pts_database_t {
        enumerator_t* (*create_files_in_dir_enumerator)(pts_database_t *this, int id);
 
        /**
-       * Get Hash measurement of a file with given id and hashing algorithm type
-       *
-       * @product                              software product (os, vpn client, etc.)
-       * @id                                   primary key in files table
-       * @algorithm                            measurement algorithm type
-       * @return                               enumerator over all measurements matching a given release
-       */
-       enumerator_t* (*create_file_meas_enumerator)(pts_database_t *this, char *product,
-                                                                               int id, pts_meas_algorithms_t algorithm);
-       /**
        * 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
+       * @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
        */
-       enumerator_t* (*create_dir_meas_enumerator)(pts_database_t *this, char *product,
-                                                       int id, char *file_name, pts_meas_algorithms_t algorithm);
+       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);
 
 
        /**
@@ -90,7 +73,7 @@ struct pts_database_t {
 /**
  * Creates an pts_database_t object
  *
- * @param ur                           database uri
+ * @param uri                          database uri
  */
 pts_database_t* pts_database_create(char *uri);