curl.c (4946B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2019-2024 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it 6 under the terms of the GNU General Public License as published 7 by the Free Software Foundation; either version 3, or (at your 8 option) any later version. 9 10 TALER is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public 16 License along with TALER; see the file COPYING. If not, see 17 <http://www.gnu.org/licenses/> 18 */ 19 /** 20 * @file curl/curl.c 21 * @brief Helper routines for interactions with libcurl 22 * @author Christian Grothoff 23 */ 24 #include "taler/taler_curl_lib.h" 25 26 27 #if TALER_CURL_COMPRESS_BODIES 28 #include <zlib.h> 29 #endif 30 31 32 void 33 TALER_curl_set_secure_redirect_policy (CURL *eh, 34 const char *url) 35 { 36 GNUNET_assert (CURLE_OK == 37 curl_easy_setopt (eh, 38 CURLOPT_FOLLOWLOCATION, 39 1L)); 40 GNUNET_assert ( (0 == strncasecmp (url, 41 "https://", 42 strlen ("https://"))) || 43 (0 == strncasecmp (url, 44 "http://", 45 strlen ("http://"))) ); 46 #ifdef CURLOPT_REDIR_PROTOCOLS_STR 47 if (0 == strncasecmp (url, 48 "https://", 49 strlen ("https://"))) 50 GNUNET_assert (CURLE_OK == 51 curl_easy_setopt (eh, 52 CURLOPT_REDIR_PROTOCOLS_STR, 53 "https")); 54 else 55 GNUNET_assert (CURLE_OK == 56 curl_easy_setopt (eh, 57 CURLOPT_REDIR_PROTOCOLS_STR, 58 "http,https")); 59 #else 60 #ifdef CURLOPT_REDIR_PROTOCOLS 61 if (0 == strncasecmp (url, 62 "https://", 63 strlen ("https://"))) 64 GNUNET_assert (CURLE_OK == 65 curl_easy_setopt (eh, 66 CURLOPT_REDIR_PROTOCOLS, 67 CURLPROTO_HTTPS)); 68 else 69 GNUNET_assert (CURLE_OK == 70 curl_easy_setopt (eh, 71 CURLOPT_REDIR_PROTOCOLS, 72 CURLPROTO_HTTP | CURLPROTO_HTTPS)); 73 #endif 74 #endif 75 /* limit MAXREDIRS to 5 as a simple security measure against 76 a potential infinite loop caused by a malicious target */ 77 GNUNET_assert (CURLE_OK == 78 curl_easy_setopt (eh, 79 CURLOPT_MAXREDIRS, 80 5L)); 81 } 82 83 84 enum GNUNET_GenericReturnValue 85 TALER_curl_easy_post (struct TALER_CURL_PostContext *ctx, 86 CURL *eh, 87 const json_t *body) 88 { 89 char *str; 90 size_t slen; 91 92 str = json_dumps (body, 93 JSON_COMPACT); 94 if (NULL == str) 95 { 96 GNUNET_break (0); 97 return GNUNET_SYSERR; 98 } 99 slen = strlen (str); 100 if (TALER_CURL_COMPRESS_BODIES && 101 (! ctx->disable_compression) ) 102 { 103 Bytef *cbuf; 104 uLongf cbuf_size; 105 int ret; 106 107 cbuf_size = compressBound (slen); 108 cbuf = GNUNET_malloc (cbuf_size); 109 ret = compress (cbuf, 110 &cbuf_size, 111 (const Bytef *) str, 112 slen); 113 if (Z_OK != ret) 114 { 115 /* compression failed!? */ 116 GNUNET_break (0); 117 GNUNET_free (cbuf); 118 return GNUNET_SYSERR; 119 } 120 free (str); 121 slen = (size_t) cbuf_size; 122 ctx->json_enc = (char *) cbuf; 123 GNUNET_assert ( 124 NULL != 125 (ctx->headers = curl_slist_append ( 126 ctx->headers, 127 "Content-Encoding: deflate"))); 128 } 129 else 130 { 131 ctx->json_enc = str; 132 } 133 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 134 "Uploading JSON of %d bytes (%s)\n", 135 (int) slen, 136 (TALER_CURL_COMPRESS_BODIES && 137 (! ctx->disable_compression) ) 138 ? "compressed" 139 : "uncompressed"); 140 GNUNET_assert ( 141 NULL != 142 (ctx->headers = curl_slist_append ( 143 ctx->headers, 144 "Content-Type: application/json"))); 145 146 GNUNET_assert (CURLE_OK == 147 curl_easy_setopt (eh, 148 CURLOPT_POSTFIELDS, 149 ctx->json_enc)); 150 GNUNET_assert (CURLE_OK == 151 curl_easy_setopt (eh, 152 CURLOPT_POSTFIELDSIZE, 153 (long) slen)); 154 return GNUNET_OK; 155 } 156 157 158 void 159 TALER_curl_easy_post_finished (struct TALER_CURL_PostContext *ctx) 160 { 161 curl_slist_free_all (ctx->headers); 162 ctx->headers = NULL; 163 GNUNET_free (ctx->json_enc); 164 ctx->json_enc = NULL; 165 }