From 45e2be239910e67422564ef123c7b21da6916f0d Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Sun, 31 Mar 2013 16:37:30 +0200 Subject: renamed tnc_ifmap2 plugin to tnc_ifmap --- src/libcharon/Makefile.am | 6 +- src/libcharon/plugins/tnc_ifmap/Makefile.am | 27 + .../plugins/tnc_ifmap/tnc_ifmap_listener.c | 173 +++++ .../plugins/tnc_ifmap/tnc_ifmap_listener.h | 51 ++ src/libcharon/plugins/tnc_ifmap/tnc_ifmap_plugin.c | 129 ++++ src/libcharon/plugins/tnc_ifmap/tnc_ifmap_plugin.h | 42 ++ src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c | 805 +++++++++++++++++++++ src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.h | 95 +++ .../plugins/tnc_ifmap/tnc_ifmap_soap_msg.c | 335 +++++++++ .../plugins/tnc_ifmap/tnc_ifmap_soap_msg.h | 62 ++ src/libcharon/plugins/tnc_ifmap2/Makefile.am | 27 - .../plugins/tnc_ifmap2/tnc_ifmap2_listener.c | 173 ----- .../plugins/tnc_ifmap2/tnc_ifmap2_listener.h | 51 -- .../plugins/tnc_ifmap2/tnc_ifmap2_plugin.c | 129 ---- .../plugins/tnc_ifmap2/tnc_ifmap2_plugin.h | 42 -- src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap.c | 805 --------------------- src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap.h | 95 --- .../plugins/tnc_ifmap2/tnc_ifmap2_soap_msg.c | 335 --------- .../plugins/tnc_ifmap2/tnc_ifmap2_soap_msg.h | 62 -- 19 files changed, 1722 insertions(+), 1722 deletions(-) create mode 100644 src/libcharon/plugins/tnc_ifmap/Makefile.am create mode 100644 src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c create mode 100644 src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.h create mode 100644 src/libcharon/plugins/tnc_ifmap/tnc_ifmap_plugin.c create mode 100644 src/libcharon/plugins/tnc_ifmap/tnc_ifmap_plugin.h create mode 100644 src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c create mode 100644 src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.h create mode 100644 src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap_msg.c create mode 100644 src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap_msg.h delete mode 100644 src/libcharon/plugins/tnc_ifmap2/Makefile.am delete mode 100644 src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_listener.c delete mode 100644 src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_listener.h delete mode 100644 src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_plugin.c delete mode 100644 src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_plugin.h delete mode 100644 src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap.c delete mode 100644 src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap.h delete mode 100644 src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap_msg.c delete mode 100644 src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap_msg.h (limited to 'src') diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index b817bdb4e..f0736c5ca 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -373,10 +373,10 @@ if MONOLITHIC 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 diff --git a/src/libcharon/plugins/tnc_ifmap/Makefile.am b/src/libcharon/plugins/tnc_ifmap/Makefile.am new file mode 100644 index 000000000..d055bbcbd --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/Makefile.am @@ -0,0 +1,27 @@ + +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 + diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c new file mode 100644 index 000000000..0280b30d2 --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c @@ -0,0 +1,173 @@ +/* + * 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 . + * + * 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 +#include +#include + +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; +} + diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.h b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.h new file mode 100644 index 000000000..4ecccf4df --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.h @@ -0,0 +1,51 @@ +/* + * 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 . + * + * 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 + +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_ @}*/ diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_plugin.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_plugin.c new file mode 100644 index 000000000..c9e84241c --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_plugin.c @@ -0,0 +1,129 @@ +/* + * 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 . + * + * 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 + +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; +} + diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_plugin.h b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_plugin.h new file mode 100644 index 000000000..d3bba7f9c --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_plugin.h @@ -0,0 +1,42 @@ +/* + * 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 . + * + * 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 + +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_ @}*/ diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c new file mode 100644 index 000000000..bce4156c3 --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c @@ -0,0 +1,805 @@ +/* + * 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 . + * + * 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 +#include +#include + +#include + +#include +#include +#include +#include + +#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; +} + diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.h b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.h new file mode 100644 index 000000000..5ab31ef19 --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.h @@ -0,0 +1,95 @@ +/* + * 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 . + * + * 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 +#include +#include + +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_ @}*/ diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap_msg.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap_msg.c new file mode 100644 index 000000000..8afd6ff09 --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap_msg.c @@ -0,0 +1,335 @@ +/* + * 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 . + * + * 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 +#include + +#include + +#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; +} + diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap_msg.h b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap_msg.h new file mode 100644 index 000000000..4f809ba1a --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap_msg.h @@ -0,0 +1,62 @@ +/* + * 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 . + * + * 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 +#include + +#include + +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_ @}*/ diff --git a/src/libcharon/plugins/tnc_ifmap2/Makefile.am b/src/libcharon/plugins/tnc_ifmap2/Makefile.am deleted file mode 100644 index 217d8972f..000000000 --- a/src/libcharon/plugins/tnc_ifmap2/Makefile.am +++ /dev/null @@ -1,27 +0,0 @@ - -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 - diff --git a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_listener.c b/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_listener.c deleted file mode 100644 index 4922a3ecc..000000000 --- a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_listener.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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 . - * - * 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 -#include -#include - -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; -} - diff --git a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_listener.h b/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_listener.h deleted file mode 100644 index dfb8adcd5..000000000 --- a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_listener.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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 . - * - * 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 - -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_ @}*/ diff --git a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_plugin.c b/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_plugin.c deleted file mode 100644 index 8969c116e..000000000 --- a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_plugin.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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 . - * - * 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 - -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; -} - diff --git a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_plugin.h b/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_plugin.h deleted file mode 100644 index 387daa635..000000000 --- a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_plugin.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 . - * - * 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 - -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_ @}*/ diff --git a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap.c b/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap.c deleted file mode 100644 index 887a781bf..000000000 --- a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap.c +++ /dev/null @@ -1,805 +0,0 @@ -/* - * 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 . - * - * 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 -#include -#include - -#include - -#include -#include -#include -#include - -#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; -} - diff --git a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap.h b/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap.h deleted file mode 100644 index 8e9788072..000000000 --- a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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 . - * - * 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 -#include -#include - -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_ @}*/ diff --git a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap_msg.c b/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap_msg.c deleted file mode 100644 index 5cf966a29..000000000 --- a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap_msg.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * 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 . - * - * 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 -#include - -#include - -#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; -} - diff --git a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap_msg.h b/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap_msg.h deleted file mode 100644 index 2a50bfc8b..000000000 --- a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap_msg.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 . - * - * 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 -#include - -#include - -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_ @}*/ -- cgit v1.2.3