Manage files and directories
authorAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 22 Apr 2013 22:06:34 +0000 (00:06 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 21 Jun 2013 21:25:21 +0000 (23:25 +0200)
src/libpts/plugins/imv_attestation/attest.c
src/libpts/plugins/imv_attestation/attest_db.c
src/libpts/plugins/imv_attestation/attest_db.h
src/libpts/plugins/imv_attestation/tables.sql

index 1cdacae..944716a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Andreas Steffen
+ * Copyright (C) 2011-2013 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -20,6 +20,7 @@
 #include <string.h>
 #include <errno.h>
 #include <syslog.h>
+#include <libgen.h>
 
 #include <library.h>
 #include <utils/debug.h>
@@ -81,6 +82,7 @@ static void attest_dbg(debug_t group, level_t level, char *fmt, ...)
  */
 attest_db_t *attest;
 
+
 /**
  * atexit handler to close db on shutdown
  */
@@ -100,6 +102,7 @@ static void do_args(int argc, char *argv[])
                OP_KEYS,
                OP_COMPONENTS,
                OP_DEVICES,
+               OP_DIRECTORIES,
                OP_FILES,
                OP_HASHES,
                OP_MEASUREMENTS,
@@ -120,6 +123,8 @@ static void do_args(int argc, char *argv[])
                        { "help", no_argument, NULL, 'h' },
                        { "components", no_argument, NULL, 'c' },
                        { "devices", no_argument, NULL, 'e' },
+                       { "directories", no_argument, NULL, 'd' },
+                       { "dirs", no_argument, NULL, 'd' },
                        { "files", no_argument, NULL, 'f' },
                        { "keys", no_argument, NULL, 'k' },
                        { "packages", no_argument, NULL, 'g' },
@@ -127,8 +132,9 @@ static void do_args(int argc, char *argv[])
                        { "hashes", no_argument, NULL, 'H' },
                        { "measurements", no_argument, NULL, 'm' },
                        { "add", no_argument, NULL, 'a' },
-                       { "delete", no_argument, NULL, 'd' },
-                       { "del", no_argument, NULL, 'd' },
+                       { "delete", no_argument, NULL, 'r' },
+                       { "del", no_argument, NULL, 'r' },
+                       { "remove", no_argument, NULL, 'r' },
                        { "aik", required_argument, NULL, 'A' },
                        { "blacklist", no_argument, NULL, 'B' },
                        { "component", required_argument, NULL, 'C' },
@@ -171,6 +177,9 @@ static void do_args(int argc, char *argv[])
                        case 'c':
                                op = OP_COMPONENTS;
                                continue;
+                       case 'd':
+                               op = OP_DIRECTORIES;
+                               continue;
                        case 'e':
                                op = OP_DEVICES;
                                continue;
@@ -195,7 +204,7 @@ static void do_args(int argc, char *argv[])
                        case 'a':
                                op = OP_ADD;
                                continue;
-                       case 'd':
+                       case 'r':
                                op = OP_DEL;
                                continue;
                        case 'A':
@@ -251,11 +260,26 @@ static void do_args(int argc, char *argv[])
                                }
                                continue;
                        case 'F':
-                               if (!attest->set_file(attest, optarg, op == OP_ADD))
+                       {
+                               char *path = strdup(optarg);
+                               char *dir = dirname(path);
+                               char *file = basename(optarg);
+
+                               if (*dir != '.')
+                               {
+                                       if (!attest->set_directory(attest, dir, op == OP_ADD))
+                                       {
+                                               free(path);
+                                               exit(EXIT_FAILURE);
+                                       }
+                               }
+                               free(path);
+                               if (!attest->set_file(attest, file, op == OP_ADD))
                                {
                                        exit(EXIT_FAILURE);
                                }
                                continue;
+                       }
                        case 'G':
                                if (!attest->set_package(attest, optarg, op == OP_ADD))
                                {
@@ -372,6 +396,9 @@ static void do_args(int argc, char *argv[])
                case OP_DEVICES:
                        attest->list_devices(attest);
                        break;
+               case OP_DIRECTORIES:
+                       attest->list_directories(attest);
+                       break;
                case OP_FILES:
                        attest->list_files(attest);
                        break;
index b2116c0..8459e2b 100644 (file)
@@ -63,11 +63,6 @@ struct private_attest_db_t {
        int did;
 
        /**
-        * TRUE if directory has been set
-        */
-       bool dir_set;
-
-       /**
         * Measurement file to be queried
         */
        char *file;
@@ -78,11 +73,6 @@ struct private_attest_db_t {
        int fid;
 
        /**
-        * TRUE if file has been set
-        */
-       bool file_set;
-
-       /**
         *  AIK to be queried
         */
        chunk_t key;
@@ -304,35 +294,35 @@ METHOD(attest_db_t, set_directory, bool,
        private_attest_db_t *this, char *dir, bool create)
 {
        enumerator_t *e;
+       int did;
        size_t len;
 
-       if (this->dir_set)
+       if (this->did)
        {
                printf("directory has already been set\n");
                return FALSE;
        }
-       free(this->dir);
 
-       /* remove trailing '/' character */
+       /* remove trailing '/' character if not root directory */
        len = strlen(dir);
-       if (len && dir[len-1] == '/')
+       if (len > 1 && dir[len-1] == '/')
        {
                dir[len-1] = '\0';
        }
        this->dir = strdup(dir);
 
        e = this->db->query(this->db,
-                                               "SELECT id FROM files WHERE type = 1 AND path = ?",
+                                               "SELECT id FROM directories WHERE path = ?",
                                                DB_TEXT, dir, DB_INT);
        if (e)
        {
-               if (e->enumerate(e, &this->did))
+               if (e->enumerate(e, &did))
                {
-                       this->dir_set = TRUE;
+                       this->did = did;
                }
                e->destroy(e);
        }
-       if (this->dir_set)
+       if (this->did)
        {
                return TRUE;
        }
@@ -344,14 +334,15 @@ METHOD(attest_db_t, set_directory, bool,
        }
 
        /* Add a new database entry */
-       this->dir_set = this->db->execute(this->db, &this->did,
-                                                               "INSERT INTO files (type, path) VALUES (1, ?)",
-                                                               DB_TEXT, dir) == 1;
-
+       if (1 == this->db->execute(this->db, &did,
+                               "INSERT INTO directories (path) VALUES (?)", DB_TEXT, dir))
+       {
+               this->did = did;
+       }
        printf("directory '%s' %sinserted into database\n", dir,
-                  this->dir_set ? "" : "could not be ");
+                       this->did ? "" : "could not be ");
 
-       return this->dir_set;
+       return this->did > 0;
 }
 
 METHOD(attest_db_t, set_did, bool,
@@ -360,22 +351,20 @@ METHOD(attest_db_t, set_did, bool,
        enumerator_t *e;
        char *dir;
 
-       if (this->dir_set)
+       if (this->did)
        {
                printf("directory has already been set\n");
                return FALSE;
        }
-       this->did = did;
 
-       e = this->db->query(this->db, "SELECT path FROM files WHERE id = ?",
+       e = this->db->query(this->db, "SELECT path FROM directories WHERE id = ?",
                                                DB_UINT, did, DB_TEXT);
        if (e)
        {
                if (e->enumerate(e, &dir))
                {
-                       free(this->dir);
                        this->dir = strdup(dir);
-                       this->dir_set = TRUE;
+                       this->did = did;
                }
                else
                {
@@ -383,76 +372,88 @@ METHOD(attest_db_t, set_did, bool,
                }
                e->destroy(e);
        }
-       return this->dir_set;
+       return this->did > 0;
 }
 
 METHOD(attest_db_t, set_file, bool,
        private_attest_db_t *this, char *file, bool create)
 {
+       int fid;
+       char *sep;
        enumerator_t *e;
-       char *filename;
 
-       if (this->file_set)
+       if (this->file)
        {
                printf("file has already been set\n");
                return FALSE;
        }
        this->file = strdup(file);
-       filename = this->relative ? basename(file) : file;
 
-       e = this->db->query(this->db, "SELECT id FROM files WHERE path = ?",
-                                               DB_TEXT, filename, DB_INT);
+       if (!this->did)
+       {
+               return TRUE;
+       }
+       sep = streq(this->dir, "/") ? "" : "/";
+       e = this->db->query(this->db, "SELECT id FROM files "
+                                               "WHERE dir = ? AND name = ?",
+                                               DB_INT, this->did, DB_TEXT, file, DB_INT);
        if (e)
        {
-               if (e->enumerate(e, &this->fid))
+               if (e->enumerate(e, &fid))
                {
-                       this->file_set = TRUE;
+                       this->fid = fid;
                }
                e->destroy(e);
        }
-       if (this->file_set)
+       if (this->fid)
        {
                return TRUE;
        }
 
        if (!create)
        {
-               printf("file '%s' not found in database\n", file);
+               printf("file '%s%s%s' not found in database\n", this->dir, sep, file);
                return FALSE;
        }
 
        /* Add a new database entry */
-       this->file_set = this->db->execute(this->db, &this->fid,
-                                                               "INSERT INTO files (type, path) VALUES (0, ?)",
-                                                               DB_TEXT, filename) == 1;
-
-       printf("file '%s' %sinserted into database\n", filename,
-                  this->file_set ? "" : "could not be ");
+       if (1 == this->db->execute(this->db, &fid,
+                                                          "INSERT INTO files (dir, name) VALUES (?, ?)",
+                                                          DB_INT, this->did, DB_TEXT, file))
+       {
+               this->fid = fid;
+       }
+       printf("file '%s%s%s' %sinserted into database\n", this->dir, sep, file,
+                  this->fid ? "" : "could not be ");
 
-       return this->file_set;
+       return this->fid > 0;
 }
 
 METHOD(attest_db_t, set_fid, bool,
        private_attest_db_t *this, int fid)
 {
        enumerator_t *e;
+       int did;
        char *file;
 
-       if (this->file_set)
+       if (this->fid)
        {
                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_UINT, fid, DB_TEXT);
+       e = this->db->query(this->db, "SELECT dir, name FROM files WHERE id = ?",
+                                               DB_UINT, fid, DB_INT, DB_TEXT);
        if (e)
        {
-               if (e->enumerate(e, &file))
+               if (e->enumerate(e, &did, &file))
                {
+                       if (did)
+                       {
+                               set_did(this, did);
+                       }
                        this->file = strdup(file);
-                       this->file_set = TRUE;
+                       this->fid = fid;
                }
                else
                {
@@ -460,7 +461,7 @@ METHOD(attest_db_t, set_fid, bool,
                }
                e->destroy(e);
        }
-       return this->file_set;
+       return this->fid > 0;
 }
 
 METHOD(attest_db_t, set_key, bool,
@@ -920,53 +921,92 @@ METHOD(attest_db_t, list_files, void,
        private_attest_db_t *this)
 {
        enumerator_t *e;
-       char *file, *file_type[] = { " ", "d", "r" };
-       int fid, type, meas, meta, count = 0;
+       char *dir, *file;
+       int did, last_did = 0, fid, count = 0;
 
-       if (this->pid)
+       if (this->did)
        {
                e = this->db->query(this->db,
-                               "SELECT f.id, f.type, f.path, pf.measurement, pf.metadata "
-                               "FROM files AS f "
-                               "JOIN product_file AS pf ON f.id = pf.file "
-                               "WHERE pf.product = ? ORDER BY f.path",
-                               DB_UINT, this->pid, DB_INT, DB_INT, DB_TEXT, DB_INT, DB_INT);
+                               "SELECT id, name FROM files WHERE dir = ? ORDER BY name",
+                               DB_INT, this->did, DB_INT, DB_TEXT);
                if (e)
                {
-                       while (e->enumerate(e, &fid, &type, &file, &meas, &meta))
+                       while (e->enumerate(e, &fid, &file))
                        {
-                               type = (type < 0 || type > 2) ? 0 : type;
-                               printf("%4d: |%s%s| %s %s\n", fid, meas ? "M":" ", meta ? "T":" ",
-                                                                                         file_type[type], file);
+                               printf("%4d: %s\n", fid, file);
                                count++;
                        }
                        e->destroy(e);
                }
+               printf("%d file%s found in directory '%s'\n", count,
+                         (count == 1) ? "" : "s", this->dir);
        }
        else
        {
                e = this->db->query(this->db,
-                               "SELECT id, type, path FROM files "
-                               "ORDER BY path",
-                               DB_INT, DB_INT, DB_TEXT);
+                               "SELECT d.id, d.path, f.id, f.name FROM files AS f "
+                               "JOIN directories AS d ON f.dir = d.id "
+                               "ORDER BY d.path, f.name",
+                               DB_INT, DB_TEXT, DB_INT, DB_TEXT);
                if (e)
                {
-                       while (e->enumerate(e, &fid, &type, &file))
+                       while (e->enumerate(e, &did, &dir, &fid, &file))
                        {
-                               type = (type < 0 || type > 2) ? 0 : type;
-                               printf("%4d: %s %s\n", fid, file_type[type], file);
+                               if (did != last_did)
+                               {
+                                       printf("%4d: %s\n", did, dir);
+                                       last_did = did;
+                               }
+                               printf("%4d:   %s\n", fid, file);
                                count++;
                        }
                        e->destroy(e);
                }
+               printf("%d file%s found\n", count, (count == 1) ? "" : "s");
        }
+}
 
-       printf("%d file%s found", count, (count == 1) ? "" : "s");
-       if (this->product_set)
+METHOD(attest_db_t, list_directories, void,
+       private_attest_db_t *this)
+{
+       enumerator_t *e;
+       char *dir;
+       int did, count = 0;
+
+       if (this->file)
        {
-               printf(" for product '%s'", this->product);
+               e = this->db->query(this->db,
+                               "SELECT d.id, d.path FROM directories AS d "
+                               "JOIN files AS f ON f.dir = d.id WHERE f.name = ? "
+                               "ORDER BY path", DB_TEXT, this->file, DB_INT, DB_TEXT);
+               if (e)
+               {
+                       while (e->enumerate(e, &did, &dir))
+                       {
+                               printf("%4d: %s\n", did, dir);
+                               count++;
+                       }
+                       e->destroy(e);
+               }
+               printf("%d director%s found containing file '%s'\n", count,
+                         (count == 1) ? "y" : "ies", this->file);
+       }
+       else
+       {
+               e = this->db->query(this->db,
+                               "SELECT id, path FROM directories ORDER BY path",
+                               DB_INT, DB_TEXT);
+               if (e)
+               {
+                       while (e->enumerate(e, &did, &dir))
+                       {
+                               printf("%4d: %s\n", did, dir);
+                               count++;
+                       }
+                       e->destroy(e);
+               }
+               printf("%d director%s found\n", count, (count == 1) ? "y" : "ies");
        }
-       printf("\n");
 }
 
 METHOD(attest_db_t, list_packages, void,
@@ -1077,7 +1117,7 @@ METHOD(attest_db_t, list_products, void,
        }
 
        printf("%d product%s found", count, (count == 1) ? "" : "s");
-       if (this->file_set)
+       if (this->fid)
        {
                printf(" for file '%s'", this->file);
        }
@@ -1607,6 +1647,9 @@ METHOD(attest_db_t, delete, bool,
        private_attest_db_t *this)
 {
        bool success;
+       int id, count = 0;
+       char *name;
+       enumerator_t *e;
 
        /* delete a file measurement hash for a given product */
        if (this->algo && this->pid && this->fid)
@@ -1667,24 +1710,44 @@ METHOD(attest_db_t, delete, bool,
                return success;
        }
 
-       if (this->did)
+       if (this->fid)
        {
                success = this->db->execute(this->db, NULL,
-                                                               "DELETE FROM files WHERE type = 1 AND id = ?",
-                                                               DB_UINT, this->did) > 0;
+                                                               "DELETE FROM files WHERE id = ?",
+                                                               DB_UINT, this->fid) > 0;
 
-               printf("directory '%s' %sdeleted from database\n", this->dir,
+               printf("file '%s%s%s' %sdeleted from database\n", this->dir,
+                          streq(this->dir, "/") ? "" : "/", this->file,
                           success ? "" : "could not be ");
                return success;
        }
 
-       if (this->fid)
+       if (this->did)
        {
-               success = this->db->execute(this->db, NULL,
-                                                               "DELETE FROM files WHERE id = ?",
-                                                               DB_UINT, this->fid) > 0;
+               e = this->db->query(this->db,
+                               "SELECT id, name FROM files WHERE dir = ? ORDER BY name",
+                               DB_INT, this->did, DB_INT, DB_TEXT);
+               if (e)
+               {
+                       while (e->enumerate(e, &id, &name))
+                       {
+                               printf("%4d: %s\n", id, name);
+                               count++;
+                       }
+                       e->destroy(e);
 
-               printf("file '%s' %sdeleted from database\n", this->file,
+                       if (count)
+                       {
+                               printf("%d dependent file%s found, "
+                                          "directory '%s' could not deleted\n",
+                                          count, (count == 1) ? "" : "s", this->dir);
+                               return FALSE;
+                       }
+               }
+               success = this->db->execute(this->db, NULL,
+                                                               "DELETE FROM directories WHERE id = ?",
+                                                               DB_UINT, this->did) > 0;
+               printf("directory '%s' %sdeleted from database\n", this->dir,
                           success ? "" : "could not be ");
                return success;
        }
@@ -1760,6 +1823,7 @@ attest_db_t *attest_db_create(char *uri)
                        .list_packages = _list_packages,
                        .list_products = _list_products,
                        .list_files = _list_files,
+                       .list_directories = _list_directories,
                        .list_components = _list_components,
                        .list_devices = _list_devices,
                        .list_keys = _list_keys,
@@ -1769,7 +1833,6 @@ attest_db_t *attest_db_create(char *uri)
                        .delete = _delete,
                        .destroy = _destroy,
                },
-               .dir = strdup(""),
                .db = lib->db->create(lib->db, uri),
        );
 
index a20023f..a110be9 100644 (file)
@@ -193,6 +193,11 @@ struct attest_db_t {
        void (*list_products)(attest_db_t *this);
 
        /**
+        * List all directories stored in the database
+        */
+       void (*list_directories)(attest_db_t *this);
+
+       /**
         * List selected files stored in the database
         */
        void (*list_files)(attest_db_t *this);
index 0c038d3..5e9f4d7 100644 (file)
@@ -1,16 +1,26 @@
 /* PTS SQLite database */
 
-DROP TABLE IF EXISTS files;
-CREATE TABLE files (
+DROP TABLE IF EXISTS directories;
+CREATE TABLE directories (
   id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
-  type INTEGER NOT NULL,
   path TEXT NOT NULL
 );
-DROP INDEX IF EXISTS files_path;
-CREATE INDEX files_path ON files (
+DROP INDEX IF EXISTS directories_path;
+CREATE INDEX directories_path ON directories (
   path
 );
 
+DROP TABLE IF EXISTS files;
+CREATE TABLE files (
+  id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+  dir INTEGER DEFAULT 0,
+  name TEXT NOT NULL
+);
+DROP INDEX IF EXISTS files_name;
+CREATE INDEX files_name ON files (
+  name
+);
+
 DROP TABLE IF EXISTS products;
 CREATE TABLE products (
   id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
@@ -21,39 +31,20 @@ CREATE INDEX products_name ON products (
   name
 );
 
-DROP TABLE IF EXISTS product_file;
-CREATE TABLE product_file (
-  product INTEGER NOT NULL,
-  file INTEGER NOT NULL,
-  measurement INTEGER DEFAULT 0,
-  metadata INTEGER DEFAULT 0,
-  PRIMARY KEY (product, file)
+DROP TABLE IF EXISTS algorithms;
+CREATE TABLE algorithms (
+  id INTEGER PRIMARY KEY,
+  name TEXT not NULL
 );
 
 DROP TABLE IF EXISTS file_hashes;
 CREATE TABLE file_hashes (
+  id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
   file INTEGER NOT NULL,
-  directory INTEGER DEFAULT 0,
   product INTEGER NOT NULL,
-  key INTEGER DEFAULT 0,
+  device INTEGER DEFAULT 0,
   algo INTEGER NOT NULL,
-  hash BLOB NOT NULL,
-  PRIMARY KEY(file, directory, product, algo)
-);
-
-DROP TABLE IF EXISTS keys;
-CREATE TABLE keys (
-  id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
-  keyid BLOB NOT NULL,
-  owner TEXT NOT NULL
-);
-DROP INDEX IF EXISTS keys_keyid;
-CREATE INDEX keys_keyid ON keys (
-  keyid
-);
-DROP INDEX IF EXISTS keys_owner;
-CREATE INDEX keys_owner ON keys (
-  owner
+  hash BLOB NOT NULL
 );
 
 DROP TABLE IF EXISTS components;