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