diff options
Diffstat (limited to 'src/libimcv/imv')
-rwxr-xr-x | src/libimcv/imv/_imv_policy | 39 | ||||
-rw-r--r-- | src/libimcv/imv/data.sql | 846 | ||||
-rw-r--r-- | src/libimcv/imv/imv_agent.c | 38 | ||||
-rw-r--r-- | src/libimcv/imv/imv_agent.h | 1 | ||||
-rw-r--r-- | src/libimcv/imv/imv_agent_if.h | 115 | ||||
-rw-r--r-- | src/libimcv/imv/imv_database.c | 381 | ||||
-rw-r--r-- | src/libimcv/imv/imv_database.h | 125 | ||||
-rw-r--r-- | src/libimcv/imv/imv_if.h | 167 | ||||
-rw-r--r-- | src/libimcv/imv/imv_msg.c | 7 | ||||
-rw-r--r-- | src/libimcv/imv/imv_msg.h | 7 | ||||
-rw-r--r-- | src/libimcv/imv/imv_policy_manager.c | 359 | ||||
-rw-r--r-- | src/libimcv/imv/imv_policy_manager_usage.c | 29 | ||||
-rw-r--r-- | src/libimcv/imv/imv_policy_manager_usage.h | 24 | ||||
-rw-r--r-- | src/libimcv/imv/imv_session.c | 171 | ||||
-rw-r--r-- | src/libimcv/imv/imv_session.h | 113 | ||||
-rw-r--r-- | src/libimcv/imv/imv_state.h | 45 | ||||
-rw-r--r-- | src/libimcv/imv/imv_workitem.c | 213 | ||||
-rw-r--r-- | src/libimcv/imv/imv_workitem.h | 138 | ||||
-rw-r--r-- | src/libimcv/imv/tables.sql | 234 |
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, ¤t)) + { + 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, ¤t)) + { + 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) +); + |