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