added package management to ipsec attest
authorAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 2 Nov 2012 22:16:54 +0000 (23:16 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 2 Nov 2012 22:17:19 +0000 (23:17 +0100)
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 a938688..bcce833 100644 (file)
@@ -102,6 +102,7 @@ static void do_args(int argc, char *argv[])
                OP_FILES,
                OP_HASHES,
                OP_MEASUREMENTS,
+               OP_PACKAGES,
                OP_PRODUCTS,
                OP_ADD,
                OP_DEL,
@@ -119,6 +120,7 @@ static void do_args(int argc, char *argv[])
                        { "components", no_argument, NULL, 'c' },
                        { "files", no_argument, NULL, 'f' },
                        { "keys", no_argument, NULL, 'k' },
+                       { "packages", no_argument, NULL, 'g' },
                        { "products", no_argument, NULL, 'p' },
                        { "hashes", no_argument, NULL, 'H' },
                        { "measurements", no_argument, NULL, 'm' },
@@ -126,18 +128,21 @@ static void do_args(int argc, char *argv[])
                        { "delete", no_argument, NULL, 'd' },
                        { "del", no_argument, NULL, 'd' },
                        { "aik", required_argument, NULL, 'A' },
+                       { "security", no_argument, NULL, 'B' },
                        { "component", required_argument, NULL, 'C' },
                        { "comp", required_argument, NULL, 'C' },
                        { "directory", required_argument, NULL, 'D' },
                        { "dir", required_argument, NULL, 'D' },
                        { "file", required_argument, NULL, 'F' },
                        { "sha1-ima", no_argument, NULL, 'I' },
+                       { "package", required_argument, NULL, 'G' },
                        { "key", required_argument, NULL, 'K' },
                        { "owner", required_argument, NULL, 'O' },
                        { "product", required_argument, NULL, 'P' },
                        { "relative", no_argument, NULL, 'R' },
                        { "rel", no_argument, NULL, 'R' },
                        { "sequence", required_argument, NULL, 'S' },
+                       { "version", required_argument, NULL, 'V' },
                        { "seq", required_argument, NULL, 'S' },
                        { "sha1", no_argument, NULL, '1' },
                        { "sha256", no_argument, NULL, '2' },
@@ -147,6 +152,7 @@ static void do_args(int argc, char *argv[])
                        { "pid", required_argument, NULL, '6' },
                        { "cid", required_argument, NULL, '7' },
                        { "kid", required_argument, NULL, '8' },
+                       { "gid", required_argument, NULL, '9' },
                        { 0,0,0,0 }
                };
 
@@ -164,6 +170,9 @@ static void do_args(int argc, char *argv[])
                        case 'f':
                                op = OP_FILES;
                                continue;
+                       case 'g':
+                               op = OP_PACKAGES;
+                               continue;
                        case 'k':
                                op = OP_KEYS;
                                continue;
@@ -219,6 +228,9 @@ static void do_args(int argc, char *argv[])
                                }
                                continue;
                        }
+                       case 'B':
+                               attest->set_security(attest);
+                               continue;
                        case 'C':
                                if (!attest->set_component(attest, optarg, op == OP_ADD))
                                {
@@ -237,6 +249,12 @@ static void do_args(int argc, char *argv[])
                                        exit(EXIT_FAILURE);
                                }
                                continue;
+                       case 'G':
+                               if (!attest->set_package(attest, optarg, op == OP_ADD))
+                               {
+                                       exit(EXIT_FAILURE);
+                               }
+                               continue;
                        case 'I':
                                attest->set_algo(attest, PTS_MEAS_ALGO_SHA1_IMA);
                                continue;
@@ -266,6 +284,12 @@ static void do_args(int argc, char *argv[])
                        case 'S':
                                attest->set_sequence(attest, atoi(optarg));
                                continue;
+                       case 'V':
+                               if (!attest->set_version(attest, optarg))
+                               {
+                                       exit(EXIT_FAILURE);
+                               }
+                               continue;
                        case '1':
                                attest->set_algo(attest, PTS_MEAS_ALGO_SHA1);
                                continue;
@@ -305,6 +329,12 @@ static void do_args(int argc, char *argv[])
                                        exit(EXIT_FAILURE);
                                }
                                continue;
+                       case '9':
+                               if (!attest->set_gid(attest, atoi(optarg)))
+                               {
+                                       exit(EXIT_FAILURE);
+                               }
+                               continue;
                }
                break;
        }
@@ -314,6 +344,9 @@ static void do_args(int argc, char *argv[])
                case OP_USAGE:
                        usage();
                        break;
+               case OP_PACKAGES:
+                       attest->list_packages(attest);
+                       break;
                case OP_PRODUCTS:
                        attest->list_products(attest);
                        break;
index 26301c4..e71442f 100644 (file)
@@ -97,6 +97,21 @@ struct private_attest_db_t {
        bool key_set;
 
        /**
+        * Software package to be queried
+        */
+       char *package;
+
+       /**
+        * Primary key of software package to be queried
+        */
+       int gid;
+
+       /**
+        * TRUE if package has been set
+        */
+       bool package_set;
+
+       /**
         * Software product to be queried
         */
        char *product;
@@ -112,11 +127,26 @@ struct private_attest_db_t {
        bool product_set;
 
        /**
+        * Software package version to be queried
+        */
+       char *version;
+
+       /**
+        * TRUE if version has been set
+        */
+       bool version_set;
+
+       /**
         * TRUE if relative filenames are to be used
         */
        bool relative;
 
        /**
+        * TRUE if a security issue exists
+        */
+       bool security;
+
+       /**
         * Sequence number for ordering entries
         */
        int seq_no;
@@ -588,6 +618,96 @@ METHOD(attest_db_t, set_pid, bool,
        return this->product_set;
 }
 
+METHOD(attest_db_t, set_package, bool,
+       private_attest_db_t *this, char *package, bool create)
+{
+       enumerator_t *e;
+
+       if (this->package_set)
+       {
+               printf("package has already been set\n");
+               return FALSE;
+       }
+       this->package = strdup(package);
+
+       e = this->db->query(this->db, "SELECT id FROM packages WHERE name = ?",
+                                               DB_TEXT, package, DB_INT);
+       if (e)
+       {
+               if (e->enumerate(e, &this->gid))
+               {
+                       this->package_set = TRUE;
+               }
+               e->destroy(e);
+       }
+       if (this->package_set)
+       {
+               return TRUE;
+       }
+
+       if (!create)
+       {
+               printf("package '%s' not found in database\n", package);
+               return FALSE;
+       }
+
+       /* Add a new database entry */
+       this->package_set = this->db->execute(this->db, &this->gid,
+                                                                       "INSERT INTO packages (name) VALUES (?)",
+                                                                       DB_TEXT, package) == 1;
+
+       printf("package '%s' %sinserted into database\n", package,
+                  this->package_set ? "" : "could not be ");
+
+       return this->package_set;
+}
+
+METHOD(attest_db_t, set_gid, bool,
+       private_attest_db_t *this, int gid)
+{
+       enumerator_t *e;
+       char *package;
+
+       if (this->package_set)
+       {
+               printf("package has already been set\n");
+               return FALSE;
+       }
+       this->gid = gid;
+
+       e = this->db->query(this->db, "SELECT name FROM packages WHERE id = ?",
+                                               DB_UINT, gid, DB_TEXT);
+       if (e)
+       {
+               if (e->enumerate(e, &package))
+               {
+                       this->package = strdup(package);
+                       this->package_set = TRUE;
+               }
+               else
+               {
+                       printf("no package found with gid %d in database\n", gid);
+               }
+               e->destroy(e);
+       }
+       return this->package_set;
+}
+
+METHOD(attest_db_t, set_version, bool,
+       private_attest_db_t *this, char *version)
+{
+       if (this->version_set)
+       {
+               printf("version has already been set\n");
+               return FALSE;
+       }
+       this->version = strdup(version);
+       this->version_set = TRUE;
+
+       return TRUE;
+}
+
+
 METHOD(attest_db_t, set_algo, void,
        private_attest_db_t *this, pts_meas_algorithms_t algo)
 {
@@ -600,6 +720,12 @@ METHOD(attest_db_t, set_relative, void,
        this->relative = TRUE;
 }
 
+METHOD(attest_db_t, set_security, void,
+       private_attest_db_t *this)
+{
+       this->security = TRUE;
+}
+
 METHOD(attest_db_t, set_sequence, void,
        private_attest_db_t *this, int seq_no)
 {
@@ -765,6 +891,67 @@ METHOD(attest_db_t, list_files, void,
        printf("\n");
 }
 
+METHOD(attest_db_t, list_packages, void,
+       private_attest_db_t *this)
+{
+       enumerator_t *e;
+       char *package, *version;
+       int gid, gid_old = 0, security, spaces, count = 0;
+
+       if (this->pid)
+       {
+               e = this->db->query(this->db,
+                               "SELECT p.id, p.name, v.release, v.security FROM packages AS p "
+                               "JOIN versions AS v ON v.package = p.id "
+                               "Where v.product = ? ORDER BY p.name, v.release",
+                               DB_INT, this->pid, DB_INT, DB_TEXT, DB_TEXT, DB_INT);
+               if (e)
+               {
+                       while (e->enumerate(e, &gid, &package, &version, &security))
+                       {
+                               if (gid != gid_old)
+                               {
+                                       printf("%5d: %s", gid, package);
+                                       gid_old = gid;
+                               }
+                               else
+                               {
+                                       spaces = 7 + strlen(package);
+                                       while (spaces--)
+                                       {
+                                               printf(" ");
+                                       }
+                               }
+                               printf(" (%s) %s\n", version, security ? "[s]" : "");
+                               count++;
+                       }
+                       e->destroy(e);
+               }
+       }
+       else
+       {
+               e = this->db->query(this->db, "SELECT id, name FROM packages "
+                               "ORDER BY name",
+                               DB_INT, DB_TEXT);
+               if (e)
+               {
+                       while (e->enumerate(e, &gid, &package))
+                       {
+                               printf("%4d: %s\n", gid, package);
+                               count++;
+                       }
+                       e->destroy(e);
+               }
+       }
+
+       printf("%d package%s found", count, (count == 1) ? "" : "s");
+       if (this->product_set)
+       {
+               printf(" for product '%s'", this->product);
+       }
+       printf("\n");
+}
+
 METHOD(attest_db_t, list_products, void,
        private_attest_db_t *this)
 {
@@ -889,7 +1076,7 @@ METHOD(attest_db_t, list_hashes, void,
        {
                e = this->db->query(this->db,
                                "SELECT f.path, fh.hash FROM file_hashes AS fh "
-                               "JOIN files AS f ON f.id = fh.directory "
+                               "JOIN files AS f ON f.id = fh.file "
                                "WHERE algo = ? AND file = ? AND product = ?",
                                DB_INT, this->algo, DB_INT, this->fid, DB_INT, this->pid,
                                DB_TEXT, DB_BLOB);
@@ -1291,6 +1478,20 @@ METHOD(attest_db_t, add, bool,
                measurements->destroy(measurements);
                success = TRUE;
        }
+
+       /* insert package version */
+       if (this->version_set && this->gid && this->pid)
+       {
+               success = this->db->execute(this->db, NULL,
+                                       "INSERT INTO versions (package, product, release, security) "
+                                       "VALUES (?, ?, ?, ?)",
+                                       DB_UINT, this->gid, DB_UINT, this->pid,
+                                       DB_TEXT, this->version, DB_UINT, this->security) == 1;
+
+               printf("'%s' package %s (%s) %s%sinserted into database\n",
+                               this->product, this->package, this->version,
+                               this->security ? "[s] " : "", success ? "" : "could not be ");
+       }
        return success;
 }
 
@@ -1410,7 +1611,9 @@ METHOD(attest_db_t, destroy, void,
 {
        DESTROY_IF(this->db);
        DESTROY_IF(this->cfn);
+       free(this->package);
        free(this->product);
+       free(this->version);
        free(this->file);
        free(this->dir);
        free(this->owner);
@@ -1435,12 +1638,17 @@ attest_db_t *attest_db_create(char *uri)
                        .set_fid = _set_fid,
                        .set_key = _set_key,
                        .set_kid = _set_kid,
+                       .set_package = _set_package,
+                       .set_gid = _set_gid,
                        .set_product = _set_product,
                        .set_pid = _set_pid,
+                       .set_version = _set_version,
                        .set_algo = _set_algo,
                        .set_relative = _set_relative,
+                       .set_security = _set_security,
                        .set_sequence = _set_sequence,
                        .set_owner = _set_owner,
+                       .list_packages = _list_packages,
                        .list_products = _list_products,
                        .list_files = _list_files,
                        .list_components = _list_components,
index e32a368..cd7b5f4 100644 (file)
@@ -102,6 +102,23 @@ struct attest_db_t {
        bool (*set_kid)(attest_db_t *this, int kid);
 
        /**
+        * Set software package to be queried
+        *
+        * @param product               software package
+        * @param create                if TRUE create database entry if it doesn't exist
+        * @return                              TRUE if successful
+        */
+       bool (*set_package)(attest_db_t *this, char *package, bool create);
+
+       /**
+        * Set primary key of the software package to be queried
+        *
+        * @param gid                   primary key of software package
+        * @return                              TRUE if successful
+        */
+       bool (*set_gid)(attest_db_t *this, int gid);
+
+       /**
         * Set software product to be queried
         *
         * @param product               software product
@@ -119,6 +136,14 @@ struct attest_db_t {
        bool (*set_pid)(attest_db_t *this, int pid);
 
        /**
+        * Set software package version to be queried
+        *
+        * @param version               software package version
+        * @return                              TRUE if successful
+        */
+       bool (*set_version)(attest_db_t *this, char *version);
+
+       /**
         * Set measurement hash algorithm
         *
         * @param algo                  hash algorithm
@@ -136,6 +161,11 @@ struct attest_db_t {
        void (*set_relative)(attest_db_t *this);
 
        /**
+        * Set the security vulnerability flag
+        */
+       void (*set_security)(attest_db_t *this);
+
+       /**
         * Set the sequence number
         */
        void (*set_sequence)(attest_db_t *this, int seq_no);
@@ -149,6 +179,11 @@ struct attest_db_t {
        void (*set_owner)(attest_db_t *this, char *owner);
 
        /**
+        * List all packages stored in the database
+        */
+       void (*list_packages)(attest_db_t *this);
+
+       /**
         * List all products stored in the database
         */
        void (*list_products)(attest_db_t *this);
index 42553be..63a0fa9 100644 (file)
@@ -85,3 +85,26 @@ CREATE TABLE component_hashes (
   hash BLOB NOT NULL,
   PRIMARY KEY(component, key, seq_no, algo)
 );
+
+DROP TABLE IF EXISTS packages;
+CREATE TABLE packages (
+  id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+  name TEXT NOT NULL
+);
+DROP INDEX IF EXISTS packages_name;
+CREATE INDEX packages_name ON packages (
+  name
+);
+
+DROP TABLE IF EXISTS versions;
+CREATE TABLE versions (
+  id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+  package INTEGER NOT NULL,
+  product INTEGER NOT NULL,
+  release TEXT NOT NULL,
+  security INTEGER DEFAULT 0
+);
+DROP INDEX IF EXISTS versions_release;
+CREATE INDEX versions_release ON versions (
+  release
+);