Annotation of embedaddon/strongswan/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap_msg.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2013 Andreas Steffen
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "tnc_ifmap_soap_msg.h"
                     17: #include "tnc_ifmap_http.h"
                     18: 
                     19: #include <utils/debug.h>
                     20: 
                     21: #define SOAP_NS                "http://www.w3.org/2003/05/soap-envelope"
                     22: 
                     23: typedef struct private_tnc_ifmap_soap_msg_t private_tnc_ifmap_soap_msg_t;
                     24: 
                     25: /**
                     26:  * Private data of an tnc_ifmap_soap_msg_t object.
                     27:  */
                     28: struct private_tnc_ifmap_soap_msg_t {
                     29: 
                     30:        /**
                     31:         * Public tnc_ifmap_soap_msg_t interface.
                     32:         */
                     33:        tnc_ifmap_soap_msg_t public;
                     34: 
                     35:        /**
                     36:         * HTTP POST request builder and response processing
                     37:         */
                     38:        tnc_ifmap_http_t *http;
                     39: 
                     40:        /**
                     41:         * TLS socket
                     42:         */
                     43:        tls_socket_t *tls;
                     44: 
                     45:        /**
                     46:         * XML Document
                     47:         */
                     48:        xmlDocPtr doc;
                     49: 
                     50: };
                     51: 
                     52: /**
                     53:  * Find a child node with a given name
                     54:  */
                     55: static xmlNodePtr find_child(xmlNodePtr parent, const xmlChar* name)
                     56: {
                     57:        xmlNodePtr child;
                     58: 
                     59:        child = parent->xmlChildrenNode;
                     60:        while (child)
                     61:        {
                     62:                if (xmlStrcmp(child->name, name) == 0)
                     63:                {
                     64:                        return child;
                     65:                }
                     66:                child = child->next;
                     67:        }
                     68: 
                     69:        DBG1(DBG_TNC, "child node \"%s\" not found", name);
                     70:        return NULL;
                     71: }
                     72: 
                     73: METHOD(tnc_ifmap_soap_msg_t, post, bool,
                     74:        private_tnc_ifmap_soap_msg_t *this, xmlNodePtr request, char *result_name,
                     75:        xmlNodePtr *result)
                     76: {
                     77:        xmlDocPtr doc;
                     78:        xmlNodePtr env, body, cur, response;
                     79:        xmlNsPtr ns;
                     80:        xmlChar *xml_str, *errorCode, *errorString;
                     81:        int xml_len, len, written;
                     82:        chunk_t xml, http;
                     83:        char buf[4096] = { 0 };
                     84:        status_t status;
                     85: 
                     86:        DBG2(DBG_TNC, "sending ifmap %s", request->name);
                     87: 
                     88:        /* Generate XML Document containing SOAP Envelope */
                     89:        doc = xmlNewDoc("1.0");
                     90:        env =xmlNewNode(NULL, "Envelope");
                     91:        ns = xmlNewNs(env, SOAP_NS, "env");
                     92:        xmlSetNs(env, ns);
                     93:        xmlDocSetRootElement(doc, env);
                     94: 
                     95:        /* Add SOAP Body containing IF-MAP request */
                     96:        body = xmlNewNode(ns, "Body");
                     97:        xmlAddChild(body, request);
                     98:        xmlAddChild(env, body);
                     99: 
                    100:        /* Convert XML Document into a character string */
                    101:        xmlDocDumpFormatMemory(doc, &xml_str, &xml_len, 1);
                    102:        xmlFreeDoc(doc);
                    103:        DBG3(DBG_TNC, "%.*s", xml_len, xml_str);
                    104:        xml = chunk_create(xml_str, xml_len);
                    105: 
                    106:        /* Send SOAP-XML request via HTTPS POST */
                    107:        do
                    108:        {
                    109:                status = this->http->build(this->http, &xml, &http);
                    110:                if (status == FAILED)
                    111:                {
                    112:                        break;
                    113:                }
                    114:                written = this->tls->write(this->tls, http.ptr, http.len);
                    115:                free(http.ptr);
                    116:                if (written != http.len)
                    117:                {
                    118:                        status = FAILED;
                    119:                        break;
                    120:                }
                    121:        }
                    122:        while (status == NEED_MORE);
                    123: 
                    124:        xmlFree(xml_str);
                    125:        if (status != SUCCESS)
                    126:        {
                    127:                return FALSE;
                    128:        }
                    129: 
                    130:        /* Receive SOAP-XML response via [chunked] HTTPS */
                    131:        xml = chunk_empty;
                    132:        do
                    133:        {
                    134:                /* reduce size so the buffer is null-terminated */
                    135:                len = this->tls->read(this->tls, buf, sizeof(buf)-1, TRUE);
                    136:                if (len <= 0)
                    137:                {
                    138:                        return FALSE;
                    139:                }
                    140:                http = chunk_create(buf, len);
                    141: 
                    142:                status = this->http->process(this->http, &http, &xml);
                    143:                if (status == FAILED)
                    144:                {
                    145:                        free(xml.ptr);
                    146:                        return FALSE;
                    147:                }
                    148:        }
                    149:        while (status == NEED_MORE);
                    150: 
                    151:        DBG3(DBG_TNC, "parsing XML message %B", &xml);
                    152:        this->doc = xmlParseMemory(xml.ptr, xml.len);
                    153:        free(xml.ptr);
                    154: 
                    155:        if (!this->doc)
                    156:        {
                    157:                DBG1(DBG_TNC, "failed to parse XML message");
                    158:                return FALSE;
                    159:        }
                    160: 
                    161:        /* check out XML document */
                    162:        cur = xmlDocGetRootElement(this->doc);
                    163:        if (!cur)
                    164:        {
                    165:                DBG1(DBG_TNC, "empty XML message");
                    166:                return FALSE;
                    167:        }
                    168: 
                    169:        /* get XML Document type is a SOAP Envelope */
                    170:        if (xmlStrcmp(cur->name, "Envelope"))
                    171:        {
                    172:                DBG1(DBG_TNC, "XML message does not contain a SOAP Envelope");
                    173:                return FALSE;
                    174:        }
                    175: 
                    176:        /* get SOAP Body */
                    177:        cur = find_child(cur, "Body");
                    178:        if (!cur)
                    179:        {
                    180:                return FALSE;
                    181:        }
                    182: 
                    183:        /* get IF-MAP response */
                    184:        response = find_child(cur, "response");
                    185:        if (!response)
                    186:        {
                    187:                return FALSE;
                    188:        }
                    189: 
                    190:        /* get IF-MAP result */
                    191:        cur = find_child(response, result_name);
                    192:        if (!cur)
                    193:        {
                    194:                cur = find_child(response, "errorResult");
                    195:                if (cur)
                    196:                {
                    197:                        DBG1(DBG_TNC, "received errorResult");
                    198: 
                    199:                        errorCode = xmlGetProp(cur, "errorCode");
                    200:                        if (errorCode)
                    201:                        {
                    202:                                DBG1(DBG_TNC, "  %s", errorCode);
                    203:                                xmlFree(errorCode);
                    204:                        }
                    205: 
                    206:                        cur = find_child(cur, "errorString");
                    207:                        if (cur)
                    208:                        {
                    209:                                errorString = xmlNodeGetContent(cur);
                    210:                                if (errorString)
                    211:                                {
                    212:                                        DBG1(DBG_TNC, "  %s", errorString);
                    213:                                        xmlFree(errorString);
                    214:                                }
                    215:                        }
                    216:                }
                    217:                return FALSE;
                    218:        }
                    219: 
                    220:        if (result)
                    221:        {
                    222:                *result = cur;
                    223:        }
                    224:        return TRUE;
                    225: }
                    226: 
                    227: METHOD(tnc_ifmap_soap_msg_t, destroy, void,
                    228:        private_tnc_ifmap_soap_msg_t *this)
                    229: {
                    230:        this->http->destroy(this->http);
                    231:        if (this->doc)
                    232:        {
                    233:                xmlFreeDoc(this->doc);
                    234:        }
                    235:        free(this);
                    236: }
                    237: 
                    238: /**
                    239:  * See header
                    240:  */
                    241: tnc_ifmap_soap_msg_t *tnc_ifmap_soap_msg_create(char *uri, chunk_t user_pass,
                    242:                                                                                                tls_socket_t *tls)
                    243: {
                    244:        private_tnc_ifmap_soap_msg_t *this;
                    245: 
                    246:        INIT(this,
                    247:                .public = {
                    248:                        .post = _post,
                    249:                        .destroy = _destroy,
                    250:                },
                    251:                .http = tnc_ifmap_http_create(uri, user_pass),
                    252:                .tls = tls,
                    253:        );
                    254: 
                    255:        return &this->public;
                    256: }
                    257: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>