refactored attest database tool
This commit is contained in:
parent
e4ac6698bd
commit
e881ee23ee
|
@ -22,7 +22,10 @@ imv_attestation_la_SOURCES = imv_attestation.c \
|
|||
imv_attestation_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
ipsec_PROGRAMS = attest
|
||||
attest_SOURCES = attest.c attest_usage.h attest_usage.c
|
||||
attest_SOURCES = attest.c \
|
||||
attest_usage.h attest_usage.c \
|
||||
attest_db.h attest_db.c \
|
||||
tables.sql data.sql
|
||||
attest_LDADD = \
|
||||
$(top_builddir)/src/libpts/libpts.la \
|
||||
$(top_builddir)/src/libimcv/libimcv.la \
|
||||
|
|
|
@ -20,390 +20,28 @@
|
|||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <debug.h>
|
||||
#include <library.h>
|
||||
|
||||
#include <pts/pts_meas_algo.h>
|
||||
|
||||
#include "attest_db.h"
|
||||
#include "attest_usage.h"
|
||||
|
||||
/**
|
||||
* global database handle
|
||||
* global attestation database object
|
||||
*/
|
||||
database_t *db;
|
||||
|
||||
/**
|
||||
* forward declarations
|
||||
*/
|
||||
static void do_args(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* ipsec attest --files - show files
|
||||
*/
|
||||
static void list_files(char *product, int pid)
|
||||
{
|
||||
enumerator_t *e;
|
||||
char *file;
|
||||
bool select = TRUE;
|
||||
int fid, is_dir, count = 0;
|
||||
|
||||
if (pid)
|
||||
{
|
||||
e = db->query(db,
|
||||
"SELECT f.id, f.type, f.path FROM files AS f "
|
||||
"JOIN product_file AS pf ON f.id = pf.file "
|
||||
"JOIN products AS p ON p.id = pf.product "
|
||||
"WHERE p.id = ? ORDER BY f.path",
|
||||
DB_INT, pid, DB_INT, DB_INT, DB_TEXT);
|
||||
}
|
||||
else if (!product || *product == '\0')
|
||||
{
|
||||
select = FALSE;
|
||||
e = db->query(db,
|
||||
"SELECT id, type, path FROM files "
|
||||
"ORDER BY path",
|
||||
DB_INT, DB_INT, DB_TEXT);
|
||||
}
|
||||
else
|
||||
{
|
||||
e = db->query(db,
|
||||
"SELECT f.id, f.type, f.path FROM files AS f "
|
||||
"JOIN product_file AS pf ON f.id = pf.file "
|
||||
"JOIN products AS p ON p.id = pf.product "
|
||||
"WHERE p.name = ? ORDER BY f.path",
|
||||
DB_TEXT, product, DB_INT, DB_INT, DB_TEXT);
|
||||
}
|
||||
if (e)
|
||||
{
|
||||
while (e->enumerate(e, &fid, &is_dir, &file))
|
||||
{
|
||||
printf("%3d: %s %s\n", fid, is_dir ? "d":" ", file);
|
||||
count++;
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
printf("%d file%s found", count, (count == 1) ? "" : "s");
|
||||
if (select)
|
||||
{
|
||||
printf(" for product '%s'", product);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ipsec attest --products - show products
|
||||
*/
|
||||
static void list_products(char *file, int fid)
|
||||
{
|
||||
enumerator_t *e;
|
||||
char *product;
|
||||
bool select = TRUE;
|
||||
int pid, count = 0;
|
||||
|
||||
if (fid)
|
||||
{
|
||||
e = db->query(db,
|
||||
"SELECT p.id, p.name FROM products AS p "
|
||||
"JOIN product_file AS pf ON p.id = pf.product "
|
||||
"JOIN files AS f ON f.id = pf.file "
|
||||
"WHERE f.id = ? ORDER BY p.name",
|
||||
DB_INT, fid, DB_INT, DB_TEXT);
|
||||
}
|
||||
else if (!file || *file == '\0')
|
||||
{
|
||||
select = FALSE;
|
||||
e = db->query(db, "SELECT id, name FROM products "
|
||||
"ORDER BY name",
|
||||
DB_INT, DB_TEXT);
|
||||
}
|
||||
else
|
||||
{
|
||||
e = db->query(db,
|
||||
"SELECT p.id, p.name FROM products AS p "
|
||||
"JOIN product_file AS pf ON p.id = pf.product "
|
||||
"JOIN files AS f ON f.id = pf.file "
|
||||
"WHERE f.path = ? ORDER BY p.name",
|
||||
DB_TEXT, file, DB_INT, DB_TEXT);
|
||||
}
|
||||
if (e)
|
||||
{
|
||||
while (e->enumerate(e, &pid, &product))
|
||||
{
|
||||
printf("%3d: %s\n", pid, product);
|
||||
count++;
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
printf("%d product%s found", count, (count == 1) ? "" : "s");
|
||||
if (select)
|
||||
{
|
||||
printf(" for file '%s'", file);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the directory if there is one from the files tables
|
||||
*/
|
||||
static void get_directory(int did, char **directory)
|
||||
{
|
||||
enumerator_t *e;
|
||||
char *dir;
|
||||
|
||||
free(*directory);
|
||||
*directory = strdup("");
|
||||
|
||||
if (did)
|
||||
{
|
||||
e = db->query(db, "SELECT path from files WHERE id = ?",
|
||||
DB_INT, did, DB_TEXT);
|
||||
if (e)
|
||||
{
|
||||
if (e->enumerate(e, &dir))
|
||||
{
|
||||
free(*directory);
|
||||
*directory = strdup(dir);
|
||||
}
|
||||
e->destroy(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool slash(char *directory, char *file)
|
||||
{
|
||||
return *file != '/' && directory[max(0, strlen(directory)-1)] != '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* ipsec attest --hashes - show all file measurement hashes
|
||||
*/
|
||||
static void list_hashes(pts_meas_algorithms_t algo)
|
||||
{
|
||||
enumerator_t *e;
|
||||
chunk_t hash;
|
||||
char *file, *dir, *product;
|
||||
int fid, fid_old = 0, did, did_old = 0, count = 0;
|
||||
|
||||
dir = strdup("");
|
||||
|
||||
e = db->query(db,
|
||||
"SELECT f.id, f.path, p.name, fh.hash, fh.directory "
|
||||
"FROM file_hashes AS fh "
|
||||
"JOIN files AS f ON f.id = fh.file "
|
||||
"JOIN products AS p ON p.id = fh.product "
|
||||
"WHERE fh.algo = ? "
|
||||
"ORDER BY fh.directory, f.path, p.name",
|
||||
DB_INT, algo, DB_INT, DB_TEXT, DB_TEXT, DB_BLOB, DB_INT);
|
||||
if (e)
|
||||
{
|
||||
while (e->enumerate(e, &fid, &file, &product, &hash, &did))
|
||||
{
|
||||
if (fid != fid_old || did != did_old)
|
||||
{
|
||||
if (did != did_old)
|
||||
{
|
||||
get_directory(did, &dir);
|
||||
did_old = did;
|
||||
}
|
||||
printf("%3d: %s%s%s\n", fid,
|
||||
dir, slash(dir, file) ? "/" : "", file);
|
||||
fid_old = fid;
|
||||
}
|
||||
printf(" %#B '%s'\n", &hash, product);
|
||||
count++;
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
printf("%d %N value%s found\n", count, hash_algorithm_names,
|
||||
pts_meas_algo_to_hash(algo), (count == 1) ? "" : "s");
|
||||
free(dir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ipsec attest --hashes - show file measurement hashes for a given file
|
||||
*/
|
||||
static void list_hashes_for_file(pts_meas_algorithms_t algo, char *file, int fid)
|
||||
{
|
||||
enumerator_t *e;
|
||||
chunk_t hash;
|
||||
char *product, *dir;
|
||||
int did, count = 0;
|
||||
|
||||
dir = strdup("");
|
||||
|
||||
if (fid)
|
||||
{
|
||||
e = db->query(db,
|
||||
"SELECT p.name, fh.hash, fh.directory "
|
||||
"FROM file_hashes AS fh "
|
||||
"JOIN files AS f ON f.id = fh.file "
|
||||
"JOIN products AS p ON p.id = fh.product "
|
||||
"WHERE fh.algo = ? AND f.id = ? "
|
||||
"ORDER BY p.name",
|
||||
DB_INT, algo, DB_INT, fid, DB_TEXT, DB_BLOB, DB_INT);
|
||||
}
|
||||
else
|
||||
{
|
||||
e = db->query(db,
|
||||
"SELECT p.name, fh.hash, fh.directory "
|
||||
"FROM file_hashes AS fh "
|
||||
"JOIN files AS f ON f.id = fh.file "
|
||||
"JOIN products AS p ON p.id = fh.product "
|
||||
"WHERE fh.algo = ? AND f.path = ? "
|
||||
"ORDER BY p.name",
|
||||
DB_INT, algo, DB_TEXT, file, DB_TEXT, DB_BLOB, DB_INT);
|
||||
}
|
||||
if (e)
|
||||
{
|
||||
while (e->enumerate(e, &product, &hash, &did))
|
||||
{
|
||||
printf("%#B '%s'\n", &hash, product);
|
||||
count++;
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
get_directory(did, &dir);
|
||||
printf("%d %N value%s found for file '%s%s%s'\n",
|
||||
count, hash_algorithm_names, pts_meas_algo_to_hash(algo),
|
||||
(count == 1) ? "" : "s",
|
||||
dir, slash(dir, file) ? "/" : "", file);
|
||||
free(dir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ipsec attest --hashes - show file measurement hashes for a given product
|
||||
*/
|
||||
static void list_hashes_for_product(pts_meas_algorithms_t algo,
|
||||
char *product, int pid)
|
||||
{
|
||||
enumerator_t *e;
|
||||
chunk_t hash;
|
||||
char *file, *dir;
|
||||
int fid, fid_old = 0, did, did_old = 0, count = 0;
|
||||
|
||||
dir = strdup("");
|
||||
|
||||
if (pid)
|
||||
{
|
||||
e = db->query(db,
|
||||
"SELECT f.id, f. f.path, fh.hash, fh.directory "
|
||||
"FROM file_hashes AS fh "
|
||||
"JOIN files AS f ON f.id = fh.file "
|
||||
"JOIN products AS p ON p.id = fh.product "
|
||||
"WHERE fh.algo = ? AND p.id = ? "
|
||||
"ORDER BY fh.directory, f.path",
|
||||
DB_INT, algo, DB_INT, pid, DB_INT, DB_TEXT, DB_BLOB, DB_INT);
|
||||
}
|
||||
else
|
||||
{
|
||||
e = db->query(db,
|
||||
"SELECT f.id, f.path, fh.hash, fh.directory "
|
||||
"FROM file_hashes AS fh "
|
||||
"JOIN files AS f ON f.id = fh.file "
|
||||
"JOIN products AS p ON p.id = fh.product "
|
||||
"WHERE fh.algo = ? AND p.name = ? "
|
||||
"ORDER BY fh.directory, f.path",
|
||||
DB_INT, algo, DB_TEXT, product, DB_INT, DB_TEXT, DB_BLOB, DB_INT);
|
||||
}
|
||||
if (e)
|
||||
{
|
||||
while (e->enumerate(e, &fid, &file, &hash, &did))
|
||||
{
|
||||
if (fid != fid_old || did != did_old)
|
||||
{
|
||||
if (did != did_old)
|
||||
{
|
||||
get_directory(did, &dir);
|
||||
}
|
||||
printf("%3d: %s%s%s\n", fid,
|
||||
dir, slash(dir, file) ? "/" : "", file);
|
||||
fid_old = fid;
|
||||
did_old = did;
|
||||
}
|
||||
printf(" %#B\n", &hash);
|
||||
count++;
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
printf("%d %N value%s found for product '%s'\n",
|
||||
count, hash_algorithm_names, pts_meas_algo_to_hash(algo),
|
||||
(count == 1) ? "" : "s", product);
|
||||
free(dir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* find file corresponding to primary key fid
|
||||
*/
|
||||
static bool fid_to_file(int fid, char **file)
|
||||
{
|
||||
enumerator_t *e;
|
||||
bool found = FALSE;
|
||||
char *f;
|
||||
|
||||
e = db->query(db, "SELECT path FROM files WHERE id = ?",
|
||||
DB_INT, fid, DB_TEXT);
|
||||
if (e)
|
||||
{
|
||||
if (e->enumerate(e, &f))
|
||||
{
|
||||
found = TRUE;
|
||||
*file = strdup(f);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("no file found with fid %d\n", fid);
|
||||
}
|
||||
e->destroy(e);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* find product corresponding to primary key pid
|
||||
*/
|
||||
static bool pid_to_product(int pid, char **product)
|
||||
{
|
||||
enumerator_t *e;
|
||||
bool found = FALSE;
|
||||
char *p;
|
||||
|
||||
e = db->query(db, "SELECT name FROM products WHERE id = ?",
|
||||
DB_INT, pid, DB_TEXT);
|
||||
if (e)
|
||||
{
|
||||
if (e->enumerate(e, &p))
|
||||
{
|
||||
found = TRUE;
|
||||
*product = strdup(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("no product found with pid %d\n", pid);
|
||||
}
|
||||
e->destroy(e);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
attest_db_t *attest;
|
||||
|
||||
/**
|
||||
* atexit handler to close db on shutdown
|
||||
*/
|
||||
static void cleanup(void)
|
||||
{
|
||||
db->destroy(db);
|
||||
attest->destroy(attest);
|
||||
}
|
||||
|
||||
static void do_args(int argc, char *argv[])
|
||||
{
|
||||
char *product = NULL, *file = NULL;
|
||||
int fid = 0, pid = 0;
|
||||
pts_meas_algorithms_t algo = PTS_MEAS_ALGO_SHA256;
|
||||
|
||||
enum {
|
||||
OP_UNDEF,
|
||||
OP_USAGE,
|
||||
|
@ -424,13 +62,15 @@ static void do_args(int argc, char *argv[])
|
|||
{ "files", no_argument, NULL, 'f' },
|
||||
{ "products", no_argument, NULL, 'p' },
|
||||
{ "hashes", no_argument, NULL, 'H' },
|
||||
{ "directory", required_argument, NULL, 'D' },
|
||||
{ "file", required_argument, NULL, 'F' },
|
||||
{ "product", required_argument, NULL, 'P' },
|
||||
{ "sha1", no_argument, NULL, '1' },
|
||||
{ "sha256", no_argument, NULL, '2' },
|
||||
{ "sha384", no_argument, NULL, '3' },
|
||||
{ "fid", required_argument, NULL, '4' },
|
||||
{ "pid", required_argument, NULL, '5' },
|
||||
{ "did", required_argument, NULL, '4' },
|
||||
{ "fid", required_argument, NULL, '5' },
|
||||
{ "pid", required_argument, NULL, '6' },
|
||||
{ 0,0,0,0 }
|
||||
};
|
||||
|
||||
|
@ -451,31 +91,47 @@ static void do_args(int argc, char *argv[])
|
|||
case 'H':
|
||||
operation = OP_HASHES;
|
||||
continue;
|
||||
case 'D':
|
||||
if (!attest->set_directory(attest, optarg))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
case 'F':
|
||||
file = optarg;
|
||||
if (!attest->set_file(attest, optarg))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
case 'P':
|
||||
product = optarg;
|
||||
if (!attest->set_product(attest, optarg))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
case '1':
|
||||
algo = PTS_MEAS_ALGO_SHA1;
|
||||
attest->set_algo(attest, PTS_MEAS_ALGO_SHA1);
|
||||
continue;
|
||||
case '2':
|
||||
algo = PTS_MEAS_ALGO_SHA256;
|
||||
attest->set_algo(attest, PTS_MEAS_ALGO_SHA256);
|
||||
continue;
|
||||
case '3':
|
||||
algo = PTS_MEAS_ALGO_SHA384;
|
||||
attest->set_algo(attest, PTS_MEAS_ALGO_SHA384);
|
||||
continue;
|
||||
case '4':
|
||||
fid = atoi(optarg);
|
||||
if (!fid_to_file(fid, &file))
|
||||
if (!attest->set_did(attest, atoi(optarg)))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
case '5':
|
||||
pid = atoi(optarg);
|
||||
if (!pid_to_product(pid, &product))
|
||||
if (!attest->set_fid(attest, atoi(optarg)))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
case '6':
|
||||
if (!attest->set_pid(attest, atoi(optarg)))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
@ -490,39 +146,18 @@ static void do_args(int argc, char *argv[])
|
|||
usage();
|
||||
break;
|
||||
case OP_PRODUCTS:
|
||||
list_products(file, fid);
|
||||
attest->list_products(attest);
|
||||
break;
|
||||
case OP_FILES:
|
||||
list_files(product, pid);
|
||||
attest->list_files(attest);
|
||||
break;
|
||||
case OP_HASHES:
|
||||
if ((!product || *product == '\0') && (!file || *file == '\0'))
|
||||
{
|
||||
list_hashes(algo);
|
||||
}
|
||||
else if (product)
|
||||
{
|
||||
list_hashes_for_product(algo, product, pid);
|
||||
}
|
||||
else
|
||||
{
|
||||
list_hashes_for_file(algo, file, fid);
|
||||
}
|
||||
attest->list_hashes(attest);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (fid)
|
||||
{
|
||||
free(file);
|
||||
}
|
||||
if (pid)
|
||||
{
|
||||
free(product);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -548,10 +183,9 @@ int main(int argc, char *argv[])
|
|||
fprintf(stderr, "database URI attest.database not set.\n");
|
||||
exit(SS_RC_INITIALIZATION_FAILED);
|
||||
}
|
||||
db = lib->db->create(lib->db, uri);
|
||||
if (!db)
|
||||
attest = attest_db_create(uri);
|
||||
if (!attest)
|
||||
{
|
||||
fprintf(stderr, "opening database failed.\n");
|
||||
exit(SS_RC_INITIALIZATION_FAILED);
|
||||
}
|
||||
atexit(cleanup);
|
||||
|
|
|
@ -0,0 +1,544 @@
|
|||
/*
|
||||
* Copyright (C) 2011 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "attest_db.h"
|
||||
|
||||
typedef struct private_attest_db_t private_attest_db_t;
|
||||
|
||||
/**
|
||||
* Private data of an attest_db_t object.
|
||||
*/
|
||||
struct private_attest_db_t {
|
||||
|
||||
/**
|
||||
* Public members of attest_db_state_t
|
||||
*/
|
||||
attest_db_t public;
|
||||
|
||||
/**
|
||||
* Software product to be queried
|
||||
*/
|
||||
char *product;
|
||||
|
||||
/**
|
||||
* Primary key of software product to be queried
|
||||
*/
|
||||
int pid;
|
||||
|
||||
/**
|
||||
* TRUE if product has been set
|
||||
*/
|
||||
bool product_set;
|
||||
|
||||
/**
|
||||
* Measurement file to be queried
|
||||
*/
|
||||
char *file;
|
||||
|
||||
/**
|
||||
* Primary key of measurement file to be queried
|
||||
*/
|
||||
int fid;
|
||||
|
||||
/**
|
||||
* TRUE if file has been set
|
||||
*/
|
||||
bool file_set;
|
||||
|
||||
/**
|
||||
* Directory containing the Measurement file to be queried
|
||||
*/
|
||||
char *dir;
|
||||
|
||||
/**
|
||||
* Primary key of the directory to be queried
|
||||
*/
|
||||
int did;
|
||||
|
||||
/**
|
||||
* TRUE if directory has been set
|
||||
*/
|
||||
bool dir_set;
|
||||
|
||||
/**
|
||||
* File measurement hash algorithm
|
||||
*/
|
||||
pts_meas_algorithms_t algo;
|
||||
|
||||
/**
|
||||
* Attestation database
|
||||
*/
|
||||
database_t *db;
|
||||
|
||||
};
|
||||
|
||||
METHOD(attest_db_t, set_product, bool,
|
||||
private_attest_db_t *this, char *product)
|
||||
{
|
||||
enumerator_t *e;
|
||||
|
||||
if (this->product_set)
|
||||
{
|
||||
printf("product has already been set\n");
|
||||
return FALSE;
|
||||
}
|
||||
this->product = strdup(product);
|
||||
|
||||
e = this->db->query(this->db, "SELECT id FROM products WHERE name = ?",
|
||||
DB_TEXT, product, DB_INT);
|
||||
if (e)
|
||||
{
|
||||
if (e->enumerate(e, &this->pid))
|
||||
{
|
||||
this->product_set = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("product '%s' not found in database\n", product);
|
||||
}
|
||||
e->destroy(e);
|
||||
}
|
||||
return this->product_set;
|
||||
}
|
||||
|
||||
METHOD(attest_db_t, set_pid, bool,
|
||||
private_attest_db_t *this, int pid)
|
||||
{
|
||||
enumerator_t *e;
|
||||
char *product;
|
||||
|
||||
if (this->product_set)
|
||||
{
|
||||
printf("product has already been set\n");
|
||||
return FALSE;
|
||||
}
|
||||
this->pid = pid;
|
||||
|
||||
e = this->db->query(this->db, "SELECT name FROM products WHERE id = ?",
|
||||
DB_INT, pid, DB_TEXT);
|
||||
if (e)
|
||||
{
|
||||
if (e->enumerate(e, &product))
|
||||
{
|
||||
this->product = strdup(product);
|
||||
this->product_set = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("no product found with pid %d in database\n", pid);
|
||||
}
|
||||
e->destroy(e);
|
||||
}
|
||||
return this->product_set;
|
||||
}
|
||||
|
||||
METHOD(attest_db_t, set_file, bool,
|
||||
private_attest_db_t *this, char *file)
|
||||
{
|
||||
enumerator_t *e;
|
||||
|
||||
if (this->file_set)
|
||||
{
|
||||
printf("file has already been set\n");
|
||||
return FALSE;
|
||||
}
|
||||
this->file = strdup(file);
|
||||
|
||||
e = this->db->query(this->db, "SELECT id FROM file WHERE path = ?",
|
||||
DB_TEXT, file, DB_INT);
|
||||
if (e)
|
||||
{
|
||||
if (e->enumerate(e, &this->fid))
|
||||
{
|
||||
this->file_set = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("file '%s' not found in database\n", file);
|
||||
}
|
||||
e->destroy(e);
|
||||
}
|
||||
return this->file_set;
|
||||
}
|
||||
|
||||
METHOD(attest_db_t, set_fid, bool,
|
||||
private_attest_db_t *this, int fid)
|
||||
{
|
||||
enumerator_t *e;
|
||||
char *file;
|
||||
|
||||
if (this->product_set)
|
||||
{
|
||||
printf("file has already been set\n");
|
||||
return FALSE;
|
||||
}
|
||||
this->fid = fid;
|
||||
|
||||
e = this->db->query(this->db, "SELECT path FROM files WHERE id = ?",
|
||||
DB_INT, fid, DB_TEXT);
|
||||
if (e)
|
||||
{
|
||||
if (e->enumerate(e, &file))
|
||||
{
|
||||
this->file = strdup(file);
|
||||
this->file_set = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("no file found with fid %d\n", fid);
|
||||
}
|
||||
e->destroy(e);
|
||||
}
|
||||
return this->file_set;
|
||||
}
|
||||
|
||||
METHOD(attest_db_t, set_directory, bool,
|
||||
private_attest_db_t *this, char *dir)
|
||||
{
|
||||
enumerator_t *e;
|
||||
|
||||
if (this->dir_set)
|
||||
{
|
||||
printf("directory has already been set\n");
|
||||
return FALSE;
|
||||
}
|
||||
free(this->dir);
|
||||
this->dir = strdup(dir);
|
||||
|
||||
e = this->db->query(this->db, "SELECT id FROM file WHERE path = ?",
|
||||
DB_TEXT, dir, DB_INT);
|
||||
if (e)
|
||||
{
|
||||
if (e->enumerate(e, &this->did))
|
||||
{
|
||||
this->dir_set = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("directory '%s' not found in database\n", dir);
|
||||
}
|
||||
e->destroy(e);
|
||||
}
|
||||
return this->dir_set;
|
||||
}
|
||||
|
||||
METHOD(attest_db_t, set_did, bool,
|
||||
private_attest_db_t *this, int did)
|
||||
{
|
||||
enumerator_t *e;
|
||||
char *dir;
|
||||
|
||||
if (this->dir_set)
|
||||
{
|
||||
printf("directory has already been set\n");
|
||||
return FALSE;
|
||||
}
|
||||
this->did = did;
|
||||
|
||||
e = this->db->query(this->db, "SELECT path FROM file WHERE id = ?",
|
||||
DB_INT, did, DB_TEXT);
|
||||
if (e)
|
||||
{
|
||||
if (e->enumerate(e, &dir))
|
||||
{
|
||||
free(this->dir);
|
||||
this->dir = strdup(dir);
|
||||
this->dir_set = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("no directory found with did %d\n", did);
|
||||
}
|
||||
e->destroy(e);
|
||||
}
|
||||
return this->dir_set;
|
||||
}
|
||||
|
||||
METHOD(attest_db_t, set_algo, void,
|
||||
private_attest_db_t *this, pts_meas_algorithms_t algo)
|
||||
{
|
||||
this->algo = algo;
|
||||
}
|
||||
|
||||
METHOD(attest_db_t, list_files, void,
|
||||
private_attest_db_t *this)
|
||||
{
|
||||
enumerator_t *e;
|
||||
char *file;
|
||||
int fid, is_dir, count = 0;
|
||||
|
||||
if (this->pid)
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT f.id, f.type, f.path FROM files AS f "
|
||||
"JOIN product_file AS pf ON f.id = pf.file "
|
||||
"JOIN products AS p ON p.id = pf.product "
|
||||
"WHERE p.id = ? ORDER BY f.path",
|
||||
DB_INT, this->pid, DB_INT, DB_INT, DB_TEXT);
|
||||
}
|
||||
else
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT id, type, path FROM files "
|
||||
"ORDER BY path",
|
||||
DB_INT, DB_INT, DB_TEXT);
|
||||
}
|
||||
if (e)
|
||||
{
|
||||
while (e->enumerate(e, &fid, &is_dir, &file))
|
||||
{
|
||||
printf("%3d: %s %s\n", fid, is_dir ? "d":" ", file);
|
||||
count++;
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
printf("%d file%s found", count, (count == 1) ? "" : "s");
|
||||
if (this->product)
|
||||
{
|
||||
printf(" for product '%s'", this->product);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(attest_db_t, list_products, void,
|
||||
private_attest_db_t *this)
|
||||
{
|
||||
enumerator_t *e;
|
||||
char *product;
|
||||
int pid, count = 0;
|
||||
|
||||
if (this->fid)
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT p.id, p.name FROM products AS p "
|
||||
"JOIN product_file AS pf ON p.id = pf.product "
|
||||
"JOIN files AS f ON f.id = pf.file "
|
||||
"WHERE f.id = ? ORDER BY p.name",
|
||||
DB_INT, this->fid, DB_INT, DB_TEXT);
|
||||
}
|
||||
else
|
||||
{
|
||||
e = this->db->query(this->db, "SELECT id, name FROM products "
|
||||
"ORDER BY name",
|
||||
DB_INT, DB_TEXT);
|
||||
}
|
||||
if (e)
|
||||
{
|
||||
while (e->enumerate(e, &pid, &product))
|
||||
{
|
||||
printf("%3d: %s\n", pid, product);
|
||||
count++;
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
printf("%d product%s found", count, (count == 1) ? "" : "s");
|
||||
if (this->file)
|
||||
{
|
||||
printf(" for file '%s'", this->file);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the directory if there is one from the files tables
|
||||
*/
|
||||
static void get_directory(private_attest_db_t *this, int did, char **directory)
|
||||
{
|
||||
enumerator_t *e;
|
||||
char *dir;
|
||||
|
||||
free(*directory);
|
||||
*directory = strdup("");
|
||||
|
||||
if (did)
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT path from files WHERE id = ?",
|
||||
DB_INT, did, DB_TEXT);
|
||||
if (e)
|
||||
{
|
||||
if (e->enumerate(e, &dir))
|
||||
{
|
||||
free(*directory);
|
||||
*directory = strdup(dir);
|
||||
}
|
||||
e->destroy(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool slash(char *directory, char *file)
|
||||
{
|
||||
return *file != '/' && directory[max(0, strlen(directory)-1)] != '/';
|
||||
}
|
||||
|
||||
METHOD(attest_db_t, list_hashes, void,
|
||||
private_attest_db_t *this)
|
||||
{
|
||||
enumerator_t *e;
|
||||
chunk_t hash;
|
||||
char *file, *dir, *product;
|
||||
int fid, fid_old = 0, did, did_old = 0, count = 0;
|
||||
|
||||
dir = strdup("");
|
||||
|
||||
if (this->pid)
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT f.id, f. f.path, fh.hash, fh.directory "
|
||||
"FROM file_hashes AS fh "
|
||||
"JOIN files AS f ON f.id = fh.file "
|
||||
"JOIN products AS p ON p.id = fh.product "
|
||||
"WHERE fh.algo = ? AND p.id = ? "
|
||||
"ORDER BY fh.directory, f.path",
|
||||
DB_INT, this->algo, DB_INT, this->pid,
|
||||
DB_INT, DB_TEXT, DB_BLOB, DB_INT);
|
||||
if (e)
|
||||
{
|
||||
while (e->enumerate(e, &fid, &file, &hash, &did))
|
||||
{
|
||||
if (fid != fid_old || did != did_old)
|
||||
{
|
||||
if (did != did_old)
|
||||
{
|
||||
get_directory(this, did, &dir);
|
||||
}
|
||||
printf("%3d: %s%s%s\n", fid,
|
||||
dir, slash(dir, file) ? "/" : "", file);
|
||||
fid_old = fid;
|
||||
did_old = did;
|
||||
}
|
||||
printf(" %#B\n", &hash);
|
||||
count++;
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
printf("%d %N value%s found for product '%s'\n", count,
|
||||
hash_algorithm_names, pts_meas_algo_to_hash(this->algo),
|
||||
(count == 1) ? "" : "s", this->product);
|
||||
}
|
||||
}
|
||||
else if (this->fid)
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT p.name, fh.hash, fh.directory "
|
||||
"FROM file_hashes AS fh "
|
||||
"JOIN files AS f ON f.id = fh.file "
|
||||
"JOIN products AS p ON p.id = fh.product "
|
||||
"WHERE fh.algo = ? AND f.id = ? "
|
||||
"ORDER BY p.name",
|
||||
DB_INT, this->algo, DB_INT, this->fid,
|
||||
DB_TEXT, DB_BLOB, DB_INT);
|
||||
if (e)
|
||||
{
|
||||
while (e->enumerate(e, &product, &hash, &did))
|
||||
{
|
||||
printf("%#B '%s'\n", &hash, product);
|
||||
count++;
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
get_directory(this, did, &dir);
|
||||
printf("%d %N value%s found for file '%s%s%s'\n",
|
||||
count, hash_algorithm_names, pts_meas_algo_to_hash(this->algo),
|
||||
(count == 1) ? "" : "s",
|
||||
dir, slash(dir, this->file) ? "/" : "", this->file);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT f.id, f.path, p.name, fh.hash, fh.directory "
|
||||
"FROM file_hashes AS fh "
|
||||
"JOIN files AS f ON f.id = fh.file "
|
||||
"JOIN products AS p ON p.id = fh.product "
|
||||
"WHERE fh.algo = ? "
|
||||
"ORDER BY fh.directory, f.path, p.name",
|
||||
DB_INT, this->algo,
|
||||
DB_INT, DB_TEXT, DB_TEXT, DB_BLOB, DB_INT);
|
||||
if (e)
|
||||
{
|
||||
while (e->enumerate(e, &fid, &file, &product, &hash, &did))
|
||||
{
|
||||
if (fid != fid_old || did != did_old)
|
||||
{
|
||||
if (did != did_old)
|
||||
{
|
||||
get_directory(this, did, &dir);
|
||||
did_old = did;
|
||||
}
|
||||
printf("%3d: %s%s%s\n", fid,
|
||||
dir, slash(dir, file) ? "/" : "", file);
|
||||
fid_old = fid;
|
||||
}
|
||||
printf(" %#B '%s'\n", &hash, product);
|
||||
count++;
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
printf("%d %N value%s found\n", count, hash_algorithm_names,
|
||||
pts_meas_algo_to_hash(this->algo), (count == 1) ? "" : "s");
|
||||
}
|
||||
}
|
||||
free(dir);
|
||||
}
|
||||
|
||||
METHOD(attest_db_t, destroy, void,
|
||||
private_attest_db_t *this)
|
||||
{
|
||||
DESTROY_IF(this->db);
|
||||
free(this->product);
|
||||
free(this->file);
|
||||
free(this->dir);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
attest_db_t *attest_db_create(char *uri)
|
||||
{
|
||||
private_attest_db_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.set_product = _set_product,
|
||||
.set_pid = _set_pid,
|
||||
.set_file = _set_file,
|
||||
.set_fid = _set_fid,
|
||||
.set_directory = _set_directory,
|
||||
.set_did = _set_did,
|
||||
.set_algo = _set_algo,
|
||||
.list_products = _list_products,
|
||||
.list_files = _list_files,
|
||||
.list_hashes = _list_hashes,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.dir = strdup(""),
|
||||
.algo = PTS_MEAS_ALGO_SHA256,
|
||||
.db = lib->db->create(lib->db, uri),
|
||||
);
|
||||
|
||||
if (!this->db)
|
||||
{
|
||||
fprintf(stderr, "opening database failed.\n");
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (C) 2011 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @defgroup attest_db_t attest_db
|
||||
* @{ @ingroup attest_db
|
||||
*/
|
||||
|
||||
#ifndef ATTEST_DB_H_
|
||||
#define ATTEST_DB_H_
|
||||
|
||||
#include <pts/pts_meas_algo.h>
|
||||
|
||||
#include <library.h>
|
||||
|
||||
typedef struct attest_db_t attest_db_t;
|
||||
|
||||
/**
|
||||
* Attestation database object
|
||||
*/
|
||||
struct attest_db_t {
|
||||
|
||||
/**
|
||||
* Set software product to be queried
|
||||
*
|
||||
* @param product software product
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_product)(attest_db_t *this, char *product);
|
||||
|
||||
/**
|
||||
* Set primary key of the software product to be queried
|
||||
*
|
||||
* @param pid primary key of software product
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_pid)(attest_db_t *this, int pid);
|
||||
|
||||
/**
|
||||
* Set measurement file to be queried
|
||||
*
|
||||
* @param file measurement file
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_file)(attest_db_t *this, char *file);
|
||||
|
||||
/**
|
||||
* Set primary key of the measurement file to be queried
|
||||
*
|
||||
* @param fid primary key of measurement file
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_fid)(attest_db_t *this, int fid);
|
||||
|
||||
/**
|
||||
* Set directory of the measurement file to be queried
|
||||
*
|
||||
* @param directory directory containing the measurement file
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_directory)(attest_db_t *this, char *dir);
|
||||
|
||||
/**
|
||||
* Set primary key of the directory to be queried
|
||||
*
|
||||
* @param did primary key of directory
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_did)(attest_db_t *this, int did);
|
||||
|
||||
/**
|
||||
* Set measurement hash algorithm
|
||||
*
|
||||
* @param algo hash algorithm
|
||||
*/
|
||||
void (*set_algo)(attest_db_t *this, pts_meas_algorithms_t algo);
|
||||
|
||||
/**
|
||||
* List all products stored in the database
|
||||
*/
|
||||
void (*list_products)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* List selected files stored in the database
|
||||
*/
|
||||
void (*list_files)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* List selected measurement hashes stored in the database
|
||||
*/
|
||||
void (*list_hashes)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* Destroy attest_db_t object
|
||||
*/
|
||||
void (*destroy)(attest_db_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an attest_db_t instance
|
||||
*
|
||||
* @param uri database URI
|
||||
*/
|
||||
attest_db_t* attest_db_create(char *uri);
|
||||
|
||||
#endif /** ATTEST_DB_H_ @}*/
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "attest_usage.h"
|
||||
|
||||
/**
|
||||
* print attest usage info
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue