curl.c (4974B)
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/platform.h" 25 #include "taler/taler_curl_lib.h" 26 27 28 #if TALER_CURL_COMPRESS_BODIES 29 #include <zlib.h> 30 #endif 31 32 33 void 34 TALER_curl_set_secure_redirect_policy (CURL *eh, 35 const char *url) 36 { 37 GNUNET_assert (CURLE_OK == 38 curl_easy_setopt (eh, 39 CURLOPT_FOLLOWLOCATION, 40 1L)); 41 GNUNET_assert ( (0 == strncasecmp (url, 42 "https://", 43 strlen ("https://"))) || 44 (0 == strncasecmp (url, 45 "http://", 46 strlen ("http://"))) ); 47 #ifdef CURLOPT_REDIR_PROTOCOLS_STR 48 if (0 == strncasecmp (url, 49 "https://", 50 strlen ("https://"))) 51 GNUNET_assert (CURLE_OK == 52 curl_easy_setopt (eh, 53 CURLOPT_REDIR_PROTOCOLS_STR, 54 "https")); 55 else 56 GNUNET_assert (CURLE_OK == 57 curl_easy_setopt (eh, 58 CURLOPT_REDIR_PROTOCOLS_STR, 59 "http,https")); 60 #else 61 #ifdef CURLOPT_REDIR_PROTOCOLS 62 if (0 == strncasecmp (url, 63 "https://", 64 strlen ("https://"))) 65 GNUNET_assert (CURLE_OK == 66 curl_easy_setopt (eh, 67 CURLOPT_REDIR_PROTOCOLS, 68 CURLPROTO_HTTPS)); 69 else 70 GNUNET_assert (CURLE_OK == 71 curl_easy_setopt (eh, 72 CURLOPT_REDIR_PROTOCOLS, 73 CURLPROTO_HTTP | CURLPROTO_HTTPS)); 74 #endif 75 #endif 76 /* limit MAXREDIRS to 5 as a simple security measure against 77 a potential infinite loop caused by a malicious target */ 78 GNUNET_assert (CURLE_OK == 79 curl_easy_setopt (eh, 80 CURLOPT_MAXREDIRS, 81 5L)); 82 } 83 84 85 enum GNUNET_GenericReturnValue 86 TALER_curl_easy_post (struct TALER_CURL_PostContext *ctx, 87 CURL *eh, 88 const json_t *body) 89 { 90 char *str; 91 size_t slen; 92 93 str = json_dumps (body, 94 JSON_COMPACT); 95 if (NULL == str) 96 { 97 GNUNET_break (0); 98 return GNUNET_SYSERR; 99 } 100 slen = strlen (str); 101 if (TALER_CURL_COMPRESS_BODIES && 102 (! ctx->disable_compression) ) 103 { 104 Bytef *cbuf; 105 uLongf cbuf_size; 106 int ret; 107 108 cbuf_size = compressBound (slen); 109 cbuf = GNUNET_malloc (cbuf_size); 110 ret = compress (cbuf, 111 &cbuf_size, 112 (const Bytef *) str, 113 slen); 114 if (Z_OK != ret) 115 { 116 /* compression failed!? */ 117 GNUNET_break (0); 118 GNUNET_free (cbuf); 119 return GNUNET_SYSERR; 120 } 121 free (str); 122 slen = (size_t) cbuf_size; 123 ctx->json_enc = (char *) cbuf; 124 GNUNET_assert ( 125 NULL != 126 (ctx->headers = curl_slist_append ( 127 ctx->headers, 128 "Content-Encoding: deflate"))); 129 } 130 else 131 { 132 ctx->json_enc = str; 133 } 134 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 135 "Uploading JSON of %d bytes (%s)\n", 136 (int) slen, 137 (TALER_CURL_COMPRESS_BODIES && 138 (! ctx->disable_compression) ) 139 ? "compressed" 140 : "uncompressed"); 141 GNUNET_assert ( 142 NULL != 143 (ctx->headers = curl_slist_append ( 144 ctx->headers, 145 "Content-Type: application/json"))); 146 147 GNUNET_assert (CURLE_OK == 148 curl_easy_setopt (eh, 149 CURLOPT_POSTFIELDS, 150 ctx->json_enc)); 151 GNUNET_assert (CURLE_OK == 152 curl_easy_setopt (eh, 153 CURLOPT_POSTFIELDSIZE, 154 (long) slen)); 155 return GNUNET_OK; 156 } 157 158 159 void 160 TALER_curl_easy_post_finished (struct TALER_CURL_PostContext *ctx) 161 { 162 curl_slist_free_all (ctx->headers); 163 ctx->headers = NULL; 164 GNUNET_free (ctx->json_enc); 165 ctx->json_enc = NULL; 166 }