dpward / rpms / sssd

Forked from rpms/sssd 3 years ago
Clone

Blame SOURCES/0084-secrets-remove-http-parser-code-in-proxy-provider.patch

bb7cd1
From cfb82199afe237b4e892aaf2816db63279d7cb21 Mon Sep 17 00:00:00 2001
bb7cd1
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
bb7cd1
Date: Tue, 28 Feb 2017 14:14:40 +0100
bb7cd1
Subject: [PATCH 84/90] secrets: remove http-parser code in proxy provider
bb7cd1
bb7cd1
We switche to libcurl in previous patch. This just removes the unused code.
bb7cd1
bb7cd1
Resolves:
bb7cd1
https://pagure.io/SSSD/sssd/issue/3192
bb7cd1
bb7cd1
Reviewed-by: Simo Sorce <simo@redhat.com>
bb7cd1
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
bb7cd1
(cherry picked from commit 06744bf5a47d5971a338281c8243b11cf72dac90)
bb7cd1
---
bb7cd1
 src/responder/secrets/proxy.c | 581 ------------------------------------------
bb7cd1
 1 file changed, 581 deletions(-)
bb7cd1
bb7cd1
diff --git a/src/responder/secrets/proxy.c b/src/responder/secrets/proxy.c
bb7cd1
index fe2f0134e233d9a98f499fe563abe0af69762514..3c495716010ac468c9e2f1fb6356529a8dbdc614 100644
bb7cd1
--- a/src/responder/secrets/proxy.c
bb7cd1
+++ b/src/responder/secrets/proxy.c
bb7cd1
@@ -395,587 +395,6 @@ done:
bb7cd1
     return ret;
bb7cd1
 }
bb7cd1
 
bb7cd1
-struct proxy_http_request {
bb7cd1
-    struct sec_data *data;
bb7cd1
-    size_t written;
bb7cd1
-};
bb7cd1
-
bb7cd1
-struct proxy_http_reply {
bb7cd1
-    http_parser parser;
bb7cd1
-    bool complete;
bb7cd1
-
bb7cd1
-    int status_code;
bb7cd1
-    char *reason_phrase;
bb7cd1
-    struct sec_kvp *headers;
bb7cd1
-    int num_headers;
bb7cd1
-    struct sec_data body;
bb7cd1
-
bb7cd1
-    size_t received;
bb7cd1
-};
bb7cd1
-
bb7cd1
-struct proxy_http_req_state {
bb7cd1
-    struct tevent_context *ev;
bb7cd1
-
bb7cd1
-    char *proxyname;
bb7cd1
-    int port;
bb7cd1
-
bb7cd1
-    struct resolv_hostent *hostent;
bb7cd1
-    int hostidx;
bb7cd1
-
bb7cd1
-    int sd;
bb7cd1
-    struct tevent_fd *fde;
bb7cd1
-
bb7cd1
-    struct proxy_http_request request;
bb7cd1
-    struct proxy_http_reply *reply;
bb7cd1
-};
bb7cd1
-
bb7cd1
-static int proxy_http_req_state_destroy(void *data);
bb7cd1
-static void proxy_http_req_gethostname_done(struct tevent_req *subreq);
bb7cd1
-static void proxy_http_req_connect_step(struct tevent_req *req);
bb7cd1
-static void proxy_http_req_connect_done(struct tevent_req *subreq);
bb7cd1
-static void proxy_fd_handler(struct tevent_context *ev, struct tevent_fd *fde,
bb7cd1
-                             uint16_t flags, void *ptr);
bb7cd1
-
bb7cd1
-struct tevent_req *proxy_http_req_send(struct proxy_context *pctx,
bb7cd1
-                                       TALLOC_CTX *mem_ctx,
bb7cd1
-                                       struct tevent_context *ev,
bb7cd1
-                                       struct sec_req_ctx *secreq,
bb7cd1
-                                       const char *http_uri,
bb7cd1
-                                       struct sec_data *http_req)
bb7cd1
-{
bb7cd1
-    struct proxy_http_req_state *state;
bb7cd1
-    struct http_parser_url parsed;
bb7cd1
-    struct tevent_req *req, *subreq;
bb7cd1
-    int ret;
bb7cd1
-
bb7cd1
-    req = tevent_req_create(mem_ctx, &state, struct proxy_http_req_state);
bb7cd1
-    if (!req) return NULL;
bb7cd1
-
bb7cd1
-    state->ev = ev;
bb7cd1
-    state->request.data = http_req;
bb7cd1
-    state->sd = -1;
bb7cd1
-    talloc_set_destructor((TALLOC_CTX *)state,
bb7cd1
-                          proxy_http_req_state_destroy);
bb7cd1
-
bb7cd1
-    /* STEP1: reparse URL to get hostname and port */
bb7cd1
-    ret = http_parser_parse_url(http_uri, strlen(http_uri), 0, &parsed);
bb7cd1
-    if (ret) {
bb7cd1
-        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse URL [%s]: %d: %s\n",
bb7cd1
-                                   http_uri, ret, sss_strerror(ret));
bb7cd1
-        goto done;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    if (!(parsed.field_set & (1 << UF_HOST))) {
bb7cd1
-        DEBUG(SSSDBG_CRIT_FAILURE, "No UF_HOST flag found\n");
bb7cd1
-        ret = EINVAL;
bb7cd1
-        goto done;
bb7cd1
-    }
bb7cd1
-    state->proxyname =
bb7cd1
-        talloc_strndup(state,
bb7cd1
-                       &http_uri[parsed.field_data[UF_HOST].off],
bb7cd1
-                       parsed.field_data[UF_HOST].len);
bb7cd1
-    if (!state->proxyname) {
bb7cd1
-        ret = ENOMEM;
bb7cd1
-        goto done;
bb7cd1
-    }
bb7cd1
-    DEBUG(SSSDBG_TRACE_LIBS, "proxy name: %s\n", state->proxyname);
bb7cd1
-
bb7cd1
-    if (parsed.field_set & (1 << UF_PORT)) {
bb7cd1
-        state->port = parsed.port;
bb7cd1
-    } else if (parsed.field_set & (1 << UF_SCHEMA)) {
bb7cd1
-        uint16_t off = parsed.field_data[UF_SCHEMA].off;
bb7cd1
-        uint16_t len = parsed.field_data[UF_SCHEMA].len;
bb7cd1
-
bb7cd1
-        if ((len == 5) &&
bb7cd1
-            (strncmp("https", &http_uri[off], len) == 0)) {
bb7cd1
-            state->port = 443;
bb7cd1
-        } else if ((len == 4) &&
bb7cd1
-                   (strncmp("http", &http_uri[off], len) == 0)) {
bb7cd1
-            state->port = 80;
bb7cd1
-        }
bb7cd1
-    }
bb7cd1
-    DEBUG(SSSDBG_TRACE_LIBS, "proxy port: %d\n", state->port);
bb7cd1
-
bb7cd1
-    /* STEP2: resolve hostname first */
bb7cd1
-    subreq = resolv_gethostbyname_send(state, ev, pctx->resctx,
bb7cd1
-                                       state->proxyname, IPV4_FIRST,
bb7cd1
-                                       default_host_dbs);
bb7cd1
-    if (subreq == NULL) {
bb7cd1
-        ret = ENOMEM;
bb7cd1
-        goto done;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    tevent_req_set_callback(subreq, proxy_http_req_gethostname_done, req);
bb7cd1
-
bb7cd1
-    return req;
bb7cd1
-
bb7cd1
-done:
bb7cd1
-    if (ret == EOK) {
bb7cd1
-        tevent_req_done(req);
bb7cd1
-    } else {
bb7cd1
-        tevent_req_error(req, ret);
bb7cd1
-    }
bb7cd1
-    tevent_req_post(req, ev);
bb7cd1
-
bb7cd1
-    return req;
bb7cd1
-}
bb7cd1
-
bb7cd1
-static void proxy_http_req_gethostname_done(struct tevent_req *subreq)
bb7cd1
-{
bb7cd1
-    struct tevent_req *req;
bb7cd1
-    struct proxy_http_req_state *state;
bb7cd1
-    int resolv_status;
bb7cd1
-    int ret;
bb7cd1
-
bb7cd1
-    req = tevent_req_callback_data(subreq, struct tevent_req);
bb7cd1
-    state = tevent_req_data(req, struct proxy_http_req_state);
bb7cd1
-
bb7cd1
-    ret = resolv_gethostbyname_recv(subreq, state, &resolv_status, NULL,
bb7cd1
-                                    &state->hostent);
bb7cd1
-    talloc_zfree(subreq);
bb7cd1
-    if (ret != EOK) {
bb7cd1
-        if (ret == ENOENT) {
bb7cd1
-            /* Empty result, just quit */
bb7cd1
-            DEBUG(SSSDBG_TRACE_INTERNAL, "No hostent found\n");
bb7cd1
-        } else {
bb7cd1
-            DEBUG(SSSDBG_OP_FAILURE,
bb7cd1
-                  "Could not resolve fqdn for this machine, error [%d]: %s, "
bb7cd1
-                  "resolver returned: [%d]: %s\n", ret, strerror(ret),
bb7cd1
-                  resolv_status, resolv_strerror(resolv_status));
bb7cd1
-        }
bb7cd1
-        goto done;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    /* EOK */
bb7cd1
-    DEBUG(SSSDBG_TRACE_INTERNAL, "Found fqdn: %s\n", state->hostent->name);
bb7cd1
-
bb7cd1
-    /* STEP3: connect to one of the servers */
bb7cd1
-    proxy_http_req_connect_step(req);
bb7cd1
-    return;
bb7cd1
-
bb7cd1
-done:
bb7cd1
-    if (ret == EOK) {
bb7cd1
-        tevent_req_done(req);
bb7cd1
-    } else {
bb7cd1
-        tevent_req_error(req, ret);
bb7cd1
-    }
bb7cd1
-}
bb7cd1
-
bb7cd1
-static void proxy_http_req_connect_step(struct tevent_req *req)
bb7cd1
-{
bb7cd1
-    struct proxy_http_req_state *state;
bb7cd1
-    struct sockaddr_storage *sockaddr;
bb7cd1
-    char *ipaddr;
bb7cd1
-    struct tevent_req *subreq;
bb7cd1
-    int ret;
bb7cd1
-
bb7cd1
-    state = tevent_req_data(req, struct proxy_http_req_state);
bb7cd1
-
bb7cd1
-    if (!state->hostent->addr_list[state->hostidx]) {
bb7cd1
-        DEBUG(SSSDBG_CRIT_FAILURE, "No more addresses to try.\n");
bb7cd1
-        ret = ERR_SEC_NO_PROXY;
bb7cd1
-        goto done;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    sockaddr = resolv_get_sockaddr_address_index(state, state->hostent,
bb7cd1
-                                                 state->port, state->hostidx);
bb7cd1
-    if (sockaddr == NULL) {
bb7cd1
-        DEBUG(SSSDBG_OP_FAILURE, "resolv_get_sockaddr_address() failed\n");
bb7cd1
-        ret = EIO;
bb7cd1
-        goto done;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    if (DEBUG_IS_SET(SSSDBG_TRACE_FUNC)) {
bb7cd1
-        ipaddr = resolv_get_string_address_index(state, state->hostent,
bb7cd1
-                                                 state->hostidx);
bb7cd1
-        if (!ipaddr) {
bb7cd1
-            ret = EFAULT;
bb7cd1
-            goto done;
bb7cd1
-        }
bb7cd1
-        DEBUG(SSSDBG_TRACE_FUNC, "Connecting to %s:%d\n",
bb7cd1
-              ipaddr, state->port);
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    /* increase idx for next attempt */
bb7cd1
-    state->hostidx++;
bb7cd1
-
bb7cd1
-    subreq = sssd_async_socket_init_send(state, state->ev, sockaddr,
bb7cd1
-                                         sizeof(struct sockaddr_storage),
bb7cd1
-                                         SEC_NET_TIMEOUT);
bb7cd1
-    if (!subreq) {
bb7cd1
-        ret = EIO;
bb7cd1
-        goto done;
bb7cd1
-    }
bb7cd1
-    tevent_req_set_callback(subreq, proxy_http_req_connect_done, req);
bb7cd1
-    return;
bb7cd1
-
bb7cd1
-done:
bb7cd1
-    if (ret == EOK) {
bb7cd1
-        tevent_req_done(req);
bb7cd1
-    } else {
bb7cd1
-        tevent_req_error(req, ret);
bb7cd1
-    }
bb7cd1
-}
bb7cd1
-
bb7cd1
-static void proxy_http_req_connect_done(struct tevent_req *subreq)
bb7cd1
-{
bb7cd1
-    struct tevent_req *req;
bb7cd1
-    struct proxy_http_req_state *state;
bb7cd1
-    int ret;
bb7cd1
-
bb7cd1
-    req = tevent_req_callback_data(subreq, struct tevent_req);
bb7cd1
-    state = tevent_req_data(req, struct proxy_http_req_state);
bb7cd1
-
bb7cd1
-    ret = sssd_async_socket_init_recv(subreq, &state->sd);
bb7cd1
-    talloc_zfree(subreq);
bb7cd1
-    if (ret != EOK) {
bb7cd1
-        DEBUG(SSSDBG_CRIT_FAILURE,
bb7cd1
-              "sssd_async_socket_init request failed: [%d]: %s.\n",
bb7cd1
-              ret, sss_strerror(ret));
bb7cd1
-
bb7cd1
-        /* try next server if any */
bb7cd1
-        proxy_http_req_connect_step(req);
bb7cd1
-        return;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    /* EOK */
bb7cd1
-    DEBUG(SSSDBG_TRACE_FUNC, "Connected to %s\n", state->hostent->name);
bb7cd1
-
bb7cd1
-    state->fde = tevent_add_fd(state->ev, state, state->sd,
bb7cd1
-                               TEVENT_FD_WRITE, proxy_fd_handler,
bb7cd1
-                               req);
bb7cd1
-    if (!state->fde) {
bb7cd1
-        ret = EIO;
bb7cd1
-        goto done;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    return;
bb7cd1
-
bb7cd1
-done:
bb7cd1
-    if (ret == EOK) {
bb7cd1
-        tevent_req_done(req);
bb7cd1
-    } else {
bb7cd1
-        tevent_req_error(req, ret);
bb7cd1
-    }
bb7cd1
-}
bb7cd1
-
bb7cd1
-
bb7cd1
-int proxy_http_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
bb7cd1
-                        struct proxy_http_reply **reply)
bb7cd1
-{
bb7cd1
-    struct proxy_http_req_state *state =
bb7cd1
-                tevent_req_data(req, struct proxy_http_req_state);
bb7cd1
-
bb7cd1
-    TEVENT_REQ_RETURN_ON_ERROR(req);
bb7cd1
-
bb7cd1
-    *reply = talloc_move(mem_ctx, &state->reply);
bb7cd1
-
bb7cd1
-    return EOK;
bb7cd1
-}
bb7cd1
-
bb7cd1
-static int proxy_http_req_state_destroy(void *data)
bb7cd1
-{
bb7cd1
-    struct proxy_http_req_state *state =
bb7cd1
-        talloc_get_type(data, struct proxy_http_req_state);
bb7cd1
-
bb7cd1
-    if (!state) return 0;
bb7cd1
-
bb7cd1
-    if (state->sd != -1) {
bb7cd1
-        DEBUG(SSSDBG_TRACE_FUNC, "closing socket [%d]\n", state->sd);
bb7cd1
-        close(state->sd);
bb7cd1
-        state->sd = -1;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    return 0;
bb7cd1
-}
bb7cd1
-
bb7cd1
-static int proxy_wire_send(int fd, struct proxy_http_request *req)
bb7cd1
-{
bb7cd1
-    struct sec_data data;
bb7cd1
-    int ret;
bb7cd1
-
bb7cd1
-    data.data = req->data->data + req->written;
bb7cd1
-    data.length = req->data->length - req->written;
bb7cd1
-
bb7cd1
-    ret = sec_send_data(fd, &data);
bb7cd1
-    if (ret != EOK && ret != EAGAIN) {
bb7cd1
-        DEBUG(SSSDBG_CRIT_FAILURE,
bb7cd1
-              "sec_send_data failed [%d]: %s\n", ret, sss_strerror(ret));
bb7cd1
-        return ret;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    req->written = req->data->length - data.length;
bb7cd1
-    return ret;
bb7cd1
-}
bb7cd1
-
bb7cd1
-static void proxy_fd_send(void *data)
bb7cd1
-{
bb7cd1
-    struct proxy_http_req_state *state;
bb7cd1
-    struct tevent_req * req;
bb7cd1
-    int ret;
bb7cd1
-
bb7cd1
-    req = talloc_get_type(data, struct tevent_req);
bb7cd1
-    state = tevent_req_data(req, struct proxy_http_req_state);
bb7cd1
-
bb7cd1
-    ret = proxy_wire_send(state->sd, &state->request);
bb7cd1
-    if (ret == EAGAIN) {
bb7cd1
-        /* not all data was sent, loop again */
bb7cd1
-        return;
bb7cd1
-    }
bb7cd1
-    if (ret != EOK) {
bb7cd1
-        DEBUG(SSSDBG_FATAL_FAILURE, "Failed to send data, aborting!\n");
bb7cd1
-        tevent_req_error(req, ret);
bb7cd1
-        return;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    /* ok all sent, wait for reply now */
bb7cd1
-    TEVENT_FD_NOT_WRITEABLE(state->fde);
bb7cd1
-    TEVENT_FD_READABLE(state->fde);
bb7cd1
-    return;
bb7cd1
-}
bb7cd1
-
bb7cd1
-static bool ph_received_data(struct proxy_http_reply *reply, size_t length)
bb7cd1
-{
bb7cd1
-    reply->received += length;
bb7cd1
-    if (reply->received > SEC_REQUEST_MAX_SIZE) {
bb7cd1
-        DEBUG(SSSDBG_FATAL_FAILURE, "Request too big, aborting!\n");
bb7cd1
-        return true;
bb7cd1
-    }
bb7cd1
-    return false;
bb7cd1
-}
bb7cd1
-
bb7cd1
-static void ph_append_string(TALLOC_CTX *memctx, char **dest,
bb7cd1
-                             const char *src, size_t len)
bb7cd1
-{
bb7cd1
-    if (*dest) {
bb7cd1
-        *dest = talloc_strndup_append_buffer(*dest, src, len);
bb7cd1
-    } else {
bb7cd1
-        *dest = talloc_strndup(memctx, src, len);
bb7cd1
-    }
bb7cd1
-}
bb7cd1
-
bb7cd1
-static int ph_on_message_begin(http_parser *parser)
bb7cd1
-{
bb7cd1
-    DEBUG(SSSDBG_TRACE_INTERNAL, "HTTP Message parsing begins\n");
bb7cd1
-    return 0;
bb7cd1
-}
bb7cd1
-
bb7cd1
-#if ((HTTP_PARSER_VERSION_MAJOR >= 2) && (HTTP_PARSER_VERSION_MINOR >= 2))
bb7cd1
-static int ph_on_status(http_parser *parser, const char *at, size_t length)
bb7cd1
-{
bb7cd1
-    struct proxy_http_reply *reply =
bb7cd1
-        talloc_get_type(parser->data, struct proxy_http_reply);
bb7cd1
-
bb7cd1
-    if (ph_received_data(reply, length)) return -1;
bb7cd1
-
bb7cd1
-    ph_append_string(reply, &reply->reason_phrase, at, length);
bb7cd1
-    if (!reply->reason_phrase) {
bb7cd1
-        DEBUG(SSSDBG_FATAL_FAILURE,
bb7cd1
-              "Failed to store reason phrase, aborting client!\n");
bb7cd1
-        return -1;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    return 0;
bb7cd1
-}
bb7cd1
-#endif
bb7cd1
-
bb7cd1
-static int ph_on_header_field(http_parser *parser,
bb7cd1
-                              const char *at, size_t length)
bb7cd1
-{
bb7cd1
-    struct proxy_http_reply *reply =
bb7cd1
-        talloc_get_type(parser->data, struct proxy_http_reply);
bb7cd1
-    int n = reply->num_headers;
bb7cd1
-
bb7cd1
-    if (ph_received_data(reply, length)) return -1;
bb7cd1
-
bb7cd1
-    if (!reply->headers) {
bb7cd1
-        reply->headers = talloc_zero_array(reply, struct sec_kvp, 10);
bb7cd1
-    } else if ((n % 10 == 0) &&
bb7cd1
-               (reply->headers[n - 1].value)) {
bb7cd1
-        reply->headers = talloc_realloc(reply, reply->headers,
bb7cd1
-                                        struct sec_kvp, n + 10);
bb7cd1
-        if (reply->headers) {
bb7cd1
-            memset(&reply->headers[n], 0, sizeof(struct sec_kvp) * 10);
bb7cd1
-        }
bb7cd1
-    }
bb7cd1
-    if (!reply->headers) {
bb7cd1
-        DEBUG(SSSDBG_FATAL_FAILURE,
bb7cd1
-              "Failed to store headers, aborting client!\n");
bb7cd1
-        return -1;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    if (!n || reply->headers[n - 1].value) {
bb7cd1
-        /* new field */
bb7cd1
-        n++;
bb7cd1
-    }
bb7cd1
-    ph_append_string(reply->headers, &reply->headers[n - 1].name, at, length);
bb7cd1
-    if (!reply->headers[n - 1].name) {
bb7cd1
-        DEBUG(SSSDBG_FATAL_FAILURE,
bb7cd1
-              "Failed to store header name, aborting client!\n");
bb7cd1
-        return -1;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    return 0;
bb7cd1
-}
bb7cd1
-
bb7cd1
-static int ph_on_header_value(http_parser *parser,
bb7cd1
-                              const char *at, size_t length)
bb7cd1
-{
bb7cd1
-    struct proxy_http_reply *reply =
bb7cd1
-        talloc_get_type(parser->data, struct proxy_http_reply);
bb7cd1
-    int n = reply->num_headers;
bb7cd1
-
bb7cd1
-    if (ph_received_data(reply, length)) return -1;
bb7cd1
-
bb7cd1
-    if (!reply->headers) {
bb7cd1
-        DEBUG(SSSDBG_FATAL_FAILURE,
bb7cd1
-              "Invalid headers pointer, aborting client!\n");
bb7cd1
-        return -1;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    if (reply->headers[n].name && !reply->headers[n].value) {
bb7cd1
-        /* we increment on new value */
bb7cd1
-        n = ++reply->num_headers;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    ph_append_string(reply->headers, &reply->headers[n - 1].value, at, length);
bb7cd1
-    if (!reply->headers[n - 1].value) {
bb7cd1
-        DEBUG(SSSDBG_FATAL_FAILURE,
bb7cd1
-              "Failed to store header value, aborting client!\n");
bb7cd1
-        return -1;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    return 0;
bb7cd1
-}
bb7cd1
-
bb7cd1
-static int ph_on_headers_complete(http_parser *parser)
bb7cd1
-{
bb7cd1
-    /* TODO: if message has no body we should return 1 */
bb7cd1
-    return 0;
bb7cd1
-}
bb7cd1
-
bb7cd1
-static int ph_on_body(http_parser *parser, const char *at, size_t length)
bb7cd1
-{
bb7cd1
-    struct proxy_http_reply *reply =
bb7cd1
-        talloc_get_type(parser->data, struct proxy_http_reply);
bb7cd1
-
bb7cd1
-    if (ph_received_data(reply, length)) return -1;
bb7cd1
-
bb7cd1
-    /* FIXME: body may be binary */
bb7cd1
-    ph_append_string(reply, &reply->body.data, at, length);
bb7cd1
-    if (!reply->body.data) {
bb7cd1
-        DEBUG(SSSDBG_FATAL_FAILURE,
bb7cd1
-              "Failed to store body, aborting!\n");
bb7cd1
-        return -1;
bb7cd1
-    }
bb7cd1
-    reply->body.length += length;
bb7cd1
-
bb7cd1
-    return 0;
bb7cd1
-}
bb7cd1
-
bb7cd1
-static int ph_on_message_complete(http_parser *parser)
bb7cd1
-{
bb7cd1
-    struct proxy_http_reply *reply =
bb7cd1
-        talloc_get_type(parser->data, struct proxy_http_reply);
bb7cd1
-
bb7cd1
-    reply->status_code = parser->status_code;
bb7cd1
-    reply->complete = true;
bb7cd1
-
bb7cd1
-    return 0;
bb7cd1
-}
bb7cd1
-
bb7cd1
-static http_parser_settings ph_callbacks = {
bb7cd1
-    .on_message_begin = ph_on_message_begin,
bb7cd1
-#if ((HTTP_PARSER_VERSION_MAJOR >= 2) && (HTTP_PARSER_VERSION_MINOR >= 2))
bb7cd1
-    .on_status = ph_on_status,
bb7cd1
-#endif
bb7cd1
-    .on_header_field = ph_on_header_field,
bb7cd1
-    .on_header_value = ph_on_header_value,
bb7cd1
-    .on_headers_complete = ph_on_headers_complete,
bb7cd1
-    .on_body = ph_on_body,
bb7cd1
-    .on_message_complete = ph_on_message_complete
bb7cd1
-};
bb7cd1
-
bb7cd1
-static void proxy_fd_recv(void *data)
bb7cd1
-{
bb7cd1
-    char buffer[SEC_PACKET_MAX_RECV_SIZE];
bb7cd1
-    struct sec_data packet = { buffer,
bb7cd1
-                               SEC_PACKET_MAX_RECV_SIZE };
bb7cd1
-    struct proxy_http_req_state *state;
bb7cd1
-    struct tevent_req *req;
bb7cd1
-    bool must_complete = false;
bb7cd1
-    int ret;
bb7cd1
-
bb7cd1
-    req = talloc_get_type(data, struct tevent_req);
bb7cd1
-    state = tevent_req_data(req, struct proxy_http_req_state);
bb7cd1
-
bb7cd1
-    if (!state->reply) {
bb7cd1
-        /* A new reply */
bb7cd1
-        state->reply = talloc_zero(state, struct proxy_http_reply);
bb7cd1
-        if (!state->reply) {
bb7cd1
-            DEBUG(SSSDBG_FATAL_FAILURE, "Failed to allocate reply, aborting!\n");
bb7cd1
-            tevent_req_error(req, ENOMEM);
bb7cd1
-            return;
bb7cd1
-        }
bb7cd1
-        http_parser_init(&state->reply->parser, HTTP_RESPONSE);
bb7cd1
-        state->reply->parser.data = state->reply;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    ret = sec_recv_data(state->sd, &packet);
bb7cd1
-    switch (ret) {
bb7cd1
-    case ENODATA:
bb7cd1
-        DEBUG(SSSDBG_TRACE_ALL, "Server closed connection.\n");
bb7cd1
-        /* if we got no content length and the request is not complete,
bb7cd1
-         * then 0 length will indicate EOF to the parser, otherwise we
bb7cd1
-         * have an error */
bb7cd1
-        must_complete = true;
bb7cd1
-        break;
bb7cd1
-    case EAGAIN:
bb7cd1
-        DEBUG(SSSDBG_TRACE_ALL,
bb7cd1
-              "Interrupted before any data could be read, retry later\n");
bb7cd1
-        return;
bb7cd1
-    case EOK:
bb7cd1
-        /* all fine */
bb7cd1
-        break;
bb7cd1
-    default:
bb7cd1
-        DEBUG(SSSDBG_FATAL_FAILURE,
bb7cd1
-              "Failed to receive data (%d, %s), aborting\n",
bb7cd1
-              ret, sss_strerror(ret));
bb7cd1
-        tevent_req_error(req, EIO);
bb7cd1
-        return;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    ret = http_parser_execute(&state->reply->parser, &ph_callbacks,
bb7cd1
-                              packet.data, packet.length);
bb7cd1
-    if (ret != packet.length) {
bb7cd1
-        DEBUG(SSSDBG_FATAL_FAILURE,
bb7cd1
-              "Failed to parse request, aborting!\n");
bb7cd1
-        tevent_req_error(req, EIO);
bb7cd1
-        return;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    if (!state->reply->complete) {
bb7cd1
-        if (must_complete) {
bb7cd1
-            tevent_req_error(req, EIO);
bb7cd1
-        }
bb7cd1
-        return;
bb7cd1
-    }
bb7cd1
-
bb7cd1
-    /* do not read anymore, server is done sending */
bb7cd1
-    TEVENT_FD_NOT_READABLE(state->fde);
bb7cd1
-    tevent_req_done(req);
bb7cd1
-}
bb7cd1
-
bb7cd1
-static void proxy_fd_handler(struct tevent_context *ev, struct tevent_fd *fde,
bb7cd1
-                             uint16_t flags, void *data)
bb7cd1
-{
bb7cd1
-    if (flags & TEVENT_FD_READ) {
bb7cd1
-        proxy_fd_recv(data);
bb7cd1
-    } else if (flags & TEVENT_FD_WRITE) {
bb7cd1
-        proxy_fd_send(data);
bb7cd1
-    }
bb7cd1
-}
bb7cd1
-
bb7cd1
 struct proxy_secret_state {
bb7cd1
     struct tevent_context *ev;
bb7cd1
     struct sec_req_ctx *secreq;
bb7cd1
-- 
bb7cd1
2.9.3
bb7cd1