ipsec attest now can measure all files in a directory
authorAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 16 Jul 2012 07:53:32 +0000 (09:53 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 16 Jul 2012 07:54:11 +0000 (09:54 +0200)
src/libpts/plugins/imc_attestation/imc_attestation_process.c
src/libpts/plugins/imv_attestation/attest.c
src/libpts/plugins/imv_attestation/attest_db.c
src/libpts/plugins/imv_attestation/attest_db.h
src/libpts/plugins/imv_attestation/data.sql
src/libpts/pts/pts.c
src/libpts/pts/pts.h
src/libpts/pts/pts_file_meas.c
src/libpts/pts/pts_file_meas.h

index d5ff07f..edaaa57 100644 (file)
@@ -254,8 +254,9 @@ bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list,
                        DBG2(DBG_IMC, "measurement request %d for %s '%s'",
                                 request_id, is_directory ? "directory" : "file",
                                 pathname);
-                       measurements = pts->do_measurements(pts, request_id,
-                                                                       pathname, is_directory);
+                       measurements = pts_file_meas_create_from_path(request_id,
+                                                                               pathname, is_directory, TRUE,
+                                                                               pts->get_meas_algorithm(pts));
                        if (!measurements)
                        {
                                /* TODO handle error codes from measurements */
index 518ec7a..ffea7c2 100644 (file)
@@ -131,9 +131,11 @@ static void do_args(int argc, char *argv[])
                        { "directory", required_argument, NULL, 'D' },
                        { "dir", required_argument, NULL, 'D' },
                        { "file", required_argument, NULL, 'F' },
+                       { "ima", no_argument, NULL, 'I' },
                        { "key", required_argument, NULL, 'K' },
                        { "owner", required_argument, NULL, 'O' },
                        { "product", required_argument, NULL, 'P' },
+                       { "relative", no_argument, NULL, 'R' },
                        { "sha1", no_argument, NULL, '1' },
                        { "sha256", no_argument, NULL, '2' },
                        { "sha384", no_argument, NULL, '3' },
@@ -232,6 +234,9 @@ static void do_args(int argc, char *argv[])
                                        exit(EXIT_FAILURE);
                                }
                                continue;
+                       case 'I':
+                               attest->set_ima(attest);
+                               continue;
                        case 'K':
                        {
                                chunk_t aik;
@@ -252,6 +257,9 @@ static void do_args(int argc, char *argv[])
                                        exit(EXIT_FAILURE);
                                }
                                continue;
+                       case 'R':
+                               attest->set_relative(attest);
+                               continue;
                        case '1':
                                attest->set_algo(attest, PTS_MEAS_ALGO_SHA1);
                                continue;
index 213c72e..64cc4b9 100644 (file)
 #include "attest_db.h"
 
 #include "libpts.h"
+#include "pts/pts_file_meas.h"
 #include "pts/components/pts_comp_func_name.h"
 
+#include <libgen.h>
+
 typedef struct private_attest_db_t private_attest_db_t;
 
 /**
@@ -106,6 +109,16 @@ struct private_attest_db_t {
        bool product_set;
 
        /**
+        * TRUE if relative filenames are to be used
+        */
+       bool relative;
+
+       /**
+        * TRUE if IMA-specific SHA-1 template hash be computed
+        */
+       bool ima;
+
+       /**
         * File measurement hash algorithm
         */
        pts_meas_algorithms_t algo;
@@ -252,6 +265,7 @@ METHOD(attest_db_t, set_directory, bool,
        private_attest_db_t *this, char *dir, bool create)
 {
        enumerator_t *e;
+       size_t len;
 
        if (this->dir_set)
        {
@@ -259,6 +273,13 @@ METHOD(attest_db_t, set_directory, bool,
                return FALSE;
        }
        free(this->dir);
+
+       /* remove trailing '/' character */
+       len = strlen(dir);
+       if (len && dir[len-1] == '/')
+       {
+               dir[len-1] = '\0';
+       }
        this->dir = strdup(dir);
 
        e = this->db->query(this->db,
@@ -568,6 +589,18 @@ METHOD(attest_db_t, set_algo, void,
        this->algo = algo;
 }
 
+METHOD(attest_db_t, set_ima, void,
+       private_attest_db_t *this)
+{
+       this->ima = TRUE;
+}
+
+METHOD(attest_db_t, set_relative, void,
+       private_attest_db_t *this)
+{
+       this->relative = TRUE;
+}
+
 METHOD(attest_db_t, set_owner, void,
        private_attest_db_t *this, char *owner)
 {
@@ -603,7 +636,7 @@ METHOD(attest_db_t, list_components, void,
                while (e->enumerate(e, &cid, &vid, &name, &qualifier))
                {
                        cfn   = pts_comp_func_name_create(vid, name, qualifier);
-                       printf("%3d: %s\n", cid, print_cfn(cfn));
+                       printf("%4d: %s\n", cid, print_cfn(cfn));
                        cfn->destroy(cfn);
                        count++;
                }
@@ -637,7 +670,7 @@ METHOD(attest_db_t, list_keys, void,
                {
                        while (e->enumerate(e, &kid, &keyid, &owner))
                        {
-                               printf("%3d: %#B '%s'\n", kid, &keyid, owner);
+                               printf("%4d: %#B '%s'\n", kid, &keyid, owner);
                                count++;
                        }
                        e->destroy(e);
@@ -652,7 +685,7 @@ METHOD(attest_db_t, list_keys, void,
                {
                        while (e->enumerate(e, &kid, &keyid, &owner))
                        {
-                               printf("%3d: %#B '%s'\n", kid, &keyid, owner);
+                               printf("%4d: %#B '%s'\n", kid, &keyid, owner);
                                count++;
                        }
                        e->destroy(e);
@@ -687,7 +720,7 @@ METHOD(attest_db_t, list_files, void,
                        while (e->enumerate(e, &fid, &type, &file, &meas, &meta))
                        {
                                type = (type < 0 || type > 2) ? 0 : type;
-                               printf("%3d: |%s%s| %s %s\n", fid, meas ? "M":" ", meta ? "T":" ",
+                               printf("%4d: |%s%s| %s %s\n", fid, meas ? "M":" ", meta ? "T":" ",
                                                                                          file_type[type], file);
                                count++;
                        }
@@ -705,7 +738,7 @@ METHOD(attest_db_t, list_files, void,
                        while (e->enumerate(e, &fid, &type, &file))
                        {
                                type = (type < 0 || type > 2) ? 0 : type;
-                               printf("%3d: %s %s\n", fid, file_type[type], file);
+                               printf("%4d: %s %s\n", fid, file_type[type], file);
                                count++;
                        }
                        e->destroy(e);
@@ -739,7 +772,7 @@ METHOD(attest_db_t, list_products, void,
                {
                        while (e->enumerate(e, &pid, &product, &meas, &meta))
                        {
-                               printf("%3d: |%s%s| %s\n", pid, meas ? "M":" ", meta ? "T":" ",
+                               printf("%4d: |%s%s| %s\n", pid, meas ? "M":" ", meta ? "T":" ",
                                                                                   product);
                                count++;
                        }
@@ -755,7 +788,7 @@ METHOD(attest_db_t, list_products, void,
                {
                        while (e->enumerate(e, &pid, &product))
                        {
-                               printf("%3d: %s\n", pid, product);
+                               printf("%4d: %s\n", pid, product);
                                count++;
                        }
                        e->destroy(e);
@@ -826,11 +859,11 @@ METHOD(attest_db_t, list_hashes, void,
                        {
                                if (this->fid != fid_old)
                                {
-                                       printf("%3d: %s%s%s\n", this->fid, this->dir,
+                                       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("      %#B\n", &hash);
                                count++;
                        }
                        e->destroy(e);
@@ -860,12 +893,12 @@ METHOD(attest_db_t, list_hashes, void,
                                        {
                                                get_directory(this, did, &dir);
                                        }
-                                       printf("%3d: %s%s%s\n", fid,
+                                       printf("%4d: %s%s%s\n", fid,
                                                   dir, slash(dir, file) ? "/" : "", file);
                                        fid_old = fid;
                                        did_old = did;
                                }
-                               printf("     %#B\n", &hash);
+                               printf("      %#B\n", &hash);
                                count++;
                        }
                        e->destroy(e);
@@ -922,11 +955,11 @@ METHOD(attest_db_t, list_hashes, void,
                                                get_directory(this, did, &dir);
                                                did_old = did;
                                        }
-                                       printf("%3d: %s%s%s\n", fid,
+                                       printf("%4d: %s%s%s\n", fid,
                                                   dir, slash(dir, file) ? "/" : "", file);
                                        fid_old = fid;
                                }
-                               printf("     %#B '%s'\n", &hash, product);
+                               printf("      %#B '%s'\n", &hash, product);
                                count++;
                        }
                        e->destroy(e);
@@ -964,7 +997,7 @@ METHOD(attest_db_t, list_measurements, void,
                        {
                                if (this->kid != kid_old)
                                {
-                                       printf("%3d: %#B '%s'\n", this->kid, &this->key, owner);
+                                       printf("%4d: %#B '%s'\n", this->kid, &this->key, owner);
                                        kid_old = this->kid;
                                }
                                printf("%5d %02d %#B\n", seq_no, pcr, &hash);
@@ -993,7 +1026,7 @@ METHOD(attest_db_t, list_measurements, void,
                        {
                                if (kid != kid_old)
                                {
-                                       printf("%3d: %#B '%s'\n", kid, &keyid, owner);
+                                       printf("%4d: %#B '%s'\n", kid, &keyid, owner);
                                        kid_old = kid;
                                }
                                printf("%5d %02d %#B\n", seq_no, pcr, &hash);
@@ -1026,7 +1059,7 @@ METHOD(attest_db_t, list_measurements, void,
                                if (cid != cid_old)
                                {
                                        cfn = pts_comp_func_name_create(vid, name, qualifier);
-                                       printf("%3d: %s\n", cid, print_cfn(cfn));
+                                       printf("%4d: %s\n", cid, print_cfn(cfn));
                                        cfn->destroy(cfn);
                                        cid_old = cid;
                                }
@@ -1047,6 +1080,7 @@ METHOD(attest_db_t, add, bool,
 {
        bool success = FALSE;
 
+       /* add key/component pair */
        if (this->kid && this->cid)
        {
                success = this->db->execute(this->db, NULL,
@@ -1056,6 +1090,104 @@ METHOD(attest_db_t, add, bool,
                printf("key/component pair (%d/%d) %sinserted into database\n",
                                this->kid, this->cid, success ? "" : "could not be ");
        }
+
+       /* add directory or file measurement for a given product */
+       if ((this->did || this->fid) && this->pid)
+       {
+               char *pathname, *filename, *label;
+               pts_file_meas_t *measurements;
+               chunk_t measurement, hash;
+               int fid, did, files_added = 0, hashes_added = 0;
+               enumerator_t *enumerator, *e;
+
+               pathname = this->did ? this->dir : this->file;
+               measurements = pts_file_meas_create_from_path(0, pathname, this->did,
+                                                                                               this->relative, this->algo);
+               if (!measurements)
+               {
+                       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);
+
+                       /* retrieve or create file hash */
+                       label = "could not be created";
+
+                       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, fid, DB_INT, did, DB_INT, this->pid,
+                               DB_BLOB);
+                       if (!e)
+                       {
+                               printf("file_hashes query failed\n");
+                               break;
+                       }
+                       if (e->enumerate(e, &hash))
+                       {
+                               label = chunk_equals(measurement, hash) ?
+                                               "exists and equals" : "exists and differs";
+                       }
+                       else
+                       {
+                               if (this->db->execute(this->db, NULL,
+                                       "INSERT INTO file_hashes "
+                                       "(file, directory, product, algo, hash) "
+                                       "VALUES (?, ?, ?, ?, ?)",
+                                       DB_INT, fid, DB_INT, did, DB_INT, this->pid,
+                                       DB_INT, this->algo,     DB_BLOB, measurement) == 1)
+                               {
+                                       label = "created";
+                                       hashes_added++;
+                               }
+                       }
+                       e->destroy(e);
+
+                       printf("     %#B - %s\n", &measurement, label);
+               }
+               enumerator->destroy(enumerator);
+
+               printf("%d measurements, added %d new files and %d new file hashes\n",
+                           measurements->get_file_count(measurements),
+                           files_added, hashes_added);
+               measurements->destroy(measurements);
+               success = TRUE;
+       }
        return success;
 }
 
@@ -1173,6 +1305,8 @@ attest_db_t *attest_db_create(char *uri)
                        .set_product = _set_product,
                        .set_pid = _set_pid,
                        .set_algo = _set_algo,
+                       .set_ima = _set_ima,
+                       .set_relative = _set_relative,
                        .set_owner = _set_owner,
                        .list_products = _list_products,
                        .list_files = _list_files,
index 9c9a9dc..4e7991a 100644 (file)
@@ -126,6 +126,16 @@ struct attest_db_t {
        void (*set_algo)(attest_db_t *this, pts_meas_algorithms_t algo);
 
        /**
+        * Set that the IMA-specific SHA-1 template hash be computed
+        */
+       void (*set_ima)(attest_db_t *this);
+
+       /**
+        * Set that relative filenames are to be used
+        */
+       void (*set_relative)(attest_db_t *this);
+
+       /**
         * Set owner [user/host] of an AIK
         *
         * @param owner                 user/host name
index a42245c..e014711 100644 (file)
@@ -89,7 +89,7 @@ INSERT INTO files (
 INSERT INTO files (
   type, path
 ) VALUES (
-  1, '/lib/xtables/'
+  1, '/lib/xtables'
 );
 
 INSERT INTO files (
index 3c42366..4ee20b4 100644 (file)
 #include <trousers/tss.h>
 #include <trousers/trousers.h>
 
+#include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/utsname.h>
+#include <libgen.h>
+#include <unistd.h>
 #include <errno.h>
 
-#define PTS_BUF_SIZE   4096
-
 /**
  * Maximum number of PCR's of TPM, TPM Spec 1.2
  */
@@ -486,54 +487,6 @@ METHOD(pts_t, get_aik_keyid, bool,
        return success;
 }
 
-METHOD(pts_t, hash_file, bool,
-       private_pts_t *this, hasher_t *hasher, char *pathname, u_char *hash)
-{
-       u_char buffer[PTS_BUF_SIZE];
-       FILE *file;
-       int bytes_read;
-
-       file = fopen(pathname, "rb");
-       if (!file)
-       {
-               DBG1(DBG_PTS,"  file '%s' can not be opened, %s", pathname,
-                        strerror(errno));
-               return FALSE;
-       }
-       while (TRUE)
-       {
-               bytes_read = fread(buffer, 1, sizeof(buffer), file);
-               if (bytes_read > 0)
-               {
-                       hasher->get_hash(hasher, chunk_create(buffer, bytes_read), NULL);
-               }
-               else
-               {
-                       hasher->get_hash(hasher, chunk_empty, hash);
-                       break;
-               }
-       }
-       fclose(file);
-
-       return TRUE;
-}
-
-/**
- * Get the relative filename of a fully qualified file pathname
- */
-static char* get_filename(char *pathname)
-{
-       char *pos, *filename;
-
-       pos = filename = pathname;
-       while (pos && *(++pos) != '\0')
-       {
-               filename = pos;
-               pos = strchr(filename, '/');
-       }
-       return filename;
-}
-
 METHOD(pts_t, is_path_valid, bool,
        private_pts_t *this, char *path, pts_error_code_t *error_code)
 {
@@ -565,82 +518,6 @@ METHOD(pts_t, is_path_valid, bool,
        return TRUE;
 }
 
-METHOD(pts_t, do_measurements, pts_file_meas_t*,
-       private_pts_t *this, u_int16_t request_id, char *pathname, bool is_directory)
-{
-       hasher_t *hasher;
-       hash_algorithm_t hash_alg;
-       u_char hash[HASH_SIZE_SHA384];
-       chunk_t measurement;
-       pts_file_meas_t *measurements;
-
-       /* Create a hasher */
-       hash_alg = pts_meas_algo_to_hash(this->algorithm);
-       hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
-       if (!hasher)
-       {
-               DBG1(DBG_PTS, "hasher %N not available", hash_algorithm_names, hash_alg);
-               return NULL;
-       }
-
-       /* Create a measurement object */
-       measurements = pts_file_meas_create(request_id);
-
-       /* Link the hash to the measurement and set the measurement length */
-       measurement = chunk_create(hash, hasher->get_hash_size(hasher));
-
-       if (is_directory)
-       {
-               enumerator_t *enumerator;
-               char *rel_name, *abs_name;
-               struct stat st;
-
-               enumerator = enumerator_create_directory(pathname);
-               if (!enumerator)
-               {
-                       DBG1(DBG_PTS,"  directory '%s' can not be opened, %s", pathname,
-                                strerror(errno));
-                       hasher->destroy(hasher);
-                       measurements->destroy(measurements);
-                       return NULL;
-               }
-               while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
-               {
-                       /* measure regular files only */
-                       if (S_ISREG(st.st_mode) && *rel_name != '.')
-                       {
-                               if (!hash_file(this, hasher, abs_name, hash))
-                               {
-                                       enumerator->destroy(enumerator);
-                                       hasher->destroy(hasher);
-                                       measurements->destroy(measurements);
-                                       return NULL;
-                               }
-                               DBG2(DBG_PTS, "  %#B for '%s'", &measurement, rel_name);
-                               measurements->add(measurements, rel_name, measurement);
-                       }
-               }
-               enumerator->destroy(enumerator);
-       }
-       else
-       {
-               char *filename;
-
-               if (!hash_file(this, hasher, pathname, hash))
-               {
-                       hasher->destroy(hasher);
-                       measurements->destroy(measurements);
-                       return NULL;
-               }
-               filename = get_filename(pathname);
-               DBG2(DBG_PTS, "  %#B for '%s'", &measurement, filename);
-               measurements->add(measurements, filename, measurement);
-       }
-       hasher->destroy(hasher);
-
-       return measurements;
-}
-
 /**
  * Obtain statistical information describing a file
  */
@@ -748,7 +625,7 @@ METHOD(pts_t, get_metadata, pts_file_meta_t*,
                        metadata->destroy(metadata);
                        return NULL;
                }
-               entry->filename = strdup(get_filename(pathname));
+               entry->filename = strdup(basename(pathname));
                metadata->add(metadata, entry);
        }
 
@@ -1499,8 +1376,6 @@ pts_t *pts_create(bool is_imc)
                        .set_aik = _set_aik,
                        .get_aik_keyid = _get_aik_keyid,
                        .is_path_valid = _is_path_valid,
-                       .hash_file = _hash_file,
-                       .do_measurements = _do_measurements,
                        .get_metadata = _get_metadata,
                        .read_pcr = _read_pcr,
                        .extend_pcr = _extend_pcr,
index 212acb0..c35f686 100644 (file)
@@ -230,34 +230,13 @@ struct pts_t {
        bool (*is_path_valid)(pts_t *this, char *path, pts_error_code_t *error_code);
 
        /**
-       * Compute a hash over a file
-        * @param hasher                        Hasher to be used
-        * @param pathname                      Absolute path of a file
-        * @param hash                          Buffer to keep hash output
-        * @return                                      TRUE if path is valid and hashing succeeded
-        */
-       bool (*hash_file)(pts_t *this, hasher_t *hasher, char *pathname, u_char *hash);
-
-       /**
-        * Do PTS File Measurements
-        *
-        * @param request_id            ID of PTS File Measurement Request
-        * @param pathname                      Absolute pathname of file to be measured
-        * @param is_directory          TRUE if directory contents are measured
-        * @return                                      PTS File Measurements of NULL if FAILED
-        */
-       pts_file_meas_t* (*do_measurements)(pts_t *this, u_int16_t request_id,
-                                                                               char *pathname, bool is_directory);
-
-       /**
         * Obtain file metadata
         *
         * @param pathname                      Absolute pathname of file/directory
-        * @param is_directory          TRUE if directory contents are requested
+        * @param is_dir                        TRUE if directory contents are requested
         * @return                                      PTS File Metadata or NULL if FAILED
         */
-       pts_file_meta_t* (*get_metadata)(pts_t *this, char *pathname,
-                                                                        bool is_directory);
+       pts_file_meta_t* (*get_metadata)(pts_t *this, char *pathname, bool is_dir);
 
        /**
         * Reads given PCR value and returns it
index 8db3ea9..32d50c9 100644 (file)
 #include <utils/linked_list.h>
 #include <debug.h>
 
+#include <sys/stat.h>
+#include <libgen.h>
+#include <errno.h>
+
 typedef struct private_pts_file_meas_t private_pts_file_meas_t;
 
 /**
@@ -201,3 +205,131 @@ pts_file_meas_t *pts_file_meas_create(u_int16_t request_id)
        return &this->public;
 }
 
+/**
+ * Hash a file with a given absolute pathname
+ */
+static bool hash_file(hasher_t *hasher, char *pathname, u_char *hash)
+{
+       u_char buffer[4096];
+       size_t bytes_read;
+       FILE *file;
+
+       file = fopen(pathname, "rb");
+       if (!file)
+       {
+               DBG1(DBG_PTS,"  file '%s' can not be opened, %s", pathname,
+                        strerror(errno));
+               return FALSE;
+       }
+       while (TRUE)
+       {
+               bytes_read = fread(buffer, 1, sizeof(buffer), file);
+               if (bytes_read > 0)
+               {
+                       hasher->get_hash(hasher, chunk_create(buffer, bytes_read), NULL);
+               }
+               else
+               {
+                       hasher->get_hash(hasher, chunk_empty, hash);
+                       break;
+               }
+       }
+       fclose(file);
+
+       return TRUE;
+}
+
+/**
+ * See header
+ */
+pts_file_meas_t *pts_file_meas_create_from_path(u_int16_t request_id,
+                                                       char *pathname, bool is_dir, bool use_rel_name,
+                                                       pts_meas_algorithms_t alg)
+{
+       private_pts_file_meas_t *this;
+       hash_algorithm_t hash_alg;
+       hasher_t *hasher;
+       u_char hash[HASH_SIZE_SHA384];
+       chunk_t measurement;
+       char* filename;
+       bool success = TRUE;
+
+       /* Create a hasher and a hash measurement buffer */
+       hash_alg = pts_meas_algo_to_hash(alg);
+       hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+       if (!hasher)
+       {
+               DBG1(DBG_PTS, "hasher %N not available", hash_algorithm_names, hash_alg);
+               return NULL;
+       }
+       measurement = chunk_create(hash, hasher->get_hash_size(hasher));
+
+       INIT(this,
+               .public = {
+                       .get_request_id = _get_request_id,
+                       .get_file_count = _get_file_count,
+                       .add = _add,
+                       .create_enumerator = _create_enumerator,
+                       .insert = _insert,
+                       .verify = _verify,
+                       .destroy = _destroy,
+               },
+               .request_id = request_id,
+               .list = linked_list_create(),
+       );
+
+       if (is_dir)
+       {
+               enumerator_t *enumerator;
+               char *rel_name, *abs_name;
+               struct stat st;
+
+               enumerator = enumerator_create_directory(pathname);
+               if (!enumerator)
+               {
+                       DBG1(DBG_PTS, "  directory '%s' can not be opened, %s", pathname,
+                                strerror(errno));
+                       success = FALSE;
+                       goto end;
+               }
+               while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
+               {
+                       /* measure regular files only */
+                       if (S_ISREG(st.st_mode) && *rel_name != '.')
+                       {
+                               if (!hash_file(hasher, abs_name, hash))
+                               {
+                                       success = FALSE;
+                                       break;
+                               }
+                               filename = use_rel_name ? rel_name : abs_name;
+                               DBG2(DBG_PTS, "  %#B for '%s'", &measurement, filename);
+                               add(this, filename, measurement);
+                       }
+               }
+               enumerator->destroy(enumerator);
+       }
+       else
+       {
+               if (!hash_file(hasher, pathname, hash))
+               {
+                       success = FALSE;
+                       goto end;
+               }
+               filename = use_rel_name ? basename(pathname) : pathname;
+               DBG2(DBG_PTS, "  %#B for '%s'", &measurement, filename);
+               add(this, filename, measurement);
+       }
+
+end:
+       hasher->destroy(hasher);
+       if (success)
+       {
+               return &this->public;
+       }
+       else
+       {
+               destroy(this);
+               return NULL;
+       }
+}
index 9b197e7..817cb54 100644 (file)
@@ -93,4 +93,17 @@ struct pts_file_meas_t {
  */
 pts_file_meas_t* pts_file_meas_create(u_int16_t request_id);
 
+/**
+ * Creates a pts_file_meas_t object measuring a file/directory
+ *
+ * @param request_id           ID of PTS File Measurement Request
+ * @param pathname                     Absolute file or directory pathname
+ * @param is_dir                       TRUE if directory path
+ * @param use_rel_name         TRUE if relative filenames are to be used
+ * @param alg                          PTS hash measurement algorithm to be used
+ */
+pts_file_meas_t* pts_file_meas_create_from_path(u_int16_t request_id,
+                                                       char* pathname, bool is_dir, bool use_rel_name,
+                                                       pts_meas_algorithms_t alg);
+
 #endif /** PTS_FILE_MEAS_H_ @}*/