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