Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/curl/src/config2setopts.c
2654 views
1
/***************************************************************************
2
* _ _ ____ _
3
* Project ___| | | | _ \| |
4
* / __| | | | |_) | |
5
* | (__| |_| | _ <| |___
6
* \___|\___/|_| \_\_____|
7
*
8
* Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9
*
10
* This software is licensed as described in the file COPYING, which
11
* you should have received as part of this distribution. The terms
12
* are also available at https://curl.se/docs/copyright.html.
13
*
14
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
15
* copies of the Software, and permit persons to whom the Software is
16
* furnished to do so, under the terms of the COPYING file.
17
*
18
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
* KIND, either express or implied.
20
*
21
* SPDX-License-Identifier: curl
22
*
23
***************************************************************************/
24
#include "tool_setup.h"
25
26
#include "tool_cfgable.h"
27
#include "tool_setopt.h"
28
#include "tool_findfile.h"
29
#include "tool_msgs.h"
30
#include "tool_libinfo.h"
31
#include "tool_cb_soc.h"
32
#include "tool_operate.h"
33
#include "config2setopts.h"
34
#include "tool_ipfs.h"
35
#include "tool_cb_wrt.h"
36
#include "tool_cb_rea.h"
37
#include "tool_cb_see.h"
38
#include "tool_cb_dbg.h"
39
#include "tool_helpers.h"
40
41
#define BUFFER_SIZE 102400L
42
43
#ifdef IP_TOS
44
static int get_address_family(curl_socket_t sockfd)
45
{
46
struct sockaddr addr;
47
curl_socklen_t addrlen = sizeof(addr);
48
memset(&addr, 0, sizeof(addr));
49
if(getsockname(sockfd, (struct sockaddr *)&addr, &addrlen) == 0)
50
return addr.sa_family;
51
return AF_UNSPEC;
52
}
53
#endif
54
55
#ifndef SOL_IP
56
# define SOL_IP IPPROTO_IP
57
#endif
58
59
#if defined(IP_TOS) || defined(IPV6_TCLASS) || defined(SO_PRIORITY)
60
static int sockopt_callback(void *clientp, curl_socket_t curlfd,
61
curlsocktype purpose)
62
{
63
struct OperationConfig *config = (struct OperationConfig *)clientp;
64
if(purpose != CURLSOCKTYPE_IPCXN)
65
return CURL_SOCKOPT_OK;
66
(void)config;
67
(void)curlfd;
68
#if defined(IP_TOS) || defined(IPV6_TCLASS)
69
if(config->ip_tos > 0) {
70
int tos = (int)config->ip_tos;
71
int result = 0;
72
switch(get_address_family(curlfd)) {
73
case AF_INET:
74
#ifdef IP_TOS
75
result = setsockopt(curlfd, SOL_IP, IP_TOS, (void *)&tos, sizeof(tos));
76
#endif
77
break;
78
#if defined(IPV6_TCLASS) && defined(AF_INET6)
79
case AF_INET6:
80
result = setsockopt(curlfd, IPPROTO_IPV6, IPV6_TCLASS,
81
(void *)&tos, sizeof(tos));
82
break;
83
#endif
84
}
85
if(result < 0) {
86
char buffer[STRERROR_LEN];
87
int error = errno;
88
warnf("Setting type of service to %d failed with errno %d: %s", tos,
89
error, curlx_strerror(error, buffer, sizeof(buffer)));
90
}
91
}
92
#endif
93
#ifdef SO_PRIORITY
94
if(config->vlan_priority > 0) {
95
int priority = (int)config->vlan_priority;
96
if(setsockopt(curlfd, SOL_SOCKET, SO_PRIORITY,
97
(void *)&priority, sizeof(priority)) != 0) {
98
char buffer[STRERROR_LEN];
99
int error = errno;
100
warnf("VLAN priority %d failed with errno %d: %s", priority,
101
error, curlx_strerror(error, buffer, sizeof(buffer)));
102
}
103
}
104
#endif
105
return CURL_SOCKOPT_OK;
106
}
107
#endif /* IP_TOD || IPV6_TCLASS || SO_PRIORITY */
108
109
/* return current SSL backend name, chop off multissl */
110
static char *ssl_backend(void)
111
{
112
static char ssl_ver[80] = "no ssl";
113
static bool already = FALSE;
114
if(!already) { /* if there is no existing version */
115
const char *v = curl_version_info(CURLVERSION_NOW)->ssl_version;
116
if(v)
117
curl_msnprintf(ssl_ver, sizeof(ssl_ver),
118
"%.*s", (int)strcspn(v, " "), v);
119
already = TRUE;
120
}
121
return ssl_ver;
122
}
123
124
/*
125
* Possibly rewrite the URL for IPFS and return the protocol token for the
126
* scheme used in the given URL.
127
*/
128
static CURLcode url_proto_and_rewrite(char **url,
129
struct OperationConfig *config,
130
const char **scheme)
131
{
132
CURLcode result = CURLE_OK;
133
CURLU *uh = curl_url();
134
const char *proto = NULL;
135
*scheme = NULL;
136
137
DEBUGASSERT(url && *url);
138
if(uh) {
139
char *schemep = NULL;
140
if(!curl_url_set(uh, CURLUPART_URL, *url,
141
CURLU_GUESS_SCHEME | CURLU_NON_SUPPORT_SCHEME) &&
142
!curl_url_get(uh, CURLUPART_SCHEME, &schemep,
143
CURLU_DEFAULT_SCHEME)) {
144
#ifdef CURL_DISABLE_IPFS
145
(void)config;
146
#else
147
if(curl_strequal(schemep, proto_ipfs) ||
148
curl_strequal(schemep, proto_ipns)) {
149
result = ipfs_url_rewrite(uh, schemep, url, config);
150
/* short-circuit proto_token, we know it is ipfs or ipns */
151
if(curl_strequal(schemep, proto_ipfs))
152
proto = proto_ipfs;
153
else if(curl_strequal(schemep, proto_ipns))
154
proto = proto_ipns;
155
if(result)
156
config->synthetic_error = TRUE;
157
}
158
else
159
#endif /* !CURL_DISABLE_IPFS */
160
proto = proto_token(schemep);
161
162
curl_free(schemep);
163
}
164
curl_url_cleanup(uh);
165
}
166
else
167
result = CURLE_OUT_OF_MEMORY;
168
169
*scheme = proto ? proto : "?"; /* Never match if not found. */
170
return result;
171
}
172
173
static CURLcode ssh_setopts(struct OperationConfig *config, CURL *curl)
174
{
175
CURLcode result;
176
177
/* SSH and SSL private key uses same command-line option */
178
/* new in libcurl 7.16.1 */
179
my_setopt_str(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key);
180
/* new in libcurl 7.16.1 */
181
my_setopt_str(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey);
182
183
/* new in libcurl 7.17.1: SSH host key md5 checking allows us
184
to fail if we are not talking to who we think we should */
185
my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
186
config->hostpubmd5);
187
188
/* new in libcurl 7.80.0: SSH host key sha256 checking allows us
189
to fail if we are not talking to who we think we should */
190
my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256,
191
config->hostpubsha256);
192
193
/* new in libcurl 7.56.0 */
194
if(config->ssh_compression)
195
my_setopt_long(curl, CURLOPT_SSH_COMPRESSION, 1);
196
197
if(!config->insecure_ok) {
198
char *known = config->knownhosts;
199
200
if(!known)
201
known = findfile(".ssh/known_hosts", FALSE);
202
if(known) {
203
/* new in curl 7.19.6 */
204
result = my_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, known);
205
if(result) {
206
config->knownhosts = NULL;
207
curl_free(known);
208
return result;
209
}
210
/* store it in global to avoid repeated checks */
211
config->knownhosts = known;
212
}
213
else if(!config->hostpubmd5 && !config->hostpubsha256) {
214
errorf("Couldn't find a known_hosts file");
215
return CURLE_FAILED_INIT;
216
}
217
else
218
warnf("Couldn't find a known_hosts file");
219
}
220
return CURLE_OK; /* ignore if SHA256 did not work */
221
}
222
223
#ifdef CURL_CA_EMBED
224
#ifndef CURL_DECLARED_CURL_CA_EMBED
225
#define CURL_DECLARED_CURL_CA_EMBED
226
extern const unsigned char curl_ca_embed[];
227
#endif
228
#endif
229
230
static long tlsversion(unsigned char mintls,
231
unsigned char maxtls)
232
{
233
long tlsver = 0;
234
if(!mintls) { /* minimum is at default */
235
/* minimum is set to default, which we want to be 1.2 */
236
if(maxtls && (maxtls < 3))
237
/* max is set lower than 1.2 and minimum is default, change minimum to
238
the same as max */
239
mintls = maxtls;
240
}
241
switch(mintls) {
242
case 1:
243
tlsver = CURL_SSLVERSION_TLSv1_0;
244
break;
245
case 2:
246
tlsver = CURL_SSLVERSION_TLSv1_1;
247
break;
248
case 0: /* let default minimum be 1.2 */
249
case 3:
250
tlsver = CURL_SSLVERSION_TLSv1_2;
251
break;
252
case 4:
253
default: /* just in case */
254
tlsver = CURL_SSLVERSION_TLSv1_3;
255
break;
256
}
257
switch(maxtls) {
258
case 0: /* not set, leave it */
259
break;
260
case 1:
261
tlsver |= CURL_SSLVERSION_MAX_TLSv1_0;
262
break;
263
case 2:
264
tlsver |= CURL_SSLVERSION_MAX_TLSv1_1;
265
break;
266
case 3:
267
tlsver |= CURL_SSLVERSION_MAX_TLSv1_2;
268
break;
269
case 4:
270
default: /* just in case */
271
tlsver |= CURL_SSLVERSION_MAX_TLSv1_3;
272
break;
273
}
274
return tlsver;
275
}
276
277
/* only called if libcurl supports TLS */
278
static CURLcode ssl_setopts(struct OperationConfig *config, CURL *curl)
279
{
280
CURLcode result = CURLE_OK;
281
282
if(config->cacert)
283
my_setopt_str(curl, CURLOPT_CAINFO, config->cacert);
284
if(config->proxy_cacert)
285
my_setopt_str(curl, CURLOPT_PROXY_CAINFO, config->proxy_cacert);
286
287
if(config->capath) {
288
result = my_setopt_str(curl, CURLOPT_CAPATH, config->capath);
289
if(result)
290
return result;
291
}
292
/* For the time being if --proxy-capath is not set then we use the
293
--capath value for it, if any. See #1257 */
294
if(config->proxy_capath || config->capath) {
295
result = my_setopt_str(curl, CURLOPT_PROXY_CAPATH,
296
(config->proxy_capath ? config->proxy_capath :
297
config->capath));
298
if((result == CURLE_NOT_BUILT_IN) ||
299
(result == CURLE_UNKNOWN_OPTION)) {
300
if(config->proxy_capath) {
301
warnf("ignoring %s, not supported by libcurl with %s",
302
config->proxy_capath ? "--proxy-capath" : "--capath",
303
ssl_backend());
304
}
305
}
306
else if(result)
307
return result;
308
}
309
310
#ifdef CURL_CA_EMBED
311
if(!config->cacert && !config->capath) {
312
struct curl_blob blob;
313
blob.data = CURL_UNCONST(curl_ca_embed);
314
blob.len = strlen((const char *)curl_ca_embed);
315
blob.flags = CURL_BLOB_NOCOPY;
316
notef("Using embedded CA bundle (%zu bytes)", blob.len);
317
result = curl_easy_setopt(curl, CURLOPT_CAINFO_BLOB, &blob);
318
if(result == CURLE_NOT_BUILT_IN) {
319
warnf("ignoring %s, not supported by libcurl with %s",
320
"embedded CA bundle", ssl_backend());
321
}
322
}
323
if(!config->proxy_cacert && !config->proxy_capath) {
324
struct curl_blob blob;
325
blob.data = CURL_UNCONST(curl_ca_embed);
326
blob.len = strlen((const char *)curl_ca_embed);
327
blob.flags = CURL_BLOB_NOCOPY;
328
notef("Using embedded CA bundle, for proxies (%zu bytes)", blob.len);
329
result = curl_easy_setopt(curl, CURLOPT_PROXY_CAINFO_BLOB, &blob);
330
if(result == CURLE_NOT_BUILT_IN) {
331
warnf("ignoring %s, not supported by libcurl with %s",
332
"embedded CA bundle", ssl_backend());
333
}
334
}
335
#endif
336
337
if(config->crlfile)
338
my_setopt_str(curl, CURLOPT_CRLFILE, config->crlfile);
339
if(config->proxy_crlfile)
340
my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->proxy_crlfile);
341
else if(config->crlfile) /* CURLOPT_PROXY_CRLFILE default is crlfile */
342
my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->crlfile);
343
344
if(config->pinnedpubkey) {
345
result = my_setopt_str(curl, CURLOPT_PINNEDPUBLICKEY,
346
config->pinnedpubkey);
347
if(result == CURLE_NOT_BUILT_IN)
348
warnf("ignoring %s, not supported by libcurl with %s",
349
"--pinnedpubkey", ssl_backend());
350
}
351
if(config->proxy_pinnedpubkey) {
352
result = my_setopt_str(curl, CURLOPT_PROXY_PINNEDPUBLICKEY,
353
config->proxy_pinnedpubkey);
354
if(result == CURLE_NOT_BUILT_IN)
355
warnf("ignoring %s, not supported by libcurl with %s",
356
"--proxy-pinnedpubkey", ssl_backend());
357
}
358
359
if(config->ssl_ec_curves)
360
my_setopt_str(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves);
361
362
if(config->ssl_signature_algorithms)
363
my_setopt_str(curl, CURLOPT_SSL_SIGNATURE_ALGORITHMS,
364
config->ssl_signature_algorithms);
365
366
if(config->writeout)
367
my_setopt_long(curl, CURLOPT_CERTINFO, 1);
368
369
my_setopt_str(curl, CURLOPT_SSLCERT, config->cert);
370
my_setopt_str(curl, CURLOPT_PROXY_SSLCERT, config->proxy_cert);
371
my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
372
my_setopt_str(curl, CURLOPT_PROXY_SSLCERTTYPE,
373
config->proxy_cert_type);
374
my_setopt_str(curl, CURLOPT_SSLKEY, config->key);
375
my_setopt_str(curl, CURLOPT_PROXY_SSLKEY, config->proxy_key);
376
my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
377
my_setopt_str(curl, CURLOPT_PROXY_SSLKEYTYPE,
378
config->proxy_key_type);
379
380
/* libcurl default is strict verifyhost -> 1L, verifypeer -> 1L */
381
if(config->insecure_ok) {
382
my_setopt_long(curl, CURLOPT_SSL_VERIFYPEER, 0);
383
my_setopt_long(curl, CURLOPT_SSL_VERIFYHOST, 0);
384
}
385
386
if(config->doh_insecure_ok) {
387
my_setopt_long(curl, CURLOPT_DOH_SSL_VERIFYPEER, 0);
388
my_setopt_long(curl, CURLOPT_DOH_SSL_VERIFYHOST, 0);
389
}
390
391
if(config->proxy_insecure_ok) {
392
my_setopt_long(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0);
393
my_setopt_long(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0);
394
}
395
396
if(config->verifystatus)
397
my_setopt_long(curl, CURLOPT_SSL_VERIFYSTATUS, 1);
398
399
if(config->doh_verifystatus)
400
my_setopt_long(curl, CURLOPT_DOH_SSL_VERIFYSTATUS, 1);
401
402
my_setopt_SSLVERSION(curl, CURLOPT_SSLVERSION,
403
tlsversion(config->ssl_version,
404
config->ssl_version_max));
405
if(config->proxy)
406
my_setopt_SSLVERSION(curl, CURLOPT_PROXY_SSLVERSION,
407
config->proxy_ssl_version);
408
409
{
410
long mask =
411
(config->ssl_allow_beast ? CURLSSLOPT_ALLOW_BEAST : 0) |
412
(config->ssl_allow_earlydata ? CURLSSLOPT_EARLYDATA : 0) |
413
(config->ssl_no_revoke ? CURLSSLOPT_NO_REVOKE : 0) |
414
(config->ssl_revoke_best_effort ? CURLSSLOPT_REVOKE_BEST_EFFORT : 0) |
415
(config->native_ca_store ? CURLSSLOPT_NATIVE_CA : 0) |
416
(config->ssl_auto_client_cert ? CURLSSLOPT_AUTO_CLIENT_CERT : 0);
417
418
if(mask)
419
my_setopt_bitmask(curl, CURLOPT_SSL_OPTIONS, mask);
420
}
421
422
{
423
long mask =
424
(config->proxy_ssl_allow_beast ? CURLSSLOPT_ALLOW_BEAST : 0) |
425
(config->proxy_ssl_auto_client_cert ?
426
CURLSSLOPT_AUTO_CLIENT_CERT : 0) |
427
(config->proxy_native_ca_store ? CURLSSLOPT_NATIVE_CA : 0);
428
429
if(mask)
430
my_setopt_bitmask(curl, CURLOPT_PROXY_SSL_OPTIONS, mask);
431
}
432
433
if(config->cipher_list) {
434
result = my_setopt_str(curl, CURLOPT_SSL_CIPHER_LIST,
435
config->cipher_list);
436
if(result == CURLE_NOT_BUILT_IN)
437
warnf("ignoring %s, not supported by libcurl with %s",
438
"--ciphers", ssl_backend());
439
}
440
if(config->proxy_cipher_list) {
441
result = my_setopt_str(curl, CURLOPT_PROXY_SSL_CIPHER_LIST,
442
config->proxy_cipher_list);
443
if(result == CURLE_NOT_BUILT_IN)
444
warnf("ignoring %s, not supported by libcurl with %s",
445
"--proxy-ciphers", ssl_backend());
446
}
447
if(config->cipher13_list) {
448
result = my_setopt_str(curl, CURLOPT_TLS13_CIPHERS,
449
config->cipher13_list);
450
if(result == CURLE_NOT_BUILT_IN)
451
warnf("ignoring %s, not supported by libcurl with %s",
452
"--tls13-ciphers", ssl_backend());
453
}
454
if(config->proxy_cipher13_list) {
455
result = my_setopt_str(curl, CURLOPT_PROXY_TLS13_CIPHERS,
456
config->proxy_cipher13_list);
457
if(result == CURLE_NOT_BUILT_IN)
458
warnf("ignoring %s, not supported by libcurl with %s",
459
"--proxy-tls13-ciphers", ssl_backend());
460
}
461
462
/* curl 7.16.0 */
463
if(config->disable_sessionid)
464
/* disable it */
465
my_setopt_long(curl, CURLOPT_SSL_SESSIONID_CACHE, 0);
466
467
if(feature_ech) {
468
/* only if enabled in libcurl */
469
if(config->ech) /* only if set (optional) */
470
my_setopt_str(curl, CURLOPT_ECH, config->ech);
471
if(config->ech_public) /* only if set (optional) */
472
my_setopt_str(curl, CURLOPT_ECH, config->ech_public);
473
if(config->ech_config) /* only if set (optional) */
474
my_setopt_str(curl, CURLOPT_ECH, config->ech_config);
475
}
476
477
/* new in curl 7.9.3 */
478
if(config->engine) {
479
result = my_setopt_str(curl, CURLOPT_SSLENGINE, config->engine);
480
if(result)
481
return result;
482
}
483
484
/* new in curl 7.15.5 */
485
if(config->ftp_ssl_reqd)
486
my_setopt_enum(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
487
488
/* new in curl 7.11.0 */
489
else if(config->ftp_ssl)
490
my_setopt_enum(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
491
492
/* new in curl 7.16.0 */
493
else if(config->ftp_ssl_control)
494
my_setopt_enum(curl, CURLOPT_USE_SSL, CURLUSESSL_CONTROL);
495
496
if(config->noalpn)
497
my_setopt_long(curl, CURLOPT_SSL_ENABLE_ALPN, 0);
498
499
return CURLE_OK;
500
}
501
502
/* only called for HTTP transfers */
503
static CURLcode http_setopts(struct OperationConfig *config,
504
CURL *curl)
505
{
506
long postRedir = 0;
507
508
my_setopt_long(curl, CURLOPT_FOLLOWLOCATION, config->followlocation);
509
my_setopt_long(curl, CURLOPT_UNRESTRICTED_AUTH,
510
config->unrestricted_auth);
511
my_setopt_str(curl, CURLOPT_AWS_SIGV4, config->aws_sigv4);
512
my_setopt_long(curl, CURLOPT_AUTOREFERER, config->autoreferer);
513
514
/* new in libcurl 7.36.0 */
515
if(config->proxyheaders) {
516
my_setopt_slist(curl, CURLOPT_PROXYHEADER, config->proxyheaders);
517
my_setopt_long(curl, CURLOPT_HEADEROPT, CURLHEADER_SEPARATE);
518
}
519
520
/* new in libcurl 7.5 */
521
my_setopt_long(curl, CURLOPT_MAXREDIRS, config->maxredirs);
522
523
if(config->httpversion)
524
my_setopt_enum(curl, CURLOPT_HTTP_VERSION, config->httpversion);
525
526
/* curl 7.19.1 (the 301 version existed in 7.18.2),
527
303 was added in 7.26.0 */
528
if(config->post301)
529
postRedir |= CURL_REDIR_POST_301;
530
if(config->post302)
531
postRedir |= CURL_REDIR_POST_302;
532
if(config->post303)
533
postRedir |= CURL_REDIR_POST_303;
534
my_setopt_long(curl, CURLOPT_POSTREDIR, postRedir);
535
536
/* new in libcurl 7.21.6 */
537
if(config->encoding)
538
my_setopt_str(curl, CURLOPT_ACCEPT_ENCODING, "");
539
540
/* new in libcurl 7.21.6 */
541
if(config->tr_encoding)
542
my_setopt_long(curl, CURLOPT_TRANSFER_ENCODING, 1);
543
/* new in libcurl 7.64.0 */
544
my_setopt_long(curl, CURLOPT_HTTP09_ALLOWED, config->http09_allowed);
545
546
if(config->altsvc)
547
my_setopt_str(curl, CURLOPT_ALTSVC, config->altsvc);
548
549
if(config->hsts)
550
my_setopt_str(curl, CURLOPT_HSTS, config->hsts);
551
552
/* new in 7.47.0 */
553
if(config->expect100timeout_ms > 0)
554
my_setopt_long(curl, CURLOPT_EXPECT_100_TIMEOUT_MS,
555
config->expect100timeout_ms);
556
557
return CURLE_OK;
558
}
559
560
static CURLcode cookie_setopts(struct OperationConfig *config, CURL *curl)
561
{
562
CURLcode result = CURLE_OK;
563
if(config->cookies) {
564
struct dynbuf cookies;
565
struct curl_slist *cl;
566
567
/* The maximum size needs to match MAX_NAME in cookie.h */
568
#define MAX_COOKIE_LINE 8200
569
curlx_dyn_init(&cookies, MAX_COOKIE_LINE);
570
for(cl = config->cookies; cl; cl = cl->next) {
571
if(cl == config->cookies)
572
result = curlx_dyn_add(&cookies, cl->data);
573
else
574
result = curlx_dyn_addf(&cookies, ";%s", cl->data);
575
576
if(result) {
577
warnf("skipped provided cookie, the cookie header "
578
"would go over %u bytes", MAX_COOKIE_LINE);
579
return result;
580
}
581
}
582
583
my_setopt_str(curl, CURLOPT_COOKIE, curlx_dyn_ptr(&cookies));
584
curlx_dyn_free(&cookies);
585
}
586
587
if(config->cookiefiles) {
588
struct curl_slist *cfl;
589
590
for(cfl = config->cookiefiles; cfl; cfl = cfl->next)
591
my_setopt_str(curl, CURLOPT_COOKIEFILE, cfl->data);
592
}
593
594
/* new in libcurl 7.9 */
595
if(config->cookiejar)
596
my_setopt_str(curl, CURLOPT_COOKIEJAR, config->cookiejar);
597
598
/* new in libcurl 7.9.7 */
599
my_setopt_long(curl, CURLOPT_COOKIESESSION, config->cookiesession);
600
601
return result;
602
}
603
604
static CURLcode tcp_setopts(struct OperationConfig *config,
605
CURL *curl)
606
{
607
if(!config->tcp_nodelay)
608
my_setopt_long(curl, CURLOPT_TCP_NODELAY, 0);
609
610
if(config->tcp_fastopen)
611
my_setopt_long(curl, CURLOPT_TCP_FASTOPEN, 1);
612
613
if(config->mptcp)
614
my_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, tool_socket_open_mptcp_cb);
615
616
/* curl 7.17.1 */
617
if(!config->nokeepalive) {
618
my_setopt_long(curl, CURLOPT_TCP_KEEPALIVE, 1);
619
if(config->alivetime) {
620
my_setopt_long(curl, CURLOPT_TCP_KEEPIDLE, config->alivetime);
621
my_setopt_long(curl, CURLOPT_TCP_KEEPINTVL, config->alivetime);
622
}
623
if(config->alivecnt)
624
my_setopt_long(curl, CURLOPT_TCP_KEEPCNT, config->alivecnt);
625
}
626
else
627
my_setopt_long(curl, CURLOPT_TCP_KEEPALIVE, 0);
628
return CURLE_OK;
629
}
630
631
static CURLcode ftp_setopts(struct OperationConfig *config, CURL *curl)
632
{
633
my_setopt_str(curl, CURLOPT_FTPPORT, config->ftpport);
634
635
/* new in libcurl 7.9.2: */
636
if(config->disable_epsv)
637
/* disable it */
638
my_setopt_long(curl, CURLOPT_FTP_USE_EPSV, 0);
639
640
/* new in libcurl 7.10.5 */
641
if(config->disable_eprt)
642
/* disable it */
643
my_setopt_long(curl, CURLOPT_FTP_USE_EPRT, 0);
644
645
/* new in curl 7.16.1 */
646
if(config->ftp_ssl_ccc)
647
my_setopt_enum(curl, CURLOPT_FTP_SSL_CCC, config->ftp_ssl_ccc_mode);
648
649
my_setopt_str(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account);
650
651
/* curl 7.14.2 */
652
my_setopt_long(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip);
653
654
/* curl 7.15.1 */
655
my_setopt_long(curl, CURLOPT_FTP_FILEMETHOD, config->ftp_filemethod);
656
657
/* curl 7.15.5 */
658
my_setopt_str(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER,
659
config->ftp_alternative_to_user);
660
661
/* curl 7.20.x */
662
if(config->ftp_pret)
663
my_setopt_long(curl, CURLOPT_FTP_USE_PRET, 1);
664
665
return CURLE_OK;
666
}
667
668
static void gen_trace_setopts(struct OperationConfig *config, CURL *curl)
669
{
670
if(global->tracetype != TRACE_NONE) {
671
my_setopt(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb);
672
my_setopt(curl, CURLOPT_DEBUGDATA, config);
673
my_setopt_long(curl, CURLOPT_VERBOSE, 1L);
674
}
675
}
676
677
static void gen_cb_setopts(struct OperationConfig *config,
678
struct per_transfer *per,
679
CURL *curl)
680
{
681
(void)config; /* when --libcurl is disabled */
682
683
/* where to store */
684
my_setopt(curl, CURLOPT_WRITEDATA, per);
685
my_setopt(curl, CURLOPT_INTERLEAVEDATA, per);
686
687
/* what call to write */
688
my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb);
689
690
/* what to read */
691
my_setopt(curl, CURLOPT_READDATA, per);
692
my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb);
693
694
/* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what
695
CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */
696
my_setopt(curl, CURLOPT_SEEKDATA, per);
697
my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb);
698
699
if((global->progressmode == CURL_PROGRESS_BAR) &&
700
!global->noprogress && !global->silent) {
701
/* we want the alternative style, then we have to implement it
702
ourselves! */
703
my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_progress_cb);
704
my_setopt(curl, CURLOPT_XFERINFODATA, per);
705
}
706
else if(per->uploadfile && !strcmp(per->uploadfile, ".")) {
707
/* when reading from stdin in non-blocking mode, we use the progress
708
function to unpause a busy read */
709
my_setopt_long(curl, CURLOPT_NOPROGRESS, 0);
710
my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_readbusy_cb);
711
my_setopt(curl, CURLOPT_XFERINFODATA, per);
712
}
713
714
my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb);
715
my_setopt(curl, CURLOPT_HEADERDATA, per);
716
}
717
718
static CURLcode proxy_setopts(struct OperationConfig *config, CURL *curl)
719
{
720
if(config->proxy) {
721
CURLcode result = my_setopt_str(curl, CURLOPT_PROXY, config->proxy);
722
723
if(result) {
724
errorf("proxy support is disabled in this libcurl");
725
config->synthetic_error = TRUE;
726
return CURLE_NOT_BUILT_IN;
727
}
728
}
729
730
/* new in libcurl 7.5 */
731
if(config->proxy)
732
my_setopt_enum(curl, CURLOPT_PROXYTYPE, config->proxyver);
733
734
my_setopt_str(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
735
736
/* new in libcurl 7.3 */
737
my_setopt_long(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel);
738
739
/* new in libcurl 7.52.0 */
740
if(config->preproxy)
741
my_setopt_str(curl, CURLOPT_PRE_PROXY, config->preproxy);
742
743
/* new in libcurl 7.10.6 */
744
if(config->proxyanyauth)
745
my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
746
else if(config->proxynegotiate)
747
my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_GSSNEGOTIATE);
748
else if(config->proxyntlm)
749
my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
750
else if(config->proxydigest)
751
my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
752
else if(config->proxybasic)
753
my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
754
755
/* new in libcurl 7.19.4 */
756
my_setopt_str(curl, CURLOPT_NOPROXY, config->noproxy);
757
758
my_setopt_long(curl, CURLOPT_SUPPRESS_CONNECT_HEADERS,
759
config->suppress_connect_headers);
760
761
/* new in curl 7.43.0 */
762
if(config->proxy_service_name)
763
my_setopt_str(curl, CURLOPT_PROXY_SERVICE_NAME,
764
config->proxy_service_name);
765
766
/* new in 7.60.0 */
767
if(config->haproxy_protocol)
768
my_setopt_long(curl, CURLOPT_HAPROXYPROTOCOL, 1);
769
770
/* new in 8.2.0 */
771
if(config->haproxy_clientip)
772
my_setopt_str(curl, CURLOPT_HAPROXY_CLIENT_IP, config->haproxy_clientip);
773
774
return CURLE_OK;
775
}
776
777
static void tls_srp_setopts(struct OperationConfig *config, CURL *curl)
778
{
779
if(config->tls_username)
780
my_setopt_str(curl, CURLOPT_TLSAUTH_USERNAME, config->tls_username);
781
if(config->tls_password)
782
my_setopt_str(curl, CURLOPT_TLSAUTH_PASSWORD, config->tls_password);
783
if(config->tls_authtype)
784
my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE, config->tls_authtype);
785
if(config->proxy_tls_username)
786
my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_USERNAME,
787
config->proxy_tls_username);
788
if(config->proxy_tls_password)
789
my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD,
790
config->proxy_tls_password);
791
if(config->proxy_tls_authtype)
792
my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_TYPE,
793
config->proxy_tls_authtype);
794
}
795
796
CURLcode config2setopts(struct OperationConfig *config,
797
struct per_transfer *per,
798
CURL *curl,
799
CURLSH *share)
800
{
801
const char *use_proto;
802
CURLcode result = url_proto_and_rewrite(&per->url, config, &use_proto);
803
804
/* Avoid having this setopt added to the --libcurl source output. */
805
if(!result)
806
result = curl_easy_setopt(curl, CURLOPT_SHARE, share);
807
if(result)
808
return result;
809
810
#ifndef DEBUGBUILD
811
/* On most modern OSes, exiting works thoroughly,
812
we will clean everything up via exit(), so do not bother with
813
slow cleanups. Crappy ones might need to skip this.
814
Note: avoid having this setopt added to the --libcurl source
815
output. */
816
result = curl_easy_setopt(curl, CURLOPT_QUICK_EXIT, 1L);
817
if(result)
818
return result;
819
#endif
820
821
gen_trace_setopts(config, curl);
822
823
{
824
#ifdef DEBUGBUILD
825
char *env = getenv("CURL_BUFFERSIZE");
826
if(env) {
827
curl_off_t num;
828
const char *p = env;
829
if(!curlx_str_number(&p, &num, LONG_MAX))
830
my_setopt_long(curl, CURLOPT_BUFFERSIZE, (long)num);
831
}
832
else
833
#endif
834
if(config->recvpersecond && (config->recvpersecond < BUFFER_SIZE))
835
/* use a smaller sized buffer for better sleeps */
836
my_setopt_long(curl, CURLOPT_BUFFERSIZE, (long)config->recvpersecond);
837
else
838
my_setopt_long(curl, CURLOPT_BUFFERSIZE, BUFFER_SIZE);
839
}
840
841
my_setopt_str(curl, CURLOPT_URL, per->url);
842
my_setopt_long(curl, CURLOPT_NOPROGRESS,
843
global->noprogress || global->silent);
844
/* call after the line above. It may override CURLOPT_NOPROGRESS */
845
gen_cb_setopts(config, per, curl);
846
847
my_setopt_long(curl, CURLOPT_NOBODY, config->no_body);
848
my_setopt_str(curl, CURLOPT_XOAUTH2_BEARER, config->oauth_bearer);
849
850
result = proxy_setopts(config, curl);
851
if(result)
852
return result;
853
854
my_setopt_long(curl, CURLOPT_FAILONERROR, config->fail == FAIL_WO_BODY);
855
my_setopt_str(curl, CURLOPT_REQUEST_TARGET, config->request_target);
856
my_setopt_long(curl, CURLOPT_UPLOAD, !!per->uploadfile);
857
my_setopt_long(curl, CURLOPT_DIRLISTONLY, config->dirlistonly);
858
my_setopt_long(curl, CURLOPT_APPEND, config->ftp_append);
859
860
if(config->netrc_opt)
861
my_setopt_enum(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
862
else if(config->netrc || config->netrc_file)
863
my_setopt_enum(curl, CURLOPT_NETRC, CURL_NETRC_REQUIRED);
864
else
865
my_setopt_enum(curl, CURLOPT_NETRC, CURL_NETRC_IGNORED);
866
867
my_setopt_str(curl, CURLOPT_NETRC_FILE, config->netrc_file);
868
my_setopt_long(curl, CURLOPT_TRANSFERTEXT, config->use_ascii);
869
my_setopt_str(curl, CURLOPT_LOGIN_OPTIONS, config->login_options);
870
my_setopt_str(curl, CURLOPT_USERPWD, config->userpwd);
871
my_setopt_str(curl, CURLOPT_RANGE, config->range);
872
my_setopt(curl, CURLOPT_ERRORBUFFER, per->errorbuffer);
873
my_setopt_long(curl, CURLOPT_TIMEOUT_MS, config->timeout_ms);
874
875
switch(config->httpreq) {
876
case TOOL_HTTPREQ_SIMPLEPOST:
877
if(config->resume_from) {
878
errorf("cannot mix --continue-at with --data");
879
result = CURLE_FAILED_INIT;
880
}
881
else {
882
my_setopt_str(curl, CURLOPT_POSTFIELDS,
883
curlx_dyn_ptr(&config->postdata));
884
my_setopt_offt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
885
curlx_dyn_len(&config->postdata));
886
}
887
break;
888
case TOOL_HTTPREQ_MIMEPOST:
889
/* free previous remainders */
890
curl_mime_free(config->mimepost);
891
config->mimepost = NULL;
892
if(config->resume_from) {
893
errorf("cannot mix --continue-at with --form");
894
result = CURLE_FAILED_INIT;
895
}
896
else {
897
result = tool2curlmime(curl, config->mimeroot, &config->mimepost);
898
if(!result)
899
my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost);
900
}
901
break;
902
default:
903
break;
904
}
905
if(result)
906
return result;
907
908
if(config->mime_options)
909
my_setopt_long(curl, CURLOPT_MIME_OPTIONS, config->mime_options);
910
911
if(config->authtype)
912
my_setopt_bitmask(curl, CURLOPT_HTTPAUTH, config->authtype);
913
914
my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers);
915
916
if(proto_http || proto_rtsp) {
917
my_setopt_str(curl, CURLOPT_REFERER, config->referer);
918
my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent);
919
}
920
921
if(use_proto == proto_http || use_proto == proto_https) {
922
result = http_setopts(config, curl);
923
if(!result)
924
result = cookie_setopts(config, curl);
925
if(result)
926
return result;
927
}
928
929
if(use_proto == proto_ftp || use_proto == proto_ftps) {
930
result = ftp_setopts(config, curl);
931
if(result)
932
return result;
933
}
934
935
my_setopt_long(curl, CURLOPT_LOW_SPEED_LIMIT, config->low_speed_limit);
936
my_setopt_long(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
937
my_setopt_offt(curl, CURLOPT_MAX_SEND_SPEED_LARGE, config->sendpersecond);
938
my_setopt_offt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, config->recvpersecond);
939
940
if(config->use_resume)
941
my_setopt_offt(curl, CURLOPT_RESUME_FROM_LARGE, config->resume_from);
942
else
943
my_setopt_offt(curl, CURLOPT_RESUME_FROM_LARGE, 0);
944
945
my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd);
946
my_setopt_str(curl, CURLOPT_PROXY_KEYPASSWD, config->proxy_key_passwd);
947
948
if(use_proto == proto_scp || use_proto == proto_sftp) {
949
result = ssh_setopts(config, curl);
950
if(result)
951
return result;
952
}
953
954
if(feature_ssl) {
955
result = ssl_setopts(config, curl);
956
if(result)
957
return result;
958
}
959
960
if(config->path_as_is)
961
my_setopt_long(curl, CURLOPT_PATH_AS_IS, 1);
962
963
if(config->no_body || config->remote_time) {
964
/* no body or use remote time */
965
my_setopt_long(curl, CURLOPT_FILETIME, 1);
966
}
967
968
my_setopt_long(curl, CURLOPT_CRLF, config->crlf);
969
my_setopt_slist(curl, CURLOPT_QUOTE, config->quote);
970
my_setopt_slist(curl, CURLOPT_POSTQUOTE, config->postquote);
971
my_setopt_slist(curl, CURLOPT_PREQUOTE, config->prequote);
972
973
my_setopt_enum(curl, CURLOPT_TIMECONDITION, config->timecond);
974
my_setopt_offt(curl, CURLOPT_TIMEVALUE_LARGE, config->condtime);
975
my_setopt_str(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
976
customrequest_helper(config->httpreq, config->customrequest);
977
my_setopt(curl, CURLOPT_STDERR, tool_stderr);
978
my_setopt_str(curl, CURLOPT_INTERFACE, config->iface);
979
progressbarinit(&per->progressbar, config);
980
my_setopt_str(curl, CURLOPT_DNS_SERVERS, config->dns_servers);
981
my_setopt_str(curl, CURLOPT_DNS_INTERFACE, config->dns_interface);
982
my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP4, config->dns_ipv4_addr);
983
my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr);
984
my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
985
my_setopt_long(curl, CURLOPT_CONNECTTIMEOUT_MS, config->connecttimeout_ms);
986
my_setopt_str(curl, CURLOPT_DOH_URL, config->doh_url);
987
my_setopt_long(curl, CURLOPT_FTP_CREATE_MISSING_DIRS,
988
(config->ftp_create_dirs ?
989
CURLFTP_CREATE_DIR_RETRY : CURLFTP_CREATE_DIR_NONE));
990
my_setopt_offt(curl, CURLOPT_MAXFILESIZE_LARGE,
991
config->max_filesize);
992
my_setopt_long(curl, CURLOPT_IPRESOLVE, config->ip_version);
993
if(config->socks5_gssapi_nec)
994
my_setopt_long(curl, CURLOPT_SOCKS5_GSSAPI_NEC, 1);
995
if(config->socks5_auth)
996
my_setopt_bitmask(curl, CURLOPT_SOCKS5_AUTH, config->socks5_auth);
997
my_setopt_str(curl, CURLOPT_SERVICE_NAME, config->service_name);
998
my_setopt_long(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl);
999
1000
if(config->localport) {
1001
my_setopt_long(curl, CURLOPT_LOCALPORT, config->localport);
1002
my_setopt_long(curl, CURLOPT_LOCALPORTRANGE, config->localportrange);
1003
}
1004
1005
if(config->raw) {
1006
my_setopt_long(curl, CURLOPT_HTTP_CONTENT_DECODING, 0);
1007
my_setopt_long(curl, CURLOPT_HTTP_TRANSFER_DECODING, 0);
1008
}
1009
1010
result = tcp_setopts(config, curl);
1011
if(result)
1012
return result;
1013
1014
if(config->tftp_blksize && proto_tftp)
1015
my_setopt_long(curl, CURLOPT_TFTP_BLKSIZE, config->tftp_blksize);
1016
1017
my_setopt_str(curl, CURLOPT_MAIL_FROM, config->mail_from);
1018
my_setopt_slist(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt);
1019
my_setopt_long(curl, CURLOPT_MAIL_RCPT_ALLOWFAILS,
1020
config->mail_rcpt_allowfails);
1021
if(config->create_file_mode)
1022
my_setopt_long(curl, CURLOPT_NEW_FILE_PERMS, config->create_file_mode);
1023
1024
if(config->proto_present)
1025
my_setopt_str(curl, CURLOPT_PROTOCOLS_STR, config->proto_str);
1026
if(config->proto_redir_present)
1027
my_setopt_str(curl, CURLOPT_REDIR_PROTOCOLS_STR, config->proto_redir_str);
1028
1029
my_setopt_slist(curl, CURLOPT_RESOLVE, config->resolve);
1030
my_setopt_slist(curl, CURLOPT_CONNECT_TO, config->connect_to);
1031
1032
if(feature_tls_srp)
1033
tls_srp_setopts(config, curl);
1034
1035
if(config->gssapi_delegation)
1036
my_setopt_long(curl, CURLOPT_GSSAPI_DELEGATION, config->gssapi_delegation);
1037
1038
my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
1039
my_setopt_str(curl, CURLOPT_SASL_AUTHZID, config->sasl_authzid);
1040
my_setopt_long(curl, CURLOPT_SASL_IR, config->sasl_ir);
1041
1042
if(config->unix_socket_path) {
1043
if(config->abstract_unix_socket) {
1044
my_setopt_str(curl, CURLOPT_ABSTRACT_UNIX_SOCKET,
1045
config->unix_socket_path);
1046
}
1047
else {
1048
my_setopt_str(curl, CURLOPT_UNIX_SOCKET_PATH,
1049
config->unix_socket_path);
1050
}
1051
}
1052
1053
my_setopt_str(curl, CURLOPT_DEFAULT_PROTOCOL, config->proto_default);
1054
my_setopt_long(curl, CURLOPT_TFTP_NO_OPTIONS,
1055
config->tftp_no_options && proto_tftp);
1056
1057
if(config->happy_eyeballs_timeout_ms != CURL_HET_DEFAULT)
1058
my_setopt_long(curl, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS,
1059
config->happy_eyeballs_timeout_ms);
1060
1061
my_setopt_long(curl, CURLOPT_DISALLOW_USERNAME_IN_URL,
1062
config->disallow_username_in_url);
1063
1064
if(config->ip_tos > 0 || config->vlan_priority > 0) {
1065
#if defined(IP_TOS) || defined(IPV6_TCLASS) || defined(SO_PRIORITY)
1066
my_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
1067
my_setopt(curl, CURLOPT_SOCKOPTDATA, config);
1068
#else
1069
if(config->ip_tos > 0) {
1070
errorf("Type of service is not supported in this build.");
1071
result = CURLE_NOT_BUILT_IN;
1072
}
1073
if(config->vlan_priority > 0) {
1074
errorf("VLAN priority is not supported in this build.");
1075
result = CURLE_NOT_BUILT_IN;
1076
}
1077
#endif
1078
}
1079
my_setopt_long(curl, CURLOPT_UPLOAD_FLAGS, config->upload_flags);
1080
return result;
1081
}
1082
1083