Line data Source code
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 "platform.h"
25 : #include "taler_curl_lib.h"
26 :
27 :
28 : #if TALER_CURL_COMPRESS_BODIES
29 : #include <zlib.h>
30 : #endif
31 :
32 :
33 : void
34 4716 : TALER_curl_set_secure_redirect_policy (CURL *eh,
35 : const char *url)
36 : {
37 4716 : GNUNET_assert (CURLE_OK ==
38 : curl_easy_setopt (eh,
39 : CURLOPT_FOLLOWLOCATION,
40 : 1L));
41 4716 : 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 4716 : GNUNET_assert (CURLE_OK ==
79 : curl_easy_setopt (eh,
80 : CURLOPT_MAXREDIRS,
81 : 5L));
82 4716 : }
83 :
84 :
85 : enum GNUNET_GenericReturnValue
86 4673 : 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 4673 : str = json_dumps (body,
94 : JSON_COMPACT);
95 4673 : if (NULL == str)
96 : {
97 0 : GNUNET_break (0);
98 0 : return GNUNET_SYSERR;
99 : }
100 4673 : slen = strlen (str);
101 4673 : if (TALER_CURL_COMPRESS_BODIES &&
102 4673 : (! ctx->disable_compression) )
103 : {
104 : Bytef *cbuf;
105 : uLongf cbuf_size;
106 : int ret;
107 :
108 4673 : cbuf_size = compressBound (slen);
109 4673 : cbuf = GNUNET_malloc (cbuf_size);
110 4673 : ret = compress (cbuf,
111 : &cbuf_size,
112 : (const Bytef *) str,
113 : slen);
114 4673 : if (Z_OK != ret)
115 : {
116 : /* compression failed!? */
117 0 : GNUNET_break (0);
118 0 : GNUNET_free (cbuf);
119 0 : return GNUNET_SYSERR;
120 : }
121 4673 : free (str);
122 4673 : slen = (size_t) cbuf_size;
123 4673 : ctx->json_enc = (char *) cbuf;
124 4673 : GNUNET_assert (
125 : NULL !=
126 : (ctx->headers = curl_slist_append (
127 : ctx->headers,
128 : "Content-Encoding: deflate")));
129 : }
130 : else
131 : {
132 0 : ctx->json_enc = str;
133 : }
134 4673 : 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 4673 : GNUNET_assert (
142 : NULL !=
143 : (ctx->headers = curl_slist_append (
144 : ctx->headers,
145 : "Content-Type: application/json")));
146 :
147 4673 : GNUNET_assert (CURLE_OK ==
148 : curl_easy_setopt (eh,
149 : CURLOPT_POSTFIELDS,
150 : ctx->json_enc));
151 4673 : GNUNET_assert (CURLE_OK ==
152 : curl_easy_setopt (eh,
153 : CURLOPT_POSTFIELDSIZE,
154 : (long) slen));
155 4673 : return GNUNET_OK;
156 : }
157 :
158 :
159 : void
160 4703 : TALER_curl_easy_post_finished (struct TALER_CURL_PostContext *ctx)
161 : {
162 4703 : curl_slist_free_all (ctx->headers);
163 4703 : ctx->headers = NULL;
164 4703 : GNUNET_free (ctx->json_enc);
165 4703 : ctx->json_enc = NULL;
166 4703 : }
|