summaryrefslogtreecommitdiff
path: root/src/libtnccs
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2015-04-11 22:03:59 +0200
committerYves-Alexis Perez <corsac@debian.org>2015-04-11 22:30:17 +0200
commit8404fb0212f9fb77bc53b23004b829b488430700 (patch)
tree23876c7540d138f58a6a7d90793ccf9004f6afd2 /src/libtnccs
parent1b7c683a32c62b6e08ad7bf5af39b9f4edd634f3 (diff)
downloadvyos-strongswan-8404fb0212f9fb77bc53b23004b829b488430700.tar.gz
vyos-strongswan-8404fb0212f9fb77bc53b23004b829b488430700.zip
Imported Upstream version 5.3.0
Diffstat (limited to 'src/libtnccs')
-rw-r--r--src/libtnccs/Android.mk2
-rw-r--r--src/libtnccs/Makefile.in5
-rw-r--r--src/libtnccs/plugins/tnc_imc/Makefile.in5
-rw-r--r--src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.c1
-rw-r--r--src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.h2
-rw-r--r--src/libtnccs/plugins/tnc_imv/Makefile.in5
-rw-r--r--src/libtnccs/plugins/tnc_imv/tnc_imv_plugin.h2
-rw-r--r--src/libtnccs/plugins/tnc_tnccs/Makefile.in5
-rw-r--r--src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.c48
-rw-r--r--src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_plugin.h2
-rw-r--r--src/libtnccs/plugins/tnccs_11/Makefile.in5
-rw-r--r--src/libtnccs/plugins/tnccs_11/tnccs_11.c57
-rw-r--r--src/libtnccs/plugins/tnccs_11/tnccs_11.h15
-rw-r--r--src/libtnccs/plugins/tnccs_11/tnccs_11_plugin.h2
-rw-r--r--src/libtnccs/plugins/tnccs_20/Makefile.am4
-rw-r--r--src/libtnccs/plugins/tnccs_20/Makefile.in39
-rw-r--r--src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c85
-rw-r--r--src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.h30
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ita/pb_mutual_capability_msg.c174
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ita/pb_mutual_capability_msg.h75
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ita/pb_noskip_test_msg.c92
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/ita/pb_noskip_test_msg.h44
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.c22
-rw-r--r--src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.h20
-rw-r--r--src/libtnccs/plugins/tnccs_20/tnccs_20.c945
-rw-r--r--src/libtnccs/plugins/tnccs_20/tnccs_20.h15
-rw-r--r--src/libtnccs/plugins/tnccs_20/tnccs_20_client.c820
-rw-r--r--src/libtnccs/plugins/tnccs_20/tnccs_20_client.h65
-rw-r--r--src/libtnccs/plugins/tnccs_20/tnccs_20_handler.h105
-rw-r--r--src/libtnccs/plugins/tnccs_20/tnccs_20_plugin.h2
-rw-r--r--src/libtnccs/plugins/tnccs_20/tnccs_20_server.c693
-rw-r--r--src/libtnccs/plugins/tnccs_20/tnccs_20_server.h71
-rw-r--r--src/libtnccs/plugins/tnccs_dynamic/Makefile.in5
-rw-r--r--src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.c61
-rw-r--r--src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.h15
-rw-r--r--src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic_plugin.h2
-rw-r--r--src/libtnccs/tnc/imc/imc.h2
-rw-r--r--src/libtnccs/tnc/imv/imv.h2
-rw-r--r--src/libtnccs/tnc/tnc.h7
-rw-r--r--src/libtnccs/tnc/tnccs/tnccs.h30
-rw-r--r--src/libtnccs/tnc/tnccs/tnccs_manager.h15
41 files changed, 2714 insertions, 882 deletions
diff --git a/src/libtnccs/Android.mk b/src/libtnccs/Android.mk
index 68f85c252..e37973202 100644
--- a/src/libtnccs/Android.mk
+++ b/src/libtnccs/Android.mk
@@ -22,7 +22,7 @@ endif
LOCAL_SRC_FILES += $(call add_plugin, tnc-tnccs)
LOCAL_SRC_FILES += $(call add_plugin, tnccs-20)
-LOCAL_SRC_FILES += $(call add_plugin_subdirs, tnccs-20, batch messages messages/ietf messages/tcg state_machine)
+LOCAL_SRC_FILES += $(call add_plugin_subdirs, tnccs-20, batch messages messages/ietf messages/ita messages/tcg state_machine)
ifneq ($(call plugin_enabled, tnccs-20),)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/plugins/tnccs_20/
endif
diff --git a/src/libtnccs/Makefile.in b/src/libtnccs/Makefile.in
index b0bfdf20d..dc8c1b8cc 100644
--- a/src/libtnccs/Makefile.in
+++ b/src/libtnccs/Makefile.in
@@ -283,6 +283,7 @@ DLLIB = @DLLIB@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
@@ -343,10 +344,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
@@ -420,6 +423,8 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
localedir = @localedir@
localstatedir = @localstatedir@
diff --git a/src/libtnccs/plugins/tnc_imc/Makefile.in b/src/libtnccs/plugins/tnc_imc/Makefile.in
index 2b76aabe6..3641bdf5b 100644
--- a/src/libtnccs/plugins/tnc_imc/Makefile.in
+++ b/src/libtnccs/plugins/tnc_imc/Makefile.in
@@ -231,6 +231,7 @@ DLLIB = @DLLIB@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
@@ -291,10 +292,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
@@ -368,6 +371,8 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
localedir = @localedir@
localstatedir = @localstatedir@
diff --git a/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.c b/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.c
index 859dded79..ce5b48133 100644
--- a/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.c
+++ b/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.c
@@ -44,6 +44,7 @@ METHOD(plugin_t, get_features, int,
PLUGIN_CALLBACK(tnc_manager_register, tnc_imc_manager_create),
PLUGIN_PROVIDE(CUSTOM, "imc-manager"),
PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
+ PLUGIN_SDEPEND(CUSTOM, "imv-manager"),
PLUGIN_SDEPEND(CERT_DECODE, CERT_X509),
PLUGIN_SDEPEND(CERT_DECODE, CERT_TRUSTED_PUBKEY),
};
diff --git a/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.h b/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.h
index 8c5521cb2..8cbc70367 100644
--- a/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.h
+++ b/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.h
@@ -15,7 +15,7 @@
/**
* @defgroup tnc_imc tnc_imc
- * @ingroup cplugins
+ * @ingroup tplugins
*
* @defgroup tnc_imc_plugin tnc_imc_plugin
* @{ @ingroup tnc_imc
diff --git a/src/libtnccs/plugins/tnc_imv/Makefile.in b/src/libtnccs/plugins/tnc_imv/Makefile.in
index 06e7b0480..c4b1bee23 100644
--- a/src/libtnccs/plugins/tnc_imv/Makefile.in
+++ b/src/libtnccs/plugins/tnc_imv/Makefile.in
@@ -232,6 +232,7 @@ DLLIB = @DLLIB@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
@@ -292,10 +293,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
@@ -369,6 +372,8 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
localedir = @localedir@
localstatedir = @localstatedir@
diff --git a/src/libtnccs/plugins/tnc_imv/tnc_imv_plugin.h b/src/libtnccs/plugins/tnc_imv/tnc_imv_plugin.h
index afeee2ea2..5786bbaab 100644
--- a/src/libtnccs/plugins/tnc_imv/tnc_imv_plugin.h
+++ b/src/libtnccs/plugins/tnc_imv/tnc_imv_plugin.h
@@ -15,7 +15,7 @@
/**
* @defgroup tnc_imv tnc_imv
- * @ingroup cplugins
+ * @ingroup tplugins
*
* @defgroup tnc_imv_plugin tnc_imv_plugin
* @{ @ingroup tnc_imv
diff --git a/src/libtnccs/plugins/tnc_tnccs/Makefile.in b/src/libtnccs/plugins/tnc_tnccs/Makefile.in
index 8910fe761..5b01e317a 100644
--- a/src/libtnccs/plugins/tnc_tnccs/Makefile.in
+++ b/src/libtnccs/plugins/tnc_tnccs/Makefile.in
@@ -231,6 +231,7 @@ DLLIB = @DLLIB@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
@@ -291,10 +292,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
@@ -368,6 +371,8 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
localedir = @localedir@
localstatedir = @localstatedir@
diff --git a/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.c b/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.c
index b8683f78c..30e505246 100644
--- a/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.c
+++ b/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 Andreas Steffen
+ * Copyright (C) 2010-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -169,8 +169,8 @@ METHOD(tnccs_manager_t, remove_method, void,
METHOD(tnccs_manager_t, create_instance, tnccs_t*,
private_tnc_tnccs_manager_t *this, tnccs_type_t type, bool is_server,
- identification_t *server, identification_t *peer, tnc_ift_type_t transport,
- tnccs_cb_t cb)
+ identification_t *server_id, identification_t *peer_id, host_t *server_ip,
+ host_t *peer_ip, tnc_ift_type_t transport, tnccs_cb_t cb)
{
enumerator_t *enumerator;
tnccs_entry_t *entry;
@@ -182,7 +182,8 @@ METHOD(tnccs_manager_t, create_instance, tnccs_t*,
{
if (type == entry->type)
{
- protocol = entry->constructor(is_server, server, peer, transport, cb);
+ protocol = entry->constructor(is_server, server_id, peer_id,
+ server_ip, peer_ip, transport, cb);
if (protocol)
{
break;
@@ -716,7 +717,8 @@ METHOD(tnccs_manager_t, get_attribute, TNC_Result,
case TNC_ATTRIBUTEID_AR_IDENTITIES:
{
linked_list_t *list;
- identification_t *peer;
+ identification_t *peer_id;
+ host_t *peer_ip;
tnccs_t *tnccs;
tncif_identity_t *tnc_id;
u_int32_t id_type, subject_type;
@@ -726,10 +728,11 @@ METHOD(tnccs_manager_t, get_attribute, TNC_Result,
list = linked_list_create();
tnccs = entry->tnccs;
- peer = tnccs->tls.get_peer_id(&tnccs->tls);
- if (peer)
+
+ peer_id = tnccs->tls.get_peer_id(&tnccs->tls);
+ if (peer_id)
{
- switch (peer->get_type(peer))
+ switch (peer_id->get_type(peer_id))
{
case ID_IPV4_ADDR:
id_type = TNC_ID_IPV4_ADDR;
@@ -756,7 +759,7 @@ METHOD(tnccs_manager_t, get_attribute, TNC_Result,
subject_type = TNC_SUBJECT_UNKNOWN;
}
if (id_type != TNC_ID_UNKNOWN &&
- asprintf(&id_str, "%Y", peer) >= 0)
+ asprintf(&id_str, "%Y", peer_id) >= 0)
{
id_value = chunk_from_str(id_str);
tnc_id = tncif_identity_create(
@@ -767,6 +770,33 @@ METHOD(tnccs_manager_t, get_attribute, TNC_Result,
list->insert_last(list, tnc_id);
}
}
+
+ peer_ip = tnccs->get_peer_ip(tnccs);
+ if (peer_ip)
+ {
+ switch (peer_ip->get_family(peer_ip))
+ {
+ case AF_INET:
+ id_type = TNC_ID_IPV4_ADDR;
+ break;
+ case AF_INET6:
+ id_type = TNC_ID_IPV6_ADDR;
+ break;
+ default:
+ id_type = TNC_ID_UNKNOWN;
+ }
+
+ if (id_type != TNC_ID_UNKNOWN &&
+ asprintf(&id_str, "%H", peer_ip) >= 0)
+ {
+ id_value = chunk_from_str(id_str);
+ tnc_id = tncif_identity_create(
+ pen_type_create(PEN_TCG, id_type), id_value,
+ pen_type_create(PEN_TCG, TNC_SUBJECT_MACHINE),
+ pen_type_create(PEN_TCG, TNC_AUTH_UNKNOWN));
+ list->insert_last(list, tnc_id);
+ }
+ }
result = identity_attribute(buffer_len, buffer, value_len, list);
list->destroy_offset(list, offsetof(tncif_identity_t, destroy));
return result;
diff --git a/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_plugin.h b/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_plugin.h
index f935fa462..c99d5e7c8 100644
--- a/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_plugin.h
+++ b/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_plugin.h
@@ -15,7 +15,7 @@
/**
* @defgroup tnc_tnccs tnc_tnccs
- * @ingroup cplugins
+ * @ingroup tplugins
*
* @defgroup tnc_tnccs_plugin tnc_tnccs_plugin
* @{ @ingroup tnc_tnccs
diff --git a/src/libtnccs/plugins/tnccs_11/Makefile.in b/src/libtnccs/plugins/tnccs_11/Makefile.in
index ea6ac5546..e0c039af9 100644
--- a/src/libtnccs/plugins/tnccs_11/Makefile.in
+++ b/src/libtnccs/plugins/tnccs_11/Makefile.in
@@ -241,6 +241,7 @@ DLLIB = @DLLIB@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
@@ -301,10 +302,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
@@ -378,6 +381,8 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
localedir = @localedir@
localstatedir = @localstatedir@
diff --git a/src/libtnccs/plugins/tnccs_11/tnccs_11.c b/src/libtnccs/plugins/tnccs_11/tnccs_11.c
index 28c5e52b7..0918a2bad 100644
--- a/src/libtnccs/plugins/tnccs_11/tnccs_11.c
+++ b/src/libtnccs/plugins/tnccs_11/tnccs_11.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 Andreas Steffen
+ * Copyright (C) 2010-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -54,12 +54,22 @@ struct private_tnccs_11_t {
/**
* Server identity
*/
- identification_t *server;
+ identification_t *server_id;
/**
* Client identity
*/
- identification_t *peer;
+ identification_t *peer_id;
+
+ /**
+ * Server IP address
+ */
+ host_t *server_ip;
+
+ /**
+ * Client IP address
+ */
+ host_t *peer_ip;
/**
* Underlying TNC IF-T transport protocol
@@ -527,20 +537,20 @@ METHOD(tls_t, is_server, bool,
METHOD(tls_t, get_server_id, identification_t*,
private_tnccs_11_t *this)
{
- return this->server;
+ return this->server_id;
}
METHOD(tls_t, set_peer_id, void,
private_tnccs_11_t *this, identification_t *id)
{
- DESTROY_IF(this->peer);
- this->peer = id->clone(id);
+ DESTROY_IF(this->peer_id);
+ this->peer_id = id->clone(id);
}
METHOD(tls_t, get_peer_id, identification_t*,
private_tnccs_11_t *this)
{
- return this->peer;
+ return this->peer_id;
}
METHOD(tls_t, get_purpose, tls_purpose_t,
@@ -578,14 +588,28 @@ METHOD(tls_t, destroy, void,
{
tnc->tnccs->remove_connection(tnc->tnccs, this->connection_id,
this->is_server);
- this->server->destroy(this->server);
- this->peer->destroy(this->peer);
+ this->server_id->destroy(this->server_id);
+ this->peer_id->destroy(this->peer_id);
+ this->server_ip->destroy(this->server_ip);
+ this->peer_ip->destroy(this->peer_ip);
this->mutex->destroy(this->mutex);
DESTROY_IF(this->batch);
free(this);
}
}
+METHOD(tnccs_t, get_server_ip, host_t*,
+ private_tnccs_11_t *this)
+{
+ return this->server_ip;
+}
+
+METHOD(tnccs_t, get_peer_ip, host_t*,
+ private_tnccs_11_t *this)
+{
+ return this->peer_ip;
+}
+
METHOD(tnccs_t, get_transport, tnc_ift_type_t,
private_tnccs_11_t *this)
{
@@ -628,9 +652,10 @@ METHOD(tnccs_t, get_ref, tnccs_t*,
/**
* See header
*/
-tnccs_t* tnccs_11_create(bool is_server,
- identification_t *server, identification_t *peer,
- tnc_ift_type_t transport, tnccs_cb_t cb)
+tnccs_t* tnccs_11_create(bool is_server, identification_t *server_id,
+ identification_t *peer_id, host_t *server_ip,
+ host_t *peer_ip, tnc_ift_type_t transport,
+ tnccs_cb_t cb)
{
private_tnccs_11_t *this;
@@ -648,6 +673,8 @@ tnccs_t* tnccs_11_create(bool is_server,
.get_eap_msk = _get_eap_msk,
.destroy = _destroy,
},
+ .get_server_ip = _get_server_ip,
+ .get_peer_ip = _get_peer_ip,
.get_transport = _get_transport,
.set_transport = _set_transport,
.get_auth_type = _get_auth_type,
@@ -656,8 +683,10 @@ tnccs_t* tnccs_11_create(bool is_server,
.get_ref = _get_ref,
},
.is_server = is_server,
- .server = server->clone(server),
- .peer = peer->clone(peer),
+ .server_id = server_id->clone(server_id),
+ .peer_id = peer_id->clone(peer_id),
+ .server_ip = server_ip->clone(server_ip),
+ .peer_ip = peer_ip->clone(peer_ip),
.transport = transport,
.callback = cb,
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
diff --git a/src/libtnccs/plugins/tnccs_11/tnccs_11.h b/src/libtnccs/plugins/tnccs_11/tnccs_11.h
index e805df8bb..60d5518bc 100644
--- a/src/libtnccs/plugins/tnccs_11/tnccs_11.h
+++ b/src/libtnccs/plugins/tnccs_11/tnccs_11.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 Andreas Steffen
+ * Copyright (C) 2010-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -29,14 +29,17 @@
* Create an instance of the TNC IF-TNCCS 1.1 protocol handler.
*
* @param is_server TRUE to act as TNC Server, FALSE for TNC Client
- * @param server Server identity
- * @param peer Client identity
+ * @param server_id Server identity
+ * @param peer_id Client identity
+ * @param server_ip Server IP address
+ * @param peer_ip Client IP address
* @param transport Underlying IF-T transport protocol
* @param cb Callback function if TNC Server, NULL if TNC Client
* @return TNC_IF_TNCCS 1.1 protocol stack
*/
-tnccs_t* tnccs_11_create(bool is_server,
- identification_t *server, identification_t *peer,
- tnc_ift_type_t transport, tnccs_cb_t cb);
+tnccs_t* tnccs_11_create(bool is_server, identification_t *server_id,
+ identification_t *peer_id, host_t *server_ip,
+ host_t *peer_ip, tnc_ift_type_t transport,
+ tnccs_cb_t cb);
#endif /** TNCCS_11_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_11/tnccs_11_plugin.h b/src/libtnccs/plugins/tnccs_11/tnccs_11_plugin.h
index 619a073ad..73ea5759b 100644
--- a/src/libtnccs/plugins/tnccs_11/tnccs_11_plugin.h
+++ b/src/libtnccs/plugins/tnccs_11/tnccs_11_plugin.h
@@ -15,7 +15,7 @@
/**
* @defgroup tnccs_11 tnccs_11
- * @ingroup cplugins
+ * @ingroup tplugins
*
* @defgroup tnccs_11_plugin tnccs_11_plugin
* @{ @ingroup tnccs_11
diff --git a/src/libtnccs/plugins/tnccs_20/Makefile.am b/src/libtnccs/plugins/tnccs_20/Makefile.am
index 2aefecd26..7d1cdded1 100644
--- a/src/libtnccs/plugins/tnccs_20/Makefile.am
+++ b/src/libtnccs/plugins/tnccs_20/Makefile.am
@@ -18,6 +18,8 @@ endif
libstrongswan_tnccs_20_la_SOURCES = \
tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c \
+ tnccs_20_handler.h \
+ tnccs_20_server.h tnccs_20_server.c tnccs_20_client.h tnccs_20_client.c \
batch/pb_tnc_batch.h batch/pb_tnc_batch.c \
messages/pb_tnc_msg.h messages/pb_tnc_msg.c \
messages/ietf/pb_experimental_msg.h messages/ietf/pb_experimental_msg.c \
@@ -28,6 +30,8 @@ libstrongswan_tnccs_20_la_SOURCES = \
messages/ietf/pb_language_preference_msg.h messages/ietf/pb_language_preference_msg.c \
messages/ietf/pb_reason_string_msg.h messages/ietf/pb_reason_string_msg.c \
messages/ietf/pb_remediation_parameters_msg.h messages/ietf/pb_remediation_parameters_msg.c \
+ messages/ita/pb_mutual_capability_msg.h messages/ita/pb_mutual_capability_msg.c \
+ messages/ita/pb_noskip_test_msg.h messages/ita/pb_noskip_test_msg.c \
messages/tcg/pb_pdp_referral_msg.h messages/tcg/pb_pdp_referral_msg.c \
state_machine/pb_tnc_state_machine.h state_machine/pb_tnc_state_machine.c
diff --git a/src/libtnccs/plugins/tnccs_20/Makefile.in b/src/libtnccs/plugins/tnccs_20/Makefile.in
index 90c804710..17d997f76 100644
--- a/src/libtnccs/plugins/tnccs_20/Makefile.in
+++ b/src/libtnccs/plugins/tnccs_20/Makefile.in
@@ -132,8 +132,8 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la
am__dirstamp = $(am__leading_dot)dirstamp
am_libstrongswan_tnccs_20_la_OBJECTS = tnccs_20_plugin.lo tnccs_20.lo \
- batch/pb_tnc_batch.lo messages/pb_tnc_msg.lo \
- messages/ietf/pb_experimental_msg.lo \
+ tnccs_20_server.lo tnccs_20_client.lo batch/pb_tnc_batch.lo \
+ messages/pb_tnc_msg.lo messages/ietf/pb_experimental_msg.lo \
messages/ietf/pb_pa_msg.lo \
messages/ietf/pb_assessment_result_msg.lo \
messages/ietf/pb_access_recommendation_msg.lo \
@@ -141,6 +141,8 @@ am_libstrongswan_tnccs_20_la_OBJECTS = tnccs_20_plugin.lo tnccs_20.lo \
messages/ietf/pb_language_preference_msg.lo \
messages/ietf/pb_reason_string_msg.lo \
messages/ietf/pb_remediation_parameters_msg.lo \
+ messages/ita/pb_mutual_capability_msg.lo \
+ messages/ita/pb_noskip_test_msg.lo \
messages/tcg/pb_pdp_referral_msg.lo \
state_machine/pb_tnc_state_machine.lo
libstrongswan_tnccs_20_la_OBJECTS = \
@@ -242,6 +244,7 @@ DLLIB = @DLLIB@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
@@ -302,10 +305,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
@@ -379,6 +384,8 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
localedir = @localedir@
localstatedir = @localstatedir@
@@ -454,6 +461,8 @@ AM_CFLAGS = \
libstrongswan_tnccs_20_la_SOURCES = \
tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c \
+ tnccs_20_handler.h \
+ tnccs_20_server.h tnccs_20_server.c tnccs_20_client.h tnccs_20_client.c \
batch/pb_tnc_batch.h batch/pb_tnc_batch.c \
messages/pb_tnc_msg.h messages/pb_tnc_msg.c \
messages/ietf/pb_experimental_msg.h messages/ietf/pb_experimental_msg.c \
@@ -464,6 +473,8 @@ libstrongswan_tnccs_20_la_SOURCES = \
messages/ietf/pb_language_preference_msg.h messages/ietf/pb_language_preference_msg.c \
messages/ietf/pb_reason_string_msg.h messages/ietf/pb_reason_string_msg.c \
messages/ietf/pb_remediation_parameters_msg.h messages/ietf/pb_remediation_parameters_msg.c \
+ messages/ita/pb_mutual_capability_msg.h messages/ita/pb_mutual_capability_msg.c \
+ messages/ita/pb_noskip_test_msg.h messages/ita/pb_noskip_test_msg.c \
messages/tcg/pb_pdp_referral_msg.h messages/tcg/pb_pdp_referral_msg.c \
state_machine/pb_tnc_state_machine.h state_machine/pb_tnc_state_machine.c
@@ -590,6 +601,17 @@ messages/ietf/pb_reason_string_msg.lo: messages/ietf/$(am__dirstamp) \
messages/ietf/pb_remediation_parameters_msg.lo: \
messages/ietf/$(am__dirstamp) \
messages/ietf/$(DEPDIR)/$(am__dirstamp)
+messages/ita/$(am__dirstamp):
+ @$(MKDIR_P) messages/ita
+ @: > messages/ita/$(am__dirstamp)
+messages/ita/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) messages/ita/$(DEPDIR)
+ @: > messages/ita/$(DEPDIR)/$(am__dirstamp)
+messages/ita/pb_mutual_capability_msg.lo: \
+ messages/ita/$(am__dirstamp) \
+ messages/ita/$(DEPDIR)/$(am__dirstamp)
+messages/ita/pb_noskip_test_msg.lo: messages/ita/$(am__dirstamp) \
+ messages/ita/$(DEPDIR)/$(am__dirstamp)
messages/tcg/$(am__dirstamp):
@$(MKDIR_P) messages/tcg
@: > messages/tcg/$(am__dirstamp)
@@ -618,6 +640,8 @@ mostlyclean-compile:
-rm -f messages/*.lo
-rm -f messages/ietf/*.$(OBJEXT)
-rm -f messages/ietf/*.lo
+ -rm -f messages/ita/*.$(OBJEXT)
+ -rm -f messages/ita/*.lo
-rm -f messages/tcg/*.$(OBJEXT)
-rm -f messages/tcg/*.lo
-rm -f state_machine/*.$(OBJEXT)
@@ -627,7 +651,9 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_20.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_20_client.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_20_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnccs_20_server.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@batch/$(DEPDIR)/pb_tnc_batch.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@messages/$(DEPDIR)/pb_tnc_msg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@messages/ietf/$(DEPDIR)/pb_access_recommendation_msg.Plo@am__quote@
@@ -638,6 +664,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@messages/ietf/$(DEPDIR)/pb_pa_msg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@messages/ietf/$(DEPDIR)/pb_reason_string_msg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@messages/ietf/$(DEPDIR)/pb_remediation_parameters_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/ita/$(DEPDIR)/pb_mutual_capability_msg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@messages/ita/$(DEPDIR)/pb_noskip_test_msg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@messages/tcg/$(DEPDIR)/pb_pdp_referral_msg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@state_machine/$(DEPDIR)/pb_tnc_state_machine.Plo@am__quote@
@@ -673,6 +701,7 @@ clean-libtool:
-rm -rf batch/.libs batch/_libs
-rm -rf messages/.libs messages/_libs
-rm -rf messages/ietf/.libs messages/ietf/_libs
+ -rm -rf messages/ita/.libs messages/ita/_libs
-rm -rf messages/tcg/.libs messages/tcg/_libs
-rm -rf state_machine/.libs state_machine/_libs
@@ -797,6 +826,8 @@ distclean-generic:
-rm -f messages/$(am__dirstamp)
-rm -f messages/ietf/$(DEPDIR)/$(am__dirstamp)
-rm -f messages/ietf/$(am__dirstamp)
+ -rm -f messages/ita/$(DEPDIR)/$(am__dirstamp)
+ -rm -f messages/ita/$(am__dirstamp)
-rm -f messages/tcg/$(DEPDIR)/$(am__dirstamp)
-rm -f messages/tcg/$(am__dirstamp)
-rm -f state_machine/$(DEPDIR)/$(am__dirstamp)
@@ -811,7 +842,7 @@ clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
clean-pluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
- -rm -rf ./$(DEPDIR) batch/$(DEPDIR) messages/$(DEPDIR) messages/ietf/$(DEPDIR) messages/tcg/$(DEPDIR) state_machine/$(DEPDIR)
+ -rm -rf ./$(DEPDIR) batch/$(DEPDIR) messages/$(DEPDIR) messages/ietf/$(DEPDIR) messages/ita/$(DEPDIR) messages/tcg/$(DEPDIR) state_machine/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@@ -857,7 +888,7 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR) batch/$(DEPDIR) messages/$(DEPDIR) messages/ietf/$(DEPDIR) messages/tcg/$(DEPDIR) state_machine/$(DEPDIR)
+ -rm -rf ./$(DEPDIR) batch/$(DEPDIR) messages/$(DEPDIR) messages/ietf/$(DEPDIR) messages/ita/$(DEPDIR) messages/tcg/$(DEPDIR) state_machine/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c b/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c
index 228c08255..faad02b9b 100644
--- a/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c
+++ b/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Sansar Choinyanbuu
- * Copyright (C) 2010-2012 Andreas Steffen
+ * Copyright (C) 2010-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -85,7 +85,7 @@ struct private_pb_tnc_batch_t {
pb_tnc_batch_t public;
/**
- * TNCC if TRUE, TNCS if FALSE
+ * from TNC server if TRUE, from TNC client if FALSE
*/
bool is_server;
@@ -166,6 +166,9 @@ METHOD(pb_tnc_batch_t, add_msg, bool,
case PEN_TCG:
msg_type_names = pb_tnc_tcg_msg_type_names;
break;
+ case PEN_ITA:
+ msg_type_names = pb_tnc_ita_msg_type_names;
+ break;
}
DBG2(DBG_TNC, "adding %N/%N message", pen_names, msg_type.vendor_id,
msg_type_names, msg_type.type);
@@ -176,6 +179,7 @@ METHOD(pb_tnc_batch_t, add_msg, bool,
METHOD(pb_tnc_batch_t, build, void,
private_pb_tnc_batch_t *this)
{
+ u_int8_t version;
u_int32_t msg_len;
chunk_t msg_value;
enumerator_t *enumerator;
@@ -184,9 +188,14 @@ METHOD(pb_tnc_batch_t, build, void,
pb_tnc_msg_info_t *msg_infos;
bio_writer_t *writer;
+ /* Set wrong PB-TNC version for testing purposes to force a PB-TNC error */
+ version = lib->settings->get_int(lib->settings,
+ "%s.plugins.tnccs-20.tests.pb_tnc_version",
+ PB_TNC_VERSION, lib->ns);
+
/* build PB-TNC batch header */
writer = bio_writer_create(this->batch_len);
- writer->write_uint8 (writer, PB_TNC_VERSION);
+ writer->write_uint8 (writer, version);
writer->write_uint8 (writer, this->is_server ?
PB_TNC_BATCH_FLAG_D : PB_TNC_BATCH_FLAG_NONE);
writer->write_uint16(writer, this->type);
@@ -211,6 +220,9 @@ METHOD(pb_tnc_batch_t, build, void,
case PEN_TCG:
msg_infos = pb_tnc_tcg_msg_infos;
break;
+ case PEN_ITA:
+ msg_infos = pb_tnc_ita_msg_infos;
+ break;
}
if (msg_infos[msg_type.type].has_noskip_flag)
{
@@ -228,15 +240,15 @@ METHOD(pb_tnc_batch_t, build, void,
writer->destroy(writer);
}
-static status_t process_batch_header(private_pb_tnc_batch_t *this,
- pb_tnc_state_machine_t *state_machine)
+METHOD(pb_tnc_batch_t, process_header, status_t,
+ private_pb_tnc_batch_t *this, bool directionality, bool is_server,
+ bool *from_server)
{
bio_reader_t *reader;
pb_tnc_msg_t *msg;
pb_error_msg_t *err_msg;
u_int8_t version, flags, reserved, type;
u_int32_t batch_len;
- bool directionality;
if (this->encoding.len < PB_TNC_BATCH_HEADER_SIZE)
{
@@ -267,13 +279,14 @@ static status_t process_batch_header(private_pb_tnc_batch_t *this,
}
/* Directionality */
- directionality = (flags & PB_TNC_BATCH_FLAG_D) != PB_TNC_BATCH_FLAG_NONE;
- if (directionality == this->is_server)
+ *from_server = (flags & PB_TNC_BATCH_FLAG_D) != PB_TNC_BATCH_FLAG_NONE;
+
+ if (directionality & (*from_server == is_server))
{
DBG1(DBG_TNC, "wrong Directionality: batch is from a PB %s",
- directionality ? "server" : "client");
+ is_server ? "server" : "client");
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
- PB_ERROR_INVALID_PARAMETER, 1);
+ PB_ERROR_INVALID_PARAMETER, 1);
goto fatal;
}
@@ -287,17 +300,6 @@ static status_t process_batch_header(private_pb_tnc_batch_t *this,
goto fatal;
}
- if (!state_machine->receive_batch(state_machine, this->type))
- {
- DBG1(DBG_TNC, "unexpected PB-TNC batch type: %N",
- pb_tnc_batch_type_names, this->type);
- msg = pb_error_msg_create(TRUE, PEN_IETF,
- PB_ERROR_UNEXPECTED_BATCH_TYPE);
- goto fatal;
- }
- DBG1(DBG_TNC, "processing PB-TNC %N batch", pb_tnc_batch_type_names,
- this->type);
-
/* Batch Length */
if (this->encoding.len != batch_len)
{
@@ -310,12 +312,6 @@ static status_t process_batch_header(private_pb_tnc_batch_t *this,
this->offset = PB_TNC_BATCH_HEADER_SIZE;
- /* Register an empty CDATA batch with the state machine */
- if (this->type == PB_BATCH_CDATA)
- {
- state_machine->set_empty_cdata(state_machine,
- this->offset == this->encoding.len);
- }
return SUCCESS;
fatal:
@@ -395,11 +391,18 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this)
msg_type_names = pb_tnc_msg_type_names;
msg_infos = pb_tnc_msg_infos;
}
- else if (vendor_id == PEN_TCG && msg_type <= PB_TCG_MSG_ROOF)
+ else if (vendor_id == PEN_TCG && msg_type <= PB_TCG_MSG_ROOF &&
+ msg_type > PB_TCG_MSG_RESERVED)
{
msg_type_names = pb_tnc_tcg_msg_type_names;
msg_infos = pb_tnc_tcg_msg_infos;
}
+ else if (vendor_id == PEN_ITA && msg_type <= PB_ITA_MSG_ROOF &&
+ msg_type > PB_ITA_MSG_NOSKIP_TEST)
+ {
+ msg_type_names = pb_tnc_ita_msg_type_names;
+ msg_infos = pb_tnc_ita_msg_infos;
+ }
else
{
if (msg_len < PB_TNC_MSG_HEADER_SIZE)
@@ -413,7 +416,7 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this)
if (noskip_flag)
{
- DBG1(DBG_TNC, "reject PB-TNC message 0x%06x/0x%08x)",
+ DBG1(DBG_TNC, "reject PB-TNC message (0x%06x/0x%08x)",
vendor_id, msg_type);
msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
PB_ERROR_UNSUPPORTED_MANDATORY_MSG, this->offset);
@@ -421,7 +424,7 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this)
}
else
{
- DBG1(DBG_TNC, "ignore PB-TNC message 0x%06x/0x%08x)",
+ DBG1(DBG_TNC, "ignore PB-TNC message (0x%06x/0x%08x)",
vendor_id, msg_type);
this->offset += msg_len;
return SUCCESS;
@@ -502,14 +505,26 @@ fatal:
METHOD(pb_tnc_batch_t, process, status_t,
private_pb_tnc_batch_t *this, pb_tnc_state_machine_t *state_machine)
{
- status_t status;
+ pb_tnc_msg_t *msg;
+ status_t status = SUCCESS;
- status = process_batch_header(this, state_machine);
- if (status != SUCCESS)
+ if (!state_machine->receive_batch(state_machine, this->type))
{
+ DBG1(DBG_TNC, "unexpected PB-TNC batch type: %N",
+ pb_tnc_batch_type_names, this->type);
+ msg = pb_error_msg_create(TRUE, PEN_IETF,
+ PB_ERROR_UNEXPECTED_BATCH_TYPE);
+ this->errors->insert_last(this->errors, msg);
return FAILED;
}
+ /* Register an empty CDATA batch with the state machine */
+ if (this->type == PB_BATCH_CDATA)
+ {
+ state_machine->set_empty_cdata(state_machine,
+ this->offset == this->encoding.len);
+ }
+
while (this->offset < this->encoding.len)
{
switch (process_tnc_msg(this))
@@ -585,7 +600,7 @@ pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type,
/**
* See header
*/
-pb_tnc_batch_t* pb_tnc_batch_create_from_data(bool is_server, chunk_t data)
+pb_tnc_batch_t* pb_tnc_batch_create_from_data(chunk_t data)
{
private_pb_tnc_batch_t *this;
@@ -595,12 +610,12 @@ pb_tnc_batch_t* pb_tnc_batch_create_from_data(bool is_server, chunk_t data)
.get_encoding = _get_encoding,
.add_msg = _add_msg,
.build = _build,
+ .process_header = _process_header,
.process = _process,
.create_msg_enumerator = _create_msg_enumerator,
.create_error_enumerator = _create_error_enumerator,
.destroy = _destroy,
},
- .is_server = is_server,
.messages = linked_list_create(),
.errors = linked_list_create(),
.encoding = chunk_clone(data),
diff --git a/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.h b/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.h
index 106c5578c..6089c7d2e 100644
--- a/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.h
+++ b/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2012 Andreas Steffen
+ * Copyright (C) 2010-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -84,10 +84,21 @@ struct pb_tnc_batch_t {
void (*build)(pb_tnc_batch_t *this);
/**
+ * Process the PB-TNC Batch header
+ *
+ * @param directionality TRUE if no mutual TNC measurements
+ * @param is_server TRUE if called by TNC server
+ * @param from_server TRUE if sent by TNC server
+ * @return return processing status
+ */
+ status_t (*process_header)(pb_tnc_batch_t *this, bool directionality,
+ bool is_server, bool *from_server);
+
+ /**
* Process the PB-TNC Batch
*
- * @param PB-TNC state machine
- * @return return processing status
+ * @param state_machine PB-TNC state machine
+ * @return return processing status
*/
status_t (*process)(pb_tnc_batch_t *this,
pb_tnc_state_machine_t *state_machine);
@@ -95,14 +106,14 @@ struct pb_tnc_batch_t {
/**
* Enumerates over all PB-TNC Messages
*
- * @return return message enumerator
+ * @return return message enumerator
*/
enumerator_t* (*create_msg_enumerator)(pb_tnc_batch_t *this);
/**
* Enumerates over all parsing errors
*
- * @return return error enumerator
+ * @return return error enumerator
*/
enumerator_t* (*create_error_enumerator)(pb_tnc_batch_t *this);
@@ -115,9 +126,9 @@ struct pb_tnc_batch_t {
/**
* Create an empty PB-TNC Batch of a given type
*
- * @param is_server TRUE if server, FALSE if client
- * @param type PB-TNC batch type
- * @param max_batch_len maximum size the PB-TNC batch
+ * @param is_server TRUE if server, FALSE if client
+ * @param type PB-TNC batch type
+ * @param max_batch_len maximum size the PB-TNC batch
*/
pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type,
size_t max_batch_len);
@@ -125,9 +136,8 @@ pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type,
/**
* Create an unprocessed PB-TNC Batch from data
*
- * @param is_server TRUE if server, FALSE if client
* @param data encoded PB-TNC batch
*/
-pb_tnc_batch_t* pb_tnc_batch_create_from_data(bool is_server, chunk_t data);
+pb_tnc_batch_t* pb_tnc_batch_create_from_data(chunk_t data);
#endif /** PB_TNC_BATCH_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ita/pb_mutual_capability_msg.c b/src/libtnccs/plugins/tnccs_20/messages/ita/pb_mutual_capability_msg.c
new file mode 100644
index 000000000..1f35cae6b
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ita/pb_mutual_capability_msg.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2015 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 "pb_mutual_capability_msg.h"
+
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+ENUM(pb_tnc_mutual_protocol_type_names, PB_MUTUAL_HALF_DUPLEX,
+ PB_MUTUAL_FULL_DUPLEX,
+ "half duplex",
+ "full duplex"
+);
+
+typedef struct private_pb_mutual_capability_msg_t private_pb_mutual_capability_msg_t;
+
+/**
+ * PB-Mutual-Capability message
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |H|F| Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+# define MUTUAL_CAPABILITY_HEADER_SIZE 4
+
+/**
+ * Private data of a pb_mutual_capability_msg_t object.
+ *
+ */
+struct private_pb_mutual_capability_msg_t {
+ /**
+ * Public pb_mutual_capability_msg_t interface.
+ */
+ pb_mutual_capability_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pen_type_t type;
+
+ /**
+ * PB-TNC mutual protocols
+ */
+ uint32_t protocols;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pen_type_t,
+ private_pb_mutual_capability_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_mutual_capability_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_mutual_capability_msg_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->encoding.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(MUTUAL_CAPABILITY_HEADER_SIZE);
+ writer->write_uint32(writer, this->protocols);
+
+ this->encoding = writer->get_buf(writer);
+ this->encoding = chunk_clone(this->encoding);
+ writer->destroy(writer);
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_mutual_capability_msg_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+
+ *offset = 0;
+
+ /* process message */
+ reader = bio_reader_create(this->encoding);
+ reader->read_uint32(reader, &this->protocols);
+ reader->destroy(reader);
+
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_mutual_capability_msg_t *this)
+{
+ free(this->encoding.ptr);
+ free(this);
+}
+
+METHOD(pb_mutual_capability_msg_t, get_protocols, uint32_t,
+ private_pb_mutual_capability_msg_t *this)
+{
+ return this->protocols;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t* pb_mutual_capability_msg_create(uint32_t protocols)
+{
+ private_pb_mutual_capability_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_protocols = _get_protocols,
+ },
+ .type = { PEN_ITA, PB_ITA_MSG_MUTUAL_CAPABILITY },
+ .protocols = protocols,
+ );
+
+ return &this->public.pb_interface;
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_mutual_capability_msg_create_from_data(chunk_t data)
+{
+ private_pb_mutual_capability_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ .get_protocols = _get_protocols,
+ },
+ .type = { PEN_ITA, PB_ITA_MSG_MUTUAL_CAPABILITY },
+ .encoding = chunk_clone(data),
+ );
+
+ return &this->public.pb_interface;
+}
+
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ita/pb_mutual_capability_msg.h b/src/libtnccs/plugins/tnccs_20/messages/ita/pb_mutual_capability_msg.h
new file mode 100644
index 000000000..db810a012
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ita/pb_mutual_capability_msg.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2015 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 pb_mutual_capability_msg pb_mutual_capability_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_MUTUAL_CAPABILITY_MSG_H_
+#define PB_MUTUAL_CAPABILITY_MSG_H_
+
+typedef enum pb_tnc_mutual_protocol_type_t pb_tnc_mutual_protocol_type_t;
+typedef struct pb_mutual_capability_msg_t pb_mutual_capability_msg_t;
+
+#include "messages/pb_tnc_msg.h"
+
+/**
+ * PB-TNC mutual protocol types
+ */
+enum pb_tnc_mutual_protocol_type_t {
+ PB_MUTUAL_HALF_DUPLEX = (1 << 31),
+ PB_MUTUAL_FULL_DUPLEX = (1 << 30)
+};
+
+/**
+ * enum name for pb_mutual_protocol_type_t.
+ */
+extern enum_name_t *pb_tnc_mutual_protocol_type_names;
+
+/**
+ * Class representing the PB-Mutual-Capabilities message type.
+ */
+struct pb_mutual_capability_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+
+ /**
+ * Get the PB-TNC mutual protocol types
+ *
+ * @return PB-TNC mutual protocol types
+ */
+ uint32_t(*get_protocols)(pb_mutual_capability_msg_t *this);
+
+};
+
+/**
+ * Create a PB-Mutual-Capability message
+ *
+ * @param protocols Supported PB-TNC mutual protocols
+ */
+pb_tnc_msg_t* pb_mutual_capability_msg_create(uint32_t protocols);
+
+/**
+ * Create an unprocessed PB-Mutual-Capability message from raw data
+ *
+ * @param data PB-Mutual-Capability message data
+ */
+pb_tnc_msg_t* pb_mutual_capability_msg_create_from_data(chunk_t data);
+
+#endif /** PB_MUTUAL_CAPABILITY_MSG_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ita/pb_noskip_test_msg.c b/src/libtnccs/plugins/tnccs_20/messages/ita/pb_noskip_test_msg.c
new file mode 100644
index 000000000..c95222e3a
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ita/pb_noskip_test_msg.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2015 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 "pb_noskip_test_msg.h"
+
+typedef struct private_pb_noskip_test_msg_t private_pb_noskip_test_msg_t;
+
+/**
+ * Private data of a pb_noskip_test_msg_t object.
+ *
+ */
+struct private_pb_noskip_test_msg_t {
+ /**
+ * Public pb_noskip_test_msg_t interface.
+ */
+ pb_noskip_test_msg_t public;
+
+ /**
+ * PB-TNC message type
+ */
+ pen_type_t type;
+
+ /**
+ * Encoded message
+ */
+ chunk_t encoding;
+};
+
+METHOD(pb_tnc_msg_t, get_type, pen_type_t,
+ private_pb_noskip_test_msg_t *this)
+{
+ return this->type;
+}
+
+METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
+ private_pb_noskip_test_msg_t *this)
+{
+ return this->encoding;
+}
+
+METHOD(pb_tnc_msg_t, build, void,
+ private_pb_noskip_test_msg_t *this)
+{
+ /* nothing to do since the message is empty */
+}
+
+METHOD(pb_tnc_msg_t, process, status_t,
+ private_pb_noskip_test_msg_t *this, u_int32_t *offset)
+{
+ return SUCCESS;
+}
+
+METHOD(pb_tnc_msg_t, destroy, void,
+ private_pb_noskip_test_msg_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+pb_tnc_msg_t *pb_noskip_test_msg_create(void)
+{
+ private_pb_noskip_test_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .pb_interface = {
+ .get_type = _get_type,
+ .get_encoding = _get_encoding,
+ .build = _build,
+ .process = _process,
+ .destroy = _destroy,
+ },
+ },
+ .type = { PEN_ITA, PB_ITA_MSG_NOSKIP_TEST },
+ );
+
+ return &this->public.pb_interface;
+}
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ita/pb_noskip_test_msg.h b/src/libtnccs/plugins/tnccs_20/messages/ita/pb_noskip_test_msg.h
new file mode 100644
index 000000000..6325582da
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/messages/ita/pb_noskip_test_msg.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 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 pb_noskip_test_msg pb_noskip_test_msg
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef PB_NOSKIP_TEST_MSG_H_
+#define PB_NOSKIP_TEST_MSG_H_
+
+typedef struct pb_noskip_test_msg_t pb_noskip_test_msg_t;
+
+#include "messages/pb_tnc_msg.h"
+
+/**
+ * Class representing the PB-Noskip-Test message type.
+ */
+struct pb_noskip_test_msg_t {
+
+ /**
+ * PB-TNC Message interface
+ */
+ pb_tnc_msg_t pb_interface;
+};
+
+/**
+ * Create a PB-Noskip-Test message from parameters
+ */
+pb_tnc_msg_t* pb_noskip_test_msg_create(void);
+
+#endif /** PB_NOSKIP_TEST_MSG_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.c b/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.c
index ec43490f4..b46c776e4 100644
--- a/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.c
+++ b/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.c
@@ -22,6 +22,7 @@
#include "ietf/pb_access_recommendation_msg.h"
#include "ietf/pb_remediation_parameters_msg.h"
#include "ietf/pb_reason_string_msg.h"
+#include "ita/pb_mutual_capability_msg.h"
#include "tcg/pb_pdp_referral_msg.h"
#include <library.h>
@@ -37,10 +38,17 @@ ENUM(pb_tnc_msg_type_names, PB_MSG_EXPERIMENTAL, PB_MSG_REASON_STRING,
"PB-Reason-String"
);
-ENUM(pb_tnc_tcg_msg_type_names, PB_TCG_MSG_PDP_REFERRAL, PB_TCG_MSG_PDP_REFERRAL,
+ENUM(pb_tnc_tcg_msg_type_names, PB_TCG_MSG_PDP_REFERRAL,
+ PB_TCG_MSG_PDP_REFERRAL,
"PB-PDP-Referral"
);
+ENUM(pb_tnc_ita_msg_type_names, PB_ITA_MSG_NOSKIP_TEST,
+ PB_ITA_MSG_MUTUAL_CAPABILITY,
+ "PB-Noskip-Test",
+ "PB-Mutual-Capability"
+);
+
pb_tnc_msg_info_t pb_tnc_msg_infos[] = {
{ 12, FALSE, FALSE, TRUE_OR_FALSE },
{ 24, FALSE, FALSE, TRUE },
@@ -57,6 +65,11 @@ pb_tnc_msg_info_t pb_tnc_tcg_msg_infos[] = {
{ 20, FALSE, FALSE, FALSE },
};
+pb_tnc_msg_info_t pb_tnc_ita_msg_infos[] = {
+ { 12, TRUE, FALSE, TRUE },
+ { 16, FALSE, FALSE, FALSE },
+};
+
/**
* See header
*/
@@ -91,5 +104,12 @@ pb_tnc_msg_t* pb_tnc_msg_create_from_data(pen_type_t msg_type, chunk_t value)
return pb_pdp_referral_msg_create_from_data(value);
}
}
+ else if (msg_type.vendor_id == PEN_ITA)
+ {
+ if (msg_type.type == PB_ITA_MSG_MUTUAL_CAPABILITY)
+ {
+ return pb_mutual_capability_msg_create_from_data(value);
+ }
+ }
return NULL;
}
diff --git a/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.h b/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.h
index 6eeed5156..35b0b7c26 100644
--- a/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.h
+++ b/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.h
@@ -54,6 +54,7 @@ extern enum_name_t *pb_tnc_msg_type_names;
* PB-TNC Message Type defined in the TCG namespace
*/
enum pb_tnc_tcg_msg_type_t {
+ PB_TCG_MSG_RESERVED = 0,
PB_TCG_MSG_PDP_REFERRAL = 1,
PB_TCG_MSG_ROOF = 1
};
@@ -64,6 +65,20 @@ enum pb_tnc_tcg_msg_type_t {
extern enum_name_t *pb_tnc_tcg_msg_type_names;
/**
+ * PB-TNC Message Type defined in the ITA namespace
+ */
+enum pb_tnc_ita_msg_type_t {
+ PB_ITA_MSG_NOSKIP_TEST = 0,
+ PB_ITA_MSG_MUTUAL_CAPABILITY = 1,
+ PB_ITA_MSG_ROOF = 1
+};
+
+/**
+ * enum name for pb_tnc_tcg_msg_type_t.
+ */
+extern enum_name_t *pb_tnc_ita_msg_type_names;
+
+/**
* Information entry describing a PB-TNC Message Type
*/
struct pb_tnc_msg_info_t {
@@ -86,6 +101,11 @@ extern pb_tnc_msg_info_t pb_tnc_msg_infos[];
extern pb_tnc_msg_info_t pb_tnc_tcg_msg_infos[];
/**
+ * Information on PB-TNC ITA Message Types
+ */
+extern pb_tnc_msg_info_t pb_tnc_ita_msg_infos[];
+
+/**
* Generic interface for all PB-TNC message types.
*
* To handle all messages in a generic way, this interface
diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20.c b/src/libtnccs/plugins/tnccs_20/tnccs_20.c
index dc4da51c6..a1a95733f 100644
--- a/src/libtnccs/plugins/tnccs_20/tnccs_20.c
+++ b/src/libtnccs/plugins/tnccs_20/tnccs_20.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Sansar Choinyanbuu
- * Copyright (C) 2010-2013 Andreas Steffen
+ * Copyright (C) 2010-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -15,30 +15,17 @@
*/
#include "tnccs_20.h"
+#include "tnccs_20_handler.h"
+#include "tnccs_20_server.h"
+#include "tnccs_20_client.h"
#include "batch/pb_tnc_batch.h"
#include "messages/pb_tnc_msg.h"
#include "messages/ietf/pb_pa_msg.h"
-#include "messages/ietf/pb_error_msg.h"
-#include "messages/ietf/pb_assessment_result_msg.h"
-#include "messages/ietf/pb_access_recommendation_msg.h"
-#include "messages/ietf/pb_remediation_parameters_msg.h"
-#include "messages/ietf/pb_reason_string_msg.h"
-#include "messages/ietf/pb_language_preference_msg.h"
-#include "messages/tcg/pb_pdp_referral_msg.h"
-#include "state_machine/pb_tnc_state_machine.h"
#include <tncif_names.h>
#include <tncif_pa_subtypes.h>
-#include <tnc/tnc.h>
-#include <tnc/tnccs/tnccs_manager.h>
-#include <tnc/imc/imc_manager.h>
-#include <tnc/imv/imv_manager.h>
-
-#include <threading/mutex.h>
#include <utils/debug.h>
-#include <collections/linked_list.h>
-#include <pen/pen.h>
typedef struct private_tnccs_20_t private_tnccs_20_t;
@@ -60,77 +47,72 @@ struct private_tnccs_20_t {
/**
* Server identity
*/
- identification_t *server;
+ identification_t *server_id;
/**
* Client identity
*/
- identification_t *peer;
+ identification_t *peer_id;
/**
- * Underlying TNC IF-T transport protocol
+ * Server IP address
*/
- tnc_ift_type_t transport;
+ host_t *server_ip;
/**
- * Type of TNC client authentication
+ * Client IP address
*/
- u_int32_t auth_type;
+ host_t *peer_ip;
/**
- * PB-TNC State Machine
+ * Underlying TNC IF-T transport protocol
*/
- pb_tnc_state_machine_t *state_machine;
+ tnc_ift_type_t transport;
/**
- * Connection ID assigned to this TNCCS connection
+ * TNC IF-T transport protocol for EAP methods
*/
- TNC_ConnectionID connection_id;
+ bool eap_transport;
/**
- * PB-TNC messages to be sent
+ * Type of TNC client authentication
*/
- linked_list_t *messages;
+ u_int32_t auth_type;
/**
- * Type of PB-TNC batch being constructed
+ * Mutual PB-TNC protocol enabled
*/
- pb_tnc_batch_type_t batch_type;
+ bool mutual;
/**
- * Maximum PB-TNC batch size
+ * Direction the next batch will go to
*/
- size_t max_batch_len;
+ bool to_server;
/**
- * Maximum PA-TNC message size
+ * TNC Server
*/
- size_t max_msg_len;
+ tnccs_20_handler_t *tnc_server;
/**
- * Mutex locking the batch in construction
+ * TNC Client
*/
- mutex_t *mutex;
+ tnccs_20_handler_t *tnc_client;
/**
- * Flag set while processing
+ * Active TNCSS handler
*/
- bool fatal_error;
+ tnccs_20_handler_t *tnccs_handler;
/**
- * Flag set by IMC/IMV RequestHandshakeRetry() function
+ * Maximum PB-TNC batch size
*/
- bool request_handshake_retry;
-
- /**
- * SendMessage() by IMC/IMV only allowed if flag is set
- */
- bool send_msg;
+ size_t max_batch_len;
/**
- * Set of IMV recommendations (TNC Server only)
+ * Maximum PA-TNC message size
*/
- recommendations_t *recs;
+ size_t max_msg_len;
/**
* Callback function to communicate recommendation (TNC Server only)
@@ -138,69 +120,30 @@ struct private_tnccs_20_t {
tnccs_cb_t callback;
/**
- * Data to pass to callback function (TNC Server only)
- */
- void *cb_data;
-
- /**
- * PDP server FQDN
- */
- chunk_t pdp_server;
-
- /**
- * PDP server port
- */
- u_int16_t pdp_port;
-
- /**
* reference count
*/
refcount_t ref;
};
-/**
- * If the batch type changes then delete all accumulated PB-TNC messages
- */
-void change_batch_type(private_tnccs_20_t *this, pb_tnc_batch_type_t batch_type)
-{
- pb_tnc_msg_t *msg;
-
- if (batch_type != this->batch_type)
- {
- if (this->batch_type != PB_BATCH_NONE)
- {
- DBG1(DBG_TNC, "cancelling PB-TNC %N batch",
- pb_tnc_batch_type_names, this->batch_type);
-
- while (this->messages->remove_last(this->messages,
- (void**)&msg) == SUCCESS)
- {
- msg->destroy(msg);
- }
- }
- this->batch_type = batch_type;
- }
-}
-
METHOD(tnccs_t, send_msg, TNC_Result,
private_tnccs_20_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id,
- TNC_UInt32 msg_flags,
+ TNC_UInt32 msg_flags,
TNC_BufferReference msg,
TNC_UInt32 msg_len,
- TNC_VendorID msg_vid,
- TNC_MessageSubtype msg_subtype)
+ TNC_VendorID msg_vid,
+ TNC_MessageSubtype msg_subtype)
{
pb_tnc_msg_t *pb_tnc_msg;
- pb_tnc_batch_type_t batch_type;
enum_name_t *pa_subtype_names;
bool excl;
- if (!this->send_msg)
+ if (!this->tnccs_handler->get_send_flag(this->tnccs_handler))
{
DBG1(DBG_TNC, "%s %u not allowed to call SendMessage()",
- this->is_server ? "IMV" : "IMC",
- this->is_server ? imv_id : imc_id);
+ this->to_server ? "IMC" : "IMV",
+ this->to_server ? imc_id : imv_id);
+
return TNC_RESULT_ILLEGAL_OPERATION;
}
excl = (msg_flags & TNC_MESSAGE_FLAGS_EXCLUSIVE) != 0;
@@ -220,698 +163,169 @@ METHOD(tnccs_t, send_msg, TNC_Result,
DBG2(DBG_TNC, "creating PB-PA message type '%N' 0x%06x/0x%08x",
pen_names, msg_vid, msg_vid, msg_subtype);
}
+ this->tnccs_handler->add_msg(this->tnccs_handler, pb_tnc_msg);
- /* adding PA message to SDATA or CDATA batch only */
- batch_type = this->is_server ? PB_BATCH_SDATA : PB_BATCH_CDATA;
- this->mutex->lock(this->mutex);
- if (this->batch_type == PB_BATCH_NONE)
- {
- this->batch_type = batch_type;
- }
- if (this->batch_type == batch_type)
- {
- this->messages->insert_last(this->messages, pb_tnc_msg);
- }
- else
- {
- pb_tnc_msg->destroy(pb_tnc_msg);
- }
- this->mutex->unlock(this->mutex);
return TNC_RESULT_SUCCESS;
}
-/**
- * Handle a single PB-TNC IETF standard message according to its type
- */
-static void handle_ietf_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
-{
- pen_type_t msg_type = msg->get_type(msg);
-
- switch (msg_type.type)
- {
- case PB_MSG_EXPERIMENTAL:
- /* nothing to do */
- break;
- case PB_MSG_PA:
- {
- pb_pa_msg_t *pa_msg;
- pen_type_t msg_subtype;
- u_int16_t imc_id, imv_id;
- chunk_t msg_body;
- bool excl;
- enum_name_t *pa_subtype_names;
-
- pa_msg = (pb_pa_msg_t*)msg;
- msg_subtype = pa_msg->get_subtype(pa_msg);
- msg_body = pa_msg->get_body(pa_msg);
- imc_id = pa_msg->get_collector_id(pa_msg);
- imv_id = pa_msg->get_validator_id(pa_msg);
- excl = pa_msg->get_exclusive_flag(pa_msg);
-
- pa_subtype_names = get_pa_subtype_names(msg_subtype.vendor_id);
- if (pa_subtype_names)
- {
- DBG2(DBG_TNC, "handling PB-PA message type '%N/%N' 0x%06x/0x%08x",
- pen_names, msg_subtype.vendor_id, pa_subtype_names,
- msg_subtype.type, msg_subtype.vendor_id, msg_subtype.type);
- }
- else
- {
- DBG2(DBG_TNC, "handling PB-PA message type '%N' 0x%06x/0x%08x",
- pen_names, msg_subtype.vendor_id, msg_subtype.vendor_id,
- msg_subtype.type);
- }
-
- this->send_msg = TRUE;
- if (this->is_server)
- {
- tnc->imvs->receive_message(tnc->imvs, this->connection_id,
- excl, msg_body.ptr, msg_body.len,
- msg_subtype.vendor_id,
- msg_subtype.type, imc_id, imv_id);
- }
- else
- {
- tnc->imcs->receive_message(tnc->imcs, this->connection_id,
- excl, msg_body.ptr, msg_body.len,
- msg_subtype.vendor_id,
- msg_subtype.type, imv_id, imc_id);
- }
- this->send_msg = FALSE;
- break;
- }
- case PB_MSG_ASSESSMENT_RESULT:
- {
- pb_assessment_result_msg_t *assess_msg;
- u_int32_t result;
-
- assess_msg = (pb_assessment_result_msg_t*)msg;
- result = assess_msg->get_assessment_result(assess_msg);
- DBG1(DBG_TNC, "PB-TNC assessment result is '%N'",
- TNC_IMV_Evaluation_Result_names, result);
- break;
- }
- case PB_MSG_ACCESS_RECOMMENDATION:
- {
- pb_access_recommendation_msg_t *rec_msg;
- pb_access_recommendation_code_t rec;
- TNC_ConnectionState state = TNC_CONNECTION_STATE_ACCESS_NONE;
-
- rec_msg = (pb_access_recommendation_msg_t*)msg;
- rec = rec_msg->get_access_recommendation(rec_msg);
- DBG1(DBG_TNC, "PB-TNC access recommendation is '%N'",
- pb_access_recommendation_code_names, rec);
- switch (rec)
- {
- case PB_REC_ACCESS_ALLOWED:
- state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
- break;
- case PB_REC_ACCESS_DENIED:
- state = TNC_CONNECTION_STATE_ACCESS_NONE;
- break;
- case PB_REC_QUARANTINED:
- state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
- }
- tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
- state);
- break;
- }
- case PB_MSG_REMEDIATION_PARAMETERS:
- {
- pb_remediation_parameters_msg_t *rem_msg;
- pen_type_t parameters_type;
- chunk_t parameters, string, lang_code;
-
- rem_msg = (pb_remediation_parameters_msg_t*)msg;
- parameters_type = rem_msg->get_parameters_type(rem_msg);
- parameters = rem_msg->get_parameters(rem_msg);
-
- if (parameters_type.vendor_id == PEN_IETF)
- {
- switch (parameters_type.type)
- {
- case PB_REMEDIATION_URI:
- DBG1(DBG_TNC, "remediation uri: %.*s",
- parameters.len, parameters.ptr);
- break;
- case PB_REMEDIATION_STRING:
- string = rem_msg->get_string(rem_msg, &lang_code);
- DBG1(DBG_TNC, "remediation string: [%.*s]\n%.*s",
- lang_code.len, lang_code.ptr,
- string.len, string.ptr);
- break;
- default:
- DBG1(DBG_TNC, "remediation parameters: %B", &parameters);
- }
- }
- else
- {
- DBG1(DBG_TNC, "remediation parameters: %B", &parameters);
- }
- break;
- }
- case PB_MSG_ERROR:
- {
- pb_error_msg_t *err_msg;
- bool fatal;
- u_int32_t vendor_id;
- u_int16_t error_code;
-
- err_msg = (pb_error_msg_t*)msg;
- fatal = err_msg->get_fatal_flag(err_msg);
- vendor_id = err_msg->get_vendor_id(err_msg);
- error_code = err_msg->get_error_code(err_msg);
-
- if (fatal)
- {
- this->fatal_error = TRUE;
- }
-
- if (vendor_id == PEN_IETF)
- {
- switch (error_code)
- {
- case PB_ERROR_INVALID_PARAMETER:
- case PB_ERROR_UNSUPPORTED_MANDATORY_MSG:
- DBG1(DBG_TNC, "received %s PB-TNC error '%N' "
- "(offset %u bytes)",
- fatal ? "fatal" : "non-fatal",
- pb_tnc_error_code_names, error_code,
- err_msg->get_offset(err_msg));
- break;
- case PB_ERROR_VERSION_NOT_SUPPORTED:
- DBG1(DBG_TNC, "received %s PB-TNC error '%N' "
- "caused by bad version 0x%02x",
- fatal ? "fatal" : "non-fatal",
- pb_tnc_error_code_names, error_code,
- err_msg->get_bad_version(err_msg));
- break;
- case PB_ERROR_UNEXPECTED_BATCH_TYPE:
- case PB_ERROR_LOCAL_ERROR:
- default:
- DBG1(DBG_TNC, "received %s PB-TNC error '%N'",
- fatal ? "fatal" : "non-fatal",
- pb_tnc_error_code_names, error_code);
- break;
- }
- }
- else
- {
- DBG1(DBG_TNC, "received %s PB-TNC error (%u) "
- "with Vendor ID 0x%06x",
- fatal ? "fatal" : "non-fatal",
- error_code, vendor_id);
- }
- break;
- }
- case PB_MSG_LANGUAGE_PREFERENCE:
- {
- pb_language_preference_msg_t *lang_msg;
- chunk_t lang;
-
- lang_msg = (pb_language_preference_msg_t*)msg;
- lang = lang_msg->get_language_preference(lang_msg);
-
- if (this->recs)
- {
- DBG2(DBG_TNC, "setting language preference to '%.*s'",
- (int)lang.len, lang.ptr);
- this->recs->set_preferred_language(this->recs, lang);
- }
- break;
- }
- case PB_MSG_REASON_STRING:
- {
- pb_reason_string_msg_t *reason_msg;
- chunk_t reason_string, language_code;
-
- reason_msg = (pb_reason_string_msg_t*)msg;
- reason_string = reason_msg->get_reason_string(reason_msg);
- language_code = reason_msg->get_language_code(reason_msg);
- DBG1(DBG_TNC, "reason string is '%.*s' [%.*s]",
- (int)reason_string.len, reason_string.ptr,
- (int)language_code.len, language_code.ptr);
- break;
- }
- default:
- break;
- }
-}
-
-/**
- * Handle a single PB-TNC TCG standard message according to its type
- */
-static void handle_tcg_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
-{
- pen_type_t msg_type = msg->get_type(msg);
-
- switch (msg_type.type)
- {
- case PB_TCG_MSG_PDP_REFERRAL:
- {
- pb_pdp_referral_msg_t *pdp_msg;
- pen_type_t pdp_id_type;
- u_int8_t pdp_protocol;
-
- pdp_msg = (pb_pdp_referral_msg_t*)msg;
- pdp_id_type = pdp_msg->get_identifier_type(pdp_msg);
-
- if (pdp_id_type.vendor_id == PEN_TCG &&
- pdp_id_type.type == PB_PDP_ID_FQDN)
- {
- this->pdp_server = chunk_clone(pdp_msg->get_fqdn(pdp_msg,
- &pdp_protocol, &this->pdp_port));
- if (pdp_protocol != 0)
- {
- DBG1(DBG_TNC, "unsupported PDP transport protocol");
- break;
- }
- DBG1(DBG_TNC, "PDP server '%.*s' is listening on port %u",
- this->pdp_server.len, this->pdp_server.ptr,
- this->pdp_port);
- }
- break;
- }
- default:
- break;
- }
-}
-
-/**
- * Handle a single PB-TNC message according to its type
- */
-static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
-{
- pen_type_t msg_type = msg->get_type(msg);
-
- switch (msg_type.vendor_id)
- {
- case PEN_IETF:
- handle_ietf_message(this, msg);
- break;
- case PEN_TCG:
- handle_tcg_message(this, msg);
- break;
- default:
- break;
- }
-}
-
-/**
- * Build a CRETRY or SRETRY batch
- */
-static void build_retry_batch(private_tnccs_20_t *this)
-{
- pb_tnc_batch_type_t batch_retry_type;
-
- batch_retry_type = this->is_server ? PB_BATCH_SRETRY : PB_BATCH_CRETRY;
- if (this->batch_type == batch_retry_type)
- {
- /* retry batch has already been selected */
- return;
- }
-
- change_batch_type(this, batch_retry_type);
-
- if (this->is_server)
- {
- this->recs->clear_recommendation(this->recs);
- tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
- TNC_CONNECTION_STATE_HANDSHAKE);
- }
-}
-
METHOD(tls_t, process, status_t,
private_tnccs_20_t *this, void *buf, size_t buflen)
{
- chunk_t data;
pb_tnc_batch_t *batch;
- pb_tnc_msg_t *msg;
- enumerator_t *enumerator;
- identification_t *pdp_server;
- u_int16_t *pdp_port;
+ bool from_server, fatal_header_error = FALSE;
status_t status;
+ chunk_t data;
- if (this->is_server && !this->connection_id)
+ /* On arrival of first batch from TNC client create TNC server */
+ if (this->is_server && !this->tnc_server)
{
- this->connection_id = tnc->tnccs->create_connection(tnc->tnccs,
- TNCCS_2_0, (tnccs_t*)this, _send_msg,
- &this->request_handshake_retry,
- this->max_msg_len, &this->recs);
- if (!this->connection_id)
+ this->tnc_server = tnccs_20_server_create(&this->public, _send_msg,
+ this->max_batch_len, this->max_msg_len,
+ this->eap_transport);
+ if (!this->tnc_server)
{
return FAILED;
}
- tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
- TNC_CONNECTION_STATE_CREATE);
- tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
- TNC_CONNECTION_STATE_HANDSHAKE);
-
- /* Send a PB-TNC TCG PDP Referral message if PDP is known */
- pdp_server = (identification_t*)lib->get(lib, "pt-tls-server");
- pdp_port = (u_int16_t*)lib->get(lib, "pt-tls-port");
-
- if ((this->transport == TNC_IFT_EAP_1_1 ||
- this->transport == TNC_IFT_EAP_2_0) && pdp_server && pdp_port)
- {
- msg = pb_pdp_referral_msg_create_from_fqdn(
- pdp_server->get_encoding(pdp_server), *pdp_port);
- this->messages->insert_last(this->messages, msg);
- }
-
+ this->tnccs_handler = this->tnc_server;
+ this->tnccs_handler->begin_handshake(this->tnccs_handler, FALSE);
}
data = chunk_create(buf, buflen);
- DBG1(DBG_TNC, "received TNCCS batch (%u bytes) for Connection ID %u",
- data.len, this->connection_id);
+ DBG1(DBG_TNC, "received TNCCS batch (%u bytes)", data.len);
DBG3(DBG_TNC, "%B", &data);
- batch = pb_tnc_batch_create_from_data(this->is_server, data);
- status = batch->process(batch, this->state_machine);
- if (status != FAILED)
+ /* Parse the header of the received PB-TNC batch */
+ batch = pb_tnc_batch_create_from_data(data);
+ status = batch->process_header(batch, !this->mutual, this->is_server,
+ &from_server);
+ if (status == FAILED)
{
- enumerator_t *enumerator;
- pb_tnc_msg_t *msg;
- pb_tnc_batch_type_t batch_type;
- bool empty = TRUE;
-
- batch_type = batch->get_type(batch);
-
- if (batch_type == PB_BATCH_CRETRY)
- {
- /* Send an SRETRY batch in response */
- this->mutex->lock(this->mutex);
- build_retry_batch(this);
- this->mutex->unlock(this->mutex);
- }
- else if (batch_type == PB_BATCH_SRETRY)
- {
- /* Restart the measurements */
- tnc->imcs->notify_connection_change(tnc->imcs,
- this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE);
- this->send_msg = TRUE;
- tnc->imcs->begin_handshake(tnc->imcs, this->connection_id);
- this->send_msg = FALSE;
- }
-
- enumerator = batch->create_msg_enumerator(batch);
- while (enumerator->enumerate(enumerator, &msg))
- {
- handle_message(this, msg);
- empty = FALSE;
- }
- enumerator->destroy(enumerator);
+ fatal_header_error = TRUE;
+ status = VERIFY_ERROR;
+ }
+ this->to_server = this->mutual ? from_server : !this->is_server;
- /* received an empty CLOSE batch from PB-TNC client */
- if (this->is_server && batch_type == PB_BATCH_CLOSE && empty)
+ /* In the mutual case, first batch from TNC server requires a TNC client */
+ if (this->to_server && !this->tnc_client)
+ {
+ this->tnc_client = tnccs_20_client_create(&this->public, _send_msg,
+ this->max_batch_len, this->max_msg_len);
+ if (!this->tnc_client)
{
batch->destroy(batch);
- if (this->fatal_error)
- {
- DBG1(DBG_TNC, "a fatal PB-TNC error occurred, "
- "terminating connection");
- return FAILED;
- }
- else
- {
- return SUCCESS;
- }
- }
-
- this->send_msg = TRUE;
- if (this->is_server)
- {
- tnc->imvs->batch_ending(tnc->imvs, this->connection_id);
- }
- else
- {
- tnc->imcs->batch_ending(tnc->imcs, this->connection_id);
+ return FAILED;
}
- this->send_msg = FALSE;
+ this->tnccs_handler = this->tnc_client;
+ this->tnccs_handler->begin_handshake(this->tnccs_handler, this->mutual);
}
+ else
+ {
+ /* Set active TNCCS handler for processing */
+ this->tnccs_handler = this->to_server ? this->tnc_client :
+ this->tnc_server;
+ }
+ DBG2(DBG_TNC, "TNC %s is handling inbound connection",
+ this->to_server ? "client" : "server");
- switch (status)
+ if (status == SUCCESS)
{
- case FAILED:
- this->fatal_error = TRUE;
- this->mutex->lock(this->mutex);
- change_batch_type(this, PB_BATCH_CLOSE);
- this->mutex->unlock(this->mutex);
- /* fall through to add error messages to outbound batch */
- case VERIFY_ERROR:
- enumerator = batch->create_error_enumerator(batch);
- while (enumerator->enumerate(enumerator, &msg))
- {
- this->mutex->lock(this->mutex);
- this->messages->insert_last(this->messages, msg->get_ref(msg));
- this->mutex->unlock(this->mutex);
- }
- enumerator->destroy(enumerator);
- break;
- case SUCCESS:
- default:
- break;
+ status = this->tnccs_handler->process(this->tnccs_handler, batch);
+ }
+ if (status == VERIFY_ERROR)
+ {
+ this->tnccs_handler->handle_errors(this->tnccs_handler, batch,
+ fatal_header_error);
+ status = NEED_MORE;
}
batch->destroy(batch);
- return NEED_MORE;
-}
+ /* Has a mutual connection been established? */
+ this->mutual = this->is_server ?
+ this->tnc_server->get_mutual(this->tnc_server) :
+ this->tnc_client->get_mutual(this->tnc_client);
-/**
- * Build a RESULT batch if a final recommendation is available
- */
-static void check_and_build_recommendation(private_tnccs_20_t *this)
-{
- TNC_IMV_Action_Recommendation rec;
- TNC_IMV_Evaluation_Result eval;
- TNC_ConnectionState state;
- TNC_IMVID id;
- chunk_t reason, language;
- enumerator_t *enumerator;
- pb_tnc_msg_t *msg;
- pb_access_recommendation_code_t pb_rec;
-
- if (!this->recs->have_recommendation(this->recs, &rec, &eval))
- {
- tnc->imvs->solicit_recommendation(tnc->imvs, this->connection_id);
- }
- if (this->recs->have_recommendation(this->recs, &rec, &eval))
+ if (this->mutual && !this->is_server)
{
- this->batch_type = PB_BATCH_RESULT;
+ pb_tnc_state_t client_state, server_state;
- msg = pb_assessment_result_msg_create(eval);
- this->messages->insert_last(this->messages, msg);
+ client_state = !this->tnc_client ? PB_STATE_INIT :
+ this->tnc_client->get_state(this->tnc_client);
+ server_state = !this->tnc_server ? PB_STATE_INIT :
+ this->tnc_server->get_state(this->tnc_server);
- /**
- * Map IMV Action Recommendation codes to PB Access Recommendation codes
- * and communicate Access Recommendation to IMVs
- */
- switch (rec)
+ /* In half-duplex mutual mode toggle the direction on the client side */
+ if ((!this->to_server && client_state != PB_STATE_DECIDED) ||
+ ( this->to_server && server_state != PB_STATE_END))
{
- case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
- state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
- pb_rec = PB_REC_ACCESS_ALLOWED;
- break;
- case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
- state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
- pb_rec = PB_REC_QUARANTINED;
- break;
- case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
- case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
- default:
- state = TNC_CONNECTION_STATE_ACCESS_NONE;
- pb_rec = PB_REC_ACCESS_DENIED;
+ this->to_server = !this->to_server;
+ }
+ else if (client_state == PB_STATE_DECIDED &&
+ server_state == PB_STATE_END)
+ {
+ /* Cause the final CLOSE batch to be sent to the TNC server */
+ this->to_server = TRUE;
}
- tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
- state);
-
- msg = pb_access_recommendation_msg_create(pb_rec);
- this->messages->insert_last(this->messages, msg);
- enumerator = this->recs->create_reason_enumerator(this->recs);
- while (enumerator->enumerate(enumerator, &id, &reason, &language))
+ /* Suppress a successful CLOSE batch coming from the TNC server */
+ if (status == SUCCESS)
{
- msg = pb_reason_string_msg_create(reason, language);
- this->messages->insert_last(this->messages, msg);
+ status = NEED_MORE;
}
- enumerator->destroy(enumerator);
}
+
+ return status;
}
METHOD(tls_t, build, status_t,
private_tnccs_20_t *this, void *buf, size_t *buflen, size_t *msglen)
{
- status_t status;
- pb_tnc_state_t state;
-
- /* Initialize the connection */
- if (!this->is_server && !this->connection_id)
- {
- pb_tnc_msg_t *msg;
- char *pref_lang;
-
- this->connection_id = tnc->tnccs->create_connection(tnc->tnccs,
- TNCCS_2_0, (tnccs_t*)this, _send_msg,
- &this->request_handshake_retry,
- this->max_msg_len, NULL);
- if (!this->connection_id)
- {
- return FAILED;
- }
-
- /* Create PB-TNC Language Preference message */
- pref_lang = tnc->imcs->get_preferred_language(tnc->imcs);
- msg = pb_language_preference_msg_create(chunk_create(pref_lang,
- strlen(pref_lang)));
- this->mutex->lock(this->mutex);
- this->batch_type = PB_BATCH_CDATA;
- this->messages->insert_last(this->messages, msg);
- this->mutex->unlock(this->mutex);
-
- tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
- TNC_CONNECTION_STATE_CREATE);
- tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
- TNC_CONNECTION_STATE_HANDSHAKE);
- this->send_msg = TRUE;
- tnc->imcs->begin_handshake(tnc->imcs, this->connection_id);
- this->send_msg = FALSE;
- }
-
- state = this->state_machine->get_state(this->state_machine);
-
- if (this->fatal_error && state == PB_STATE_END)
- {
- DBG1(DBG_TNC, "a fatal PB-TNC error occurred, terminating connection");
- return FAILED;
- }
-
- /* Do not allow any asynchronous IMCs or IMVs to add additional messages */
- this->mutex->lock(this->mutex);
-
- if (this->request_handshake_retry)
- {
- if (state != PB_STATE_INIT)
- {
- build_retry_batch(this);
- }
-
- /* Reset the flag for the next handshake retry request */
- this->request_handshake_retry = FALSE;
- }
-
- if (this->is_server && state == PB_STATE_SERVER_WORKING &&
- this->recs->have_recommendation(this->recs, NULL, NULL))
+ if (this->to_server)
{
- check_and_build_recommendation(this);
- }
+ DBG2(DBG_TNC, "TNC client is handling outbound connection");
- if (this->batch_type == PB_BATCH_NONE)
- {
- if (this->is_server)
+ /* Before sending the first PB-TNC batch create TNC client */
+ if (this->tnc_client)
{
- if (state == PB_STATE_SERVER_WORKING)
- {
- if (this->state_machine->get_empty_cdata(this->state_machine))
- {
- check_and_build_recommendation(this);
- }
- else
- {
- DBG2(DBG_TNC, "no recommendation available yet, "
- "sending empty PB-TNC SDATA batch");
- this->batch_type = PB_BATCH_SDATA;
- }
- }
+ this->tnccs_handler = this->tnc_client;
}
else
{
- switch (state)
+ this->tnc_client = tnccs_20_client_create(&this->public, _send_msg,
+ this->max_batch_len,
+ this->max_msg_len);
+ if (!this->tnc_client)
{
- case PB_STATE_CLIENT_WORKING:
- DBG2(DBG_TNC, "no client data to send, "
- "sending empty PB-TNC CDATA batch");
- this->batch_type = PB_BATCH_CDATA;
- break;
- case PB_STATE_DECIDED:
- /**
- * In the DECIDED state and if no CRETRY is under way,
- * a PB-TNC client replies with an empty CLOSE batch.
- */
- this->batch_type = PB_BATCH_CLOSE;
- break;
- default:
- break;
+ return FAILED;
}
+ this->tnccs_handler = this->tnc_client;
+ this->tnccs_handler->begin_handshake(this->tnccs_handler,
+ this->mutual);
}
}
-
- if (this->batch_type != PB_BATCH_NONE)
+ else
{
- pb_tnc_batch_t *batch;
- pb_tnc_msg_t *msg;
- chunk_t data;
- int msg_count;
- enumerator_t *enumerator;
+ DBG2(DBG_TNC, "TNC server is handling outbound connection");
- if (this->state_machine->send_batch(this->state_machine, this->batch_type))
+ /* Before sending the first PB-TNC batch create TNC server */
+ if (this->tnc_server)
{
- batch = pb_tnc_batch_create(this->is_server, this->batch_type,
- min(this->max_batch_len, *buflen));
-
- enumerator = this->messages->create_enumerator(this->messages);
- while (enumerator->enumerate(enumerator, &msg))
- {
- if (batch->add_msg(batch, msg))
- {
- this->messages->remove_at(this->messages, enumerator);
- }
- else
- {
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- batch->build(batch);
- data = batch->get_encoding(batch);
- DBG1(DBG_TNC, "sending PB-TNC %N batch (%d bytes) for Connection ID %u",
- pb_tnc_batch_type_names, this->batch_type, data.len,
- this->connection_id);
- DBG3(DBG_TNC, "%B", &data);
-
- *buflen = data.len;
- *msglen = 0;
- memcpy(buf, data.ptr, *buflen);
- batch->destroy(batch);
-
- msg_count = this->messages->get_count(this->messages);
- if (msg_count)
- {
- DBG2(DBG_TNC, "queued %d PB-TNC message%s for next %N batch",
- msg_count, (msg_count == 1) ? "" : "s",
- pb_tnc_batch_type_names, this->batch_type);
- }
- else
- {
- this->batch_type = PB_BATCH_NONE;
- }
-
- status = ALREADY_DONE;
+ this->tnccs_handler = this->tnc_server;
}
else
{
- change_batch_type(this, PB_BATCH_NONE);
- status = INVALID_STATE;
+ this->tnc_server = tnccs_20_server_create(&this->public, _send_msg,
+ this->max_batch_len, this->max_msg_len,
+ this->eap_transport);
+ if (!this->tnc_server)
+ {
+ return FAILED;
+ }
+ this->tnccs_handler = this->tnc_server;
+ this->tnccs_handler->begin_handshake(this->tnccs_handler,
+ this->mutual);
}
}
- else
- {
- DBG1(DBG_TNC, "no PB-TNC batch to send");
- status = INVALID_STATE;
- }
- this->mutex->unlock(this->mutex);
-
- return status;
+ return this->tnccs_handler->build(this->tnccs_handler, buf, buflen, msglen);
}
METHOD(tls_t, is_server, bool,
@@ -923,20 +337,20 @@ METHOD(tls_t, is_server, bool,
METHOD(tls_t, get_server_id, identification_t*,
private_tnccs_20_t *this)
{
- return this->server;
+ return this->server_id;
}
METHOD(tls_t, set_peer_id, void,
private_tnccs_20_t *this, identification_t *id)
{
- DESTROY_IF(this->peer);
- this->peer = id->clone(id);
+ DESTROY_IF(this->peer_id);
+ this->peer_id = id->clone(id);
}
METHOD(tls_t, get_peer_id, identification_t*,
private_tnccs_20_t *this)
{
- return this->peer;
+ return this->peer_id;
}
METHOD(tls_t, get_purpose, tls_purpose_t,
@@ -951,14 +365,17 @@ METHOD(tls_t, is_complete, bool,
TNC_IMV_Action_Recommendation rec;
TNC_IMV_Evaluation_Result eval;
- if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval))
+ if (this->tnc_server)
{
- return this->callback ? this->callback(rec, eval) : TRUE;
- }
- else
- {
- return FALSE;
+ tnccs_20_server_t *tnc_server;
+
+ tnc_server = (tnccs_20_server_t*)this->tnc_server;
+ if (tnc_server->have_recommendation(tnc_server, &rec, &eval))
+ {
+ return this->callback ? this->callback(rec, eval) : TRUE;
+ }
}
+ return FALSE;
}
METHOD(tls_t, get_eap_msk, chunk_t,
@@ -972,19 +389,28 @@ METHOD(tls_t, destroy, void,
{
if (ref_put(&this->ref))
{
- tnc->tnccs->remove_connection(tnc->tnccs, this->connection_id,
- this->is_server);
- this->server->destroy(this->server);
- this->peer->destroy(this->peer);
- this->state_machine->destroy(this->state_machine);
- this->mutex->destroy(this->mutex);
- this->messages->destroy_offset(this->messages,
- offsetof(pb_tnc_msg_t, destroy));
- free(this->pdp_server.ptr);
+ DESTROY_IF(this->tnc_server);
+ DESTROY_IF(this->tnc_client);
+ this->server_id->destroy(this->server_id);
+ this->peer_id->destroy(this->peer_id);
+ this->server_ip->destroy(this->server_ip);
+ this->peer_ip->destroy(this->peer_ip);
free(this);
}
}
+METHOD(tnccs_t, get_server_ip, host_t*,
+ private_tnccs_20_t *this)
+{
+ return this->server_ip;
+}
+
+METHOD(tnccs_t, get_peer_ip, host_t*,
+ private_tnccs_20_t *this)
+{
+ return this->peer_ip;
+}
+
METHOD(tnccs_t, get_transport, tnc_ift_type_t,
private_tnccs_20_t *this)
{
@@ -1012,9 +438,19 @@ METHOD(tnccs_t, set_auth_type, void,
METHOD(tnccs_t, get_pdp_server, chunk_t,
private_tnccs_20_t *this, u_int16_t *port)
{
- *port = this->pdp_port;
+ if (this->tnc_client)
+ {
+ tnccs_20_client_t *tnc_client;
+
+ tnc_client = (tnccs_20_client_t*)this->tnc_client;
- return this->pdp_server;
+ return tnc_client->get_pdp_server(tnc_client, port);
+ }
+ else
+ {
+ *port = 0;
+ return chunk_empty;
+ }
}
METHOD(tnccs_t, get_ref, tnccs_t*,
@@ -1027,9 +463,10 @@ METHOD(tnccs_t, get_ref, tnccs_t*,
/**
* See header
*/
-tnccs_t* tnccs_20_create(bool is_server,
- identification_t *server, identification_t *peer,
- tnc_ift_type_t transport, tnccs_cb_t cb)
+tnccs_t* tnccs_20_create(bool is_server, identification_t *server_id,
+ identification_t *peer_id, host_t *server_ip,
+ host_t *peer_ip, tnc_ift_type_t transport,
+ tnccs_cb_t cb)
{
private_tnccs_20_t *this;
size_t max_batch_size, default_max_batch_size;
@@ -1079,6 +516,8 @@ tnccs_t* tnccs_20_create(bool is_server,
.get_eap_msk = _get_eap_msk,
.destroy = _destroy,
},
+ .get_server_ip = _get_server_ip,
+ .get_peer_ip = _get_peer_ip,
.get_transport = _get_transport,
.set_transport = _set_transport,
.get_auth_type = _get_auth_type,
@@ -1087,13 +526,15 @@ tnccs_t* tnccs_20_create(bool is_server,
.get_ref = _get_ref,
},
.is_server = is_server,
- .server = server->clone(server),
- .peer = peer->clone(peer),
+ .to_server = !is_server,
+ .server_id = server_id->clone(server_id),
+ .peer_id = peer_id->clone(peer_id),
+ .server_ip = server_ip->clone(server_ip),
+ .peer_ip = peer_ip->clone(peer_ip),
.transport = transport,
+ .eap_transport = transport == TNC_IFT_EAP_1_1 ||
+ transport == TNC_IFT_EAP_2_0,
.callback = cb,
- .state_machine = pb_tnc_state_machine_create(is_server),
- .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
- .messages = linked_list_create(),
.max_batch_len = max_batch_size,
.max_msg_len = max_message_size,
.ref = 1,
diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20.h b/src/libtnccs/plugins/tnccs_20/tnccs_20.h
index 2857b1408..010cbecdc 100644
--- a/src/libtnccs/plugins/tnccs_20/tnccs_20.h
+++ b/src/libtnccs/plugins/tnccs_20/tnccs_20.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 Andreas Steffen
+ * Copyright (C) 2010-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -29,14 +29,17 @@
* Create an instance of the TNC IF-TNCCS 2.0 protocol handler.
*
* @param is_server TRUE to act as TNC Server, FALSE for TNC Client
- * @param server Server identity
- * @param peer Client identity
+ * @param server_id Server identity
+ * @param peer_id Client identity
+ * @param server_ip Server IP address
+ * @param peer_ip Client IP address
* @param transport Underlying IF-T transport protocol
* @param cb Callback function if TNC Server, NULL if TNC Client
* @return TNC_IF_TNCCS 2.0 protocol stack
*/
-tnccs_t* tnccs_20_create(bool is_server,
- identification_t *server, identification_t *peer,
- tnc_ift_type_t transport, tnccs_cb_t cb);
+tnccs_t* tnccs_20_create(bool is_server, identification_t *server_id,
+ identification_t *peer_id, host_t *server_ip,
+ host_t *peer_ip, tnc_ift_type_t transport,
+ tnccs_cb_t cb);
#endif /** TNCCS_20_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20_client.c b/src/libtnccs/plugins/tnccs_20/tnccs_20_client.c
new file mode 100644
index 000000000..4ba8221d0
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/tnccs_20_client.c
@@ -0,0 +1,820 @@
+/*
+ * Copyright (C) 2015 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 "tnccs_20_client.h"
+#include "messages/pb_tnc_msg.h"
+#include "messages/ietf/pb_pa_msg.h"
+#include "messages/ietf/pb_error_msg.h"
+#include "messages/ietf/pb_assessment_result_msg.h"
+#include "messages/ietf/pb_access_recommendation_msg.h"
+#include "messages/ietf/pb_remediation_parameters_msg.h"
+#include "messages/ietf/pb_reason_string_msg.h"
+#include "messages/ietf/pb_language_preference_msg.h"
+#include "messages/ita/pb_mutual_capability_msg.h"
+#include "messages/ita/pb_noskip_test_msg.h"
+#include "messages/tcg/pb_pdp_referral_msg.h"
+#include "state_machine/pb_tnc_state_machine.h"
+
+#include <tncif_names.h>
+#include <tncif_pa_subtypes.h>
+
+#include <tnc/tnc.h>
+#include <tnc/tnccs/tnccs_manager.h>
+#include <tnc/imc/imc_manager.h>
+
+#include <threading/mutex.h>
+#include <utils/debug.h>
+#include <collections/linked_list.h>
+#include <pen/pen.h>
+
+typedef struct private_tnccs_20_client_t private_tnccs_20_client_t;
+
+/**
+ * Private data of a tnccs_20_client_t object.
+ */
+struct private_tnccs_20_client_t {
+
+ /**
+ * Public tnccs_20_client_t interface.
+ */
+ tnccs_20_client_t public;
+
+ /**
+ * PB-TNC State Machine
+ */
+ pb_tnc_state_machine_t *state_machine;
+
+ /**
+ * Connection ID assigned to this TNCCS connection
+ */
+ TNC_ConnectionID connection_id;
+
+ /**
+ * PB-TNC messages to be sent
+ */
+ linked_list_t *messages;
+
+ /**
+ * Type of PB-TNC batch being constructed
+ */
+ pb_tnc_batch_type_t batch_type;
+
+ /**
+ * Maximum PB-TNC batch size
+ */
+ size_t max_batch_len;
+
+ /**
+ * Mutex locking the batch in construction
+ */
+ mutex_t *mutex;
+
+ /**
+ * Flag set while processing
+ */
+ bool fatal_error;
+
+ /**
+ * Flag set by IMC RequestHandshakeRetry() function
+ */
+ bool request_handshake_retry;
+
+ /**
+ * SendMessage() by IMC only allowed if flag is set
+ */
+ bool send_msg;
+
+ /**
+ * PDP server FQDN
+ */
+ chunk_t pdp_server;
+
+ /**
+ * PDP server port
+ */
+ u_int16_t pdp_port;
+
+ /**
+ * Mutual PB-TNC protocol enabled
+ */
+ bool mutual;
+
+ /**
+ * Mutual Capability message sent
+ */
+ bool sent_mutual_capability;
+
+};
+
+/**
+ * The following two functions are shared with the tnccs_20_server class
+ */
+void tnccs_20_handle_ietf_error_msg(pb_tnc_msg_t *msg, bool *fatal_error)
+{
+ pb_error_msg_t *err_msg;
+ u_int32_t vendor_id;
+ u_int16_t error_code;
+ bool fatal;
+
+ err_msg = (pb_error_msg_t*)msg;
+ fatal = err_msg->get_fatal_flag(err_msg);
+ vendor_id = err_msg->get_vendor_id(err_msg);
+ error_code = err_msg->get_error_code(err_msg);
+
+ if (fatal)
+ {
+ *fatal_error = TRUE;
+ }
+
+ if (vendor_id == PEN_IETF)
+ {
+ switch (error_code)
+ {
+ case PB_ERROR_INVALID_PARAMETER:
+ case PB_ERROR_UNSUPPORTED_MANDATORY_MSG:
+ DBG1(DBG_TNC, "received %s PB-TNC error '%N' (offset %u bytes)",
+ fatal ? "fatal" : "non-fatal",
+ pb_tnc_error_code_names, error_code,
+ err_msg->get_offset(err_msg));
+ break;
+ case PB_ERROR_VERSION_NOT_SUPPORTED:
+ DBG1(DBG_TNC, "received %s PB-TNC error '%N' "
+ "caused by bad version 0x%02x",
+ fatal ? "fatal" : "non-fatal",
+ pb_tnc_error_code_names, error_code,
+ err_msg->get_bad_version(err_msg));
+ break;
+ case PB_ERROR_UNEXPECTED_BATCH_TYPE:
+ case PB_ERROR_LOCAL_ERROR:
+ default:
+ DBG1(DBG_TNC, "received %s PB-TNC error '%N'",
+ fatal ? "fatal" : "non-fatal",
+ pb_tnc_error_code_names, error_code);
+ break;
+ }
+ }
+ else
+ {
+ DBG1(DBG_TNC, "received %s PB-TNC error (%u) with Vendor ID 0x%06x",
+ fatal ? "fatal" : "non-fatal", error_code, vendor_id);
+ }
+}
+
+bool tnccs_20_handle_ita_mutual_capability_msg(pb_tnc_msg_t *msg)
+{
+ pb_mutual_capability_msg_t *mutual_msg;
+ uint32_t protocols;
+
+ if (!lib->settings->get_bool(lib->settings,
+ "%s.plugins.tnccs-20.mutual", FALSE, lib->ns))
+ {
+ /* PB-TNC mutual capability disabled, ignore message */
+ return FALSE;
+ }
+
+ mutual_msg = (pb_mutual_capability_msg_t*)msg;
+ protocols = mutual_msg->get_protocols(mutual_msg);
+
+ if (protocols & PB_MUTUAL_HALF_DUPLEX)
+ {
+ DBG1(DBG_TNC, "activating mutual PB-TNC %N protocol",
+ pb_tnc_mutual_protocol_type_names, PB_MUTUAL_HALF_DUPLEX);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * If the batch type changes then delete all accumulated PB-TNC messages
+ */
+static void change_batch_type(private_tnccs_20_client_t *this,
+ pb_tnc_batch_type_t batch_type)
+{
+ pb_tnc_msg_t *msg;
+
+ if (batch_type != this->batch_type)
+ {
+ if (this->batch_type != PB_BATCH_NONE)
+ {
+ DBG1(DBG_TNC, "cancelling PB-TNC %N batch",
+ pb_tnc_batch_type_names, this->batch_type);
+
+ while (this->messages->remove_last(this->messages,
+ (void**)&msg) == SUCCESS)
+ {
+ msg->destroy(msg);
+ }
+ }
+ this->batch_type = batch_type;
+ }
+}
+
+/**
+ * Handle a single PB-TNC IETF standard message according to its type
+ */
+static void handle_ietf_message(private_tnccs_20_client_t *this, pb_tnc_msg_t *msg)
+{
+ pen_type_t msg_type = msg->get_type(msg);
+
+ switch (msg_type.type)
+ {
+ case PB_MSG_EXPERIMENTAL:
+ /* nothing to do */
+ break;
+ case PB_MSG_PA:
+ {
+ pb_pa_msg_t *pa_msg;
+ pen_type_t msg_subtype;
+ u_int16_t imc_id, imv_id;
+ chunk_t msg_body;
+ bool excl;
+ enum_name_t *pa_subtype_names;
+
+ pa_msg = (pb_pa_msg_t*)msg;
+ msg_subtype = pa_msg->get_subtype(pa_msg);
+ msg_body = pa_msg->get_body(pa_msg);
+ imc_id = pa_msg->get_collector_id(pa_msg);
+ imv_id = pa_msg->get_validator_id(pa_msg);
+ excl = pa_msg->get_exclusive_flag(pa_msg);
+
+ pa_subtype_names = get_pa_subtype_names(msg_subtype.vendor_id);
+ if (pa_subtype_names)
+ {
+ DBG2(DBG_TNC, "handling PB-PA message type '%N/%N' 0x%06x/0x%08x",
+ pen_names, msg_subtype.vendor_id, pa_subtype_names,
+ msg_subtype.type, msg_subtype.vendor_id, msg_subtype.type);
+ }
+ else
+ {
+ DBG2(DBG_TNC, "handling PB-PA message type '%N' 0x%06x/0x%08x",
+ pen_names, msg_subtype.vendor_id, msg_subtype.vendor_id,
+ msg_subtype.type);
+ }
+ this->send_msg = TRUE;
+ tnc->imcs->receive_message(tnc->imcs, this->connection_id,
+ excl, msg_body.ptr, msg_body.len,
+ msg_subtype.vendor_id,
+ msg_subtype.type, imv_id, imc_id);
+ this->send_msg = FALSE;
+ break;
+ }
+ case PB_MSG_ASSESSMENT_RESULT:
+ {
+ pb_assessment_result_msg_t *assess_msg;
+ u_int32_t result;
+
+ assess_msg = (pb_assessment_result_msg_t*)msg;
+ result = assess_msg->get_assessment_result(assess_msg);
+ DBG1(DBG_TNC, "PB-TNC assessment result is '%N'",
+ TNC_IMV_Evaluation_Result_names, result);
+ break;
+ }
+ case PB_MSG_ACCESS_RECOMMENDATION:
+ {
+ pb_access_recommendation_msg_t *rec_msg;
+ pb_access_recommendation_code_t rec;
+ TNC_ConnectionState state = TNC_CONNECTION_STATE_ACCESS_NONE;
+
+ rec_msg = (pb_access_recommendation_msg_t*)msg;
+ rec = rec_msg->get_access_recommendation(rec_msg);
+ DBG1(DBG_TNC, "PB-TNC access recommendation is '%N'",
+ pb_access_recommendation_code_names, rec);
+ switch (rec)
+ {
+ case PB_REC_ACCESS_ALLOWED:
+ state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
+ break;
+ case PB_REC_ACCESS_DENIED:
+ state = TNC_CONNECTION_STATE_ACCESS_NONE;
+ break;
+ case PB_REC_QUARANTINED:
+ state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
+ }
+ tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
+ state);
+ break;
+ }
+ case PB_MSG_REMEDIATION_PARAMETERS:
+ {
+ pb_remediation_parameters_msg_t *rem_msg;
+ pen_type_t parameters_type;
+ chunk_t parameters, string, lang_code;
+
+ rem_msg = (pb_remediation_parameters_msg_t*)msg;
+ parameters_type = rem_msg->get_parameters_type(rem_msg);
+ parameters = rem_msg->get_parameters(rem_msg);
+
+ if (parameters_type.vendor_id == PEN_IETF)
+ {
+ switch (parameters_type.type)
+ {
+ case PB_REMEDIATION_URI:
+ DBG1(DBG_TNC, "remediation uri: %.*s",
+ parameters.len, parameters.ptr);
+ break;
+ case PB_REMEDIATION_STRING:
+ string = rem_msg->get_string(rem_msg, &lang_code);
+ DBG1(DBG_TNC, "remediation string: [%.*s]\n%.*s",
+ lang_code.len, lang_code.ptr,
+ string.len, string.ptr);
+ break;
+ default:
+ DBG1(DBG_TNC, "remediation parameters: %B", &parameters);
+ }
+ }
+ else
+ {
+ DBG1(DBG_TNC, "remediation parameters: %B", &parameters);
+ }
+ break;
+ }
+ case PB_MSG_ERROR:
+ tnccs_20_handle_ietf_error_msg(msg, &this->fatal_error);
+ break;
+ case PB_MSG_REASON_STRING:
+ {
+ pb_reason_string_msg_t *reason_msg;
+ chunk_t reason_string, language_code;
+
+ reason_msg = (pb_reason_string_msg_t*)msg;
+ reason_string = reason_msg->get_reason_string(reason_msg);
+ language_code = reason_msg->get_language_code(reason_msg);
+ DBG1(DBG_TNC, "reason string is '%.*s' [%.*s]",
+ (int)reason_string.len, reason_string.ptr,
+ (int)language_code.len, language_code.ptr);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+/**
+ * Handle a single PB-TNC TCG standard message according to its type
+ */
+static void handle_tcg_message(private_tnccs_20_client_t *this, pb_tnc_msg_t *msg)
+{
+ pen_type_t msg_type = msg->get_type(msg);
+
+ switch (msg_type.type)
+ {
+ case PB_TCG_MSG_PDP_REFERRAL:
+ {
+ pb_pdp_referral_msg_t *pdp_msg;
+ pen_type_t pdp_id_type;
+ u_int8_t pdp_protocol;
+
+ pdp_msg = (pb_pdp_referral_msg_t*)msg;
+ pdp_id_type = pdp_msg->get_identifier_type(pdp_msg);
+
+ if (pdp_id_type.vendor_id == PEN_TCG &&
+ pdp_id_type.type == PB_PDP_ID_FQDN)
+ {
+ this->pdp_server = chunk_clone(pdp_msg->get_fqdn(pdp_msg,
+ &pdp_protocol, &this->pdp_port));
+ if (pdp_protocol != 0)
+ {
+ DBG1(DBG_TNC, "unsupported PDP transport protocol");
+ break;
+ }
+ DBG1(DBG_TNC, "PDP server '%.*s' is listening on port %u",
+ this->pdp_server.len, this->pdp_server.ptr,
+ this->pdp_port);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+/**
+ * Handle a single PB-TNC ITA standard message according to its type
+ */
+static void handle_ita_message(private_tnccs_20_client_t *this, pb_tnc_msg_t *msg)
+{
+ pen_type_t msg_type = msg->get_type(msg);
+
+ switch (msg_type.type)
+ {
+ case PB_ITA_MSG_MUTUAL_CAPABILITY:
+ this->mutual = tnccs_20_handle_ita_mutual_capability_msg(msg);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Handle a single PB-TNC message according to its type
+ */
+static void handle_message(private_tnccs_20_client_t *this, pb_tnc_msg_t *msg)
+{
+ pen_type_t msg_type = msg->get_type(msg);
+
+ switch (msg_type.vendor_id)
+ {
+ case PEN_IETF:
+ handle_ietf_message(this, msg);
+ break;
+ case PEN_TCG:
+ handle_tcg_message(this, msg);
+ break;
+ case PEN_ITA:
+ handle_ita_message(this, msg);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Build a CRETRY batch
+ */
+static void build_retry_batch(private_tnccs_20_client_t *this)
+{
+ if (this->batch_type == PB_BATCH_CRETRY)
+ {
+ /* retry batch has already been selected */
+ return;
+ }
+ change_batch_type(this, PB_BATCH_CRETRY);
+}
+
+METHOD(tnccs_20_handler_t, process, status_t,
+ private_tnccs_20_client_t *this, pb_tnc_batch_t *batch)
+{
+ pb_tnc_batch_type_t batch_type;
+ status_t status;
+
+ batch_type = batch->get_type(batch);
+
+ DBG1(DBG_TNC, "processing PB-TNC %N batch for Connection ID %d",
+ pb_tnc_batch_type_names, batch_type, this->connection_id);
+
+ status = batch->process(batch, this->state_machine);
+
+ if (status != FAILED)
+ {
+ enumerator_t *enumerator;
+ pb_tnc_msg_t *msg;
+ bool empty = TRUE;
+
+ if (batch_type == PB_BATCH_SRETRY)
+ {
+ /* Restart the measurements */
+ tnc->imcs->notify_connection_change(tnc->imcs,
+ this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE);
+ this->send_msg = TRUE;
+ tnc->imcs->begin_handshake(tnc->imcs, this->connection_id);
+ this->send_msg = FALSE;
+ }
+
+ enumerator = batch->create_msg_enumerator(batch);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ handle_message(this, msg);
+ empty = FALSE;
+ }
+ enumerator->destroy(enumerator);
+
+ /* received a CLOSE batch from PB-TNC server */
+ if (batch_type == PB_BATCH_CLOSE)
+ {
+ return empty ? SUCCESS : FAILED;
+ }
+
+ this->send_msg = TRUE;
+ tnc->imcs->batch_ending(tnc->imcs, this->connection_id);
+ this->send_msg = FALSE;
+ }
+
+ switch (status)
+ {
+ case FAILED:
+ this->fatal_error = TRUE;
+ status = VERIFY_ERROR;
+ break;
+ case VERIFY_ERROR:
+ break;
+ case SUCCESS:
+ default:
+ status = NEED_MORE;
+ break;
+ }
+
+ return status;
+}
+
+METHOD(tnccs_20_handler_t, build, status_t,
+ private_tnccs_20_client_t *this, void *buf, size_t *buflen, size_t *msglen)
+{
+ status_t status;
+ pb_tnc_state_t state;
+
+ state = this->state_machine->get_state(this->state_machine);
+
+ if (this->fatal_error && state == PB_STATE_END)
+ {
+ DBG1(DBG_TNC, "a fatal PB-TNC error occurred, terminating connection");
+ return FAILED;
+ }
+
+ /* Do not allow any asynchronous IMCs to add additional messages */
+ this->mutex->lock(this->mutex);
+
+ if (this->request_handshake_retry)
+ {
+ if (state != PB_STATE_INIT)
+ {
+ build_retry_batch(this);
+ }
+
+ /* Reset the flag for the next handshake retry request */
+ this->request_handshake_retry = FALSE;
+ }
+
+ if (this->batch_type == PB_BATCH_NONE)
+ {
+ switch (state)
+ {
+ case PB_STATE_CLIENT_WORKING:
+ DBG2(DBG_TNC, "no client data to send, "
+ "sending empty PB-TNC CDATA batch");
+ this->batch_type = PB_BATCH_CDATA;
+ break;
+ case PB_STATE_DECIDED:
+ /**
+ * In the DECIDED state and if no CRETRY is under way,
+ * a PB-TNC client replies with an empty CLOSE batch.
+ */
+ this->batch_type = PB_BATCH_CLOSE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (this->batch_type != PB_BATCH_NONE)
+ {
+ pb_tnc_batch_t *batch;
+ pb_tnc_msg_t *msg;
+ chunk_t data;
+ int msg_count;
+ enumerator_t *enumerator;
+
+ if (this->state_machine->send_batch(this->state_machine, this->batch_type))
+ {
+ batch = pb_tnc_batch_create(FALSE, this->batch_type,
+ min(this->max_batch_len, *buflen));
+
+ enumerator = this->messages->create_enumerator(this->messages);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ if (batch->add_msg(batch, msg))
+ {
+ this->messages->remove_at(this->messages, enumerator);
+ }
+ else
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ batch->build(batch);
+ data = batch->get_encoding(batch);
+ DBG1(DBG_TNC, "sending PB-TNC %N batch (%d bytes) for Connection ID %u",
+ pb_tnc_batch_type_names, this->batch_type, data.len,
+ this->connection_id);
+ DBG3(DBG_TNC, "%B", &data);
+
+ *buflen = data.len;
+ *msglen = 0;
+ memcpy(buf, data.ptr, *buflen);
+ batch->destroy(batch);
+
+ msg_count = this->messages->get_count(this->messages);
+ if (msg_count)
+ {
+ DBG2(DBG_TNC, "queued %d PB-TNC message%s for next %N batch",
+ msg_count, (msg_count == 1) ? "" : "s",
+ pb_tnc_batch_type_names, this->batch_type);
+ }
+ else
+ {
+ this->batch_type = PB_BATCH_NONE;
+ }
+
+ status = ALREADY_DONE;
+ }
+ else
+ {
+ change_batch_type(this, PB_BATCH_NONE);
+ status = INVALID_STATE;
+ }
+ }
+ else
+ {
+ DBG1(DBG_TNC, "no PB-TNC batch to send");
+ status = INVALID_STATE;
+ }
+ this->mutex->unlock(this->mutex);
+
+ return status;
+}
+
+METHOD(tnccs_20_handler_t, begin_handshake, void,
+ private_tnccs_20_client_t *this, bool mutual)
+{
+ pb_tnc_msg_t *msg;
+ char *pref_lang;
+
+ tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
+ TNC_CONNECTION_STATE_HANDSHAKE);
+
+ /* Announce PB-TNC Mutual Capability if activated */
+ this->sent_mutual_capability = mutual;
+
+ if (!mutual && lib->settings->get_bool(lib->settings,
+ "%s.plugins.tnccs-20.mutual", FALSE, lib->ns))
+ {
+ pb_tnc_mutual_protocol_type_t protocols;
+
+ protocols = PB_MUTUAL_HALF_DUPLEX;
+ DBG2(DBG_TNC, "proposing PB-TNC mutual %N protocol",
+ pb_tnc_mutual_protocol_type_names, PB_MUTUAL_HALF_DUPLEX);
+ msg = pb_mutual_capability_msg_create(protocols);
+ this->mutex->lock(this->mutex);
+ this->messages->insert_last(this->messages, msg);
+ this->mutex->unlock(this->mutex);
+ this->sent_mutual_capability = TRUE;
+ }
+
+ /* Create PB-TNC Language Preference message */
+ pref_lang = tnc->imcs->get_preferred_language(tnc->imcs);
+ msg = pb_language_preference_msg_create(chunk_create(pref_lang,
+ strlen(pref_lang)));
+ this->mutex->lock(this->mutex);
+ this->messages->insert_last(this->messages, msg);
+ this->mutex->unlock(this->mutex);
+
+ this->send_msg = TRUE;
+ tnc->imcs->begin_handshake(tnc->imcs, this->connection_id);
+ this->send_msg = FALSE;
+
+ /* Send a PB-Noskip-Test message for testing purposes */
+ if (lib->settings->get_bool(lib->settings,
+ "%s.plugins.tnccs-20.tests.pb_tnc_noskip", FALSE, lib->ns))
+ {
+ msg = pb_noskip_test_msg_create();
+ this->mutex->lock(this->mutex);
+ this->messages->insert_last(this->messages, msg);
+ this->mutex->unlock(this->mutex);
+ }
+}
+
+METHOD(tnccs_20_handler_t, get_send_flag, bool,
+ private_tnccs_20_client_t *this)
+{
+ return this->send_msg;
+}
+
+METHOD(tnccs_20_handler_t, get_mutual, bool,
+ private_tnccs_20_client_t *this)
+{
+ return this->mutual;
+}
+
+METHOD(tnccs_20_handler_t, get_state, pb_tnc_state_t,
+ private_tnccs_20_client_t *this)
+{
+ return this->state_machine->get_state(this->state_machine);
+}
+
+METHOD(tnccs_20_handler_t, add_msg, void,
+ private_tnccs_20_client_t *this, pb_tnc_msg_t *msg)
+{
+ /* adding PA message to CDATA batch only */
+ this->mutex->lock(this->mutex);
+ if (this->batch_type == PB_BATCH_NONE)
+ {
+ this->batch_type = PB_BATCH_CDATA;
+ }
+ if (this->batch_type == PB_BATCH_CDATA)
+ {
+ this->messages->insert_last(this->messages, msg);
+ }
+ else
+ {
+ msg->destroy(msg);
+ }
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(tnccs_20_handler_t, handle_errors, void,
+ private_tnccs_20_client_t *this, pb_tnc_batch_t *batch,
+ bool fatal_header_error)
+{
+ pb_tnc_msg_t *msg;
+ enumerator_t *enumerator;
+
+ if (fatal_header_error || this->fatal_error)
+ {
+ this->mutex->lock(this->mutex);
+ change_batch_type(this, PB_BATCH_CLOSE);
+ this->mutex->unlock(this->mutex);
+ }
+
+ enumerator = batch->create_error_enumerator(batch);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ this->mutex->lock(this->mutex);
+ this->messages->insert_last(this->messages, msg->get_ref(msg));
+ this->mutex->unlock(this->mutex);
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(tnccs_20_handler_t, destroy, void,
+ private_tnccs_20_client_t *this)
+{
+ if (this->connection_id)
+ {
+ tnc->tnccs->remove_connection(tnc->tnccs, this->connection_id, FALSE);
+ }
+ this->state_machine->destroy(this->state_machine);
+ this->mutex->destroy(this->mutex);
+ this->messages->destroy_offset(this->messages,
+ offsetof(pb_tnc_msg_t, destroy));
+ free(this->pdp_server.ptr);
+ free(this);
+}
+
+METHOD(tnccs_20_client_t, get_pdp_server, chunk_t,
+ private_tnccs_20_client_t *this, u_int16_t *port)
+{
+ *port = this->pdp_port;
+
+ return this->pdp_server;
+}
+
+/**
+ * See header
+ */
+tnccs_20_handler_t* tnccs_20_client_create(tnccs_t *tnccs,
+ tnccs_send_message_t send_msg,
+ size_t max_batch_len,
+ size_t max_msg_len)
+{
+ private_tnccs_20_client_t *this;
+
+ INIT(this,
+ .public = {
+ .handler = {
+ .process = _process,
+ .build = _build,
+ .begin_handshake = _begin_handshake,
+ .get_send_flag = _get_send_flag,
+ .get_mutual = _get_mutual,
+ .get_state = _get_state,
+ .add_msg = _add_msg,
+ .handle_errors = _handle_errors,
+ .destroy = _destroy,
+ },
+ .get_pdp_server = _get_pdp_server,
+ },
+ .state_machine = pb_tnc_state_machine_create(FALSE),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .messages = linked_list_create(),
+ .batch_type = PB_BATCH_CDATA,
+ .max_batch_len = max_batch_len,
+ );
+
+ this->connection_id = tnc->tnccs->create_connection(tnc->tnccs,
+ TNCCS_2_0, tnccs, send_msg,
+ &this->request_handshake_retry,
+ max_msg_len, NULL);
+ if (!this->connection_id)
+ {
+ destroy(this);
+ return NULL;
+ }
+ tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id,
+ TNC_CONNECTION_STATE_CREATE);
+
+ return &this->public.handler;
+}
diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20_client.h b/src/libtnccs/plugins/tnccs_20/tnccs_20_client.h
new file mode 100644
index 000000000..7a5f33ebc
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/tnccs_20_client.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 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 tnccs_20_client_h tnccs_20_client
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef TNCCS_20_CLIENT_H_
+#define TNCCS_20_CLIENT_H_
+
+#include <library.h>
+
+#include <tnc/tnccs/tnccs.h>
+
+#include "tnccs_20_handler.h"
+
+typedef struct tnccs_20_client_t tnccs_20_client_t;
+
+/**
+ * Interface for a TNC client
+ */
+struct tnccs_20_client_t {
+
+ /**
+ * IF-TNCCS 2.0 protocol handler interface
+ */
+ tnccs_20_handler_t handler;
+
+ /**
+ * Get PDP server information if available
+ *
+ * @param port PT-TLS port of the PDP server
+ * @return FQDN of PDP server
+ */
+ chunk_t (*get_pdp_server)(tnccs_20_client_t *this, u_int16_t *port);
+
+};
+
+/**
+ * Create an instance of the TNC IF-TNCCS 2.0 client-side protocol handler.
+ *
+ * @param tnccs TNC IF-TNCCS 2.0 stack
+ * @param send_msg TNF IF-TNCCS 2.0 send message callback function
+ * @param max_batch_len Maximum PB-TNC batch size
+ * @param max_msg_len Maximum PA-TNC message size
+ */
+tnccs_20_handler_t* tnccs_20_client_create(tnccs_t *tnccs,
+ tnccs_send_message_t send_msg,
+ size_t max_batch_len,
+ size_t max_msg_len);
+
+#endif /** TNCCS_20_CLIENT_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20_handler.h b/src/libtnccs/plugins/tnccs_20/tnccs_20_handler.h
new file mode 100644
index 000000000..5c4d7a7b4
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/tnccs_20_handler.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015 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 tnccs_20_handler_h tnccs_20_handler
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef TNCCS_20_HANDLER_H_
+#define TNCCS_20_HANDLER_H_
+
+#include <library.h>
+
+#include "batch/pb_tnc_batch.h"
+#include "messages/pb_tnc_msg.h"
+
+typedef struct tnccs_20_handler_t tnccs_20_handler_t;
+
+/**
+ * Interface for an IF-TNCCS 2.0 protocol handler
+ */
+struct tnccs_20_handler_t {
+
+ /**
+ * Process content of received PB-TNC batch
+ *
+ * @param batch PB-TNC batch to be processed
+ * @return status
+ */
+ status_t (*process)(tnccs_20_handler_t *this, pb_tnc_batch_t *batch);
+
+ /**
+ * Build PB-TNC batch to be sent
+ *
+ * @param buf buffer to write PB-TNC batch to
+ * @param buflen size of buffer, receives bytes written
+ * @param msglen receives size of all PB-TNCH batch
+ * @return status
+ */
+ status_t (*build)(tnccs_20_handler_t *this, void *buf, size_t *buflen,
+ size_t *msglen);
+
+ /**
+ * Put the IMCs or IMVs into the handshake state
+ *
+ * @param mutual TRUE if PB-TNC mutual mode is already established
+ */
+ void (*begin_handshake)(tnccs_20_handler_t *this, bool mutual);
+
+ /**
+ * Indicates if IMCs or IMVs are allowed to send PA-TNC messages
+ *
+ * @return TRUE if allowed to send
+ */
+ bool (*get_send_flag)(tnccs_20_handler_t *this);
+
+ /**
+ * Indicates if the PB-TNC mutual protocol has been enabled
+ *
+ * @return TRUE if enabled
+ */
+ bool (*get_mutual)(tnccs_20_handler_t *this);
+
+ /**
+ * Get state of the PB-TNC protocol
+ *
+ * @return PB-TNC state
+ */
+ pb_tnc_state_t (*get_state)(tnccs_20_handler_t *this);
+
+ /**
+ * Add a PB-PA message to the handler's message queue
+ *
+ * @param msg PB-PA message to be added
+ */
+ void (*add_msg)(tnccs_20_handler_t *this, pb_tnc_msg_t *msg);
+
+ /**
+ * Handle errors that occurred during PB-TNC batch header processing
+ *
+ * @param batch batch where a fatal error occurred
+ * @param fatal_header_error TRUE if fatal error in batch header
+ */
+ void (*handle_errors)(tnccs_20_handler_t *this, pb_tnc_batch_t *batch,
+ bool fatal_header_error);
+
+ /**
+ * Destroys a tnccs_20_handler_t object.
+ */
+ void (*destroy)(tnccs_20_handler_t *this);
+};
+
+#endif /** TNCCS_20_HANDLER_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20_plugin.h b/src/libtnccs/plugins/tnccs_20/tnccs_20_plugin.h
index 1c4ecf4c9..5073fbe7c 100644
--- a/src/libtnccs/plugins/tnccs_20/tnccs_20_plugin.h
+++ b/src/libtnccs/plugins/tnccs_20/tnccs_20_plugin.h
@@ -15,7 +15,7 @@
/**
* @defgroup tnccs_20 tnccs_20
- * @ingroup cplugins
+ * @ingroup tplugins
*
* @defgroup tnccs_20_plugin tnccs_20_plugin
* @{ @ingroup tnccs_20
diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20_server.c b/src/libtnccs/plugins/tnccs_20/tnccs_20_server.c
new file mode 100644
index 000000000..038fc178b
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/tnccs_20_server.c
@@ -0,0 +1,693 @@
+/*
+ * Copyright (C) 2015 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 "tnccs_20_server.h"
+#include "messages/pb_tnc_msg.h"
+#include "messages/ietf/pb_pa_msg.h"
+#include "messages/ietf/pb_error_msg.h"
+#include "messages/ietf/pb_assessment_result_msg.h"
+#include "messages/ietf/pb_access_recommendation_msg.h"
+#include "messages/ietf/pb_remediation_parameters_msg.h"
+#include "messages/ietf/pb_reason_string_msg.h"
+#include "messages/ietf/pb_language_preference_msg.h"
+#include "messages/ita/pb_mutual_capability_msg.h"
+#include "messages/ita/pb_noskip_test_msg.h"
+#include "messages/tcg/pb_pdp_referral_msg.h"
+#include "state_machine/pb_tnc_state_machine.h"
+
+#include <tncif_names.h>
+#include <tncif_pa_subtypes.h>
+
+#include <tnc/tnc.h>
+#include <tnc/tnccs/tnccs_manager.h>
+#include <tnc/imv/imv_manager.h>
+
+#include <threading/mutex.h>
+#include <utils/debug.h>
+#include <collections/linked_list.h>
+#include <pen/pen.h>
+
+typedef struct private_tnccs_20_server_t private_tnccs_20_server_t;
+
+/**
+ * Private data of a tnccs_20_server_t object.
+ */
+struct private_tnccs_20_server_t {
+
+ /**
+ * Public tnccs_20_server_t interface.
+ */
+ tnccs_20_server_t public;
+
+ /**
+ * PB-TNC State Machine
+ */
+ pb_tnc_state_machine_t *state_machine;
+
+ /**
+ * Connection ID assigned to this TNCCS connection
+ */
+ TNC_ConnectionID connection_id;
+
+ /**
+ * PB-TNC messages to be sent
+ */
+ linked_list_t *messages;
+
+ /**
+ * Type of PB-TNC batch being constructed
+ */
+ pb_tnc_batch_type_t batch_type;
+
+ /**
+ * Maximum PB-TNC batch size
+ */
+ size_t max_batch_len;
+
+ /**
+ * Mutex locking the batch in construction
+ */
+ mutex_t *mutex;
+
+ /**
+ * Flag set while processing
+ */
+ bool fatal_error;
+
+ /**
+ * Flag set by IMC/IMV RequestHandshakeRetry() function
+ */
+ bool request_handshake_retry;
+
+ /**
+ * SendMessage() by IMV only allowed if flag is set
+ */
+ bool send_msg;
+
+ /**
+ * Set of IMV recommendations
+ */
+ recommendations_t *recs;
+
+ /**
+ * TNC IF-T transport protocol for EAP methods
+ */
+ bool eap_transport;
+
+ /**
+ * Mutual PB-TNC protocol enabled
+ */
+ bool mutual;
+
+ /**
+ * Mutual Capability message sent
+ */
+ bool sent_mutual_capability;
+
+};
+
+/**
+ * The following two functions are shared with the tnccs_20_server class
+ */
+extern void tnccs_20_handle_ietf_error_msg(pb_tnc_msg_t *msg,
+ bool *fatal_error);
+extern bool tnccs_20_handle_ita_mutual_capability_msg(pb_tnc_msg_t *msg);
+
+/**
+ * If the batch type changes then delete all accumulated PB-TNC messages
+ */
+static void change_batch_type(private_tnccs_20_server_t *this,
+ pb_tnc_batch_type_t batch_type)
+{
+ pb_tnc_msg_t *msg;
+
+ if (batch_type != this->batch_type)
+ {
+ if (this->batch_type != PB_BATCH_NONE)
+ {
+ DBG1(DBG_TNC, "cancelling PB-TNC %N batch",
+ pb_tnc_batch_type_names, this->batch_type);
+
+ while (this->messages->remove_last(this->messages,
+ (void**)&msg) == SUCCESS)
+ {
+ msg->destroy(msg);
+ }
+ }
+ this->batch_type = batch_type;
+ }
+}
+
+/**
+ * Handle a single PB-TNC IETF standard message according to its type
+ */
+static void handle_ietf_message(private_tnccs_20_server_t *this, pb_tnc_msg_t *msg)
+{
+ pen_type_t msg_type = msg->get_type(msg);
+
+ switch (msg_type.type)
+ {
+ case PB_MSG_EXPERIMENTAL:
+ /* nothing to do */
+ break;
+ case PB_MSG_PA:
+ {
+ pb_pa_msg_t *pa_msg;
+ pen_type_t msg_subtype;
+ u_int16_t imc_id, imv_id;
+ chunk_t msg_body;
+ bool excl;
+ enum_name_t *pa_subtype_names;
+
+ pa_msg = (pb_pa_msg_t*)msg;
+ msg_subtype = pa_msg->get_subtype(pa_msg);
+ msg_body = pa_msg->get_body(pa_msg);
+ imc_id = pa_msg->get_collector_id(pa_msg);
+ imv_id = pa_msg->get_validator_id(pa_msg);
+ excl = pa_msg->get_exclusive_flag(pa_msg);
+
+ pa_subtype_names = get_pa_subtype_names(msg_subtype.vendor_id);
+ if (pa_subtype_names)
+ {
+ DBG2(DBG_TNC, "handling PB-PA message type '%N/%N' 0x%06x/0x%08x",
+ pen_names, msg_subtype.vendor_id, pa_subtype_names,
+ msg_subtype.type, msg_subtype.vendor_id, msg_subtype.type);
+ }
+ else
+ {
+ DBG2(DBG_TNC, "handling PB-PA message type '%N' 0x%06x/0x%08x",
+ pen_names, msg_subtype.vendor_id, msg_subtype.vendor_id,
+ msg_subtype.type);
+ }
+ this->send_msg = TRUE;
+ tnc->imvs->receive_message(tnc->imvs, this->connection_id,
+ excl, msg_body.ptr, msg_body.len,
+ msg_subtype.vendor_id,
+ msg_subtype.type, imc_id, imv_id);
+ this->send_msg = FALSE;
+ break;
+ }
+ case PB_MSG_ERROR:
+ tnccs_20_handle_ietf_error_msg(msg, &this->fatal_error);
+ break;
+ case PB_MSG_LANGUAGE_PREFERENCE:
+ {
+ pb_language_preference_msg_t *lang_msg;
+ chunk_t lang;
+
+ lang_msg = (pb_language_preference_msg_t*)msg;
+ lang = lang_msg->get_language_preference(lang_msg);
+ DBG2(DBG_TNC, "setting language preference to '%.*s'",
+ (int)lang.len, lang.ptr);
+ this->recs->set_preferred_language(this->recs, lang);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+/**
+ * Handle a single PB-TNC ITA standard message according to its type
+ */
+static void handle_ita_message(private_tnccs_20_server_t *this, pb_tnc_msg_t *msg)
+{
+ pen_type_t msg_type = msg->get_type(msg);
+
+ switch (msg_type.type)
+ {
+ case PB_ITA_MSG_MUTUAL_CAPABILITY:
+ this->mutual = tnccs_20_handle_ita_mutual_capability_msg(msg);
+
+ /* Respond with PB-TNC Mutual Capability message if necessary */
+ if (this->mutual && !this->sent_mutual_capability)
+ {
+ msg = pb_mutual_capability_msg_create(PB_MUTUAL_HALF_DUPLEX);
+ this->mutex->lock(this->mutex);
+ this->messages->insert_last(this->messages, msg);
+ this->mutex->unlock(this->mutex);
+ this->sent_mutual_capability = TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Handle a single PB-TNC message according to its type
+ */
+static void handle_message(private_tnccs_20_server_t *this, pb_tnc_msg_t *msg)
+{
+ pen_type_t msg_type = msg->get_type(msg);
+
+ switch (msg_type.vendor_id)
+ {
+ case PEN_IETF:
+ handle_ietf_message(this, msg);
+ break;
+ case PEN_ITA:
+ handle_ita_message(this, msg);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Build an SRETRY batch
+ */
+static void build_retry_batch(private_tnccs_20_server_t *this)
+{
+ if (this->batch_type == PB_BATCH_SRETRY)
+ {
+ /* retry batch has already been selected */
+ return;
+ }
+ change_batch_type(this, PB_BATCH_SRETRY);
+
+ this->recs->clear_recommendation(this->recs);
+ tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
+ TNC_CONNECTION_STATE_HANDSHAKE);
+}
+
+METHOD(tnccs_20_handler_t, process, status_t,
+ private_tnccs_20_server_t *this, pb_tnc_batch_t *batch)
+{
+ pb_tnc_batch_type_t batch_type;
+ status_t status;
+
+ batch_type = batch->get_type(batch);
+
+ DBG1(DBG_TNC, "processing PB-TNC %N batch for Connection ID %d",
+ pb_tnc_batch_type_names, batch_type, this->connection_id);
+ status = batch->process(batch, this->state_machine);
+
+ if (status != FAILED)
+ {
+ enumerator_t *enumerator;
+ pb_tnc_msg_t *msg;
+ bool empty = TRUE;
+
+ if (batch_type == PB_BATCH_CRETRY)
+ {
+ /* Send an SRETRY batch in response */
+ this->mutex->lock(this->mutex);
+ build_retry_batch(this);
+ this->mutex->unlock(this->mutex);
+ }
+
+ enumerator = batch->create_msg_enumerator(batch);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ handle_message(this, msg);
+ empty = FALSE;
+ }
+ enumerator->destroy(enumerator);
+
+ /* received a CLOSE batch from PB-TNC client */
+ if (batch_type == PB_BATCH_CLOSE)
+ {
+ return empty ? SUCCESS : FAILED;
+ }
+
+ this->send_msg = TRUE;
+ tnc->imvs->batch_ending(tnc->imvs, this->connection_id);
+ this->send_msg = FALSE;
+ }
+
+ switch (status)
+ {
+ case FAILED:
+ this->fatal_error = TRUE;
+ status = VERIFY_ERROR;
+ break;
+ case VERIFY_ERROR:
+ break;
+ case SUCCESS:
+ default:
+ status = NEED_MORE;
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * Build a RESULT batch if a final recommendation is available
+ */
+static void check_and_build_recommendation(private_tnccs_20_server_t *this)
+{
+ TNC_IMV_Action_Recommendation rec;
+ TNC_IMV_Evaluation_Result eval;
+ TNC_ConnectionState state;
+ TNC_IMVID id;
+ chunk_t reason, language;
+ enumerator_t *enumerator;
+ pb_tnc_msg_t *msg;
+ pb_access_recommendation_code_t pb_rec;
+
+ if (!this->recs->have_recommendation(this->recs, &rec, &eval))
+ {
+ tnc->imvs->solicit_recommendation(tnc->imvs, this->connection_id);
+ }
+ if (this->recs->have_recommendation(this->recs, &rec, &eval))
+ {
+ this->batch_type = PB_BATCH_RESULT;
+
+ msg = pb_assessment_result_msg_create(eval);
+ this->messages->insert_last(this->messages, msg);
+
+ /**
+ * Map IMV Action Recommendation codes to PB Access Recommendation codes
+ * and communicate Access Recommendation to IMVs
+ */
+ switch (rec)
+ {
+ case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
+ state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
+ pb_rec = PB_REC_ACCESS_ALLOWED;
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
+ state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
+ pb_rec = PB_REC_QUARANTINED;
+ break;
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
+ case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
+ default:
+ state = TNC_CONNECTION_STATE_ACCESS_NONE;
+ pb_rec = PB_REC_ACCESS_DENIED;
+ }
+ tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
+ state);
+
+ msg = pb_access_recommendation_msg_create(pb_rec);
+ this->messages->insert_last(this->messages, msg);
+
+ enumerator = this->recs->create_reason_enumerator(this->recs);
+ while (enumerator->enumerate(enumerator, &id, &reason, &language))
+ {
+ msg = pb_reason_string_msg_create(reason, language);
+ this->messages->insert_last(this->messages, msg);
+ }
+ enumerator->destroy(enumerator);
+ }
+}
+
+METHOD(tnccs_20_handler_t, build, status_t,
+ private_tnccs_20_server_t *this, void *buf, size_t *buflen, size_t *msglen)
+{
+ status_t status;
+ pb_tnc_state_t state;
+
+ state = this->state_machine->get_state(this->state_machine);
+
+ if (this->fatal_error && state == PB_STATE_END)
+ {
+ DBG1(DBG_TNC, "a fatal PB-TNC error occurred, terminating connection");
+ return FAILED;
+ }
+
+ /* Do not allow any asynchronous IMVs to add additional messages */
+ this->mutex->lock(this->mutex);
+
+ if (this->request_handshake_retry)
+ {
+ if (state != PB_STATE_INIT)
+ {
+ build_retry_batch(this);
+ }
+
+ /* Reset the flag for the next handshake retry request */
+ this->request_handshake_retry = FALSE;
+ }
+
+ if (state == PB_STATE_SERVER_WORKING &&
+ this->recs->have_recommendation(this->recs, NULL, NULL))
+ {
+ check_and_build_recommendation(this);
+ }
+
+ if (this->batch_type == PB_BATCH_NONE)
+ {
+ if (state == PB_STATE_SERVER_WORKING)
+ {
+ if (this->state_machine->get_empty_cdata(this->state_machine))
+ {
+ check_and_build_recommendation(this);
+ }
+ else
+ {
+ DBG2(DBG_TNC, "no recommendation available yet, "
+ "sending empty PB-TNC SDATA batch");
+ this->batch_type = PB_BATCH_SDATA;
+ }
+ }
+ }
+
+ if (this->batch_type != PB_BATCH_NONE)
+ {
+ pb_tnc_batch_t *batch;
+ pb_tnc_msg_t *msg;
+ chunk_t data;
+ int msg_count;
+ enumerator_t *enumerator;
+
+ if (this->state_machine->send_batch(this->state_machine, this->batch_type))
+ {
+ batch = pb_tnc_batch_create(TRUE, this->batch_type,
+ min(this->max_batch_len, *buflen));
+
+ enumerator = this->messages->create_enumerator(this->messages);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ if (batch->add_msg(batch, msg))
+ {
+ this->messages->remove_at(this->messages, enumerator);
+ }
+ else
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ batch->build(batch);
+ data = batch->get_encoding(batch);
+ DBG1(DBG_TNC, "sending PB-TNC %N batch (%d bytes) for Connection ID %u",
+ pb_tnc_batch_type_names, this->batch_type, data.len,
+ this->connection_id);
+ DBG3(DBG_TNC, "%B", &data);
+
+ *buflen = data.len;
+ *msglen = 0;
+ memcpy(buf, data.ptr, *buflen);
+ batch->destroy(batch);
+
+ msg_count = this->messages->get_count(this->messages);
+ if (msg_count)
+ {
+ DBG2(DBG_TNC, "queued %d PB-TNC message%s for next %N batch",
+ msg_count, (msg_count == 1) ? "" : "s",
+ pb_tnc_batch_type_names, this->batch_type);
+ }
+ else
+ {
+ this->batch_type = PB_BATCH_NONE;
+ }
+
+ status = ALREADY_DONE;
+ }
+ else
+ {
+ change_batch_type(this, PB_BATCH_NONE);
+ status = INVALID_STATE;
+ }
+ }
+ else
+ {
+ DBG1(DBG_TNC, "no PB-TNC batch to send");
+ status = INVALID_STATE;
+ }
+ this->mutex->unlock(this->mutex);
+
+ return status;
+}
+
+METHOD(tnccs_20_handler_t, begin_handshake, void,
+ private_tnccs_20_server_t *this, bool mutual)
+{
+ pb_tnc_msg_t *msg;
+ identification_t *pdp_server;
+ u_int16_t *pdp_port;
+
+ tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
+ TNC_CONNECTION_STATE_HANDSHAKE);
+
+ /* Send a PB-TNC TCG PDP Referral message if PDP is known */
+ pdp_server = (identification_t*)lib->get(lib, "pt-tls-server");
+ pdp_port = (u_int16_t*)lib->get(lib, "pt-tls-port");
+
+ if (this->eap_transport && pdp_server && pdp_port)
+ {
+ msg = pb_pdp_referral_msg_create_from_fqdn(
+ pdp_server->get_encoding(pdp_server), *pdp_port);
+ this->mutex->lock(this->mutex);
+ this->messages->insert_last(this->messages, msg);
+ this->mutex->unlock(this->mutex);
+ }
+
+ /* Send a PB-Noskip-Test message for testing purposes */
+ if (lib->settings->get_bool(lib->settings,
+ "%s.plugins.tnccs-20.tests.pb_tnc_noskip", FALSE, lib->ns))
+ {
+ msg = pb_noskip_test_msg_create();
+ this->mutex->lock(this->mutex);
+ this->messages->insert_last(this->messages, msg);
+ this->mutex->unlock(this->mutex);
+ }
+}
+
+METHOD(tnccs_20_handler_t, get_send_flag, bool,
+ private_tnccs_20_server_t *this)
+{
+ return this->send_msg;
+}
+
+METHOD(tnccs_20_handler_t, get_mutual, bool,
+ private_tnccs_20_server_t *this)
+{
+ return this->mutual;
+}
+
+METHOD(tnccs_20_handler_t, get_state, pb_tnc_state_t,
+ private_tnccs_20_server_t *this)
+{
+ return this->state_machine->get_state(this->state_machine);
+}
+
+METHOD(tnccs_20_handler_t, add_msg, void,
+ private_tnccs_20_server_t *this, pb_tnc_msg_t *msg)
+{
+ /* adding PA message to SDATA batch only */
+ this->mutex->lock(this->mutex);
+ if (this->batch_type == PB_BATCH_NONE)
+ {
+ this->batch_type = PB_BATCH_SDATA;
+ }
+ if (this->batch_type == PB_BATCH_SDATA)
+ {
+ this->messages->insert_last(this->messages, msg);
+ }
+ else
+ {
+ msg->destroy(msg);
+ }
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(tnccs_20_handler_t, handle_errors, void,
+ private_tnccs_20_server_t *this, pb_tnc_batch_t *batch,
+ bool fatal_header_error)
+{
+ pb_tnc_msg_t *msg;
+ enumerator_t *enumerator;
+
+ if (fatal_header_error || this->fatal_error)
+ {
+ this->mutex->lock(this->mutex);
+ change_batch_type(this, PB_BATCH_CLOSE);
+ this->mutex->unlock(this->mutex);
+ }
+
+ enumerator = batch->create_error_enumerator(batch);
+ while (enumerator->enumerate(enumerator, &msg))
+ {
+ this->mutex->lock(this->mutex);
+ this->messages->insert_last(this->messages, msg->get_ref(msg));
+ this->mutex->unlock(this->mutex);
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(tnccs_20_handler_t, destroy, void,
+ private_tnccs_20_server_t *this)
+{
+ if (this->connection_id)
+ {
+ tnc->tnccs->remove_connection(tnc->tnccs, this->connection_id, TRUE);
+ }
+ this->state_machine->destroy(this->state_machine);
+ this->mutex->destroy(this->mutex);
+ this->messages->destroy_offset(this->messages,
+ offsetof(pb_tnc_msg_t, destroy));
+ free(this);
+}
+
+METHOD(tnccs_20_server_t, have_recommendation, bool,
+ private_tnccs_20_server_t *this, TNC_IMV_Action_Recommendation *rec,
+ TNC_IMV_Evaluation_Result *eval)
+{
+ return this->recs->have_recommendation(this->recs, rec, eval);
+}
+
+/**
+ * See header
+ */
+tnccs_20_handler_t* tnccs_20_server_create(tnccs_t *tnccs,
+ tnccs_send_message_t send_msg,
+ size_t max_batch_len,
+ size_t max_msg_len,
+ bool eap_transport)
+{
+ private_tnccs_20_server_t *this;
+
+ INIT(this,
+ .public = {
+ .handler = {
+ .process = _process,
+ .build = _build,
+ .begin_handshake = _begin_handshake,
+ .get_send_flag = _get_send_flag,
+ .get_mutual = _get_mutual,
+ .get_state = _get_state,
+ .add_msg = _add_msg,
+ .handle_errors = _handle_errors,
+ .destroy = _destroy,
+ },
+ .have_recommendation = _have_recommendation,
+ },
+ .state_machine = pb_tnc_state_machine_create(TRUE),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .messages = linked_list_create(),
+ .batch_type = PB_BATCH_SDATA,
+ .max_batch_len = max_batch_len,
+ .eap_transport = eap_transport,
+ );
+
+ this->connection_id = tnc->tnccs->create_connection(tnc->tnccs,
+ TNCCS_2_0, tnccs, send_msg,
+ &this->request_handshake_retry,
+ max_msg_len, &this->recs);
+ if (!this->connection_id)
+ {
+ destroy(this);
+ return NULL;
+ }
+ tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id,
+ TNC_CONNECTION_STATE_CREATE);
+
+ return &this->public.handler;
+}
diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20_server.h b/src/libtnccs/plugins/tnccs_20/tnccs_20_server.h
new file mode 100644
index 000000000..5833d1132
--- /dev/null
+++ b/src/libtnccs/plugins/tnccs_20/tnccs_20_server.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 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 tnccs_20_server_h tnccs_20_server
+ * @{ @ingroup tnccs_20
+ */
+
+#ifndef TNCCS_20_SERVER_H_
+#define TNCCS_20_SERVER_H_
+
+#include <library.h>
+
+#include <tnc/tnccs/tnccs.h>
+
+#include "tnccs_20_handler.h"
+
+typedef struct tnccs_20_server_t tnccs_20_server_t;
+
+/**
+ * Interface for a TNC server
+ */
+struct tnccs_20_server_t {
+
+ /**
+ * IF-TNCCS 2.0 protocol handler interface
+ */
+ tnccs_20_handler_t handler;
+
+ /**
+ * Check if an Action Recommendation is already available
+ *
+ * @param rec TNC Action Recommendation
+ * @param eval TNC Evaluation Result
+ * @return TRUE if Action Recommendation is
+ */
+ bool (*have_recommendation)(tnccs_20_server_t *this,
+ TNC_IMV_Action_Recommendation *rec,
+ TNC_IMV_Evaluation_Result *eval);
+
+};
+
+/**
+ * Create an instance of the TNC IF-TNCCS 2.0 server-side protocol handler.
+ *
+ * @param tnccs TNC IF-TNCCS 2.0 stack
+ * @param send_msg TNF IF-TNCCS 2.0 send message callback function
+ * @param max_batch_len Maximum PB-TNC batch size
+ * @param max_msg_len Maximum PA-TNC message size
+ * @param eap_transport TRUE if IF-T for EAP methods
+ */
+tnccs_20_handler_t* tnccs_20_server_create(tnccs_t *tnccs,
+ tnccs_send_message_t send_msg,
+ size_t max_batch_len,
+ size_t max_msg_len,
+ bool eap_transport);
+
+
+#endif /** TNCCS_20_SERVER_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_dynamic/Makefile.in b/src/libtnccs/plugins/tnccs_dynamic/Makefile.in
index 6a03df994..3f21a22d4 100644
--- a/src/libtnccs/plugins/tnccs_dynamic/Makefile.in
+++ b/src/libtnccs/plugins/tnccs_dynamic/Makefile.in
@@ -231,6 +231,7 @@ DLLIB = @DLLIB@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
@@ -291,10 +292,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
@@ -368,6 +371,8 @@ json_CFLAGS = @json_CFLAGS@
json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
linux_headers = @linux_headers@
localedir = @localedir@
localstatedir = @localstatedir@
diff --git a/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.c b/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.c
index e08236eb7..44b804fb2 100644
--- a/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.c
+++ b/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2013 Andreas Steffen
+ * Copyright (C) 2011-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -34,12 +34,22 @@ struct private_tnccs_dynamic_t {
/**
* Server identity
*/
- identification_t *server;
+ identification_t *server_id;
/**
* Client identity
*/
- identification_t *peer;
+ identification_t *peer_id;
+
+ /**
+ * Server IP address
+ */
+ host_t *server_ip;
+
+ /**
+ * Client IP address
+ */
+ host_t *peer_ip;
/**
* Detected TNC IF-TNCCS stack
@@ -109,8 +119,8 @@ METHOD(tls_t, process, status_t,
DBG1(DBG_TNC, "%N protocol detected dynamically",
tnccs_type_names, type);
tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, TRUE,
- this->server, this->peer, this->transport,
- this->callback);
+ this->server_id, this->peer_id, this->server_ip,
+ this->peer_ip, this->transport, this->callback);
if (!tnccs)
{
DBG1(DBG_TNC, "N% protocol not supported", tnccs_type_names, type);
@@ -137,14 +147,14 @@ METHOD(tls_t, is_server, bool,
METHOD(tls_t, get_server_id, identification_t*,
private_tnccs_dynamic_t *this)
{
- return this->server;
+ return this->server_id;
}
METHOD(tls_t, set_peer_id, void,
private_tnccs_dynamic_t *this, identification_t *id)
{
- DESTROY_IF(this->peer);
- this->peer = id->clone(id);
+ DESTROY_IF(this->peer_id);
+ this->peer_id = id->clone(id);
if (this->tls)
{
this->tls->set_peer_id(this->tls, id);
@@ -154,7 +164,7 @@ METHOD(tls_t, set_peer_id, void,
METHOD(tls_t, get_peer_id, identification_t*,
private_tnccs_dynamic_t *this)
{
- return this->peer;
+ return this->peer_id;
}
METHOD(tls_t, get_purpose, tls_purpose_t,
@@ -181,12 +191,26 @@ METHOD(tls_t, destroy, void,
if (ref_put(&this->ref))
{
DESTROY_IF(this->tls);
- this->server->destroy(this->server);
- this->peer->destroy(this->peer);
+ this->server_id->destroy(this->server_id);
+ this->peer_id->destroy(this->peer_id);
+ this->server_ip->destroy(this->server_ip);
+ this->peer_ip->destroy(this->peer_ip);
free(this);
}
}
+METHOD(tnccs_t, get_server_ip, host_t*,
+ private_tnccs_dynamic_t *this)
+{
+ return this->server_ip;
+}
+
+METHOD(tnccs_t, get_peer_ip, host_t*,
+ private_tnccs_dynamic_t *this)
+{
+ return this->peer_ip;
+}
+
METHOD(tnccs_t, get_transport, tnc_ift_type_t,
private_tnccs_dynamic_t *this)
{
@@ -229,9 +253,10 @@ METHOD(tnccs_t, get_ref, tnccs_t*,
/**
* See header
*/
-tnccs_t* tnccs_dynamic_create(bool is_server,
- identification_t *server, identification_t *peer,
- tnc_ift_type_t transport, tnccs_cb_t cb)
+tnccs_t* tnccs_dynamic_create(bool is_server, identification_t *server_id,
+ identification_t *peer_id, host_t *server_ip,
+ host_t *peer_ip, tnc_ift_type_t transport,
+ tnccs_cb_t cb)
{
private_tnccs_dynamic_t *this;
@@ -249,6 +274,8 @@ tnccs_t* tnccs_dynamic_create(bool is_server,
.get_eap_msk = _get_eap_msk,
.destroy = _destroy,
},
+ .get_server_ip = _get_server_ip,
+ .get_peer_ip = _get_peer_ip,
.get_transport = _get_transport,
.set_transport = _set_transport,
.get_auth_type = _get_auth_type,
@@ -256,8 +283,10 @@ tnccs_t* tnccs_dynamic_create(bool is_server,
.get_pdp_server = _get_pdp_server,
.get_ref = _get_ref,
},
- .server = server->clone(server),
- .peer = peer->clone(peer),
+ .server_id = server_id->clone(server_id),
+ .peer_id = peer_id->clone(peer_id),
+ .server_ip = server_ip->clone(server_ip),
+ .peer_ip = peer_ip->clone(peer_ip),
.transport = transport,
.callback = cb,
.ref = 1,
diff --git a/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.h b/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.h
index cbdc80b83..2e1141780 100644
--- a/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.h
+++ b/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2013 Andreas Steffen
+ * Copyright (C) 2011-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -29,14 +29,17 @@
* Create an instance of a dynamic TNC IF-TNCCS protocol handler.
*
* @param is_server TRUE to act as TNC Server, FALSE for TNC Client
- * @param server Server identity
- * @param peer Client identity
+ * @param server_id Server identity
+ * @param peer_id Client identity
+ * @param server_ip Server IP address
+ * @param peer_ip Client IP address
* @param transport Underlying IF-T transport protocol
* @param cb Callback function if TNC Server, NULL if TNC Client
* @return dynamic TNC IF-TNCCS protocol stack
*/
-tnccs_t* tnccs_dynamic_create(bool is_server,
- identification_t *server, identification_t *peer,
- tnc_ift_type_t transport, tnccs_cb_t cb);
+tnccs_t* tnccs_dynamic_create(bool is_server, identification_t *server_id,
+ identification_t *peer_id, host_t *server_ip,
+ host_t *peer_ip, tnc_ift_type_t transport,
+ tnccs_cb_t cb);
#endif /** TNCCS_DYNAMIC_H_ @}*/
diff --git a/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic_plugin.h b/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic_plugin.h
index b518e1278..97dd0df43 100644
--- a/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic_plugin.h
+++ b/src/libtnccs/plugins/tnccs_dynamic/tnccs_dynamic_plugin.h
@@ -15,7 +15,7 @@
/**
* @defgroup tnccs_dynamic tnccs_dynamic
- * @ingroup cplugins
+ * @ingroup tplugins
*
* @defgroup tnccs_dynamic_plugin tnccs_dynamic_plugin
* @{ @ingroup tnccs_dynamic
diff --git a/src/libtnccs/tnc/imc/imc.h b/src/libtnccs/tnc/imc/imc.h
index 3ff7d5194..6d13f6bc5 100644
--- a/src/libtnccs/tnc/imc/imc.h
+++ b/src/libtnccs/tnc/imc/imc.h
@@ -15,7 +15,7 @@
/**
* @defgroup imc imc
- * @ingroup tnc
+ * @ingroup libtnccs
*
* @defgroup imct imc
* @{ @ingroup imc
diff --git a/src/libtnccs/tnc/imv/imv.h b/src/libtnccs/tnc/imv/imv.h
index 3716532d6..fbc26a1e7 100644
--- a/src/libtnccs/tnc/imv/imv.h
+++ b/src/libtnccs/tnc/imv/imv.h
@@ -15,7 +15,7 @@
/**
* @defgroup imv imv
- * @ingroup tnc
+ * @ingroup libtnccs
*
* @defgroup imvt imv
* @{ @ingroup imv
diff --git a/src/libtnccs/tnc/tnc.h b/src/libtnccs/tnc/tnc.h
index e5a4a2959..7bf8c84b7 100644
--- a/src/libtnccs/tnc/tnc.h
+++ b/src/libtnccs/tnc/tnc.h
@@ -14,9 +14,12 @@
*/
/**
- * @defgroup tnc tnc
+ * @defgroup libtnccs libtnccs
*
- * @addtogroup tnc
+ * @defgroup tplugins plugins
+ * @ingroup libtnccs
+ *
+ * @addtogroup libtnccs
* @{
*/
diff --git a/src/libtnccs/tnc/tnccs/tnccs.h b/src/libtnccs/tnc/tnccs/tnccs.h
index eefd5565d..8ff295bcc 100644
--- a/src/libtnccs/tnc/tnccs/tnccs.h
+++ b/src/libtnccs/tnc/tnccs/tnccs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 Andreas Steffen
+ * Copyright (C) 2010-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -15,7 +15,7 @@
/**
* @defgroup tnccs tnccs
- * @ingroup tnc
+ * @ingroup libtnccs
*
* @defgroup tnccst tnccs
* @{ @ingroup tnccs
@@ -87,6 +87,20 @@ struct tnccs_t {
tls_t tls;
/**
+ * Get server IP address
+ *
+ * @return Server IP address
+ */
+ host_t* (*get_server_ip)(tnccs_t *this);
+
+ /**
+ * Get peer IP address
+ *
+ * @return Peer IP address
+ */
+ host_t* (*get_peer_ip)(tnccs_t *this);
+
+ /**
* Get underlying TNC IF-T transport protocol
*
* @return TNC IF-T transport protocol
@@ -135,15 +149,19 @@ struct tnccs_t {
* Constructor definition for a pluggable TNCCS protocol implementation.
*
* @param is_server TRUE if TNC Server, FALSE if TNC Client
- * @param server Server identity
- * @param peer Client identity
+ * @param server_id Server identity
+ * @param peer_id Client identity
+ * @param server_ip Server IP address
+ * @param peer_ip Client IP address
* @param transport Underlying TNC IF-T transport protocol used
* @param cb Callback function if TNC Server, NULL if TNC Client
* @return implementation of the tnccs_t interface
*/
typedef tnccs_t *(*tnccs_constructor_t)(bool is_server,
- identification_t *server,
- identification_t *peer,
+ identification_t *server_id,
+ identification_t *peer_id,
+ host_t *server_ip,
+ host_t *peer_ip,
tnc_ift_type_t transport,
tnccs_cb_t cb);
diff --git a/src/libtnccs/tnc/tnccs/tnccs_manager.h b/src/libtnccs/tnc/tnccs/tnccs_manager.h
index 791336ee1..b5c85f3c0 100644
--- a/src/libtnccs/tnc/tnccs/tnccs_manager.h
+++ b/src/libtnccs/tnc/tnccs/tnccs_manager.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 Andreas Steffen
+ * Copyright (C) 2010-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -56,16 +56,19 @@ struct tnccs_manager_t {
*
* @param type type of the TNCCS protocol
* @param is_server TRUE if TNC Server, FALSE if TNC Client
- * @param server Server identity
- * @param peer Client identity
+ * @param server_id Server identity
+ * @param peer_id Client identity
+ * @param server_ip Server IP address
+ * @param peer_ip Client IP address
* @param transport Underlying TNC IF-T transport protocol used
* @param cb Callback function if TNC Server, NULL if TNC Client
* @return TNCCS protocol instance, NULL if no constructor found
*/
tnccs_t* (*create_instance)(tnccs_manager_t *this, tnccs_type_t type,
- bool is_server, identification_t *server,
- identification_t *peer,
- tnc_ift_type_t transport, tnccs_cb_t cb);
+ bool is_server, identification_t *server_id,
+ identification_t *peer_id, host_t *server_ip,
+ host_t *peer_ip, tnc_ift_type_t transport,
+ tnccs_cb_t cb);
/**
* Create a TNCCS connection and assign a unique connection ID as well a