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