generate workitems based on group policy
authorAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 23 May 2013 20:12:10 +0000 (22:12 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 21 Jun 2013 21:25:23 +0000 (23:25 +0200)
src/libimcv/imv/data.sql
src/libimcv/imv/imv_policy_manager.c
src/libimcv/imv/tables.sql
src/libimcv/plugins/imv_os/imv_os.c

index dfab9e2..4df72be 100644 (file)
@@ -144,6 +144,18 @@ INSERT INTO products (                     /* 24 */
  'Ubuntu 13.04 x86_64'
 );
 
+INSERT INTO products (                 /* 25 */
+  name
+) VALUES (
+ 'Android 4.1.1'
+);
+
+INSERT INTO products (                 /* 26 */
+  name
+) VALUES (
+ 'Android 4.2.1'
+);
+
 /* Directories */
 
 INSERT INTO directories (              /*  1 */
@@ -250,26 +262,6 @@ INSERT INTO files (                                /*  5 */
   'openssl', 8
 );
 
-/* Product-File */
-
-INSERT INTO product_file (
-  product, file, measurement
-) VALUES (
-  3, 1, 1
-);
-
-INSERT INTO product_file (
-  product, file, measurement
-) VALUES (
-  3, 3, 1
-);
-
-INSERT INTO product_file (
-  product, file, measurement
-) VALUES (
-  3, 5, 1
-);
-
 /* Algorithms */
 
 INSERT INTO algorithms (
@@ -436,24 +428,363 @@ INSERT INTO packages (                   /*  4 */
 
 INSERT INTO versions (
   package, product, release, time
-) values (
+) VALUES (
   1, 1, '1.0.1e-2', 1366531494
 );
 
 INSERT INTO versions (
   package, product, release, time
-) values (
+) VALUES (
   2, 1, '1.0.1e-2', 1366531494
 );
 
 INSERT INTO versions (
   package, product, release, time
-) values (
+) VALUES (
   3, 1, '1.0.1e-2', 1366531494
 );
 
 INSERT INTO versions (
   package, product, release, time
-) values (
+) VALUES (
   4, 1, '1.0.1e-2', 1366531494
 );
+
+/* Groups */
+
+INSERT INTO groups (                   /*  1 */
+  name
+) VALUES (
+  'Default Debian i686'
+);
+
+INSERT INTO groups (                   /*  2 */
+  name
+) VALUES (
+  'Default Debian x86_64'
+);
+
+INSERT INTO groups (                   /*  3 */
+  name
+) VALUES (
+  'Default Ubuntu i686'
+);
+
+INSERT INTO groups (                   /*  4 */
+  name
+) VALUES (
+  'Default Ubuntu x86_64'
+);
+
+INSERT INTO groups (                   /*  5 */
+  name
+) VALUES (
+  'Default Android'
+);
+
+/* Default Product Groups */
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  1, 2
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  2, 3
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  3, 5
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  3, 8
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  3, 11
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  3, 14
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  3, 17
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  3, 20
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  3, 23
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  4, 6
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  4, 9
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  4, 12
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  4, 15
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  4, 18
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  4, 21
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  4, 24
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  5, 25
+);
+
+INSERT INTO default_product_groups (
+  group_id, product
+) VALUES (
+  5, 26
+);
+
+/* Policies */
+
+INSERT INTO policies (                 /*  1 */
+  type, name, rec_fail, rec_noresult
+) VALUES (
+  1, 'Installed Packages', 2, 2
+);
+
+INSERT INTO policies (                 /*  2 */
+  type, name, rec_fail, rec_noresult
+) VALUES (
+  2, 'Unknown Source', 2, 2
+);
+
+INSERT INTO policies (                 /*  3 */
+  type, name, rec_fail, rec_noresult
+) VALUES (
+  3, 'IP Forwarding Enabled',  1, 1
+);
+
+INSERT INTO policies (                 /*  4 */
+  type, name, rec_fail, rec_noresult
+) VALUES (
+  4, 'Default Factory Password Enabled', 1, 1
+);
+
+INSERT INTO policies (                 /*  5 */
+  type, name, file, rec_fail, rec_noresult
+) VALUES (
+  6, 'Measure /lib/x86_64-linux-gnu/libcrypto.so.1.0.0', 1, 2, 2
+);
+
+INSERT INTO policies (                 /*  6 */
+  type, name, file, rec_fail, rec_noresult
+) VALUES (
+  6, 'Measure /lib/x86_64-linux-gnu/libssl.so.1.0.0', 3, 2, 2
+);
+
+INSERT INTO policies (                 /*  7 */
+  type, name, file, rec_fail, rec_noresult
+) VALUES (
+  6, 'Measure /usr/bin/openssl', 5, 2, 2
+);
+
+INSERT INTO policies (                 /*  8 */
+  type, name, rec_fail, rec_noresult
+) VALUES (
+  9, 'No Open TCP Ports', 1, 1
+);
+
+INSERT INTO policies (                 /*  9 */
+  type, name, rec_fail, rec_noresult
+) VALUES (
+  10, 'No Open UDP Ports', 1, 1
+);
+
+/* Enforcements */
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  1, 1, 86400
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  1, 2, 86400
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  1, 3, 86400
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  1, 4, 86400
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  1, 5, 86400
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  2, 5, 0
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  3, 1, 0
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  3, 2, 0
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  3, 3, 0
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  3, 4, 0
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  5, 2, 86400
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  6, 2, 86400
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  7, 2, 86400
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  8, 1, 60
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  8, 2, 60
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  8, 3, 60
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  8, 4, 60
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  8, 5, 60
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  9, 1, 60
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  9, 2, 60
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  9, 3, 60
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  9, 4, 60
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  9, 5, 60
+);
+
index 7819a10..a91deec 100644 (file)
@@ -49,42 +49,121 @@ static void stderr_dbg(debug_t group, level_t level, char *fmt, ...)
 
 bool policy_start(database_t *db, int session_id)
 {
-       if (db->execute(db, NULL,
-                               "INSERT INTO workitems (session, type, argument, "
-                               "rec_fail, rec_noresult) VALUES (?, ?, ?, ?, ?)",
-                               DB_INT, session_id, DB_INT, IMV_WORKITEM_PACKAGES,
-                               DB_TEXT, "",
-                               DB_INT, TNC_IMV_ACTION_RECOMMENDATION_ISOLATE,
-                               DB_INT, TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS) != 1)
+       enumerator_t *e;
+       int id, gid, device_id, product_id, group_id = 0;
+       int type, rec_fail, rec_noresult;
+       char *argument;
+
+       /* get session data */
+       e = db->query(db,
+                       "SELECT device, product FROM sessions WHERE id = ? ",
+                        DB_INT, session_id, DB_INT, DB_INT);
+       if (!e || !e->enumerate(e, &device_id, &product_id))
        {
+               DESTROY_IF(e);
+               fprintf(stderr, "session %d not found\n", session_id);
                return FALSE;
        }
-       if (db->execute(db, NULL,
-                               "INSERT INTO workitems (session, type, argument, "
-                               "rec_fail, rec_noresult) VALUES (?, ?, ?, ?, ?)",
-                               DB_INT, session_id, DB_INT, IMV_WORKITEM_FORWARDING,
-                               DB_TEXT, "",
-                               DB_INT, TNC_IMV_ACTION_RECOMMENDATION_ISOLATE,
-                               DB_INT, TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS) != 1)
+       e->destroy(e);
+
+       /* if a device ID exists, check if device belongs to a group */
+       if (device_id)
        {
-               return FALSE;
+               e = db->query(db,
+                               "SELECT group_id FROM group_members WHERE device = ?",
+                                DB_INT, device_id, DB_INT);
+               if (e)
+               {
+                       if (e->enumerate(e, &gid))
+                       {
+                               group_id = gid;
+                       }
+                       e->destroy(e);
+               }
        }
-       if (db->execute(db, NULL,
-                               "INSERT INTO workitems (session, type, argument, "
-                               "rec_fail, rec_noresult) VALUES (?, ?, ?, ?, ?)",
-                               DB_INT, session_id, DB_INT, IMV_WORKITEM_TCP_SCAN,
-                               DB_TEXT, "22",
-                               DB_INT, TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS,
-                               DB_INT, TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS) != 1)
+
+       /* if no group membership found, try default product group */
+       if (!group_id)
+       {
+               e = db->query(db,
+                               "SELECT group_id FROM default_product_groups WHERE product = ?",
+                                DB_INT, product_id, DB_INT);
+               if (e)
+               {
+                       if (e->enumerate(e, &gid))
+                       {
+                               group_id = gid;
+                       }
+                       e->destroy(e);
+               }
+       }
+
+       /* if still no group membership found, leave */
+       if (!group_id)
+       {
+               fprintf(stderr, "no group membership found\n");
+               return TRUE;
+       }
+
+       /* get enforcements for given group */
+       e = db->query(db,
+                       "SELECT e.id, p.type, p.argument, p.rec_fail, p.rec_noresult "
+                       "FROM enforcements AS e JOIN policies as p ON  e.policy = p.id "
+                       "WHERE e.group_id = ?",
+                        DB_INT, group_id, DB_INT, DB_INT, DB_TEXT, DB_INT, DB_INT);
+       if (!e)
        {
                return FALSE;
        }
+       while (e->enumerate(e, &id, &type, &argument, &rec_fail, &rec_noresult))
+       {
+               /* insert a workitem */
+               if (db->execute(db, NULL,
+                               "INSERT INTO workitems (session, enforcement, type, argument, "
+                               "rec_fail, rec_noresult) VALUES (?, ?, ?, ?, ?, ?)",
+                               DB_INT, session_id, DB_INT, id, DB_INT, type, DB_TEXT, argument,
+                               DB_INT, rec_fail, DB_INT, rec_noresult) != 1)
+               {
+                       e->destroy(e);
+                       fprintf(stderr, "could not insert workitem\n");
+                       return FALSE;
+               }
+       }
+       e->destroy(e);
 
        return TRUE;
 }
 
 bool policy_stop(database_t *db, int session_id)
 {
+       enumerator_t *e;
+       int rec, policy;
+       char *result;
+       bool no_worklists = TRUE;
+
+       e = db->query(db,
+                       "SELECT w.rec_final, w.result, e.policy FROM workitems AS w "
+                       "JOIN enforcements AS e ON w.enforcement = e.id WHERE w.id = ?",
+                        DB_INT, session_id, DB_INT, DB_TEXT, DB_INT);
+       if (e)
+       {
+               while (e->enumerate(e, &rec, &result, &policy))
+               {
+                       no_worklists = FALSE;
+
+                       /* insert result */
+                       db->execute(db, NULL,
+                               "INSERT INTO results (session, policy, rec, result) "
+                               "VALUES (?, ?, ?, ?)", DB_INT, session_id, DB_INT, policy,
+                                DB_INT, rec, DB_TEXT, result);
+               }
+               e->destroy(e);
+
+               if (no_worklists)
+               {
+                       return TRUE;
+               }
+       }
        return db->execute(db, NULL,
                                "DELETE FROM workitems WHERE session = ?",
                                DB_UINT, session_id) > 0;
index 5377322..c65de68 100644 (file)
@@ -31,15 +31,6 @@ CREATE INDEX products_name ON products (
   name
 );
 
-DROP TABLE IF EXISTS product_file;
-CREATE TABLE product_file (
-  product INTEGER NOT NULL REFERENCES products(id),
-  file INTEGER NOT NULL REFERENCES files(id),
-  measurement INTEGER DEFAULT 0,
-  metadata INTEGER DEFAULT 0,
-  PRIMARY KEY (product, file)
-);
-
 DROP TABLE IF EXISTS algorithms;
 CREATE TABLE algorithms (
   id INTEGER PRIMARY KEY,
@@ -56,6 +47,49 @@ CREATE TABLE file_hashes (
   hash BLOB NOT NULL
 );
 
+DROP TABLE IF EXISTS groups;
+CREATE TABLE groups (
+  id integer NOT NULL PRIMARY KEY,
+  name varchar(50) NOT NULL UNIQUE
+);
+
+DROP TABLE IF EXISTS group_members;
+CREATE TABLE group_members (
+  id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
+  group_id integer NOT NULL REFERENCES groups(id),
+  device integer NOT NULL REFERENCES devices(id),
+  UNIQUE (group_id, device)
+);
+
+DROP TABLE IF EXISTS default_product_groups;
+CREATE TABLE default_product_groups (
+  id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
+  group_id integer NOT NULL REFERENCES groups(id),
+  product integer NOT NULL REFERENCES products(id),
+  UNIQUE (group_id, product)
+);
+
+DROP TABLE IF EXISTS policies;
+CREATE TABLE policies (
+  id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
+  type integer NOT NULL,
+  name varchar(100) NOT NULL UNIQUE,
+  argument text DEFAULT '' NOT NULL,
+  rec_fail integer NOT NULL,
+  rec_noresult integer NOT NULL,
+  file integer DEFAULT 0 REFERENCES files(id),
+  dir integer DEFAULT 0 REFERENCES directories(id)
+);
+
+DROP TABLE IF EXISTS enforcements;
+CREATE TABLE enforcements (
+  id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
+  policy integer NOT NULL REFERENCES policies(id),
+  group_id integer NOT NULL REFERENCES groups(id),
+  max_age integer NOT NULL,
+  UNIQUE (policy, group_id)
+);
+
 DROP TABLE IF EXISTS sessions;
 CREATE TABLE sessions (
   id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
@@ -69,20 +103,34 @@ CREATE TABLE sessions (
 
 DROP TABLE IF EXISTS workitems;
 CREATE TABLE workitems (
-    id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
-    session integer NOT NULL REFERENCES sessions(id),
-    type integer DEFAULT 0,
-    argument text NOT NULL,
-    rec_fail integer DEFAULT 1,
-    rec_noresult integer DEFAULT 1,
-    rec_final integer DEFAULT 3,
-    result text
+  id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
+  session integer NOT NULL REFERENCES sessions(id),
+  enforcement integer NOT NULL REFERENCES enforcements(id),
+  type integer NOT NULL,
+  argument text NOT NULL,
+  rec_fail integer NOT NULL,
+  rec_noresult integer NOT NULL,
+  rec_final integer DEFAULT 3,
+  result text
 );
 DROP INDEX IF EXISTS workitems_session;
 CREATE INDEX workitems_sessions ON workitems (
   session
 );
 
+DROP TABLE IF EXISTS results;
+CREATE TABLE results (
+  id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
+  session integer NOT NULL REFERENCES measurements(id),
+  policy integer NOT NULL REFERENCES policies(id),
+  rec integer NOT NULL,
+  result text NOT NULL
+);
+DROP INDEX IF EXISTS results_session;
+CREATE INDEX results_session ON results (
+  session
+);
+
 DROP TABLE IF EXISTS components;
 CREATE TABLE components (
   id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
@@ -158,3 +206,4 @@ CREATE TABLE identities (
   value BLOB NOT NULL,
   UNIQUE (type, value)
 );
+
index c0ce805..edffdb3 100644 (file)
@@ -576,6 +576,7 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id, TNC_ConnectionID connection_id)
        imv_os_handshake_state_t handshake_state;
        pa_tnc_attr_t *attr;
        TNC_Result result = TNC_RESULT_SUCCESS;
+       bool no_workitems = TRUE;
        enumerator_t *enumerator;
        u_int received;
 
@@ -620,7 +621,7 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id, TNC_ConnectionID connection_id)
                        }
                        else
                        {
-                               /* just gather information without evaluation */
+                               DBG2(DBG_IMV, "no workitems available - no evaluation possible");
                                state->set_recommendation(state,
                                                                TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
                                                                TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
@@ -665,6 +666,8 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id, TNC_ConnectionID connection_id)
                                {
                                        continue;
                                }
+                               no_workitems = FALSE;
+
                                switch (workitem->get_type(workitem))
                                {
                                        case IMV_WORKITEM_PACKAGES:
@@ -686,6 +689,13 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id, TNC_ConnectionID connection_id)
                        }
                        enumerator->destroy(enumerator);
 
+                       if (no_workitems)
+                       {
+                               DBG2(DBG_IMV, "no workitems generated - no evaluation requested");
+                               state->set_recommendation(state,
+                                                               TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
+                                                               TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
+                       }
                        handshake_state = IMV_OS_STATE_WORKITEMS;
                        os_state->set_handshake_state(os_state, handshake_state);
                }