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