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