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 */
{ "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' },
exit(EXIT_FAILURE);
}
continue;
+ case 'I':
+ attest->set_ima(attest);
+ continue;
case 'K':
{
chunk_t aik;
exit(EXIT_FAILURE);
}
continue;
+ case 'R':
+ attest->set_relative(attest);
+ continue;
case '1':
attest->set_algo(attest, PTS_MEAS_ALGO_SHA1);
continue;
#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;
/**
*/
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
*/
private_attest_db_t *this, char *dir, bool create)
{
enumerator_t *e;
+ size_t len;
if (this->dir_set)
{
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,
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)
{
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++;
}
{
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);
{
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);
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++;
}
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);
{
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++;
}
{
while (e->enumerate(e, &pid, &product))
{
- printf("%3d: %s\n", pid, product);
+ printf("%4d: %s\n", pid, product);
count++;
}
e->destroy(e);
{
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);
{
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);
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);
{
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);
{
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);
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;
}
{
bool success = FALSE;
+ /* add key/component pair */
if (this->kid && this->cid)
{
success = this->db->execute(this->db, NULL,
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;
}
.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,
*/
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
*
INSERT INTO files (
type, path
) VALUES (
- 1, '/lib/xtables/'
+ 1, '/lib/xtables'
);
INSERT INTO files (
#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
*/
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)
{
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
*/
metadata->destroy(metadata);
return NULL;
}
- entry->filename = strdup(get_filename(pathname));
+ entry->filename = strdup(basename(pathname));
metadata->add(metadata, entry);
}
.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,
*/
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
#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;
/**
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;
+ }
+}
*/
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_ @}*/