ipsec attest now can measure all files in a directory
This commit is contained in:
@@ -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'",
|
DBG2(DBG_IMC, "measurement request %d for %s '%s'",
|
||||||
request_id, is_directory ? "directory" : "file",
|
request_id, is_directory ? "directory" : "file",
|
||||||
pathname);
|
pathname);
|
||||||
measurements = pts->do_measurements(pts, request_id,
|
measurements = pts_file_meas_create_from_path(request_id,
|
||||||
pathname, is_directory);
|
pathname, is_directory, TRUE,
|
||||||
|
pts->get_meas_algorithm(pts));
|
||||||
if (!measurements)
|
if (!measurements)
|
||||||
{
|
{
|
||||||
/* TODO handle error codes from measurements */
|
/* TODO handle error codes from measurements */
|
||||||
|
|||||||
@@ -131,9 +131,11 @@ static void do_args(int argc, char *argv[])
|
|||||||
{ "directory", required_argument, NULL, 'D' },
|
{ "directory", required_argument, NULL, 'D' },
|
||||||
{ "dir", required_argument, NULL, 'D' },
|
{ "dir", required_argument, NULL, 'D' },
|
||||||
{ "file", required_argument, NULL, 'F' },
|
{ "file", required_argument, NULL, 'F' },
|
||||||
|
{ "ima", no_argument, NULL, 'I' },
|
||||||
{ "key", required_argument, NULL, 'K' },
|
{ "key", required_argument, NULL, 'K' },
|
||||||
{ "owner", required_argument, NULL, 'O' },
|
{ "owner", required_argument, NULL, 'O' },
|
||||||
{ "product", required_argument, NULL, 'P' },
|
{ "product", required_argument, NULL, 'P' },
|
||||||
|
{ "relative", no_argument, NULL, 'R' },
|
||||||
{ "sha1", no_argument, NULL, '1' },
|
{ "sha1", no_argument, NULL, '1' },
|
||||||
{ "sha256", no_argument, NULL, '2' },
|
{ "sha256", no_argument, NULL, '2' },
|
||||||
{ "sha384", no_argument, NULL, '3' },
|
{ "sha384", no_argument, NULL, '3' },
|
||||||
@@ -232,6 +234,9 @@ static void do_args(int argc, char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
case 'I':
|
||||||
|
attest->set_ima(attest);
|
||||||
|
continue;
|
||||||
case 'K':
|
case 'K':
|
||||||
{
|
{
|
||||||
chunk_t aik;
|
chunk_t aik;
|
||||||
@@ -252,6 +257,9 @@ static void do_args(int argc, char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
case 'R':
|
||||||
|
attest->set_relative(attest);
|
||||||
|
continue;
|
||||||
case '1':
|
case '1':
|
||||||
attest->set_algo(attest, PTS_MEAS_ALGO_SHA1);
|
attest->set_algo(attest, PTS_MEAS_ALGO_SHA1);
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -16,8 +16,11 @@
|
|||||||
#include "attest_db.h"
|
#include "attest_db.h"
|
||||||
|
|
||||||
#include "libpts.h"
|
#include "libpts.h"
|
||||||
|
#include "pts/pts_file_meas.h"
|
||||||
#include "pts/components/pts_comp_func_name.h"
|
#include "pts/components/pts_comp_func_name.h"
|
||||||
|
|
||||||
|
#include <libgen.h>
|
||||||
|
|
||||||
typedef struct private_attest_db_t private_attest_db_t;
|
typedef struct private_attest_db_t private_attest_db_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,6 +108,16 @@ struct private_attest_db_t {
|
|||||||
*/
|
*/
|
||||||
bool product_set;
|
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
|
* File measurement hash algorithm
|
||||||
*/
|
*/
|
||||||
@@ -252,6 +265,7 @@ METHOD(attest_db_t, set_directory, bool,
|
|||||||
private_attest_db_t *this, char *dir, bool create)
|
private_attest_db_t *this, char *dir, bool create)
|
||||||
{
|
{
|
||||||
enumerator_t *e;
|
enumerator_t *e;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
if (this->dir_set)
|
if (this->dir_set)
|
||||||
{
|
{
|
||||||
@@ -259,6 +273,13 @@ METHOD(attest_db_t, set_directory, bool,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
free(this->dir);
|
free(this->dir);
|
||||||
|
|
||||||
|
/* remove trailing '/' character */
|
||||||
|
len = strlen(dir);
|
||||||
|
if (len && dir[len-1] == '/')
|
||||||
|
{
|
||||||
|
dir[len-1] = '\0';
|
||||||
|
}
|
||||||
this->dir = strdup(dir);
|
this->dir = strdup(dir);
|
||||||
|
|
||||||
e = this->db->query(this->db,
|
e = this->db->query(this->db,
|
||||||
@@ -568,6 +589,18 @@ METHOD(attest_db_t, set_algo, void,
|
|||||||
this->algo = algo;
|
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,
|
METHOD(attest_db_t, set_owner, void,
|
||||||
private_attest_db_t *this, char *owner)
|
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))
|
while (e->enumerate(e, &cid, &vid, &name, &qualifier))
|
||||||
{
|
{
|
||||||
cfn = pts_comp_func_name_create(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);
|
cfn->destroy(cfn);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@@ -637,7 +670,7 @@ METHOD(attest_db_t, list_keys, void,
|
|||||||
{
|
{
|
||||||
while (e->enumerate(e, &kid, &keyid, &owner))
|
while (e->enumerate(e, &kid, &keyid, &owner))
|
||||||
{
|
{
|
||||||
printf("%3d: %#B '%s'\n", kid, &keyid, owner);
|
printf("%4d: %#B '%s'\n", kid, &keyid, owner);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
e->destroy(e);
|
e->destroy(e);
|
||||||
@@ -652,7 +685,7 @@ METHOD(attest_db_t, list_keys, void,
|
|||||||
{
|
{
|
||||||
while (e->enumerate(e, &kid, &keyid, &owner))
|
while (e->enumerate(e, &kid, &keyid, &owner))
|
||||||
{
|
{
|
||||||
printf("%3d: %#B '%s'\n", kid, &keyid, owner);
|
printf("%4d: %#B '%s'\n", kid, &keyid, owner);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
e->destroy(e);
|
e->destroy(e);
|
||||||
@@ -687,7 +720,7 @@ METHOD(attest_db_t, list_files, void,
|
|||||||
while (e->enumerate(e, &fid, &type, &file, &meas, &meta))
|
while (e->enumerate(e, &fid, &type, &file, &meas, &meta))
|
||||||
{
|
{
|
||||||
type = (type < 0 || type > 2) ? 0 : type;
|
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);
|
file_type[type], file);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@@ -705,7 +738,7 @@ METHOD(attest_db_t, list_files, void,
|
|||||||
while (e->enumerate(e, &fid, &type, &file))
|
while (e->enumerate(e, &fid, &type, &file))
|
||||||
{
|
{
|
||||||
type = (type < 0 || type > 2) ? 0 : type;
|
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++;
|
count++;
|
||||||
}
|
}
|
||||||
e->destroy(e);
|
e->destroy(e);
|
||||||
@@ -739,7 +772,7 @@ METHOD(attest_db_t, list_products, void,
|
|||||||
{
|
{
|
||||||
while (e->enumerate(e, &pid, &product, &meas, &meta))
|
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);
|
product);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@@ -755,7 +788,7 @@ METHOD(attest_db_t, list_products, void,
|
|||||||
{
|
{
|
||||||
while (e->enumerate(e, &pid, &product))
|
while (e->enumerate(e, &pid, &product))
|
||||||
{
|
{
|
||||||
printf("%3d: %s\n", pid, product);
|
printf("%4d: %s\n", pid, product);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
e->destroy(e);
|
e->destroy(e);
|
||||||
@@ -826,11 +859,11 @@ METHOD(attest_db_t, list_hashes, void,
|
|||||||
{
|
{
|
||||||
if (this->fid != fid_old)
|
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);
|
slash(this->dir, this->file) ? "/" : "", this->file);
|
||||||
fid_old = this->fid;
|
fid_old = this->fid;
|
||||||
}
|
}
|
||||||
printf(" %#B\n", &hash);
|
printf(" %#B\n", &hash);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
e->destroy(e);
|
e->destroy(e);
|
||||||
@@ -860,12 +893,12 @@ METHOD(attest_db_t, list_hashes, void,
|
|||||||
{
|
{
|
||||||
get_directory(this, did, &dir);
|
get_directory(this, did, &dir);
|
||||||
}
|
}
|
||||||
printf("%3d: %s%s%s\n", fid,
|
printf("%4d: %s%s%s\n", fid,
|
||||||
dir, slash(dir, file) ? "/" : "", file);
|
dir, slash(dir, file) ? "/" : "", file);
|
||||||
fid_old = fid;
|
fid_old = fid;
|
||||||
did_old = did;
|
did_old = did;
|
||||||
}
|
}
|
||||||
printf(" %#B\n", &hash);
|
printf(" %#B\n", &hash);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
e->destroy(e);
|
e->destroy(e);
|
||||||
@@ -922,11 +955,11 @@ METHOD(attest_db_t, list_hashes, void,
|
|||||||
get_directory(this, did, &dir);
|
get_directory(this, did, &dir);
|
||||||
did_old = did;
|
did_old = did;
|
||||||
}
|
}
|
||||||
printf("%3d: %s%s%s\n", fid,
|
printf("%4d: %s%s%s\n", fid,
|
||||||
dir, slash(dir, file) ? "/" : "", file);
|
dir, slash(dir, file) ? "/" : "", file);
|
||||||
fid_old = fid;
|
fid_old = fid;
|
||||||
}
|
}
|
||||||
printf(" %#B '%s'\n", &hash, product);
|
printf(" %#B '%s'\n", &hash, product);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
e->destroy(e);
|
e->destroy(e);
|
||||||
@@ -964,7 +997,7 @@ METHOD(attest_db_t, list_measurements, void,
|
|||||||
{
|
{
|
||||||
if (this->kid != kid_old)
|
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;
|
kid_old = this->kid;
|
||||||
}
|
}
|
||||||
printf("%5d %02d %#B\n", seq_no, pcr, &hash);
|
printf("%5d %02d %#B\n", seq_no, pcr, &hash);
|
||||||
@@ -993,7 +1026,7 @@ METHOD(attest_db_t, list_measurements, void,
|
|||||||
{
|
{
|
||||||
if (kid != kid_old)
|
if (kid != kid_old)
|
||||||
{
|
{
|
||||||
printf("%3d: %#B '%s'\n", kid, &keyid, owner);
|
printf("%4d: %#B '%s'\n", kid, &keyid, owner);
|
||||||
kid_old = kid;
|
kid_old = kid;
|
||||||
}
|
}
|
||||||
printf("%5d %02d %#B\n", seq_no, pcr, &hash);
|
printf("%5d %02d %#B\n", seq_no, pcr, &hash);
|
||||||
@@ -1026,7 +1059,7 @@ METHOD(attest_db_t, list_measurements, void,
|
|||||||
if (cid != cid_old)
|
if (cid != cid_old)
|
||||||
{
|
{
|
||||||
cfn = pts_comp_func_name_create(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);
|
cfn->destroy(cfn);
|
||||||
cid_old = cid;
|
cid_old = cid;
|
||||||
}
|
}
|
||||||
@@ -1047,6 +1080,7 @@ METHOD(attest_db_t, add, bool,
|
|||||||
{
|
{
|
||||||
bool success = FALSE;
|
bool success = FALSE;
|
||||||
|
|
||||||
|
/* add key/component pair */
|
||||||
if (this->kid && this->cid)
|
if (this->kid && this->cid)
|
||||||
{
|
{
|
||||||
success = this->db->execute(this->db, NULL,
|
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",
|
printf("key/component pair (%d/%d) %sinserted into database\n",
|
||||||
this->kid, this->cid, success ? "" : "could not be ");
|
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;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1173,6 +1305,8 @@ attest_db_t *attest_db_create(char *uri)
|
|||||||
.set_product = _set_product,
|
.set_product = _set_product,
|
||||||
.set_pid = _set_pid,
|
.set_pid = _set_pid,
|
||||||
.set_algo = _set_algo,
|
.set_algo = _set_algo,
|
||||||
|
.set_ima = _set_ima,
|
||||||
|
.set_relative = _set_relative,
|
||||||
.set_owner = _set_owner,
|
.set_owner = _set_owner,
|
||||||
.list_products = _list_products,
|
.list_products = _list_products,
|
||||||
.list_files = _list_files,
|
.list_files = _list_files,
|
||||||
|
|||||||
@@ -125,6 +125,16 @@ struct attest_db_t {
|
|||||||
*/
|
*/
|
||||||
void (*set_algo)(attest_db_t *this, pts_meas_algorithms_t algo);
|
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
|
* Set owner [user/host] of an AIK
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ INSERT INTO files (
|
|||||||
INSERT INTO files (
|
INSERT INTO files (
|
||||||
type, path
|
type, path
|
||||||
) VALUES (
|
) VALUES (
|
||||||
1, '/lib/xtables/'
|
1, '/lib/xtables'
|
||||||
);
|
);
|
||||||
|
|
||||||
INSERT INTO files (
|
INSERT INTO files (
|
||||||
|
|||||||
+4
-129
@@ -23,12 +23,13 @@
|
|||||||
#include <trousers/tss.h>
|
#include <trousers/tss.h>
|
||||||
#include <trousers/trousers.h>
|
#include <trousers/trousers.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#define PTS_BUF_SIZE 4096
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum number of PCR's of TPM, TPM Spec 1.2
|
* Maximum number of PCR's of TPM, TPM Spec 1.2
|
||||||
*/
|
*/
|
||||||
@@ -486,54 +487,6 @@ METHOD(pts_t, get_aik_keyid, bool,
|
|||||||
return success;
|
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,
|
METHOD(pts_t, is_path_valid, bool,
|
||||||
private_pts_t *this, char *path, pts_error_code_t *error_code)
|
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;
|
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
|
* Obtain statistical information describing a file
|
||||||
*/
|
*/
|
||||||
@@ -748,7 +625,7 @@ METHOD(pts_t, get_metadata, pts_file_meta_t*,
|
|||||||
metadata->destroy(metadata);
|
metadata->destroy(metadata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
entry->filename = strdup(get_filename(pathname));
|
entry->filename = strdup(basename(pathname));
|
||||||
metadata->add(metadata, entry);
|
metadata->add(metadata, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1499,8 +1376,6 @@ pts_t *pts_create(bool is_imc)
|
|||||||
.set_aik = _set_aik,
|
.set_aik = _set_aik,
|
||||||
.get_aik_keyid = _get_aik_keyid,
|
.get_aik_keyid = _get_aik_keyid,
|
||||||
.is_path_valid = _is_path_valid,
|
.is_path_valid = _is_path_valid,
|
||||||
.hash_file = _hash_file,
|
|
||||||
.do_measurements = _do_measurements,
|
|
||||||
.get_metadata = _get_metadata,
|
.get_metadata = _get_metadata,
|
||||||
.read_pcr = _read_pcr,
|
.read_pcr = _read_pcr,
|
||||||
.extend_pcr = _extend_pcr,
|
.extend_pcr = _extend_pcr,
|
||||||
|
|||||||
+2
-23
@@ -229,35 +229,14 @@ struct pts_t {
|
|||||||
*/
|
*/
|
||||||
bool (*is_path_valid)(pts_t *this, char *path, pts_error_code_t *error_code);
|
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
|
* Obtain file metadata
|
||||||
*
|
*
|
||||||
* @param pathname Absolute pathname of file/directory
|
* @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
|
* @return PTS File Metadata or NULL if FAILED
|
||||||
*/
|
*/
|
||||||
pts_file_meta_t* (*get_metadata)(pts_t *this, char *pathname,
|
pts_file_meta_t* (*get_metadata)(pts_t *this, char *pathname, bool is_dir);
|
||||||
bool is_directory);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads given PCR value and returns it
|
* Reads given PCR value and returns it
|
||||||
|
|||||||
@@ -18,6 +18,10 @@
|
|||||||
#include <utils/linked_list.h>
|
#include <utils/linked_list.h>
|
||||||
#include <debug.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;
|
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;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -93,4 +93,17 @@ struct pts_file_meas_t {
|
|||||||
*/
|
*/
|
||||||
pts_file_meas_t* pts_file_meas_create(u_int16_t request_id);
|
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_ @}*/
|
#endif /** PTS_FILE_MEAS_H_ @}*/
|
||||||
|
|||||||
Reference in New Issue
Block a user