Annotation of embedaddon/strongswan/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_http.c, revision 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: #define _GNU_SOURCE /* for asprintf() */
        !            17: 
        !            18: #include "tnc_ifmap_http.h"
        !            19: 
        !            20: #include <utils/debug.h>
        !            21: #include <utils/lexparser.h>
        !            22: 
        !            23: #include <stdio.h>
        !            24: 
        !            25: typedef struct private_tnc_ifmap_http_t private_tnc_ifmap_http_t;
        !            26: 
        !            27: /**
        !            28:  * Private data of an tnc_ifmap_http_t object.
        !            29:  */
        !            30: struct private_tnc_ifmap_http_t {
        !            31: 
        !            32:        /**
        !            33:         * Public tnc_ifmap_http_t interface.
        !            34:         */
        !            35:        tnc_ifmap_http_t public;
        !            36: 
        !            37:        /**
        !            38:         * HTTPS Server URI with https:// prefix removed
        !            39:         */
        !            40:        char *uri;
        !            41: 
        !            42:        /**
        !            43:         * Optional base64-encoded username:password for HTTP Basic Authentication
        !            44:         */
        !            45:        chunk_t user_pass;
        !            46: 
        !            47:        /**
        !            48:         * HTTP chunked mode
        !            49:         */
        !            50:        bool chunked;
        !            51: 
        !            52: };
        !            53: 
        !            54: METHOD(tnc_ifmap_http_t, build, status_t,
        !            55:        private_tnc_ifmap_http_t *this, chunk_t *in, chunk_t *out)
        !            56: {
        !            57:        char *host, *path, *request, auth[128];
        !            58:        int len;
        !            59: 
        !            60:        /* Duplicate host[/path] string since we are going to manipulate it */
        !            61:        len = strlen(this->uri) + 2;
        !            62:        host = malloc(len);
        !            63:        memset(host, '\0', len);
        !            64:        strcpy(host, this->uri);
        !            65: 
        !            66:        /* Extract appended path or set to root */
        !            67:        path = strchr(host, '/');
        !            68:        if (!path)
        !            69:        {
        !            70:                path = host + len - 2;
        !            71:                *path = '/';
        !            72:        }
        !            73: 
        !            74:        /* Use Basic Authentication? */
        !            75:        if (this->user_pass.len)
        !            76:        {
        !            77:                snprintf(auth, sizeof(auth), "Authorization: Basic %.*s\r\n",
        !            78:                                (int)this->user_pass.len, this->user_pass.ptr);
        !            79:        }
        !            80:        else
        !            81:        {
        !            82:                *auth = '\0';
        !            83:        }
        !            84: 
        !            85:        /* Write HTTP POST request, TODO break up into chunks */
        !            86:        len = asprintf(&request,
        !            87:                        "POST %s HTTP/1.1\r\n"
        !            88:                        "Host: %.*s\r\n"
        !            89:                        "%s"
        !            90:                        "Content-Type: application/soap+xml;charset=utf-8\r\n"
        !            91:                        "Content-Length: %d\r\n"
        !            92:                        "\r\n"
        !            93:                        "%.*s", path, (int)(path-host), host, auth, (int)in->len,
        !            94:                        (int)in->len, in->ptr);
        !            95:        free(host);
        !            96: 
        !            97:        if (len == -1)
        !            98:        {
        !            99:                return FAILED;
        !           100:        }
        !           101:        *out = chunk_create(request, len);
        !           102:        DBG3(DBG_TLS, "sending HTTP POST request %B", out);
        !           103: 
        !           104:        return SUCCESS;
        !           105: }
        !           106: 
        !           107: static bool process_header(chunk_t *in, bool *chunked, u_int *content_len)
        !           108: {
        !           109:        chunk_t line, version, parameter;
        !           110:        int code;
        !           111:        u_int len;
        !           112: 
        !           113:        /* Process HTTP protocol version */
        !           114:        if (!fetchline(in, &line) || !extract_token(&version, ' ', &line) ||
        !           115:                !match("HTTP/1.1", &version) || sscanf(line.ptr, "%d", &code) != 1)
        !           116:        {
        !           117:                DBG1(DBG_TNC, "malformed http response header");
        !           118:                return FALSE;
        !           119:        }
        !           120:        if (code != 200)
        !           121:        {
        !           122:                DBG1(DBG_TNC, "http response returns error code %d", code);
        !           123:                return FALSE;
        !           124:        }
        !           125: 
        !           126:        *content_len = 0;
        !           127:        *chunked = FALSE;
        !           128: 
        !           129:        /* Process HTTP header line by line until the HTTP body is reached */
        !           130:        while (fetchline(in, &line))
        !           131:        {
        !           132:                if (line.len == 0)
        !           133:                {
        !           134:                        break;
        !           135:                }
        !           136:                if (extract_token(&parameter, ':', &line) && eat_whitespace(&line))
        !           137:                {
        !           138:                        if (match("Content-Length", &parameter))
        !           139:                        {
        !           140:                                if (sscanf(line.ptr, "%u", &len) == 1)
        !           141:                                {
        !           142:                                        *content_len = len;
        !           143:                                }
        !           144:                        }
        !           145:                        else if (match("Transfer-Encoding", &parameter) &&
        !           146:                                         match("chunked", &line))
        !           147:                        {
        !           148:                                *chunked = TRUE;
        !           149:                        }
        !           150:                }
        !           151:        }
        !           152: 
        !           153:        return TRUE;
        !           154: }
        !           155: 
        !           156: METHOD(tnc_ifmap_http_t, process, status_t,
        !           157:        private_tnc_ifmap_http_t *this, chunk_t *in, chunk_t *out)
        !           158: {
        !           159:        u_int len = 0;
        !           160:        chunk_t line, out_chunk;
        !           161: 
        !           162:        DBG3(DBG_TLS, "receiving HTTP response %B", in);
        !           163: 
        !           164:        if (!this->chunked)
        !           165:        {
        !           166:                if (!process_header(in, &this->chunked, &len))
        !           167:                {
        !           168:                        return FAILED;
        !           169:                }
        !           170:        }
        !           171: 
        !           172:        while (in->len)
        !           173:        {
        !           174:                if (this->chunked)
        !           175:                {
        !           176:                        if (!fetchline(in, &line) || sscanf(line.ptr, "%x", &len) != 1)
        !           177:                        {
        !           178:                                return FAILED;
        !           179:                        }
        !           180:                        DBG3(DBG_TLS, "received HTTP response is chunked (%u bytes)", len);
        !           181: 
        !           182:                        /* Received last chunk? */
        !           183:                        if (len == 0)
        !           184:                        {
        !           185:                                return SUCCESS;
        !           186:                        }
        !           187:                }
        !           188: 
        !           189:                /* Check size of of remaining HTTP body */
        !           190:                if (len > in->len)
        !           191:                {
        !           192:                        DBG1(DBG_TNC, "insufficient data in HTTP body");
        !           193:                        return FAILED;
        !           194:                }
        !           195: 
        !           196:                if (this->chunked)
        !           197:                {
        !           198:                        out_chunk = *in;
        !           199:                        out_chunk.len = len;
        !           200:                        *out = chunk_cat("mc", *out, out_chunk);
        !           201:                        *in = chunk_skip(*in, len);
        !           202:                        if (!fetchline(in, &line) || line.len > 0)
        !           203:                        {
        !           204:                                return FAILED;
        !           205:                        }
        !           206:                }
        !           207:                else
        !           208:                {
        !           209:                        if (len)
        !           210:                        {
        !           211:                                in->len = len;
        !           212:                        }
        !           213:                        *out = chunk_clone(*in);
        !           214:                        return SUCCESS;
        !           215:                }
        !           216:        }
        !           217:        return NEED_MORE;
        !           218: }
        !           219: 
        !           220: METHOD(tnc_ifmap_http_t, destroy, void,
        !           221:        private_tnc_ifmap_http_t *this)
        !           222: {
        !           223:        free(this);
        !           224: }
        !           225: 
        !           226: /**
        !           227:  * See header
        !           228:  */
        !           229: tnc_ifmap_http_t *tnc_ifmap_http_create(char *uri, chunk_t user_pass)
        !           230: {
        !           231:        private_tnc_ifmap_http_t *this;
        !           232: 
        !           233:        INIT(this,
        !           234:                .public = {
        !           235:                        .build = _build,
        !           236:                        .process = _process,
        !           237:                        .destroy = _destroy,
        !           238:                },
        !           239:                .uri = uri,
        !           240:                .user_pass = user_pass,
        !           241:        );
        !           242: 
        !           243:        return &this->public;
        !           244: }
        !           245: 

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