Coverage Report

Created: 2026-07-14 07:09

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