created tnc_ifmap2_soap_msg class

This commit is contained in:
Andreas Steffen 2013-03-29 23:09:11 +01:00
parent b885c3cde6
commit cd13c9a90f
4 changed files with 343 additions and 220 deletions

View 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

View File

@ -13,28 +13,20 @@
* 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;
}

View File

@ -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;
}

View File

@ -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_ @}*/