ARG_ENABL_SET([xauth-eap], [enable XAuth backend using EAP methods to verify passwords.])
ARG_ENABL_SET([xauth-pam], [enable XAuth backend using PAM to verify passwords.])
ARG_ENABL_SET([xauth-noauth], [enable XAuth pseudo-backend that does not actually verify or even request any credentials.])
-ARG_ENABL_SET([tnc-ifmap2], [enable TNC IF-MAP v2 module. Requires libxml])
+ARG_ENABL_SET([tnc-ifmap], [enable TNC IF-MAP module. Requires libxml])
ARG_ENABL_SET([tnc-pdp], [enable TNC policy decision point module.])
ARG_ENABL_SET([tnc-imc], [enable TNC IMC module.])
ARG_ENABL_SET([tnc-imv], [enable TNC IMV module.])
fi
fi
-if test x$smp = xtrue -o x$tnccs_11 = xtrue -o x$tnc_ifmap2 = xtrue; then
+if test x$smp = xtrue -o x$tnccs_11 = xtrue -o x$tnc_ifmap = xtrue; then
xml=true
fi
ADD_PLUGIN([xauth-eap], [c charon])
ADD_PLUGIN([xauth-pam], [c charon])
ADD_PLUGIN([xauth-noauth], [c charon])
-ADD_PLUGIN([tnc-ifmap2], [c charon])
+ADD_PLUGIN([tnc-ifmap], [c charon])
ADD_PLUGIN([tnc-pdp], [c charon])
ADD_PLUGIN([tnc-imc], [c charon])
ADD_PLUGIN([tnc-imv], [c charon])
AM_CONDITIONAL(USE_XAUTH_EAP, test x$xauth_eap = xtrue)
AM_CONDITIONAL(USE_XAUTH_PAM, test x$xauth_pam = xtrue)
AM_CONDITIONAL(USE_XAUTH_NOAUTH, test x$xauth_noauth = xtrue)
-AM_CONDITIONAL(USE_TNC_IFMAP2, test x$tnc_ifmap2 = xtrue)
+AM_CONDITIONAL(USE_TNC_IFMAP, test x$tnc_ifmap = xtrue)
AM_CONDITIONAL(USE_TNC_PDP, test x$tnc_pdp = xtrue)
AM_CONDITIONAL(USE_TNC_IMC, test x$tnc_imc = xtrue)
AM_CONDITIONAL(USE_TNC_IMV, test x$tnc_imv = xtrue)
src/libcharon/plugins/xauth_eap/Makefile
src/libcharon/plugins/xauth_pam/Makefile
src/libcharon/plugins/xauth_noauth/Makefile
- src/libcharon/plugins/tnc_ifmap2/Makefile
+ src/libcharon/plugins/tnc_ifmap/Makefile
src/libcharon/plugins/tnc_pdp/Makefile
src/libcharon/plugins/tnc_imc/Makefile
src/libcharon/plugins/tnc_imv/Makefile
endif
endif
-if USE_TNC_IFMAP2
- SUBDIRS += plugins/tnc_ifmap2
+if USE_TNC_IFMAP
+ SUBDIRS += plugins/tnc_ifmap
if MONOLITHIC
- libcharon_la_LIBADD += plugins/tnc_ifmap2/libstrongswan-tnc-ifmap2.la
+ libcharon_la_LIBADD += plugins/tnc_ifmap/libstrongswan-tnc-ifmap.la
endif
endif
--- /dev/null
+
+INCLUDES = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtls \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon \
+ ${xml_CFLAGS}
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-tnc-ifmap.la
+else
+plugin_LTLIBRARIES = libstrongswan-tnc-ifmap.la
+endif
+
+libstrongswan_tnc_ifmap_la_LIBADD = \
+ $(top_builddir)/src/libtls/libtls.la ${xml_LIBS}
+
+libstrongswan_tnc_ifmap_la_SOURCES = \
+ tnc_ifmap_plugin.h tnc_ifmap_plugin.c \
+ tnc_ifmap_listener.h tnc_ifmap_listener.c \
+ tnc_ifmap_soap.h tnc_ifmap_soap.c \
+ tnc_ifmap_soap_msg.h tnc_ifmap_soap_msg.c
+
+libstrongswan_tnc_ifmap_la_LDFLAGS = -module -avoid-version
+
--- /dev/null
+/*
+ * Copyright (C) 2011-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnc_ifmap_listener.h"
+#include "tnc_ifmap_soap.h"
+
+#include <daemon.h>
+#include <hydra.h>
+#include <utils/debug.h>
+
+typedef struct private_tnc_ifmap_listener_t private_tnc_ifmap_listener_t;
+
+/**
+ * Private data of an tnc_ifmap_listener_t object.
+ */
+struct private_tnc_ifmap_listener_t {
+
+ /**
+ * Public tnc_ifmap_listener_t interface.
+ */
+ tnc_ifmap_listener_t public;
+
+ /**
+ * TNC IF-MAP 2.0 SOAP interface
+ */
+ tnc_ifmap_soap_t *ifmap;
+
+};
+
+/**
+ * Publish PEP device-ip metadata
+ */
+static bool publish_device_ip_addresses(private_tnc_ifmap_listener_t *this)
+{
+ enumerator_t *enumerator;
+ host_t *host;
+ bool success = TRUE;
+
+ enumerator = hydra->kernel_interface->create_address_enumerator(
+ hydra->kernel_interface, ADDR_TYPE_REGULAR);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ if (!this->ifmap->publish_device_ip(this->ifmap, host))
+ {
+ success = FALSE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return success;
+}
+
+/**
+ * Publish all IKE_SA metadata
+ */
+static bool reload_metadata(private_tnc_ifmap_listener_t *this)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ bool success = TRUE;
+
+ enumerator = charon->controller->create_ike_sa_enumerator(
+ charon->controller, FALSE);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ if (ike_sa->get_state(ike_sa) != IKE_ESTABLISHED)
+ {
+ continue;
+ }
+ if (!this->ifmap->publish_ike_sa(this->ifmap, ike_sa, TRUE))
+ {
+ success = FALSE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return success;
+}
+
+METHOD(listener_t, ike_updown, bool,
+ private_tnc_ifmap_listener_t *this, ike_sa_t *ike_sa, bool up)
+{
+ if (ike_sa->get_state(ike_sa) != IKE_CONNECTING)
+ {
+ this->ifmap->publish_ike_sa(this->ifmap, ike_sa, up);
+ }
+ return TRUE;
+}
+
+METHOD(listener_t, alert, bool,
+ private_tnc_ifmap_listener_t *this, ike_sa_t *ike_sa, alert_t alert,
+ va_list args)
+{
+ if (alert == ALERT_PEER_AUTH_FAILED)
+ {
+ this->ifmap->publish_enforcement_report(this->ifmap,
+ ike_sa->get_other_host(ike_sa),
+ "block", "authentication failed");
+ }
+ return TRUE;
+}
+
+METHOD(tnc_ifmap_listener_t, destroy, void,
+ private_tnc_ifmap_listener_t *this)
+{
+ DESTROY_IF(this->ifmap);
+ free(this);
+}
+
+/**
+ * See header
+ */
+tnc_ifmap_listener_t *tnc_ifmap_listener_create(bool reload)
+{
+ private_tnc_ifmap_listener_t *this;
+
+ INIT(this,
+ .public = {
+ .listener = {
+ .ike_updown = _ike_updown,
+ .alert = _alert,
+ },
+ .destroy = _destroy,
+ },
+ .ifmap = tnc_ifmap_soap_create(),
+ );
+
+ if (!this->ifmap)
+ {
+ destroy(this);
+ return NULL;
+ }
+ if (!this->ifmap->newSession(this->ifmap))
+ {
+ destroy(this);
+ return NULL;
+ }
+ if (!this->ifmap->purgePublisher(this->ifmap))
+ {
+ destroy(this);
+ return NULL;
+ }
+ if (!publish_device_ip_addresses(this))
+ {
+ destroy(this);
+ return NULL;
+ }
+ if (reload)
+ {
+ if (!reload_metadata(this))
+ {
+ destroy(this);
+ return NULL;
+ }
+ }
+
+ return &this->public;
+}
+
--- /dev/null
+/*
+ * Copyright (C) 2011-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tnc_ifmap_listener tnc_ifmap_listener
+ * @{ @ingroup tnc_ifmap
+ */
+
+#ifndef TNC_IFMAP_LISTENER_H_
+#define TNC_IFMAP_LISTENER_H_
+
+#include <bus/bus.h>
+
+typedef struct tnc_ifmap_listener_t tnc_ifmap_listener_t;
+
+/**
+ * Listener which collects information on IKE_SAs
+ */
+struct tnc_ifmap_listener_t {
+
+ /**
+ * Implements listener_t.
+ */
+ listener_t listener;
+
+ /**
+ * Destroy a tnc_ifmap_listener_t.
+ */
+ void (*destroy)(tnc_ifmap_listener_t *this);
+};
+
+/**
+ * Create a tnc_ifmap_listener instance.
+ *
+ * @param reload reload all IKE_SA metadata
+ */
+tnc_ifmap_listener_t *tnc_ifmap_listener_create(bool reload);
+
+#endif /** TNC_IFMAP_LISTENER_H_ @}*/
--- /dev/null
+/*
+ * Copyright (C) 2011-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnc_ifmap_plugin.h"
+#include "tnc_ifmap_listener.h"
+
+#include <daemon.h>
+
+typedef struct private_tnc_ifmap_plugin_t private_tnc_ifmap_plugin_t;
+
+/**
+ * private data of tnc_ifmap plugin
+ */
+struct private_tnc_ifmap_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ tnc_ifmap_plugin_t public;
+
+ /**
+ * Listener interface, listens to CHILD_SA state changes
+ */
+ tnc_ifmap_listener_t *listener;
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_tnc_ifmap_plugin_t *this)
+{
+ return "tnc-ifmap";
+}
+
+/**
+ * Register tnc_ifmap plugin features
+ */
+static bool register_tnc_ifmap(private_tnc_ifmap_plugin_t *this,
+ plugin_feature_t *feature, bool reg, void *data)
+{
+ if (reg)
+ {
+ this->listener = tnc_ifmap_listener_create(FALSE);
+ if (!this->listener)
+ {
+ return FALSE;
+ }
+ charon->bus->add_listener(charon->bus, &this->listener->listener);
+ }
+ else
+ {
+ if (this->listener)
+ {
+ charon->bus->remove_listener(charon->bus, &this->listener->listener);
+ this->listener->destroy(this->listener);
+ }
+ }
+ return TRUE;
+}
+
+METHOD(plugin_t, get_features, int,
+ tnc_ifmap_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK((plugin_feature_callback_t)register_tnc_ifmap, NULL),
+ PLUGIN_PROVIDE(CUSTOM, "tnc-ifmap-2.1"),
+ PLUGIN_SDEPEND(CERT_DECODE, CERT_X509),
+ PLUGIN_SDEPEND(PRIVKEY, KEY_RSA),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, reload, bool,
+ private_tnc_ifmap_plugin_t *this)
+{
+ if (this->listener)
+ {
+ charon->bus->remove_listener(charon->bus, &this->listener->listener);
+ this->listener->destroy(this->listener);
+ }
+
+ this->listener = tnc_ifmap_listener_create(TRUE);
+ if (!this->listener)
+ {
+ return FALSE;
+ }
+ charon->bus->add_listener(charon->bus, &this->listener->listener);
+
+ return TRUE;
+}
+
+METHOD(plugin_t, destroy, void,
+ private_tnc_ifmap_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *tnc_ifmap_plugin_create()
+{
+ private_tnc_ifmap_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .reload = _reload,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ return &this->public.plugin;
+}
+
--- /dev/null
+/*
+ * Copyright (C) 2011-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tnc_ifmap tnc_ifmap
+ * @ingroup cplugins
+ *
+ * @defgroup tnc_ifmap_plugin tnc_ifmap_plugin
+ * @{ @ingroup tnc_ifmap
+ */
+
+#ifndef TNC_IFMAP_PLUGIN_H_
+#define TNC_IFMAP_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct tnc_ifmap_plugin_t tnc_ifmap_plugin_t;
+
+/**
+ * TNC IF-MAP plugin
+ */
+struct tnc_ifmap_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** TNC_IFMAP_PLUGIN_H_ @}*/
--- /dev/null
+/*
+ * Copyright (C) 2011-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "tnc_ifmap_soap.h"
+#include "tnc_ifmap_soap_msg.h"
+
+#include <utils/debug.h>
+#include <credentials/sets/mem_cred.h>
+#include <daemon.h>
+
+#include <tls_socket.h>
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#define IFMAP_NS "http://www.trustedcomputinggroup.org/2010/IFMAP/2"
+#define IFMAP_META_NS "http://www.trustedcomputinggroup.org/2010/IFMAP-METADATA/2"
+#define IFMAP_URI "https://localhost:8444/imap"
+#define IFMAP_NO_FD -1
+
+typedef struct private_tnc_ifmap_soap_t private_tnc_ifmap_soap_t;
+
+/**
+ * Private data of an tnc_ifmap_soap_t object.
+ */
+struct private_tnc_ifmap_soap_t {
+
+ /**
+ * Public tnc_ifmap_soap_t interface.
+ */
+ tnc_ifmap_soap_t public;
+
+ /**
+ * SOAP Session ID
+ */
+ xmlChar *session_id;
+
+ /**
+ * IF-MAP Publisher ID
+ */
+ xmlChar *ifmap_publisher_id;
+
+ /**
+ * IF-MAP namespace
+ */
+ xmlNsPtr ns;
+
+ /**
+ * IF-MAP metadata namespace
+ */
+ xmlNsPtr ns_meta;
+
+ /**
+ * PEP and PDP device name
+ */
+ char *device_name;
+
+ /**
+ * HTTPS Server URI with https:// prefix removed
+ */
+ char *uri;
+
+ /**
+ * Optional base64-encoded username:password for HTTP Basic Authentication
+ */
+ chunk_t user_pass;
+
+ /**
+ * IF-MAP Server (IP address and port)
+ */
+ host_t *host;
+
+ /**
+ * TLS socket
+ */
+ tls_socket_t *tls;
+
+ /**
+ * File descriptor for secure TCP socket
+ */
+ int fd;
+
+ /**
+ * In memory credential set
+ */
+ mem_cred_t *creds;
+
+};
+
+METHOD(tnc_ifmap_soap_t, newSession, bool,
+ private_tnc_ifmap_soap_t *this)
+{
+ tnc_ifmap_soap_msg_t *soap_msg;
+ xmlNodePtr request, result;
+
+ /*build newSession request */
+ request = xmlNewNode(NULL, "newSession");
+ this->ns = xmlNewNs(request, IFMAP_NS, "ifmap");
+ xmlSetNs(request, this->ns);
+
+ soap_msg = tnc_ifmap_soap_msg_create(this->uri, this->user_pass, this->tls);
+ if (!soap_msg->post(soap_msg, request, "newSessionResult", &result))
+ {
+ soap_msg->destroy(soap_msg);
+ return FALSE;
+ }
+
+ /* get session-id and ifmap-publisher-id properties */
+ this->session_id = xmlGetProp(result, "session-id");
+ this->ifmap_publisher_id = xmlGetProp(result, "ifmap-publisher-id");
+ soap_msg->destroy(soap_msg);
+
+ DBG1(DBG_TNC, "session-id: %s, ifmap-publisher-id: %s",
+ this->session_id, this->ifmap_publisher_id);
+
+ /* set PEP and PDP device name (defaults to IF-MAP Publisher ID) */
+ this->device_name = lib->settings->get_str(lib->settings,
+ "%s.plugins.tnc-ifmap.device_name",
+ this->ifmap_publisher_id, charon->name);
+ this->device_name = strdup(this->device_name);
+
+ return this->session_id && this->ifmap_publisher_id;
+}
+
+METHOD(tnc_ifmap_soap_t, purgePublisher, bool,
+ private_tnc_ifmap_soap_t *this)
+{
+ tnc_ifmap_soap_msg_t *soap_msg;
+ xmlNodePtr request;
+ bool success;
+
+ /* build purgePublisher request */
+ request = xmlNewNode(NULL, "purgePublisher");
+ this->ns = xmlNewNs(request, IFMAP_NS, "ifmap");
+ xmlSetNs(request, this->ns);
+ xmlNewProp(request, "session-id", this->session_id);
+ xmlNewProp(request, "ifmap-publisher-id", this->ifmap_publisher_id);
+
+ soap_msg = tnc_ifmap_soap_msg_create(this->uri, this->user_pass, this->tls);
+ success = soap_msg->post(soap_msg, request, "purgePublisherReceived", NULL);
+ soap_msg->destroy(soap_msg);
+
+ return success;
+}
+
+/**
+ * Create an access-request based on device_name and ike_sa_id
+ */
+static xmlNodePtr create_access_request(private_tnc_ifmap_soap_t *this,
+ u_int32_t id)
+{
+ xmlNodePtr node;
+ char buf[BUF_LEN];
+
+ node = xmlNewNode(NULL, "access-request");
+
+ snprintf(buf, BUF_LEN, "%s:%d", this->device_name, id);
+ xmlNewProp(node, "name", buf);
+
+ return node;
+}
+
+/**
+ * Create an identity
+ */
+static xmlNodePtr create_identity(private_tnc_ifmap_soap_t *this,
+ identification_t *id, bool is_user)
+{
+ xmlNodePtr node;
+ char buf[BUF_LEN], *id_type;
+
+ node = xmlNewNode(NULL, "identity");
+
+ snprintf(buf, BUF_LEN, "%Y", id);
+ xmlNewProp(node, "name", buf);
+
+ switch (id->get_type(id))
+ {
+ case ID_IPV4_ADDR:
+ id_type = "other";
+ xmlNewProp(node, "other-type-definition", "36906:ipv4-address");
+ break;
+ case ID_FQDN:
+ id_type = is_user ? "username" : "dns-name";
+ break;
+ case ID_RFC822_ADDR:
+ id_type = "email-address";
+ break;
+ case ID_IPV6_ADDR:
+ id_type = "other";
+ xmlNewProp(node, "other-type-definition", "36906:ipv6-address");
+ break;
+ case ID_DER_ASN1_DN:
+ id_type = "distinguished-name";
+ break;
+ case ID_KEY_ID:
+ id_type = "other";
+ xmlNewProp(node, "other-type-definition", "36906:key-id");
+ break;
+ default:
+ id_type = "other";
+ xmlNewProp(node, "other-type-definition", "36906:other");
+ }
+ xmlNewProp(node, "type", id_type);
+
+ return node;
+}
+
+/**
+ * Create enforcement-report metadata
+ */
+static xmlNodePtr create_enforcement_report(private_tnc_ifmap_soap_t *this,
+ xmlChar *action, xmlChar *reason)
+{
+ xmlNodePtr node, node2, node3;
+
+ node = xmlNewNode(NULL, "metadata");
+ node2 = xmlNewNode(this->ns_meta, "enforcement-report");
+ xmlAddChild(node, node2);
+ xmlNewProp(node2, "ifmap-cardinality", "multiValue");
+
+ node3 = xmlNewNode(NULL, "enforcement-action");
+ xmlAddChild(node2, node3);
+ xmlNodeAddContent(node3, action);
+
+ node3 = xmlNewNode(NULL, "enforcement-reason");
+ xmlAddChild(node2, node3);
+ xmlNodeAddContent(node3, reason);
+
+ return node;
+}
+
+/**
+ * Create delete filter
+ */
+static xmlNodePtr create_delete_filter(private_tnc_ifmap_soap_t *this,
+ char *metadata)
+{
+ xmlNodePtr node;
+ char buf[BUF_LEN];
+
+ node = xmlNewNode(NULL, "delete");
+
+ snprintf(buf, BUF_LEN, "meta:%s[@ifmap-publisher-id='%s']",
+ metadata, this->ifmap_publisher_id);
+ xmlNewProp(node, "filter", buf);
+
+ return node;
+}
+
+/**
+ * Create a publish request
+ */
+static xmlNodePtr create_publish_request(private_tnc_ifmap_soap_t *this)
+{
+ xmlNodePtr request;
+
+ request = xmlNewNode(NULL, "publish");
+ this->ns = xmlNewNs(request, IFMAP_NS, "ifmap");
+ xmlSetNs(request, this->ns);
+ this->ns_meta = xmlNewNs(request, IFMAP_META_NS, "meta");
+ xmlNewProp(request, "session-id", this->session_id);
+
+ return request;
+}
+
+/**
+ * Create a device
+ */
+static xmlNodePtr create_device(private_tnc_ifmap_soap_t *this)
+{
+ xmlNodePtr node, node2;
+
+ node = xmlNewNode(NULL, "device");
+ node2 = xmlNewNode(NULL, "name");
+ xmlAddChild(node, node2);
+ xmlNodeAddContent(node2, this->device_name);
+
+ return node;
+}
+
+/**
+ * Create an ip-address
+ */
+static xmlNodePtr create_ip_address(private_tnc_ifmap_soap_t *this,
+ host_t *host)
+{
+ xmlNodePtr node;
+ char buf[BUF_LEN];
+
+ node = xmlNewNode(NULL, "ip-address");
+
+ if (host->get_family(host) == AF_INET6)
+ {
+ chunk_t address;
+ int len, written, i;
+ char *pos;
+ bool first = TRUE;
+
+ /* output IPv6 address in canonical IF-MAP 2.0 format */
+ address = host->get_address(host);
+ pos = buf;
+ len = sizeof(buf);
+
+ for (i = 0; i < address.len; i = i + 2)
+ {
+ written = snprintf(pos, len, "%s%x", first ? "" : ":",
+ 256*address.ptr[i] + address.ptr[i+1]);
+ if (written < 0 || written >= len)
+ {
+ break;
+ }
+ pos += written;
+ len -= written;
+ first = FALSE;
+ }
+ }
+ else
+ {
+ snprintf(buf, BUF_LEN, "%H", host);
+ }
+
+ xmlNewProp(node, "value", buf);
+ xmlNewProp(node, "type", host->get_family(host) == AF_INET ? "IPv4" : "IPv6");
+
+ return node;
+}
+
+/**
+ * Create metadata
+ */
+static xmlNodePtr create_metadata(private_tnc_ifmap_soap_t *this,
+ xmlChar *metadata)
+{
+ xmlNodePtr node, node2;
+
+ node = xmlNewNode(NULL, "metadata");
+ node2 = xmlNewNode(this->ns_meta, metadata);
+ xmlAddChild(node, node2);
+ xmlNewProp(node2, "ifmap-cardinality", "singleValue");
+
+ return node;
+}
+
+/**
+ * Create capability metadata
+ */
+static xmlNodePtr create_capability(private_tnc_ifmap_soap_t *this,
+ identification_t *name)
+{
+ xmlNodePtr node, node2;
+ char buf[BUF_LEN];
+
+ node = xmlNewNode(this->ns_meta, "capability");
+ xmlNewProp(node, "ifmap-cardinality", "multiValue");
+
+ node2 = xmlNewNode(NULL, "name");
+ xmlAddChild(node, node2);
+ snprintf(buf, BUF_LEN, "%Y", name);
+ xmlNodeAddContent(node2, this->device_name);
+
+ node2 = xmlNewNode(NULL, "administrative-domain");
+ xmlNodeAddContent(node2, "strongswan");
+
+ return node;
+}
+
+METHOD(tnc_ifmap_soap_t, publish_ike_sa, bool,
+ private_tnc_ifmap_soap_t *this, ike_sa_t *ike_sa, bool up)
+{
+ tnc_ifmap_soap_msg_t *soap_msg;
+ xmlNodePtr request, node, node2 = NULL;
+ enumerator_t *e1, *e2;
+ auth_rule_t type;
+ identification_t *id, *eap_id, *group;
+ host_t *host;
+ auth_cfg_t *auth;
+ u_int32_t ike_sa_id;
+ bool is_user = FALSE, first = TRUE, success;
+
+ /* extract relevant data from IKE_SA*/
+ ike_sa_id = ike_sa->get_unique_id(ike_sa);
+ id = ike_sa->get_other_id(ike_sa);
+ eap_id = ike_sa->get_other_eap_id(ike_sa);
+ host = ike_sa->get_other_host(ike_sa);
+
+ /* in the presence of an EAP Identity, treat it as a username */
+ if (!id->equals(id, eap_id))
+ {
+ is_user = TRUE;
+ id = eap_id;
+ }
+
+ /* build publish request */
+ request = create_publish_request(this);
+
+ /* delete any existing enforcement reports */
+ if (up)
+ {
+ node = create_delete_filter(this, "enforcement-report");
+ xmlAddChild(request, node);
+ xmlAddChild(node, create_ip_address(this, host));
+ xmlAddChild(node, create_device(this));
+ }
+
+ /**
+ * update or delete authenticated-as metadata
+ */
+ if (up)
+ {
+ node = xmlNewNode(NULL, "update");
+ }
+ else
+ {
+ node = create_delete_filter(this, "authenticated-as");
+ }
+ xmlAddChild(request, node);
+
+ /* add access-request, identity and [if up] metadata */
+ xmlAddChild(node, create_access_request(this, ike_sa_id));
+ xmlAddChild(node, create_identity(this, id, is_user));
+ if (up)
+ {
+ xmlAddChild(node, create_metadata(this, "authenticated-as"));
+ }
+
+ /**
+ * update or delete access-request-ip metadata
+ */
+ if (up)
+ {
+ node = xmlNewNode(NULL, "update");
+ }
+ else
+ {
+ node = create_delete_filter(this, "access-request-ip");
+ }
+ xmlAddChild(request, node);
+
+ /* add access-request, ip-address and [if up] metadata */
+ xmlAddChild(node, create_access_request(this, ike_sa_id));
+ xmlAddChild(node, create_ip_address(this, host));
+ if (up)
+ {
+ xmlAddChild(node, create_metadata(this, "access-request-ip"));
+ }
+
+ /**
+ * update or delete authenticated-by metadata
+ */
+ if (up)
+ {
+ node = xmlNewNode(NULL, "update");
+ }
+ else
+ {
+ node = create_delete_filter(this, "authenticated-by");
+ }
+ xmlAddChild(request, node);
+
+ /* add access-request, device and [if up] metadata */
+ xmlAddChild(node, create_access_request(this, ike_sa_id));
+ xmlAddChild(node, create_device(this));
+ if (up)
+ {
+ xmlAddChild(node, create_metadata(this, "authenticated-by"));
+ }
+
+ /**
+ * update or delete capability metadata
+ */
+ e1 = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE);
+ while (e1->enumerate(e1, &auth) && (first || up))
+ {
+ e2 = auth->create_enumerator(auth);
+ while (e2->enumerate(e2, &type, &group))
+ {
+ /* look for group memberships */
+ if (type == AUTH_RULE_GROUP)
+ {
+ if (first)
+ {
+ first = FALSE;
+
+ if (up)
+ {
+ node = xmlNewNode(NULL, "update");
+ }
+ else
+ {
+ node = create_delete_filter(this, "capability");
+ }
+ xmlAddChild(request, node);
+
+ /* add access-request */
+ xmlAddChild(node, create_access_request(this, ike_sa_id));
+ if (!up)
+ {
+ break;
+ }
+ node2 = xmlNewNode(NULL, "metadata");
+ xmlAddChild(node, node2);
+ }
+ xmlAddChild(node2, create_capability(this, group));
+ }
+ }
+ e2->destroy(e2);
+ }
+ e1->destroy(e1);
+
+ soap_msg = tnc_ifmap_soap_msg_create(this->uri, this->user_pass, this->tls);
+ success = soap_msg->post(soap_msg, request, "publishReceived", NULL);
+ soap_msg->destroy(soap_msg);
+
+ return success;
+}
+
+METHOD(tnc_ifmap_soap_t, publish_device_ip, bool,
+ private_tnc_ifmap_soap_t *this, host_t *host)
+{
+ tnc_ifmap_soap_msg_t *soap_msg;
+ xmlNodePtr request, update;
+ bool success;
+
+ /* build publish update request */
+ request = create_publish_request(this);
+ update = xmlNewNode(NULL, "update");
+ xmlAddChild(request, update);
+
+ /* add device, ip-address and metadata */
+ xmlAddChild(update, create_device(this));
+ xmlAddChild(update, create_ip_address(this, host));
+ xmlAddChild(update, create_metadata(this, "device-ip"));
+
+ soap_msg = tnc_ifmap_soap_msg_create(this->uri, this->user_pass, this->tls);
+ success = soap_msg->post(soap_msg, request, "publishReceived", NULL);
+ soap_msg->destroy(soap_msg);
+
+ return success;
+}
+
+METHOD(tnc_ifmap_soap_t, publish_enforcement_report, bool,
+ private_tnc_ifmap_soap_t *this, host_t *host, char *action, char *reason)
+{
+ tnc_ifmap_soap_msg_t *soap_msg;
+ xmlNodePtr request, update;
+ bool success;
+
+ /* build publish update request */
+ request = create_publish_request(this);
+ update = xmlNewNode(NULL, "update");
+ xmlAddChild(request, update);
+
+ /* add ip-address and metadata */
+ xmlAddChild(update, create_ip_address(this, host));
+ xmlAddChild(update, create_device(this));
+ xmlAddChild(update, create_enforcement_report(this, action, reason));
+
+ soap_msg = tnc_ifmap_soap_msg_create(this->uri, this->user_pass, this->tls);
+ success = soap_msg->post(soap_msg, request, "publishReceived", NULL);
+ soap_msg->destroy(soap_msg);
+
+ return success;
+}
+
+METHOD(tnc_ifmap_soap_t, endSession, bool,
+ private_tnc_ifmap_soap_t *this)
+{
+ tnc_ifmap_soap_msg_t *soap_msg;
+ xmlNodePtr request;
+ bool success;
+
+ /* build endSession request */
+ request = xmlNewNode(NULL, "endSession");
+ this->ns = xmlNewNs(request, IFMAP_NS, "ifmap");
+ xmlSetNs(request, this->ns);
+ xmlNewProp(request, "session-id", this->session_id);
+
+ soap_msg = tnc_ifmap_soap_msg_create(this->uri, this->user_pass, this->tls);
+ success = soap_msg->post(soap_msg, request, "endSessionResult", NULL);
+ soap_msg->destroy(soap_msg);
+
+ return success;
+}
+
+METHOD(tnc_ifmap_soap_t, destroy, void,
+ private_tnc_ifmap_soap_t *this)
+{
+ if (this->session_id)
+ {
+ endSession(this);
+ xmlFree(this->session_id);
+ xmlFree(this->ifmap_publisher_id);
+ free(this->device_name);
+ }
+ DESTROY_IF(this->tls);
+ DESTROY_IF(this->host);
+
+ if (this->fd != IFMAP_NO_FD)
+ {
+ close(this->fd);
+ }
+ lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
+ this->creds->destroy(this->creds);
+ free(this->user_pass.ptr);
+ free(this);
+}
+
+static bool soap_init(private_tnc_ifmap_soap_t *this)
+{
+ char *server_uri, *server_str, *port_str, *uri_str;
+ char *server_cert, *client_cert, *client_key, *user_pass;
+ int port;
+ certificate_t *cert;
+ private_key_t *key;
+ identification_t *server_id, *client_id = NULL;
+
+ /* getting configuration parameters from strongswan.conf */
+ server_uri = lib->settings->get_str(lib->settings,
+ "%s.plugins.tnc-ifmap.server_uri", IFMAP_URI, charon->name);
+ server_cert = lib->settings->get_str(lib->settings,
+ "%s.plugins.tnc-ifmap.server_cert", NULL, charon->name);
+ client_cert = lib->settings->get_str(lib->settings,
+ "%s.plugins.tnc-ifmap.client_cert", NULL, charon->name);
+ client_key = lib->settings->get_str(lib->settings,
+ "%s.plugins.tnc-ifmap.client_key", NULL, charon->name);
+ user_pass = lib->settings->get_str(lib->settings,
+ "%s.plugins.tnc-ifmap.username_password", NULL, charon->name);
+
+ /* load [self-signed] MAP server certificate */
+ if (!server_cert)
+ {
+ DBG1(DBG_TNC, "MAP server certificate not defined");
+ return FALSE;
+ }
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, server_cert, BUILD_END);
+ if (!cert)
+ {
+ DBG1(DBG_TNC, "loading MAP server certificate from '%s' failed",
+ server_cert);
+ return FALSE;
+ }
+ DBG1(DBG_TNC, "loaded MAP server certificate from '%s'", server_cert);
+ server_id = cert->get_subject(cert);
+ this->creds->add_cert(this->creds, TRUE, cert);
+
+ /* check availability of client credentials */
+ if (!((client_cert && client_key) || user_pass))
+ {
+ DBG1(DBG_TNC, "neither MAP client certificate and private key "
+ "nor username:password defined");
+ return FALSE;
+ }
+
+ if (client_cert)
+ {
+ /* load MAP client certificate */
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, client_cert, BUILD_END);
+ if (!cert)
+ {
+ DBG1(DBG_TNC, "loading MAP client certificate from '%s' failed",
+ client_cert);
+ return FALSE;
+ }
+ DBG1(DBG_TNC, "loaded MAP client certificate from '%s'", client_cert);
+ this->creds->add_cert(this->creds, TRUE, cert);
+
+ /* load MAP client private key */
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_FROM_FILE, client_key, BUILD_END);
+ if (!key)
+ {
+ DBG1(DBG_TNC, "loading MAP client private key from '%s' failed",
+ client_key);
+ return FALSE;
+ }
+ DBG1(DBG_TNC, "loaded MAP client RSA private key from '%s'", client_key);
+ this->creds->add_key(this->creds, key);
+
+ /* set client ID to certificate distinguished name */
+ client_id = cert->get_subject(cert);
+ }
+ else
+ {
+ /* set base64-encoded username:password for HTTP Basic Authentication */
+ this->user_pass = chunk_to_base64(chunk_from_str(user_pass), NULL);
+ }
+
+ /* remove HTTPS prefix if any */
+ if (strlen(server_uri) >= 8 && strncaseeq(server_uri, "https://", 8))
+ {
+ server_uri += 8;
+ }
+ this->uri = server_uri;
+
+ /* duplicate server string since we are going to manipulate it */
+ server_str = strdup(server_uri);
+
+ /* extract server name and port from server URI */
+ port_str = strchr(server_str, ':');
+ if (port_str)
+ {
+ *port_str++ = '\0';
+ if (sscanf(port_str, "%d", &port) != 1)
+ {
+ DBG1(DBG_TNC, "parsing server port %s failed", port_str);
+ free(server_str);
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* use default https port */
+ port = 443;
+ uri_str = strchr(server_str, '/');
+ if (uri_str)
+ {
+ *uri_str = '\0';
+ }
+ }
+
+ /* open TCP socket and connect to MAP server */
+ this->host = host_create_from_dns(server_str, 0, port);
+ if (!this->host)
+ {
+ DBG1(DBG_TNC, "resolving hostname %s failed", server_str);
+ free(server_str);
+ return FALSE;
+ }
+ free(server_str);
+
+ this->fd = socket(this->host->get_family(this->host), SOCK_STREAM, 0);
+ if (this->fd == IFMAP_NO_FD)
+ {
+ DBG1(DBG_TNC, "opening socket failed: %s", strerror(errno));
+ return FALSE;
+ }
+
+ if (connect(this->fd, this->host->get_sockaddr(this->host),
+ *this->host->get_sockaddr_len(this->host)) == -1)
+ {
+ DBG1(DBG_TNC, "connecting to %#H failed: %s",
+ this->host, strerror(errno));
+ return FALSE;
+ }
+
+ /* open TLS socket */
+ this->tls = tls_socket_create(FALSE, server_id, client_id, this->fd, NULL);
+ if (!this->tls)
+ {
+ DBG1(DBG_TNC, "creating TLS socket failed");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * See header
+ */
+tnc_ifmap_soap_t *tnc_ifmap_soap_create()
+{
+ private_tnc_ifmap_soap_t *this;
+
+ INIT(this,
+ .public = {
+ .newSession = _newSession,
+ .purgePublisher = _purgePublisher,
+ .publish_ike_sa = _publish_ike_sa,
+ .publish_device_ip = _publish_device_ip,
+ .publish_enforcement_report = _publish_enforcement_report,
+ .endSession = _endSession,
+ .destroy = _destroy,
+ },
+ .fd = IFMAP_NO_FD,
+ .creds = mem_cred_create(),
+ );
+
+ lib->credmgr->add_set(lib->credmgr, &this->creds->set);
+
+ if (!soap_init(this))
+ {
+ destroy(this);
+ return NULL;
+ }
+
+ return &this->public;
+}
+
--- /dev/null
+/*
+ * Copyright (C) 2011-2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tnc_ifmap_soap tnc_ifmap_soap
+ * @{ @ingroup tnc_ifmap
+ */
+
+#ifndef TNC_IFMAP_SOAP_H_
+#define TNC_IFMAP_SOAP_H_
+
+#include <library.h>
+#include <networking/host.h>
+#include <sa/ike_sa.h>
+
+typedef struct tnc_ifmap_soap_t tnc_ifmap_soap_t;
+
+/**
+ * Implements the TNC IF-MAP 2.0 SOAP Binding
+ */
+struct tnc_ifmap_soap_t {
+
+ /**
+ * Creates a new IF-MAP session
+ *
+ * @return TRUE if command was successful
+ */
+ bool (*newSession)(tnc_ifmap_soap_t *this);
+
+ /**
+ * Purges all metadata published by this publisher
+ *
+ * @return TRUE if command was successful
+ */
+ bool (*purgePublisher)(tnc_ifmap_soap_t *this);
+
+ /**
+ * Publish metadata about established/deleted IKE_SAs
+ *
+ * @param ike_sa IKE_SA for which metadate is published
+ * @param up TRUE if IKE_SEA is up, FALSE if down
+ * @return TRUE if command was successful
+ */
+ bool (*publish_ike_sa)(tnc_ifmap_soap_t *this, ike_sa_t *ike_sa, bool up);
+
+ /**
+ * Publish PEP device-ip metadata
+ *
+ * @param host IP address of local endpoint
+ * @return TRUE if command was successful
+ */
+ bool (*publish_device_ip)(tnc_ifmap_soap_t *this, host_t *host);
+
+ /**
+ * Publish enforcement-report metadata
+ *
+ * @param host Host to be enforced
+ * @param action Enforcement action ("block" or "quarantine")
+ * @param reason Enforcement reason
+ * @return TRUE if command was successful
+ */
+ bool (*publish_enforcement_report)(tnc_ifmap_soap_t *this, host_t *host,
+ char *action, char *reason);
+
+ /**
+ * Ends an IF-MAP session
+ *
+ * @return TRUE if command was successful
+ */
+ bool (*endSession)(tnc_ifmap_soap_t *this);
+
+ /**
+ * Destroy a tnc_ifmap_soap_t.
+ */
+ void (*destroy)(tnc_ifmap_soap_t *this);
+};
+
+/**
+ * Create a tnc_ifmap_soap instance.
+ */
+tnc_ifmap_soap_t *tnc_ifmap_soap_create();
+
+#endif /** TNC_IFMAP_SOAP_H_ @}*/
--- /dev/null
+/*
+ * Copyright (C) 2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE /* for asprintf() */
+
+#include "tnc_ifmap_soap_msg.h"
+
+#include <utils/debug.h>
+#include <utils/lexparser.h>
+
+#include <stdio.h>
+
+#define SOAP_NS "http://www.w3.org/2003/05/soap-envelope"
+
+typedef struct private_tnc_ifmap_soap_msg_t private_tnc_ifmap_soap_msg_t;
+
+/**
+ * Private data of an tnc_ifmap_soap_msg_t object.
+ */
+struct private_tnc_ifmap_soap_msg_t {
+
+ /**
+ * Public tnc_ifmap_soap_msg_t interface.
+ */
+ tnc_ifmap_soap_msg_t public;
+
+ /**
+ * HTTPS Server URI with https:// prefix removed
+ */
+ char *uri;
+
+ /**
+ * Optional base64-encoded username:password for HTTP Basic Authentication
+ */
+ chunk_t user_pass;
+
+ /**
+ * TLS Socket
+ */
+ tls_socket_t *tls;
+
+ /**
+ * XML Document
+ */
+ xmlDocPtr doc;
+
+};
+
+/**
+ * Send HTTP POST request and receive HTTP response
+ */
+static bool http_post(private_tnc_ifmap_soap_msg_t *this, chunk_t out,
+ chunk_t *in)
+{
+ char *host, *path, *request, buf[2048];
+ chunk_t line, http, parameter;
+ int len, code, content_len = 0;
+
+ /* Duplicate host[/path] string since we are going to manipulate it */
+ len = strlen(this->uri) + 2;
+ host = malloc(len);
+ memset(host, '\0', len);
+ strcpy(host, this->uri);
+
+ /* Extract appended path or set to root */
+ path = strchr(host, '/');
+ if (!path)
+ {
+ path = host + len - 2;
+ *path = '/';
+ }
+
+ /* Use Basic Authentication? */
+ if (this->user_pass.len)
+ {
+ snprintf(buf, sizeof(buf), "Authorization: Basic %.*s\r\n",
+ this->user_pass.len, this->user_pass.ptr);
+ }
+ else
+ {
+ *buf = '\0';
+ }
+
+ /* Write HTTP POST request */
+ len = asprintf(&request,
+ "POST %s HTTP/1.1\r\n"
+ "Host: %.*s\r\n"
+ "%s"
+ "Content-Type: application/soap+xml;charset=utf-8\r\n"
+ "Content-Length: %d\r\n"
+ "\r\n"
+ "%.*s", path, (path-host), host, buf, out.len, out.len, out.ptr);
+ free(host);
+
+ if (len == -1)
+ {
+ return FALSE;
+ }
+ http = chunk_create(request, len);
+ DBG3(DBG_TLS, "%B", &http);
+
+ this->tls->write(this->tls, request, len);
+ free(request);
+
+ /* Read HTTP response */
+ len = this->tls->read(this->tls, buf, sizeof(buf), TRUE);
+ if (len == -1)
+ {
+ return FALSE;
+ }
+ *in = chunk_create(buf, len);
+
+ /* Process HTTP protocol version */
+ if (!fetchline(in, &line) || !extract_token(&http, ' ', &line) ||
+ !match("HTTP/1.1", &http) || sscanf(line.ptr, "%d", &code) != 1)
+ {
+ DBG1(DBG_TNC, "malformed http response header");
+ return FALSE;
+ }
+ if (code != 200)
+ {
+ DBG1(DBG_TNC, "http response returns error code %d", code);
+ return FALSE;
+ }
+
+ /* Process HTTP header line by line until the HTTP body is reached */
+ while (fetchline(in, &line))
+ {
+ if (line.len == 0)
+ {
+ break;
+ }
+
+ if (extract_token(¶meter, ':', &line) &&
+ match("Content-Length", ¶meter) &&
+ sscanf(line.ptr, "%d", &len) == 1)
+ {
+ content_len = len;
+ }
+ }
+
+ /* Found Content-Length parameter and check size of HTTP body */
+ if (content_len)
+ {
+ if (content_len > in->len)
+ {
+ DBG1(DBG_TNC, "http body is smaller than content length");
+ return FALSE;
+ }
+ in->len = content_len;
+ }
+ *in = chunk_clone(*in);
+
+ return TRUE;
+}
+
+/**
+ * Find a child node with a given name
+ */
+static xmlNodePtr find_child(xmlNodePtr parent, const xmlChar* name)
+{
+ xmlNodePtr child;
+
+ child = parent->xmlChildrenNode;
+ while (child)
+ {
+ if (xmlStrcmp(child->name, name) == 0)
+ {
+ return child;
+ }
+ child = child->next;
+ }
+
+ DBG1(DBG_TNC, "child node \"%s\" not found", name);
+ return NULL;
+}
+
+METHOD(tnc_ifmap_soap_msg_t, post, bool,
+ private_tnc_ifmap_soap_msg_t *this, xmlNodePtr request, char *result_name,
+ xmlNodePtr *result)
+{
+ xmlDocPtr doc;
+ xmlNodePtr env, body, cur, response;
+ xmlNsPtr ns;
+ xmlChar *xml, *errorCode, *errorString;
+ int len;
+ chunk_t in, out;
+
+ DBG2(DBG_TNC, "sending ifmap %s", request->name);
+
+ /* Generate XML Document containing SOAP Envelope */
+ doc = xmlNewDoc("1.0");
+ env =xmlNewNode(NULL, "Envelope");
+ ns = xmlNewNs(env, SOAP_NS, "env");
+ xmlSetNs(env, ns);
+ xmlDocSetRootElement(doc, env);
+
+ /* Add SOAP Body containing IF-MAP request */
+ body = xmlNewNode(ns, "Body");
+ xmlAddChild(body, request);
+ xmlAddChild(env, body);
+
+ /* Convert XML Document into a character string */
+ xmlDocDumpFormatMemory(doc, &xml, &len, 1);
+ xmlFreeDoc(doc);
+ DBG3(DBG_TNC, "%.*s", len, xml);
+ out = chunk_create(xml, len);
+
+ /* Send SOAP-XML request via HTTP POST */
+ if (!http_post(this, out, &in))
+ {
+ xmlFree(xml);
+ return FALSE;
+ }
+ xmlFree(xml);
+
+ DBG3(DBG_TNC, "%B", &in);
+ this->doc = xmlParseMemory(in.ptr, in.len);
+ free(in.ptr);
+
+ if (!this->doc)
+ {
+ DBG1(DBG_TNC, "failed to parse XML message");
+ return FALSE;
+ }
+
+ /* check out XML document */
+ cur = xmlDocGetRootElement(this->doc);
+ if (!cur)
+ {
+ DBG1(DBG_TNC, "empty XML message");
+ return FALSE;
+ }
+
+ /* get XML Document type is a SOAP Envelope */
+ if (xmlStrcmp(cur->name, "Envelope"))
+ {
+ DBG1(DBG_TNC, "XML message does not contain a SOAP Envelope");
+ return FALSE;
+ }
+
+ /* get SOAP Body */
+ cur = find_child(cur, "Body");
+ if (!cur)
+ {
+ return FALSE;
+ }
+
+ /* get IF-MAP response */
+ response = find_child(cur, "response");
+ if (!response)
+ {
+ return FALSE;
+ }
+
+ /* get IF-MAP result */
+ cur = find_child(response, result_name);
+ if (!cur)
+ {
+ cur = find_child(response, "errorResult");
+ if (cur)
+ {
+ DBG1(DBG_TNC, "received errorResult");
+
+ errorCode = xmlGetProp(cur, "errorCode");
+ if (errorCode)
+ {
+ DBG1(DBG_TNC, " %s", errorCode);
+ xmlFree(errorCode);
+ }
+
+ cur = find_child(cur, "errorString");
+ if (cur)
+ {
+ errorString = xmlNodeGetContent(cur);
+ if (errorString)
+ {
+ DBG1(DBG_TNC, " %s", errorString);
+ xmlFree(errorString);
+ }
+ }
+ }
+ return FALSE;
+ }
+
+ if (result)
+ {
+ *result = cur;
+ }
+ return TRUE;
+}
+
+METHOD(tnc_ifmap_soap_msg_t, destroy, void,
+ private_tnc_ifmap_soap_msg_t *this)
+{
+ if (this->doc)
+ {
+ xmlFreeDoc(this->doc);
+ }
+ free(this);
+}
+
+/**
+ * See header
+ */
+tnc_ifmap_soap_msg_t *tnc_ifmap_soap_msg_create(char *uri, chunk_t user_pass,
+ tls_socket_t *tls)
+{
+ private_tnc_ifmap_soap_msg_t *this;
+
+ INIT(this,
+ .public = {
+ .post = _post,
+ .destroy = _destroy,
+ },
+ .uri = uri,
+ .user_pass = user_pass,
+ .tls = tls,
+ );
+
+ return &this->public;
+}
+
--- /dev/null
+/*
+ * Copyright (C) 2013 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tnc_ifmap_soap_msg tnc_ifmap_soap_msg
+ * @{ @ingroup tnc_ifmap
+ */
+
+#ifndef TNC_IFMAP_SOAP_MSG_H_
+#define TNC_IFMAP_SOAP_MSG_H_
+
+#include <library.h>
+#include <tls_socket.h>
+
+#include <libxml/parser.h>
+
+typedef struct tnc_ifmap_soap_msg_t tnc_ifmap_soap_msg_t;
+
+/**
+ * Interface for sending and receiving SOAP-XML messages
+ */
+struct tnc_ifmap_soap_msg_t {
+
+ /**
+ * Post an IF-MAP request in a SOAP-XML message and return a result
+ *
+ * @param request XML-encoded IF-MAP request
+ * @param result_name name of the IF-MAP result
+ * @param result XML-encoded IF-MAP result
+ */
+ bool (*post)(tnc_ifmap_soap_msg_t *this, xmlNodePtr request,
+ char *result_name, xmlNodePtr* result);
+
+ /**
+ * Destroy a tnc_ifmap_soap_msg_t object.
+ */
+ void (*destroy)(tnc_ifmap_soap_msg_t *this);
+};
+
+/**
+ * Create a tnc_ifmap_soap_msg instance.
+ *
+ * @param uri HTTPS URI with https:// prefix removed
+ * @param user_pass Optional username:password for HTTP Basic Authentication
+ * @param tls TLS socket protecting the SOAP message
+ */
+tnc_ifmap_soap_msg_t *tnc_ifmap_soap_msg_create(char *uri, chunk_t user_pass,
+ tls_socket_t *tls);
+
+#endif /** TNC_IFMAP_SOAP_MSG_H_ @}*/
+++ /dev/null
-
-INCLUDES = \
- -I$(top_srcdir)/src/libstrongswan \
- -I$(top_srcdir)/src/libtls \
- -I$(top_srcdir)/src/libhydra \
- -I$(top_srcdir)/src/libcharon \
- ${xml_CFLAGS}
-
-AM_CFLAGS = -rdynamic
-
-if MONOLITHIC
-noinst_LTLIBRARIES = libstrongswan-tnc-ifmap2.la
-else
-plugin_LTLIBRARIES = libstrongswan-tnc-ifmap2.la
-endif
-
-libstrongswan_tnc_ifmap2_la_LIBADD = \
- $(top_builddir)/src/libtls/libtls.la ${xml_LIBS}
-
-libstrongswan_tnc_ifmap2_la_SOURCES = \
- tnc_ifmap2_plugin.h tnc_ifmap2_plugin.c \
- tnc_ifmap2_listener.h tnc_ifmap2_listener.c \
- tnc_ifmap2_soap.h tnc_ifmap2_soap.c \
- tnc_ifmap2_soap_msg.h tnc_ifmap2_soap_msg.c
-
-libstrongswan_tnc_ifmap2_la_LDFLAGS = -module -avoid-version
-
+++ /dev/null
-/*
- * Copyright (C) 2011-2013 Andreas Steffen
- * HSR Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "tnc_ifmap2_listener.h"
-#include "tnc_ifmap2_soap.h"
-
-#include <daemon.h>
-#include <hydra.h>
-#include <utils/debug.h>
-
-typedef struct private_tnc_ifmap2_listener_t private_tnc_ifmap2_listener_t;
-
-/**
- * Private data of an tnc_ifmap2_listener_t object.
- */
-struct private_tnc_ifmap2_listener_t {
-
- /**
- * Public tnc_ifmap2_listener_t interface.
- */
- tnc_ifmap2_listener_t public;
-
- /**
- * TNC IF-MAP 2.0 SOAP interface
- */
- tnc_ifmap2_soap_t *ifmap;
-
-};
-
-/**
- * Publish PEP device-ip metadata
- */
-static bool publish_device_ip_addresses(private_tnc_ifmap2_listener_t *this)
-{
- enumerator_t *enumerator;
- host_t *host;
- bool success = TRUE;
-
- enumerator = hydra->kernel_interface->create_address_enumerator(
- hydra->kernel_interface, ADDR_TYPE_REGULAR);
- while (enumerator->enumerate(enumerator, &host))
- {
- if (!this->ifmap->publish_device_ip(this->ifmap, host))
- {
- success = FALSE;
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- return success;
-}
-
-/**
- * Publish all IKE_SA metadata
- */
-static bool reload_metadata(private_tnc_ifmap2_listener_t *this)
-{
- enumerator_t *enumerator;
- ike_sa_t *ike_sa;
- bool success = TRUE;
-
- enumerator = charon->controller->create_ike_sa_enumerator(
- charon->controller, FALSE);
- while (enumerator->enumerate(enumerator, &ike_sa))
- {
- if (ike_sa->get_state(ike_sa) != IKE_ESTABLISHED)
- {
- continue;
- }
- if (!this->ifmap->publish_ike_sa(this->ifmap, ike_sa, TRUE))
- {
- success = FALSE;
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- return success;
-}
-
-METHOD(listener_t, ike_updown, bool,
- private_tnc_ifmap2_listener_t *this, ike_sa_t *ike_sa, bool up)
-{
- if (ike_sa->get_state(ike_sa) != IKE_CONNECTING)
- {
- this->ifmap->publish_ike_sa(this->ifmap, ike_sa, up);
- }
- return TRUE;
-}
-
-METHOD(listener_t, alert, bool,
- private_tnc_ifmap2_listener_t *this, ike_sa_t *ike_sa, alert_t alert,
- va_list args)
-{
- if (alert == ALERT_PEER_AUTH_FAILED)
- {
- this->ifmap->publish_enforcement_report(this->ifmap,
- ike_sa->get_other_host(ike_sa),
- "block", "authentication failed");
- }
- return TRUE;
-}
-
-METHOD(tnc_ifmap2_listener_t, destroy, void,
- private_tnc_ifmap2_listener_t *this)
-{
- DESTROY_IF(this->ifmap);
- free(this);
-}
-
-/**
- * See header
- */
-tnc_ifmap2_listener_t *tnc_ifmap2_listener_create(bool reload)
-{
- private_tnc_ifmap2_listener_t *this;
-
- INIT(this,
- .public = {
- .listener = {
- .ike_updown = _ike_updown,
- .alert = _alert,
- },
- .destroy = _destroy,
- },
- .ifmap = tnc_ifmap2_soap_create(),
- );
-
- if (!this->ifmap)
- {
- destroy(this);
- return NULL;
- }
- if (!this->ifmap->newSession(this->ifmap))
- {
- destroy(this);
- return NULL;
- }
- if (!this->ifmap->purgePublisher(this->ifmap))
- {
- destroy(this);
- return NULL;
- }
- if (!publish_device_ip_addresses(this))
- {
- destroy(this);
- return NULL;
- }
- if (reload)
- {
- if (!reload_metadata(this))
- {
- destroy(this);
- return NULL;
- }
- }
-
- return &this->public;
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2011-2013 Andreas Steffen
- * HSR Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup tnc_ifmap2_listener tnc_ifmap2_listener
- * @{ @ingroup tnc_ifmap2
- */
-
-#ifndef TNC_IFMAP2_LISTENER_H_
-#define TNC_IFMAP2_LISTENER_H_
-
-#include <bus/bus.h>
-
-typedef struct tnc_ifmap2_listener_t tnc_ifmap2_listener_t;
-
-/**
- * Listener which collects information on IKE_SAs
- */
-struct tnc_ifmap2_listener_t {
-
- /**
- * Implements listener_t.
- */
- listener_t listener;
-
- /**
- * Destroy a tnc_ifmap2_listener_t.
- */
- void (*destroy)(tnc_ifmap2_listener_t *this);
-};
-
-/**
- * Create a tnc_ifmap2_listener instance.
- *
- * @param reload reload all IKE_SA metadata
- */
-tnc_ifmap2_listener_t *tnc_ifmap2_listener_create(bool reload);
-
-#endif /** TNC_IFMAP2_LISTENER_H_ @}*/
+++ /dev/null
-/*
- * Copyright (C) 2011-2013 Andreas Steffen
- * HSR Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "tnc_ifmap2_plugin.h"
-#include "tnc_ifmap2_listener.h"
-
-#include <daemon.h>
-
-typedef struct private_tnc_ifmap2_plugin_t private_tnc_ifmap2_plugin_t;
-
-/**
- * private data of tnc_ifmap2 plugin
- */
-struct private_tnc_ifmap2_plugin_t {
-
- /**
- * implements plugin interface
- */
- tnc_ifmap2_plugin_t public;
-
- /**
- * Listener interface, listens to CHILD_SA state changes
- */
- tnc_ifmap2_listener_t *listener;
-};
-
-METHOD(plugin_t, get_name, char*,
- private_tnc_ifmap2_plugin_t *this)
-{
- return "tnc-ifmap2";
-}
-
-/**
- * Register tnc_ifmap2 plugin features
- */
-static bool register_tnc_ifmap2(private_tnc_ifmap2_plugin_t *this,
- plugin_feature_t *feature, bool reg, void *data)
-{
- if (reg)
- {
- this->listener = tnc_ifmap2_listener_create(FALSE);
- if (!this->listener)
- {
- return FALSE;
- }
- charon->bus->add_listener(charon->bus, &this->listener->listener);
- }
- else
- {
- if (this->listener)
- {
- charon->bus->remove_listener(charon->bus, &this->listener->listener);
- this->listener->destroy(this->listener);
- }
- }
- return TRUE;
-}
-
-METHOD(plugin_t, get_features, int,
- tnc_ifmap2_plugin_t *this, plugin_feature_t *features[])
-{
- static plugin_feature_t f[] = {
- PLUGIN_CALLBACK((plugin_feature_callback_t)register_tnc_ifmap2, NULL),
- PLUGIN_PROVIDE(CUSTOM, "tnc-ifmap-2.1"),
- PLUGIN_SDEPEND(CERT_DECODE, CERT_X509),
- PLUGIN_SDEPEND(PRIVKEY, KEY_RSA),
- };
- *features = f;
- return countof(f);
-}
-
-METHOD(plugin_t, reload, bool,
- private_tnc_ifmap2_plugin_t *this)
-{
- if (this->listener)
- {
- charon->bus->remove_listener(charon->bus, &this->listener->listener);
- this->listener->destroy(this->listener);
- }
-
- this->listener = tnc_ifmap2_listener_create(TRUE);
- if (!this->listener)
- {
- return FALSE;
- }
- charon->bus->add_listener(charon->bus, &this->listener->listener);
-
- return TRUE;
-}
-
-METHOD(plugin_t, destroy, void,
- private_tnc_ifmap2_plugin_t *this)
-{
- free(this);
-}
-
-/*
- * see header file
- */
-plugin_t *tnc_ifmap2_plugin_create()
-{
- private_tnc_ifmap2_plugin_t *this;
-
- INIT(this,
- .public = {
- .plugin = {
- .get_name = _get_name,
- .get_features = _get_features,
- .reload = _reload,
- .destroy = _destroy,
- },
- },
- );
-
- return &this->public.plugin;
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2011-2013 Andreas Steffen
- * HSR Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup tnc_ifmap2 tnc_ifmap2
- * @ingroup cplugins
- *
- * @defgroup tnc_ifmap2_plugin tnc_ifmap2_plugin
- * @{ @ingroup tnc_ifmap2
- */
-
-#ifndef TNC_IFMAP2_PLUGIN_H_
-#define TNC_IFMAP2_PLUGIN_H_
-
-#include <plugins/plugin.h>
-
-typedef struct tnc_ifmap2_plugin_t tnc_ifmap2_plugin_t;
-
-/**
- * TNC IF-MAP plugin
- */
-struct tnc_ifmap2_plugin_t {
-
- /**
- * implements plugin interface
- */
- plugin_t plugin;
-};
-
-#endif /** TNC_IFMAP2_PLUGIN_H_ @}*/
+++ /dev/null
-/*
- * Copyright (C) 2011-2013 Andreas Steffen
- * HSR Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "tnc_ifmap2_soap.h"
-#include "tnc_ifmap2_soap_msg.h"
-
-#include <utils/debug.h>
-#include <credentials/sets/mem_cred.h>
-#include <daemon.h>
-
-#include <tls_socket.h>
-
-#include <errno.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#define IFMAP_NS "http://www.trustedcomputinggroup.org/2010/IFMAP/2"
-#define IFMAP_META_NS "http://www.trustedcomputinggroup.org/2010/IFMAP-METADATA/2"
-#define IFMAP_URI "https://localhost:8444/imap"
-#define IFMAP_NO_FD -1
-
-typedef struct private_tnc_ifmap2_soap_t private_tnc_ifmap2_soap_t;
-
-/**
- * Private data of an tnc_ifmap2_soap_t object.
- */
-struct private_tnc_ifmap2_soap_t {
-
- /**
- * Public tnc_ifmap2_soap_t interface.
- */
- tnc_ifmap2_soap_t public;
-
- /**
- * SOAP Session ID
- */
- xmlChar *session_id;
-
- /**
- * IF-MAP Publisher ID
- */
- xmlChar *ifmap_publisher_id;
-
- /**
- * IF-MAP namespace
- */
- xmlNsPtr ns;
-
- /**
- * IF-MAP metadata namespace
- */
- xmlNsPtr ns_meta;
-
- /**
- * PEP and PDP device name
- */
- char *device_name;
-
- /**
- * HTTPS Server URI with https:// prefix removed
- */
- char *uri;
-
- /**
- * Optional base64-encoded username:password for HTTP Basic Authentication
- */
- chunk_t user_pass;
-
- /**
- * IF-MAP Server (IP address and port)
- */
- host_t *host;
-
- /**
- * TLS socket
- */
- tls_socket_t *tls;
-
- /**
- * File descriptor for secure TCP socket
- */
- int fd;
-
- /**
- * In memory credential set
- */
- mem_cred_t *creds;
-
-};
-
-METHOD(tnc_ifmap2_soap_t, newSession, bool,
- private_tnc_ifmap2_soap_t *this)
-{
- tnc_ifmap2_soap_msg_t *soap_msg;
- xmlNodePtr request, result;
-
- /*build newSession request */
- request = xmlNewNode(NULL, "newSession");
- this->ns = xmlNewNs(request, IFMAP_NS, "ifmap");
- xmlSetNs(request, this->ns);
-
- soap_msg = tnc_ifmap2_soap_msg_create(this->uri, this->user_pass, this->tls);
- if (!soap_msg->post(soap_msg, request, "newSessionResult", &result))
- {
- soap_msg->destroy(soap_msg);
- return FALSE;
- }
-
- /* get session-id and ifmap-publisher-id properties */
- this->session_id = xmlGetProp(result, "session-id");
- this->ifmap_publisher_id = xmlGetProp(result, "ifmap-publisher-id");
- soap_msg->destroy(soap_msg);
-
- DBG1(DBG_TNC, "session-id: %s, ifmap-publisher-id: %s",
- this->session_id, this->ifmap_publisher_id);
-
- /* set PEP and PDP device name (defaults to IF-MAP Publisher ID) */
- this->device_name = lib->settings->get_str(lib->settings,
- "%s.plugins.tnc-ifmap2.device_name",
- this->ifmap_publisher_id, charon->name);
- this->device_name = strdup(this->device_name);
-
- return this->session_id && this->ifmap_publisher_id;
-}
-
-METHOD(tnc_ifmap2_soap_t, purgePublisher, bool,
- private_tnc_ifmap2_soap_t *this)
-{
- tnc_ifmap2_soap_msg_t *soap_msg;
- xmlNodePtr request;
- bool success;
-
- /* build purgePublisher request */
- request = xmlNewNode(NULL, "purgePublisher");
- this->ns = xmlNewNs(request, IFMAP_NS, "ifmap");
- xmlSetNs(request, this->ns);
- xmlNewProp(request, "session-id", this->session_id);
- xmlNewProp(request, "ifmap-publisher-id", this->ifmap_publisher_id);
-
- soap_msg = tnc_ifmap2_soap_msg_create(this->uri, this->user_pass, this->tls);
- success = soap_msg->post(soap_msg, request, "purgePublisherReceived", NULL);
- soap_msg->destroy(soap_msg);
-
- return success;
-}
-
-/**
- * Create an access-request based on device_name and ike_sa_id
- */
-static xmlNodePtr create_access_request(private_tnc_ifmap2_soap_t *this,
- u_int32_t id)
-{
- xmlNodePtr node;
- char buf[BUF_LEN];
-
- node = xmlNewNode(NULL, "access-request");
-
- snprintf(buf, BUF_LEN, "%s:%d", this->device_name, id);
- xmlNewProp(node, "name", buf);
-
- return node;
-}
-
-/**
- * Create an identity
- */
-static xmlNodePtr create_identity(private_tnc_ifmap2_soap_t *this,
- identification_t *id, bool is_user)
-{
- xmlNodePtr node;
- char buf[BUF_LEN], *id_type;
-
- node = xmlNewNode(NULL, "identity");
-
- snprintf(buf, BUF_LEN, "%Y", id);
- xmlNewProp(node, "name", buf);
-
- switch (id->get_type(id))
- {
- case ID_IPV4_ADDR:
- id_type = "other";
- xmlNewProp(node, "other-type-definition", "36906:ipv4-address");
- break;
- case ID_FQDN:
- id_type = is_user ? "username" : "dns-name";
- break;
- case ID_RFC822_ADDR:
- id_type = "email-address";
- break;
- case ID_IPV6_ADDR:
- id_type = "other";
- xmlNewProp(node, "other-type-definition", "36906:ipv6-address");
- break;
- case ID_DER_ASN1_DN:
- id_type = "distinguished-name";
- break;
- case ID_KEY_ID:
- id_type = "other";
- xmlNewProp(node, "other-type-definition", "36906:key-id");
- break;
- default:
- id_type = "other";
- xmlNewProp(node, "other-type-definition", "36906:other");
- }
- xmlNewProp(node, "type", id_type);
-
- return node;
-}
-
-/**
- * Create enforcement-report metadata
- */
-static xmlNodePtr create_enforcement_report(private_tnc_ifmap2_soap_t *this,
- xmlChar *action, xmlChar *reason)
-{
- xmlNodePtr node, node2, node3;
-
- node = xmlNewNode(NULL, "metadata");
- node2 = xmlNewNode(this->ns_meta, "enforcement-report");
- xmlAddChild(node, node2);
- xmlNewProp(node2, "ifmap-cardinality", "multiValue");
-
- node3 = xmlNewNode(NULL, "enforcement-action");
- xmlAddChild(node2, node3);
- xmlNodeAddContent(node3, action);
-
- node3 = xmlNewNode(NULL, "enforcement-reason");
- xmlAddChild(node2, node3);
- xmlNodeAddContent(node3, reason);
-
- return node;
-}
-
-/**
- * Create delete filter
- */
-static xmlNodePtr create_delete_filter(private_tnc_ifmap2_soap_t *this,
- char *metadata)
-{
- xmlNodePtr node;
- char buf[BUF_LEN];
-
- node = xmlNewNode(NULL, "delete");
-
- snprintf(buf, BUF_LEN, "meta:%s[@ifmap-publisher-id='%s']",
- metadata, this->ifmap_publisher_id);
- xmlNewProp(node, "filter", buf);
-
- return node;
-}
-
-/**
- * Create a publish request
- */
-static xmlNodePtr create_publish_request(private_tnc_ifmap2_soap_t *this)
-{
- xmlNodePtr request;
-
- request = xmlNewNode(NULL, "publish");
- this->ns = xmlNewNs(request, IFMAP_NS, "ifmap");
- xmlSetNs(request, this->ns);
- this->ns_meta = xmlNewNs(request, IFMAP_META_NS, "meta");
- xmlNewProp(request, "session-id", this->session_id);
-
- return request;
-}
-
-/**
- * Create a device
- */
-static xmlNodePtr create_device(private_tnc_ifmap2_soap_t *this)
-{
- xmlNodePtr node, node2;
-
- node = xmlNewNode(NULL, "device");
- node2 = xmlNewNode(NULL, "name");
- xmlAddChild(node, node2);
- xmlNodeAddContent(node2, this->device_name);
-
- return node;
-}
-
-/**
- * Create an ip-address
- */
-static xmlNodePtr create_ip_address(private_tnc_ifmap2_soap_t *this,
- host_t *host)
-{
- xmlNodePtr node;
- char buf[BUF_LEN];
-
- node = xmlNewNode(NULL, "ip-address");
-
- if (host->get_family(host) == AF_INET6)
- {
- chunk_t address;
- int len, written, i;
- char *pos;
- bool first = TRUE;
-
- /* output IPv6 address in canonical IF-MAP 2.0 format */
- address = host->get_address(host);
- pos = buf;
- len = sizeof(buf);
-
- for (i = 0; i < address.len; i = i + 2)
- {
- written = snprintf(pos, len, "%s%x", first ? "" : ":",
- 256*address.ptr[i] + address.ptr[i+1]);
- if (written < 0 || written >= len)
- {
- break;
- }
- pos += written;
- len -= written;
- first = FALSE;
- }
- }
- else
- {
- snprintf(buf, BUF_LEN, "%H", host);
- }
-
- xmlNewProp(node, "value", buf);
- xmlNewProp(node, "type", host->get_family(host) == AF_INET ? "IPv4" : "IPv6");
-
- return node;
-}
-
-/**
- * Create metadata
- */
-static xmlNodePtr create_metadata(private_tnc_ifmap2_soap_t *this,
- xmlChar *metadata)
-{
- xmlNodePtr node, node2;
-
- node = xmlNewNode(NULL, "metadata");
- node2 = xmlNewNode(this->ns_meta, metadata);
- xmlAddChild(node, node2);
- xmlNewProp(node2, "ifmap-cardinality", "singleValue");
-
- return node;
-}
-
-/**
- * Create capability metadata
- */
-static xmlNodePtr create_capability(private_tnc_ifmap2_soap_t *this,
- identification_t *name)
-{
- xmlNodePtr node, node2;
- char buf[BUF_LEN];
-
- node = xmlNewNode(this->ns_meta, "capability");
- xmlNewProp(node, "ifmap-cardinality", "multiValue");
-
- node2 = xmlNewNode(NULL, "name");
- xmlAddChild(node, node2);
- snprintf(buf, BUF_LEN, "%Y", name);
- xmlNodeAddContent(node2, this->device_name);
-
- node2 = xmlNewNode(NULL, "administrative-domain");
- xmlNodeAddContent(node2, "strongswan");
-
- return node;
-}
-
-METHOD(tnc_ifmap2_soap_t, publish_ike_sa, bool,
- private_tnc_ifmap2_soap_t *this, ike_sa_t *ike_sa, bool up)
-{
- tnc_ifmap2_soap_msg_t *soap_msg;
- xmlNodePtr request, node, node2 = NULL;
- enumerator_t *e1, *e2;
- auth_rule_t type;
- identification_t *id, *eap_id, *group;
- host_t *host;
- auth_cfg_t *auth;
- u_int32_t ike_sa_id;
- bool is_user = FALSE, first = TRUE, success;
-
- /* extract relevant data from IKE_SA*/
- ike_sa_id = ike_sa->get_unique_id(ike_sa);
- id = ike_sa->get_other_id(ike_sa);
- eap_id = ike_sa->get_other_eap_id(ike_sa);
- host = ike_sa->get_other_host(ike_sa);
-
- /* in the presence of an EAP Identity, treat it as a username */
- if (!id->equals(id, eap_id))
- {
- is_user = TRUE;
- id = eap_id;
- }
-
- /* build publish request */
- request = create_publish_request(this);
-
- /* delete any existing enforcement reports */
- if (up)
- {
- node = create_delete_filter(this, "enforcement-report");
- xmlAddChild(request, node);
- xmlAddChild(node, create_ip_address(this, host));
- xmlAddChild(node, create_device(this));
- }
-
- /**
- * update or delete authenticated-as metadata
- */
- if (up)
- {
- node = xmlNewNode(NULL, "update");
- }
- else
- {
- node = create_delete_filter(this, "authenticated-as");
- }
- xmlAddChild(request, node);
-
- /* add access-request, identity and [if up] metadata */
- xmlAddChild(node, create_access_request(this, ike_sa_id));
- xmlAddChild(node, create_identity(this, id, is_user));
- if (up)
- {
- xmlAddChild(node, create_metadata(this, "authenticated-as"));
- }
-
- /**
- * update or delete access-request-ip metadata
- */
- if (up)
- {
- node = xmlNewNode(NULL, "update");
- }
- else
- {
- node = create_delete_filter(this, "access-request-ip");
- }
- xmlAddChild(request, node);
-
- /* add access-request, ip-address and [if up] metadata */
- xmlAddChild(node, create_access_request(this, ike_sa_id));
- xmlAddChild(node, create_ip_address(this, host));
- if (up)
- {
- xmlAddChild(node, create_metadata(this, "access-request-ip"));
- }
-
- /**
- * update or delete authenticated-by metadata
- */
- if (up)
- {
- node = xmlNewNode(NULL, "update");
- }
- else
- {
- node = create_delete_filter(this, "authenticated-by");
- }
- xmlAddChild(request, node);
-
- /* add access-request, device and [if up] metadata */
- xmlAddChild(node, create_access_request(this, ike_sa_id));
- xmlAddChild(node, create_device(this));
- if (up)
- {
- xmlAddChild(node, create_metadata(this, "authenticated-by"));
- }
-
- /**
- * update or delete capability metadata
- */
- e1 = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE);
- while (e1->enumerate(e1, &auth) && (first || up))
- {
- e2 = auth->create_enumerator(auth);
- while (e2->enumerate(e2, &type, &group))
- {
- /* look for group memberships */
- if (type == AUTH_RULE_GROUP)
- {
- if (first)
- {
- first = FALSE;
-
- if (up)
- {
- node = xmlNewNode(NULL, "update");
- }
- else
- {
- node = create_delete_filter(this, "capability");
- }
- xmlAddChild(request, node);
-
- /* add access-request */
- xmlAddChild(node, create_access_request(this, ike_sa_id));
- if (!up)
- {
- break;
- }
- node2 = xmlNewNode(NULL, "metadata");
- xmlAddChild(node, node2);
- }
- xmlAddChild(node2, create_capability(this, group));
- }
- }
- e2->destroy(e2);
- }
- e1->destroy(e1);
-
- soap_msg = tnc_ifmap2_soap_msg_create(this->uri, this->user_pass, this->tls);
- success = soap_msg->post(soap_msg, request, "publishReceived", NULL);
- soap_msg->destroy(soap_msg);
-
- return success;
-}
-
-METHOD(tnc_ifmap2_soap_t, publish_device_ip, bool,
- private_tnc_ifmap2_soap_t *this, host_t *host)
-{
- tnc_ifmap2_soap_msg_t *soap_msg;
- xmlNodePtr request, update;
- bool success;
-
- /* build publish update request */
- request = create_publish_request(this);
- update = xmlNewNode(NULL, "update");
- xmlAddChild(request, update);
-
- /* add device, ip-address and metadata */
- xmlAddChild(update, create_device(this));
- xmlAddChild(update, create_ip_address(this, host));
- xmlAddChild(update, create_metadata(this, "device-ip"));
-
- soap_msg = tnc_ifmap2_soap_msg_create(this->uri, this->user_pass, this->tls);
- success = soap_msg->post(soap_msg, request, "publishReceived", NULL);
- soap_msg->destroy(soap_msg);
-
- return success;
-}
-
-METHOD(tnc_ifmap2_soap_t, publish_enforcement_report, bool,
- private_tnc_ifmap2_soap_t *this, host_t *host, char *action, char *reason)
-{
- tnc_ifmap2_soap_msg_t *soap_msg;
- xmlNodePtr request, update;
- bool success;
-
- /* build publish update request */
- request = create_publish_request(this);
- update = xmlNewNode(NULL, "update");
- xmlAddChild(request, update);
-
- /* add ip-address and metadata */
- xmlAddChild(update, create_ip_address(this, host));
- xmlAddChild(update, create_device(this));
- xmlAddChild(update, create_enforcement_report(this, action, reason));
-
- soap_msg = tnc_ifmap2_soap_msg_create(this->uri, this->user_pass, this->tls);
- success = soap_msg->post(soap_msg, request, "publishReceived", NULL);
- soap_msg->destroy(soap_msg);
-
- return success;
-}
-
-METHOD(tnc_ifmap2_soap_t, endSession, bool,
- private_tnc_ifmap2_soap_t *this)
-{
- tnc_ifmap2_soap_msg_t *soap_msg;
- xmlNodePtr request;
- bool success;
-
- /* build endSession request */
- request = xmlNewNode(NULL, "endSession");
- this->ns = xmlNewNs(request, IFMAP_NS, "ifmap");
- xmlSetNs(request, this->ns);
- xmlNewProp(request, "session-id", this->session_id);
-
- soap_msg = tnc_ifmap2_soap_msg_create(this->uri, this->user_pass, this->tls);
- success = soap_msg->post(soap_msg, request, "endSessionResult", NULL);
- soap_msg->destroy(soap_msg);
-
- return success;
-}
-
-METHOD(tnc_ifmap2_soap_t, destroy, void,
- private_tnc_ifmap2_soap_t *this)
-{
- if (this->session_id)
- {
- endSession(this);
- xmlFree(this->session_id);
- xmlFree(this->ifmap_publisher_id);
- free(this->device_name);
- }
- DESTROY_IF(this->tls);
- DESTROY_IF(this->host);
-
- if (this->fd != IFMAP_NO_FD)
- {
- close(this->fd);
- }
- lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
- this->creds->destroy(this->creds);
- free(this->user_pass.ptr);
- free(this);
-}
-
-static bool soap_init(private_tnc_ifmap2_soap_t *this)
-{
- char *server_uri, *server_str, *port_str, *uri_str;
- char *server_cert, *client_cert, *client_key, *user_pass;
- int port;
- certificate_t *cert;
- private_key_t *key;
- identification_t *server_id, *client_id = NULL;
-
- /* getting configuration parameters from strongswan.conf */
- server_uri = lib->settings->get_str(lib->settings,
- "%s.plugins.tnc-ifmap2.server_uri", IFMAP_URI, charon->name);
- server_cert = lib->settings->get_str(lib->settings,
- "%s.plugins.tnc-ifmap2.server_cert", NULL, charon->name);
- client_cert = lib->settings->get_str(lib->settings,
- "%s.plugins.tnc-ifmap2.client_cert", NULL, charon->name);
- client_key = lib->settings->get_str(lib->settings,
- "%s.plugins.tnc-ifmap2.client_key", NULL, charon->name);
- user_pass = lib->settings->get_str(lib->settings,
- "%s.plugins.tnc-ifmap2.username_password", NULL, charon->name);
-
- /* load [self-signed] MAP server certificate */
- if (!server_cert)
- {
- DBG1(DBG_TNC, "MAP server certificate not defined");
- return FALSE;
- }
- cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
- BUILD_FROM_FILE, server_cert, BUILD_END);
- if (!cert)
- {
- DBG1(DBG_TNC, "loading MAP server certificate from '%s' failed",
- server_cert);
- return FALSE;
- }
- DBG1(DBG_TNC, "loaded MAP server certificate from '%s'", server_cert);
- server_id = cert->get_subject(cert);
- this->creds->add_cert(this->creds, TRUE, cert);
-
- /* check availability of client credentials */
- if (!((client_cert && client_key) || user_pass))
- {
- DBG1(DBG_TNC, "neither MAP client certificate and private key "
- "nor username:password defined");
- return FALSE;
- }
-
- if (client_cert)
- {
- /* load MAP client certificate */
- cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
- BUILD_FROM_FILE, client_cert, BUILD_END);
- if (!cert)
- {
- DBG1(DBG_TNC, "loading MAP client certificate from '%s' failed",
- client_cert);
- return FALSE;
- }
- DBG1(DBG_TNC, "loaded MAP client certificate from '%s'", client_cert);
- this->creds->add_cert(this->creds, TRUE, cert);
-
- /* load MAP client private key */
- key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
- BUILD_FROM_FILE, client_key, BUILD_END);
- if (!key)
- {
- DBG1(DBG_TNC, "loading MAP client private key from '%s' failed",
- client_key);
- return FALSE;
- }
- DBG1(DBG_TNC, "loaded MAP client RSA private key from '%s'", client_key);
- this->creds->add_key(this->creds, key);
-
- /* set client ID to certificate distinguished name */
- client_id = cert->get_subject(cert);
- }
- else
- {
- /* set base64-encoded username:password for HTTP Basic Authentication */
- this->user_pass = chunk_to_base64(chunk_from_str(user_pass), NULL);
- }
-
- /* remove HTTPS prefix if any */
- if (strlen(server_uri) >= 8 && strncaseeq(server_uri, "https://", 8))
- {
- server_uri += 8;
- }
- this->uri = server_uri;
-
- /* duplicate server string since we are going to manipulate it */
- server_str = strdup(server_uri);
-
- /* extract server name and port from server URI */
- port_str = strchr(server_str, ':');
- if (port_str)
- {
- *port_str++ = '\0';
- if (sscanf(port_str, "%d", &port) != 1)
- {
- DBG1(DBG_TNC, "parsing server port %s failed", port_str);
- free(server_str);
- return FALSE;
- }
- }
- else
- {
- /* use default https port */
- port = 443;
- uri_str = strchr(server_str, '/');
- if (uri_str)
- {
- *uri_str = '\0';
- }
- }
-
- /* open TCP socket and connect to MAP server */
- this->host = host_create_from_dns(server_str, 0, port);
- if (!this->host)
- {
- DBG1(DBG_TNC, "resolving hostname %s failed", server_str);
- free(server_str);
- return FALSE;
- }
- free(server_str);
-
- this->fd = socket(this->host->get_family(this->host), SOCK_STREAM, 0);
- if (this->fd == IFMAP_NO_FD)
- {
- DBG1(DBG_TNC, "opening socket failed: %s", strerror(errno));
- return FALSE;
- }
-
- if (connect(this->fd, this->host->get_sockaddr(this->host),
- *this->host->get_sockaddr_len(this->host)) == -1)
- {
- DBG1(DBG_TNC, "connecting to %#H failed: %s",
- this->host, strerror(errno));
- return FALSE;
- }
-
- /* open TLS socket */
- this->tls = tls_socket_create(FALSE, server_id, client_id, this->fd, NULL);
- if (!this->tls)
- {
- DBG1(DBG_TNC, "creating TLS socket failed");
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * See header
- */
-tnc_ifmap2_soap_t *tnc_ifmap2_soap_create()
-{
- private_tnc_ifmap2_soap_t *this;
-
- INIT(this,
- .public = {
- .newSession = _newSession,
- .purgePublisher = _purgePublisher,
- .publish_ike_sa = _publish_ike_sa,
- .publish_device_ip = _publish_device_ip,
- .publish_enforcement_report = _publish_enforcement_report,
- .endSession = _endSession,
- .destroy = _destroy,
- },
- .fd = IFMAP_NO_FD,
- .creds = mem_cred_create(),
- );
-
- lib->credmgr->add_set(lib->credmgr, &this->creds->set);
-
- if (!soap_init(this))
- {
- destroy(this);
- return NULL;
- }
-
- return &this->public;
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2011-2013 Andreas Steffen
- * HSR Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup tnc_ifmap2_soap tnc_ifmap2_soap
- * @{ @ingroup tnc_ifmap2
- */
-
-#ifndef TNC_IFMAP2_SOAP_H_
-#define TNC_IFMAP2_SOAP_H_
-
-#include <library.h>
-#include <networking/host.h>
-#include <sa/ike_sa.h>
-
-typedef struct tnc_ifmap2_soap_t tnc_ifmap2_soap_t;
-
-/**
- * Implements the TNC IF-MAP 2.0 SOAP Binding
- */
-struct tnc_ifmap2_soap_t {
-
- /**
- * Creates a new IF-MAP session
- *
- * @return TRUE if command was successful
- */
- bool (*newSession)(tnc_ifmap2_soap_t *this);
-
- /**
- * Purges all metadata published by this publisher
- *
- * @return TRUE if command was successful
- */
- bool (*purgePublisher)(tnc_ifmap2_soap_t *this);
-
- /**
- * Publish metadata about established/deleted IKE_SAs
- *
- * @param ike_sa IKE_SA for which metadate is published
- * @param up TRUE if IKE_SEA is up, FALSE if down
- * @return TRUE if command was successful
- */
- bool (*publish_ike_sa)(tnc_ifmap2_soap_t *this, ike_sa_t *ike_sa, bool up);
-
- /**
- * Publish PEP device-ip metadata
- *
- * @param host IP address of local endpoint
- * @return TRUE if command was successful
- */
- bool (*publish_device_ip)(tnc_ifmap2_soap_t *this, host_t *host);
-
- /**
- * Publish enforcement-report metadata
- *
- * @param host Host to be enforced
- * @param action Enforcement action ("block" or "quarantine")
- * @param reason Enforcement reason
- * @return TRUE if command was successful
- */
- bool (*publish_enforcement_report)(tnc_ifmap2_soap_t *this, host_t *host,
- char *action, char *reason);
-
- /**
- * Ends an IF-MAP session
- *
- * @return TRUE if command was successful
- */
- bool (*endSession)(tnc_ifmap2_soap_t *this);
-
- /**
- * Destroy a tnc_ifmap2_soap_t.
- */
- void (*destroy)(tnc_ifmap2_soap_t *this);
-};
-
-/**
- * Create a tnc_ifmap2_soap instance.
- */
-tnc_ifmap2_soap_t *tnc_ifmap2_soap_create();
-
-#endif /** TNC_IFMAP2_SOAP_H_ @}*/
+++ /dev/null
-/*
- * Copyright (C) 2013 Andreas Steffen
- * HSR Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#define _GNU_SOURCE /* for asprintf() */
-
-#include "tnc_ifmap2_soap_msg.h"
-
-#include <utils/debug.h>
-#include <utils/lexparser.h>
-
-#include <stdio.h>
-
-#define SOAP_NS "http://www.w3.org/2003/05/soap-envelope"
-
-typedef struct private_tnc_ifmap2_soap_msg_t private_tnc_ifmap2_soap_msg_t;
-
-/**
- * Private data of an tnc_ifmap2_soap_msg_t object.
- */
-struct private_tnc_ifmap2_soap_msg_t {
-
- /**
- * Public tnc_ifmap2_soap_msg_t interface.
- */
- tnc_ifmap2_soap_msg_t public;
-
- /**
- * HTTPS Server URI with https:// prefix removed
- */
- char *uri;
-
- /**
- * Optional base64-encoded username:password for HTTP Basic Authentication
- */
- chunk_t user_pass;
-
- /**
- * TLS Socket
- */
- tls_socket_t *tls;
-
- /**
- * XML Document
- */
- xmlDocPtr doc;
-
-};
-
-/**
- * Send HTTP POST request and receive HTTP response
- */
-static bool http_post(private_tnc_ifmap2_soap_msg_t *this, chunk_t out,
- chunk_t *in)
-{
- char *host, *path, *request, buf[2048];
- chunk_t line, http, parameter;
- int len, code, content_len = 0;
-
- /* Duplicate host[/path] string since we are going to manipulate it */
- len = strlen(this->uri) + 2;
- host = malloc(len);
- memset(host, '\0', len);
- strcpy(host, this->uri);
-
- /* Extract appended path or set to root */
- path = strchr(host, '/');
- if (!path)
- {
- path = host + len - 2;
- *path = '/';
- }
-
- /* Use Basic Authentication? */
- if (this->user_pass.len)
- {
- snprintf(buf, sizeof(buf), "Authorization: Basic %.*s\r\n",
- this->user_pass.len, this->user_pass.ptr);
- }
- else
- {
- *buf = '\0';
- }
-
- /* Write HTTP POST request */
- len = asprintf(&request,
- "POST %s HTTP/1.1\r\n"
- "Host: %.*s\r\n"
- "%s"
- "Content-Type: application/soap+xml;charset=utf-8\r\n"
- "Content-Length: %d\r\n"
- "\r\n"
- "%.*s", path, (path-host), host, buf, out.len, out.len, out.ptr);
- free(host);
-
- if (len == -1)
- {
- return FALSE;
- }
- http = chunk_create(request, len);
- DBG3(DBG_TLS, "%B", &http);
-
- this->tls->write(this->tls, request, len);
- free(request);
-
- /* Read HTTP response */
- len = this->tls->read(this->tls, buf, sizeof(buf), TRUE);
- if (len == -1)
- {
- return FALSE;
- }
- *in = chunk_create(buf, len);
-
- /* Process HTTP protocol version */
- if (!fetchline(in, &line) || !extract_token(&http, ' ', &line) ||
- !match("HTTP/1.1", &http) || sscanf(line.ptr, "%d", &code) != 1)
- {
- DBG1(DBG_TNC, "malformed http response header");
- return FALSE;
- }
- if (code != 200)
- {
- DBG1(DBG_TNC, "http response returns error code %d", code);
- return FALSE;
- }
-
- /* Process HTTP header line by line until the HTTP body is reached */
- while (fetchline(in, &line))
- {
- if (line.len == 0)
- {
- break;
- }
-
- if (extract_token(¶meter, ':', &line) &&
- match("Content-Length", ¶meter) &&
- sscanf(line.ptr, "%d", &len) == 1)
- {
- content_len = len;
- }
- }
-
- /* Found Content-Length parameter and check size of HTTP body */
- if (content_len)
- {
- if (content_len > in->len)
- {
- DBG1(DBG_TNC, "http body is smaller than content length");
- return FALSE;
- }
- in->len = content_len;
- }
- *in = chunk_clone(*in);
-
- return TRUE;
-}
-
-/**
- * Find a child node with a given name
- */
-static xmlNodePtr find_child(xmlNodePtr parent, const xmlChar* name)
-{
- xmlNodePtr child;
-
- child = parent->xmlChildrenNode;
- while (child)
- {
- if (xmlStrcmp(child->name, name) == 0)
- {
- return child;
- }
- child = child->next;
- }
-
- DBG1(DBG_TNC, "child node \"%s\" not found", name);
- return NULL;
-}
-
-METHOD(tnc_ifmap2_soap_msg_t, post, bool,
- private_tnc_ifmap2_soap_msg_t *this, xmlNodePtr request, char *result_name,
- xmlNodePtr *result)
-{
- xmlDocPtr doc;
- xmlNodePtr env, body, cur, response;
- xmlNsPtr ns;
- xmlChar *xml, *errorCode, *errorString;
- int len;
- chunk_t in, out;
-
- DBG2(DBG_TNC, "sending ifmap %s", request->name);
-
- /* Generate XML Document containing SOAP Envelope */
- doc = xmlNewDoc("1.0");
- env =xmlNewNode(NULL, "Envelope");
- ns = xmlNewNs(env, SOAP_NS, "env");
- xmlSetNs(env, ns);
- xmlDocSetRootElement(doc, env);
-
- /* Add SOAP Body containing IF-MAP request */
- body = xmlNewNode(ns, "Body");
- xmlAddChild(body, request);
- xmlAddChild(env, body);
-
- /* Convert XML Document into a character string */
- xmlDocDumpFormatMemory(doc, &xml, &len, 1);
- xmlFreeDoc(doc);
- DBG3(DBG_TNC, "%.*s", len, xml);
- out = chunk_create(xml, len);
-
- /* Send SOAP-XML request via HTTP POST */
- if (!http_post(this, out, &in))
- {
- xmlFree(xml);
- return FALSE;
- }
- xmlFree(xml);
-
- DBG3(DBG_TNC, "%B", &in);
- this->doc = xmlParseMemory(in.ptr, in.len);
- free(in.ptr);
-
- if (!this->doc)
- {
- DBG1(DBG_TNC, "failed to parse XML message");
- return FALSE;
- }
-
- /* check out XML document */
- cur = xmlDocGetRootElement(this->doc);
- if (!cur)
- {
- DBG1(DBG_TNC, "empty XML message");
- return FALSE;
- }
-
- /* get XML Document type is a SOAP Envelope */
- if (xmlStrcmp(cur->name, "Envelope"))
- {
- DBG1(DBG_TNC, "XML message does not contain a SOAP Envelope");
- return FALSE;
- }
-
- /* get SOAP Body */
- cur = find_child(cur, "Body");
- if (!cur)
- {
- return FALSE;
- }
-
- /* get IF-MAP response */
- response = find_child(cur, "response");
- if (!response)
- {
- return FALSE;
- }
-
- /* get IF-MAP result */
- cur = find_child(response, result_name);
- if (!cur)
- {
- cur = find_child(response, "errorResult");
- if (cur)
- {
- DBG1(DBG_TNC, "received errorResult");
-
- errorCode = xmlGetProp(cur, "errorCode");
- if (errorCode)
- {
- DBG1(DBG_TNC, " %s", errorCode);
- xmlFree(errorCode);
- }
-
- cur = find_child(cur, "errorString");
- if (cur)
- {
- errorString = xmlNodeGetContent(cur);
- if (errorString)
- {
- DBG1(DBG_TNC, " %s", errorString);
- xmlFree(errorString);
- }
- }
- }
- return FALSE;
- }
-
- if (result)
- {
- *result = cur;
- }
- return TRUE;
-}
-
-METHOD(tnc_ifmap2_soap_msg_t, destroy, void,
- private_tnc_ifmap2_soap_msg_t *this)
-{
- if (this->doc)
- {
- xmlFreeDoc(this->doc);
- }
- free(this);
-}
-
-/**
- * See header
- */
-tnc_ifmap2_soap_msg_t *tnc_ifmap2_soap_msg_create(char *uri, chunk_t user_pass,
- tls_socket_t *tls)
-{
- private_tnc_ifmap2_soap_msg_t *this;
-
- INIT(this,
- .public = {
- .post = _post,
- .destroy = _destroy,
- },
- .uri = uri,
- .user_pass = user_pass,
- .tls = tls,
- );
-
- return &this->public;
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2013 Andreas Steffen
- * HSR Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup tnc_ifmap2_soap_msg tnc_ifmap2_soap_msg
- * @{ @ingroup tnc_ifmap2
- */
-
-#ifndef TNC_IFMAP2_SOAP_MSG_H_
-#define TNC_IFMAP2_SOAP_MSG_H_
-
-#include <library.h>
-#include <tls_socket.h>
-
-#include <libxml/parser.h>
-
-typedef struct tnc_ifmap2_soap_msg_t tnc_ifmap2_soap_msg_t;
-
-/**
- * Interface for sending and receiving SOAP-XML messages
- */
-struct tnc_ifmap2_soap_msg_t {
-
- /**
- * Post an IF-MAP request in a SOAP-XML message and return a result
- *
- * @param request XML-encoded IF-MAP request
- * @param result_name name of the IF-MAP result
- * @param result XML-encoded IF-MAP result
- */
- bool (*post)(tnc_ifmap2_soap_msg_t *this, xmlNodePtr request,
- char *result_name, xmlNodePtr* result);
-
- /**
- * Destroy a tnc_ifmap2_soap_msg_t object.
- */
- void (*destroy)(tnc_ifmap2_soap_msg_t *this);
-};
-
-/**
- * Create a tnc_ifmap2_soap_msg instance.
- *
- * @param uri HTTPS URI with https:// prefix removed
- * @param user_pass Optional username:password for HTTP Basic Authentication
- * @param tls TLS socket protecting the SOAP message
- */
-tnc_ifmap2_soap_msg_t *tnc_ifmap2_soap_msg_create(char *uri, chunk_t user_pass,
- tls_socket_t *tls);
-
-#endif /** TNC_IFMAP2_SOAP_MSG_H_ @}*/