a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce/*
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce SSSD
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce Secrets Responder
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce Copyright (C) Simo Sorce <ssorce@redhat.com> 2016
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
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
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
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*/
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "config.h"
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce#include "util/util.h"
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce#include "responder/common/responder.h"
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce#include "responder/secrets/secsrv.h"
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce#include "responder/secrets/secsrv_private.h"
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce/* ##### Request Handling ##### */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestruct sec_http_request_state {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct tevent_context *ev;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct sec_req_ctx *secreq;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce};
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorcestatic void sec_http_request_pipeline_done(struct tevent_req *subreq);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic struct tevent_req *sec_http_request_send(TALLOC_CTX *mem_ctx,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct tevent_context *ev,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct sec_req_ctx *secreq)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct tevent_req *req;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce struct tevent_req *subreq;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct sec_http_request_state *state;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce struct provider_handle *provider_handle;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce errno_t ret;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce req = tevent_req_create(mem_ctx, &state, struct sec_http_request_state);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (!req) return NULL;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce state->ev = ev;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce state->secreq = secreq;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* Go through the pipeline */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* 1. mapping and path conversion */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce ret = sec_req_routing(state, secreq, &provider_handle);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek if (ret) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "sec_req_routing failed [%d]: %s\n", ret, sss_strerror(ret));
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek goto done;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* 2. backend invocation */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce subreq = provider_handle->fn(state, state->ev,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce provider_handle->context, secreq);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (!subreq) {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce ret = ENOMEM;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce goto done;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce tevent_req_set_callback(subreq, sec_http_request_pipeline_done, req);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce return req;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcedone:
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (ret != EOK) {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce tevent_req_error(req, ret);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce return tevent_req_post(req, state->ev);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce}
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorcestatic void sec_http_request_pipeline_done(struct tevent_req *subreq)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce{
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce struct tevent_req *req;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce errno_t ret;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce req = tevent_req_callback_data(subreq, struct tevent_req);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* 3. reply construction */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce ret = sec_provider_recv(subreq);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek if (ret == ENOENT) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_LIBS, "Did not find the requested data\n");
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek tevent_req_error(req, ret);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek } else if (ret != EOK) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "sec request failed [%d]: %s\n", ret, sss_strerror(ret));
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce tevent_req_error(req, ret);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce } else {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "sec request done\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce tevent_req_done(req);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic int sec_http_request_recv(struct tevent_req *req)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce TEVENT_REQ_RETURN_ON_ERROR(req);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return EOK;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce/* --- */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic void
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcesec_http_request_done(struct tevent_req *req)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce struct sec_req_ctx *secreq;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce struct cli_ctx *cctx;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce int ret;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce secreq = tevent_req_callback_data(req, struct sec_req_ctx);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce cctx = secreq->cctx;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce ret = sec_http_request_recv(req);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (ret != EOK) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek if (ret == ENOENT) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_LIBS, "Did not find the requested data\n");
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek } else {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "sec_http_request_recv failed [%d]: %s\n",
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek ret, sss_strerror(ret));
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* Always return an error if we get here */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce ret = sec_http_status_reply(secreq, &secreq->reply,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce sec_errno_to_http_status(ret));
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (ret != EOK) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_FATAL_FAILURE,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to find reply, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_free(cctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* Turn writable on so we can write back the reply */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce TEVENT_FD_WRITEABLE(cctx->cfde);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic void sec_cmd_execute(struct cli_ctx *cctx)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct sec_req_ctx *secreq;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct tevent_req *req;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce secreq = talloc_get_type(cctx->state_ctx, struct sec_req_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce req = sec_http_request_send(secreq, cctx->ev, secreq);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (!req) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to schedule secret retrieval\n.");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_free(cctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce tevent_req_set_callback(req, sec_http_request_done, secreq);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce/* ##### HTTP Parsing Callbacks ##### */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic void sec_append_string(TALLOC_CTX *memctx, char **dest,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce const char *src, size_t len)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (*dest) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce *dest = talloc_strndup_append_buffer(*dest, src, len);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce } else {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce *dest = talloc_strndup(memctx, src, len);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic bool sec_too_much_data(struct sec_req_ctx *req, size_t length)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce req->total_size += length;
109ed7ca1a82420798efdc6a9b019675a5bd0f4fJakub Hrozek if (req->max_payload_size > 0
109ed7ca1a82420798efdc6a9b019675a5bd0f4fJakub Hrozek && req->total_size > req->max_payload_size) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_FATAL_FAILURE,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Request too big, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return true;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return false;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic int sec_on_message_begin(http_parser *parser)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_TRACE_INTERNAL, "HTTP Message parsing begins\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return 0;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic int sec_on_url(http_parser *parser,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce const char *at, size_t length)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct sec_req_ctx *req =
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_get_type(parser->data, struct sec_req_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (sec_too_much_data(req, length)) return -1;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce sec_append_string(req, &req->request_url, at, length);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (!req->request_url) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_FATAL_FAILURE,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to store URL, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return -1;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return 0;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic int sec_on_header_field(http_parser *parser,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce const char *at, size_t length)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct sec_req_ctx *req =
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_get_type(parser->data, struct sec_req_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce int n = req->num_headers;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (sec_too_much_data(req, length)) return -1;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (!req->headers) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce req->headers = talloc_zero_array(req, struct sec_kvp, 10);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce } else if ((n % 10 == 0) &&
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce (req->headers[n - 1].value)) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce req->headers = talloc_realloc(req, req->headers,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct sec_kvp, n + 10);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (req->headers) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce memset(&req->headers[n], 0, sizeof(struct sec_kvp) * 10);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (!req->headers) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_FATAL_FAILURE,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to store headers, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return -1;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (!n || req->headers[n - 1].value) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* new field */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce n++;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce sec_append_string(req->headers, &req->headers[n - 1].name, at, length);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (!req->headers[n - 1].name) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_FATAL_FAILURE,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to store header name, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return -1;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return 0;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic int sec_on_header_value(http_parser *parser,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce const char *at, size_t length)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct sec_req_ctx *req =
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_get_type(parser->data, struct sec_req_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce int n = req->num_headers;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (sec_too_much_data(req, length)) return -1;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (!req->headers) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_FATAL_FAILURE,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Invalid headers pointer, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return -1;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (req->headers[n].name && !req->headers[n].value) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* we increment on new value */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce n = ++req->num_headers;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce sec_append_string(req->headers, &req->headers[n - 1].value, at, length);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (!req->headers[n - 1].value) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_FATAL_FAILURE,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to store header value, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return -1;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return 0;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic int sec_on_headers_complete(http_parser *parser)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* TODO: if message has no body we should return 1 */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return 0;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic int sec_on_body(http_parser *parser,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce const char *at, size_t length)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct sec_req_ctx *req =
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_get_type(parser->data, struct sec_req_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (sec_too_much_data(req, length)) return -1;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce sec_append_string(req, &req->body.data, at, length);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (!req->body.data) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_FATAL_FAILURE,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to store body, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return -1;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce req->body.length += length;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return 0;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
f931864f46cb19346be45f3b6f55da54c8dc7078Jakub Hrozekstatic int sec_get_parsed_field(TALLOC_CTX *mem_ctx, int field,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce struct http_parser_url *parsed,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce char *source_buf,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce char **dest)
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce{
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce uint16_t off = parsed->field_data[field].off;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce uint16_t len = parsed->field_data[field].len;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce *dest = talloc_strndup(mem_ctx, &source_buf[off], len);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (!*dest) {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce DEBUG(SSSDBG_FATAL_FAILURE,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce "Failed to parse url, aborting client!\n");
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce return ENOMEM;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce return EOK;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce}
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic int sec_on_message_complete(http_parser *parser)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct sec_req_ctx *req =
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_get_type(parser->data, struct sec_req_ctx);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce struct http_parser_url parsed;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce int ret;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* parse url as well */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce ret = http_parser_parse_url(req->request_url,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce strlen(req->request_url),
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce 0, &parsed);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek if (ret) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "Failed to parse URL %s\n", req->request_url);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek return ret;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (parsed.field_set & (1 << UF_SCHEMA)) {
f931864f46cb19346be45f3b6f55da54c8dc7078Jakub Hrozek ret = sec_get_parsed_field(req, UF_SCHEMA, &parsed,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce req->request_url,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce &req->parsed_url.schema);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek if (ret) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "Failed to retrieve schema from %s\n", req->request_url);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek return -1;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek }
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "schema: %s\n", req->parsed_url.schema);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (parsed.field_set & (1 << UF_HOST)) {
f931864f46cb19346be45f3b6f55da54c8dc7078Jakub Hrozek ret = sec_get_parsed_field(req, UF_HOST, &parsed,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce req->request_url,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce &req->parsed_url.host);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek if (ret) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "Failed to retrieve host from %s\n", req->request_url);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek return -1;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek }
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "host: %s\n", req->parsed_url.host);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (parsed.field_set & (1 << UF_PORT)) {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce req->parsed_url.port = parsed.port;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "port: %d\n", req->parsed_url.port);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (parsed.field_set & (1 << UF_PATH)) {
f931864f46cb19346be45f3b6f55da54c8dc7078Jakub Hrozek ret = sec_get_parsed_field(req, UF_PATH, &parsed,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce req->request_url,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce &req->parsed_url.path);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek if (ret) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "Failed to retrieve path from %s\n", req->request_url);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek return -1;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek }
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "path: %s\n", req->parsed_url.path);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (parsed.field_set & (1 << UF_QUERY)) {
f931864f46cb19346be45f3b6f55da54c8dc7078Jakub Hrozek ret = sec_get_parsed_field(req, UF_QUERY, &parsed,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce req->request_url,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce &req->parsed_url.query);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek if (ret) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "Failed to retrieve query from %s\n", req->request_url);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek return -1;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek }
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "query: %s\n", req->parsed_url.query);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (parsed.field_set & (1 << UF_FRAGMENT)) {
f931864f46cb19346be45f3b6f55da54c8dc7078Jakub Hrozek ret = sec_get_parsed_field(req, UF_FRAGMENT, &parsed,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce req->request_url,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce &req->parsed_url.fragment);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek if (ret) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "Failed to retrieve fragment from %s\n", req->request_url);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek return -1;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek }
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "fragment: %s\n", req->parsed_url.fragment);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce if (parsed.field_set & (1 << UF_USERINFO)) {
f931864f46cb19346be45f3b6f55da54c8dc7078Jakub Hrozek ret = sec_get_parsed_field(req, UF_USERINFO, &parsed,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce req->request_url,
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce &req->parsed_url.userinfo);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek if (ret) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "Failed to retrieve userinfo from %s\n", req->request_url);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek return -1;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek }
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "userinfo: %s\n", req->parsed_url.userinfo);
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce req->method = parser->method;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce req->complete = true;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "parsing complete\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return 0;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce/* ##### Communications ##### */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorceint sec_send_data(int fd, struct sec_data *data)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce ssize_t len;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek errno_t ret;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce errno = 0;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce len = send(fd, data->data, data->length, 0);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (len == -1) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return EAGAIN;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce } else {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek ret = errno;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "send failed [%d]: %s\n", ret, strerror(ret));
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek return ret;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (len == 0) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return EIO;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce data->length -= len;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce data->data += len;
db826f57b4c2ee814823057cc536386889f7aa1dPavel Bƙezina DEBUG(SSSDBG_TRACE_INTERNAL, "sent %zu bytes, %zu bytes remaining\n",
db826f57b4c2ee814823057cc536386889f7aa1dPavel Bƙezina len, data->length);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return EOK;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic void sec_send(struct cli_ctx *cctx)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct sec_req_ctx *req;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce int ret;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce req = talloc_get_type(cctx->state_ctx, struct sec_req_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce ret = sec_send_data(cctx->cfd, &req->reply);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (ret == EAGAIN) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* not all data was sent, loop again */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (ret != EOK) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_FATAL_FAILURE, "Failed to send data, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_free(cctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* ok all sent */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce TEVENT_FD_NOT_WRITEABLE(cctx->cfde);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce TEVENT_FD_READABLE(cctx->cfde);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_zfree(cctx->state_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorceint sec_recv_data(int fd, struct sec_data *data)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce ssize_t len;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek errno_t ret;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce errno = 0;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce len = recv(fd, data->data, data->length, 0);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (len == -1) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return EAGAIN;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce } else {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek ret = errno;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "send failed [%d]: %s\n", ret, strerror(ret));
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek return ret;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (len == 0) {
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce data->length = 0;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return ENODATA;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce data->length = len;
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "received %zu bytes\n", data->length);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return EOK;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic void sec_recv(struct cli_ctx *cctx)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct sec_proto_ctx *prctx;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct sec_req_ctx *req;
109ed7ca1a82420798efdc6a9b019675a5bd0f4fJakub Hrozek struct sec_ctx *sec_ctx = talloc_get_type(cctx->rctx->pvt_ctx,
109ed7ca1a82420798efdc6a9b019675a5bd0f4fJakub Hrozek struct sec_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce char buffer[SEC_PACKET_MAX_RECV_SIZE];
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct sec_data data = { buffer,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce SEC_PACKET_MAX_RECV_SIZE };
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce size_t len;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce int ret;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
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 if (!req) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* A new request comes in, setup data structures */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce req = talloc_zero(cctx, struct sec_req_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (!req) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_FATAL_FAILURE,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to setup request handlers, aborting client\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_free(cctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce req->cctx = cctx;
109ed7ca1a82420798efdc6a9b019675a5bd0f4fJakub Hrozek req->max_payload_size = sec_ctx->max_payload_size;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce cctx->state_ctx = req;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce http_parser_init(&prctx->parser, HTTP_REQUEST);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce prctx->parser.data = req;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce ret = sec_recv_data(cctx->cfd, &data);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce switch (ret) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce case ENODATA:
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_TRACE_ALL,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Client closed connection.\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_free(cctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce case EAGAIN:
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_TRACE_ALL,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Interrupted before any data could be read, retry later\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce case EOK:
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* all fine */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce break;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce default:
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_FATAL_FAILURE,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to receive data (%d, %s), aborting client\n",
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce ret, sss_strerror(ret));
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_free(cctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce len = http_parser_execute(&prctx->parser, &prctx->callbacks,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce data.data, data.length);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (len != data.length) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce DEBUG(SSSDBG_FATAL_FAILURE,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce "Failed to parse request, aborting client!\n");
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce talloc_free(cctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (!req->complete) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* do not read anymore, client is done sending */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce TEVENT_FD_NOT_READABLE(cctx->cfde);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce sec_cmd_execute(cctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic void sec_fd_handler(struct tevent_context *ev,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct tevent_fd *fde,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce uint16_t flags, void *ptr)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
04c236ca801b0edaefe9e5553ca26126087c5d68Fabiano FidĂȘncio sss_client_fd_handler(ptr, sec_recv, sec_send, flags);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestatic http_parser_settings sec_callbacks = {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce .on_message_begin = sec_on_message_begin,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce .on_url = sec_on_url,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce .on_header_field = sec_on_header_field,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce .on_header_value = sec_on_header_value,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce .on_headers_complete = sec_on_headers_complete,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce .on_body = sec_on_body,
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce .on_message_complete = sec_on_message_complete
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce};
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorceint sec_connection_setup(struct cli_ctx *cctx)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct sec_proto_ctx *protocol_ctx;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce protocol_ctx = talloc_zero(cctx, struct sec_proto_ctx);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (!protocol_ctx) return ENOMEM;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce protocol_ctx->callbacks = sec_callbacks;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce cctx->protocol_ctx = protocol_ctx;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce cctx->cfd_handler = sec_fd_handler;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return EOK;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce/* Dummy, not used here but required to link to other responder files */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorcestruct cli_protocol_version *register_cli_protocol_version(void)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return NULL;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce}