]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
refactored attest database tool
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 30 Oct 2011 21:20:20 +0000 (22:20 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 28 Nov 2011 13:39:53 +0000 (14:39 +0100)
src/libimcv/plugins/imv_attestation/Makefile.am
src/libimcv/plugins/imv_attestation/attest.c
src/libimcv/plugins/imv_attestation/attest_db.c [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/attest_db.h [new file with mode: 0644]
src/libimcv/plugins/imv_attestation/attest_usage.c

index d485aa4731aa4ff4f42952d43244fd00b917da6a..ee045dd0ee46a21be8a1f6a99b93c7b2ce4f5a20 100644 (file)
@@ -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 \
index 8fbfb200bc3b6358b235f75810a0aa9f43d6762d..6b45dafe51a92bb131a59beb66efe10170b9ccc9 100644 (file)
 #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);
diff --git a/src/libimcv/plugins/imv_attestation/attest_db.c b/src/libimcv/plugins/imv_attestation/attest_db.c
new file mode 100644 (file)
index 0000000..107f6e0
--- /dev/null
@@ -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;
+}
diff --git a/src/libimcv/plugins/imv_attestation/attest_db.h b/src/libimcv/plugins/imv_attestation/attest_db.h
new file mode 100644 (file)
index 0000000..9c6ba1a
--- /dev/null
@@ -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_ @}*/
index 61cffb9885b61adc62fac16c191a83dc1368864f..32d175483a47a64f89e1c756d5095dbd7ffb6da2 100644 (file)
@@ -15,6 +15,8 @@
 
 #include <stdio.h>
 
+#include "attest_usage.h"
+
 /**
  * print attest usage info
  */