Coverage Report

Created: 2023-06-07 07:02

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