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