Coverage Report

Created: 2026-08-31 06:46

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