a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce Secrets Responder
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce Copyright (C) Simo Sorce <ssorce@redhat.com> 2016
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce This program is free software; you can redistribute it and/or modify
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce it under the terms of the GNU General Public License as published by
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce the Free Software Foundation; either version 3 of the License, or
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce (at your option) any later version.
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce This program is distributed in the hope that it will be useful,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce but WITHOUT ANY WARRANTY; without even the implied warranty of
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce GNU General Public License for more details.
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce You should have received a copy of the GNU General Public License
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce along with this program. If not, see <http://www.gnu.org/licenses/>.
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce/* ##### Request Handling ##### */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorcestatic void sec_http_request_pipeline_done(struct tevent_req *subreq);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic struct tevent_req *sec_http_request_send(TALLOC_CTX *mem_ctx,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce req = tevent_req_create(mem_ctx, &state, struct sec_http_request_state);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* Go through the pipeline */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* 1. mapping and path conversion */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce ret = sec_req_routing(state, secreq, &provider_handle);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "sec_req_routing failed [%d]: %s\n", ret, sss_strerror(ret));
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* 2. backend invocation */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce tevent_req_set_callback(subreq, sec_http_request_pipeline_done, req);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorcestatic void sec_http_request_pipeline_done(struct tevent_req *subreq)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce req = tevent_req_callback_data(subreq, struct tevent_req);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* 3. reply construction */
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_LIBS, "Did not find the requested data\n");
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "sec request failed [%d]: %s\n", ret, sss_strerror(ret));
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "sec request done\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic int sec_http_request_recv(struct tevent_req *req)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce secreq = tevent_req_callback_data(req, struct sec_req_ctx);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_LIBS, "Did not find the requested data\n");
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "sec_http_request_recv failed [%d]: %s\n",
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* Always return an error if we get here */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce ret = sec_http_status_reply(secreq, &secreq->reply,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to find reply, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* Turn writable on so we can write back the reply */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce secreq = talloc_get_type(cctx->state_ctx, struct sec_req_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce req = sec_http_request_send(secreq, cctx->ev, secreq);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to schedule secret retrieval\n.");
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce tevent_req_set_callback(req, sec_http_request_done, secreq);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce/* ##### HTTP Parsing Callbacks ##### */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic void sec_append_string(TALLOC_CTX *memctx, char **dest,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce *dest = talloc_strndup_append_buffer(*dest, src, len);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic bool sec_too_much_data(struct sec_req_ctx *req, size_t length)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Request too big, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return true;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return false;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic int sec_on_message_begin(http_parser *parser)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_TRACE_INTERNAL, "HTTP Message parsing begins\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_get_type(parser->data, struct sec_req_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce sec_append_string(req, &req->request_url, at, length);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to store URL, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic int sec_on_header_field(http_parser *parser,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_get_type(parser->data, struct sec_req_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce req->headers = talloc_zero_array(req, struct sec_kvp, 10);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce } else if ((n % 10 == 0) &&
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce memset(&req->headers[n], 0, sizeof(struct sec_kvp) * 10);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to store headers, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* new field */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce sec_append_string(req->headers, &req->headers[n - 1].name, at, length);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to store header name, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic int sec_on_header_value(http_parser *parser,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_get_type(parser->data, struct sec_req_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Invalid headers pointer, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (req->headers[n].name && !req->headers[n].value) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* we increment on new value */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce sec_append_string(req->headers, &req->headers[n - 1].value, at, length);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to store header value, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic int sec_on_headers_complete(http_parser *parser)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* TODO: if message has no body we should return 1 */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_get_type(parser->data, struct sec_req_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce sec_append_string(req, &req->body.data, at, length);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to store body, aborting client!\n");
f931864f46cb19346be45f3b6f55da54c8dc7078Jakub Hrozekstatic int sec_get_parsed_field(TALLOC_CTX *mem_ctx, int field,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce *dest = talloc_strndup(mem_ctx, &source_buf[off], len);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce "Failed to parse url, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic int sec_on_message_complete(http_parser *parser)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_get_type(parser->data, struct sec_req_ctx);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* parse url as well */
f931864f46cb19346be45f3b6f55da54c8dc7078Jakub Hrozek ret = sec_get_parsed_field(req, UF_SCHEMA, &parsed,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "Failed to retrieve schema from %s\n", req->request_url);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "schema: %s\n", req->parsed_url.schema);
f931864f46cb19346be45f3b6f55da54c8dc7078Jakub Hrozek ret = sec_get_parsed_field(req, UF_HOST, &parsed,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "Failed to retrieve host from %s\n", req->request_url);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "host: %s\n", req->parsed_url.host);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "port: %d\n", req->parsed_url.port);
f931864f46cb19346be45f3b6f55da54c8dc7078Jakub Hrozek ret = sec_get_parsed_field(req, UF_PATH, &parsed,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "Failed to retrieve path from %s\n", req->request_url);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "path: %s\n", req->parsed_url.path);
f931864f46cb19346be45f3b6f55da54c8dc7078Jakub Hrozek ret = sec_get_parsed_field(req, UF_QUERY, &parsed,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "Failed to retrieve query from %s\n", req->request_url);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "query: %s\n", req->parsed_url.query);
f931864f46cb19346be45f3b6f55da54c8dc7078Jakub Hrozek ret = sec_get_parsed_field(req, UF_FRAGMENT, &parsed,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "Failed to retrieve fragment from %s\n", req->request_url);
f931864f46cb19346be45f3b6f55da54c8dc7078Jakub Hrozek ret = sec_get_parsed_field(req, UF_USERINFO, &parsed,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "Failed to retrieve userinfo from %s\n", req->request_url);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "parsing complete\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce/* ##### Communications ##### */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
db826f57b4c2ee814823057cc536386889f7aa1dPavel BĆezina DEBUG(SSSDBG_TRACE_INTERNAL, "sent %zu bytes, %zu bytes remaining\n",
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce req = talloc_get_type(cctx->state_ctx, struct sec_req_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* not all data was sent, loop again */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_FATAL_FAILURE, "Failed to send data, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* ok all sent */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "received %zu bytes\n", data->length);
109ed7ca1a82420798efdc6a9b019675a5bd0f4fJakub Hrozek struct sec_ctx *sec_ctx = talloc_get_type(cctx->rctx->pvt_ctx,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce prctx = talloc_get_type(cctx->protocol_ctx, struct sec_proto_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce req = talloc_get_type(cctx->state_ctx, struct sec_req_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* A new request comes in, setup data structures */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to setup request handlers, aborting client\n");
109ed7ca1a82420798efdc6a9b019675a5bd0f4fJakub Hrozek req->max_payload_size = sec_ctx->max_payload_size;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Client closed connection.\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Interrupted before any data could be read, retry later\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* all fine */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to receive data (%d, %s), aborting client\n",
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce len = http_parser_execute(&prctx->parser, &prctx->callbacks,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to parse request, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* do not read anymore, client is done sending */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic void sec_fd_handler(struct tevent_context *ev,
04c236ca801b0edaefe9e5553ca26126087c5d68Fabiano FidĂȘncio sss_client_fd_handler(ptr, sec_recv, sec_send, flags);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce protocol_ctx = talloc_zero(cctx, struct sec_proto_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce/* Dummy, not used here but required to link to other responder files */