ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek/*
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek SSSD
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek libcurl tevent integration
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek Copyright (C) Red Hat, 2016
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek This program is free software; you can redistribute it and/or modify
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek it under the terms of the GNU General Public License as published by
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek the Free Software Foundation; either version 3 of the License, or
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek (at your option) any later version.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek This program is distributed in the hope that it will be useful,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek but WITHOUT ANY WARRANTY; without even the implied warranty of
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek GNU General Public License for more details.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek You should have received a copy of the GNU General Public License
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek along with this program. If not, see <http://www.gnu.org/licenses/>.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek*/
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <stdio.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <string.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <stdlib.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <sys/time.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <unistd.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <errno.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <talloc.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <tevent.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <curl/curl.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include "util/util.h"
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include "util/tev_curl.h"
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina#define TCURL_IOBUF_CHUNK 1024
b09cd3072153663bfcce902633b5e6f9134e72e0Fabiano Fidêncio/* This limit in the same one as KCM_REPLY_MAX */
b09cd3072153663bfcce902633b5e6f9134e72e0Fabiano Fidêncio#define TCURL_IOBUF_MAX 10*1024*1024
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic bool global_is_curl_initialized;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek/**
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * @brief The main structure of the tcurl module.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek *
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * Use tcurl_init() to initialize it, then pass to the request.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * Should be kept opaque in the future.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek *
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * @see tcurl_init()
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstruct tcurl_ctx {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_context *ev;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* See where we set CURLMOPT_TIMERFUNCTION */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_timer *process_timer;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* Since we want the API to be non-blocking, all the transfers use
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * the curl's multi interface:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * https://ec.haxx.se/libcurl-drive-multi.html
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * and then each transfer also uses an easy interface instance for
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * the transfer's private data
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLM *multi_handle;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek};
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek/**
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * @brief A tevent wrapper around curl socket
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstruct tcurl_sock {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_ctx *tctx; /* Backchannel to the main context */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
a02a5ed51178b2cbede0396d66aed716b8898096René Genz curl_socket_t sockfd; /* curl socket is an int typedef on UNIX */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_fd *fde; /* tevent tracker of the fd events */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek};
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinastatic void tcurl_request_done(struct tevent_req *req,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina errno_t process_error,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina int response_code);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic errno_t curl_code2errno(CURLcode crv)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek switch (crv) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* HTTP error does not fail the whole request, just returns the error
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * separately
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURLE_HTTP_RETURNED_ERROR:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURLE_OK:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EOK;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURLE_URL_MALFORMAT:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EBADMSG;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURLE_COULDNT_CONNECT:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EHOSTUNREACH;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURLE_REMOTE_ACCESS_DENIED:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EACCES;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURLE_OUT_OF_MEMORY:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return ENOMEM;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURLE_OPERATION_TIMEDOUT:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return ETIMEDOUT;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLE_SSL_ISSUER_ERROR:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLE_SSL_CACERT_BADFILE:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLE_SSL_CACERT:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLE_SSL_CERTPROBLEM:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return ERR_INVALID_CERT;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLE_SSL_CRL_BADFILE:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLE_SSL_SHUTDOWN_FAILED:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLE_SSL_ENGINE_INITFAILED:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLE_USE_SSL_FAILED:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLE_SSL_CIPHER:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLE_SSL_ENGINE_SETFAILED:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLE_SSL_ENGINE_NOTFOUND:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLE_SSL_CONNECT_ERROR:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return ERR_SSL_FAILURE;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLE_PEER_FAILED_VERIFICATION:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return ERR_UNABLE_TO_VERIFY_PEER;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLE_COULDNT_RESOLVE_HOST:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return ERR_UNABLE_TO_RESOLVE_HOST;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina default:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina break;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return EIO;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina}
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinastatic errno_t curlm_code2errno(CURLcode crv)
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina{
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina switch (crv) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLM_OK:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return EOK;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLM_BAD_SOCKET:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return EPIPE;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLM_OUT_OF_MEMORY:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return ENOMEM;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLM_BAD_HANDLE:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLM_BAD_EASY_HANDLE:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLM_UNKNOWN_OPTION:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return EINVAL;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case CURLM_INTERNAL_ERROR:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return ERR_INTERNAL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek default:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic errno_t tcurl_global_init(void)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek errno_t ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (global_is_curl_initialized == false) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret = curl_global_init(CURL_GLOBAL_ALL);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Cannot initialize global curl options [%d]\n", ret);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek global_is_curl_initialized = true;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EOK;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic int curl2tev_flags(int curlflags)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int flags = 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek switch (curlflags) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURL_POLL_IN:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek flags |= TEVENT_FD_READ;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURL_POLL_OUT:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek flags |= TEVENT_FD_WRITE;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURL_POLL_INOUT:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek flags |= (TEVENT_FD_READ | TEVENT_FD_WRITE);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return flags;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic void handle_curlmsg_done(CURLMsg *message)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURL *easy_handle;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLcode crv;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_req *req;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina long response_code = 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek char *done_url;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek errno_t ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek easy_handle = message->easy_handle;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (easy_handle == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "BUG: NULL handle for message %p\n", message);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (DEBUG_IS_SET(SSSDBG_TRACE_FUNC)) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_getinfo(easy_handle, CURLINFO_EFFECTIVE_URL, &done_url);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_MINOR_FAILURE, "Cannot get CURLINFO_EFFECTIVE_URL "
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina "[%d]: %s\n", crv, curl_easy_strerror(crv));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* not fatal since we need this only for debugging */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek } else {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_TRACE_FUNC, "Handled %s\n", done_url);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_getinfo(easy_handle, CURLINFO_PRIVATE, (void *) &req);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Cannot get CURLINFO_PRIVATE [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv, curl_easy_strerror(crv));
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = curl_code2errno(crv);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret = curl_code2errno(message->data.result);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_OP_FAILURE, "CURL operation failed [%d]: %s\n",
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret, sss_strerror(ret));
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina /* If there was no fatal error, let's read the response code
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina * and mark the request as done */
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina crv = curl_easy_getinfo(easy_handle, CURLINFO_RESPONSE_CODE, &response_code);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_OP_FAILURE, "Cannot get response code\n");
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = curl_code2errno(crv);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = EOK;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinadone:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tcurl_request_done(req, ret, response_code);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic void process_curl_activity(struct tcurl_ctx *tctx)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLMsg *message;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int pending;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek while ((message = curl_multi_info_read(tctx->multi_handle, &pending))) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek switch (message->msg) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURLMSG_DONE:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek handle_curlmsg_done(message);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek default:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_TRACE_LIBS,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "noop for curl msg %d\n", message->msg);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic void tcurlsock_input_available(struct tevent_context *ev,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_fd *fde,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek uint16_t flags,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek void *data)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_ctx *tctx;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_sock *tcs = NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int curl_flags = 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int running_handles;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcs = talloc_get_type(data, struct tcurl_sock);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tcs == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (flags & TEVENT_FD_READ) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_flags |= CURL_CSELECT_IN;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (flags & TEVENT_FD_WRITE) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_flags |= CURL_CSELECT_OUT;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* multi_socket_action might invalidate tcs when the transfer ends,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * so we need to store tctx separately
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tctx = tcs->tctx;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* https://ec.haxx.se/libcurl-drive-multi-socket.html */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_multi_socket_action(tcs->tctx->multi_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcs->sockfd,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_flags,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek &running_handles);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek process_curl_activity(tctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek/**
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * @brief Registers a curl's socket with tevent
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek *
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * Creates a private structure, registers the socket with tevent and finally
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * registers the tcurl_sock structure as a private pointer for the curl
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * socket for later
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic struct tcurl_sock *register_curl_socket(struct tcurl_ctx *tctx,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_socket_t sockfd,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int flags)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_sock *tcs;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcs = talloc_zero(tctx, struct tcurl_sock);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tcs == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcs->sockfd = sockfd;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcs->tctx = tctx;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcs->fde = tevent_add_fd(tctx->ev, tcs, sockfd, flags,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcurlsock_input_available, tcs);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tcs->fde == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek talloc_free(tcs);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_multi_assign(tctx->multi_handle, sockfd, (void *) tcs);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return tcs;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek/* libcurl informs the application about socket activity to wait for with
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * this callback */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic int handle_socket(CURL *easy,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_socket_t s,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int action,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek void *userp,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek void *socketp)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_ctx *tctx = NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_sock *tcsock;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int flags = 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tctx = talloc_get_type(userp, struct tcurl_ctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tctx == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 1;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Activity on curl socket %d socket data %p\n", s, socketp);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek switch (action) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURL_POLL_IN:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURL_POLL_OUT:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURL_POLL_INOUT:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* There is some activity on a socket */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek flags = curl2tev_flags(action);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (socketp == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* If this socket doesn't have private data, it must be a new one,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * let's start tracking it with tevent
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcsock = register_curl_socket(tctx, s, flags);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tcsock == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 1;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek } else {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* If we are already tracking this socket, just set the correct
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * flags for tevent and pass the control to tevent
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcsock = talloc_get_type(socketp, struct tcurl_sock);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tcsock == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "BUG: No private data for socket %d\n", s);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 1;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tevent_fd_set_flags(tcsock->fde, flags);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURL_POLL_REMOVE:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* This socket is being closed by curl, so we need to.. */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcsock = talloc_get_type(socketp, struct tcurl_sock);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tcsock == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "BUG: Trying to remove an untracked socket %d\n", s);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* ..stop tracking the socket with the multi handle.. */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_multi_assign(tctx->multi_handle, s, NULL);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* ..and stop tracking the fd with tevent */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek talloc_free(tcsock);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek default:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 1;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic void check_curl_timeouts(struct tcurl_ctx *tctx)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int running_handles;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_multi_socket_action(tctx->multi_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURL_SOCKET_TIMEOUT,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek 0,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek &running_handles);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_TRACE_ALL,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Still tracking %d outstanding requests\n", running_handles);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* https://ec.haxx.se/libcurl-drive-multi-socket.html */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek process_curl_activity(tctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic void check_fd_activity(struct tevent_context *ev,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_timer *te,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct timeval current_time,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek void *private_data)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_ctx *tctx = talloc_get_type(private_data, struct tcurl_ctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek check_curl_timeouts(tctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic int schedule_fd_processing(CURLM *multi,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek long timeout_ms,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek void *userp)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct timeval tv = { 0, 0 };
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_ctx *tctx = talloc_get_type(userp, struct tcurl_ctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "timeout_ms: %ld\n", timeout_ms);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (timeout_ms == -1) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* man curlmopt_timerfunction(3) says:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * A timeout_ms value of -1 means you should delete your timer.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek talloc_zfree(tctx->process_timer);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek check_curl_timeouts(tctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tv = tevent_timeval_current_ofs(0, timeout_ms * 1000);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* There is only one timer per multi handle, so it makes sense to cancel
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * the previous one.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek *
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * From https://ec.haxx.se/libcurl-drive-multi-socket.html:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * There is only one timeout for the application to handle for the
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * entire multi handle, no matter how many individual easy handles
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * that have been added or transfers that are in progress. The timer
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * callback will be updated with the current nearest-in-time period to
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * wait.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek talloc_zfree(tctx->process_timer);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tctx->process_timer = tevent_add_timer(tctx->ev, tctx, tv,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek check_fd_activity, tctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tctx->process_timer == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return -1;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic int tcurl_ctx_destroy(struct tcurl_ctx *ctx)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ctx == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_multi_cleanup(ctx->multi_handle);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstruct tcurl_ctx *tcurl_init(TALLOC_CTX *mem_ctx,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_context *ev)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek errno_t ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_ctx *tctx = NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLMcode cmret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* Per the manpage it is safe to call the initialization multiple
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * times, as long as this is done before any other curl calls to
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * make sure we don't mangle the global curl environment
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret = tcurl_global_init();
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != EOK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek goto fail;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tctx = talloc_zero(mem_ctx, struct tcurl_ctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tctx == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek goto fail;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tctx->ev = ev;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tctx->multi_handle = curl_multi_init();
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tctx->multi_handle == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek goto fail;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek talloc_set_destructor(tctx, tcurl_ctx_destroy);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek cmret = curl_multi_setopt(tctx->multi_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLMOPT_SOCKETDATA, tctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (cmret != CURLM_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Cannot set CURLMOPT_SOCKETDATA [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek cmret, curl_multi_strerror(cmret));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek goto fail;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /*
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * When there is some activity on a socket associated with the multi
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * handle, then the handle_socket() function will be called with the
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * global context as private data
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek cmret = curl_multi_setopt(tctx->multi_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLMOPT_SOCKETFUNCTION, handle_socket);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (cmret != CURLM_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Cannot set CURLMOPT_SOCKETFUNCTION [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek cmret, curl_multi_strerror(cmret));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek goto fail;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* When integrated in a mainloop, the curl multi interface must
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * kick off the communication in another eventloop tick. Similar
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * to the handle_socet function, the tcurl context is passed in
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * as private data
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek cmret = curl_multi_setopt(tctx->multi_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLMOPT_TIMERFUNCTION, schedule_fd_processing);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (cmret != CURLM_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Cannot set CURLMOPT_TIMERFUNCTION [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek cmret, curl_multi_strerror(cmret));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek goto fail;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek cmret = curl_multi_setopt(tctx->multi_handle, CURLMOPT_TIMERDATA, tctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (cmret != CURLM_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Cannot set CURLMOPT_TIMERDATA [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek cmret, curl_multi_strerror(cmret));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return tctx;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekfail:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek talloc_free(tctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina#define tcurl_set_option(tcurl_req, option, value) \
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina({ \
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina CURLcode __curl_code; \
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina errno_t __ret; \
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina \
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina __curl_code = curl_easy_setopt((tcurl_req)->curl_easy_handle, \
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina (option), (value)); \
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (__curl_code == CURLE_OK) { \
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina __ret = EOK; \
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina } else { \
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_OP_FAILURE, "Failed to set CURL option %s [%d]: %s\n", \
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina #option, __curl_code, curl_easy_strerror(__curl_code)); \
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina __ret = curl_code2errno(__curl_code); \
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina } \
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina __ret; \
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina})
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinastatic size_t tcurl_write_data(char *ptr,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina size_t size,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina size_t nmemb,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina void *userdata)
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina{
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina errno_t ret;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina size_t realsize = size * nmemb;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct sss_iobuf *outbuf;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina outbuf = talloc_get_type(userdata, struct sss_iobuf);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_TRACE_INTERNAL, "---> begin libcurl data\n");
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_TRACE_INTERNAL, "%s\n", ptr);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_TRACE_INTERNAL, "<--- end libcurl data\n");
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = sss_iobuf_write_len(outbuf, (uint8_t *)ptr, realsize);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Failed to write data to buffer [%d]: %s\n",
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret, sss_strerror(ret));
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina /* zero signifies an EOF */
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return 0;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return realsize;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinastatic size_t tcurl_read_data(void *ptr,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina size_t size,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina size_t nmemb,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina void *userdata)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek errno_t ret;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina size_t readbytes;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct sss_iobuf *inbuf;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina inbuf = talloc_get_type(userdata, struct sss_iobuf);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (inbuf == NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return CURL_READFUNC_ABORT;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = sss_iobuf_read(inbuf, size * nmemb, ptr, &readbytes);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return CURL_READFUNC_ABORT;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return readbytes;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina}
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinastruct tcurl_request {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina CURL *curl_easy_handle;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct sss_iobuf *body;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct curl_slist *headers;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina const char *url;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina const char *socket;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina /* Associated tcurl context if this request is in progress. */
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct tcurl_ctx *tcurl_ctx;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina};
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinastruct tcurl_request_state {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct tcurl_request *tcurl_req;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct sss_iobuf *response;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina int response_code;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina};
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinastruct tevent_req *
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinatcurl_request_send(TALLOC_CTX *mem_ctx,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct tevent_context *ev,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct tcurl_ctx *tcurl_ctx,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct tcurl_request *tcurl_req,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina long int timeout)
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina{
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct tcurl_request_state *state;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_req *req;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina CURLMcode curl_code;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina errno_t ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina req = tevent_req_create(mem_ctx, &state, struct tcurl_request_state);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (req == NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_TRACE_FUNC, "Sending TCURL request for %s, at socket %s\n",
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tcurl_req->url == NULL ? "<none>" : tcurl_req->url,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tcurl_req->socket == NULL ? "<none>" : tcurl_req->socket);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina state->tcurl_req = talloc_steal(state, tcurl_req);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina state->response = sss_iobuf_init_empty(state, TCURL_IOBUF_CHUNK, TCURL_IOBUF_MAX);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (state->response == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret = ENOMEM;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_PRIVATE, req);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_TIMEOUT, timeout);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_WRITEFUNCTION, tcurl_write_data);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_WRITEDATA, state->response);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (tcurl_req->body != NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_READFUNCTION, tcurl_read_data);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_READDATA, tcurl_req->body);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina curl_code = curl_multi_add_handle(tcurl_ctx->multi_handle,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tcurl_req->curl_easy_handle);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (curl_code != CURLM_OK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = curlm_code2errno(curl_code);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tcurl_req->tcurl_ctx = tcurl_ctx;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = EAGAIN;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinadone:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret == EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tevent_req_done(req);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tevent_req_post(req, ev);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina } else if (ret != EAGAIN) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tevent_req_error(req, ret);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tevent_req_post(req, ev);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return req;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinastatic void tcurl_request_done(struct tevent_req *req,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina errno_t process_error,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina int response_code)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct tcurl_request_state *state;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_TRACE_FUNC, "TCURL request finished [%d]: %s\n",
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina process_error, sss_strerror(process_error));
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (req == NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina /* To handle case where we fail to obtain request from private data. */
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_MINOR_FAILURE, "No tevent request provided!\n");
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina state = tevent_req_data(req, struct tcurl_request_state);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina curl_multi_remove_handle(state->tcurl_req->tcurl_ctx->multi_handle,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina state->tcurl_req->curl_easy_handle);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina /* This request is no longer associated with tcurl context. */
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina state->tcurl_req->tcurl_ctx = NULL;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (process_error != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tevent_req_error(req, process_error);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina state->response_code = response_code;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tevent_req_done(req);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinaerrno_t tcurl_request_recv(TALLOC_CTX *mem_ctx,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct tevent_req *req,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct sss_iobuf **_response,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina int *_response_code)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct tcurl_request_state *state;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina state = tevent_req_data(req, struct tcurl_request_state);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina TEVENT_REQ_RETURN_ON_ERROR(req);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (_response != NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina *_response = talloc_steal(mem_ctx, state->response);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (_response_code != NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina *_response_code = state->response_code;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return EOK;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina}
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinastatic struct curl_slist *
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinatcurl_add_header(struct curl_slist *slist, const char *header)
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina{
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct curl_slist *new;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina new = curl_slist_append(slist, header);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (new == NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Cannot add header %s\n", header);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (slist != NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina curl_slist_free_all(slist);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return NULL;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return new;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina}
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinastatic errno_t
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinatcurl_construct_headers(const char **headers,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct curl_slist **_slist)
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina{
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct curl_slist *slist = NULL;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina int i;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (headers == NULL || headers[0] == NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina *_slist = NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EOK;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina for (i = 0; headers[i] != NULL; i++) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina slist = tcurl_add_header(slist, headers[i]);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (slist == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return ENOMEM;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* Add a dummy header to suppress libcurl adding Expect 100-continue which
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * was causing libcurl to always wait for the internal timeout when sending
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina * a PUT/POST request because secrets responder does not implement this.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina slist = tcurl_add_header(slist, "Expect: ");
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (slist == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return ENOMEM;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina *_slist = slist;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EOK;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinastatic int
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinatcurl_request_destructor(struct tcurl_request *tcurl_req)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (tcurl_req->tcurl_ctx != NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_MINOR_FAILURE, "Terminating TCURL request...\n");
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina curl_multi_remove_handle(tcurl_req->tcurl_ctx->multi_handle,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tcurl_req->curl_easy_handle);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (tcurl_req->headers != NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina curl_slist_free_all(tcurl_req->headers);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (tcurl_req->curl_easy_handle != NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina curl_easy_cleanup(tcurl_req->curl_easy_handle);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return 0;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina}
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinastatic struct tcurl_request *
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinatcurl_request_create(TALLOC_CTX *mem_ctx,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina const char *socket_path,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina const char *url,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina const char **headers,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct sss_iobuf *body)
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina{
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct tcurl_request *tcurl_req;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina errno_t ret;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tcurl_req = talloc_zero(mem_ctx, struct tcurl_request);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (tcurl_req == NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (url == NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "URL cannot be NULL!\n");
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = EINVAL;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina /* Setup a curl easy handle. This handle contains state for the request
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina * and is later associated with curl multi handle which performs
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina * asynchronous processing. */
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tcurl_req->curl_easy_handle = curl_easy_init();
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (tcurl_req->curl_easy_handle == NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize curl easy handle!\n");
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = ENOMEM;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tcurl_req->url = talloc_strdup(tcurl_req, url);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (tcurl_req->url == NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = ENOMEM;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (socket_path != NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tcurl_req->socket = talloc_strdup(tcurl_req, socket_path);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (tcurl_req->socket == NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = ENOMEM;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_construct_headers(headers, &tcurl_req->headers);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Unable to construct headers [%d]: %s\n",
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret, sss_strerror(ret));
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = ENOMEM;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tcurl_req->body = body;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina talloc_set_destructor(tcurl_req, tcurl_request_destructor);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_URL, url);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (socket_path != NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_UNIX_SOCKET_PATH, socket_path);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (body != NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina /* Curl will tell the underlying protocol about incoming data length.
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina * In case of HTTP it will add a sane Content-Length header. */
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_INFILESIZE_LARGE,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina (curl_off_t)sss_iobuf_get_size(body));
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = EOK;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinadone:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina talloc_free(tcurl_req);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return NULL;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return tcurl_req;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinastruct tcurl_request *tcurl_http(TALLOC_CTX *mem_ctx,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina enum tcurl_http_method method,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina const char *socket_path,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina const char *url,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina const char **headers,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct sss_iobuf *body)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct tcurl_request *tcurl_req;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek errno_t ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tcurl_req = tcurl_request_create(mem_ctx, socket_path, url, headers, body);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (tcurl_req == NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina /* Set HTTP specific options. */
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_HTTPHEADER, tcurl_req->headers);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina switch (method) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case TCURL_HTTP_GET:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina /* Nothing to do here. GET is default. */
c9db8b8b19827c3d492b8d2769aa77a37dbc12d3Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case TCURL_HTTP_PUT:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_UPLOAD, 1L);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina case TCURL_HTTP_POST:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_CUSTOMREQUEST, "POST");
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case TCURL_HTTP_DELETE:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_CUSTOMREQUEST, "DELETE");
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina goto done;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = EOK;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinadone:
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina talloc_free(tcurl_req);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return NULL;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return tcurl_req;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinastruct tevent_req *tcurl_http_send(TALLOC_CTX *mem_ctx,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct tevent_context *ev,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct tcurl_ctx *tcurl_ctx,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina enum tcurl_http_method method,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina const char *socket_path,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina const char *url,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina const char **headers,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct sss_iobuf *body,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina int timeout)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct tcurl_request *tcurl_req;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct tevent_req *req;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina tcurl_req = tcurl_http(mem_ctx, method, socket_path, url, headers, body);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (tcurl_req == NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return NULL;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina req = tcurl_request_send(mem_ctx, ev, tcurl_ctx, tcurl_req, timeout);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (req == NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina talloc_free(tcurl_req);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return req;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinaerrno_t tcurl_http_recv(TALLOC_CTX *mem_ctx,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct tevent_req *req,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina int *_http_code,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina struct sss_iobuf **_response)
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina{
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return tcurl_request_recv(mem_ctx, req, _response, _http_code);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina}
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinaerrno_t tcurl_req_enable_rawoutput(struct tcurl_request *tcurl_req)
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina{
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return tcurl_set_option(tcurl_req, CURLOPT_HEADER, 1L);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina}
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinaerrno_t tcurl_req_verify_peer(struct tcurl_request *tcurl_req,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina const char *capath,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina const char *cacert,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina bool verify_peer,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina bool verify_host)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek errno_t ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina long peer = verify_peer ? 1L : 0L;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina long host = verify_host ? 2L : 0L;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_SSL_VERIFYPEER, peer);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_SSL_VERIFYHOST, host);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (capath != NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_CAPATH, capath);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return ret;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (cacert != NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_CAINFO, cacert);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return ret;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return EOK;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březinaerrno_t tcurl_req_set_client_cert(struct tcurl_request *tcurl_req,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina const char *cert,
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina const char *key)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina errno_t ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (cert == NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "You must specify client certificate!\n");
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return EINVAL;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_SSLCERT, cert);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (key != NULL) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina /* If client's private key is in separate file. */
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_SSLKEY, key);
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina if (ret != EOK) {
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return ret;
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
300b9e9217ee1ed8d845ed2370c5ccf5c87afb36Pavel Březina return EOK;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březinaerrno_t tcurl_req_http_basic_auth(struct tcurl_request *tcurl_req,
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina const char *username,
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina const char *password)
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina{
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina errno_t ret;
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina if (ret != EOK) {
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina return ret;
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina }
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_USERNAME, username);
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina if (ret != EOK) {
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina return ret;
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina }
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina ret = tcurl_set_option(tcurl_req, CURLOPT_PASSWORD, password);
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina if (ret != EOK) {
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina return ret;
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina }
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina return EOK;
c2ea75da72b426d98ba489039e220d417bfb4c2aPavel Březina}