summaryrefslogtreecommitdiff
path: root/src/libimcv/imv
diff options
context:
space:
mode:
Diffstat (limited to 'src/libimcv/imv')
-rwxr-xr-xsrc/libimcv/imv/_imv_policy39
-rw-r--r--src/libimcv/imv/data.sql846
-rw-r--r--src/libimcv/imv/imv_agent.c38
-rw-r--r--src/libimcv/imv/imv_agent.h1
-rw-r--r--src/libimcv/imv/imv_agent_if.h115
-rw-r--r--src/libimcv/imv/imv_database.c381
-rw-r--r--src/libimcv/imv/imv_database.h125
-rw-r--r--src/libimcv/imv/imv_if.h167
-rw-r--r--src/libimcv/imv/imv_msg.c7
-rw-r--r--src/libimcv/imv/imv_msg.h7
-rw-r--r--src/libimcv/imv/imv_policy_manager.c359
-rw-r--r--src/libimcv/imv/imv_policy_manager_usage.c29
-rw-r--r--src/libimcv/imv/imv_policy_manager_usage.h24
-rw-r--r--src/libimcv/imv/imv_session.c171
-rw-r--r--src/libimcv/imv/imv_session.h113
-rw-r--r--src/libimcv/imv/imv_state.h45
-rw-r--r--src/libimcv/imv/imv_workitem.c213
-rw-r--r--src/libimcv/imv/imv_workitem.h138
-rw-r--r--src/libimcv/imv/tables.sql234
19 files changed, 3047 insertions, 5 deletions
diff --git a/src/libimcv/imv/_imv_policy b/src/libimcv/imv/_imv_policy
new file mode 100755
index 000000000..68a963c27
--- /dev/null
+++ b/src/libimcv/imv/_imv_policy
@@ -0,0 +1,39 @@
+#! /bin/sh
+# default TNC policy command script
+#
+# Copyright 2013 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.
+#
+# CAUTION: Installing a new version of strongSwan will install a new
+# copy of this script, wiping out any custom changes you make. If
+# you need changes, make a copy of this under another name, and customize
+# that, and use the "libimcv.policy_script = " option in strongswan.conf
+# to make strongSwan use yours instead of this default one.
+
+# Environment variables that this script gets
+#
+# TNC_SESSION_ID
+# unique session ID used as a reference by the policy
+# manager.
+#
+case "$1" in
+start)
+ echo "start session $TNC_SESSION_ID"
+ ;;
+stop)
+ echo "stop session $TNC_SESSION_ID"
+ ;;
+*) echo "$0: unknown command '$1'"
+ exit 1
+ ;;
+esac
diff --git a/src/libimcv/imv/data.sql b/src/libimcv/imv/data.sql
new file mode 100644
index 000000000..35fd65753
--- /dev/null
+++ b/src/libimcv/imv/data.sql
@@ -0,0 +1,846 @@
+/* Products */
+
+INSERT INTO products ( /* 1 */
+ name
+) VALUES (
+ 'Debian 6.0 i686'
+);
+
+INSERT INTO products ( /* 2 */
+ name
+) VALUES (
+ 'Debian 6.0 x86_64'
+);
+
+INSERT INTO products ( /* 3 */
+ name
+) VALUES (
+ 'Debian 7.0 i686'
+);
+
+INSERT INTO products ( /* 4 */
+ name
+) VALUES (
+ 'Debian 7.0 x86_64'
+);
+
+INSERT INTO products ( /* 5 */
+ name
+) VALUES (
+ 'Debian 8.0 i686'
+);
+
+INSERT INTO products ( /* 6 */
+ name
+) VALUES (
+ 'Debian 8.0 x86_64'
+);
+
+INSERT INTO products ( /* 7 */
+ name
+) VALUES (
+ 'Ubuntu 10.04 i686'
+);
+
+INSERT INTO products ( /* 8 */
+ name
+) VALUES (
+ 'Ubuntu 10.04 x86_64'
+);
+
+INSERT INTO products ( /* 9 */
+ name
+) VALUES (
+ 'Ubuntu 10.10 i686'
+);
+
+INSERT INTO products ( /* 10 */
+ name
+) VALUES (
+ 'Ubuntu 10.10 x86_64'
+);
+
+INSERT INTO products ( /* 11 */
+ name
+) VALUES (
+ 'Ubuntu 11.04 i686'
+);
+
+INSERT INTO products ( /* 12 */
+ name
+) VALUES (
+ 'Ubuntu 11.04 x86_64'
+);
+
+INSERT INTO products ( /* 13 */
+ name
+) VALUES (
+ 'Ubuntu 11.10 i686'
+);
+
+INSERT INTO products ( /* 14 */
+ name
+) VALUES (
+ 'Ubuntu 11.10 x86_64'
+);
+
+INSERT INTO products ( /* 15 */
+ name
+) VALUES (
+ 'Ubuntu 12.04 i686'
+);
+
+INSERT INTO products ( /* 16 */
+ name
+) VALUES (
+ 'Ubuntu 12.04 x86_64'
+);
+
+INSERT INTO products ( /* 17 */
+ name
+) VALUES (
+ 'Ubuntu 12.10 i686'
+);
+
+INSERT INTO products ( /* 18 */
+ name
+) VALUES (
+ 'Ubuntu 12.10 x86_64'
+);
+
+INSERT INTO products ( /* 19 */
+ name
+) VALUES (
+ 'Ubuntu 13.04 i686'
+);
+
+INSERT INTO products ( /* 20 */
+ name
+) VALUES (
+ 'Ubuntu 13.04 x86_64'
+);
+
+INSERT INTO products ( /* 21 */
+ name
+) VALUES (
+ 'Android 4.1.1'
+);
+
+INSERT INTO products ( /* 22 */
+ name
+) VALUES (
+ 'Android 4.2.1'
+);
+
+/* Directories */
+
+INSERT INTO directories ( /* 1 */
+ path
+) VALUES (
+ '/bin'
+);
+
+INSERT INTO directories ( /* 2 */
+ path
+) VALUES (
+ '/etc'
+);
+
+INSERT INTO directories ( /* 3 */
+ path
+) VALUES (
+ '/lib'
+);
+
+INSERT INTO directories ( /* 4 */
+ path
+) VALUES (
+ '/lib/i386-linux-gnu'
+);
+
+INSERT INTO directories ( /* 5 */
+ path
+) VALUES (
+ '/lib/x86_64-linux-gnu'
+);
+
+INSERT INTO directories ( /* 6 */
+ path
+) VALUES (
+ '/lib/xtables'
+);
+
+INSERT INTO directories ( /* 7 */
+ path
+) VALUES (
+ '/sbin'
+);
+
+INSERT INTO directories ( /* 8 */
+ path
+) VALUES (
+ '/usr/bin'
+);
+
+INSERT INTO directories ( /* 9 */
+ path
+) VALUES (
+ '/usr/lib'
+);
+
+INSERT INTO directories ( /* 10 */
+ path
+) VALUES (
+ '/usr/lib/i386-linux-gnu'
+);
+
+INSERT INTO directories ( /* 11 */
+ path
+) VALUES (
+ '/usr/lib/x86_64-linux-gnu'
+);
+
+INSERT INTO directories ( /* 12 */
+ path
+) VALUES (
+ '/usr/sbin'
+);
+
+INSERT INTO directories ( /* 13 */
+ path
+) VALUES (
+ '/system/bin'
+);
+
+INSERT INTO directories ( /* 14 */
+ path
+) VALUES (
+ '/system/lib'
+);
+
+/* Files */
+
+INSERT INTO files ( /* 1 */
+ name, dir
+) VALUES (
+ 'libcrypto.so.1.0.0', 5
+);
+
+INSERT INTO files ( /* 2 */
+ name, dir
+) VALUES (
+ 'libcrypto.so.1.0.0', 11
+);
+
+INSERT INTO files ( /* 3 */
+ name, dir
+) VALUES (
+ 'libssl.so.1.0.0', 5
+);
+
+INSERT INTO files ( /* 4 */
+ name, dir
+) VALUES (
+ 'libssl.so.1.0.0', 11
+);
+
+INSERT INTO files ( /* 5 */
+ name, dir
+) VALUES (
+ 'openssl', 8
+);
+
+INSERT INTO files ( /* 6 */
+ name, dir
+) VALUES (
+ 'tnc_config', 2
+);
+
+/* Algorithms */
+
+INSERT INTO algorithms (
+ id, name
+) VALUES (
+ 65536, 'SHA1-IMA'
+);
+
+INSERT INTO algorithms (
+ id, name
+) VALUES (
+ 32768, 'SHA1'
+);
+
+INSERT INTO algorithms (
+ id, name
+) VALUES (
+ 16384, 'SHA256'
+);
+
+INSERT INTO algorithms (
+ id, name
+) VALUES (
+ 8192, 'SHA384'
+);
+
+/* File Hashes */
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 4, 2, 32768, X'6c6f8e12f6cbfba612e780374c4cdcd40f20968a'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 4, 2, 16384, X'dbcecd19d59310183cf5c31ddee29e8d7bec64d3f9583aad074330a1b3024b07'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 4, 2, 8192, X'197c5385e5853003188833d4f991136c1b0875fa416a60b1159f64e57e457b3184762c884a802a2bda194c058e3bd953'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 4, 4, 32768, X'3ad204f99eb7262efab79cfca02628870ea76361'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 4, 4, 16384, X'3a2170aad92fdd58b55e0e199822bc873cf587b2d1eb1ed7ed8dcea97ae86376'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 4, 4, 8192, X'f778076baa876b5e4b502494a3db081fb09dd870dee6991d54104a74b7e009c58fe261db5ffd13c11e08ef0cefcfa59f'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 4, 5, 32768, X'ecd9c7076cc0572724c7a67db7f19c2831e0445f'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 4, 5, 16384, X'28f3ea5afd34444c8232ea75003131e294a0c9b847de300e4b205d38c1a41305'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 4, 5, 8192, X'51921a8b9322f2d3f06d55002ff40a79da67e70cb563b2a50977642d603dfac2ccbb68b3d32a8bb350769b75d6254208'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 18, 1, 32768, X'd9309b9e45928239d7a7b18711e690792632cce4'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 18, 1, 16384, X'dbfa1856d278d8707c4989b30dd065b4bcd309908f0f2e6e66ff2aa83ff93f59'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 18, 1, 8192, X'fb8d027f03bb5ebb47741ed247eb9e174127b714d20229885feb37e0979aeb14a1b74020cded891d680441093625729c'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 18, 3, 32768, X'3715f2f94016a91fab5bbc503f0f1d43c5a9fc2b'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 18, 3, 16384, X'c03a5296b5decb87b01517f9927a8b2349dfb29ff9f5ba084f994c155ca5d4be'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 18, 3, 8192, X'b8bc345f56115235cc6091f61e312ce43ea54a5b99e7295002ae7b415fd35e06ec4c731ab70ad00d784bb53a318a2fa0'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 18, 5, 32768, X'e59602f4edf24c1b36199588886d06665d4adcd7'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 18, 5, 16384, X'090e1b77bda7fe665e498c6b5e09dbb7ddc5cfe57f213de48f4fb6736484f500'
+);
+
+INSERT INTO file_hashes (
+ product, file, algo, hash
+) VALUES (
+ 18, 5, 8192, X'7cbdb4612a13443dba910ecdef5161f2213e52c9b4a2eef14bcee5d287e9df931cd022e9e9715518ad9c9b6e3384a668'
+);
+
+/* Packages */
+
+INSERT INTO packages ( /* 1 */
+ name
+) VALUES (
+ 'libssl-dev'
+);
+
+INSERT INTO packages ( /* 2 */
+ name
+) VALUES (
+ 'libssl1.0.0'
+);
+
+INSERT INTO packages ( /* 3 */
+ name
+) VALUES (
+ 'libssl1.0.0-dbg'
+);
+
+INSERT INTO packages ( /* 4 */
+ name
+) VALUES (
+ 'openssl'
+);
+
+/* Versions */
+
+INSERT INTO versions (
+ package, product, release, time
+) VALUES (
+ 1, 4, '1.0.1e-2', 1366531494
+);
+
+INSERT INTO versions (
+ package, product, release, time
+) VALUES (
+ 2, 4, '1.0.1e-2', 1366531494
+);
+
+INSERT INTO versions (
+ package, product, release, time
+) VALUES (
+ 3, 4, '1.0.1e-2', 1366531494
+);
+
+INSERT INTO versions (
+ package, product, release, time
+) VALUES (
+ 4, 4, '1.0.1e-2', 1366531494
+);
+
+/* Components */
+
+INSERT INTO components (
+ vendor_id, name, qualifier
+) VALUES (
+ 36906, 1, 33 /* ITA TGRUB */
+);
+
+INSERT INTO components (
+ vendor_id, name, qualifier
+) VALUES (
+ 36906, 2, 33 /* ITA TBOOT */
+);
+
+INSERT INTO components (
+ vendor_id, name, qualifier
+) VALUES (
+ 36906, 3, 33 /* ITA IMA - Trusted Platform */
+);
+
+INSERT INTO components (
+ vendor_id, name, qualifier
+) VALUES (
+ 36906, 3, 34 /* ITA IMA - Operating System */
+);
+
+/* Groups */
+
+INSERT INTO groups ( /* 1 */
+ name
+) VALUES (
+ 'Default'
+);
+
+INSERT INTO groups ( /* 2 */
+ name, parent
+) VALUES (
+ 'Linux', 1
+);
+
+INSERT INTO groups ( /* 3 */
+ name, parent
+) VALUES (
+ 'Android', 1
+);
+
+INSERT INTO groups ( /* 4 */
+ name, parent
+) VALUES (
+ 'Debian i686', 2
+);
+
+INSERT INTO groups ( /* 5 */
+ name, parent
+) VALUES (
+ 'Debian x86_64', 2
+);
+
+INSERT INTO groups ( /* 6 */
+ name, parent
+) VALUES (
+ 'Ubuntu i686', 2
+);
+
+INSERT INTO groups ( /* 7 */
+ name, parent
+) VALUES (
+ 'Ubuntu x86_64', 2
+);
+
+INSERT INTO groups ( /* 8 */
+ name
+) VALUES (
+ 'Reference'
+);
+
+INSERT INTO groups ( /* 9 */
+ name, parent
+) VALUES (
+ 'Ref. Android', 8
+);
+
+INSERT INTO groups ( /* 10 */
+ name, parent
+) VALUES (
+ 'Ref. Linux', 8
+);
+
+/* Default Product Groups */
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 4, 1
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 4, 3
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 4, 5
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 5, 2
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 5, 4
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 5, 6
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 6, 7
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 6, 9
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 6, 11
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 6, 13
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 6, 15
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 6, 17
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 6, 19
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 7, 8
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 7, 10
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 7, 12
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 7, 14
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 7, 16
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 7, 18
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 7, 20
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 3, 21
+);
+
+INSERT INTO groups_product_defaults (
+ group_id, product_id
+) VALUES (
+ 3, 22
+);
+
+/* 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 (
+ 11, 'No Open TCP Ports', 1, 1
+);
+
+INSERT INTO policies ( /* 9 */
+ type, name, argument, rec_fail, rec_noresult
+) VALUES (
+ 13, 'Open UDP Ports', '500 4500 10000-65000', 1, 1
+);
+
+INSERT INTO policies ( /* 10 */
+ type, name, file, rec_fail, rec_noresult
+) VALUES (
+ 7, 'Metadata of /etc/tnc_config', 6, 0, 0
+);
+
+INSERT INTO policies ( /* 11 */
+ type, name, dir, rec_fail, rec_noresult
+) VALUES (
+ 8, 'Get /bin', 1, 0, 0
+);
+
+INSERT INTO policies ( /* 12 */
+ type, name, file, rec_fail, rec_noresult
+) VALUES (
+ 6, 'Measure /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0', 2, 2, 2
+);
+
+INSERT INTO policies ( /* 13 */
+ type, name, file, rec_fail, rec_noresult
+) VALUES (
+ 6, 'Measure /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0', 4, 2, 2
+);
+
+INSERT INTO policies ( /* 14 */
+ type, name, dir, rec_fail, rec_noresult
+) VALUES (
+ 8, 'Get /system/bin', 13, 0, 0
+);
+
+INSERT INTO policies ( /* 15 */
+ type, name, dir, rec_fail, rec_noresult
+) VALUES (
+ 8, 'Get /system/lib', 14, 0, 0
+);
+
+/* Enforcements */
+
+INSERT INTO enforcements (
+ policy, group_id, max_age
+) VALUES (
+ 1, 1, 86400
+);
+
+INSERT INTO enforcements (
+ policy, group_id, max_age
+) VALUES (
+ 2, 3, 0
+);
+
+INSERT INTO enforcements (
+ policy, group_id, max_age
+) VALUES (
+ 3, 2, 0
+);
+
+INSERT INTO enforcements (
+ policy, group_id, max_age
+) VALUES (
+ 5, 7, 86400
+);
+
+INSERT INTO enforcements (
+ policy, group_id, max_age
+) VALUES (
+ 6, 7, 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 (
+ 9, 1, 60
+);
+
+INSERT INTO enforcements (
+ policy, group_id, max_age
+) VALUES (
+ 10, 2, 60
+);
+
+INSERT INTO enforcements (
+ policy, group_id, max_age
+) VALUES (
+ 11, 10, 86400
+);
+
+INSERT INTO enforcements (
+ policy, group_id, max_age
+) VALUES (
+ 12, 5, 86400
+);
+
+INSERT INTO enforcements (
+ policy, group_id, max_age
+) VALUES (
+ 13, 5, 86400
+);
+
+INSERT INTO enforcements (
+ policy, group_id, max_age
+) VALUES (
+ 14, 9, 0
+);
+
+INSERT INTO enforcements (
+ policy, group_id, max_age
+) VALUES (
+ 15, 9, 0
+);
+
diff --git a/src/libimcv/imv/imv_agent.c b/src/libimcv/imv/imv_agent.c
index 879a0103a..435c25a3c 100644
--- a/src/libimcv/imv/imv_agent.c
+++ b/src/libimcv/imv/imv_agent.c
@@ -15,6 +15,8 @@
#include "imcv.h"
#include "imv_agent.h"
+#include "imv_session.h"
+
#include "ietf/ietf_attr_assess_result.h"
#include <tncif_names.h>
@@ -283,6 +285,7 @@ static bool delete_connection(private_imv_agent_t *this, TNC_ConnectionID id)
{
enumerator_t *enumerator;
imv_state_t *state;
+ imv_session_t *session;
bool found = FALSE;
this->connection_lock->write_lock(this->connection_lock);
@@ -292,6 +295,11 @@ static bool delete_connection(private_imv_agent_t *this, TNC_ConnectionID id)
if (id == state->get_connection_id(state))
{
found = TRUE;
+ session = state->get_session(state);
+ if (session)
+ {
+ imcv_db->remove_session(imcv_db, session);
+ }
state->destroy(state);
this->connections->remove_at(this->connections, enumerator);
break;
@@ -402,11 +410,14 @@ METHOD(imv_agent_t, create_state, TNC_Result,
{
TNC_ConnectionID conn_id;
char *tnccs_p = NULL, *tnccs_v = NULL, *t_p = NULL, *t_v = NULL;
- bool has_long = FALSE, has_excl = FALSE, has_soh = FALSE;
+ bool has_long = FALSE, has_excl = FALSE, has_soh = FALSE, first = TRUE;
linked_list_t *ar_identities;
enumerator_t *enumerator;
tncif_identity_t *tnc_id;
+ imv_session_t *session;
u_int32_t max_msg_len;
+ u_int32_t ar_id_type = TNC_ID_UNKNOWN;
+ chunk_t ar_id_value = chunk_empty;
conn_id = state->get_connection_id(state);
if (find_connection(this, conn_id))
@@ -462,10 +473,31 @@ METHOD(imv_agent_t, create_state, TNC_Result,
TNC_Subject_names, tcg_subject_type,
id_value.len, id_value.ptr,
TNC_Authentication_names, tcg_auth_type);
- state->set_ar_id(state, tcg_id_type, id_value);
+
+ if (first)
+ {
+ ar_id_type = tcg_id_type;
+ ar_id_value = id_value;
+ state->set_ar_id(state, ar_id_type, ar_id_value);
+ first = FALSE;
+ }
}
enumerator->destroy(enumerator);
+ if (imcv_db)
+ {
+ session = imcv_db->add_session(imcv_db, conn_id, ar_id_type, ar_id_value);
+ if (session)
+ {
+ DBG2(DBG_IMV, " assigned session ID %d",
+ session->get_session_id(session));
+ state->set_session(state, session);
+ }
+ else
+ {
+ DBG1(DBG_IMV, " no session ID assigned");
+ }
+ }
ar_identities->destroy_offset(ar_identities,
offsetof(tncif_identity_t, destroy));
free(tnccs_p);
@@ -774,7 +806,7 @@ imv_agent_t *imv_agent_create(const char *name,
private_imv_agent_t *this;
/* initialize or increase the reference count */
- if (!libimcv_init())
+ if (!libimcv_init(TRUE))
{
return NULL;
}
diff --git a/src/libimcv/imv/imv_agent.h b/src/libimcv/imv/imv_agent.h
index 6f3d2b4b7..d58af260b 100644
--- a/src/libimcv/imv/imv_agent.h
+++ b/src/libimcv/imv/imv_agent.h
@@ -23,6 +23,7 @@
#define IMV_AGENT_H_
#include "imv_state.h"
+#include "imv_database.h"
#include "pa_tnc/pa_tnc_msg.h"
#include <tncifimv.h>
diff --git a/src/libimcv/imv/imv_agent_if.h b/src/libimcv/imv/imv_agent_if.h
new file mode 100644
index 000000000..db188793a
--- /dev/null
+++ b/src/libimcv/imv/imv_agent_if.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2013 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 imv_agent_if_t imv_agent_if
+ * @{ @ingroup imv_os
+ */
+
+#ifndef IMV_AGENT_IF_H_
+#define IMV_AGENT_IF_H_
+
+#include <tncifimv.h>
+
+#include <library.h>
+
+typedef struct imv_agent_if_t imv_agent_if_t;
+
+/**
+ * IF-IMV interface for IMV agents
+ */
+struct imv_agent_if_t {
+
+ /**
+ * Implements the TNC_IMV_ProvideBindFunction function of the IMV
+ *
+ * @param bind_function Function offered by the TNCS
+ * @return TNC result code
+ */
+ TNC_Result (*bind_functions)(imv_agent_if_t *this,
+ TNC_TNCS_BindFunctionPointer bind_function);
+
+ /**
+ * Implements the TNC_IMV_NotifyConnectionChange() function of the IMV
+ *
+ * @param id Network connection ID assigned by TNCS
+ * @param new_state New connection state to be set
+ * @return TNC result code
+ */
+ TNC_Result (*notify_connection_change)(imv_agent_if_t *this,
+ TNC_ConnectionID id,
+ TNC_ConnectionState new_state);
+
+ /**
+ * Implements the TNC_IMV_ReceiveMessage() function of the IMV
+ *
+ * @param id Network connection ID assigned by TNCS
+ * @param msg_type PA-TNC message type
+ * @param msg Received message
+ * @return TNC result code
+ */
+ TNC_Result (*receive_message)(imv_agent_if_t *this, TNC_ConnectionID id,
+ TNC_MessageType msg_type, chunk_t msg);
+
+ /**
+ * Implements the TNC_IMV_ReceiveMessageLong() function of the IMV
+ *
+ * @param id Network connection ID assigned by TNCS
+ * @param src_imc_id ID of source IMC
+ * @param dst_imv_id ID of destination IMV
+ * @param msg_vid Vendor ID of message type
+ * @param msg_subtype PA-TNC message subtype
+ * @param msg Received message
+ * @return TNC result code
+ */
+ TNC_Result (*receive_message_long)(imv_agent_if_t *this,
+ TNC_ConnectionID id,
+ TNC_UInt32 src_imc_id,
+ TNC_UInt32 dst_imv_id,
+ TNC_VendorID msg_vid,
+ TNC_MessageSubtype msg_subtype,
+ chunk_t msg);
+
+ /**
+ * Implements the TNC_IMV_BatchEnding() function of the IMV
+ *
+ * @param id Network connection ID assigned by TNCS
+ * @return TNC result code
+ */
+ TNC_Result (*batch_ending)(imv_agent_if_t *this, TNC_ConnectionID id);
+
+ /**
+ * Implements the TNC_IMV_SolicitRecommendation() function of the IMV
+ *
+ * @param id Network connection ID assigned by TNCS
+ * @return TNC result code
+ */
+ TNC_Result (*solicit_recommendation)(imv_agent_if_t *this,
+ TNC_ConnectionID id);
+
+ /**
+ * Destroys an imv_agent_if_t object
+ */
+ void (*destroy)(imv_agent_if_t *this);
+
+};
+
+/**
+ * Constructor template
+ */
+typedef imv_agent_if_t* (*imv_agent_create_t)(const char* name, TNC_IMVID id,
+ TNC_Version *actual_version);
+
+#endif /** IMV_AGENT_IF_H_ @}*/
diff --git a/src/libimcv/imv/imv_database.c b/src/libimcv/imv/imv_database.c
new file mode 100644
index 000000000..dc7edd7aa
--- /dev/null
+++ b/src/libimcv/imv/imv_database.c
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+
+#include "imv_database.h"
+
+#include <utils/debug.h>
+#include <threading/mutex.h>
+
+typedef struct private_imv_database_t private_imv_database_t;
+
+/**
+ * Private data of a imv_database_t object.
+ */
+struct private_imv_database_t {
+
+ /**
+ * Public imv_database_t interface.
+ */
+ imv_database_t public;
+
+ /**
+ * database instance
+ */
+ database_t *db;
+
+ /**
+ * policy script
+ */
+ char *script;
+
+ /**
+ * Session list
+ */
+ linked_list_t *sessions;
+
+ /**
+ * mutex used to lock session list
+ */
+ mutex_t *mutex;
+
+};
+
+METHOD(imv_database_t, add_session, imv_session_t*,
+ private_imv_database_t *this, TNC_ConnectionID conn_id,
+ u_int32_t ar_id_type, chunk_t ar_id_value)
+{
+ enumerator_t *enumerator, *e;
+ imv_session_t *current, *session = NULL;
+ int ar_id = 0, session_id;
+ u_int created;
+
+ this->mutex->lock(this->mutex);
+
+ /* check if a session has already been assigned */
+ enumerator = this->sessions->create_enumerator(this->sessions);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (conn_id == current->get_connection_id(current))
+ {
+ session = current;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* session already exists */
+ if (session)
+ {
+ this->mutex->unlock(this->mutex);
+ return session->get_ref(session);
+ }
+
+ if (ar_id_value.len)
+ {
+ /* get primary key of AR identity if it exists */
+ e = this->db->query(this->db,
+ "SELECT id FROM identities WHERE type = ? AND value = ?",
+ DB_INT, ar_id_type, DB_BLOB, ar_id_value, DB_INT);
+ if (e)
+ {
+ e->enumerate(e, &ar_id);
+ e->destroy(e);
+ }
+
+ /* if AR identity has not been found - register it */
+ if (!ar_id)
+ {
+ this->db->execute(this->db, &ar_id,
+ "INSERT INTO identities (type, value) VALUES (?, ?)",
+ DB_INT, ar_id_type, DB_BLOB, ar_id_value);
+ }
+ }
+ /* create a new session entry */
+ created = time(NULL);
+ this->db->execute(this->db, &session_id,
+ "INSERT INTO sessions (time, connection, identity) "
+ "VALUES (?, ?, ?)",
+ DB_UINT, created, DB_INT, conn_id, DB_INT, ar_id);
+ session = imv_session_create(session_id, conn_id);
+ this->sessions->insert_last(this->sessions, session);
+
+ this->mutex->unlock(this->mutex);
+
+ return session;
+}
+
+METHOD(imv_database_t, remove_session, void,
+ private_imv_database_t *this, imv_session_t *session)
+{
+ enumerator_t *enumerator;
+ imv_session_t *current;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->sessions->create_enumerator(this->sessions);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current == session)
+ {
+ this->sessions->remove_at(this->sessions, enumerator);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(imv_database_t, add_product, int,
+ private_imv_database_t *this, imv_session_t *session, char *product)
+{
+ enumerator_t *e;
+ int pid = 0;
+
+ /* get primary key of product info string if it exists */
+ e = this->db->query(this->db,
+ "SELECT id FROM products WHERE name = ?", DB_TEXT, product, DB_INT);
+ if (e)
+ {
+ e->enumerate(e, &pid);
+ e->destroy(e);
+ }
+
+ /* if product info string has not been found - register it */
+ if (!pid)
+ {
+ this->db->execute(this->db, &pid,
+ "INSERT INTO products (name) VALUES (?)", DB_TEXT, product);
+ }
+
+ /* add product reference to session */
+ if (pid)
+ {
+ this->db->execute(this->db, NULL,
+ "UPDATE sessions SET product = ? WHERE id = ?",
+ DB_INT, pid, DB_INT, session->get_session_id(session));
+ }
+
+ return pid;
+}
+
+METHOD(imv_database_t, add_device, int,
+ private_imv_database_t *this, imv_session_t *session, chunk_t device)
+{
+ enumerator_t *e;
+ char *device_str;
+ int pid = 0, did = 0;
+
+ /* get primary key of product from session */
+ e = this->db->query(this->db,
+ "SELECT product FROM sessions WHERE id = ?",
+ DB_INT, session->get_session_id(session), DB_INT);
+ if (e)
+ {
+ e->enumerate(e, &pid);
+ e->destroy(e);
+ }
+
+ /* some IMV policy manager expect a text string */
+ device_str = strndup(device.ptr, device.len);
+
+ /* get primary key of device identification if it exists */
+ e = this->db->query(this->db,
+ "SELECT id FROM devices WHERE value = ? AND product = ?",
+ DB_TEXT, device_str, DB_INT, pid, DB_INT);
+ if (e)
+ {
+ e->enumerate(e, &did);
+ e->destroy(e);
+ }
+
+ /* if device identification has not been found - register it */
+ if (!did)
+ {
+ this->db->execute(this->db, &did,
+ "INSERT INTO devices (value, product) VALUES (?, ?)",
+ DB_TEXT, device_str, DB_INT, pid);
+ }
+ free(device_str);
+
+ /* add device reference to session */
+ if (did)
+ {
+ this->db->execute(this->db, NULL,
+ "UPDATE sessions SET device = ? WHERE id = ?",
+ DB_INT, did, DB_INT, session->get_session_id(session));
+ }
+
+ return did;
+}
+
+METHOD(imv_database_t, add_recommendation, void,
+ private_imv_database_t *this, imv_session_t *session,
+ TNC_IMV_Action_Recommendation rec)
+{
+ /* add final recommendation to session */
+ this->db->execute(this->db, NULL,
+ "UPDATE sessions SET rec = ? WHERE id = ?",
+ DB_INT, rec, DB_INT, session->get_session_id(session));
+}
+
+METHOD(imv_database_t, policy_script, bool,
+ private_imv_database_t *this, imv_session_t *session, bool start)
+{
+ imv_workitem_t *workitem;
+ imv_workitem_type_t type;
+ int id, session_id, arg_int, rec_fail, rec_noresult;
+ enumerator_t *e;
+ char command[512], resp[128], *last, *arg_str;
+ FILE *shell;
+
+ session_id = session->get_session_id(session);
+
+ snprintf(command, sizeof(command), "2>&1 TNC_SESSION_ID='%d' %s %s",
+ session_id, this->script, start ? "start" : "stop");
+ DBG3(DBG_IMV, "running policy script: %s", command);
+
+ shell = popen(command, "r");
+ if (shell == NULL)
+ {
+ DBG1(DBG_IMV, "could not execute policy script '%s'",
+ this->script);
+ return FALSE;
+ }
+ while (TRUE)
+ {
+ if (fgets(resp, sizeof(resp), shell) == NULL)
+ {
+ if (ferror(shell))
+ {
+ DBG1(DBG_IMV, "error reading output from policy script");
+ }
+ break;
+ }
+ else
+ {
+ last = resp + strlen(resp) - 1;
+ if (last >= resp && *last == '\n')
+ {
+ /* replace trailing '\n' */
+ *last = '\0';
+ }
+ DBG1(DBG_IMV, "policy: %s", resp);
+ }
+ }
+ pclose(shell);
+
+ if (start && !session->get_policy_started(session))
+ {
+ /* get workitem list generated by policy manager */
+ e = this->db->query(this->db,
+ "SELECT id, type, arg_str, arg_int, rec_fail, rec_noresult "
+ "FROM workitems WHERE session = ?", DB_INT, session_id,
+ DB_INT, DB_INT, DB_TEXT, DB_INT,DB_INT, DB_INT);
+ if (!e)
+ {
+ DBG1(DBG_IMV, "no workitem enumerator returned");
+ return FALSE;
+ }
+ while (e->enumerate(e, &id, &type, &arg_str, &arg_int, &rec_fail,
+ &rec_noresult))
+ {
+ workitem = imv_workitem_create(id, type, arg_str, arg_int, rec_fail,
+ rec_noresult);
+ session->insert_workitem(session, workitem);
+ }
+ e->destroy(e);
+
+ session->set_policy_started(session, TRUE);
+ }
+ else if (!start && session->get_policy_started(session))
+ {
+ session->set_policy_started(session, FALSE);
+ }
+
+ return TRUE;
+}
+
+METHOD(imv_database_t, finalize_workitem, bool,
+ private_imv_database_t *this, imv_workitem_t *workitem)
+{
+ char *result;
+ int rec;
+
+ rec = workitem->get_result(workitem, &result);
+
+ return this->db->execute(this->db, NULL,
+ "UPDATE workitems SET result = ?, rec_final = ? WHERE id = ?",
+ DB_TEXT, result, DB_INT, rec,
+ DB_INT, workitem->get_id(workitem)) == 1;
+}
+
+METHOD(imv_database_t, get_database, database_t*,
+ private_imv_database_t *this)
+{
+ return this->db;
+}
+
+METHOD(imv_database_t, destroy, void,
+ private_imv_database_t *this)
+{
+ DESTROY_IF(this->db);
+ this->sessions->destroy_offset(this->sessions,
+ offsetof(imv_session_t, destroy));
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/**
+ * See header
+ */
+imv_database_t *imv_database_create(char *uri, char *script)
+{
+ private_imv_database_t *this;
+
+ INIT(this,
+ .public = {
+ .add_session = _add_session,
+ .remove_session = _remove_session,
+ .add_product = _add_product,
+ .add_device = _add_device,
+ .add_recommendation = _add_recommendation,
+ .policy_script = _policy_script,
+ .finalize_workitem = _finalize_workitem,
+ .get_database = _get_database,
+ .destroy = _destroy,
+ },
+ .db = lib->db->create(lib->db, uri),
+ .script = script,
+ .sessions = linked_list_create(),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ );
+
+ if (!this->db)
+ {
+ DBG1(DBG_IMV,
+ "failed to connect to IMV database '%s'", uri);
+ destroy(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/imv/imv_database.h b/src/libimcv/imv/imv_database.h
new file mode 100644
index 000000000..48a3ded9e
--- /dev/null
+++ b/src/libimcv/imv/imv_database.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2013 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 imv_database_t imv_database
+ * @{ @ingroup libimcv_imv
+ */
+
+#ifndef IMV_DATABASE_H_
+#define IMV_DATABASE_H_
+
+#include "imv_session.h"
+#include "imv_workitem.h"
+
+#include <tncifimv.h>
+
+#include <library.h>
+
+typedef struct imv_database_t imv_database_t;
+
+/**
+ * IMV database interface
+ */
+struct imv_database_t {
+
+ /**
+ * Create or get a session associated with a TNCCS connection
+ *
+ * @param conn_id TNCCS Connection ID
+ * @param ar_id_type Access Requestor identity type
+ * @param ar_id_value Access Requestor identity value
+ * @return Session associated with TNCCS Connection
+ */
+ imv_session_t* (*add_session)(imv_database_t *this,
+ TNC_ConnectionID conn_id,
+ u_int32_t ar_id_type, chunk_t ar_id_value);
+
+ /**
+ * Remove and delete a session
+ *
+ * @param session Session
+ */
+ void (*remove_session)(imv_database_t *this, imv_session_t *session);
+
+ /**
+ * Add product information string to a session database entry
+ *
+ * @param session Session
+ * @param product Product information string
+ * @return Product ID
+ */
+ int (*add_product)(imv_database_t *this, imv_session_t *session,
+ char *product);
+
+ /**
+ * Add device identification to a session database entry
+ *
+ * @param session Session
+ * @param device Device identification
+ * @return Device ID
+ */
+ int (*add_device)(imv_database_t *this, imv_session_t *session,
+ chunk_t device);
+
+ /**
+ * Add final recommendation to a session database entry
+ *
+ * @param session Session
+ * @param rec Final recommendation
+ */
+ void (*add_recommendation)(imv_database_t *this, imv_session_t *session,
+ TNC_IMV_Action_Recommendation rec);
+
+ /**
+ * Announce session start/stop to policy script
+ *
+ * @param session Session
+ * @param start TRUE if session start, FALSE if session stop
+ * @return TRUE if command successful, FALSE otherwise
+ */
+ bool (*policy_script)(imv_database_t *this, imv_session_t *session,
+ bool start);
+
+ /**
+ * Finalize a workitem
+ *
+ * @param workitem Workitem to be finalized
+ */
+ bool (*finalize_workitem)(imv_database_t *this, imv_workitem_t *workitem);
+
+ /**
+ * Get database handle
+ *
+ * @return Database handle
+ */
+ database_t* (*get_database)(imv_database_t *this);
+
+ /**
+ * Destroys an imv_database_t object
+ */
+ void (*destroy)(imv_database_t *this);
+};
+
+/**
+ * Create an imv_database_t instance
+ *
+ * @param uri Database uri
+ * @param script Policy Manager script
+ */
+imv_database_t* imv_database_create(char *uri, char *script);
+
+#endif /** IMV_DATABASE_H_ @}*/
diff --git a/src/libimcv/imv/imv_if.h b/src/libimcv/imv/imv_if.h
new file mode 100644
index 000000000..fa9765b11
--- /dev/null
+++ b/src/libimcv/imv/imv_if.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2012-2013 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.
+ */
+
+/**
+ * Define the following two static constants externally:
+ * static const char imv_name[] = "xx";
+ * static const imv_agent_create_t imv_agent_create = imv_xx_agent_create;
+ */
+
+#include <utils/debug.h>
+
+static imv_agent_if_t *imv_agent;
+
+/*
+ * see section 3.8.1 of TCG TNC IF-IMV Specification 1.3
+ */
+TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id,
+ TNC_Version min_version,
+ TNC_Version max_version,
+ TNC_Version *actual_version)
+{
+ if (imv_agent)
+ {
+ DBG1(DBG_IMV, "IMV \"%s\" has already been initialized", imv_name);
+ return TNC_RESULT_ALREADY_INITIALIZED;
+ }
+
+ imv_agent = imv_agent_create(imv_name, imv_id, actual_version);
+
+ if (!imv_agent)
+ {
+ return TNC_RESULT_FATAL;
+ }
+ if (min_version > TNC_IFIMV_VERSION_1 || max_version < TNC_IFIMV_VERSION_1)
+ {
+ DBG1(DBG_IMV, "no common IF-IMV version");
+ return TNC_RESULT_NO_COMMON_VERSION;
+ }
+ return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 3.8.2 of TCG TNC IF-IMV Specification 1.3
+ */
+TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id,
+ TNC_ConnectionState new_state)
+{
+ if (!imv_agent)
+ {
+ DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ return imv_agent->notify_connection_change(imv_agent, connection_id,
+ new_state);
+}
+
+/**
+ * see section 3.8.4 of TCG TNC IF-IMV Specification 1.3
+ */
+TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_MessageType msg_type)
+{
+ if (!imv_agent)
+ {
+ DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ return imv_agent->receive_message(imv_agent, connection_id, msg_type,
+ chunk_create(msg, msg_len));
+}
+
+/**
+ * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
+ */
+TNC_Result TNC_IMV_ReceiveMessageLong(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id,
+ TNC_UInt32 msg_flags,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_VendorID msg_vid,
+ TNC_MessageSubtype msg_subtype,
+ TNC_UInt32 src_imc_id,
+ TNC_UInt32 dst_imv_id)
+{
+ if (!imv_agent)
+ {
+ DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ return imv_agent->receive_message_long(imv_agent, connection_id,
+ src_imc_id, dst_imv_id,
+ msg_vid, msg_subtype, chunk_create(msg, msg_len));
+}
+
+/**
+ * see section 3.8.7 of TCG TNC IF-IMV Specification 1.3
+ */
+TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id)
+{
+
+ if (!imv_agent)
+ {
+ DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ return imv_agent->solicit_recommendation(imv_agent, connection_id);
+}
+
+/**
+ * see section 3.8.8 of TCG TNC IF-IMV Specification 1.3
+ */
+TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id, TNC_ConnectionID connection_id)
+{
+ if (!imv_agent)
+ {
+ DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ return imv_agent->batch_ending(imv_agent, connection_id);
+}
+
+/**
+ * see section 3.8.9 of TCG TNC IF-IMV Specification 1.3
+ */
+TNC_Result TNC_IMV_Terminate(TNC_IMVID imv_id)
+{
+ if (!imv_agent)
+ {
+ DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ imv_agent->destroy(imv_agent);
+ imv_agent = NULL;
+
+ return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 4.2.8.1 of TCG TNC IF-IMV Specification 1.3
+ */
+TNC_Result TNC_IMV_ProvideBindFunction(TNC_IMVID imv_id,
+ TNC_TNCS_BindFunctionPointer bind_function)
+{
+ if (!imv_agent)
+ {
+ DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ return imv_agent->bind_functions(imv_agent, bind_function);
+}
diff --git a/src/libimcv/imv/imv_msg.c b/src/libimcv/imv/imv_msg.c
index 496d0ee1c..642b47935 100644
--- a/src/libimcv/imv/imv_msg.c
+++ b/src/libimcv/imv/imv_msg.c
@@ -318,6 +318,12 @@ METHOD(imv_msg_t, receive, TNC_Result,
return TNC_RESULT_SUCCESS;
}
+METHOD(imv_msg_t, get_attribute_count, int,
+ private_imv_msg_t *this)
+{
+ return this->attr_list->get_count(this->attr_list);
+}
+
METHOD(imv_msg_t, create_attribute_enumerator, enumerator_t*,
private_imv_msg_t *this)
{
@@ -363,6 +369,7 @@ imv_msg_t *imv_msg_create(imv_agent_t *agent, imv_state_t *state,
.send_assessment = _send_assessment,
.receive = _receive,
.add_attribute = _add_attribute,
+ .get_attribute_count = _get_attribute_count,
.create_attribute_enumerator = _create_attribute_enumerator,
.get_encoding = _get_encoding,
.destroy = _destroy,
diff --git a/src/libimcv/imv/imv_msg.h b/src/libimcv/imv/imv_msg.h
index 9e56d9fe7..dfec169cc 100644
--- a/src/libimcv/imv/imv_msg.h
+++ b/src/libimcv/imv/imv_msg.h
@@ -92,6 +92,13 @@ struct imv_msg_t {
void (*add_attribute)(imv_msg_t *this, pa_tnc_attr_t *attr);
/**
+ * Get the number of PA-TNC attributes in the send queue
+ *
+ * @return number of PA-TNC attribute in send queue
+ */
+ int (*get_attribute_count)(imv_msg_t *this);
+
+ /**
* Enumerator over PA-TNC attributes contained in the PA-TNC message
*
* @return PA-TNC attribute enumerator
diff --git a/src/libimcv/imv/imv_policy_manager.c b/src/libimcv/imv/imv_policy_manager.c
new file mode 100644
index 000000000..61e0cd05b
--- /dev/null
+++ b/src/libimcv/imv/imv_policy_manager.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2013 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 "imv_policy_manager_usage.h"
+#include "imv_workitem.h"
+
+#include <library.h>
+#include <utils/debug.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+/* The default policy group #1 is assumed to always exist */
+#define DEFAULT_GROUP_ID 1
+
+/**
+ * global debug output variables
+ */
+static int debug_level = 1;
+static bool stderr_quiet = FALSE;
+
+/**
+ * attest dbg function
+ */
+static void stderr_dbg(debug_t group, level_t level, char *fmt, ...)
+{
+ va_list args;
+
+ if (level <= debug_level)
+ {
+ if (!stderr_quiet)
+ {
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+ }
+ }
+}
+
+/**
+ * Collect all enforcements by iterating up through parent groups
+ */
+static bool iterate_enforcements(database_t *db, int device_id, int session_id,
+ int group_id)
+{
+ int id, type, file, dir, arg_int, parent, policy, max_age;
+ int p_rec_fail, p_rec_noresult, e_rec_fail, e_rec_noresult, latest_rec;
+ bool latest_success;
+ char *argument;
+ time_t now;
+ enumerator_t *e, *e1, *e2;
+
+ now = time(NULL);
+
+ while (group_id)
+ {
+ e1 = db->query(db,
+ "SELECT e.id, p.type, p.argument, p.file, p.dir, p.rec_fail, "
+ "p.rec_noresult, e.policy, e.max_age, e.rec_fail, e.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, DB_INT, DB_INT,
+ DB_INT, DB_INT, DB_INT, DB_INT);
+ if (!e1)
+ {
+ return FALSE;
+ }
+ while (e1->enumerate(e1, &id, &type, &argument, &file, &dir,
+ &p_rec_fail, &p_rec_noresult, &policy, &max_age,
+ &e_rec_fail, &e_rec_noresult))
+ {
+ /* check if the latest measurement of the device was successful */
+ latest_success = FALSE;
+
+ if (device_id)
+ {
+ e2 = db->query(db,
+ "SELECT r.rec FROM results AS r "
+ "JOIN sessions AS s ON s.id = r.session "
+ "WHERE r.policy = ? AND s.device = ? AND s.time > ? "
+ "ORDER BY s.time DESC",
+ DB_INT, policy, DB_INT, device_id,
+ DB_UINT, now - max_age, DB_INT);
+ if (!e2)
+ {
+ e1->destroy(e1);
+ return FALSE;
+ }
+ if (e2->enumerate(e2, &latest_rec) &&
+ latest_rec == TNC_IMV_ACTION_RECOMMENDATION_ALLOW)
+ {
+ latest_success = TRUE;
+ }
+ e2->destroy(e2);
+ }
+
+ if (latest_success)
+ {
+ /*skipping enforcement */
+ printf("skipping enforcment %d\n", id);
+ continue;
+ }
+
+ /* determine arg_int */
+ switch ((imv_workitem_type_t)type)
+ {
+ case IMV_WORKITEM_FILE_REF_MEAS:
+ case IMV_WORKITEM_FILE_MEAS:
+ case IMV_WORKITEM_FILE_META:
+ arg_int = file;
+ break;
+ case IMV_WORKITEM_DIR_REF_MEAS:
+ case IMV_WORKITEM_DIR_MEAS:
+ case IMV_WORKITEM_DIR_META:
+ arg_int = dir;
+ break;
+ default:
+ arg_int = 0;
+ }
+
+ /* insert a workitem */
+ if (db->execute(db, NULL,
+ "INSERT INTO workitems (session, enforcement, type, arg_str, "
+ "arg_int, rec_fail, rec_noresult) VALUES (?, ?, ?, ?, ?, ?, ?)",
+ DB_INT, session_id, DB_INT, id, DB_INT, type, DB_TEXT, argument,
+ DB_INT, arg_int, DB_INT, e_rec_fail ? e_rec_fail : p_rec_fail,
+ DB_INT, e_rec_noresult ? e_rec_noresult : p_rec_noresult) != 1)
+ {
+ e1->destroy(e1);
+ fprintf(stderr, "could not insert workitem\n");
+ return FALSE;
+ }
+ }
+ e1->destroy(e1);
+
+ e = db->query(db,
+ "SELECT parent FROM groups WHERE id = ?",
+ DB_INT, group_id, DB_INT);
+ if (!e)
+ {
+ return FALSE;
+ }
+ if (e->enumerate(e, &parent))
+ {
+ group_id = parent;
+ }
+ else
+ {
+ fprintf(stderr, "group information not found\n");
+ group_id = 0;
+ }
+ e->destroy(e);
+ }
+ return TRUE;
+}
+
+static bool policy_start(database_t *db, int session_id)
+{
+ enumerator_t *e;
+ int device_id, product_id, gid, group_id = DEFAULT_GROUP_ID;
+ u_int created;
+
+ /* get session data */
+ e = db->query(db,
+ "SELECT s.device, s.product, d.created FROM sessions AS s "
+ "LEFT JOIN devices AS d ON s.device = d.id WHERE s.id = ?",
+ DB_INT, session_id, DB_INT, DB_INT, DB_UINT);
+ if (!e || !e->enumerate(e, &device_id, &product_id, &created))
+ {
+ DESTROY_IF(e);
+ fprintf(stderr, "session %d not found\n", session_id);
+ return FALSE;
+ }
+ e->destroy(e);
+
+ /* if a device ID with a creation date exists, get all group memberships */
+ if (device_id & created)
+ {
+ e = db->query(db,
+ "SELECT group_id FROM groups_members WHERE device_id = ?",
+ DB_INT, device_id, DB_INT);
+ if (!e)
+ {
+ return FALSE;
+ }
+ while (e->enumerate(e, &group_id))
+ {
+ if (!iterate_enforcements(db, device_id, session_id, group_id))
+ {
+ e->destroy(e);
+ return FALSE;
+ }
+ }
+ e->destroy(e);
+
+ return TRUE;
+ }
+
+ /* determine if a default product group exists */
+ e = db->query(db,
+ "SELECT group_id FROM groups_product_defaults "
+ "WHERE product_id = ?", DB_INT, product_id, DB_INT);
+ if (!e)
+ {
+ return FALSE;
+ }
+ if (e->enumerate(e, &gid))
+ {
+ group_id = gid;
+ }
+ e->destroy(e);
+
+ if (device_id && !created)
+ {
+ /* assign a newly created device to a default group */
+ if (db->execute(db, NULL,
+ "INSERT INTO groups_members (device_id, group_id) "
+ "VALUES (?, ?)", DB_INT, device_id, DB_INT, group_id) != 1)
+ {
+ fprintf(stderr, "could not assign device to a default group\n");
+ return FALSE;
+ }
+
+ /* set the creation date if it hasn't been set yet */
+ if (db->execute(db, NULL,
+ "UPDATE devices SET created = ? WHERE id = ?",
+ DB_UINT, time(NULL), DB_INT, device_id) != 1)
+ {
+ fprintf(stderr, "creation date of device could not be set\n");
+ return FALSE;
+ }
+ }
+
+ return iterate_enforcements(db, device_id, session_id, group_id);
+}
+
+static bool policy_stop(database_t *db, int session_id)
+{
+ enumerator_t *e;
+ int rec, policy;
+ char *result;
+
+ 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.session = ? AND w.result IS NOT NULL",
+ DB_INT, session_id, DB_INT, DB_TEXT, DB_INT);
+ if (e)
+ {
+ while (e->enumerate(e, &rec, &result, &policy))
+ {
+ 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);
+ }
+ return db->execute(db, NULL,
+ "DELETE FROM workitems WHERE session = ?",
+ DB_UINT, session_id) >= 0;
+}
+
+int main(int argc, char *argv[])
+{
+ database_t *db;
+ char *uri, *tnc_session_id;
+ int session_id;
+ bool start, success;
+
+ /* enable attest debugging hook */
+ dbg = stderr_dbg;
+
+ atexit(library_deinit);
+
+ /* initialize library */
+ if (!library_init(NULL))
+ {
+ exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
+ }
+ if (!lib->plugins->load(lib->plugins,
+ lib->settings->get_str(lib->settings, "imv_policy_manager.load",
+ "sqlite")))
+ {
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+
+ if (argc < 2)
+ {
+ usage();
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+ if (streq(argv[1], "start"))
+ {
+ start = TRUE;
+ }
+ else if (streq(argv[1], "stop"))
+ {
+ start = FALSE;
+ }
+ else
+ {
+ usage();
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+
+ /* get session ID */
+ tnc_session_id = getenv("TNC_SESSION_ID");
+ if (!tnc_session_id)
+ {
+ fprintf(stderr, "environment variable TNC_SESSION_ID is not defined\n");
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+ session_id = atoi(tnc_session_id);
+
+ /* attach IMV database */
+ uri = lib->settings->get_str(lib->settings, "libimcv.database", NULL);
+ if (!uri)
+ {
+ fprintf(stderr, "database uri not defined.\n");
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+
+ db = lib->db->create(lib->db, uri);
+ if (!db)
+ {
+ fprintf(stderr, "opening database failed.\n");
+ exit(SS_RC_INITIALIZATION_FAILED);
+ }
+
+ if (start)
+ {
+ success = policy_start(db, session_id);
+ }
+ else
+ {
+ success = policy_stop(db, session_id);
+ }
+ db->destroy(db);
+
+ fprintf(stderr, "imv_policy_manager %s %s\n", start ? "start" : "stop",
+ success ? "successful" : "failed");
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/src/libimcv/imv/imv_policy_manager_usage.c b/src/libimcv/imv/imv_policy_manager_usage.c
new file mode 100644
index 000000000..3167a5441
--- /dev/null
+++ b/src/libimcv/imv/imv_policy_manager_usage.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2013 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 <stdio.h>
+
+#include "imv_policy_manager_usage.h"
+
+/**
+ * print imv_policy_manager usage info
+ */
+void usage(void)
+{
+ printf("\
+Usage:\n\
+ imv_policy_manager start|stop\n");
+}
+
diff --git a/src/libimcv/imv/imv_policy_manager_usage.h b/src/libimcv/imv/imv_policy_manager_usage.h
new file mode 100644
index 000000000..9c90d40c6
--- /dev/null
+++ b/src/libimcv/imv/imv_policy_manager_usage.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef IMV_POLICY_MANAGER_USAGE_H_
+#define IMV_POLICY_MANAGER_USAGE_H_
+
+/**
+ * print imv_policy_manager usage info
+ */
+void usage(void);
+
+#endif /* IMV_POLICY_MANAGER_USAGE_H_ */
diff --git a/src/libimcv/imv/imv_session.c b/src/libimcv/imv/imv_session.c
new file mode 100644
index 000000000..754f1f74c
--- /dev/null
+++ b/src/libimcv/imv/imv_session.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2013 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 "imv_session.h"
+
+#include <utils/debug.h>
+
+typedef struct private_imv_session_t private_imv_session_t;
+
+/**
+ * Private data of a imv_session_t object.
+ */
+struct private_imv_session_t {
+
+ /**
+ * Public imv_session_t interface.
+ */
+ imv_session_t public;
+
+ /**
+ * Unique Session ID
+ */
+ int session_id;
+
+ /**
+ * TNCCS connection ID
+ */
+ TNC_ConnectionID conn_id;
+
+ /**
+ * Have the workitems been generated?
+ */
+ bool policy_started;
+
+ /**
+ * List of worklist items
+ */
+ linked_list_t *workitems;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+
+};
+
+METHOD(imv_session_t, get_session_id, int,
+ private_imv_session_t *this)
+{
+ return this->session_id;
+}
+
+METHOD(imv_session_t, get_connection_id, TNC_ConnectionID,
+ private_imv_session_t *this)
+{
+ return this->conn_id;
+}
+
+METHOD(imv_session_t, set_policy_started, void,
+ private_imv_session_t *this, bool start)
+{
+ this->policy_started = start;
+}
+
+METHOD(imv_session_t, get_policy_started, bool,
+ private_imv_session_t *this)
+{
+ return this->policy_started;
+}
+
+METHOD(imv_session_t, insert_workitem, void,
+ private_imv_session_t *this, imv_workitem_t *workitem)
+{
+ this->workitems->insert_last(this->workitems, workitem);
+}
+
+METHOD(imv_session_t, remove_workitem, void,
+ private_imv_session_t *this, enumerator_t *enumerator)
+{
+ this->workitems->remove_at(this->workitems, enumerator);
+}
+
+METHOD(imv_session_t, create_workitem_enumerator, enumerator_t*,
+ private_imv_session_t *this)
+{
+ if (!this->policy_started)
+ {
+ return NULL;
+ }
+ return this->workitems->create_enumerator(this->workitems);
+}
+
+METHOD(imv_session_t, get_workitem_count, int,
+ private_imv_session_t *this, TNC_IMVID imv_id)
+{
+ enumerator_t *enumerator;
+ imv_workitem_t *workitem;
+ int count = 0;
+
+ enumerator = this->workitems->create_enumerator(this->workitems);
+ while (enumerator->enumerate(enumerator, &workitem))
+ {
+ if (workitem->get_imv_id(workitem) == imv_id)
+ {
+ count++;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return count;
+}
+
+METHOD(imv_session_t, get_ref, imv_session_t*,
+ private_imv_session_t *this)
+{
+ ref_get(&this->ref);
+
+ return &this->public;
+}
+
+METHOD(imv_session_t, destroy, void,
+ private_imv_session_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ this->workitems->destroy_offset(this->workitems,
+ offsetof(imv_workitem_t, destroy));
+ free(this);
+ }
+}
+
+/**
+ * See header
+ */
+imv_session_t *imv_session_create(int session_id, TNC_ConnectionID conn_id)
+{
+ private_imv_session_t *this;
+
+ INIT(this,
+ .public = {
+ .get_session_id = _get_session_id,
+ .get_connection_id = _get_connection_id,
+ .set_policy_started = _set_policy_started,
+ .get_policy_started = _get_policy_started,
+ .insert_workitem = _insert_workitem,
+ .remove_workitem = _remove_workitem,
+ .create_workitem_enumerator = _create_workitem_enumerator,
+ .get_workitem_count = _get_workitem_count,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .session_id = session_id,
+ .conn_id = conn_id,
+ .workitems = linked_list_create(),
+ .ref = 1,
+ );
+
+ return &this->public;
+}
diff --git a/src/libimcv/imv/imv_session.h b/src/libimcv/imv/imv_session.h
new file mode 100644
index 000000000..6b94523b8
--- /dev/null
+++ b/src/libimcv/imv/imv_session.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2013 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 imv_session_t imv_session
+ * @{ @ingroup libimcv_imv
+ */
+
+#ifndef IMV_SESSION_H_
+#define IMV_SESSION_H_
+
+#include "imv_workitem.h"
+
+#include <tncifimv.h>
+
+#include <library.h>
+
+typedef struct imv_session_t imv_session_t;
+
+/**
+ * IMV session interface
+ */
+struct imv_session_t {
+
+ /**
+ * Get unique session ID
+ *
+ * @return Session ID
+ */
+ int (*get_session_id)(imv_session_t *this);
+
+ /**
+ * Get TNCCS Connection ID
+ *
+ * @return TNCCS Connection ID
+ */
+ TNC_ConnectionID (*get_connection_id)(imv_session_t *this);
+
+ /**
+ * Set policy_started status
+ *
+ * @param start TRUE if policy started, FALSE if policy stopped
+ */
+ void (*set_policy_started)(imv_session_t *this, bool start);
+
+ /**
+ * Get policy_started status
+ *
+ * @return TRUE if policy started, FALSE if policy stopped
+ */
+ bool (*get_policy_started)(imv_session_t *this);
+
+ /**
+ * Insert workitem into list
+ *
+ * @param workitem Workitem to be inserted
+ */
+ void (*insert_workitem)(imv_session_t *this, imv_workitem_t *workitem);
+
+ /**
+ * Remove workitem from list
+ *
+ * @param enumerator Enumerator pointing to workitem to be removed
+ */
+ void (*remove_workitem)(imv_session_t *this, enumerator_t *enumerator);
+
+ /**
+ * Create workitem enumerator
+ *
+ */
+ enumerator_t* (*create_workitem_enumerator)(imv_session_t *this);
+
+ /**
+ * Get number of workitem allocated to a given IMV
+ *
+ * @param imv_id IMV ID
+ * @return Number of workitems assigned to given IMV
+ */
+ int (*get_workitem_count)(imv_session_t *this, TNC_IMVID imv_id);
+
+ /**
+ * Get reference to session
+ */
+ imv_session_t* (*get_ref)(imv_session_t*);
+
+ /**
+ * Destroys an imv_session_t object
+ */
+ void (*destroy)(imv_session_t *this);
+};
+
+/**
+ * Create an imv_session_t instance
+ *
+ * @param session_id Unique Session ID
+ * @param id Associated Connection ID
+ */
+imv_session_t* imv_session_create(int session_id, TNC_ConnectionID id);
+
+#endif /** IMV_SESSION_H_ @}*/
diff --git a/src/libimcv/imv/imv_state.h b/src/libimcv/imv/imv_state.h
index d1a87d2d7..791846bb1 100644
--- a/src/libimcv/imv/imv_state.h
+++ b/src/libimcv/imv/imv_state.h
@@ -22,6 +22,8 @@
#ifndef IMV_STATE_H_
#define IMV_STATE_H_
+#include "imv_session.h"
+
#include <tncifimv.h>
#include <library.h>
@@ -34,9 +36,9 @@ typedef struct imv_state_t imv_state_t;
struct imv_state_t {
/**
- * Get the TNCS connection ID attached to the state
+ * Get the TNCCS connection ID attached to the state
*
- * @return TNCS connection ID of the state
+ * @return TNCCS connection ID of the state
*/
TNC_ConnectionID (*get_connection_id)(imv_state_t *this);
@@ -78,6 +80,20 @@ struct imv_state_t {
u_int32_t (*get_max_msg_len)(imv_state_t *this);
/**
+ * Set flags for completed actions
+ *
+ * @param flags Flags to be set
+ */
+ void (*set_action_flags)(imv_state_t *this, u_int32_t flags);
+
+ /**
+ * Get flags set for completed actions
+ *
+ * @return Flags set for completed actions
+ */
+ u_int32_t (*get_action_flags)(imv_state_t *this);
+
+ /**
* Set Access Requestor ID
*
* @param id_type Access Requestor TCG Standard ID Type
@@ -95,6 +111,20 @@ struct imv_state_t {
chunk_t (*get_ar_id)(imv_state_t *this, u_int32_t *id_type);
/**
+ * Set session associated with TNCCS Connection
+ *
+ * @param session Session associated with TNCCS Connection
+ */
+ void (*set_session)(imv_state_t *this, imv_session_t *session);
+
+ /**
+ * Get session associated with TNCCS Connection
+ *
+ * @return Session associated with TNCCS Connection
+ */
+ imv_session_t* (*get_session)(imv_state_t *this);
+
+ /**
* Change the connection state
*
* @param new_state new connection state
@@ -124,6 +154,17 @@ struct imv_state_t {
TNC_IMV_Evaluation_Result eval);
/**
+ * Update IMV action recommendation and evaluation result
+ *
+ * @param rec IMV action recommendation
+ * @param eval IMV evaluation result
+ *
+ */
+ void (*update_recommendation)(imv_state_t *this,
+ TNC_IMV_Action_Recommendation rec,
+ TNC_IMV_Evaluation_Result eval);
+
+ /**
* Get reason string based on the preferred language
*
* @param language_enumerator language enumerator
diff --git a/src/libimcv/imv/imv_workitem.c b/src/libimcv/imv/imv_workitem.c
new file mode 100644
index 000000000..a61a826bc
--- /dev/null
+++ b/src/libimcv/imv/imv_workitem.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2013 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 "imv_workitem.h"
+
+#include <utils/debug.h>
+#include <tncif_names.h>
+
+typedef struct private_imv_workitem_t private_imv_workitem_t;
+
+ENUM(imv_workitem_type_names, IMV_WORKITEM_PACKAGES, IMV_WORKITEM_UDP_PORT_BLOCK,
+ "PCKGS",
+ "UNSRC",
+ "FWDEN",
+ "PWDEN",
+ "FREFM",
+ "FMEAS",
+ "FMETA",
+ "DREFM",
+ "DMEAS",
+ "DMETA",
+ "TCPOP",
+ "TCPBL",
+ "UDPOP",
+ "UDPBL"
+);
+
+/**
+ * Private data of a imv_workitem_t object.
+ *
+ */
+struct private_imv_workitem_t {
+
+ /**
+ * Public imv_workitem_t interface.
+ */
+ imv_workitem_t public;
+
+ /**
+ * Primary workitem key
+ */
+ int id;
+
+ /**
+ * IMV ID
+ */
+ TNC_IMVID imv_id;
+
+ /**
+ * Workitem type
+ */
+ imv_workitem_type_t type;
+
+ /**
+ * Argument string
+ */
+ char *arg_str;
+
+ /**
+ * Argument integer
+ */
+ int arg_int;
+
+ /**
+ * Result string
+ */
+ char *result;
+
+ /**
+ * IMV action recommendation
+ */
+ TNC_IMV_Action_Recommendation rec_fail;
+
+ /**
+ * IMV action recommendation
+ */
+ TNC_IMV_Action_Recommendation rec_noresult;
+
+ /**
+ * IMV action recommendation
+ */
+ TNC_IMV_Action_Recommendation rec_final;
+
+};
+
+METHOD(imv_workitem_t, get_id, int,
+ private_imv_workitem_t *this)
+{
+ return this->id;
+}
+
+METHOD(imv_workitem_t, set_imv_id, void,
+ private_imv_workitem_t *this, TNC_IMVID imv_id)
+{
+ this->imv_id = imv_id;
+}
+
+METHOD(imv_workitem_t, get_imv_id, TNC_IMVID,
+ private_imv_workitem_t *this)
+{
+ return this->imv_id;
+}
+
+METHOD(imv_workitem_t, get_type, imv_workitem_type_t,
+ private_imv_workitem_t *this)
+{
+ return this->type;
+}
+
+METHOD(imv_workitem_t, get_arg_str, char*,
+ private_imv_workitem_t *this)
+{
+ return this->arg_str;
+}
+
+METHOD(imv_workitem_t, get_arg_int, int,
+ private_imv_workitem_t *this)
+{
+ return this->arg_int;
+}
+
+METHOD(imv_workitem_t, set_result, TNC_IMV_Action_Recommendation,
+ private_imv_workitem_t *this, char *result, TNC_IMV_Evaluation_Result eval)
+{
+ this->result = strdup(result);
+ switch (eval)
+ {
+ case TNC_IMV_EVALUATION_RESULT_COMPLIANT:
+ this->rec_final = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
+ break;
+ case TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR:
+ case TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR:
+ this->rec_final = this->rec_fail;
+ break;
+ case TNC_IMV_EVALUATION_RESULT_ERROR:
+ case TNC_IMV_EVALUATION_RESULT_DONT_KNOW:
+ default:
+ this->rec_final = this->rec_noresult;
+ break;
+ }
+ DBG2(DBG_IMV, "IMV %d handled %N workitem %d: %N%s%s", this->imv_id,
+ imv_workitem_type_names, this->type, this->id,
+ TNC_IMV_Action_Recommendation_names, this->rec_final,
+ strlen(result) ? " - " : "", result);
+
+ return this->rec_final;
+}
+
+METHOD(imv_workitem_t, get_result, TNC_IMV_Action_Recommendation,
+ private_imv_workitem_t *this, char **result)
+{
+ if (result)
+ {
+ *result = this->result;
+ }
+ return this->rec_final;
+}
+
+METHOD(imv_workitem_t, destroy, void,
+ private_imv_workitem_t *this)
+{
+ free(this->arg_str);
+ free(this->result);
+ free(this);
+}
+
+/**
+ * See header
+ */
+imv_workitem_t *imv_workitem_create(int id, imv_workitem_type_t type,
+ char *arg_str, int arg_int,
+ TNC_IMV_Action_Recommendation rec_fail,
+ TNC_IMV_Action_Recommendation rec_noresult)
+{
+ private_imv_workitem_t *this;
+
+ INIT(this,
+ .public = {
+ .get_id = _get_id,
+ .set_imv_id = _set_imv_id,
+ .get_imv_id = _get_imv_id,
+ .get_type = _get_type,
+ .get_arg_str = _get_arg_str,
+ .get_arg_int = _get_arg_int,
+ .set_result = _set_result,
+ .get_result = _get_result,
+ .destroy = _destroy,
+ },
+ .id = id,
+ .imv_id = TNC_IMVID_ANY,
+ .type = type,
+ .arg_str = arg_str ? strdup(arg_str) : NULL,
+ .arg_int = arg_int,
+ .rec_fail = rec_fail,
+ .rec_noresult = rec_noresult,
+ .rec_final = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/imv/imv_workitem.h b/src/libimcv/imv/imv_workitem.h
new file mode 100644
index 000000000..f6ca3ea68
--- /dev/null
+++ b/src/libimcv/imv/imv_workitem.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2013 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 imv_workitem_t imv_workitem
+ * @{ @ingroup libimcv_imv
+ */
+
+#ifndef IMV_WORKITEM_H_
+#define IMV_WORKITEM_H_
+
+#include <tncifimv.h>
+
+#include <library.h>
+
+typedef struct imv_workitem_t imv_workitem_t;
+typedef enum imv_workitem_type_t imv_workitem_type_t;
+
+enum imv_workitem_type_t {
+ IMV_WORKITEM_PACKAGES = 1,
+ IMV_WORKITEM_UNKNOWN_SOURCE = 2,
+ IMV_WORKITEM_FORWARDING = 3,
+ IMV_WORKITEM_DEFAULT_PWD = 4,
+ IMV_WORKITEM_FILE_REF_MEAS = 5,
+ IMV_WORKITEM_FILE_MEAS = 6,
+ IMV_WORKITEM_FILE_META = 7,
+ IMV_WORKITEM_DIR_REF_MEAS = 8,
+ IMV_WORKITEM_DIR_MEAS = 9,
+ IMV_WORKITEM_DIR_META = 10,
+ IMV_WORKITEM_TCP_PORT_OPEN = 11,
+ IMV_WORKITEM_TCP_PORT_BLOCK = 12,
+ IMV_WORKITEM_UDP_PORT_OPEN = 13,
+ IMV_WORKITEM_UDP_PORT_BLOCK = 14
+};
+
+extern enum_name_t *imv_workitem_type_names;
+
+/**
+ * IMV database interface
+ */
+struct imv_workitem_t {
+
+ /**
+ * Get primary workitem key
+ *
+ * @return Primary workitem key
+ */
+ int (*get_id)(imv_workitem_t *this);
+
+ /**
+ * Get workitem type
+ *
+ * @return Workitem type
+ */
+ imv_workitem_type_t (*get_type)(imv_workitem_t *this);
+
+ /**
+ * Set IMV ID
+ *
+ * @param id IMV ID
+ */
+ void (*set_imv_id)(imv_workitem_t *this, TNC_IMVID imv_id);
+
+ /**
+ * Get IMV ID
+ *
+ * @return IMV ID
+ */
+ TNC_IMVID (*get_imv_id)(imv_workitem_t *this);
+
+ /**
+ * Get string argument
+ *
+ * @return Argument string
+ */
+ char* (*get_arg_str)(imv_workitem_t *this);
+
+ /**
+ * Get integer argument
+ *
+ * @return Argument integer
+ */
+ int (*get_arg_int)(imv_workitem_t *this);
+
+ /**
+ * Set result string
+ *
+ * @param result Result string
+ * @param eval Evaluation Result
+ * @return Action Recommendation
+ */
+ TNC_IMV_Action_Recommendation (*set_result)(imv_workitem_t *this,
+ char *result, TNC_IMV_Evaluation_Result eval);
+
+ /**
+ * Set result string
+ *
+ * @param result Result string
+ * @return Action Recommendatino
+ */
+ TNC_IMV_Action_Recommendation (*get_result)(imv_workitem_t *this,
+ char **result);
+
+ /**
+ * Destroys an imv_workitem_t object
+ */
+ void (*destroy)(imv_workitem_t *this);
+};
+
+/**
+ * Create an imv_workitem_t instance
+ *
+ * @param id Primary workitem key
+ * @param type Workitem type
+ * @param arg_str String argument
+ * @param arg_int Integer argument
+ * @param rec_fail Recommendation with minor/major non-compliance case
+ * @param rec_noresult Recommendation in don't know/error case
+ */
+imv_workitem_t *imv_workitem_create(int id, imv_workitem_type_t type,
+ char *arg_str, int arg_int,
+ TNC_IMV_Action_Recommendation rec_fail,
+ TNC_IMV_Action_Recommendation rec_noresult);
+
+#endif /** IMV_WORKITEM_H_ @}*/
diff --git a/src/libimcv/imv/tables.sql b/src/libimcv/imv/tables.sql
new file mode 100644
index 000000000..4cc959e09
--- /dev/null
+++ b/src/libimcv/imv/tables.sql
@@ -0,0 +1,234 @@
+/* IMV PTS SQLite database */
+
+DROP TABLE IF EXISTS directories;
+CREATE TABLE directories (
+ id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ path TEXT NOT NULL
+);
+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 REFERENCES directories(id),
+ 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,
+ name TEXT NOT NULL
+);
+DROP INDEX IF EXISTS products_name;
+CREATE INDEX products_name ON products (
+ name
+);
+
+DROP TABLE IF EXISTS algorithms;
+CREATE TABLE algorithms (
+ id INTEGER PRIMARY KEY,
+ name VARCHAR(20) not NULL
+);
+
+DROP TABLE IF EXISTS file_hashes;
+CREATE TABLE file_hashes (
+ id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ file INTEGER NOT NULL REFERENCES files(id),
+ product INTEGER NOT NULL REFERENCES products(id),
+ device INTEGER DEFAULT 0,
+ key INTEGER DEFAULT 0 REFERENCES keys(id),
+ algo INTEGER NOT NULL REFERENCES algorithms(id),
+ hash BLOB NOT NULL
+);
+
+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
+);
+
+DROP TABLE IF EXISTS groups;
+CREATE TABLE groups (
+ id INTEGER NOT NULL PRIMARY KEY,
+ name VARCHAR(50) NOT NULL UNIQUE,
+ parent INTEGER
+);
+
+DROP TABLE IF EXISTS groups_members;
+CREATE TABLE groups_members (
+ id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ group_id INTEGER NOT NULL REFERENCES groups(id),
+ device_id INTEGER NOT NULL REFERENCES devices(id),
+ UNIQUE (group_id, device_id)
+);
+
+DROP TABLE IF EXISTS groups_product_defaults;
+CREATE TABLE groups_product_defaults (
+ id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ group_id INTEGER NOT NULL REFERENCES groups(id),
+ product_id INTEGER NOT NULL REFERENCES products(id),
+ UNIQUE (group_id, product_id)
+);
+
+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),
+ rec_fail INTEGER,
+ rec_noresult INTEGER,
+ max_age INTEGER NOT NULL,
+ UNIQUE (policy, group_id)
+);
+
+DROP TABLE IF EXISTS sessions;
+CREATE TABLE sessions (
+ id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ time INTEGER NOT NULL,
+ connection INTEGER NOT NULL,
+ identity INTEGER DEFAULT 0 REFERENCES identities(id),
+ device INTEGER DEFAULT 0 REFERENCES devices(id),
+ product INTEGER DEFAULT 0 REFERENCES products(id),
+ rec INTEGER DEFAULT 3
+);
+
+DROP TABLE IF EXISTS workitems;
+CREATE TABLE workitems (
+ 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,
+ arg_str TEXT,
+ arg_int INTEGER DEFAULT 0,
+ rec_fail INTEGER NOT NULL,
+ rec_noresult INTEGER NOT NULL,
+ rec_final INTEGER,
+ 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,
+ vendor_id INTEGER NOT NULL,
+ name INTEGER NOT NULL,
+ qualifier INTEGER DEFAULT 0
+);
+
+
+DROP TABLE IF EXISTS key_component;
+CREATE TABLE key_component (
+ key INTEGER NOT NULL,
+ component INTEGER NOT NULL,
+ depth INTEGER DEFAULT 0,
+ seq_no INTEGER DEFAULT 0,
+ PRIMARY KEY (key, component)
+);
+
+
+DROP TABLE IF EXISTS component_hashes;
+CREATE TABLE component_hashes (
+ component INTEGER NOT NULL,
+ key INTEGER NOT NULL,
+ seq_no INTEGER NOT NULL,
+ pcr INTEGER NOT NULL,
+ algo INTEGER NOT NULL,
+ 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,
+ blacklist INTEGER DEFAULT 0
+);
+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 REFERENCES packages(id),
+ product INTEGER NOT NULL REFERENCES products(id),
+ release TEXT NOT NULL,
+ security INTEGER DEFAULT 0,
+ blacklist INTEGER DEFAULT 0,
+ time INTEGER DEFAULT 0
+);
+DROP INDEX IF EXISTS versions_release;
+CREATE INDEX versions_release ON versions (
+ release
+);
+DROP INDEX IF EXISTS versions_package_product;
+CREATE INDEX versions_package_product ON versions (
+ package, product
+);
+
+DROP TABLE IF EXISTS devices;
+CREATE TABLE devices (
+ id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ description TEXT DEFAULT '',
+ value TEXT NOT NULL,
+ product INTEGER REFERENCES products(id),
+ created INTEGER
+);
+DROP INDEX IF EXISTS devices_id;
+CREATE INDEX devices_value ON devices (
+ value
+);
+
+DROP TABLE IF EXISTS identities;
+CREATE TABLE identities (
+ id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ type INTEGER NOT NULL,
+ value BLOB NOT NULL,
+ UNIQUE (type, value)
+);
+