Coverage Report

Created: 2026-07-16 06:10

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