1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, 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
25 #include "curl_setup.h"
26
27 #include <limits.h>
28
29 #ifdef HAVE_NETINET_IN_H
30 #include <netinet/in.h>
31 #endif
32
33 #ifdef HAVE_LINUX_TCP_H
34 #include <linux/tcp.h>
35 #elif defined(HAVE_NETINET_TCP_H)
36 #include <netinet/tcp.h>
37 #endif
38
39 #include "urldata.h"
40 #include "url.h"
41 #include "progress.h"
42 #include "content_encoding.h"
43 #include "strcase.h"
44 #include "share.h"
45 #include "vtls/vtls.h"
46 #include "warnless.h"
47 #include "sendf.h"
48 #include "http2.h"
49 #include "setopt.h"
50 #include "multiif.h"
51 #include "altsvc.h"
52 #include "hsts.h"
53 #include "tftp.h"
54 #include "strdup.h"
55 #include "escape.h"
56
57 /* The last 3 #include files should be in this order */
58 #include "curl_printf.h"
59 #include "curl_memory.h"
60 #include "memdebug.h"
61
Curl_setstropt(char ** charp,const char * s)62 CURLcode Curl_setstropt(char **charp, const char *s)
63 {
64 /* Release the previous storage at `charp' and replace by a dynamic storage
65 copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
66
67 Curl_safefree(*charp);
68
69 if(s) {
70 if(strlen(s) > CURL_MAX_INPUT_LENGTH)
71 return CURLE_BAD_FUNCTION_ARGUMENT;
72
73 *charp = strdup(s);
74 if(!*charp)
75 return CURLE_OUT_OF_MEMORY;
76 }
77
78 return CURLE_OK;
79 }
80
Curl_setblobopt(struct curl_blob ** blobp,const struct curl_blob * blob)81 CURLcode Curl_setblobopt(struct curl_blob **blobp,
82 const struct curl_blob *blob)
83 {
84 /* free the previous storage at `blobp' and replace by a dynamic storage
85 copy of blob. If CURL_BLOB_COPY is set, the data is copied. */
86
87 Curl_safefree(*blobp);
88
89 if(blob) {
90 struct curl_blob *nblob;
91 if(blob->len > CURL_MAX_INPUT_LENGTH)
92 return CURLE_BAD_FUNCTION_ARGUMENT;
93 nblob = (struct curl_blob *)
94 malloc(sizeof(struct curl_blob) +
95 ((blob->flags & CURL_BLOB_COPY) ? blob->len : 0));
96 if(!nblob)
97 return CURLE_OUT_OF_MEMORY;
98 *nblob = *blob;
99 if(blob->flags & CURL_BLOB_COPY) {
100 /* put the data after the blob struct in memory */
101 nblob->data = (char *)nblob + sizeof(struct curl_blob);
102 memcpy(nblob->data, blob->data, blob->len);
103 }
104
105 *blobp = nblob;
106 return CURLE_OK;
107 }
108
109 return CURLE_OK;
110 }
111
setstropt_userpwd(char * option,char ** userp,char ** passwdp)112 static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
113 {
114 char *user = NULL;
115 char *passwd = NULL;
116
117 DEBUGASSERT(userp);
118 DEBUGASSERT(passwdp);
119
120 /* Parse the login details if specified. It not then we treat NULL as a hint
121 to clear the existing data */
122 if(option) {
123 size_t len = strlen(option);
124 CURLcode result;
125 if(len > CURL_MAX_INPUT_LENGTH)
126 return CURLE_BAD_FUNCTION_ARGUMENT;
127
128 result = Curl_parse_login_details(option, len, &user, &passwd, NULL);
129 if(result)
130 return result;
131 }
132
133 free(*userp);
134 *userp = user;
135
136 free(*passwdp);
137 *passwdp = passwd;
138
139 return CURLE_OK;
140 }
141
setstropt_interface(char * option,char ** devp,char ** ifacep,char ** hostp)142 static CURLcode setstropt_interface(
143 char *option, char **devp, char **ifacep, char **hostp)
144 {
145 char *dev = NULL;
146 char *iface = NULL;
147 char *host = NULL;
148 size_t len;
149 CURLcode result;
150
151 DEBUGASSERT(devp);
152 DEBUGASSERT(ifacep);
153 DEBUGASSERT(hostp);
154
155 /* Parse the interface details */
156 if(!option || !*option)
157 return CURLE_BAD_FUNCTION_ARGUMENT;
158 len = strlen(option);
159 if(len > 255)
160 return CURLE_BAD_FUNCTION_ARGUMENT;
161
162 result = Curl_parse_interface(option, len, &dev, &iface, &host);
163 if(result)
164 return result;
165
166 free(*devp);
167 *devp = dev;
168
169 free(*ifacep);
170 *ifacep = iface;
171
172 free(*hostp);
173 *hostp = host;
174
175 return CURLE_OK;
176 }
177
178 #define C_SSLVERSION_VALUE(x) (x & 0xffff)
179 #define C_SSLVERSION_MAX_VALUE(x) ((unsigned long)x & 0xffff0000)
180
protocol2num(const char * str,curl_prot_t * val)181 static CURLcode protocol2num(const char *str, curl_prot_t *val)
182 {
183 /*
184 * We are asked to cherry-pick protocols, so play it safe and disallow all
185 * protocols to start with, and re-add the wanted ones back in.
186 */
187 *val = 0;
188
189 if(!str)
190 return CURLE_BAD_FUNCTION_ARGUMENT;
191
192 if(curl_strequal(str, "all")) {
193 *val = ~(curl_prot_t) 0;
194 return CURLE_OK;
195 }
196
197 do {
198 const char *token = str;
199 size_t tlen;
200
201 str = strchr(str, ',');
202 tlen = str? (size_t) (str - token): strlen(token);
203 if(tlen) {
204 const struct Curl_handler *h = Curl_getn_scheme_handler(token, tlen);
205
206 if(!h)
207 return CURLE_UNSUPPORTED_PROTOCOL;
208
209 *val |= h->protocol;
210 }
211 } while(str && str++);
212
213 if(!*val)
214 /* no protocol listed */
215 return CURLE_BAD_FUNCTION_ARGUMENT;
216 return CURLE_OK;
217 }
218
219 /*
220 * Do not make Curl_vsetopt() static: it is called from
221 * packages/OS400/ccsidcurl.c.
222 */
Curl_vsetopt(struct Curl_easy * data,CURLoption option,va_list param)223 CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
224 {
225 char *argptr;
226 CURLcode result = CURLE_OK;
227 long arg;
228 unsigned long uarg;
229 curl_off_t bigsize;
230
231 switch(option) {
232 case CURLOPT_DNS_CACHE_TIMEOUT:
233 arg = va_arg(param, long);
234 if(arg < -1)
235 return CURLE_BAD_FUNCTION_ARGUMENT;
236 else if(arg > INT_MAX)
237 arg = INT_MAX;
238
239 data->set.dns_cache_timeout = (int)arg;
240 break;
241 case CURLOPT_CA_CACHE_TIMEOUT:
242 if(Curl_ssl_supports(data, SSLSUPP_CA_CACHE)) {
243 arg = va_arg(param, long);
244 if(arg < -1)
245 return CURLE_BAD_FUNCTION_ARGUMENT;
246 else if(arg > INT_MAX)
247 arg = INT_MAX;
248
249 data->set.general_ssl.ca_cache_timeout = (int)arg;
250 }
251 else
252 return CURLE_NOT_BUILT_IN;
253 break;
254 case CURLOPT_DNS_USE_GLOBAL_CACHE:
255 /* deprecated */
256 break;
257 case CURLOPT_SSL_CIPHER_LIST:
258 /* set a list of cipher we want to use in the SSL connection */
259 result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST],
260 va_arg(param, char *));
261 break;
262 #ifndef CURL_DISABLE_PROXY
263 case CURLOPT_PROXY_SSL_CIPHER_LIST:
264 /* set a list of cipher we want to use in the SSL connection for proxy */
265 result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY],
266 va_arg(param, char *));
267 break;
268 #endif
269 case CURLOPT_TLS13_CIPHERS:
270 if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES)) {
271 /* set preferred list of TLS 1.3 cipher suites */
272 result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST],
273 va_arg(param, char *));
274 }
275 else
276 return CURLE_NOT_BUILT_IN;
277 break;
278 #ifndef CURL_DISABLE_PROXY
279 case CURLOPT_PROXY_TLS13_CIPHERS:
280 if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES)) {
281 /* set preferred list of TLS 1.3 cipher suites for proxy */
282 result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_PROXY],
283 va_arg(param, char *));
284 }
285 else
286 return CURLE_NOT_BUILT_IN;
287 break;
288 #endif
289 case CURLOPT_RANDOM_FILE:
290 break;
291 case CURLOPT_EGDSOCKET:
292 break;
293 case CURLOPT_MAXCONNECTS:
294 /*
295 * Set the absolute number of maximum simultaneous alive connection that
296 * libcurl is allowed to have.
297 */
298 uarg = va_arg(param, unsigned long);
299 if(uarg > UINT_MAX)
300 return CURLE_BAD_FUNCTION_ARGUMENT;
301 data->set.maxconnects = (unsigned int)uarg;
302 break;
303 case CURLOPT_FORBID_REUSE:
304 /*
305 * When this transfer is done, it must not be left to be reused by a
306 * subsequent transfer but shall be closed immediately.
307 */
308 data->set.reuse_forbid = (0 != va_arg(param, long));
309 break;
310 case CURLOPT_FRESH_CONNECT:
311 /*
312 * This transfer shall not use a previously cached connection but
313 * should be made with a fresh new connect!
314 */
315 data->set.reuse_fresh = (0 != va_arg(param, long));
316 break;
317 case CURLOPT_VERBOSE:
318 /*
319 * Verbose means infof() calls that give a lot of information about
320 * the connection and transfer procedures as well as internal choices.
321 */
322 data->set.verbose = (0 != va_arg(param, long));
323 break;
324 case CURLOPT_HEADER:
325 /*
326 * Set to include the header in the general data output stream.
327 */
328 data->set.include_header = (0 != va_arg(param, long));
329 break;
330 case CURLOPT_NOPROGRESS:
331 /*
332 * Shut off the internal supported progress meter
333 */
334 data->set.hide_progress = (0 != va_arg(param, long));
335 if(data->set.hide_progress)
336 data->progress.flags |= PGRS_HIDE;
337 else
338 data->progress.flags &= ~PGRS_HIDE;
339 break;
340 case CURLOPT_NOBODY:
341 /*
342 * Do not include the body part in the output data stream.
343 */
344 data->set.opt_no_body = (0 != va_arg(param, long));
345 #ifndef CURL_DISABLE_HTTP
346 if(data->set.opt_no_body)
347 /* in HTTP lingo, no body means using the HEAD request... */
348 data->set.method = HTTPREQ_HEAD;
349 else if(data->set.method == HTTPREQ_HEAD)
350 data->set.method = HTTPREQ_GET;
351 #endif
352 break;
353 case CURLOPT_FAILONERROR:
354 /*
355 * Don't output the >=400 error code HTML-page, but instead only
356 * return error.
357 */
358 data->set.http_fail_on_error = (0 != va_arg(param, long));
359 break;
360 case CURLOPT_KEEP_SENDING_ON_ERROR:
361 data->set.http_keep_sending_on_error = (0 != va_arg(param, long));
362 break;
363 case CURLOPT_UPLOAD:
364 case CURLOPT_PUT:
365 /*
366 * We want to sent data to the remote host. If this is HTTP, that equals
367 * using the PUT request.
368 */
369 arg = va_arg(param, long);
370 if(arg) {
371 /* If this is HTTP, PUT is what's needed to "upload" */
372 data->set.method = HTTPREQ_PUT;
373 data->set.opt_no_body = FALSE; /* this is implied */
374 }
375 else
376 /* In HTTP, the opposite of upload is GET (unless NOBODY is true as
377 then this can be changed to HEAD later on) */
378 data->set.method = HTTPREQ_GET;
379 break;
380 case CURLOPT_REQUEST_TARGET:
381 result = Curl_setstropt(&data->set.str[STRING_TARGET],
382 va_arg(param, char *));
383 break;
384 case CURLOPT_FILETIME:
385 /*
386 * Try to get the file time of the remote document. The time will
387 * later (possibly) become available using curl_easy_getinfo().
388 */
389 data->set.get_filetime = (0 != va_arg(param, long));
390 break;
391 case CURLOPT_SERVER_RESPONSE_TIMEOUT:
392 /*
393 * Option that specifies how quickly a server response must be obtained
394 * before it is considered failure. For pingpong protocols.
395 */
396 arg = va_arg(param, long);
397 if((arg >= 0) && (arg <= (INT_MAX/1000)))
398 data->set.server_response_timeout = (unsigned int)arg * 1000;
399 else
400 return CURLE_BAD_FUNCTION_ARGUMENT;
401 break;
402 case CURLOPT_SERVER_RESPONSE_TIMEOUT_MS:
403 /*
404 * Option that specifies how quickly a server response must be obtained
405 * before it is considered failure. For pingpong protocols.
406 */
407 arg = va_arg(param, long);
408 if((arg >= 0) && (arg <= INT_MAX))
409 data->set.server_response_timeout = (unsigned int)arg;
410 else
411 return CURLE_BAD_FUNCTION_ARGUMENT;
412 break;
413 #ifndef CURL_DISABLE_TFTP
414 case CURLOPT_TFTP_NO_OPTIONS:
415 /*
416 * Option that prevents libcurl from sending TFTP option requests to the
417 * server.
418 */
419 data->set.tftp_no_options = va_arg(param, long) != 0;
420 break;
421 case CURLOPT_TFTP_BLKSIZE:
422 /*
423 * TFTP option that specifies the block size to use for data transmission.
424 */
425 arg = va_arg(param, long);
426 if(arg > TFTP_BLKSIZE_MAX || arg < TFTP_BLKSIZE_MIN)
427 return CURLE_BAD_FUNCTION_ARGUMENT;
428 data->set.tftp_blksize = arg;
429 break;
430 #endif
431 #ifndef CURL_DISABLE_NETRC
432 case CURLOPT_NETRC:
433 /*
434 * Parse the $HOME/.netrc file
435 */
436 arg = va_arg(param, long);
437 if((arg < CURL_NETRC_IGNORED) || (arg >= CURL_NETRC_LAST))
438 return CURLE_BAD_FUNCTION_ARGUMENT;
439 data->set.use_netrc = (unsigned char)arg;
440 break;
441 case CURLOPT_NETRC_FILE:
442 /*
443 * Use this file instead of the $HOME/.netrc file
444 */
445 result = Curl_setstropt(&data->set.str[STRING_NETRC_FILE],
446 va_arg(param, char *));
447 break;
448 #endif
449 case CURLOPT_TRANSFERTEXT:
450 /*
451 * This option was previously named 'FTPASCII'. Renamed to work with
452 * more protocols than merely FTP.
453 *
454 * Transfer using ASCII (instead of BINARY).
455 */
456 data->set.prefer_ascii = (0 != va_arg(param, long));
457 break;
458 case CURLOPT_TIMECONDITION:
459 /*
460 * Set HTTP time condition. This must be one of the defines in the
461 * curl/curl.h header file.
462 */
463 arg = va_arg(param, long);
464 if((arg < CURL_TIMECOND_NONE) || (arg >= CURL_TIMECOND_LAST))
465 return CURLE_BAD_FUNCTION_ARGUMENT;
466 data->set.timecondition = (unsigned char)(curl_TimeCond)arg;
467 break;
468 case CURLOPT_TIMEVALUE:
469 /*
470 * This is the value to compare with the remote document with the
471 * method set with CURLOPT_TIMECONDITION
472 */
473 data->set.timevalue = (time_t)va_arg(param, long);
474 break;
475
476 case CURLOPT_TIMEVALUE_LARGE:
477 /*
478 * This is the value to compare with the remote document with the
479 * method set with CURLOPT_TIMECONDITION
480 */
481 data->set.timevalue = (time_t)va_arg(param, curl_off_t);
482 break;
483
484 case CURLOPT_SSLVERSION:
485 #ifndef CURL_DISABLE_PROXY
486 case CURLOPT_PROXY_SSLVERSION:
487 #endif
488 /*
489 * Set explicit SSL version to try to connect with, as some SSL
490 * implementations are lame.
491 */
492 #ifdef USE_SSL
493 {
494 long version, version_max;
495 struct ssl_primary_config *primary = &data->set.ssl.primary;
496 #ifndef CURL_DISABLE_PROXY
497 if(option != CURLOPT_SSLVERSION)
498 primary = &data->set.proxy_ssl.primary;
499 #endif
500
501 arg = va_arg(param, long);
502
503 version = C_SSLVERSION_VALUE(arg);
504 version_max = (long)C_SSLVERSION_MAX_VALUE(arg);
505
506 if(version < CURL_SSLVERSION_DEFAULT ||
507 version == CURL_SSLVERSION_SSLv2 ||
508 version == CURL_SSLVERSION_SSLv3 ||
509 version >= CURL_SSLVERSION_LAST ||
510 version_max < CURL_SSLVERSION_MAX_NONE ||
511 version_max >= CURL_SSLVERSION_MAX_LAST)
512 return CURLE_BAD_FUNCTION_ARGUMENT;
513
514 primary->version = (unsigned char)version;
515 primary->version_max = (unsigned int)version_max;
516 }
517 #else
518 result = CURLE_NOT_BUILT_IN;
519 #endif
520 break;
521
522 /* MQTT "borrows" some of the HTTP options */
523 #if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MQTT)
524 case CURLOPT_COPYPOSTFIELDS:
525 /*
526 * A string with POST data. Makes curl HTTP POST. Even if it is NULL.
527 * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to
528 * CURLOPT_COPYPOSTFIELDS and not altered later.
529 */
530 argptr = va_arg(param, char *);
531
532 if(!argptr || data->set.postfieldsize == -1)
533 result = Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr);
534 else {
535 /*
536 * Check that requested length does not overflow the size_t type.
537 */
538
539 if((data->set.postfieldsize < 0) ||
540 ((sizeof(curl_off_t) != sizeof(size_t)) &&
541 (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
542 result = CURLE_OUT_OF_MEMORY;
543 else {
544 /* Allocate even when size == 0. This satisfies the need of possible
545 later address compare to detect the COPYPOSTFIELDS mode, and to
546 mark that postfields is used rather than read function or form
547 data.
548 */
549 char *p = Curl_memdup0(argptr, (size_t)data->set.postfieldsize);
550 if(!p)
551 result = CURLE_OUT_OF_MEMORY;
552 else {
553 free(data->set.str[STRING_COPYPOSTFIELDS]);
554 data->set.str[STRING_COPYPOSTFIELDS] = p;
555 }
556 }
557 }
558
559 data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
560 data->set.method = HTTPREQ_POST;
561 break;
562
563 case CURLOPT_POSTFIELDS:
564 /*
565 * Like above, but use static data instead of copying it.
566 */
567 data->set.postfields = va_arg(param, void *);
568 /* Release old copied data. */
569 Curl_safefree(data->set.str[STRING_COPYPOSTFIELDS]);
570 data->set.method = HTTPREQ_POST;
571 break;
572
573 case CURLOPT_POSTFIELDSIZE:
574 /*
575 * The size of the POSTFIELD data to prevent libcurl to do strlen() to
576 * figure it out. Enables binary posts.
577 */
578 bigsize = va_arg(param, long);
579 if(bigsize < -1)
580 return CURLE_BAD_FUNCTION_ARGUMENT;
581
582 if(data->set.postfieldsize < bigsize &&
583 data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
584 /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
585 Curl_safefree(data->set.str[STRING_COPYPOSTFIELDS]);
586 data->set.postfields = NULL;
587 }
588
589 data->set.postfieldsize = bigsize;
590 break;
591
592 case CURLOPT_POSTFIELDSIZE_LARGE:
593 /*
594 * The size of the POSTFIELD data to prevent libcurl to do strlen() to
595 * figure it out. Enables binary posts.
596 */
597 bigsize = va_arg(param, curl_off_t);
598 if(bigsize < -1)
599 return CURLE_BAD_FUNCTION_ARGUMENT;
600
601 if(data->set.postfieldsize < bigsize &&
602 data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
603 /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
604 Curl_safefree(data->set.str[STRING_COPYPOSTFIELDS]);
605 data->set.postfields = NULL;
606 }
607
608 data->set.postfieldsize = bigsize;
609 break;
610 #endif
611 #ifndef CURL_DISABLE_HTTP
612 case CURLOPT_AUTOREFERER:
613 /*
614 * Switch on automatic referer that gets set if curl follows locations.
615 */
616 data->set.http_auto_referer = (0 != va_arg(param, long));
617 break;
618
619 case CURLOPT_ACCEPT_ENCODING:
620 /*
621 * String to use at the value of Accept-Encoding header.
622 *
623 * If the encoding is set to "" we use an Accept-Encoding header that
624 * encompasses all the encodings we support.
625 * If the encoding is set to NULL we don't send an Accept-Encoding header
626 * and ignore an received Content-Encoding header.
627 *
628 */
629 argptr = va_arg(param, char *);
630 if(argptr && !*argptr) {
631 char all[256];
632 Curl_all_content_encodings(all, sizeof(all));
633 result = Curl_setstropt(&data->set.str[STRING_ENCODING], all);
634 }
635 else
636 result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
637 break;
638
639 case CURLOPT_TRANSFER_ENCODING:
640 data->set.http_transfer_encoding = (0 != va_arg(param, long));
641 break;
642
643 case CURLOPT_FOLLOWLOCATION:
644 /*
645 * Follow Location: header hints on an HTTP-server.
646 */
647 data->set.http_follow_location = (0 != va_arg(param, long));
648 break;
649
650 case CURLOPT_UNRESTRICTED_AUTH:
651 /*
652 * Send authentication (user+password) when following locations, even when
653 * hostname changed.
654 */
655 data->set.allow_auth_to_other_hosts = (0 != va_arg(param, long));
656 break;
657
658 case CURLOPT_MAXREDIRS:
659 /*
660 * The maximum amount of hops you allow curl to follow Location:
661 * headers. This should mostly be used to detect never-ending loops.
662 */
663 arg = va_arg(param, long);
664 if(arg < -1)
665 return CURLE_BAD_FUNCTION_ARGUMENT;
666 data->set.maxredirs = arg;
667 break;
668
669 case CURLOPT_POSTREDIR:
670 /*
671 * Set the behavior of POST when redirecting
672 * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
673 * CURL_REDIR_POST_301 - POST is kept as POST after 301
674 * CURL_REDIR_POST_302 - POST is kept as POST after 302
675 * CURL_REDIR_POST_303 - POST is kept as POST after 303
676 * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
677 * other - POST is kept as POST after 301 and 302
678 */
679 arg = va_arg(param, long);
680 if(arg < CURL_REDIR_GET_ALL)
681 /* no return error on too high numbers since the bitmask could be
682 extended in a future */
683 return CURLE_BAD_FUNCTION_ARGUMENT;
684 data->set.keep_post = arg & CURL_REDIR_POST_ALL;
685 break;
686
687 case CURLOPT_POST:
688 /* Does this option serve a purpose anymore? Yes it does, when
689 CURLOPT_POSTFIELDS isn't used and the POST data is read off the
690 callback! */
691 if(va_arg(param, long)) {
692 data->set.method = HTTPREQ_POST;
693 data->set.opt_no_body = FALSE; /* this is implied */
694 }
695 else
696 data->set.method = HTTPREQ_GET;
697 break;
698
699 #ifndef CURL_DISABLE_FORM_API
700 case CURLOPT_HTTPPOST:
701 /*
702 * Set to make us do HTTP POST. Legacy API-style.
703 */
704 data->set.httppost = va_arg(param, struct curl_httppost *);
705 data->set.method = HTTPREQ_POST_FORM;
706 data->set.opt_no_body = FALSE; /* this is implied */
707 Curl_mime_cleanpart(data->state.formp);
708 Curl_safefree(data->state.formp);
709 data->state.mimepost = NULL;
710 break;
711 #endif
712
713 #if !defined(CURL_DISABLE_AWS)
714 case CURLOPT_AWS_SIGV4:
715 /*
716 * String that is merged to some authentication
717 * parameters are used by the algorithm.
718 */
719 result = Curl_setstropt(&data->set.str[STRING_AWS_SIGV4],
720 va_arg(param, char *));
721 /*
722 * Basic been set by default it need to be unset here
723 */
724 if(data->set.str[STRING_AWS_SIGV4])
725 data->set.httpauth = CURLAUTH_AWS_SIGV4;
726 break;
727 #endif
728
729 case CURLOPT_REFERER:
730 /*
731 * String to set in the HTTP Referer: field.
732 */
733 if(data->state.referer_alloc) {
734 Curl_safefree(data->state.referer);
735 data->state.referer_alloc = FALSE;
736 }
737 result = Curl_setstropt(&data->set.str[STRING_SET_REFERER],
738 va_arg(param, char *));
739 data->state.referer = data->set.str[STRING_SET_REFERER];
740 break;
741
742 case CURLOPT_USERAGENT:
743 /*
744 * String to use in the HTTP User-Agent field
745 */
746 result = Curl_setstropt(&data->set.str[STRING_USERAGENT],
747 va_arg(param, char *));
748 break;
749
750 #ifndef CURL_DISABLE_PROXY
751 case CURLOPT_PROXYHEADER:
752 /*
753 * Set a list with proxy headers to use (or replace internals with)
754 *
755 * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a
756 * long time we remain doing it this way until CURLOPT_PROXYHEADER is
757 * used. As soon as this option has been used, if set to anything but
758 * NULL, custom headers for proxies are only picked from this list.
759 *
760 * Set this option to NULL to restore the previous behavior.
761 */
762 data->set.proxyheaders = va_arg(param, struct curl_slist *);
763 break;
764 #endif
765 case CURLOPT_HEADEROPT:
766 /*
767 * Set header option.
768 */
769 arg = va_arg(param, long);
770 data->set.sep_headers = !!(arg & CURLHEADER_SEPARATE);
771 break;
772
773 #if !defined(CURL_DISABLE_COOKIES)
774 case CURLOPT_COOKIE:
775 /*
776 * Cookie string to send to the remote server in the request.
777 */
778 result = Curl_setstropt(&data->set.str[STRING_COOKIE],
779 va_arg(param, char *));
780 break;
781
782 case CURLOPT_COOKIEFILE:
783 /*
784 * Set cookie file to read and parse. Can be used multiple times.
785 */
786 argptr = (char *)va_arg(param, void *);
787 if(argptr) {
788 struct curl_slist *cl;
789 /* general protection against mistakes and abuse */
790 if(strlen(argptr) > CURL_MAX_INPUT_LENGTH)
791 return CURLE_BAD_FUNCTION_ARGUMENT;
792 /* append the cookie file name to the list of file names, and deal with
793 them later */
794 cl = curl_slist_append(data->state.cookielist, argptr);
795 if(!cl) {
796 curl_slist_free_all(data->state.cookielist);
797 data->state.cookielist = NULL;
798 return CURLE_OUT_OF_MEMORY;
799 }
800 data->state.cookielist = cl; /* store the list for later use */
801 }
802 else {
803 /* clear the list of cookie files */
804 curl_slist_free_all(data->state.cookielist);
805 data->state.cookielist = NULL;
806
807 if(!data->share || !data->share->cookies) {
808 /* throw away all existing cookies if this isn't a shared cookie
809 container */
810 Curl_cookie_clearall(data->cookies);
811 Curl_cookie_cleanup(data->cookies);
812 }
813 /* disable the cookie engine */
814 data->cookies = NULL;
815 }
816 break;
817
818 case CURLOPT_COOKIEJAR:
819 /*
820 * Set cookie file name to dump all cookies to when we're done.
821 */
822 result = Curl_setstropt(&data->set.str[STRING_COOKIEJAR],
823 va_arg(param, char *));
824 if(!result) {
825 /*
826 * Activate the cookie parser. This may or may not already
827 * have been made.
828 */
829 struct CookieInfo *newcookies =
830 Curl_cookie_init(data, NULL, data->cookies, data->set.cookiesession);
831 if(!newcookies)
832 result = CURLE_OUT_OF_MEMORY;
833 data->cookies = newcookies;
834 }
835 break;
836
837 case CURLOPT_COOKIESESSION:
838 /*
839 * Set this option to TRUE to start a new "cookie session". It will
840 * prevent the forthcoming read-cookies-from-file actions to accept
841 * cookies that are marked as being session cookies, as they belong to a
842 * previous session.
843 */
844 data->set.cookiesession = (0 != va_arg(param, long));
845 break;
846
847 case CURLOPT_COOKIELIST:
848 argptr = va_arg(param, char *);
849
850 if(!argptr)
851 break;
852
853 if(strcasecompare(argptr, "ALL")) {
854 /* clear all cookies */
855 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
856 Curl_cookie_clearall(data->cookies);
857 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
858 }
859 else if(strcasecompare(argptr, "SESS")) {
860 /* clear session cookies */
861 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
862 Curl_cookie_clearsess(data->cookies);
863 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
864 }
865 else if(strcasecompare(argptr, "FLUSH")) {
866 /* flush cookies to file, takes care of the locking */
867 Curl_flush_cookies(data, FALSE);
868 }
869 else if(strcasecompare(argptr, "RELOAD")) {
870 /* reload cookies from file */
871 Curl_cookie_loadfiles(data);
872 break;
873 }
874 else {
875 if(!data->cookies)
876 /* if cookie engine was not running, activate it */
877 data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
878
879 /* general protection against mistakes and abuse */
880 if(strlen(argptr) > CURL_MAX_INPUT_LENGTH)
881 return CURLE_BAD_FUNCTION_ARGUMENT;
882 argptr = strdup(argptr);
883 if(!argptr || !data->cookies) {
884 result = CURLE_OUT_OF_MEMORY;
885 free(argptr);
886 }
887 else {
888 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
889
890 if(checkprefix("Set-Cookie:", argptr))
891 /* HTTP Header format line */
892 Curl_cookie_add(data, data->cookies, TRUE, FALSE, argptr + 11, NULL,
893 NULL, TRUE);
894
895 else
896 /* Netscape format line */
897 Curl_cookie_add(data, data->cookies, FALSE, FALSE, argptr, NULL,
898 NULL, TRUE);
899
900 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
901 free(argptr);
902 }
903 }
904
905 break;
906 #endif /* !CURL_DISABLE_COOKIES */
907
908 case CURLOPT_HTTPGET:
909 /*
910 * Set to force us do HTTP GET
911 */
912 if(va_arg(param, long)) {
913 data->set.method = HTTPREQ_GET;
914 data->set.opt_no_body = FALSE; /* this is implied */
915 }
916 break;
917
918 case CURLOPT_HTTP_VERSION:
919 /*
920 * This sets a requested HTTP version to be used. The value is one of
921 * the listed enums in curl/curl.h.
922 */
923 arg = va_arg(param, long);
924 switch(arg) {
925 case CURL_HTTP_VERSION_NONE:
926 #ifdef USE_HTTP2
927 /* TODO: this seems an undesirable quirk to force a behaviour on
928 * lower implementations that they should recognize independently? */
929 arg = CURL_HTTP_VERSION_2TLS;
930 #endif
931 /* accepted */
932 break;
933 case CURL_HTTP_VERSION_1_0:
934 case CURL_HTTP_VERSION_1_1:
935 /* accepted */
936 break;
937 #ifdef USE_HTTP2
938 case CURL_HTTP_VERSION_2_0:
939 case CURL_HTTP_VERSION_2TLS:
940 case CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE:
941 /* accepted */
942 break;
943 #endif
944 #ifdef USE_HTTP3
945 case CURL_HTTP_VERSION_3:
946 case CURL_HTTP_VERSION_3ONLY:
947 /* accepted */
948 break;
949 #endif
950 default:
951 /* not accepted */
952 if(arg < CURL_HTTP_VERSION_NONE)
953 return CURLE_BAD_FUNCTION_ARGUMENT;
954 return CURLE_UNSUPPORTED_PROTOCOL;
955 }
956 data->set.httpwant = (unsigned char)arg;
957 break;
958
959 case CURLOPT_EXPECT_100_TIMEOUT_MS:
960 /*
961 * Time to wait for a response to an HTTP request containing an
962 * Expect: 100-continue header before sending the data anyway.
963 */
964 arg = va_arg(param, long);
965 if(arg < 0)
966 return CURLE_BAD_FUNCTION_ARGUMENT;
967 data->set.expect_100_timeout = arg;
968 break;
969
970 case CURLOPT_HTTP09_ALLOWED:
971 arg = (long)va_arg(param, unsigned long);
972 if(arg > 1L)
973 return CURLE_BAD_FUNCTION_ARGUMENT;
974 #ifdef USE_HYPER
975 /* Hyper does not support HTTP/0.9 */
976 if(arg)
977 return CURLE_BAD_FUNCTION_ARGUMENT;
978 #else
979 data->set.http09_allowed = !!arg;
980 #endif
981 break;
982
983 case CURLOPT_HTTP200ALIASES:
984 /*
985 * Set a list of aliases for HTTP 200 in response header
986 */
987 data->set.http200aliases = va_arg(param, struct curl_slist *);
988 break;
989 #endif /* CURL_DISABLE_HTTP */
990
991 #if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
992 !defined(CURL_DISABLE_IMAP)
993 # if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MIME)
994 case CURLOPT_HTTPHEADER:
995 /*
996 * Set a list with HTTP headers to use (or replace internals with)
997 */
998 data->set.headers = va_arg(param, struct curl_slist *);
999 break;
1000 # endif
1001
1002 # ifndef CURL_DISABLE_MIME
1003 case CURLOPT_MIMEPOST:
1004 /*
1005 * Set to make us do MIME POST
1006 */
1007 result = Curl_mime_set_subparts(&data->set.mimepost,
1008 va_arg(param, curl_mime *), FALSE);
1009 if(!result) {
1010 data->set.method = HTTPREQ_POST_MIME;
1011 data->set.opt_no_body = FALSE; /* this is implied */
1012 #ifndef CURL_DISABLE_FORM_API
1013 Curl_mime_cleanpart(data->state.formp);
1014 Curl_safefree(data->state.formp);
1015 data->state.mimepost = NULL;
1016 #endif
1017 }
1018 break;
1019
1020 case CURLOPT_MIME_OPTIONS:
1021 arg = va_arg(param, long);
1022 data->set.mime_formescape = !!(arg & CURLMIMEOPT_FORMESCAPE);
1023 break;
1024 # endif
1025 #endif
1026
1027 case CURLOPT_HTTPAUTH:
1028 /*
1029 * Set HTTP Authentication type BITMASK.
1030 */
1031 {
1032 int bitcheck;
1033 bool authbits;
1034 unsigned long auth = va_arg(param, unsigned long);
1035
1036 if(auth == CURLAUTH_NONE) {
1037 data->set.httpauth = auth;
1038 break;
1039 }
1040
1041 /* the DIGEST_IE bit is only used to set a special marker, for all the
1042 rest we need to handle it as normal DIGEST */
1043 data->state.authhost.iestyle = !!(auth & CURLAUTH_DIGEST_IE);
1044
1045 if(auth & CURLAUTH_DIGEST_IE) {
1046 auth |= CURLAUTH_DIGEST; /* set standard digest bit */
1047 auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
1048 }
1049
1050 /* switch off bits we can't support */
1051 #ifndef USE_NTLM
1052 auth &= ~CURLAUTH_NTLM; /* no NTLM support */
1053 #endif
1054 #ifndef USE_SPNEGO
1055 auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
1056 GSS-API or SSPI */
1057 #endif
1058
1059 /* check if any auth bit lower than CURLAUTH_ONLY is still set */
1060 bitcheck = 0;
1061 authbits = FALSE;
1062 while(bitcheck < 31) {
1063 if(auth & (1UL << bitcheck++)) {
1064 authbits = TRUE;
1065 break;
1066 }
1067 }
1068 if(!authbits)
1069 return CURLE_NOT_BUILT_IN; /* no supported types left! */
1070
1071 data->set.httpauth = auth;
1072 }
1073 break;
1074
1075 case CURLOPT_CUSTOMREQUEST:
1076 /*
1077 * Set a custom string to use as request
1078 */
1079 result = Curl_setstropt(&data->set.str[STRING_CUSTOMREQUEST],
1080 va_arg(param, char *));
1081
1082 /* we don't set
1083 data->set.method = HTTPREQ_CUSTOM;
1084 here, we continue as if we were using the already set type
1085 and this just changes the actual request keyword */
1086 break;
1087
1088 #ifndef CURL_DISABLE_PROXY
1089 case CURLOPT_HTTPPROXYTUNNEL:
1090 /*
1091 * Tunnel operations through the proxy instead of normal proxy use
1092 */
1093 data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long));
1094 break;
1095
1096 case CURLOPT_PROXYPORT:
1097 /*
1098 * Explicitly set HTTP proxy port number.
1099 */
1100 arg = va_arg(param, long);
1101 if((arg < 0) || (arg > 65535))
1102 return CURLE_BAD_FUNCTION_ARGUMENT;
1103 data->set.proxyport = (unsigned short)arg;
1104 break;
1105
1106 case CURLOPT_PROXYAUTH:
1107 /*
1108 * Set HTTP Authentication type BITMASK.
1109 */
1110 {
1111 int bitcheck;
1112 bool authbits;
1113 unsigned long auth = va_arg(param, unsigned long);
1114
1115 if(auth == CURLAUTH_NONE) {
1116 data->set.proxyauth = auth;
1117 break;
1118 }
1119
1120 /* the DIGEST_IE bit is only used to set a special marker, for all the
1121 rest we need to handle it as normal DIGEST */
1122 data->state.authproxy.iestyle = !!(auth & CURLAUTH_DIGEST_IE);
1123
1124 if(auth & CURLAUTH_DIGEST_IE) {
1125 auth |= CURLAUTH_DIGEST; /* set standard digest bit */
1126 auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
1127 }
1128 /* switch off bits we can't support */
1129 #ifndef USE_NTLM
1130 auth &= ~CURLAUTH_NTLM; /* no NTLM support */
1131 #endif
1132 #ifndef USE_SPNEGO
1133 auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
1134 GSS-API or SSPI */
1135 #endif
1136
1137 /* check if any auth bit lower than CURLAUTH_ONLY is still set */
1138 bitcheck = 0;
1139 authbits = FALSE;
1140 while(bitcheck < 31) {
1141 if(auth & (1UL << bitcheck++)) {
1142 authbits = TRUE;
1143 break;
1144 }
1145 }
1146 if(!authbits)
1147 return CURLE_NOT_BUILT_IN; /* no supported types left! */
1148
1149 data->set.proxyauth = auth;
1150 }
1151 break;
1152
1153 case CURLOPT_PROXY:
1154 /*
1155 * Set proxy server:port to use as proxy.
1156 *
1157 * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL)
1158 * we explicitly say that we don't want to use a proxy
1159 * (even though there might be environment variables saying so).
1160 *
1161 * Setting it to NULL, means no proxy but allows the environment variables
1162 * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
1163 */
1164 result = Curl_setstropt(&data->set.str[STRING_PROXY],
1165 va_arg(param, char *));
1166 break;
1167
1168 case CURLOPT_PRE_PROXY:
1169 /*
1170 * Set proxy server:port to use as SOCKS proxy.
1171 *
1172 * If the proxy is set to "" or NULL we explicitly say that we don't want
1173 * to use the socks proxy.
1174 */
1175 result = Curl_setstropt(&data->set.str[STRING_PRE_PROXY],
1176 va_arg(param, char *));
1177 break;
1178
1179 case CURLOPT_PROXYTYPE:
1180 /*
1181 * Set proxy type.
1182 */
1183 arg = va_arg(param, long);
1184 if((arg < CURLPROXY_HTTP) || (arg > CURLPROXY_SOCKS5_HOSTNAME))
1185 return CURLE_BAD_FUNCTION_ARGUMENT;
1186 data->set.proxytype = (unsigned char)(curl_proxytype)arg;
1187 break;
1188
1189 case CURLOPT_PROXY_TRANSFER_MODE:
1190 /*
1191 * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
1192 */
1193 switch(va_arg(param, long)) {
1194 case 0:
1195 data->set.proxy_transfer_mode = FALSE;
1196 break;
1197 case 1:
1198 data->set.proxy_transfer_mode = TRUE;
1199 break;
1200 default:
1201 /* reserve other values for future use */
1202 result = CURLE_BAD_FUNCTION_ARGUMENT;
1203 break;
1204 }
1205 break;
1206
1207 case CURLOPT_SOCKS5_AUTH:
1208 data->set.socks5auth = (unsigned char)va_arg(param, unsigned long);
1209 if(data->set.socks5auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
1210 result = CURLE_NOT_BUILT_IN;
1211 break;
1212 #endif /* CURL_DISABLE_PROXY */
1213
1214 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
1215 case CURLOPT_SOCKS5_GSSAPI_NEC:
1216 /*
1217 * Set flag for NEC SOCK5 support
1218 */
1219 data->set.socks5_gssapi_nec = (0 != va_arg(param, long));
1220 break;
1221 #endif
1222 #ifndef CURL_DISABLE_PROXY
1223 case CURLOPT_SOCKS5_GSSAPI_SERVICE:
1224 case CURLOPT_PROXY_SERVICE_NAME:
1225 /*
1226 * Set proxy authentication service name for Kerberos 5 and SPNEGO
1227 */
1228 result = Curl_setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME],
1229 va_arg(param, char *));
1230 break;
1231 #endif
1232 case CURLOPT_SERVICE_NAME:
1233 /*
1234 * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO
1235 */
1236 result = Curl_setstropt(&data->set.str[STRING_SERVICE_NAME],
1237 va_arg(param, char *));
1238 break;
1239
1240 case CURLOPT_HEADERDATA:
1241 /*
1242 * Custom pointer to pass the header write callback function
1243 */
1244 data->set.writeheader = (void *)va_arg(param, void *);
1245 break;
1246 case CURLOPT_ERRORBUFFER:
1247 /*
1248 * Error buffer provided by the caller to get the human readable
1249 * error string in.
1250 */
1251 data->set.errorbuffer = va_arg(param, char *);
1252 break;
1253 case CURLOPT_WRITEDATA:
1254 /*
1255 * FILE pointer to write to. Or possibly
1256 * used as argument to the write callback.
1257 */
1258 data->set.out = va_arg(param, void *);
1259 break;
1260
1261 #ifdef CURL_LIST_ONLY_PROTOCOL
1262 case CURLOPT_DIRLISTONLY:
1263 /*
1264 * An option that changes the command to one that asks for a list only, no
1265 * file info details. Used for FTP, POP3 and SFTP.
1266 */
1267 data->set.list_only = (0 != va_arg(param, long));
1268 break;
1269 #endif
1270 case CURLOPT_APPEND:
1271 /*
1272 * We want to upload and append to an existing file. Used for FTP and
1273 * SFTP.
1274 */
1275 data->set.remote_append = (0 != va_arg(param, long));
1276 break;
1277
1278 #ifndef CURL_DISABLE_FTP
1279 case CURLOPT_FTP_FILEMETHOD:
1280 /*
1281 * How do access files over FTP.
1282 */
1283 arg = va_arg(param, long);
1284 if((arg < CURLFTPMETHOD_DEFAULT) || (arg >= CURLFTPMETHOD_LAST))
1285 return CURLE_BAD_FUNCTION_ARGUMENT;
1286 data->set.ftp_filemethod = (unsigned char)arg;
1287 break;
1288 case CURLOPT_FTPPORT:
1289 /*
1290 * Use FTP PORT, this also specifies which IP address to use
1291 */
1292 result = Curl_setstropt(&data->set.str[STRING_FTPPORT],
1293 va_arg(param, char *));
1294 data->set.ftp_use_port = !!(data->set.str[STRING_FTPPORT]);
1295 break;
1296
1297 case CURLOPT_FTP_USE_EPRT:
1298 data->set.ftp_use_eprt = (0 != va_arg(param, long));
1299 break;
1300
1301 case CURLOPT_FTP_USE_EPSV:
1302 data->set.ftp_use_epsv = (0 != va_arg(param, long));
1303 break;
1304
1305 case CURLOPT_FTP_USE_PRET:
1306 data->set.ftp_use_pret = (0 != va_arg(param, long));
1307 break;
1308
1309 case CURLOPT_FTP_SSL_CCC:
1310 arg = va_arg(param, long);
1311 if((arg < CURLFTPSSL_CCC_NONE) || (arg >= CURLFTPSSL_CCC_LAST))
1312 return CURLE_BAD_FUNCTION_ARGUMENT;
1313 data->set.ftp_ccc = (unsigned char)arg;
1314 break;
1315
1316 case CURLOPT_FTP_SKIP_PASV_IP:
1317 /*
1318 * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
1319 * bypass of the IP address in PASV responses.
1320 */
1321 data->set.ftp_skip_ip = (0 != va_arg(param, long));
1322 break;
1323
1324 case CURLOPT_FTP_ACCOUNT:
1325 result = Curl_setstropt(&data->set.str[STRING_FTP_ACCOUNT],
1326 va_arg(param, char *));
1327 break;
1328
1329 case CURLOPT_FTP_ALTERNATIVE_TO_USER:
1330 result = Curl_setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER],
1331 va_arg(param, char *));
1332 break;
1333
1334 case CURLOPT_FTPSSLAUTH:
1335 /*
1336 * Set a specific auth for FTP-SSL transfers.
1337 */
1338 arg = va_arg(param, long);
1339 if((arg < CURLFTPAUTH_DEFAULT) || (arg >= CURLFTPAUTH_LAST))
1340 return CURLE_BAD_FUNCTION_ARGUMENT;
1341 data->set.ftpsslauth = (unsigned char)(curl_ftpauth)arg;
1342 break;
1343 #ifdef HAVE_GSSAPI
1344 case CURLOPT_KRBLEVEL:
1345 /*
1346 * A string that defines the kerberos security level.
1347 */
1348 result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL],
1349 va_arg(param, char *));
1350 data->set.krb = !!(data->set.str[STRING_KRB_LEVEL]);
1351 break;
1352 #endif
1353 #endif
1354 #if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
1355 case CURLOPT_FTP_CREATE_MISSING_DIRS:
1356 /*
1357 * An FTP/SFTP option that modifies an upload to create missing
1358 * directories on the server.
1359 */
1360 arg = va_arg(param, long);
1361 /* reserve other values for future use */
1362 if((arg < CURLFTP_CREATE_DIR_NONE) ||
1363 (arg > CURLFTP_CREATE_DIR_RETRY))
1364 result = CURLE_BAD_FUNCTION_ARGUMENT;
1365 else
1366 data->set.ftp_create_missing_dirs = (unsigned char)arg;
1367 break;
1368
1369 case CURLOPT_POSTQUOTE:
1370 /*
1371 * List of RAW FTP commands to use after a transfer
1372 */
1373 data->set.postquote = va_arg(param, struct curl_slist *);
1374 break;
1375 case CURLOPT_PREQUOTE:
1376 /*
1377 * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
1378 */
1379 data->set.prequote = va_arg(param, struct curl_slist *);
1380 break;
1381 case CURLOPT_QUOTE:
1382 /*
1383 * List of RAW FTP commands to use before a transfer
1384 */
1385 data->set.quote = va_arg(param, struct curl_slist *);
1386 break;
1387 #endif
1388 case CURLOPT_READDATA:
1389 /*
1390 * FILE pointer to read the file to be uploaded from. Or possibly
1391 * used as argument to the read callback.
1392 */
1393 data->set.in_set = va_arg(param, void *);
1394 break;
1395 case CURLOPT_INFILESIZE:
1396 /*
1397 * If known, this should inform curl about the file size of the
1398 * to-be-uploaded file.
1399 */
1400 arg = va_arg(param, long);
1401 if(arg < -1)
1402 return CURLE_BAD_FUNCTION_ARGUMENT;
1403 data->set.filesize = arg;
1404 break;
1405 case CURLOPT_INFILESIZE_LARGE:
1406 /*
1407 * If known, this should inform curl about the file size of the
1408 * to-be-uploaded file.
1409 */
1410 bigsize = va_arg(param, curl_off_t);
1411 if(bigsize < -1)
1412 return CURLE_BAD_FUNCTION_ARGUMENT;
1413 data->set.filesize = bigsize;
1414 break;
1415 case CURLOPT_LOW_SPEED_LIMIT:
1416 /*
1417 * The low speed limit that if transfers are below this for
1418 * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
1419 */
1420 arg = va_arg(param, long);
1421 if(arg < 0)
1422 return CURLE_BAD_FUNCTION_ARGUMENT;
1423 data->set.low_speed_limit = arg;
1424 break;
1425 case CURLOPT_MAX_SEND_SPEED_LARGE:
1426 /*
1427 * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE
1428 * bytes per second the transfer is throttled..
1429 */
1430 bigsize = va_arg(param, curl_off_t);
1431 if(bigsize < 0)
1432 return CURLE_BAD_FUNCTION_ARGUMENT;
1433 data->set.max_send_speed = bigsize;
1434 break;
1435 case CURLOPT_MAX_RECV_SPEED_LARGE:
1436 /*
1437 * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per
1438 * second the transfer is throttled..
1439 */
1440 bigsize = va_arg(param, curl_off_t);
1441 if(bigsize < 0)
1442 return CURLE_BAD_FUNCTION_ARGUMENT;
1443 data->set.max_recv_speed = bigsize;
1444 break;
1445 case CURLOPT_LOW_SPEED_TIME:
1446 /*
1447 * The low speed time that if transfers are below the set
1448 * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
1449 */
1450 arg = va_arg(param, long);
1451 if(arg < 0)
1452 return CURLE_BAD_FUNCTION_ARGUMENT;
1453 data->set.low_speed_time = arg;
1454 break;
1455 case CURLOPT_CURLU:
1456 /*
1457 * pass CURLU to set URL
1458 */
1459 data->set.uh = va_arg(param, CURLU *);
1460 break;
1461 case CURLOPT_URL:
1462 /*
1463 * The URL to fetch.
1464 */
1465 if(data->state.url_alloc) {
1466 /* the already set URL is allocated, free it first! */
1467 Curl_safefree(data->state.url);
1468 data->state.url_alloc = FALSE;
1469 }
1470 result = Curl_setstropt(&data->set.str[STRING_SET_URL],
1471 va_arg(param, char *));
1472 data->state.url = data->set.str[STRING_SET_URL];
1473 break;
1474 case CURLOPT_PORT:
1475 /*
1476 * The port number to use when getting the URL. 0 disables it.
1477 */
1478 arg = va_arg(param, long);
1479 if((arg < 0) || (arg > 65535))
1480 return CURLE_BAD_FUNCTION_ARGUMENT;
1481 data->set.use_port = (unsigned short)arg;
1482 break;
1483 case CURLOPT_TIMEOUT:
1484 /*
1485 * The maximum time you allow curl to use for a single transfer
1486 * operation.
1487 */
1488 arg = va_arg(param, long);
1489 if((arg >= 0) && (arg <= (INT_MAX/1000)))
1490 data->set.timeout = (unsigned int)arg * 1000;
1491 else
1492 return CURLE_BAD_FUNCTION_ARGUMENT;
1493 break;
1494
1495 case CURLOPT_TIMEOUT_MS:
1496 uarg = va_arg(param, unsigned long);
1497 if(uarg > UINT_MAX)
1498 uarg = UINT_MAX;
1499 data->set.timeout = (unsigned int)uarg;
1500 break;
1501
1502 case CURLOPT_CONNECTTIMEOUT:
1503 /*
1504 * The maximum time you allow curl to use to connect.
1505 */
1506 arg = va_arg(param, long);
1507 if((arg >= 0) && (arg <= (INT_MAX/1000)))
1508 data->set.connecttimeout = (unsigned int)arg * 1000;
1509 else
1510 return CURLE_BAD_FUNCTION_ARGUMENT;
1511 break;
1512
1513 case CURLOPT_CONNECTTIMEOUT_MS:
1514 uarg = va_arg(param, unsigned long);
1515 if(uarg > UINT_MAX)
1516 uarg = UINT_MAX;
1517 data->set.connecttimeout = (unsigned int)uarg;
1518 break;
1519
1520 #ifndef CURL_DISABLE_FTP
1521 case CURLOPT_ACCEPTTIMEOUT_MS:
1522 /*
1523 * The maximum time for curl to wait for FTP server connect
1524 */
1525 uarg = va_arg(param, unsigned long);
1526 if(uarg > UINT_MAX)
1527 uarg = UINT_MAX;
1528 data->set.accepttimeout = (unsigned int)uarg;
1529 break;
1530 #endif
1531
1532 case CURLOPT_USERPWD:
1533 /*
1534 * user:password to use in the operation
1535 */
1536 result = setstropt_userpwd(va_arg(param, char *),
1537 &data->set.str[STRING_USERNAME],
1538 &data->set.str[STRING_PASSWORD]);
1539 break;
1540
1541 case CURLOPT_USERNAME:
1542 /*
1543 * authentication user name to use in the operation
1544 */
1545 result = Curl_setstropt(&data->set.str[STRING_USERNAME],
1546 va_arg(param, char *));
1547 break;
1548 case CURLOPT_PASSWORD:
1549 /*
1550 * authentication password to use in the operation
1551 */
1552 result = Curl_setstropt(&data->set.str[STRING_PASSWORD],
1553 va_arg(param, char *));
1554 break;
1555
1556 case CURLOPT_LOGIN_OPTIONS:
1557 /*
1558 * authentication options to use in the operation
1559 */
1560 result = Curl_setstropt(&data->set.str[STRING_OPTIONS],
1561 va_arg(param, char *));
1562 break;
1563
1564 case CURLOPT_XOAUTH2_BEARER:
1565 /*
1566 * OAuth 2.0 bearer token to use in the operation
1567 */
1568 result = Curl_setstropt(&data->set.str[STRING_BEARER],
1569 va_arg(param, char *));
1570 break;
1571
1572 case CURLOPT_RESOLVE:
1573 /*
1574 * List of HOST:PORT:[addresses] strings to populate the DNS cache with
1575 * Entries added this way will remain in the cache until explicitly
1576 * removed or the handle is cleaned up.
1577 *
1578 * Prefix the HOST with plus sign (+) to have the entry expire just like
1579 * automatically added entries.
1580 *
1581 * Prefix the HOST with dash (-) to _remove_ the entry from the cache.
1582 *
1583 * This API can remove any entry from the DNS cache, but only entries
1584 * that aren't actually in use right now will be pruned immediately.
1585 */
1586 data->set.resolve = va_arg(param, struct curl_slist *);
1587 data->state.resolve = data->set.resolve;
1588 break;
1589 case CURLOPT_PROGRESSFUNCTION:
1590 /*
1591 * Progress callback function
1592 */
1593 data->set.fprogress = va_arg(param, curl_progress_callback);
1594 if(data->set.fprogress)
1595 data->progress.callback = TRUE; /* no longer internal */
1596 else
1597 data->progress.callback = FALSE; /* NULL enforces internal */
1598 break;
1599
1600 case CURLOPT_XFERINFOFUNCTION:
1601 /*
1602 * Transfer info callback function
1603 */
1604 data->set.fxferinfo = va_arg(param, curl_xferinfo_callback);
1605 if(data->set.fxferinfo)
1606 data->progress.callback = TRUE; /* no longer internal */
1607 else
1608 data->progress.callback = FALSE; /* NULL enforces internal */
1609
1610 break;
1611
1612 case CURLOPT_PROGRESSDATA:
1613 /*
1614 * Custom client data to pass to the progress callback
1615 */
1616 data->set.progress_client = va_arg(param, void *);
1617 break;
1618
1619 #ifndef CURL_DISABLE_PROXY
1620 case CURLOPT_PROXYUSERPWD: {
1621 /*
1622 * user:password needed to use the proxy
1623 */
1624 char *u = NULL;
1625 char *p = NULL;
1626 result = setstropt_userpwd(va_arg(param, char *), &u, &p);
1627
1628 /* URL decode the components */
1629 if(!result && u)
1630 result = Curl_urldecode(u, 0, &data->set.str[STRING_PROXYUSERNAME], NULL,
1631 REJECT_ZERO);
1632 if(!result && p)
1633 result = Curl_urldecode(p, 0, &data->set.str[STRING_PROXYPASSWORD], NULL,
1634 REJECT_ZERO);
1635 free(u);
1636 free(p);
1637 }
1638 break;
1639 case CURLOPT_PROXYUSERNAME:
1640 /*
1641 * authentication user name to use in the operation
1642 */
1643 result = Curl_setstropt(&data->set.str[STRING_PROXYUSERNAME],
1644 va_arg(param, char *));
1645 break;
1646 case CURLOPT_PROXYPASSWORD:
1647 /*
1648 * authentication password to use in the operation
1649 */
1650 result = Curl_setstropt(&data->set.str[STRING_PROXYPASSWORD],
1651 va_arg(param, char *));
1652 break;
1653 case CURLOPT_NOPROXY:
1654 /*
1655 * proxy exception list
1656 */
1657 result = Curl_setstropt(&data->set.str[STRING_NOPROXY],
1658 va_arg(param, char *));
1659 break;
1660 #endif
1661
1662 case CURLOPT_RANGE:
1663 /*
1664 * What range of the file you want to transfer
1665 */
1666 result = Curl_setstropt(&data->set.str[STRING_SET_RANGE],
1667 va_arg(param, char *));
1668 break;
1669 case CURLOPT_RESUME_FROM:
1670 /*
1671 * Resume transfer at the given file position
1672 */
1673 arg = va_arg(param, long);
1674 if(arg < -1)
1675 return CURLE_BAD_FUNCTION_ARGUMENT;
1676 data->set.set_resume_from = arg;
1677 break;
1678 case CURLOPT_RESUME_FROM_LARGE:
1679 /*
1680 * Resume transfer at the given file position
1681 */
1682 bigsize = va_arg(param, curl_off_t);
1683 if(bigsize < -1)
1684 return CURLE_BAD_FUNCTION_ARGUMENT;
1685 data->set.set_resume_from = bigsize;
1686 break;
1687 case CURLOPT_DEBUGFUNCTION:
1688 /*
1689 * stderr write callback.
1690 */
1691 data->set.fdebug = va_arg(param, curl_debug_callback);
1692 /*
1693 * if the callback provided is NULL, it'll use the default callback
1694 */
1695 break;
1696 case CURLOPT_DEBUGDATA:
1697 /*
1698 * Set to a void * that should receive all error writes. This
1699 * defaults to CURLOPT_STDERR for normal operations.
1700 */
1701 data->set.debugdata = va_arg(param, void *);
1702 break;
1703 case CURLOPT_STDERR:
1704 /*
1705 * Set to a FILE * that should receive all error writes. This
1706 * defaults to stderr for normal operations.
1707 */
1708 data->set.err = va_arg(param, FILE *);
1709 if(!data->set.err)
1710 data->set.err = stderr;
1711 break;
1712 case CURLOPT_HEADERFUNCTION:
1713 /*
1714 * Set header write callback
1715 */
1716 data->set.fwrite_header = va_arg(param, curl_write_callback);
1717 break;
1718 case CURLOPT_WRITEFUNCTION:
1719 /*
1720 * Set data write callback
1721 */
1722 data->set.fwrite_func = va_arg(param, curl_write_callback);
1723 if(!data->set.fwrite_func)
1724 /* When set to NULL, reset to our internal default function */
1725 data->set.fwrite_func = (curl_write_callback)fwrite;
1726 break;
1727 case CURLOPT_READFUNCTION:
1728 /*
1729 * Read data callback
1730 */
1731 data->set.fread_func_set = va_arg(param, curl_read_callback);
1732 if(!data->set.fread_func_set) {
1733 data->set.is_fread_set = 0;
1734 /* When set to NULL, reset to our internal default function */
1735 data->set.fread_func_set = (curl_read_callback)fread;
1736 }
1737 else
1738 data->set.is_fread_set = 1;
1739 break;
1740 case CURLOPT_SEEKFUNCTION:
1741 /*
1742 * Seek callback. Might be NULL.
1743 */
1744 data->set.seek_func = va_arg(param, curl_seek_callback);
1745 break;
1746 case CURLOPT_SEEKDATA:
1747 /*
1748 * Seek control callback. Might be NULL.
1749 */
1750 data->set.seek_client = va_arg(param, void *);
1751 break;
1752 case CURLOPT_IOCTLFUNCTION:
1753 /*
1754 * I/O control callback. Might be NULL.
1755 */
1756 data->set.ioctl_func = va_arg(param, curl_ioctl_callback);
1757 break;
1758 case CURLOPT_IOCTLDATA:
1759 /*
1760 * I/O control data pointer. Might be NULL.
1761 */
1762 data->set.ioctl_client = va_arg(param, void *);
1763 break;
1764 case CURLOPT_SSLCERT:
1765 /*
1766 * String that holds file name of the SSL certificate to use
1767 */
1768 result = Curl_setstropt(&data->set.str[STRING_CERT],
1769 va_arg(param, char *));
1770 break;
1771 case CURLOPT_SSLCERT_BLOB:
1772 /*
1773 * Blob that holds file content of the SSL certificate to use
1774 */
1775 result = Curl_setblobopt(&data->set.blobs[BLOB_CERT],
1776 va_arg(param, struct curl_blob *));
1777 break;
1778 #ifndef CURL_DISABLE_PROXY
1779 case CURLOPT_PROXY_SSLCERT:
1780 /*
1781 * String that holds file name of the SSL certificate to use for proxy
1782 */
1783 result = Curl_setstropt(&data->set.str[STRING_CERT_PROXY],
1784 va_arg(param, char *));
1785 break;
1786 case CURLOPT_PROXY_SSLCERT_BLOB:
1787 /*
1788 * Blob that holds file content of the SSL certificate to use for proxy
1789 */
1790 result = Curl_setblobopt(&data->set.blobs[BLOB_CERT_PROXY],
1791 va_arg(param, struct curl_blob *));
1792 break;
1793 #endif
1794 case CURLOPT_SSLCERTTYPE:
1795 /*
1796 * String that holds file type of the SSL certificate to use
1797 */
1798 result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE],
1799 va_arg(param, char *));
1800 break;
1801 #ifndef CURL_DISABLE_PROXY
1802 case CURLOPT_PROXY_SSLCERTTYPE:
1803 /*
1804 * String that holds file type of the SSL certificate to use for proxy
1805 */
1806 result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_PROXY],
1807 va_arg(param, char *));
1808 break;
1809 #endif
1810 case CURLOPT_SSLKEY:
1811 /*
1812 * String that holds file name of the SSL key to use
1813 */
1814 result = Curl_setstropt(&data->set.str[STRING_KEY],
1815 va_arg(param, char *));
1816 break;
1817 case CURLOPT_SSLKEY_BLOB:
1818 /*
1819 * Blob that holds file content of the SSL key to use
1820 */
1821 result = Curl_setblobopt(&data->set.blobs[BLOB_KEY],
1822 va_arg(param, struct curl_blob *));
1823 break;
1824 #ifndef CURL_DISABLE_PROXY
1825 case CURLOPT_PROXY_SSLKEY:
1826 /*
1827 * String that holds file name of the SSL key to use for proxy
1828 */
1829 result = Curl_setstropt(&data->set.str[STRING_KEY_PROXY],
1830 va_arg(param, char *));
1831 break;
1832 case CURLOPT_PROXY_SSLKEY_BLOB:
1833 /*
1834 * Blob that holds file content of the SSL key to use for proxy
1835 */
1836 result = Curl_setblobopt(&data->set.blobs[BLOB_KEY_PROXY],
1837 va_arg(param, struct curl_blob *));
1838 break;
1839 #endif
1840 case CURLOPT_SSLKEYTYPE:
1841 /*
1842 * String that holds file type of the SSL key to use
1843 */
1844 result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE],
1845 va_arg(param, char *));
1846 break;
1847 #ifndef CURL_DISABLE_PROXY
1848 case CURLOPT_PROXY_SSLKEYTYPE:
1849 /*
1850 * String that holds file type of the SSL key to use for proxy
1851 */
1852 result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_PROXY],
1853 va_arg(param, char *));
1854 break;
1855 #endif
1856 case CURLOPT_KEYPASSWD:
1857 /*
1858 * String that holds the SSL or SSH private key password.
1859 */
1860 result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD],
1861 va_arg(param, char *));
1862 break;
1863 #ifndef CURL_DISABLE_PROXY
1864 case CURLOPT_PROXY_KEYPASSWD:
1865 /*
1866 * String that holds the SSL private key password for proxy.
1867 */
1868 result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY],
1869 va_arg(param, char *));
1870 break;
1871 #endif
1872 case CURLOPT_SSLENGINE:
1873 /*
1874 * String that holds the SSL crypto engine.
1875 */
1876 argptr = va_arg(param, char *);
1877 if(argptr && argptr[0]) {
1878 result = Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], argptr);
1879 if(!result) {
1880 result = Curl_ssl_set_engine(data, argptr);
1881 }
1882 }
1883 break;
1884
1885 case CURLOPT_SSLENGINE_DEFAULT:
1886 /*
1887 * flag to set engine as default.
1888 */
1889 Curl_safefree(data->set.str[STRING_SSL_ENGINE]);
1890 result = Curl_ssl_set_engine_default(data);
1891 break;
1892 case CURLOPT_CRLF:
1893 /*
1894 * Kludgy option to enable CRLF conversions. Subject for removal.
1895 */
1896 data->set.crlf = (0 != va_arg(param, long));
1897 break;
1898 #ifndef CURL_DISABLE_PROXY
1899 case CURLOPT_HAPROXYPROTOCOL:
1900 /*
1901 * Set to send the HAProxy Proxy Protocol header
1902 */
1903 data->set.haproxyprotocol = (0 != va_arg(param, long));
1904 break;
1905 case CURLOPT_HAPROXY_CLIENT_IP:
1906 /*
1907 * Set the client IP to send through HAProxy PROXY protocol
1908 */
1909 result = Curl_setstropt(&data->set.str[STRING_HAPROXY_CLIENT_IP],
1910 va_arg(param, char *));
1911 /* We enable implicitly the HAProxy protocol if we use this flag. */
1912 data->set.haproxyprotocol = TRUE;
1913 break;
1914 #endif
1915 case CURLOPT_INTERFACE:
1916 /*
1917 * Set what interface or address/hostname to bind the socket to when
1918 * performing an operation and thus what from-IP your connection will use.
1919 */
1920 result = setstropt_interface(va_arg(param, char *),
1921 &data->set.str[STRING_DEVICE],
1922 &data->set.str[STRING_INTERFACE],
1923 &data->set.str[STRING_BINDHOST]);
1924 break;
1925 #ifndef CURL_DISABLE_BINDLOCAL
1926 case CURLOPT_LOCALPORT:
1927 /*
1928 * Set what local port to bind the socket to when performing an operation.
1929 */
1930 arg = va_arg(param, long);
1931 if((arg < 0) || (arg > 65535))
1932 return CURLE_BAD_FUNCTION_ARGUMENT;
1933 data->set.localport = curlx_sltous(arg);
1934 break;
1935 case CURLOPT_LOCALPORTRANGE:
1936 /*
1937 * Set number of local ports to try, starting with CURLOPT_LOCALPORT.
1938 */
1939 arg = va_arg(param, long);
1940 if((arg < 0) || (arg > 65535))
1941 return CURLE_BAD_FUNCTION_ARGUMENT;
1942 data->set.localportrange = curlx_sltous(arg);
1943 break;
1944 #endif
1945 case CURLOPT_GSSAPI_DELEGATION:
1946 /*
1947 * GSS-API credential delegation bitmask
1948 */
1949 uarg = va_arg(param, unsigned long);
1950 data->set.gssapi_delegation = (unsigned char)uarg&
1951 (CURLGSSAPI_DELEGATION_POLICY_FLAG|CURLGSSAPI_DELEGATION_FLAG);
1952 break;
1953 case CURLOPT_SSL_VERIFYPEER:
1954 /*
1955 * Enable peer SSL verifying.
1956 */
1957 data->set.ssl.primary.verifypeer = (0 != va_arg(param, long));
1958
1959 /* Update the current connection ssl_config. */
1960 Curl_ssl_conn_config_update(data, FALSE);
1961 break;
1962 #ifndef CURL_DISABLE_DOH
1963 case CURLOPT_DOH_SSL_VERIFYPEER:
1964 /*
1965 * Enable peer SSL verifying for DoH.
1966 */
1967 data->set.doh_verifypeer = (0 != va_arg(param, long));
1968 break;
1969 #endif
1970 #ifndef CURL_DISABLE_PROXY
1971 case CURLOPT_PROXY_SSL_VERIFYPEER:
1972 /*
1973 * Enable peer SSL verifying for proxy.
1974 */
1975 data->set.proxy_ssl.primary.verifypeer =
1976 (0 != va_arg(param, long))?TRUE:FALSE;
1977
1978 /* Update the current connection proxy_ssl_config. */
1979 Curl_ssl_conn_config_update(data, TRUE);
1980 break;
1981 #endif
1982 case CURLOPT_SSL_VERIFYHOST:
1983 /*
1984 * Enable verification of the host name in the peer certificate
1985 */
1986 arg = va_arg(param, long);
1987
1988 /* Obviously people are not reading documentation and too many thought
1989 this argument took a boolean when it wasn't and misused it.
1990 Treat 1 and 2 the same */
1991 data->set.ssl.primary.verifyhost = !!(arg & 3);
1992
1993 /* Update the current connection ssl_config. */
1994 Curl_ssl_conn_config_update(data, FALSE);
1995 break;
1996 #ifndef CURL_DISABLE_DOH
1997 case CURLOPT_DOH_SSL_VERIFYHOST:
1998 /*
1999 * Enable verification of the host name in the peer certificate for DoH
2000 */
2001 arg = va_arg(param, long);
2002
2003 /* Treat both 1 and 2 as TRUE */
2004 data->set.doh_verifyhost = !!(arg & 3);
2005 break;
2006 #endif
2007 #ifndef CURL_DISABLE_PROXY
2008 case CURLOPT_PROXY_SSL_VERIFYHOST:
2009 /*
2010 * Enable verification of the host name in the peer certificate for proxy
2011 */
2012 arg = va_arg(param, long);
2013
2014 /* Treat both 1 and 2 as TRUE */
2015 data->set.proxy_ssl.primary.verifyhost = (bool)((arg & 3)?TRUE:FALSE);
2016 /* Update the current connection proxy_ssl_config. */
2017 Curl_ssl_conn_config_update(data, TRUE);
2018 break;
2019 #endif
2020 case CURLOPT_SSL_VERIFYSTATUS:
2021 /*
2022 * Enable certificate status verifying.
2023 */
2024 if(!Curl_ssl_cert_status_request()) {
2025 result = CURLE_NOT_BUILT_IN;
2026 break;
2027 }
2028
2029 data->set.ssl.primary.verifystatus = (0 != va_arg(param, long));
2030
2031 /* Update the current connection ssl_config. */
2032 Curl_ssl_conn_config_update(data, FALSE);
2033 break;
2034 #ifndef CURL_DISABLE_DOH
2035 case CURLOPT_DOH_SSL_VERIFYSTATUS:
2036 /*
2037 * Enable certificate status verifying for DoH.
2038 */
2039 if(!Curl_ssl_cert_status_request()) {
2040 result = CURLE_NOT_BUILT_IN;
2041 break;
2042 }
2043
2044 data->set.doh_verifystatus = (0 != va_arg(param, long));
2045 break;
2046 #endif
2047 case CURLOPT_SSL_CTX_FUNCTION:
2048 /*
2049 * Set a SSL_CTX callback
2050 */
2051 #ifdef USE_SSL
2052 if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX))
2053 data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
2054 else
2055 #endif
2056 result = CURLE_NOT_BUILT_IN;
2057 break;
2058 case CURLOPT_SSL_CTX_DATA:
2059 /*
2060 * Set a SSL_CTX callback parameter pointer
2061 */
2062 #ifdef USE_SSL
2063 if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX))
2064 data->set.ssl.fsslctxp = va_arg(param, void *);
2065 else
2066 #endif
2067 result = CURLE_NOT_BUILT_IN;
2068 break;
2069 case CURLOPT_SSL_FALSESTART:
2070 /*
2071 * Enable TLS false start.
2072 */
2073 if(!Curl_ssl_false_start(data)) {
2074 result = CURLE_NOT_BUILT_IN;
2075 break;
2076 }
2077
2078 data->set.ssl.falsestart = (0 != va_arg(param, long));
2079 break;
2080 case CURLOPT_CERTINFO:
2081 #ifdef USE_SSL
2082 if(Curl_ssl_supports(data, SSLSUPP_CERTINFO))
2083 data->set.ssl.certinfo = (0 != va_arg(param, long));
2084 else
2085 #endif
2086 result = CURLE_NOT_BUILT_IN;
2087 break;
2088 case CURLOPT_PINNEDPUBLICKEY:
2089 /*
2090 * Set pinned public key for SSL connection.
2091 * Specify file name of the public key in DER format.
2092 */
2093 #ifdef USE_SSL
2094 if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY))
2095 result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY],
2096 va_arg(param, char *));
2097 else
2098 #endif
2099 result = CURLE_NOT_BUILT_IN;
2100 break;
2101 #ifndef CURL_DISABLE_PROXY
2102 case CURLOPT_PROXY_PINNEDPUBLICKEY:
2103 /*
2104 * Set pinned public key for SSL connection.
2105 * Specify file name of the public key in DER format.
2106 */
2107 #ifdef USE_SSL
2108 if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY))
2109 result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
2110 va_arg(param, char *));
2111 else
2112 #endif
2113 result = CURLE_NOT_BUILT_IN;
2114 break;
2115 #endif
2116 case CURLOPT_CAINFO:
2117 /*
2118 * Set CA info for SSL connection. Specify file name of the CA certificate
2119 */
2120 result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE],
2121 va_arg(param, char *));
2122 break;
2123 case CURLOPT_CAINFO_BLOB:
2124 /*
2125 * Blob that holds CA info for SSL connection.
2126 * Specify entire PEM of the CA certificate
2127 */
2128 #ifdef USE_SSL
2129 if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) {
2130 result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO],
2131 va_arg(param, struct curl_blob *));
2132 break;
2133 }
2134 else
2135 #endif
2136 return CURLE_NOT_BUILT_IN;
2137 #ifndef CURL_DISABLE_PROXY
2138 case CURLOPT_PROXY_CAINFO:
2139 /*
2140 * Set CA info SSL connection for proxy. Specify file name of the
2141 * CA certificate
2142 */
2143 result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
2144 va_arg(param, char *));
2145 break;
2146 case CURLOPT_PROXY_CAINFO_BLOB:
2147 /*
2148 * Blob that holds CA info for SSL connection proxy.
2149 * Specify entire PEM of the CA certificate
2150 */
2151 #ifdef USE_SSL
2152 if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) {
2153 result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY],
2154 va_arg(param, struct curl_blob *));
2155 break;
2156 }
2157 else
2158 #endif
2159 return CURLE_NOT_BUILT_IN;
2160 #endif
2161 case CURLOPT_CAPATH:
2162 /*
2163 * Set CA path info for SSL connection. Specify directory name of the CA
2164 * certificates which have been prepared using openssl c_rehash utility.
2165 */
2166 #ifdef USE_SSL
2167 if(Curl_ssl_supports(data, SSLSUPP_CA_PATH))
2168 /* This does not work on windows. */
2169 result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH],
2170 va_arg(param, char *));
2171 else
2172 #endif
2173 result = CURLE_NOT_BUILT_IN;
2174 break;
2175 #ifndef CURL_DISABLE_PROXY
2176 case CURLOPT_PROXY_CAPATH:
2177 /*
2178 * Set CA path info for SSL connection proxy. Specify directory name of the
2179 * CA certificates which have been prepared using openssl c_rehash utility.
2180 */
2181 #ifdef USE_SSL
2182 if(Curl_ssl_supports(data, SSLSUPP_CA_PATH))
2183 /* This does not work on windows. */
2184 result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
2185 va_arg(param, char *));
2186 else
2187 #endif
2188 result = CURLE_NOT_BUILT_IN;
2189 break;
2190 #endif
2191 case CURLOPT_CRLFILE:
2192 /*
2193 * Set CRL file info for SSL connection. Specify file name of the CRL
2194 * to check certificates revocation
2195 */
2196 result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE],
2197 va_arg(param, char *));
2198 break;
2199 #ifndef CURL_DISABLE_PROXY
2200 case CURLOPT_PROXY_CRLFILE:
2201 /*
2202 * Set CRL file info for SSL connection for proxy. Specify file name of the
2203 * CRL to check certificates revocation
2204 */
2205 result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY],
2206 va_arg(param, char *));
2207 break;
2208 #endif
2209 case CURLOPT_ISSUERCERT:
2210 /*
2211 * Set Issuer certificate file
2212 * to check certificates issuer
2213 */
2214 result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT],
2215 va_arg(param, char *));
2216 break;
2217 case CURLOPT_ISSUERCERT_BLOB:
2218 /*
2219 * Blob that holds Issuer certificate to check certificates issuer
2220 */
2221 result = Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT],
2222 va_arg(param, struct curl_blob *));
2223 break;
2224 #ifndef CURL_DISABLE_PROXY
2225 case CURLOPT_PROXY_ISSUERCERT:
2226 /*
2227 * Set Issuer certificate file
2228 * to check certificates issuer
2229 */
2230 result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_PROXY],
2231 va_arg(param, char *));
2232 break;
2233 case CURLOPT_PROXY_ISSUERCERT_BLOB:
2234 /*
2235 * Blob that holds Issuer certificate to check certificates issuer
2236 */
2237 result = Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY],
2238 va_arg(param, struct curl_blob *));
2239 break;
2240 #endif
2241 #ifndef CURL_DISABLE_TELNET
2242 case CURLOPT_TELNETOPTIONS:
2243 /*
2244 * Set a linked list of telnet options
2245 */
2246 data->set.telnet_options = va_arg(param, struct curl_slist *);
2247 break;
2248 #endif
2249 case CURLOPT_BUFFERSIZE:
2250 /*
2251 * The application kindly asks for a differently sized receive buffer.
2252 * If it seems reasonable, we'll use it.
2253 */
2254 arg = va_arg(param, long);
2255
2256 if(arg > READBUFFER_MAX)
2257 arg = READBUFFER_MAX;
2258 else if(arg < 1)
2259 arg = READBUFFER_SIZE;
2260 else if(arg < READBUFFER_MIN)
2261 arg = READBUFFER_MIN;
2262
2263 data->set.buffer_size = (unsigned int)arg;
2264 break;
2265
2266 case CURLOPT_UPLOAD_BUFFERSIZE:
2267 /*
2268 * The application kindly asks for a differently sized upload buffer.
2269 * Cap it to sensible.
2270 */
2271 arg = va_arg(param, long);
2272
2273 if(arg > UPLOADBUFFER_MAX)
2274 arg = UPLOADBUFFER_MAX;
2275 else if(arg < UPLOADBUFFER_MIN)
2276 arg = UPLOADBUFFER_MIN;
2277
2278 data->set.upload_buffer_size = (unsigned int)arg;
2279 break;
2280
2281 case CURLOPT_NOSIGNAL:
2282 /*
2283 * The application asks not to set any signal() or alarm() handlers,
2284 * even when using a timeout.
2285 */
2286 data->set.no_signal = (0 != va_arg(param, long));
2287 break;
2288
2289 case CURLOPT_SHARE:
2290 {
2291 struct Curl_share *set;
2292 set = va_arg(param, struct Curl_share *);
2293
2294 /* disconnect from old share, if any */
2295 if(data->share) {
2296 Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
2297
2298 if(data->dns.hostcachetype == HCACHE_SHARED) {
2299 data->dns.hostcache = NULL;
2300 data->dns.hostcachetype = HCACHE_NONE;
2301 }
2302
2303 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
2304 if(data->share->cookies == data->cookies)
2305 data->cookies = NULL;
2306 #endif
2307
2308 #ifndef CURL_DISABLE_HSTS
2309 if(data->share->hsts == data->hsts)
2310 data->hsts = NULL;
2311 #endif
2312 #ifdef USE_SSL
2313 if(data->share->sslsession == data->state.session)
2314 data->state.session = NULL;
2315 #endif
2316 #ifdef USE_LIBPSL
2317 if(data->psl == &data->share->psl)
2318 data->psl = data->multi? &data->multi->psl: NULL;
2319 #endif
2320
2321 data->share->dirty--;
2322
2323 Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
2324 data->share = NULL;
2325 }
2326
2327 if(GOOD_SHARE_HANDLE(set))
2328 /* use new share if it set */
2329 data->share = set;
2330 if(data->share) {
2331
2332 Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
2333
2334 data->share->dirty++;
2335
2336 if(data->share->specifier & (1<< CURL_LOCK_DATA_DNS)) {
2337 /* use shared host cache */
2338 data->dns.hostcache = &data->share->hostcache;
2339 data->dns.hostcachetype = HCACHE_SHARED;
2340 }
2341 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
2342 if(data->share->cookies) {
2343 /* use shared cookie list, first free own one if any */
2344 Curl_cookie_cleanup(data->cookies);
2345 /* enable cookies since we now use a share that uses cookies! */
2346 data->cookies = data->share->cookies;
2347 }
2348 #endif /* CURL_DISABLE_HTTP */
2349 #ifndef CURL_DISABLE_HSTS
2350 if(data->share->hsts) {
2351 /* first free the private one if any */
2352 Curl_hsts_cleanup(&data->hsts);
2353 data->hsts = data->share->hsts;
2354 }
2355 #endif
2356 #ifdef USE_SSL
2357 if(data->share->sslsession) {
2358 data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
2359 data->state.session = data->share->sslsession;
2360 }
2361 #endif
2362 #ifdef USE_LIBPSL
2363 if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL))
2364 data->psl = &data->share->psl;
2365 #endif
2366
2367 Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
2368 }
2369 /* check for host cache not needed,
2370 * it will be done by curl_easy_perform */
2371 }
2372 break;
2373
2374 case CURLOPT_PRIVATE:
2375 /*
2376 * Set private data pointer.
2377 */
2378 data->set.private_data = va_arg(param, void *);
2379 break;
2380
2381 case CURLOPT_MAXFILESIZE:
2382 /*
2383 * Set the maximum size of a file to download.
2384 */
2385 arg = va_arg(param, long);
2386 if(arg < 0)
2387 return CURLE_BAD_FUNCTION_ARGUMENT;
2388 data->set.max_filesize = arg;
2389 break;
2390
2391 #ifdef USE_SSL
2392 case CURLOPT_USE_SSL:
2393 /*
2394 * Make transfers attempt to use SSL/TLS.
2395 */
2396 arg = va_arg(param, long);
2397 if((arg < CURLUSESSL_NONE) || (arg >= CURLUSESSL_LAST))
2398 return CURLE_BAD_FUNCTION_ARGUMENT;
2399 data->set.use_ssl = (unsigned char)arg;
2400 break;
2401
2402 case CURLOPT_SSL_OPTIONS:
2403 arg = va_arg(param, long);
2404 data->set.ssl.primary.ssl_options = (unsigned char)(arg & 0xff);
2405 data->set.ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
2406 data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
2407 data->set.ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
2408 data->set.ssl.revoke_best_effort = !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT);
2409 data->set.ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
2410 data->set.ssl.auto_client_cert = !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT);
2411 /* If a setting is added here it should also be added in dohprobe()
2412 which sets its own CURLOPT_SSL_OPTIONS based on these settings. */
2413 break;
2414
2415 #ifndef CURL_DISABLE_PROXY
2416 case CURLOPT_PROXY_SSL_OPTIONS:
2417 arg = va_arg(param, long);
2418 data->set.proxy_ssl.primary.ssl_options = (unsigned char)(arg & 0xff);
2419 data->set.proxy_ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
2420 data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
2421 data->set.proxy_ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
2422 data->set.proxy_ssl.revoke_best_effort =
2423 !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT);
2424 data->set.proxy_ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
2425 data->set.proxy_ssl.auto_client_cert =
2426 !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT);
2427 break;
2428 #endif
2429
2430 case CURLOPT_SSL_EC_CURVES:
2431 /*
2432 * Set accepted curves in SSL connection setup.
2433 * Specify colon-delimited list of curve algorithm names.
2434 */
2435 result = Curl_setstropt(&data->set.str[STRING_SSL_EC_CURVES],
2436 va_arg(param, char *));
2437 break;
2438 #endif
2439 case CURLOPT_IPRESOLVE:
2440 arg = va_arg(param, long);
2441 if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6))
2442 return CURLE_BAD_FUNCTION_ARGUMENT;
2443 data->set.ipver = (unsigned char) arg;
2444 break;
2445
2446 case CURLOPT_MAXFILESIZE_LARGE:
2447 /*
2448 * Set the maximum size of a file to download.
2449 */
2450 bigsize = va_arg(param, curl_off_t);
2451 if(bigsize < 0)
2452 return CURLE_BAD_FUNCTION_ARGUMENT;
2453 data->set.max_filesize = bigsize;
2454 break;
2455
2456 case CURLOPT_TCP_NODELAY:
2457 /*
2458 * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
2459 * algorithm
2460 */
2461 data->set.tcp_nodelay = (0 != va_arg(param, long));
2462 break;
2463
2464 case CURLOPT_IGNORE_CONTENT_LENGTH:
2465 data->set.ignorecl = (0 != va_arg(param, long));
2466 break;
2467
2468 case CURLOPT_CONNECT_ONLY:
2469 /*
2470 * No data transfer.
2471 * (1) - only do connection
2472 * (2) - do first get request but get no content
2473 */
2474 arg = va_arg(param, long);
2475 if(arg > 2)
2476 return CURLE_BAD_FUNCTION_ARGUMENT;
2477 data->set.connect_only = (unsigned char)arg;
2478 break;
2479
2480 case CURLOPT_SOCKOPTFUNCTION:
2481 /*
2482 * socket callback function: called after socket() but before connect()
2483 */
2484 data->set.fsockopt = va_arg(param, curl_sockopt_callback);
2485 break;
2486
2487 case CURLOPT_SOCKOPTDATA:
2488 /*
2489 * socket callback data pointer. Might be NULL.
2490 */
2491 data->set.sockopt_client = va_arg(param, void *);
2492 break;
2493
2494 case CURLOPT_OPENSOCKETFUNCTION:
2495 /*
2496 * open/create socket callback function: called instead of socket(),
2497 * before connect()
2498 */
2499 data->set.fopensocket = va_arg(param, curl_opensocket_callback);
2500 break;
2501
2502 case CURLOPT_OPENSOCKETDATA:
2503 /*
2504 * socket callback data pointer. Might be NULL.
2505 */
2506 data->set.opensocket_client = va_arg(param, void *);
2507 break;
2508
2509 case CURLOPT_CLOSESOCKETFUNCTION:
2510 /*
2511 * close socket callback function: called instead of close()
2512 * when shutting down a connection
2513 */
2514 data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
2515 break;
2516
2517 case CURLOPT_RESOLVER_START_FUNCTION:
2518 /*
2519 * resolver start callback function: called before a new resolver request
2520 * is started
2521 */
2522 data->set.resolver_start = va_arg(param, curl_resolver_start_callback);
2523 break;
2524
2525 case CURLOPT_RESOLVER_START_DATA:
2526 /*
2527 * resolver start callback data pointer. Might be NULL.
2528 */
2529 data->set.resolver_start_client = va_arg(param, void *);
2530 break;
2531
2532 case CURLOPT_CLOSESOCKETDATA:
2533 /*
2534 * socket callback data pointer. Might be NULL.
2535 */
2536 data->set.closesocket_client = va_arg(param, void *);
2537 break;
2538
2539 case CURLOPT_SSL_SESSIONID_CACHE:
2540 data->set.ssl.primary.sessionid = (0 != va_arg(param, long));
2541 #ifndef CURL_DISABLE_PROXY
2542 data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid;
2543 #endif
2544 break;
2545
2546 #ifdef USE_SSH
2547 /* we only include SSH options if explicitly built to support SSH */
2548 case CURLOPT_SSH_AUTH_TYPES:
2549 data->set.ssh_auth_types = (int)va_arg(param, long);
2550 break;
2551
2552 case CURLOPT_SSH_PUBLIC_KEYFILE:
2553 /*
2554 * Use this file instead of the $HOME/.ssh/id_dsa.pub file
2555 */
2556 result = Curl_setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY],
2557 va_arg(param, char *));
2558 break;
2559
2560 case CURLOPT_SSH_PRIVATE_KEYFILE:
2561 /*
2562 * Use this file instead of the $HOME/.ssh/id_dsa file
2563 */
2564 result = Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
2565 va_arg(param, char *));
2566 break;
2567 case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
2568 /*
2569 * Option to allow for the MD5 of the host public key to be checked
2570 * for validation purposes.
2571 */
2572 result = Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
2573 va_arg(param, char *));
2574 break;
2575
2576 case CURLOPT_SSH_KNOWNHOSTS:
2577 /*
2578 * Store the file name to read known hosts from.
2579 */
2580 result = Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
2581 va_arg(param, char *));
2582 break;
2583 #ifdef USE_LIBSSH2
2584 case CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256:
2585 /*
2586 * Option to allow for the SHA256 of the host public key to be checked
2587 * for validation purposes.
2588 */
2589 result = Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256],
2590 va_arg(param, char *));
2591 break;
2592
2593 case CURLOPT_SSH_HOSTKEYFUNCTION:
2594 /* the callback to check the hostkey without the knownhost file */
2595 data->set.ssh_hostkeyfunc = va_arg(param, curl_sshhostkeycallback);
2596 break;
2597
2598 case CURLOPT_SSH_HOSTKEYDATA:
2599 /*
2600 * Custom client data to pass to the SSH keyfunc callback
2601 */
2602 data->set.ssh_hostkeyfunc_userp = va_arg(param, void *);
2603 break;
2604 #endif
2605
2606 case CURLOPT_SSH_KEYFUNCTION:
2607 /* setting to NULL is fine since the ssh.c functions themselves will
2608 then revert to use the internal default */
2609 data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
2610 break;
2611
2612 case CURLOPT_SSH_KEYDATA:
2613 /*
2614 * Custom client data to pass to the SSH keyfunc callback
2615 */
2616 data->set.ssh_keyfunc_userp = va_arg(param, void *);
2617 break;
2618
2619 case CURLOPT_SSH_COMPRESSION:
2620 data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE;
2621 break;
2622 #endif /* USE_SSH */
2623
2624 case CURLOPT_HTTP_TRANSFER_DECODING:
2625 /*
2626 * disable libcurl transfer encoding is used
2627 */
2628 #ifndef USE_HYPER
2629 data->set.http_te_skip = (0 == va_arg(param, long));
2630 break;
2631 #else
2632 return CURLE_NOT_BUILT_IN; /* hyper doesn't support */
2633 #endif
2634
2635 case CURLOPT_HTTP_CONTENT_DECODING:
2636 /*
2637 * raw data passed to the application when content encoding is used
2638 */
2639 data->set.http_ce_skip = (0 == va_arg(param, long));
2640 break;
2641
2642 #if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
2643 case CURLOPT_NEW_FILE_PERMS:
2644 /*
2645 * Uses these permissions instead of 0644
2646 */
2647 arg = va_arg(param, long);
2648 if((arg < 0) || (arg > 0777))
2649 return CURLE_BAD_FUNCTION_ARGUMENT;
2650 data->set.new_file_perms = (unsigned int)arg;
2651 break;
2652 #endif
2653 #ifdef USE_SSH
2654 case CURLOPT_NEW_DIRECTORY_PERMS:
2655 /*
2656 * Uses these permissions instead of 0755
2657 */
2658 arg = va_arg(param, long);
2659 if((arg < 0) || (arg > 0777))
2660 return CURLE_BAD_FUNCTION_ARGUMENT;
2661 data->set.new_directory_perms = (unsigned int)arg;
2662 break;
2663 #endif
2664
2665 #ifdef USE_IPV6
2666 case CURLOPT_ADDRESS_SCOPE:
2667 /*
2668 * Use this scope id when using IPv6
2669 * We always get longs when passed plain numericals so we should check
2670 * that the value fits into an unsigned 32 bit integer.
2671 */
2672 uarg = va_arg(param, unsigned long);
2673 #if SIZEOF_LONG > 4
2674 if(uarg > UINT_MAX)
2675 return CURLE_BAD_FUNCTION_ARGUMENT;
2676 #endif
2677 data->set.scope_id = (unsigned int)uarg;
2678 break;
2679 #endif
2680
2681 case CURLOPT_PROTOCOLS:
2682 /* set the bitmask for the protocols that are allowed to be used for the
2683 transfer, which thus helps the app which takes URLs from users or other
2684 external inputs and want to restrict what protocol(s) to deal
2685 with. Defaults to CURLPROTO_ALL. */
2686 data->set.allowed_protocols = (curl_prot_t)va_arg(param, long);
2687 break;
2688
2689 case CURLOPT_REDIR_PROTOCOLS:
2690 /* set the bitmask for the protocols that libcurl is allowed to follow to,
2691 as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
2692 to be set in both bitmasks to be allowed to get redirected to. */
2693 data->set.redir_protocols = (curl_prot_t)va_arg(param, long);
2694 break;
2695
2696 case CURLOPT_PROTOCOLS_STR: {
2697 argptr = va_arg(param, char *);
2698 result = protocol2num(argptr, &data->set.allowed_protocols);
2699 if(result)
2700 return result;
2701 break;
2702 }
2703
2704 case CURLOPT_REDIR_PROTOCOLS_STR: {
2705 argptr = va_arg(param, char *);
2706 result = protocol2num(argptr, &data->set.redir_protocols);
2707 if(result)
2708 return result;
2709 break;
2710 }
2711
2712 case CURLOPT_DEFAULT_PROTOCOL:
2713 /* Set the protocol to use when the URL doesn't include any protocol */
2714 result = Curl_setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL],
2715 va_arg(param, char *));
2716 break;
2717 #ifndef CURL_DISABLE_SMTP
2718 case CURLOPT_MAIL_FROM:
2719 /* Set the SMTP mail originator */
2720 result = Curl_setstropt(&data->set.str[STRING_MAIL_FROM],
2721 va_arg(param, char *));
2722 break;
2723
2724 case CURLOPT_MAIL_AUTH:
2725 /* Set the SMTP auth originator */
2726 result = Curl_setstropt(&data->set.str[STRING_MAIL_AUTH],
2727 va_arg(param, char *));
2728 break;
2729
2730 case CURLOPT_MAIL_RCPT:
2731 /* Set the list of mail recipients */
2732 data->set.mail_rcpt = va_arg(param, struct curl_slist *);
2733 break;
2734 case CURLOPT_MAIL_RCPT_ALLOWFAILS:
2735 /* allow RCPT TO command to fail for some recipients */
2736 data->set.mail_rcpt_allowfails = (0 != va_arg(param, long));
2737 break;
2738 #endif
2739
2740 case CURLOPT_SASL_AUTHZID:
2741 /* Authorization identity (identity to act as) */
2742 result = Curl_setstropt(&data->set.str[STRING_SASL_AUTHZID],
2743 va_arg(param, char *));
2744 break;
2745
2746 case CURLOPT_SASL_IR:
2747 /* Enable/disable SASL initial response */
2748 data->set.sasl_ir = (0 != va_arg(param, long));
2749 break;
2750 #ifndef CURL_DISABLE_RTSP
2751 case CURLOPT_RTSP_REQUEST:
2752 {
2753 /*
2754 * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
2755 * Would this be better if the RTSPREQ_* were just moved into here?
2756 */
2757 long in_rtspreq = va_arg(param, long);
2758 Curl_RtspReq rtspreq = RTSPREQ_NONE;
2759 switch(in_rtspreq) {
2760 case CURL_RTSPREQ_OPTIONS:
2761 rtspreq = RTSPREQ_OPTIONS;
2762 break;
2763
2764 case CURL_RTSPREQ_DESCRIBE:
2765 rtspreq = RTSPREQ_DESCRIBE;
2766 break;
2767
2768 case CURL_RTSPREQ_ANNOUNCE:
2769 rtspreq = RTSPREQ_ANNOUNCE;
2770 break;
2771
2772 case CURL_RTSPREQ_SETUP:
2773 rtspreq = RTSPREQ_SETUP;
2774 break;
2775
2776 case CURL_RTSPREQ_PLAY:
2777 rtspreq = RTSPREQ_PLAY;
2778 break;
2779
2780 case CURL_RTSPREQ_PAUSE:
2781 rtspreq = RTSPREQ_PAUSE;
2782 break;
2783
2784 case CURL_RTSPREQ_TEARDOWN:
2785 rtspreq = RTSPREQ_TEARDOWN;
2786 break;
2787
2788 case CURL_RTSPREQ_GET_PARAMETER:
2789 rtspreq = RTSPREQ_GET_PARAMETER;
2790 break;
2791
2792 case CURL_RTSPREQ_SET_PARAMETER:
2793 rtspreq = RTSPREQ_SET_PARAMETER;
2794 break;
2795
2796 case CURL_RTSPREQ_RECORD:
2797 rtspreq = RTSPREQ_RECORD;
2798 break;
2799
2800 case CURL_RTSPREQ_RECEIVE:
2801 rtspreq = RTSPREQ_RECEIVE;
2802 break;
2803 default:
2804 rtspreq = RTSPREQ_NONE;
2805 }
2806
2807 data->set.rtspreq = rtspreq;
2808 break;
2809 }
2810
2811
2812 case CURLOPT_RTSP_SESSION_ID:
2813 /*
2814 * Set the RTSP Session ID manually. Useful if the application is
2815 * resuming a previously established RTSP session
2816 */
2817 result = Curl_setstropt(&data->set.str[STRING_RTSP_SESSION_ID],
2818 va_arg(param, char *));
2819 break;
2820
2821 case CURLOPT_RTSP_STREAM_URI:
2822 /*
2823 * Set the Stream URI for the RTSP request. Unless the request is
2824 * for generic server options, the application will need to set this.
2825 */
2826 result = Curl_setstropt(&data->set.str[STRING_RTSP_STREAM_URI],
2827 va_arg(param, char *));
2828 break;
2829
2830 case CURLOPT_RTSP_TRANSPORT:
2831 /*
2832 * The content of the Transport: header for the RTSP request
2833 */
2834 result = Curl_setstropt(&data->set.str[STRING_RTSP_TRANSPORT],
2835 va_arg(param, char *));
2836 break;
2837
2838 case CURLOPT_RTSP_CLIENT_CSEQ:
2839 /*
2840 * Set the CSEQ number to issue for the next RTSP request. Useful if the
2841 * application is resuming a previously broken connection. The CSEQ
2842 * will increment from this new number henceforth.
2843 */
2844 data->state.rtsp_next_client_CSeq = va_arg(param, long);
2845 break;
2846
2847 case CURLOPT_RTSP_SERVER_CSEQ:
2848 /* Same as the above, but for server-initiated requests */
2849 data->state.rtsp_next_server_CSeq = va_arg(param, long);
2850 break;
2851
2852 case CURLOPT_INTERLEAVEDATA:
2853 data->set.rtp_out = va_arg(param, void *);
2854 break;
2855 case CURLOPT_INTERLEAVEFUNCTION:
2856 /* Set the user defined RTP write function */
2857 data->set.fwrite_rtp = va_arg(param, curl_write_callback);
2858 break;
2859 #endif
2860 #ifndef CURL_DISABLE_FTP
2861 case CURLOPT_WILDCARDMATCH:
2862 data->set.wildcard_enabled = (0 != va_arg(param, long));
2863 break;
2864 case CURLOPT_CHUNK_BGN_FUNCTION:
2865 data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
2866 break;
2867 case CURLOPT_CHUNK_END_FUNCTION:
2868 data->set.chunk_end = va_arg(param, curl_chunk_end_callback);
2869 break;
2870 case CURLOPT_FNMATCH_FUNCTION:
2871 data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
2872 break;
2873 case CURLOPT_CHUNK_DATA:
2874 data->set.wildcardptr = va_arg(param, void *);
2875 break;
2876 case CURLOPT_FNMATCH_DATA:
2877 data->set.fnmatch_data = va_arg(param, void *);
2878 break;
2879 #endif
2880 #ifdef USE_TLS_SRP
2881 case CURLOPT_TLSAUTH_USERNAME:
2882 result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
2883 va_arg(param, char *));
2884 break;
2885 #ifndef CURL_DISABLE_PROXY
2886 case CURLOPT_PROXY_TLSAUTH_USERNAME:
2887 result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
2888 va_arg(param, char *));
2889 break;
2890 #endif
2891 case CURLOPT_TLSAUTH_PASSWORD:
2892 result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
2893 va_arg(param, char *));
2894 break;
2895 #ifndef CURL_DISABLE_PROXY
2896 case CURLOPT_PROXY_TLSAUTH_PASSWORD:
2897 result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
2898 va_arg(param, char *));
2899 break;
2900 #endif
2901 case CURLOPT_TLSAUTH_TYPE:
2902 argptr = va_arg(param, char *);
2903 if(argptr && !strcasecompare(argptr, "SRP"))
2904 return CURLE_BAD_FUNCTION_ARGUMENT;
2905 break;
2906 #ifndef CURL_DISABLE_PROXY
2907 case CURLOPT_PROXY_TLSAUTH_TYPE:
2908 argptr = va_arg(param, char *);
2909 if(argptr && !strcasecompare(argptr, "SRP"))
2910 return CURLE_BAD_FUNCTION_ARGUMENT;
2911 break;
2912 #endif
2913 #endif
2914 #ifdef USE_ARES
2915 case CURLOPT_DNS_SERVERS:
2916 result = Curl_setstropt(&data->set.str[STRING_DNS_SERVERS],
2917 va_arg(param, char *));
2918 if(result)
2919 return result;
2920 result = Curl_set_dns_servers(data, data->set.str[STRING_DNS_SERVERS]);
2921 break;
2922 case CURLOPT_DNS_INTERFACE:
2923 result = Curl_setstropt(&data->set.str[STRING_DNS_INTERFACE],
2924 va_arg(param, char *));
2925 if(result)
2926 return result;
2927 result = Curl_set_dns_interface(data, data->set.str[STRING_DNS_INTERFACE]);
2928 break;
2929 case CURLOPT_DNS_LOCAL_IP4:
2930 result = Curl_setstropt(&data->set.str[STRING_DNS_LOCAL_IP4],
2931 va_arg(param, char *));
2932 if(result)
2933 return result;
2934 result = Curl_set_dns_local_ip4(data, data->set.str[STRING_DNS_LOCAL_IP4]);
2935 break;
2936 case CURLOPT_DNS_LOCAL_IP6:
2937 result = Curl_setstropt(&data->set.str[STRING_DNS_LOCAL_IP6],
2938 va_arg(param, char *));
2939 if(result)
2940 return result;
2941 result = Curl_set_dns_local_ip6(data, data->set.str[STRING_DNS_LOCAL_IP6]);
2942 break;
2943 #endif
2944 case CURLOPT_TCP_KEEPALIVE:
2945 data->set.tcp_keepalive = (0 != va_arg(param, long));
2946 break;
2947 case CURLOPT_TCP_KEEPIDLE:
2948 arg = va_arg(param, long);
2949 if(arg < 0)
2950 return CURLE_BAD_FUNCTION_ARGUMENT;
2951 else if(arg > INT_MAX)
2952 arg = INT_MAX;
2953 data->set.tcp_keepidle = (int)arg;
2954 break;
2955 case CURLOPT_TCP_KEEPINTVL:
2956 arg = va_arg(param, long);
2957 if(arg < 0)
2958 return CURLE_BAD_FUNCTION_ARGUMENT;
2959 else if(arg > INT_MAX)
2960 arg = INT_MAX;
2961 data->set.tcp_keepintvl = (int)arg;
2962 break;
2963 case CURLOPT_TCP_KEEPCNT:
2964 arg = va_arg(param, long);
2965 if(arg < 0)
2966 return CURLE_BAD_FUNCTION_ARGUMENT;
2967 else if(arg > INT_MAX)
2968 arg = INT_MAX;
2969 data->set.tcp_keepcnt = (int)arg;
2970 break;
2971 case CURLOPT_TCP_FASTOPEN:
2972 #if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN) || \
2973 defined(TCP_FASTOPEN_CONNECT)
2974 data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE;
2975 #else
2976 result = CURLE_NOT_BUILT_IN;
2977 #endif
2978 break;
2979 case CURLOPT_SSL_ENABLE_NPN:
2980 break;
2981 case CURLOPT_SSL_ENABLE_ALPN:
2982 data->set.ssl_enable_alpn = (0 != va_arg(param, long));
2983 break;
2984 #ifdef USE_UNIX_SOCKETS
2985 case CURLOPT_UNIX_SOCKET_PATH:
2986 data->set.abstract_unix_socket = FALSE;
2987 result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
2988 va_arg(param, char *));
2989 break;
2990 case CURLOPT_ABSTRACT_UNIX_SOCKET:
2991 data->set.abstract_unix_socket = TRUE;
2992 result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
2993 va_arg(param, char *));
2994 break;
2995 #endif
2996
2997 case CURLOPT_PATH_AS_IS:
2998 data->set.path_as_is = (0 != va_arg(param, long));
2999 break;
3000 case CURLOPT_PIPEWAIT:
3001 data->set.pipewait = (0 != va_arg(param, long));
3002 break;
3003 case CURLOPT_STREAM_WEIGHT:
3004 #if defined(USE_HTTP2) || defined(USE_HTTP3)
3005 arg = va_arg(param, long);
3006 if((arg >= 1) && (arg <= 256))
3007 data->set.priority.weight = (int)arg;
3008 break;
3009 #else
3010 return CURLE_NOT_BUILT_IN;
3011 #endif
3012 case CURLOPT_STREAM_DEPENDS:
3013 case CURLOPT_STREAM_DEPENDS_E:
3014 {
3015 struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
3016 if(!dep || GOOD_EASY_HANDLE(dep)) {
3017 return Curl_data_priority_add_child(dep, data,
3018 option == CURLOPT_STREAM_DEPENDS_E);
3019 }
3020 break;
3021 }
3022 case CURLOPT_CONNECT_TO:
3023 data->set.connect_to = va_arg(param, struct curl_slist *);
3024 break;
3025 case CURLOPT_SUPPRESS_CONNECT_HEADERS:
3026 data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE;
3027 break;
3028 case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS:
3029 uarg = va_arg(param, unsigned long);
3030 if(uarg > UINT_MAX)
3031 uarg = UINT_MAX;
3032 data->set.happy_eyeballs_timeout = (unsigned int)uarg;
3033 break;
3034 #ifndef CURL_DISABLE_SHUFFLE_DNS
3035 case CURLOPT_DNS_SHUFFLE_ADDRESSES:
3036 data->set.dns_shuffle_addresses = (0 != va_arg(param, long));
3037 break;
3038 #endif
3039 case CURLOPT_DISALLOW_USERNAME_IN_URL:
3040 data->set.disallow_username_in_url = (0 != va_arg(param, long));
3041 break;
3042 #ifndef CURL_DISABLE_DOH
3043 case CURLOPT_DOH_URL:
3044 result = Curl_setstropt(&data->set.str[STRING_DOH],
3045 va_arg(param, char *));
3046 data->set.doh = data->set.str[STRING_DOH]?TRUE:FALSE;
3047 break;
3048 #endif
3049 case CURLOPT_UPKEEP_INTERVAL_MS:
3050 arg = va_arg(param, long);
3051 if(arg < 0)
3052 return CURLE_BAD_FUNCTION_ARGUMENT;
3053 data->set.upkeep_interval_ms = arg;
3054 break;
3055 case CURLOPT_MAXAGE_CONN:
3056 arg = va_arg(param, long);
3057 if(arg < 0)
3058 return CURLE_BAD_FUNCTION_ARGUMENT;
3059 data->set.maxage_conn = arg;
3060 break;
3061 case CURLOPT_MAXLIFETIME_CONN:
3062 arg = va_arg(param, long);
3063 if(arg < 0)
3064 return CURLE_BAD_FUNCTION_ARGUMENT;
3065 data->set.maxlifetime_conn = arg;
3066 break;
3067 case CURLOPT_TRAILERFUNCTION:
3068 #ifndef CURL_DISABLE_HTTP
3069 data->set.trailer_callback = va_arg(param, curl_trailer_callback);
3070 #endif
3071 break;
3072 case CURLOPT_TRAILERDATA:
3073 #ifndef CURL_DISABLE_HTTP
3074 data->set.trailer_data = va_arg(param, void *);
3075 #endif
3076 break;
3077 #ifndef CURL_DISABLE_HSTS
3078 case CURLOPT_HSTSREADFUNCTION:
3079 data->set.hsts_read = va_arg(param, curl_hstsread_callback);
3080 break;
3081 case CURLOPT_HSTSREADDATA:
3082 data->set.hsts_read_userp = va_arg(param, void *);
3083 break;
3084 case CURLOPT_HSTSWRITEFUNCTION:
3085 data->set.hsts_write = va_arg(param, curl_hstswrite_callback);
3086 break;
3087 case CURLOPT_HSTSWRITEDATA:
3088 data->set.hsts_write_userp = va_arg(param, void *);
3089 break;
3090 case CURLOPT_HSTS: {
3091 struct curl_slist *h;
3092 if(!data->hsts) {
3093 data->hsts = Curl_hsts_init();
3094 if(!data->hsts)
3095 return CURLE_OUT_OF_MEMORY;
3096 }
3097 argptr = va_arg(param, char *);
3098 if(argptr) {
3099 result = Curl_setstropt(&data->set.str[STRING_HSTS], argptr);
3100 if(result)
3101 return result;
3102 /* this needs to build a list of file names to read from, so that it can
3103 read them later, as we might get a shared HSTS handle to load them
3104 into */
3105 h = curl_slist_append(data->state.hstslist, argptr);
3106 if(!h) {
3107 curl_slist_free_all(data->state.hstslist);
3108 data->state.hstslist = NULL;
3109 return CURLE_OUT_OF_MEMORY;
3110 }
3111 data->state.hstslist = h; /* store the list for later use */
3112 }
3113 else {
3114 /* clear the list of HSTS files */
3115 curl_slist_free_all(data->state.hstslist);
3116 data->state.hstslist = NULL;
3117 if(!data->share || !data->share->hsts)
3118 /* throw away the HSTS cache unless shared */
3119 Curl_hsts_cleanup(&data->hsts);
3120 }
3121 break;
3122 }
3123 case CURLOPT_HSTS_CTRL:
3124 arg = va_arg(param, long);
3125 if(arg & CURLHSTS_ENABLE) {
3126 if(!data->hsts) {
3127 data->hsts = Curl_hsts_init();
3128 if(!data->hsts)
3129 return CURLE_OUT_OF_MEMORY;
3130 }
3131 }
3132 else
3133 Curl_hsts_cleanup(&data->hsts);
3134 break;
3135 #endif
3136 #ifndef CURL_DISABLE_ALTSVC
3137 case CURLOPT_ALTSVC:
3138 if(!data->asi) {
3139 data->asi = Curl_altsvc_init();
3140 if(!data->asi)
3141 return CURLE_OUT_OF_MEMORY;
3142 }
3143 argptr = va_arg(param, char *);
3144 result = Curl_setstropt(&data->set.str[STRING_ALTSVC], argptr);
3145 if(result)
3146 return result;
3147 if(argptr)
3148 (void)Curl_altsvc_load(data->asi, argptr);
3149 break;
3150 case CURLOPT_ALTSVC_CTRL:
3151 if(!data->asi) {
3152 data->asi = Curl_altsvc_init();
3153 if(!data->asi)
3154 return CURLE_OUT_OF_MEMORY;
3155 }
3156 arg = va_arg(param, long);
3157 if(!arg) {
3158 DEBUGF(infof(data, "bad CURLOPT_ALTSVC_CTRL input"));
3159 return CURLE_BAD_FUNCTION_ARGUMENT;
3160 }
3161 result = Curl_altsvc_ctrl(data->asi, arg);
3162 if(result)
3163 return result;
3164 break;
3165 #endif
3166 case CURLOPT_PREREQFUNCTION:
3167 data->set.fprereq = va_arg(param, curl_prereq_callback);
3168 break;
3169 case CURLOPT_PREREQDATA:
3170 data->set.prereq_userp = va_arg(param, void *);
3171 break;
3172 #ifdef USE_WEBSOCKETS
3173 case CURLOPT_WS_OPTIONS: {
3174 bool raw;
3175 arg = va_arg(param, long);
3176 raw = (arg & CURLWS_RAW_MODE);
3177 data->set.ws_raw_mode = raw;
3178 break;
3179 }
3180 #endif
3181 #ifdef USE_ECH
3182 case CURLOPT_ECH: {
3183 size_t plen = 0;
3184
3185 argptr = va_arg(param, char *);
3186 if(!argptr) {
3187 data->set.tls_ech = CURLECH_DISABLE;
3188 result = CURLE_BAD_FUNCTION_ARGUMENT;
3189 return result;
3190 }
3191 plen = strlen(argptr);
3192 if(plen > CURL_MAX_INPUT_LENGTH) {
3193 data->set.tls_ech = CURLECH_DISABLE;
3194 result = CURLE_BAD_FUNCTION_ARGUMENT;
3195 return result;
3196 }
3197 /* set tls_ech flag value, preserving CLA_CFG bit */
3198 if(plen == 5 && !strcmp(argptr, "false"))
3199 data->set.tls_ech = CURLECH_DISABLE
3200 | (data->set.tls_ech & CURLECH_CLA_CFG);
3201 else if(plen == 6 && !strcmp(argptr, "grease"))
3202 data->set.tls_ech = CURLECH_GREASE
3203 | (data->set.tls_ech & CURLECH_CLA_CFG);
3204 else if(plen == 4 && !strcmp(argptr, "true"))
3205 data->set.tls_ech = CURLECH_ENABLE
3206 | (data->set.tls_ech & CURLECH_CLA_CFG);
3207 else if(plen == 4 && !strcmp(argptr, "hard"))
3208 data->set.tls_ech = CURLECH_HARD
3209 | (data->set.tls_ech & CURLECH_CLA_CFG);
3210 else if(plen > 5 && !strncmp(argptr, "ecl:", 4)) {
3211 result = Curl_setstropt(&data->set.str[STRING_ECH_CONFIG], argptr + 4);
3212 if(result)
3213 return result;
3214 data->set.tls_ech |= CURLECH_CLA_CFG;
3215 }
3216 else if(plen > 4 && !strncmp(argptr, "pn:", 3)) {
3217 result = Curl_setstropt(&data->set.str[STRING_ECH_PUBLIC], argptr + 3);
3218 if(result)
3219 return result;
3220 }
3221 break;
3222 }
3223 #endif
3224 case CURLOPT_QUICK_EXIT:
3225 data->set.quick_exit = (0 != va_arg(param, long)) ? 1L:0L;
3226 break;
3227 default:
3228 /* unknown tag and its companion, just ignore: */
3229 result = CURLE_UNKNOWN_OPTION;
3230 break;
3231 }
3232
3233 return result;
3234 }
3235
3236 /*
3237 * curl_easy_setopt() is the external interface for setting options on an
3238 * easy handle.
3239 *
3240 * NOTE: This is one of few API functions that are allowed to be called from
3241 * within a callback.
3242 */
3243
3244 #undef curl_easy_setopt
curl_easy_setopt(struct Curl_easy * data,CURLoption tag,...)3245 CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...)
3246 {
3247 va_list arg;
3248 CURLcode result;
3249
3250 if(!data)
3251 return CURLE_BAD_FUNCTION_ARGUMENT;
3252
3253 va_start(arg, tag);
3254
3255 result = Curl_vsetopt(data, tag, arg);
3256
3257 va_end(arg);
3258 #ifdef DEBUGBUILD
3259 if(result == CURLE_BAD_FUNCTION_ARGUMENT)
3260 infof(data, "setopt arg 0x%x returned CURLE_BAD_FUNCTION_ARGUMENT", tag);
3261 #endif
3262 return result;
3263 }
3264