aboutsummaryrefslogtreecommitdiffstats
path: root/src/libimcv/plugins/imv_scanner.c
diff options
context:
space:
mode:
authorAndreas Steffen <andreas.steffen@strongswan.org>2011-07-04 21:40:25 +0200
committerAndreas Steffen <andreas.steffen@strongswan.org>2011-07-04 21:40:25 +0200
commitd9cdab9249c885b7e5eac50e74ceddbda58dd8d0 (patch)
tree0ff088fa5d314bf8fa022917a33013c1c5db9230 /src/libimcv/plugins/imv_scanner.c
parent956759533ff1488c251af55081db3c29daf34dab (diff)
downloadstrongswan-d9cdab9249c885b7e5eac50e74ceddbda58dd8d0.tar.bz2
strongswan-d9cdab9249c885b7e5eac50e74ceddbda58dd8d0.tar.xz
added ITA Scanner IMC/IMV pair which detects open server ports on TNC clients
Diffstat (limited to 'src/libimcv/plugins/imv_scanner.c')
-rw-r--r--src/libimcv/plugins/imv_scanner.c266
1 files changed, 266 insertions, 0 deletions
diff --git a/src/libimcv/plugins/imv_scanner.c b/src/libimcv/plugins/imv_scanner.c
new file mode 100644
index 000000000..276968c38
--- /dev/null
+++ b/src/libimcv/plugins/imv_scanner.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "imv_scanner_state.h"
+
+#include <imv/imv_agent.h>
+#include <pa_tnc/pa_tnc_msg.h>
+#include <ietf/ietf_attr.h>
+#include <ietf/ietf_attr_pa_tnc_error.h>
+#include <ietf/ietf_attr_port_filter.h>
+
+#include <tncif_names.h>
+#include <tncif_pa_subtypes.h>
+
+#include <pen/pen.h>
+#include <debug.h>
+
+/* IMV definitions */
+
+static const char imv_name[] = "Scanner";
+
+#define IMV_VENDOR_ID PEN_ITA
+#define IMV_SUBTYPE PA_SUBTYPE_ITA_SCANNER
+
+static imv_agent_t *imv_scanner;
+
+/**
+ * see section 3.7.1 of TCG TNC IF-IMV Specification 1.2
+ */
+TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id,
+ TNC_Version min_version,
+ TNC_Version max_version,
+ TNC_Version *actual_version)
+{
+ if (imv_scanner)
+ {
+ DBG1(DBG_IMV, "IMV \"%s\" has already been initialized", imv_name);
+ return TNC_RESULT_ALREADY_INITIALIZED;
+ }
+ imv_scanner = imv_agent_create(imv_name, IMV_VENDOR_ID, IMV_SUBTYPE,
+ imv_id, actual_version);
+ if (!imv_scanner)
+ {
+ return TNC_RESULT_FATAL;
+ }
+ if (min_version > TNC_IFIMV_VERSION_1 || max_version < TNC_IFIMV_VERSION_1)
+ {
+ DBG1(DBG_IMV, "no common IF-IMV version");
+ return TNC_RESULT_NO_COMMON_VERSION;
+ }
+ return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 3.7.2 of TCG TNC IF-IMV Specification 1.2
+ */
+TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id,
+ TNC_ConnectionState new_state)
+{
+ imv_state_t *state;
+
+ if (!imv_scanner)
+ {
+ DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ switch (new_state)
+ {
+ case TNC_CONNECTION_STATE_CREATE:
+ state = imv_scanner_state_create(connection_id);
+ return imv_scanner->create_state(imv_scanner, state);
+ case TNC_CONNECTION_STATE_DELETE:
+ return imv_scanner->delete_state(imv_scanner, connection_id);
+ default:
+ return imv_scanner->change_state(imv_scanner, connection_id,
+ new_state, NULL);
+ }
+}
+
+static TNC_Result send_message(TNC_ConnectionID connection_id)
+{
+ pa_tnc_msg_t *msg;
+ pa_tnc_attr_t *attr;
+ TNC_Result result;
+
+ msg = pa_tnc_msg_create();
+ msg->build(msg);
+ result = imv_scanner->send_message(imv_scanner, connection_id,
+ msg->get_encoding(msg));
+ msg->destroy(msg);
+
+ return result;
+}
+
+/**
+ * see section 3.7.3 of TCG TNC IF-IMV Specification 1.2
+ */
+TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_MessageType msg_type)
+{
+ pa_tnc_msg_t *pa_tnc_msg;
+ pa_tnc_attr_t *attr;
+ imv_state_t *state;
+ enumerator_t *enumerator;
+ TNC_Result result;
+ bool fatal_error = FALSE;
+
+ if (!imv_scanner)
+ {
+ DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+
+ /* get current IMV state */
+ if (!imv_scanner->get_state(imv_scanner, connection_id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+
+ /* parse received PA-TNC message and automatically handle any errors */
+ result = imv_scanner->receive_message(imv_scanner, connection_id,
+ chunk_create(msg, msg_len), msg_type,
+ &pa_tnc_msg);
+
+ /* no parsed PA-TNC attributes available if an error occurred */
+ if (!pa_tnc_msg)
+ {
+ return result;
+ }
+
+ /* analyze PA-TNC attributes */
+ enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (attr->get_vendor_id(attr) != PEN_IETF)
+ {
+ continue;
+ }
+
+ if (attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR)
+ {
+ ietf_attr_pa_tnc_error_t *error_attr;
+ pa_tnc_error_code_t error_code;
+ chunk_t msg_info, attr_info;
+
+ error_attr = (ietf_attr_pa_tnc_error_t*)attr;
+ error_code = error_attr->get_error_code(error_attr);
+ msg_info = error_attr->get_msg_info(error_attr);
+
+ DBG1(DBG_IMV, "received PA-TNC error '%N' concerning message %#B",
+ pa_tnc_error_code_names, error_code, &msg_info);
+ switch (error_code)
+ {
+ case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
+ attr_info = error_attr->get_attr_info(error_attr);
+ DBG1(DBG_IMV, " unsupported attribute %#B", &attr_info);
+ break;
+ default:
+ break;
+ }
+ fatal_error = TRUE;
+ }
+ else if (attr->get_type(attr) == IETF_ATTR_PORT_FILTER)
+ {
+ ietf_attr_port_filter_t *attr_port_filter;
+ enumerator_t *enumerator;
+ bool blocked;
+ u_int8_t protocol;
+ u_int16_t port;
+
+ attr_port_filter = (ietf_attr_port_filter_t*)attr;
+ enumerator = attr_port_filter->create_port_enumerator(attr_port_filter);
+ while (enumerator->enumerate(enumerator, &blocked, &protocol, &port))
+ {
+ DBG2(DBG_IMV, "%s: %s %5u", blocked ? "blocked" : "allowed",
+ (protocol == IPPROTO_TCP) ? "tcp" : "udp", port);
+ }
+ enumerator->destroy(enumerator);
+ }
+ }
+ enumerator->destroy(enumerator);
+ pa_tnc_msg->destroy(pa_tnc_msg);
+
+ if (fatal_error)
+ {
+ state->set_recommendation(state,
+ TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
+ TNC_IMV_EVALUATION_RESULT_ERROR);
+ return imv_scanner->provide_recommendation(imv_scanner, connection_id);
+ }
+
+ return imv_scanner->provide_recommendation(imv_scanner, connection_id);
+}
+
+/**
+ * see section 3.7.4 of TCG TNC IF-IMV Specification 1.2
+ */
+TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id)
+{
+ if (!imv_scanner)
+ {
+ DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ return imv_scanner->provide_recommendation(imv_scanner, connection_id);
+}
+
+/**
+ * see section 3.7.5 of TCG TNC IF-IMV Specification 1.2
+ */
+TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id,
+ TNC_ConnectionID connection_id)
+{
+ if (!imv_scanner)
+ {
+ DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 3.7.6 of TCG TNC IF-IMV Specification 1.2
+ */
+TNC_Result TNC_IMV_Terminate(TNC_IMVID imv_id)
+{
+ if (!imv_scanner)
+ {
+ DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ imv_scanner->destroy(imv_scanner);
+ imv_scanner = NULL;
+
+ return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 4.2.8.1 of TCG TNC IF-IMV Specification 1.2
+ */
+TNC_Result TNC_IMV_ProvideBindFunction(TNC_IMVID imv_id,
+ TNC_TNCS_BindFunctionPointer bind_function)
+{
+ if (!imv_scanner)
+ {
+ DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ return imv_scanner->bind_functions(imv_scanner, bind_function);
+}