|
|
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 |
|