Coverage Report

Created: 2026-10-22 06:51

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