]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
created tnc_ifmap2_soap_msg class
authorAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 29 Mar 2013 22:09:11 +0000 (23:09 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 29 Mar 2013 22:09:11 +0000 (23:09 +0100)
src/libcharon/plugins/tnc_ifmap2/Makefile.am
src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap.c
src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap_msg.c [new file with mode: 0644]
src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap_msg.h [new file with mode: 0644]

index 11524795ca3b99579130d0de5cf1b36bfe13bb50..217d8972fbfc76c4ff288a9750c9a33393db1907 100644 (file)
@@ -20,7 +20,8 @@ libstrongswan_tnc_ifmap2_la_LIBADD = \
 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.h tnc_ifmap2_soap.c \
+       tnc_ifmap2_soap_msg.h tnc_ifmap2_soap_msg.c
 
 libstrongswan_tnc_ifmap2_la_LDFLAGS = -module -avoid-version
 
index 65f92653b3e9c23a015696ca42fe1ac9606592e5..4c9334dbd02a43d28ce087f7ff8304b1ef591b27 100644 (file)
  * for more details.
  */
 
-#define _GNU_SOURCE /* for asprintf() */
-
 #include "tnc_ifmap2_soap.h"
+#include "tnc_ifmap2_soap_msg.h"
 
 #include <utils/debug.h>
-#include <utils/lexparser.h>
 #include <credentials/sets/mem_cred.h>
 #include <daemon.h>
 
 #include <tls_socket.h>
 
-#include <libxml/parser.h>
-
-#define _GNU_SOURCE
-
-#include <stdio.h>
 #include <errno.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 
-#define SOAP_NS                        "http://www.w3.org/2003/05/soap-envelope"
 #define IFMAP_NS               "http://www.trustedcomputinggroup.org/2010/IFMAP/2"
 #define IFMAP_META_NS  "http://www.trustedcomputinggroup.org/2010/IFMAP-METADATA/2"
 #define IFMAP_LOGFILE  "strongswan_ifmap.log"
@@ -90,206 +82,11 @@ struct private_tnc_ifmap2_soap_t {
 
 };
 
-/**
- * Send HTTP POST request and receive HTTP response
- */
-static bool http_send_receive(private_tnc_ifmap2_soap_t *this, chunk_t out,
-                                                                                                                          chunk_t *in)
-{
-       char header[] =
-                "POST /ifmap HTTP/1.1\r\n"
-                "Content-Type: application/soap+xml;charset=utf-8\r\n"
-                "Content-Length: ";
-       char *request, response[2048];
-       chunk_t line, http, parameter;
-       int len, code, content_len = 0;
-
-       /* Write HTTP POST request */
-       len = asprintf(&request, "%s%d\r\n\r\n%.*s", header, out.len,
-                                  out.len, out.ptr);
-       if (len == -1)
-       {
-               return FALSE;
-       }
-       this->tls->write(this->tls, request, len);
-       free(request);
-
-       /* Read HTTP response */
-       len = this->tls->read(this->tls, response, sizeof(response), TRUE);
-       if (len == -1)
-       {
-               return FALSE;
-       }
-       *in = chunk_create(response, 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(&parameter, ':', &line) &&
-                       match("Content-Length", &parameter) &&
-                       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;
-}
-
-/**
- * Send request and receive result via SOAP
- */
-static bool soap_send_receive(private_tnc_ifmap2_soap_t *this,
-                                                         char *request_name, xmlNodePtr request,
-                                                         char *result_name, xmlNodePtr *result,
-                                                         xmlDocPtr *result_doc)
-{
-       xmlDocPtr doc;
-       xmlNodePtr env, body, cur;
-       xmlNsPtr ns;
-       xmlChar *xml;
-       int len;
-       chunk_t in, out;
-
-       *result_doc = NULL;
-       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 */
-       if (!http_send_receive(this, out, &in))
-       {
-               xmlFree(xml);
-               return FALSE;
-       }
-       xmlFree(xml);
-
-       DBG3(DBG_TNC, "%B", &in);
-       doc = xmlParseMemory(in.ptr, in.len);
-       free(in.ptr);
-       
-       if (!doc)
-       {
-               DBG1(DBG_TNC, "failed to parse XML message");
-               return FALSE;
-       }
-       *result_doc = doc;
-
-       /* check out XML document */
-       cur = xmlDocGetRootElement(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 */
-       cur = find_child(cur, "response");
-       if (!cur)
-       {
-               return FALSE;
-       }
-
-       /* get IF-MAP result */
-       cur = find_child(cur, result_name);
-       if (!cur)
-       {
-               return FALSE;
-       }
-
-       if (result)
-       {
-               *result = cur;
-       }
-       return TRUE;
-}
-
 METHOD(tnc_ifmap2_soap_t, newSession, bool,
        private_tnc_ifmap2_soap_t *this)
 {
+       tnc_ifmap2_soap_msg_t *soap_msg;
        xmlNodePtr request, result;
-       xmlDocPtr result_doc;
        xmlNsPtr ns;
 
        /*build newSession request */
@@ -297,20 +94,18 @@ METHOD(tnc_ifmap2_soap_t, newSession, bool,
        ns = xmlNewNs(request, IFMAP_NS, "ifmap");
        xmlSetNs(request, ns);
 
-       if (!soap_send_receive(this, "newSession", request, "newSessionResult",
-                                                  &result, &result_doc))
+       soap_msg = tnc_ifmap2_soap_msg_create(this->tls);
+       if (!soap_msg->post(soap_msg, "newSession", request,
+                                                                 "newSessionResult", &result))
        {
-               if (result_doc)
-               {
-                       xmlFreeDoc(result_doc);
-               }
+               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");
-       xmlFreeDoc(result_doc);
+       soap_msg->destroy(soap_msg);
 
        DBG1(DBG_TNC, "session-id: %s, ifmap-publisher-id: %s",
                                   this->session_id, this->ifmap_publisher_id);
@@ -327,8 +122,8 @@ METHOD(tnc_ifmap2_soap_t, newSession, bool,
 METHOD(tnc_ifmap2_soap_t, purgePublisher, bool,
        private_tnc_ifmap2_soap_t *this)
 {
+       tnc_ifmap2_soap_msg_t *soap_msg;
        xmlNodePtr request;
-       xmlDocPtr result_doc;
        xmlNsPtr ns;
        bool success;
 
@@ -339,12 +134,11 @@ METHOD(tnc_ifmap2_soap_t, purgePublisher, bool,
        xmlNewProp(request, "session-id", this->session_id);
        xmlNewProp(request, "ifmap-publisher-id", this->ifmap_publisher_id);
 
-       success = soap_send_receive(this, "purgePublisher", request,
-                                                               "purgePublisherReceived", NULL, &result_doc);
-       if (result_doc)
-       {
-               xmlFreeDoc(result_doc);
-       }
+       soap_msg = tnc_ifmap2_soap_msg_create(this->tls);
+       success = soap_msg->post(soap_msg, "purgePublisher", request,
+                                                                          "purgePublisherReceived", NULL);
+       soap_msg->destroy(soap_msg);
+
        return success;
 }
 
diff --git a/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap_msg.c b/src/libcharon/plugins/tnc_ifmap2/tnc_ifmap2_soap_msg.c
new file mode 100644 (file)
index 0000000..7bea62d
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * 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;
+
+       /**
+        * TLS Socket
+        */
+       tls_socket_t *tls;
+
+       /**
+        * XML Document
+        */
+       xmlDocPtr doc;
+
+};
+
+/**
+ * Send HTTP POST request and receive HTTP response
+ */
+static bool http_send_receive(private_tnc_ifmap2_soap_msg_t *this,
+                                                         chunk_t out, chunk_t *in)
+{
+       char header[] =
+                "POST /ifmap HTTP/1.1\r\n"
+                "Content-Type: application/soap+xml;charset=utf-8\r\n"
+                "Content-Length: ";
+       char *request, response[2048];
+       chunk_t line, http, parameter;
+       int len, code, content_len = 0;
+
+       /* Write HTTP POST request */
+       len = asprintf(&request, "%s%d\r\n\r\n%.*s", header, out.len,
+                                  out.len, out.ptr);
+       if (len == -1)
+       {
+               return FALSE;
+       }
+       this->tls->write(this->tls, request, len);
+       free(request);
+
+       /* Read HTTP response */
+       len = this->tls->read(this->tls, response, sizeof(response), TRUE);
+       if (len == -1)
+       {
+               return FALSE;
+       }
+       *in = chunk_create(response, 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(&parameter, ':', &line) &&
+                       match("Content-Length", &parameter) &&
+                       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, char *request_name, xmlNodePtr request,
+       char *result_name, xmlNodePtr *result)
+{
+       xmlDocPtr doc;
+       xmlNodePtr env, body, cur;
+       xmlNsPtr ns;
+       xmlChar *xml;
+       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 */
+       if (!http_send_receive(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 */
+       cur = find_child(cur, "response");
+       if (!cur)
+       {
+               return FALSE;
+       }
+
+       /* get IF-MAP result */
+       cur = find_child(cur, result_name);
+       if (!cur)
+       {
+               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(tls_socket_t *tls)
+{
+       private_tnc_ifmap2_soap_msg_t *this;
+
+       INIT(this,
+               .public = {
+                       .post = _post,
+                       .destroy = _destroy,
+               },
+               .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
new file mode 100644 (file)
index 0000000..21ab5ee
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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_name  name of the IF-MAP request
+        * @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,
+                                char *request_name, 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 tls  TLS socket protecting the SOAP message
+ */
+tnc_ifmap2_soap_msg_t *tnc_ifmap2_soap_msg_create(tls_socket_t *tls);
+
+#endif /** TNC_IFMAP2_SOAP_MSG_H_ @}*/