Coverage Report

Created: 2026-09-14 07:05

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