8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce Secrets Responder
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce Copyright (C) Simo Sorce <ssorce@redhat.com> 2016
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce This program is free software; you can redistribute it and/or modify
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce it under the terms of the GNU General Public License as published by
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce the Free Software Foundation; either version 3 of the License, or
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce (at your option) any later version.
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce This program is distributed in the hope that it will be useful,
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce but WITHOUT ANY WARRANTY; without even the implied warranty of
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce GNU General Public License for more details.
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce You should have received a copy of the GNU General Public License
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce along with this program. If not, see <http://www.gnu.org/licenses/>.
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorcestatic int proxy_get_config_string(struct proxy_context *pctx,
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce if (not_null && (ret == 0) && (*value == NULL)) ret = EINVAL;
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorcestatic int proxy_sec_get_cfg(struct proxy_context *pctx,
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce /* find matching remote and build the URI */
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce ret = proxy_get_config_string(pctx, cfg, true, secreq,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_CONF_SETTINGS, "proxy_url: %s\n", cfg->url);
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce ret = proxy_get_config_string(pctx, cfg, false, secreq,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_CONF_SETTINGS, "auth_type: %s\n", auth_type);
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce ret = proxy_get_config_string(pctx, cfg, true, secreq, "username",
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce ret = proxy_get_config_string(pctx, cfg, true, secreq, "password",
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce ret = proxy_get_config_string(pctx, cfg, true, secreq,
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce "auth_header_name",
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "auth_header_name: %s\n", cfg->auth.basic.username);
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce ret = proxy_get_config_string(pctx, cfg, true, secreq,
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce "auth_header_value",
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Unknown auth type!\n");
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina ret = confdb_get_bool(pctx->cdb, secreq->cfg_section, "verify_peer",
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina DEBUG(SSSDBG_CONF_SETTINGS, "verify_peer: %s\n",
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina ret = confdb_get_bool(pctx->cdb, secreq->cfg_section, "verify_host",
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina DEBUG(SSSDBG_CONF_SETTINGS, "verify_host: %s\n",
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina ret = proxy_get_config_string(pctx, cfg, false, secreq,
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina DEBUG(SSSDBG_CONF_SETTINGS, "capath: %s\n", cfg->capath);
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina ret = proxy_get_config_string(pctx, cfg, false, secreq,
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina DEBUG(SSSDBG_CONF_SETTINGS, "cacert: %s\n", cfg->cacert);
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina ret = proxy_get_config_string(pctx, cfg, false, secreq,
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina DEBUG(SSSDBG_CONF_SETTINGS, "cert: %s\n", cfg->cert);
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina ret = proxy_get_config_string(pctx, cfg, false, secreq,
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina DEBUG(SSSDBG_CONF_SETTINGS, "key: %s\n", cfg->key);
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce ret = confdb_get_string_as_list(pctx->cdb, cfg, secreq->cfg_section,
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce while (cfg->fwd_headers && cfg->fwd_headers[cfg->num_headers]) {
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "Forwarding header: %s\n", cfg->fwd_headers[cfg->num_headers]);
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce /* Always whitelist Content-Type and Content-Length */
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce cfg->fwd_headers = talloc_realloc(cfg, cfg->fwd_headers, char *,
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce cfg->fwd_headers[cfg->num_headers] = talloc_strdup(cfg, "Content-Type");
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce cfg->fwd_headers[cfg->num_headers] = talloc_strdup(cfg, "Content-Length");
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce#define REQ_HAS_SCHEMA(secreq) ((secreq)->parsed_url.schema != NULL)
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce#define REQ_HAS_HOST(secreq) ((secreq)->parsed_url.host != NULL)
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce#define REQ_HAS_PORT(secreq) ((secreq)->parsed_url.port != 0)
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce#define REQ_HAS_PATH(secreq) ((secreq)->parsed_url.path != NULL)
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce#define REQ_HAS_QUERY(secreq) ((secreq)->parsed_url.query != NULL)
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce#define REQ_HAS_FRAGMENT(secreq) ((secreq)->parsed_url.fragment != NULL)
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce#define REQ_HAS_USERINFO(secreq) ((secreq)->parsed_url.userinfo != NULL)
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce#define SECREQ_HAS_PORT(secreq) ((secreq)->parsed_url.port != 0)
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce#define SECREQ_PORT(secreq) ((secreq)->parsed_url.port)
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce#define SECREQ_HAS_PART(secreq, part) ((secreq)->parsed_url.part != NULL)
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce ((secreq)->parsed_url.part ? (secreq)->parsed_url.part : "")
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorceint proxy_sec_map_url(TALLOC_CTX *mem_ctx, struct sec_req_ctx *secreq,
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce ret = snprintf(port, 6, "%d", SECREQ_PORT(secreq));
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "snprintf failed\n");
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce url = talloc_asprintf(mem_ctx, "%s%s%s%s%s%s%s%s/%s%s%s%s%s",
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "URL: %s\n", url);
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březinastatic errno_t proxy_http_append_header(TALLOC_CTX *mem_ctx,
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina const char ***_headers,
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina headers = talloc_realloc(mem_ctx, headers, const char *,
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina headers[num_headers - 1] = talloc_asprintf(headers, "%s: %s", name, value);
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březinastatic const char **
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory!\n");
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina headers = talloc_zero_array(tmp_ctx, const char *, 1);
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina if (strcasecmp(secreq->headers[i].name, pcfg->fwd_headers[j]) == 0) {
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina DEBUG(SSSDBG_TRACE_LIBS, "Forwarding header %s: %s\n",
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina secreq->headers[i].name, secreq->headers[i].value);
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina ret = proxy_http_append_header(tmp_ctx, secreq->headers[i].name,
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina DEBUG(SSSDBG_TRACE_LIBS, "Forwarding header %s\n",
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina ret = proxy_http_append_header(tmp_ctx, pcfg->auth.header.name,
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březinastatic errno_t proxy_http_create_request(TALLOC_CTX *mem_ctx,
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina const char *url,
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory!\n");
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina headers = proxy_http_create_headers(tmp_ctx, secreq, pcfg);
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Unable to construct HTTP headers!\n");
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina body = sss_iobuf_init_readonly(tmp_ctx, (uint8_t *)secreq->body.data,
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create HTTP body!\n");
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected HTTP method: %d\n",
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina tcurl_req = tcurl_http(tmp_ctx, method, NULL, url, headers, body);
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create TCURL request!\n");
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina /* TCURL will return response buffer also with headers. */
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina /* Set TLS settings to verify peer.
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina * This has no effect for HTTP protocol so we can set it anyway. */
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina ret = tcurl_req_verify_peer(tcurl_req, pcfg->capath, pcfg->cacert,
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina /* Set client's certificate if required. */
720e1a5b95a953a0f1c8315bbb7c9c1edf9fb417Pavel Březina ret = tcurl_req_set_client_cert(tcurl_req, pcfg->cert, pcfg->key);
af026ea6a6e812b7d6c5c889dda64ba7b7c433eePavel Březina /* Set basic authentication if required. */
af026ea6a6e812b7d6c5c889dda64ba7b7c433eePavel Březina ret = tcurl_req_http_basic_auth(tcurl_req, pcfg->auth.basic.username,
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina *_tcurl_req = talloc_steal(mem_ctx, tcurl_req);
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorcestatic void proxy_secret_req_done(struct tevent_req *subreq);
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorcestruct tevent_req *proxy_secret_req(TALLOC_CTX *mem_ctx,
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce req = tevent_req_create(mem_ctx, &state, struct proxy_secret_state);
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce pctx = talloc_get_type(provider_ctx, struct proxy_context);
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce ret = proxy_sec_get_cfg(pctx, state, state->secreq, &state->pcfg);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "proxy_sec_get_cfg failed [%d]: %s\n", ret, sss_strerror(ret));
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce ret = proxy_sec_map_url(state, secreq, state->pcfg, &http_uri);
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "proxy_sec_map_url failed [%d]: %s\n", ret, sss_strerror(ret));
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce ret = proxy_http_create_request(state, state->secreq, state->pcfg,
7128fadade544efcd86b113a5090b00d20993671Jakub Hrozek "proxy_http_create_request failed [%d]: %s\n",
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina subreq = tcurl_request_send(mem_ctx, ev, pctx->tcurl, tcurl_req,
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce tevent_req_set_callback(subreq, proxy_secret_req_done, req);
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce /* shortcircuit the request here as all called functions are
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce * synchronous and final and no further subrequests have been
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce * made if we get here */
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorcestatic void proxy_secret_req_done(struct tevent_req *subreq)
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce req = tevent_req_callback_data(subreq, struct tevent_req);
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce state = tevent_req_data(req, struct proxy_secret_state);
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina ret = tcurl_request_recv(state, subreq, &response, &http_code);
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina DEBUG(SSSDBG_OP_FAILURE, "proxy_http request failed [%d]: %s\n",
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina ret = sec_http_reply_iobuf(state->secreq, &state->secreq->reply,
df99d709c8cbef3c378c111944d83b7345e4c1eaPavel Březina "sec_http_reply_iobuf request failed [%d]: %s\n",
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorceint proxy_secrets_provider_handle(struct sec_ctx *sctx,
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce handle = talloc_zero(sctx, struct provider_handle);