1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2016, 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.haxx.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 ***************************************************************************/
22
23 #include "curl_setup.h"
24
25 #ifdef HAVE_NETINET_IN_H
26 #include <netinet/in.h>
27 #endif
28 #ifdef HAVE_NETDB_H
29 #include <netdb.h>
30 #endif
31 #ifdef HAVE_ARPA_INET_H
32 #include <arpa/inet.h>
33 #endif
34 #ifdef HAVE_NET_IF_H
35 #include <net/if.h>
36 #endif
37 #ifdef HAVE_SYS_IOCTL_H
38 #include <sys/ioctl.h>
39 #endif
40
41 #ifdef HAVE_SYS_PARAM_H
42 #include <sys/param.h>
43 #endif
44
45 #ifdef __VMS
46 #include <in.h>
47 #include <inet.h>
48 #endif
49
50 #ifdef HAVE_SYS_UN_H
51 #include <sys/un.h>
52 #endif
53
54 #ifndef HAVE_SOCKET
55 #error "We can't compile without socket() support!"
56 #endif
57
58 #ifdef HAVE_LIMITS_H
59 #include <limits.h>
60 #endif
61
62 #ifdef USE_LIBIDN
63 #include <idna.h>
64 #include <tld.h>
65 #include <stringprep.h>
66 #ifdef HAVE_IDN_FREE_H
67 #include <idn-free.h>
68 #else
69 /* prototype from idn-free.h, not provided by libidn 0.4.5's make install! */
70 void idn_free (void *ptr);
71 #endif
72 #ifndef HAVE_IDN_FREE
73 /* if idn_free() was not found in this version of libidn use free() instead */
74 #define idn_free(x) (free)(x)
75 #endif
76 #elif defined(USE_WIN32_IDN)
77 /* prototype for curl_win32_idn_to_ascii() */
78 bool curl_win32_idn_to_ascii(const char *in, char **out);
79 #endif /* USE_LIBIDN */
80
81 #include "urldata.h"
82 #include "netrc.h"
83
84 #include "formdata.h"
85 #include "vtls/vtls.h"
86 #include "hostip.h"
87 #include "transfer.h"
88 #include "sendf.h"
89 #include "progress.h"
90 #include "cookie.h"
91 #include "strequal.h"
92 #include "strerror.h"
93 #include "escape.h"
94 #include "strtok.h"
95 #include "share.h"
96 #include "content_encoding.h"
97 #include "http_digest.h"
98 #include "http_negotiate.h"
99 #include "select.h"
100 #include "multiif.h"
101 #include "easyif.h"
102 #include "speedcheck.h"
103 #include "rawstr.h"
104 #include "warnless.h"
105 #include "non-ascii.h"
106 #include "inet_pton.h"
107
108 /* And now for the protocols */
109 #include "ftp.h"
110 #include "dict.h"
111 #include "telnet.h"
112 #include "tftp.h"
113 #include "http.h"
114 #include "http2.h"
115 #include "file.h"
116 #include "curl_ldap.h"
117 #include "ssh.h"
118 #include "imap.h"
119 #include "url.h"
120 #include "connect.h"
121 #include "inet_ntop.h"
122 #include "http_ntlm.h"
123 #include "curl_ntlm_wb.h"
124 #include "socks.h"
125 #include "curl_rtmp.h"
126 #include "gopher.h"
127 #include "http_proxy.h"
128 #include "conncache.h"
129 #include "multihandle.h"
130 #include "pipeline.h"
131 #include "dotdot.h"
132 #include "strdup.h"
133 /* The last 3 #include files should be in this order */
134 #include "curl_printf.h"
135 #include "curl_memory.h"
136 #include "memdebug.h"
137
138 /* Local static prototypes */
139 static struct connectdata *
140 find_oldest_idle_connection_in_bundle(struct SessionHandle *data,
141 struct connectbundle *bundle);
142 static void conn_free(struct connectdata *conn);
143 static void free_fixed_hostname(struct hostname *host);
144 static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
145 static CURLcode parse_url_login(struct SessionHandle *data,
146 struct connectdata *conn,
147 char **userptr, char **passwdptr,
148 char **optionsptr);
149 static CURLcode parse_login_details(const char *login, const size_t len,
150 char **userptr, char **passwdptr,
151 char **optionsptr);
152 static unsigned int get_protocol_family(unsigned int protocol);
153
154 /*
155 * Protocol table.
156 */
157
158 static const struct Curl_handler * const protocols[] = {
159
160 #ifndef CURL_DISABLE_HTTP
161 &Curl_handler_http,
162 #endif
163
164 #if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
165 &Curl_handler_https,
166 #endif
167
168 #ifndef CURL_DISABLE_FTP
169 &Curl_handler_ftp,
170 #endif
171
172 #if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
173 &Curl_handler_ftps,
174 #endif
175
176 #ifndef CURL_DISABLE_TELNET
177 &Curl_handler_telnet,
178 #endif
179
180 #ifndef CURL_DISABLE_DICT
181 &Curl_handler_dict,
182 #endif
183
184 #ifndef CURL_DISABLE_LDAP
185 &Curl_handler_ldap,
186 #if !defined(CURL_DISABLE_LDAPS) && \
187 ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
188 (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
189 &Curl_handler_ldaps,
190 #endif
191 #endif
192
193 #ifndef CURL_DISABLE_FILE
194 &Curl_handler_file,
195 #endif
196
197 #ifndef CURL_DISABLE_TFTP
198 &Curl_handler_tftp,
199 #endif
200
201 #ifdef USE_LIBSSH2
202 &Curl_handler_scp,
203 &Curl_handler_sftp,
204 #endif
205
206 #ifndef CURL_DISABLE_IMAP
207 &Curl_handler_imap,
208 #ifdef USE_SSL
209 &Curl_handler_imaps,
210 #endif
211 #endif
212
213 #ifndef CURL_DISABLE_POP3
214 &Curl_handler_pop3,
215 #ifdef USE_SSL
216 &Curl_handler_pop3s,
217 #endif
218 #endif
219
220 #if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
221 (CURL_SIZEOF_CURL_OFF_T > 4) && \
222 (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO))
223 &Curl_handler_smb,
224 #ifdef USE_SSL
225 &Curl_handler_smbs,
226 #endif
227 #endif
228
229 #ifndef CURL_DISABLE_SMTP
230 &Curl_handler_smtp,
231 #ifdef USE_SSL
232 &Curl_handler_smtps,
233 #endif
234 #endif
235
236 #ifndef CURL_DISABLE_RTSP
237 &Curl_handler_rtsp,
238 #endif
239
240 #ifndef CURL_DISABLE_GOPHER
241 &Curl_handler_gopher,
242 #endif
243
244 #ifdef USE_LIBRTMP
245 &Curl_handler_rtmp,
246 &Curl_handler_rtmpt,
247 &Curl_handler_rtmpe,
248 &Curl_handler_rtmpte,
249 &Curl_handler_rtmps,
250 &Curl_handler_rtmpts,
251 #endif
252
253 (struct Curl_handler *) NULL
254 };
255
256 /*
257 * Dummy handler for undefined protocol schemes.
258 */
259
260 static const struct Curl_handler Curl_handler_dummy = {
261 "<no protocol>", /* scheme */
262 ZERO_NULL, /* setup_connection */
263 ZERO_NULL, /* do_it */
264 ZERO_NULL, /* done */
265 ZERO_NULL, /* do_more */
266 ZERO_NULL, /* connect_it */
267 ZERO_NULL, /* connecting */
268 ZERO_NULL, /* doing */
269 ZERO_NULL, /* proto_getsock */
270 ZERO_NULL, /* doing_getsock */
271 ZERO_NULL, /* domore_getsock */
272 ZERO_NULL, /* perform_getsock */
273 ZERO_NULL, /* disconnect */
274 ZERO_NULL, /* readwrite */
275 0, /* defport */
276 0, /* protocol */
277 PROTOPT_NONE /* flags */
278 };
279
Curl_freeset(struct SessionHandle * data)280 void Curl_freeset(struct SessionHandle *data)
281 {
282 /* Free all dynamic strings stored in the data->set substructure. */
283 enum dupstring i;
284 for(i=(enum dupstring)0; i < STRING_LAST; i++) {
285 Curl_safefree(data->set.str[i]);
286 }
287
288 if(data->change.referer_alloc) {
289 Curl_safefree(data->change.referer);
290 data->change.referer_alloc = FALSE;
291 }
292 data->change.referer = NULL;
293 if(data->change.url_alloc) {
294 Curl_safefree(data->change.url);
295 data->change.url_alloc = FALSE;
296 }
297 data->change.url = NULL;
298 }
299
setstropt(char ** charp,const char * s)300 static CURLcode setstropt(char **charp, const char *s)
301 {
302 /* Release the previous storage at `charp' and replace by a dynamic storage
303 copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
304
305 Curl_safefree(*charp);
306
307 if(s) {
308 char *str = strdup(s);
309
310 if(!str)
311 return CURLE_OUT_OF_MEMORY;
312
313 *charp = str;
314 }
315
316 return CURLE_OK;
317 }
318
setstropt_userpwd(char * option,char ** userp,char ** passwdp)319 static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
320 {
321 CURLcode result = CURLE_OK;
322 char *user = NULL;
323 char *passwd = NULL;
324
325 /* Parse the login details if specified. It not then we treat NULL as a hint
326 to clear the existing data */
327 if(option) {
328 result = parse_login_details(option, strlen(option),
329 (userp ? &user : NULL),
330 (passwdp ? &passwd : NULL),
331 NULL);
332 }
333
334 if(!result) {
335 /* Store the username part of option if required */
336 if(userp) {
337 if(!user && option && option[0] == ':') {
338 /* Allocate an empty string instead of returning NULL as user name */
339 user = strdup("");
340 if(!user)
341 result = CURLE_OUT_OF_MEMORY;
342 }
343
344 Curl_safefree(*userp);
345 *userp = user;
346 }
347
348 /* Store the password part of option if required */
349 if(passwdp) {
350 Curl_safefree(*passwdp);
351 *passwdp = passwd;
352 }
353 }
354
355 return result;
356 }
357
Curl_dupset(struct SessionHandle * dst,struct SessionHandle * src)358 CURLcode Curl_dupset(struct SessionHandle *dst, struct SessionHandle *src)
359 {
360 CURLcode result = CURLE_OK;
361 enum dupstring i;
362
363 /* Copy src->set into dst->set first, then deal with the strings
364 afterwards */
365 dst->set = src->set;
366
367 /* clear all string pointers first */
368 memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
369
370 /* duplicate all strings */
371 for(i=(enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
372 result = setstropt(&dst->set.str[i], src->set.str[i]);
373 if(result)
374 return result;
375 }
376
377 /* duplicate memory areas pointed to */
378 i = STRING_COPYPOSTFIELDS;
379 if(src->set.postfieldsize && src->set.str[i]) {
380 /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
381 dst->set.str[i] = Curl_memdup(src->set.str[i],
382 curlx_sotouz(src->set.postfieldsize));
383 if(!dst->set.str[i])
384 return CURLE_OUT_OF_MEMORY;
385 /* point to the new copy */
386 dst->set.postfields = dst->set.str[i];
387 }
388
389 return CURLE_OK;
390 }
391
392 /*
393 * This is the internal function curl_easy_cleanup() calls. This should
394 * cleanup and free all resources associated with this sessionhandle.
395 *
396 * NOTE: if we ever add something that attempts to write to a socket or
397 * similar here, we must ignore SIGPIPE first. It is currently only done
398 * when curl_easy_perform() is invoked.
399 */
400
Curl_close(struct SessionHandle * data)401 CURLcode Curl_close(struct SessionHandle *data)
402 {
403 struct Curl_multi *m;
404
405 if(!data)
406 return CURLE_OK;
407
408 Curl_expire(data, 0); /* shut off timers */
409
410 m = data->multi;
411
412 if(m)
413 /* This handle is still part of a multi handle, take care of this first
414 and detach this handle from there. */
415 curl_multi_remove_handle(data->multi, data);
416
417 if(data->multi_easy)
418 /* when curl_easy_perform() is used, it creates its own multi handle to
419 use and this is the one */
420 curl_multi_cleanup(data->multi_easy);
421
422 /* Destroy the timeout list that is held in the easy handle. It is
423 /normally/ done by curl_multi_remove_handle() but this is "just in
424 case" */
425 if(data->state.timeoutlist) {
426 Curl_llist_destroy(data->state.timeoutlist, NULL);
427 data->state.timeoutlist = NULL;
428 }
429
430 data->magic = 0; /* force a clear AFTER the possibly enforced removal from
431 the multi handle, since that function uses the magic
432 field! */
433
434 if(data->state.rangestringalloc)
435 free(data->state.range);
436
437 /* Free the pathbuffer */
438 Curl_safefree(data->state.pathbuffer);
439 data->state.path = NULL;
440
441 /* freed here just in case DONE wasn't called */
442 Curl_free_request_state(data);
443
444 /* Close down all open SSL info and sessions */
445 Curl_ssl_close_all(data);
446 Curl_safefree(data->state.first_host);
447 Curl_safefree(data->state.scratch);
448 Curl_ssl_free_certinfo(data);
449
450 /* Cleanup possible redirect junk */
451 free(data->req.newurl);
452 data->req.newurl = NULL;
453
454 if(data->change.referer_alloc) {
455 Curl_safefree(data->change.referer);
456 data->change.referer_alloc = FALSE;
457 }
458 data->change.referer = NULL;
459
460 if(data->change.url_alloc) {
461 Curl_safefree(data->change.url);
462 data->change.url_alloc = FALSE;
463 }
464 data->change.url = NULL;
465
466 Curl_safefree(data->state.headerbuff);
467
468 Curl_flush_cookies(data, 1);
469
470 Curl_digest_cleanup(data);
471
472 Curl_safefree(data->info.contenttype);
473 Curl_safefree(data->info.wouldredirect);
474
475 /* this destroys the channel and we cannot use it anymore after this */
476 Curl_resolver_cleanup(data->state.resolver);
477
478 Curl_convert_close(data);
479
480 /* No longer a dirty share, if it exists */
481 if(data->share) {
482 Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
483 data->share->dirty--;
484 Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
485 }
486
487 if(data->set.wildcardmatch) {
488 /* destruct wildcard structures if it is needed */
489 struct WildcardData *wc = &data->wildcard;
490 Curl_wildcard_dtor(wc);
491 }
492
493 Curl_freeset(data);
494 free(data);
495 return CURLE_OK;
496 }
497
498 /*
499 * Initialize the UserDefined fields within a SessionHandle.
500 * This may be safely called on a new or existing SessionHandle.
501 */
Curl_init_userdefined(struct UserDefined * set)502 CURLcode Curl_init_userdefined(struct UserDefined *set)
503 {
504 CURLcode result = CURLE_OK;
505
506 set->out = stdout; /* default output to stdout */
507 set->in_set = stdin; /* default input from stdin */
508 set->err = stderr; /* default stderr to stderr */
509
510 /* use fwrite as default function to store output */
511 set->fwrite_func = (curl_write_callback)fwrite;
512
513 /* use fread as default function to read input */
514 set->fread_func_set = (curl_read_callback)fread;
515 set->is_fread_set = 0;
516 set->is_fwrite_set = 0;
517
518 set->seek_func = ZERO_NULL;
519 set->seek_client = ZERO_NULL;
520
521 /* conversion callbacks for non-ASCII hosts */
522 set->convfromnetwork = ZERO_NULL;
523 set->convtonetwork = ZERO_NULL;
524 set->convfromutf8 = ZERO_NULL;
525
526 set->filesize = -1; /* we don't know the size */
527 set->postfieldsize = -1; /* unknown size */
528 set->maxredirs = -1; /* allow any amount by default */
529
530 set->httpreq = HTTPREQ_GET; /* Default HTTP request */
531 set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */
532 set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
533 set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
534 set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */
535 set->ftp_filemethod = FTPFILE_MULTICWD;
536
537 set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
538
539 /* Set the default size of the SSL session ID cache */
540 set->ssl.max_ssl_sessions = 5;
541
542 set->proxyport = CURL_DEFAULT_PROXY_PORT; /* from url.h */
543 set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
544 set->httpauth = CURLAUTH_BASIC; /* defaults to basic */
545 set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
546
547 /* make libcurl quiet by default: */
548 set->hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
549
550 /*
551 * libcurl 7.10 introduced SSL verification *by default*! This needs to be
552 * switched off unless wanted.
553 */
554 set->ssl.verifypeer = TRUE;
555 set->ssl.verifyhost = TRUE;
556 #ifdef USE_TLS_SRP
557 set->ssl.authtype = CURL_TLSAUTH_NONE;
558 #endif
559 set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
560 type */
561 set->ssl.sessionid = TRUE; /* session ID caching enabled by default */
562
563 set->new_file_perms = 0644; /* Default permissions */
564 set->new_directory_perms = 0755; /* Default permissions */
565
566 /* for the *protocols fields we don't use the CURLPROTO_ALL convenience
567 define since we internally only use the lower 16 bits for the passed
568 in bitmask to not conflict with the private bits */
569 set->allowed_protocols = CURLPROTO_ALL;
570 set->redir_protocols = CURLPROTO_ALL & /* All except FILE, SCP and SMB */
571 ~(CURLPROTO_FILE | CURLPROTO_SCP | CURLPROTO_SMB |
572 CURLPROTO_SMBS);
573
574 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
575 /*
576 * disallow unprotected protection negotiation NEC reference implementation
577 * seem not to follow rfc1961 section 4.3/4.4
578 */
579 set->socks5_gssapi_nec = FALSE;
580 #endif
581
582 /* This is our preferred CA cert bundle/path since install time */
583 #if defined(CURL_CA_BUNDLE)
584 result = setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
585 if(result)
586 return result;
587 #endif
588 #if defined(CURL_CA_PATH)
589 result = setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
590 if(result)
591 return result;
592 #endif
593
594 set->wildcardmatch = FALSE;
595 set->chunk_bgn = ZERO_NULL;
596 set->chunk_end = ZERO_NULL;
597
598 /* tcp keepalives are disabled by default, but provide reasonable values for
599 * the interval and idle times.
600 */
601 set->tcp_keepalive = FALSE;
602 set->tcp_keepintvl = 60;
603 set->tcp_keepidle = 60;
604 set->tcp_fastopen = FALSE;
605
606 set->ssl_enable_npn = TRUE;
607 set->ssl_enable_alpn = TRUE;
608
609 set->expect_100_timeout = 1000L; /* Wait for a second by default. */
610 set->sep_headers = TRUE; /* separated header lists by default */
611
612 Curl_http2_init_userset(set);
613 return result;
614 }
615
616 /**
617 * Curl_open()
618 *
619 * @param curl is a pointer to a sessionhandle pointer that gets set by this
620 * function.
621 * @return CURLcode
622 */
623
Curl_open(struct SessionHandle ** curl)624 CURLcode Curl_open(struct SessionHandle **curl)
625 {
626 CURLcode result;
627 struct SessionHandle *data;
628
629 /* Very simple start-up: alloc the struct, init it with zeroes and return */
630 data = calloc(1, sizeof(struct SessionHandle));
631 if(!data) {
632 /* this is a very serious error */
633 DEBUGF(fprintf(stderr, "Error: calloc of SessionHandle failed\n"));
634 return CURLE_OUT_OF_MEMORY;
635 }
636
637 data->magic = CURLEASY_MAGIC_NUMBER;
638
639 result = Curl_resolver_init(&data->state.resolver);
640 if(result) {
641 DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
642 free(data);
643 return result;
644 }
645
646 /* We do some initial setup here, all those fields that can't be just 0 */
647
648 data->state.headerbuff = malloc(HEADERSIZE);
649 if(!data->state.headerbuff) {
650 DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
651 result = CURLE_OUT_OF_MEMORY;
652 }
653 else {
654 result = Curl_init_userdefined(&data->set);
655
656 data->state.headersize=HEADERSIZE;
657
658 Curl_convert_init(data);
659
660 /* most recent connection is not yet defined */
661 data->state.lastconnect = NULL;
662
663 data->progress.flags |= PGRS_HIDE;
664 data->state.current_speed = -1; /* init to negative == impossible */
665
666 data->wildcard.state = CURLWC_INIT;
667 data->wildcard.filelist = NULL;
668 data->set.fnmatch = ZERO_NULL;
669 data->set.maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
670
671 Curl_http2_init_state(&data->state);
672 }
673
674 if(result) {
675 Curl_resolver_cleanup(data->state.resolver);
676 free(data->state.headerbuff);
677 Curl_freeset(data);
678 free(data);
679 data = NULL;
680 }
681 else
682 *curl = data;
683
684 return result;
685 }
686
Curl_setopt(struct SessionHandle * data,CURLoption option,va_list param)687 CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
688 va_list param)
689 {
690 char *argptr;
691 CURLcode result = CURLE_OK;
692 long arg;
693 #ifndef CURL_DISABLE_HTTP
694 curl_off_t bigsize;
695 #endif
696
697 switch(option) {
698 case CURLOPT_DNS_CACHE_TIMEOUT:
699 data->set.dns_cache_timeout = va_arg(param, long);
700 break;
701 case CURLOPT_DNS_USE_GLOBAL_CACHE:
702 /* remember we want this enabled */
703 arg = va_arg(param, long);
704 data->set.global_dns_cache = (0 != arg) ? TRUE : FALSE;
705 break;
706 case CURLOPT_SSL_CIPHER_LIST:
707 /* set a list of cipher we want to use in the SSL connection */
708 result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST],
709 va_arg(param, char *));
710 break;
711
712 case CURLOPT_RANDOM_FILE:
713 /*
714 * This is the path name to a file that contains random data to seed
715 * the random SSL stuff with. The file is only used for reading.
716 */
717 result = setstropt(&data->set.str[STRING_SSL_RANDOM_FILE],
718 va_arg(param, char *));
719 break;
720 case CURLOPT_EGDSOCKET:
721 /*
722 * The Entropy Gathering Daemon socket pathname
723 */
724 result = setstropt(&data->set.str[STRING_SSL_EGDSOCKET],
725 va_arg(param, char *));
726 break;
727 case CURLOPT_MAXCONNECTS:
728 /*
729 * Set the absolute number of maximum simultaneous alive connection that
730 * libcurl is allowed to have.
731 */
732 data->set.maxconnects = va_arg(param, long);
733 break;
734 case CURLOPT_FORBID_REUSE:
735 /*
736 * When this transfer is done, it must not be left to be reused by a
737 * subsequent transfer but shall be closed immediately.
738 */
739 data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE;
740 break;
741 case CURLOPT_FRESH_CONNECT:
742 /*
743 * This transfer shall not use a previously cached connection but
744 * should be made with a fresh new connect!
745 */
746 data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE;
747 break;
748 case CURLOPT_VERBOSE:
749 /*
750 * Verbose means infof() calls that give a lot of information about
751 * the connection and transfer procedures as well as internal choices.
752 */
753 data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE;
754 break;
755 case CURLOPT_HEADER:
756 /*
757 * Set to include the header in the general data output stream.
758 */
759 data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE;
760 break;
761 case CURLOPT_NOPROGRESS:
762 /*
763 * Shut off the internal supported progress meter
764 */
765 data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE;
766 if(data->set.hide_progress)
767 data->progress.flags |= PGRS_HIDE;
768 else
769 data->progress.flags &= ~PGRS_HIDE;
770 break;
771 case CURLOPT_NOBODY:
772 /*
773 * Do not include the body part in the output data stream.
774 */
775 data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE;
776 break;
777 case CURLOPT_FAILONERROR:
778 /*
779 * Don't output the >=400 error code HTML-page, but instead only
780 * return error.
781 */
782 data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE;
783 break;
784 case CURLOPT_UPLOAD:
785 case CURLOPT_PUT:
786 /*
787 * We want to sent data to the remote host. If this is HTTP, that equals
788 * using the PUT request.
789 */
790 data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE;
791 if(data->set.upload) {
792 /* If this is HTTP, PUT is what's needed to "upload" */
793 data->set.httpreq = HTTPREQ_PUT;
794 data->set.opt_no_body = FALSE; /* this is implied */
795 }
796 else
797 /* In HTTP, the opposite of upload is GET (unless NOBODY is true as
798 then this can be changed to HEAD later on) */
799 data->set.httpreq = HTTPREQ_GET;
800 break;
801 case CURLOPT_FILETIME:
802 /*
803 * Try to get the file time of the remote document. The time will
804 * later (possibly) become available using curl_easy_getinfo().
805 */
806 data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE;
807 break;
808 case CURLOPT_FTP_CREATE_MISSING_DIRS:
809 /*
810 * An FTP option that modifies an upload to create missing directories on
811 * the server.
812 */
813 switch(va_arg(param, long)) {
814 case 0:
815 data->set.ftp_create_missing_dirs = 0;
816 break;
817 case 1:
818 data->set.ftp_create_missing_dirs = 1;
819 break;
820 case 2:
821 data->set.ftp_create_missing_dirs = 2;
822 break;
823 default:
824 /* reserve other values for future use */
825 result = CURLE_UNKNOWN_OPTION;
826 break;
827 }
828 break;
829 case CURLOPT_SERVER_RESPONSE_TIMEOUT:
830 /*
831 * Option that specifies how quickly an server response must be obtained
832 * before it is considered failure. For pingpong protocols.
833 */
834 data->set.server_response_timeout = va_arg(param, long) * 1000;
835 break;
836 case CURLOPT_TFTP_NO_OPTIONS:
837 /*
838 * Option that prevents libcurl from sending TFTP option requests to the
839 * server.
840 */
841 data->set.tftp_no_options = va_arg(param, long) != 0;
842 break;
843 case CURLOPT_TFTP_BLKSIZE:
844 /*
845 * TFTP option that specifies the block size to use for data transmission.
846 */
847 data->set.tftp_blksize = va_arg(param, long);
848 break;
849 case CURLOPT_DIRLISTONLY:
850 /*
851 * An option that changes the command to one that asks for a list
852 * only, no file info details.
853 */
854 data->set.ftp_list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
855 break;
856 case CURLOPT_APPEND:
857 /*
858 * We want to upload and append to an existing file.
859 */
860 data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
861 break;
862 case CURLOPT_FTP_FILEMETHOD:
863 /*
864 * How do access files over FTP.
865 */
866 data->set.ftp_filemethod = (curl_ftpfile)va_arg(param, long);
867 break;
868 case CURLOPT_NETRC:
869 /*
870 * Parse the $HOME/.netrc file
871 */
872 data->set.use_netrc = (enum CURL_NETRC_OPTION)va_arg(param, long);
873 break;
874 case CURLOPT_NETRC_FILE:
875 /*
876 * Use this file instead of the $HOME/.netrc file
877 */
878 result = setstropt(&data->set.str[STRING_NETRC_FILE],
879 va_arg(param, char *));
880 break;
881 case CURLOPT_TRANSFERTEXT:
882 /*
883 * This option was previously named 'FTPASCII'. Renamed to work with
884 * more protocols than merely FTP.
885 *
886 * Transfer using ASCII (instead of BINARY).
887 */
888 data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE;
889 break;
890 case CURLOPT_TIMECONDITION:
891 /*
892 * Set HTTP time condition. This must be one of the defines in the
893 * curl/curl.h header file.
894 */
895 data->set.timecondition = (curl_TimeCond)va_arg(param, long);
896 break;
897 case CURLOPT_TIMEVALUE:
898 /*
899 * This is the value to compare with the remote document with the
900 * method set with CURLOPT_TIMECONDITION
901 */
902 data->set.timevalue = (time_t)va_arg(param, long);
903 break;
904 case CURLOPT_SSLVERSION:
905 /*
906 * Set explicit SSL version to try to connect with, as some SSL
907 * implementations are lame.
908 */
909 #ifdef USE_SSL
910 data->set.ssl.version = va_arg(param, long);
911 #else
912 result = CURLE_UNKNOWN_OPTION;
913 #endif
914 break;
915
916 #ifndef CURL_DISABLE_HTTP
917 case CURLOPT_AUTOREFERER:
918 /*
919 * Switch on automatic referer that gets set if curl follows locations.
920 */
921 data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
922 break;
923
924 case CURLOPT_ACCEPT_ENCODING:
925 /*
926 * String to use at the value of Accept-Encoding header.
927 *
928 * If the encoding is set to "" we use an Accept-Encoding header that
929 * encompasses all the encodings we support.
930 * If the encoding is set to NULL we don't send an Accept-Encoding header
931 * and ignore an received Content-Encoding header.
932 *
933 */
934 argptr = va_arg(param, char *);
935 result = setstropt(&data->set.str[STRING_ENCODING],
936 (argptr && !*argptr)?
937 ALL_CONTENT_ENCODINGS: argptr);
938 break;
939
940 case CURLOPT_TRANSFER_ENCODING:
941 data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
942 TRUE : FALSE;
943 break;
944
945 case CURLOPT_FOLLOWLOCATION:
946 /*
947 * Follow Location: header hints on a HTTP-server.
948 */
949 data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
950 break;
951
952 case CURLOPT_UNRESTRICTED_AUTH:
953 /*
954 * Send authentication (user+password) when following locations, even when
955 * hostname changed.
956 */
957 data->set.http_disable_hostname_check_before_authentication =
958 (0 != va_arg(param, long)) ? TRUE : FALSE;
959 break;
960
961 case CURLOPT_MAXREDIRS:
962 /*
963 * The maximum amount of hops you allow curl to follow Location:
964 * headers. This should mostly be used to detect never-ending loops.
965 */
966 data->set.maxredirs = va_arg(param, long);
967 break;
968
969 case CURLOPT_POSTREDIR:
970 {
971 /*
972 * Set the behaviour of POST when redirecting
973 * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
974 * CURL_REDIR_POST_301 - POST is kept as POST after 301
975 * CURL_REDIR_POST_302 - POST is kept as POST after 302
976 * CURL_REDIR_POST_303 - POST is kept as POST after 303
977 * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
978 * other - POST is kept as POST after 301 and 302
979 */
980 int postRedir = curlx_sltosi(va_arg(param, long));
981 data->set.keep_post = postRedir & CURL_REDIR_POST_ALL;
982 }
983 break;
984
985 case CURLOPT_POST:
986 /* Does this option serve a purpose anymore? Yes it does, when
987 CURLOPT_POSTFIELDS isn't used and the POST data is read off the
988 callback! */
989 if(va_arg(param, long)) {
990 data->set.httpreq = HTTPREQ_POST;
991 data->set.opt_no_body = FALSE; /* this is implied */
992 }
993 else
994 data->set.httpreq = HTTPREQ_GET;
995 break;
996
997 case CURLOPT_COPYPOSTFIELDS:
998 /*
999 * A string with POST data. Makes curl HTTP POST. Even if it is NULL.
1000 * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to
1001 * CURLOPT_COPYPOSTFIELDS and not altered later.
1002 */
1003 argptr = va_arg(param, char *);
1004
1005 if(!argptr || data->set.postfieldsize == -1)
1006 result = setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr);
1007 else {
1008 /*
1009 * Check that requested length does not overflow the size_t type.
1010 */
1011
1012 if((data->set.postfieldsize < 0) ||
1013 ((sizeof(curl_off_t) != sizeof(size_t)) &&
1014 (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
1015 result = CURLE_OUT_OF_MEMORY;
1016 else {
1017 char * p;
1018
1019 (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
1020
1021 /* Allocate even when size == 0. This satisfies the need of possible
1022 later address compare to detect the COPYPOSTFIELDS mode, and
1023 to mark that postfields is used rather than read function or
1024 form data.
1025 */
1026 p = malloc((size_t)(data->set.postfieldsize?
1027 data->set.postfieldsize:1));
1028
1029 if(!p)
1030 result = CURLE_OUT_OF_MEMORY;
1031 else {
1032 if(data->set.postfieldsize)
1033 memcpy(p, argptr, (size_t)data->set.postfieldsize);
1034
1035 data->set.str[STRING_COPYPOSTFIELDS] = p;
1036 }
1037 }
1038 }
1039
1040 data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
1041 data->set.httpreq = HTTPREQ_POST;
1042 break;
1043
1044 case CURLOPT_POSTFIELDS:
1045 /*
1046 * Like above, but use static data instead of copying it.
1047 */
1048 data->set.postfields = va_arg(param, void *);
1049 /* Release old copied data. */
1050 (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
1051 data->set.httpreq = HTTPREQ_POST;
1052 break;
1053
1054 case CURLOPT_POSTFIELDSIZE:
1055 /*
1056 * The size of the POSTFIELD data to prevent libcurl to do strlen() to
1057 * figure it out. Enables binary posts.
1058 */
1059 bigsize = va_arg(param, long);
1060
1061 if(data->set.postfieldsize < bigsize &&
1062 data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
1063 /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
1064 (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
1065 data->set.postfields = NULL;
1066 }
1067
1068 data->set.postfieldsize = bigsize;
1069 break;
1070
1071 case CURLOPT_POSTFIELDSIZE_LARGE:
1072 /*
1073 * The size of the POSTFIELD data to prevent libcurl to do strlen() to
1074 * figure it out. Enables binary posts.
1075 */
1076 bigsize = va_arg(param, curl_off_t);
1077
1078 if(data->set.postfieldsize < bigsize &&
1079 data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
1080 /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
1081 (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
1082 data->set.postfields = NULL;
1083 }
1084
1085 data->set.postfieldsize = bigsize;
1086 break;
1087
1088 case CURLOPT_HTTPPOST:
1089 /*
1090 * Set to make us do HTTP POST
1091 */
1092 data->set.httppost = va_arg(param, struct curl_httppost *);
1093 data->set.httpreq = HTTPREQ_POST_FORM;
1094 data->set.opt_no_body = FALSE; /* this is implied */
1095 break;
1096
1097 case CURLOPT_REFERER:
1098 /*
1099 * String to set in the HTTP Referer: field.
1100 */
1101 if(data->change.referer_alloc) {
1102 Curl_safefree(data->change.referer);
1103 data->change.referer_alloc = FALSE;
1104 }
1105 result = setstropt(&data->set.str[STRING_SET_REFERER],
1106 va_arg(param, char *));
1107 data->change.referer = data->set.str[STRING_SET_REFERER];
1108 break;
1109
1110 case CURLOPT_USERAGENT:
1111 /*
1112 * String to use in the HTTP User-Agent field
1113 */
1114 result = setstropt(&data->set.str[STRING_USERAGENT],
1115 va_arg(param, char *));
1116 break;
1117
1118 case CURLOPT_HTTPHEADER:
1119 /*
1120 * Set a list with HTTP headers to use (or replace internals with)
1121 */
1122 data->set.headers = va_arg(param, struct curl_slist *);
1123 break;
1124
1125 case CURLOPT_PROXYHEADER:
1126 /*
1127 * Set a list with proxy headers to use (or replace internals with)
1128 *
1129 * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a
1130 * long time we remain doing it this way until CURLOPT_PROXYHEADER is
1131 * used. As soon as this option has been used, if set to anything but
1132 * NULL, custom headers for proxies are only picked from this list.
1133 *
1134 * Set this option to NULL to restore the previous behavior.
1135 */
1136 data->set.proxyheaders = va_arg(param, struct curl_slist *);
1137 break;
1138
1139 case CURLOPT_HEADEROPT:
1140 /*
1141 * Set header option.
1142 */
1143 arg = va_arg(param, long);
1144 data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE;
1145 break;
1146
1147 case CURLOPT_HTTP200ALIASES:
1148 /*
1149 * Set a list of aliases for HTTP 200 in response header
1150 */
1151 data->set.http200aliases = va_arg(param, struct curl_slist *);
1152 break;
1153
1154 #if !defined(CURL_DISABLE_COOKIES)
1155 case CURLOPT_COOKIE:
1156 /*
1157 * Cookie string to send to the remote server in the request.
1158 */
1159 result = setstropt(&data->set.str[STRING_COOKIE],
1160 va_arg(param, char *));
1161 break;
1162
1163 case CURLOPT_COOKIEFILE:
1164 /*
1165 * Set cookie file to read and parse. Can be used multiple times.
1166 */
1167 argptr = (char *)va_arg(param, void *);
1168 if(argptr) {
1169 struct curl_slist *cl;
1170 /* append the cookie file name to the list of file names, and deal with
1171 them later */
1172 cl = curl_slist_append(data->change.cookielist, argptr);
1173 if(!cl) {
1174 curl_slist_free_all(data->change.cookielist);
1175 data->change.cookielist = NULL;
1176 return CURLE_OUT_OF_MEMORY;
1177 }
1178 data->change.cookielist = cl; /* store the list for later use */
1179 }
1180 break;
1181
1182 case CURLOPT_COOKIEJAR:
1183 /*
1184 * Set cookie file name to dump all cookies to when we're done.
1185 */
1186 {
1187 struct CookieInfo *newcookies;
1188 result = setstropt(&data->set.str[STRING_COOKIEJAR],
1189 va_arg(param, char *));
1190
1191 /*
1192 * Activate the cookie parser. This may or may not already
1193 * have been made.
1194 */
1195 newcookies = Curl_cookie_init(data, NULL, data->cookies,
1196 data->set.cookiesession);
1197 if(!newcookies)
1198 result = CURLE_OUT_OF_MEMORY;
1199 data->cookies = newcookies;
1200 }
1201 break;
1202
1203 case CURLOPT_COOKIESESSION:
1204 /*
1205 * Set this option to TRUE to start a new "cookie session". It will
1206 * prevent the forthcoming read-cookies-from-file actions to accept
1207 * cookies that are marked as being session cookies, as they belong to a
1208 * previous session.
1209 *
1210 * In the original Netscape cookie spec, "session cookies" are cookies
1211 * with no expire date set. RFC2109 describes the same action if no
1212 * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
1213 * a 'Discard' action that can enforce the discard even for cookies that
1214 * have a Max-Age.
1215 *
1216 * We run mostly with the original cookie spec, as hardly anyone implements
1217 * anything else.
1218 */
1219 data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE;
1220 break;
1221
1222 case CURLOPT_COOKIELIST:
1223 argptr = va_arg(param, char *);
1224
1225 if(argptr == NULL)
1226 break;
1227
1228 if(Curl_raw_equal(argptr, "ALL")) {
1229 /* clear all cookies */
1230 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
1231 Curl_cookie_clearall(data->cookies);
1232 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
1233 }
1234 else if(Curl_raw_equal(argptr, "SESS")) {
1235 /* clear session cookies */
1236 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
1237 Curl_cookie_clearsess(data->cookies);
1238 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
1239 }
1240 else if(Curl_raw_equal(argptr, "FLUSH")) {
1241 /* flush cookies to file, takes care of the locking */
1242 Curl_flush_cookies(data, 0);
1243 }
1244 else if(Curl_raw_equal(argptr, "RELOAD")) {
1245 /* reload cookies from file */
1246 Curl_cookie_loadfiles(data);
1247 break;
1248 }
1249 else {
1250 if(!data->cookies)
1251 /* if cookie engine was not running, activate it */
1252 data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
1253
1254 argptr = strdup(argptr);
1255 if(!argptr || !data->cookies) {
1256 result = CURLE_OUT_OF_MEMORY;
1257 free(argptr);
1258 }
1259 else {
1260 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
1261
1262 if(checkprefix("Set-Cookie:", argptr))
1263 /* HTTP Header format line */
1264 Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
1265
1266 else
1267 /* Netscape format line */
1268 Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
1269
1270 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
1271 free(argptr);
1272 }
1273 }
1274
1275 break;
1276 #endif /* CURL_DISABLE_COOKIES */
1277
1278 case CURLOPT_HTTPGET:
1279 /*
1280 * Set to force us do HTTP GET
1281 */
1282 if(va_arg(param, long)) {
1283 data->set.httpreq = HTTPREQ_GET;
1284 data->set.upload = FALSE; /* switch off upload */
1285 data->set.opt_no_body = FALSE; /* this is implied */
1286 }
1287 break;
1288
1289 case CURLOPT_HTTP_VERSION:
1290 /*
1291 * This sets a requested HTTP version to be used. The value is one of
1292 * the listed enums in curl/curl.h.
1293 */
1294 arg = va_arg(param, long);
1295 #ifndef USE_NGHTTP2
1296 if(arg >= CURL_HTTP_VERSION_2)
1297 return CURLE_UNSUPPORTED_PROTOCOL;
1298 #endif
1299 data->set.httpversion = arg;
1300 break;
1301
1302 case CURLOPT_HTTPAUTH:
1303 /*
1304 * Set HTTP Authentication type BITMASK.
1305 */
1306 {
1307 int bitcheck;
1308 bool authbits;
1309 unsigned long auth = va_arg(param, unsigned long);
1310
1311 if(auth == CURLAUTH_NONE) {
1312 data->set.httpauth = auth;
1313 break;
1314 }
1315
1316 /* the DIGEST_IE bit is only used to set a special marker, for all the
1317 rest we need to handle it as normal DIGEST */
1318 data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
1319
1320 if(auth & CURLAUTH_DIGEST_IE) {
1321 auth |= CURLAUTH_DIGEST; /* set standard digest bit */
1322 auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
1323 }
1324
1325 /* switch off bits we can't support */
1326 #ifndef USE_NTLM
1327 auth &= ~CURLAUTH_NTLM; /* no NTLM support */
1328 auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
1329 #elif !defined(NTLM_WB_ENABLED)
1330 auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
1331 #endif
1332 #ifndef USE_SPNEGO
1333 auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
1334 GSS-API or SSPI */
1335 #endif
1336
1337 /* check if any auth bit lower than CURLAUTH_ONLY is still set */
1338 bitcheck = 0;
1339 authbits = FALSE;
1340 while(bitcheck < 31) {
1341 if(auth & (1UL << bitcheck++)) {
1342 authbits = TRUE;
1343 break;
1344 }
1345 }
1346 if(!authbits)
1347 return CURLE_NOT_BUILT_IN; /* no supported types left! */
1348
1349 data->set.httpauth = auth;
1350 }
1351 break;
1352
1353 case CURLOPT_EXPECT_100_TIMEOUT_MS:
1354 /*
1355 * Time to wait for a response to a HTTP request containing an
1356 * Expect: 100-continue header before sending the data anyway.
1357 */
1358 data->set.expect_100_timeout = va_arg(param, long);
1359 break;
1360
1361 #endif /* CURL_DISABLE_HTTP */
1362
1363 case CURLOPT_CUSTOMREQUEST:
1364 /*
1365 * Set a custom string to use as request
1366 */
1367 result = setstropt(&data->set.str[STRING_CUSTOMREQUEST],
1368 va_arg(param, char *));
1369
1370 /* we don't set
1371 data->set.httpreq = HTTPREQ_CUSTOM;
1372 here, we continue as if we were using the already set type
1373 and this just changes the actual request keyword */
1374 break;
1375
1376 #ifndef CURL_DISABLE_PROXY
1377 case CURLOPT_HTTPPROXYTUNNEL:
1378 /*
1379 * Tunnel operations through the proxy instead of normal proxy use
1380 */
1381 data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ?
1382 TRUE : FALSE;
1383 break;
1384
1385 case CURLOPT_PROXYPORT:
1386 /*
1387 * Explicitly set HTTP proxy port number.
1388 */
1389 data->set.proxyport = va_arg(param, long);
1390 break;
1391
1392 case CURLOPT_PROXYAUTH:
1393 /*
1394 * Set HTTP Authentication type BITMASK.
1395 */
1396 {
1397 int bitcheck;
1398 bool authbits;
1399 unsigned long auth = va_arg(param, unsigned long);
1400
1401 if(auth == CURLAUTH_NONE) {
1402 data->set.proxyauth = auth;
1403 break;
1404 }
1405
1406 /* the DIGEST_IE bit is only used to set a special marker, for all the
1407 rest we need to handle it as normal DIGEST */
1408 data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
1409
1410 if(auth & CURLAUTH_DIGEST_IE) {
1411 auth |= CURLAUTH_DIGEST; /* set standard digest bit */
1412 auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
1413 }
1414 /* switch off bits we can't support */
1415 #ifndef USE_NTLM
1416 auth &= ~CURLAUTH_NTLM; /* no NTLM support */
1417 auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
1418 #elif !defined(NTLM_WB_ENABLED)
1419 auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
1420 #endif
1421 #ifndef USE_SPNEGO
1422 auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
1423 GSS-API or SSPI */
1424 #endif
1425
1426 /* check if any auth bit lower than CURLAUTH_ONLY is still set */
1427 bitcheck = 0;
1428 authbits = FALSE;
1429 while(bitcheck < 31) {
1430 if(auth & (1UL << bitcheck++)) {
1431 authbits = TRUE;
1432 break;
1433 }
1434 }
1435 if(!authbits)
1436 return CURLE_NOT_BUILT_IN; /* no supported types left! */
1437
1438 data->set.proxyauth = auth;
1439 }
1440 break;
1441
1442 case CURLOPT_PROXY:
1443 /*
1444 * Set proxy server:port to use as HTTP proxy.
1445 *
1446 * If the proxy is set to "" we explicitly say that we don't want to use a
1447 * proxy (even though there might be environment variables saying so).
1448 *
1449 * Setting it to NULL, means no proxy but allows the environment variables
1450 * to decide for us.
1451 */
1452 result = setstropt(&data->set.str[STRING_PROXY],
1453 va_arg(param, char *));
1454 break;
1455
1456 case CURLOPT_PROXYTYPE:
1457 /*
1458 * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
1459 */
1460 data->set.proxytype = (curl_proxytype)va_arg(param, long);
1461 break;
1462
1463 case CURLOPT_PROXY_TRANSFER_MODE:
1464 /*
1465 * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
1466 */
1467 switch (va_arg(param, long)) {
1468 case 0:
1469 data->set.proxy_transfer_mode = FALSE;
1470 break;
1471 case 1:
1472 data->set.proxy_transfer_mode = TRUE;
1473 break;
1474 default:
1475 /* reserve other values for future use */
1476 result = CURLE_UNKNOWN_OPTION;
1477 break;
1478 }
1479 break;
1480 #endif /* CURL_DISABLE_PROXY */
1481
1482 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
1483 case CURLOPT_SOCKS5_GSSAPI_NEC:
1484 /*
1485 * Set flag for NEC SOCK5 support
1486 */
1487 data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
1488 break;
1489
1490 case CURLOPT_SOCKS5_GSSAPI_SERVICE:
1491 case CURLOPT_PROXY_SERVICE_NAME:
1492 /*
1493 * Set proxy authentication service name for Kerberos 5 and SPNEGO
1494 */
1495 result = setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME],
1496 va_arg(param, char *));
1497 break;
1498 #endif
1499
1500 #if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
1501 defined(USE_SPNEGO)
1502 case CURLOPT_SERVICE_NAME:
1503 /*
1504 * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO
1505 */
1506 result = setstropt(&data->set.str[STRING_SERVICE_NAME],
1507 va_arg(param, char *));
1508 break;
1509
1510 #endif
1511
1512 case CURLOPT_HEADERDATA:
1513 /*
1514 * Custom pointer to pass the header write callback function
1515 */
1516 data->set.writeheader = (void *)va_arg(param, void *);
1517 break;
1518 case CURLOPT_ERRORBUFFER:
1519 /*
1520 * Error buffer provided by the caller to get the human readable
1521 * error string in.
1522 */
1523 data->set.errorbuffer = va_arg(param, char *);
1524 break;
1525 case CURLOPT_WRITEDATA:
1526 /*
1527 * FILE pointer to write to. Or possibly
1528 * used as argument to the write callback.
1529 */
1530 data->set.out = va_arg(param, void *);
1531 break;
1532 case CURLOPT_FTPPORT:
1533 /*
1534 * Use FTP PORT, this also specifies which IP address to use
1535 */
1536 result = setstropt(&data->set.str[STRING_FTPPORT],
1537 va_arg(param, char *));
1538 data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE;
1539 break;
1540
1541 case CURLOPT_FTP_USE_EPRT:
1542 data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE;
1543 break;
1544
1545 case CURLOPT_FTP_USE_EPSV:
1546 data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE;
1547 break;
1548
1549 case CURLOPT_FTP_USE_PRET:
1550 data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE;
1551 break;
1552
1553 case CURLOPT_FTP_SSL_CCC:
1554 data->set.ftp_ccc = (curl_ftpccc)va_arg(param, long);
1555 break;
1556
1557 case CURLOPT_FTP_SKIP_PASV_IP:
1558 /*
1559 * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
1560 * bypass of the IP address in PASV responses.
1561 */
1562 data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE;
1563 break;
1564
1565 case CURLOPT_READDATA:
1566 /*
1567 * FILE pointer to read the file to be uploaded from. Or possibly
1568 * used as argument to the read callback.
1569 */
1570 data->set.in_set = va_arg(param, void *);
1571 break;
1572 case CURLOPT_INFILESIZE:
1573 /*
1574 * If known, this should inform curl about the file size of the
1575 * to-be-uploaded file.
1576 */
1577 data->set.filesize = va_arg(param, long);
1578 break;
1579 case CURLOPT_INFILESIZE_LARGE:
1580 /*
1581 * If known, this should inform curl about the file size of the
1582 * to-be-uploaded file.
1583 */
1584 data->set.filesize = va_arg(param, curl_off_t);
1585 break;
1586 case CURLOPT_LOW_SPEED_LIMIT:
1587 /*
1588 * The low speed limit that if transfers are below this for
1589 * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
1590 */
1591 data->set.low_speed_limit=va_arg(param, long);
1592 break;
1593 case CURLOPT_MAX_SEND_SPEED_LARGE:
1594 /*
1595 * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE
1596 * bytes per second the transfer is throttled..
1597 */
1598 data->set.max_send_speed=va_arg(param, curl_off_t);
1599 break;
1600 case CURLOPT_MAX_RECV_SPEED_LARGE:
1601 /*
1602 * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per
1603 * second the transfer is throttled..
1604 */
1605 data->set.max_recv_speed=va_arg(param, curl_off_t);
1606 break;
1607 case CURLOPT_LOW_SPEED_TIME:
1608 /*
1609 * The low speed time that if transfers are below the set
1610 * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
1611 */
1612 data->set.low_speed_time=va_arg(param, long);
1613 break;
1614 case CURLOPT_URL:
1615 /*
1616 * The URL to fetch.
1617 */
1618 if(data->change.url_alloc) {
1619 /* the already set URL is allocated, free it first! */
1620 Curl_safefree(data->change.url);
1621 data->change.url_alloc = FALSE;
1622 }
1623 result = setstropt(&data->set.str[STRING_SET_URL],
1624 va_arg(param, char *));
1625 data->change.url = data->set.str[STRING_SET_URL];
1626 break;
1627 case CURLOPT_PORT:
1628 /*
1629 * The port number to use when getting the URL
1630 */
1631 data->set.use_port = va_arg(param, long);
1632 break;
1633 case CURLOPT_TIMEOUT:
1634 /*
1635 * The maximum time you allow curl to use for a single transfer
1636 * operation.
1637 */
1638 data->set.timeout = va_arg(param, long) * 1000L;
1639 break;
1640
1641 case CURLOPT_TIMEOUT_MS:
1642 data->set.timeout = va_arg(param, long);
1643 break;
1644
1645 case CURLOPT_CONNECTTIMEOUT:
1646 /*
1647 * The maximum time you allow curl to use to connect.
1648 */
1649 data->set.connecttimeout = va_arg(param, long) * 1000L;
1650 break;
1651
1652 case CURLOPT_CONNECTTIMEOUT_MS:
1653 data->set.connecttimeout = va_arg(param, long);
1654 break;
1655
1656 case CURLOPT_ACCEPTTIMEOUT_MS:
1657 /*
1658 * The maximum time you allow curl to wait for server connect
1659 */
1660 data->set.accepttimeout = va_arg(param, long);
1661 break;
1662
1663 case CURLOPT_USERPWD:
1664 /*
1665 * user:password to use in the operation
1666 */
1667 result = setstropt_userpwd(va_arg(param, char *),
1668 &data->set.str[STRING_USERNAME],
1669 &data->set.str[STRING_PASSWORD]);
1670 break;
1671
1672 case CURLOPT_USERNAME:
1673 /*
1674 * authentication user name to use in the operation
1675 */
1676 result = setstropt(&data->set.str[STRING_USERNAME],
1677 va_arg(param, char *));
1678 break;
1679
1680 case CURLOPT_PASSWORD:
1681 /*
1682 * authentication password to use in the operation
1683 */
1684 result = setstropt(&data->set.str[STRING_PASSWORD],
1685 va_arg(param, char *));
1686 break;
1687
1688 case CURLOPT_LOGIN_OPTIONS:
1689 /*
1690 * authentication options to use in the operation
1691 */
1692 result = setstropt(&data->set.str[STRING_OPTIONS],
1693 va_arg(param, char *));
1694 break;
1695
1696 case CURLOPT_XOAUTH2_BEARER:
1697 /*
1698 * OAuth 2.0 bearer token to use in the operation
1699 */
1700 result = setstropt(&data->set.str[STRING_BEARER],
1701 va_arg(param, char *));
1702 break;
1703
1704 case CURLOPT_POSTQUOTE:
1705 /*
1706 * List of RAW FTP commands to use after a transfer
1707 */
1708 data->set.postquote = va_arg(param, struct curl_slist *);
1709 break;
1710 case CURLOPT_PREQUOTE:
1711 /*
1712 * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
1713 */
1714 data->set.prequote = va_arg(param, struct curl_slist *);
1715 break;
1716 case CURLOPT_QUOTE:
1717 /*
1718 * List of RAW FTP commands to use before a transfer
1719 */
1720 data->set.quote = va_arg(param, struct curl_slist *);
1721 break;
1722 case CURLOPT_RESOLVE:
1723 /*
1724 * List of NAME:[address] names to populate the DNS cache with
1725 * Prefix the NAME with dash (-) to _remove_ the name from the cache.
1726 *
1727 * Names added with this API will remain in the cache until explicitly
1728 * removed or the handle is cleaned up.
1729 *
1730 * This API can remove any name from the DNS cache, but only entries
1731 * that aren't actually in use right now will be pruned immediately.
1732 */
1733 data->set.resolve = va_arg(param, struct curl_slist *);
1734 data->change.resolve = data->set.resolve;
1735 break;
1736 case CURLOPT_PROGRESSFUNCTION:
1737 /*
1738 * Progress callback function
1739 */
1740 data->set.fprogress = va_arg(param, curl_progress_callback);
1741 if(data->set.fprogress)
1742 data->progress.callback = TRUE; /* no longer internal */
1743 else
1744 data->progress.callback = FALSE; /* NULL enforces internal */
1745 break;
1746
1747 case CURLOPT_XFERINFOFUNCTION:
1748 /*
1749 * Transfer info callback function
1750 */
1751 data->set.fxferinfo = va_arg(param, curl_xferinfo_callback);
1752 if(data->set.fxferinfo)
1753 data->progress.callback = TRUE; /* no longer internal */
1754 else
1755 data->progress.callback = FALSE; /* NULL enforces internal */
1756
1757 break;
1758
1759 case CURLOPT_PROGRESSDATA:
1760 /*
1761 * Custom client data to pass to the progress callback
1762 */
1763 data->set.progress_client = va_arg(param, void *);
1764 break;
1765
1766 #ifndef CURL_DISABLE_PROXY
1767 case CURLOPT_PROXYUSERPWD:
1768 /*
1769 * user:password needed to use the proxy
1770 */
1771 result = setstropt_userpwd(va_arg(param, char *),
1772 &data->set.str[STRING_PROXYUSERNAME],
1773 &data->set.str[STRING_PROXYPASSWORD]);
1774 break;
1775 case CURLOPT_PROXYUSERNAME:
1776 /*
1777 * authentication user name to use in the operation
1778 */
1779 result = setstropt(&data->set.str[STRING_PROXYUSERNAME],
1780 va_arg(param, char *));
1781 break;
1782 case CURLOPT_PROXYPASSWORD:
1783 /*
1784 * authentication password to use in the operation
1785 */
1786 result = setstropt(&data->set.str[STRING_PROXYPASSWORD],
1787 va_arg(param, char *));
1788 break;
1789 case CURLOPT_NOPROXY:
1790 /*
1791 * proxy exception list
1792 */
1793 result = setstropt(&data->set.str[STRING_NOPROXY],
1794 va_arg(param, char *));
1795 break;
1796 #endif
1797
1798 case CURLOPT_RANGE:
1799 /*
1800 * What range of the file you want to transfer
1801 */
1802 result = setstropt(&data->set.str[STRING_SET_RANGE],
1803 va_arg(param, char *));
1804 break;
1805 case CURLOPT_RESUME_FROM:
1806 /*
1807 * Resume transfer at the give file position
1808 */
1809 data->set.set_resume_from = va_arg(param, long);
1810 break;
1811 case CURLOPT_RESUME_FROM_LARGE:
1812 /*
1813 * Resume transfer at the give file position
1814 */
1815 data->set.set_resume_from = va_arg(param, curl_off_t);
1816 break;
1817 case CURLOPT_DEBUGFUNCTION:
1818 /*
1819 * stderr write callback.
1820 */
1821 data->set.fdebug = va_arg(param, curl_debug_callback);
1822 /*
1823 * if the callback provided is NULL, it'll use the default callback
1824 */
1825 break;
1826 case CURLOPT_DEBUGDATA:
1827 /*
1828 * Set to a void * that should receive all error writes. This
1829 * defaults to CURLOPT_STDERR for normal operations.
1830 */
1831 data->set.debugdata = va_arg(param, void *);
1832 break;
1833 case CURLOPT_STDERR:
1834 /*
1835 * Set to a FILE * that should receive all error writes. This
1836 * defaults to stderr for normal operations.
1837 */
1838 data->set.err = va_arg(param, FILE *);
1839 if(!data->set.err)
1840 data->set.err = stderr;
1841 break;
1842 case CURLOPT_HEADERFUNCTION:
1843 /*
1844 * Set header write callback
1845 */
1846 data->set.fwrite_header = va_arg(param, curl_write_callback);
1847 break;
1848 case CURLOPT_WRITEFUNCTION:
1849 /*
1850 * Set data write callback
1851 */
1852 data->set.fwrite_func = va_arg(param, curl_write_callback);
1853 if(!data->set.fwrite_func) {
1854 data->set.is_fwrite_set = 0;
1855 /* When set to NULL, reset to our internal default function */
1856 data->set.fwrite_func = (curl_write_callback)fwrite;
1857 }
1858 else
1859 data->set.is_fwrite_set = 1;
1860 break;
1861 case CURLOPT_READFUNCTION:
1862 /*
1863 * Read data callback
1864 */
1865 data->set.fread_func_set = va_arg(param, curl_read_callback);
1866 if(!data->set.fread_func_set) {
1867 data->set.is_fread_set = 0;
1868 /* When set to NULL, reset to our internal default function */
1869 data->set.fread_func_set = (curl_read_callback)fread;
1870 }
1871 else
1872 data->set.is_fread_set = 1;
1873 break;
1874 case CURLOPT_SEEKFUNCTION:
1875 /*
1876 * Seek callback. Might be NULL.
1877 */
1878 data->set.seek_func = va_arg(param, curl_seek_callback);
1879 break;
1880 case CURLOPT_SEEKDATA:
1881 /*
1882 * Seek control callback. Might be NULL.
1883 */
1884 data->set.seek_client = va_arg(param, void *);
1885 break;
1886 case CURLOPT_CONV_FROM_NETWORK_FUNCTION:
1887 /*
1888 * "Convert from network encoding" callback
1889 */
1890 data->set.convfromnetwork = va_arg(param, curl_conv_callback);
1891 break;
1892 case CURLOPT_CONV_TO_NETWORK_FUNCTION:
1893 /*
1894 * "Convert to network encoding" callback
1895 */
1896 data->set.convtonetwork = va_arg(param, curl_conv_callback);
1897 break;
1898 case CURLOPT_CONV_FROM_UTF8_FUNCTION:
1899 /*
1900 * "Convert from UTF-8 encoding" callback
1901 */
1902 data->set.convfromutf8 = va_arg(param, curl_conv_callback);
1903 break;
1904 case CURLOPT_IOCTLFUNCTION:
1905 /*
1906 * I/O control callback. Might be NULL.
1907 */
1908 data->set.ioctl_func = va_arg(param, curl_ioctl_callback);
1909 break;
1910 case CURLOPT_IOCTLDATA:
1911 /*
1912 * I/O control data pointer. Might be NULL.
1913 */
1914 data->set.ioctl_client = va_arg(param, void *);
1915 break;
1916 case CURLOPT_SSLCERT:
1917 /*
1918 * String that holds file name of the SSL certificate to use
1919 */
1920 result = setstropt(&data->set.str[STRING_CERT],
1921 va_arg(param, char *));
1922 break;
1923 case CURLOPT_SSLCERTTYPE:
1924 /*
1925 * String that holds file type of the SSL certificate to use
1926 */
1927 result = setstropt(&data->set.str[STRING_CERT_TYPE],
1928 va_arg(param, char *));
1929 break;
1930 case CURLOPT_SSLKEY:
1931 /*
1932 * String that holds file name of the SSL key to use
1933 */
1934 result = setstropt(&data->set.str[STRING_KEY],
1935 va_arg(param, char *));
1936 break;
1937 case CURLOPT_SSLKEYTYPE:
1938 /*
1939 * String that holds file type of the SSL key to use
1940 */
1941 result = setstropt(&data->set.str[STRING_KEY_TYPE],
1942 va_arg(param, char *));
1943 break;
1944 case CURLOPT_KEYPASSWD:
1945 /*
1946 * String that holds the SSL or SSH private key password.
1947 */
1948 result = setstropt(&data->set.str[STRING_KEY_PASSWD],
1949 va_arg(param, char *));
1950 break;
1951 case CURLOPT_SSLENGINE:
1952 /*
1953 * String that holds the SSL crypto engine.
1954 */
1955 argptr = va_arg(param, char *);
1956 if(argptr && argptr[0])
1957 result = Curl_ssl_set_engine(data, argptr);
1958 break;
1959
1960 case CURLOPT_SSLENGINE_DEFAULT:
1961 /*
1962 * flag to set engine as default.
1963 */
1964 result = Curl_ssl_set_engine_default(data);
1965 break;
1966 case CURLOPT_CRLF:
1967 /*
1968 * Kludgy option to enable CRLF conversions. Subject for removal.
1969 */
1970 data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
1971 break;
1972
1973 case CURLOPT_INTERFACE:
1974 /*
1975 * Set what interface or address/hostname to bind the socket to when
1976 * performing an operation and thus what from-IP your connection will use.
1977 */
1978 result = setstropt(&data->set.str[STRING_DEVICE],
1979 va_arg(param, char *));
1980 break;
1981 case CURLOPT_LOCALPORT:
1982 /*
1983 * Set what local port to bind the socket to when performing an operation.
1984 */
1985 data->set.localport = curlx_sltous(va_arg(param, long));
1986 break;
1987 case CURLOPT_LOCALPORTRANGE:
1988 /*
1989 * Set number of local ports to try, starting with CURLOPT_LOCALPORT.
1990 */
1991 data->set.localportrange = curlx_sltosi(va_arg(param, long));
1992 break;
1993 case CURLOPT_KRBLEVEL:
1994 /*
1995 * A string that defines the kerberos security level.
1996 */
1997 result = setstropt(&data->set.str[STRING_KRB_LEVEL],
1998 va_arg(param, char *));
1999 data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE;
2000 break;
2001 case CURLOPT_GSSAPI_DELEGATION:
2002 /*
2003 * GSS-API credential delegation
2004 */
2005 data->set.gssapi_delegation = va_arg(param, long);
2006 break;
2007 case CURLOPT_SSL_VERIFYPEER:
2008 /*
2009 * Enable peer SSL verifying.
2010 */
2011 data->set.ssl.verifypeer = (0 != va_arg(param, long)) ? TRUE : FALSE;
2012 break;
2013 case CURLOPT_SSL_VERIFYHOST:
2014 /*
2015 * Enable verification of the host name in the peer certificate
2016 */
2017 arg = va_arg(param, long);
2018
2019 /* Obviously people are not reading documentation and too many thought
2020 this argument took a boolean when it wasn't and misused it. We thus ban
2021 1 as a sensible input and we warn about its use. Then we only have the
2022 2 action internally stored as TRUE. */
2023
2024 if(1 == arg) {
2025 failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
2026 return CURLE_BAD_FUNCTION_ARGUMENT;
2027 }
2028
2029 data->set.ssl.verifyhost = (0 != arg) ? TRUE : FALSE;
2030 break;
2031 case CURLOPT_SSL_VERIFYSTATUS:
2032 /*
2033 * Enable certificate status verifying.
2034 */
2035 if(!Curl_ssl_cert_status_request()) {
2036 result = CURLE_NOT_BUILT_IN;
2037 break;
2038 }
2039
2040 data->set.ssl.verifystatus = (0 != va_arg(param, long)) ? TRUE : FALSE;
2041 break;
2042 case CURLOPT_SSL_CTX_FUNCTION:
2043 #ifdef have_curlssl_ssl_ctx
2044 /*
2045 * Set a SSL_CTX callback
2046 */
2047 data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
2048 #else
2049 result = CURLE_NOT_BUILT_IN;
2050 #endif
2051 break;
2052 case CURLOPT_SSL_CTX_DATA:
2053 #ifdef have_curlssl_ssl_ctx
2054 /*
2055 * Set a SSL_CTX callback parameter pointer
2056 */
2057 data->set.ssl.fsslctxp = va_arg(param, void *);
2058 #else
2059 result = CURLE_NOT_BUILT_IN;
2060 #endif
2061 break;
2062 case CURLOPT_SSL_FALSESTART:
2063 /*
2064 * Enable TLS false start.
2065 */
2066 if(!Curl_ssl_false_start()) {
2067 result = CURLE_NOT_BUILT_IN;
2068 break;
2069 }
2070
2071 data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE;
2072 break;
2073 case CURLOPT_CERTINFO:
2074 #ifdef have_curlssl_certinfo
2075 data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
2076 #else
2077 result = CURLE_NOT_BUILT_IN;
2078 #endif
2079 break;
2080 case CURLOPT_PINNEDPUBLICKEY:
2081 #ifdef have_curlssl_pinnedpubkey /* only by supported backends */
2082 /*
2083 * Set pinned public key for SSL connection.
2084 * Specify file name of the public key in DER format.
2085 */
2086 result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY],
2087 va_arg(param, char *));
2088 #else
2089 result = CURLE_NOT_BUILT_IN;
2090 #endif
2091 break;
2092 case CURLOPT_CAINFO:
2093 /*
2094 * Set CA info for SSL connection. Specify file name of the CA certificate
2095 */
2096 result = setstropt(&data->set.str[STRING_SSL_CAFILE],
2097 va_arg(param, char *));
2098 break;
2099 case CURLOPT_CAPATH:
2100 #ifdef have_curlssl_ca_path /* not supported by all backends */
2101 /*
2102 * Set CA path info for SSL connection. Specify directory name of the CA
2103 * certificates which have been prepared using openssl c_rehash utility.
2104 */
2105 /* This does not work on windows. */
2106 result = setstropt(&data->set.str[STRING_SSL_CAPATH],
2107 va_arg(param, char *));
2108 #else
2109 result = CURLE_NOT_BUILT_IN;
2110 #endif
2111 break;
2112 case CURLOPT_CRLFILE:
2113 /*
2114 * Set CRL file info for SSL connection. Specify file name of the CRL
2115 * to check certificates revocation
2116 */
2117 result = setstropt(&data->set.str[STRING_SSL_CRLFILE],
2118 va_arg(param, char *));
2119 break;
2120 case CURLOPT_ISSUERCERT:
2121 /*
2122 * Set Issuer certificate file
2123 * to check certificates issuer
2124 */
2125 result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT],
2126 va_arg(param, char *));
2127 break;
2128 case CURLOPT_TELNETOPTIONS:
2129 /*
2130 * Set a linked list of telnet options
2131 */
2132 data->set.telnet_options = va_arg(param, struct curl_slist *);
2133 break;
2134
2135 case CURLOPT_BUFFERSIZE:
2136 /*
2137 * The application kindly asks for a differently sized receive buffer.
2138 * If it seems reasonable, we'll use it.
2139 */
2140 data->set.buffer_size = va_arg(param, long);
2141
2142 if((data->set.buffer_size> (BUFSIZE -1)) ||
2143 (data->set.buffer_size < 1))
2144 data->set.buffer_size = 0; /* huge internal default */
2145
2146 break;
2147
2148 case CURLOPT_NOSIGNAL:
2149 /*
2150 * The application asks not to set any signal() or alarm() handlers,
2151 * even when using a timeout.
2152 */
2153 data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE;
2154 break;
2155
2156 case CURLOPT_SHARE:
2157 {
2158 struct Curl_share *set;
2159 set = va_arg(param, struct Curl_share *);
2160
2161 /* disconnect from old share, if any */
2162 if(data->share) {
2163 Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
2164
2165 if(data->dns.hostcachetype == HCACHE_SHARED) {
2166 data->dns.hostcache = NULL;
2167 data->dns.hostcachetype = HCACHE_NONE;
2168 }
2169
2170 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
2171 if(data->share->cookies == data->cookies)
2172 data->cookies = NULL;
2173 #endif
2174
2175 if(data->share->sslsession == data->state.session)
2176 data->state.session = NULL;
2177
2178 data->share->dirty--;
2179
2180 Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
2181 data->share = NULL;
2182 }
2183
2184 /* use new share if it set */
2185 data->share = set;
2186 if(data->share) {
2187
2188 Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
2189
2190 data->share->dirty++;
2191
2192 if(data->share->specifier & (1<< CURL_LOCK_DATA_DNS)) {
2193 /* use shared host cache */
2194 data->dns.hostcache = &data->share->hostcache;
2195 data->dns.hostcachetype = HCACHE_SHARED;
2196 }
2197 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
2198 if(data->share->cookies) {
2199 /* use shared cookie list, first free own one if any */
2200 Curl_cookie_cleanup(data->cookies);
2201 /* enable cookies since we now use a share that uses cookies! */
2202 data->cookies = data->share->cookies;
2203 }
2204 #endif /* CURL_DISABLE_HTTP */
2205 if(data->share->sslsession) {
2206 data->set.ssl.max_ssl_sessions = data->share->max_ssl_sessions;
2207 data->state.session = data->share->sslsession;
2208 }
2209 Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
2210
2211 }
2212 /* check for host cache not needed,
2213 * it will be done by curl_easy_perform */
2214 }
2215 break;
2216
2217 case CURLOPT_PRIVATE:
2218 /*
2219 * Set private data pointer.
2220 */
2221 data->set.private_data = va_arg(param, void *);
2222 break;
2223
2224 case CURLOPT_MAXFILESIZE:
2225 /*
2226 * Set the maximum size of a file to download.
2227 */
2228 data->set.max_filesize = va_arg(param, long);
2229 break;
2230
2231 #ifdef USE_SSL
2232 case CURLOPT_USE_SSL:
2233 /*
2234 * Make transfers attempt to use SSL/TLS.
2235 */
2236 data->set.use_ssl = (curl_usessl)va_arg(param, long);
2237 break;
2238
2239 case CURLOPT_SSL_OPTIONS:
2240 arg = va_arg(param, long);
2241 data->set.ssl_enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
2242 data->set.ssl_no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
2243 break;
2244
2245 #endif
2246 case CURLOPT_FTPSSLAUTH:
2247 /*
2248 * Set a specific auth for FTP-SSL transfers.
2249 */
2250 data->set.ftpsslauth = (curl_ftpauth)va_arg(param, long);
2251 break;
2252
2253 case CURLOPT_IPRESOLVE:
2254 data->set.ipver = va_arg(param, long);
2255 break;
2256
2257 case CURLOPT_MAXFILESIZE_LARGE:
2258 /*
2259 * Set the maximum size of a file to download.
2260 */
2261 data->set.max_filesize = va_arg(param, curl_off_t);
2262 break;
2263
2264 case CURLOPT_TCP_NODELAY:
2265 /*
2266 * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
2267 * algorithm
2268 */
2269 data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE;
2270 break;
2271
2272 case CURLOPT_FTP_ACCOUNT:
2273 result = setstropt(&data->set.str[STRING_FTP_ACCOUNT],
2274 va_arg(param, char *));
2275 break;
2276
2277 case CURLOPT_IGNORE_CONTENT_LENGTH:
2278 data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE;
2279 break;
2280
2281 case CURLOPT_CONNECT_ONLY:
2282 /*
2283 * No data transfer, set up connection and let application use the socket
2284 */
2285 data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
2286 break;
2287
2288 case CURLOPT_FTP_ALTERNATIVE_TO_USER:
2289 result = setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER],
2290 va_arg(param, char *));
2291 break;
2292
2293 case CURLOPT_SOCKOPTFUNCTION:
2294 /*
2295 * socket callback function: called after socket() but before connect()
2296 */
2297 data->set.fsockopt = va_arg(param, curl_sockopt_callback);
2298 break;
2299
2300 case CURLOPT_SOCKOPTDATA:
2301 /*
2302 * socket callback data pointer. Might be NULL.
2303 */
2304 data->set.sockopt_client = va_arg(param, void *);
2305 break;
2306
2307 case CURLOPT_OPENSOCKETFUNCTION:
2308 /*
2309 * open/create socket callback function: called instead of socket(),
2310 * before connect()
2311 */
2312 data->set.fopensocket = va_arg(param, curl_opensocket_callback);
2313 break;
2314
2315 case CURLOPT_OPENSOCKETDATA:
2316 /*
2317 * socket callback data pointer. Might be NULL.
2318 */
2319 data->set.opensocket_client = va_arg(param, void *);
2320 break;
2321
2322 case CURLOPT_CLOSESOCKETFUNCTION:
2323 /*
2324 * close socket callback function: called instead of close()
2325 * when shutting down a connection
2326 */
2327 data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
2328 break;
2329
2330 case CURLOPT_CLOSESOCKETDATA:
2331 /*
2332 * socket callback data pointer. Might be NULL.
2333 */
2334 data->set.closesocket_client = va_arg(param, void *);
2335 break;
2336
2337 case CURLOPT_SSL_SESSIONID_CACHE:
2338 data->set.ssl.sessionid = (0 != va_arg(param, long)) ? TRUE : FALSE;
2339 break;
2340
2341 #ifdef USE_LIBSSH2
2342 /* we only include SSH options if explicitly built to support SSH */
2343 case CURLOPT_SSH_AUTH_TYPES:
2344 data->set.ssh_auth_types = va_arg(param, long);
2345 break;
2346
2347 case CURLOPT_SSH_PUBLIC_KEYFILE:
2348 /*
2349 * Use this file instead of the $HOME/.ssh/id_dsa.pub file
2350 */
2351 result = setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY],
2352 va_arg(param, char *));
2353 break;
2354
2355 case CURLOPT_SSH_PRIVATE_KEYFILE:
2356 /*
2357 * Use this file instead of the $HOME/.ssh/id_dsa file
2358 */
2359 result = setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
2360 va_arg(param, char *));
2361 break;
2362 case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
2363 /*
2364 * Option to allow for the MD5 of the host public key to be checked
2365 * for validation purposes.
2366 */
2367 result = setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
2368 va_arg(param, char *));
2369 break;
2370 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
2371 case CURLOPT_SSH_KNOWNHOSTS:
2372 /*
2373 * Store the file name to read known hosts from.
2374 */
2375 result = setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
2376 va_arg(param, char *));
2377 break;
2378
2379 case CURLOPT_SSH_KEYFUNCTION:
2380 /* setting to NULL is fine since the ssh.c functions themselves will
2381 then rever to use the internal default */
2382 data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
2383 break;
2384
2385 case CURLOPT_SSH_KEYDATA:
2386 /*
2387 * Custom client data to pass to the SSH keyfunc callback
2388 */
2389 data->set.ssh_keyfunc_userp = va_arg(param, void *);
2390 break;
2391 #endif /* HAVE_LIBSSH2_KNOWNHOST_API */
2392
2393 #endif /* USE_LIBSSH2 */
2394
2395 case CURLOPT_HTTP_TRANSFER_DECODING:
2396 /*
2397 * disable libcurl transfer encoding is used
2398 */
2399 data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
2400 break;
2401
2402 case CURLOPT_HTTP_CONTENT_DECODING:
2403 /*
2404 * raw data passed to the application when content encoding is used
2405 */
2406 data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
2407 break;
2408
2409 case CURLOPT_NEW_FILE_PERMS:
2410 /*
2411 * Uses these permissions instead of 0644
2412 */
2413 data->set.new_file_perms = va_arg(param, long);
2414 break;
2415
2416 case CURLOPT_NEW_DIRECTORY_PERMS:
2417 /*
2418 * Uses these permissions instead of 0755
2419 */
2420 data->set.new_directory_perms = va_arg(param, long);
2421 break;
2422
2423 case CURLOPT_ADDRESS_SCOPE:
2424 /*
2425 * We always get longs when passed plain numericals, but for this value we
2426 * know that an unsigned int will always hold the value so we blindly
2427 * typecast to this type
2428 */
2429 data->set.scope_id = curlx_sltoui(va_arg(param, long));
2430 break;
2431
2432 case CURLOPT_PROTOCOLS:
2433 /* set the bitmask for the protocols that are allowed to be used for the
2434 transfer, which thus helps the app which takes URLs from users or other
2435 external inputs and want to restrict what protocol(s) to deal
2436 with. Defaults to CURLPROTO_ALL. */
2437 data->set.allowed_protocols = va_arg(param, long);
2438 break;
2439
2440 case CURLOPT_REDIR_PROTOCOLS:
2441 /* set the bitmask for the protocols that libcurl is allowed to follow to,
2442 as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
2443 to be set in both bitmasks to be allowed to get redirected to. Defaults
2444 to all protocols except FILE and SCP. */
2445 data->set.redir_protocols = va_arg(param, long);
2446 break;
2447
2448 case CURLOPT_DEFAULT_PROTOCOL:
2449 /* Set the protocol to use when the URL doesn't include any protocol */
2450 result = setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL],
2451 va_arg(param, char *));
2452 break;
2453
2454 case CURLOPT_MAIL_FROM:
2455 /* Set the SMTP mail originator */
2456 result = setstropt(&data->set.str[STRING_MAIL_FROM],
2457 va_arg(param, char *));
2458 break;
2459
2460 case CURLOPT_MAIL_AUTH:
2461 /* Set the SMTP auth originator */
2462 result = setstropt(&data->set.str[STRING_MAIL_AUTH],
2463 va_arg(param, char *));
2464 break;
2465
2466 case CURLOPT_MAIL_RCPT:
2467 /* Set the list of mail recipients */
2468 data->set.mail_rcpt = va_arg(param, struct curl_slist *);
2469 break;
2470
2471 case CURLOPT_SASL_IR:
2472 /* Enable/disable SASL initial response */
2473 data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
2474 break;
2475
2476 case CURLOPT_RTSP_REQUEST:
2477 {
2478 /*
2479 * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
2480 * Would this be better if the RTSPREQ_* were just moved into here?
2481 */
2482 long curl_rtspreq = va_arg(param, long);
2483 Curl_RtspReq rtspreq = RTSPREQ_NONE;
2484 switch(curl_rtspreq) {
2485 case CURL_RTSPREQ_OPTIONS:
2486 rtspreq = RTSPREQ_OPTIONS;
2487 break;
2488
2489 case CURL_RTSPREQ_DESCRIBE:
2490 rtspreq = RTSPREQ_DESCRIBE;
2491 break;
2492
2493 case CURL_RTSPREQ_ANNOUNCE:
2494 rtspreq = RTSPREQ_ANNOUNCE;
2495 break;
2496
2497 case CURL_RTSPREQ_SETUP:
2498 rtspreq = RTSPREQ_SETUP;
2499 break;
2500
2501 case CURL_RTSPREQ_PLAY:
2502 rtspreq = RTSPREQ_PLAY;
2503 break;
2504
2505 case CURL_RTSPREQ_PAUSE:
2506 rtspreq = RTSPREQ_PAUSE;
2507 break;
2508
2509 case CURL_RTSPREQ_TEARDOWN:
2510 rtspreq = RTSPREQ_TEARDOWN;
2511 break;
2512
2513 case CURL_RTSPREQ_GET_PARAMETER:
2514 rtspreq = RTSPREQ_GET_PARAMETER;
2515 break;
2516
2517 case CURL_RTSPREQ_SET_PARAMETER:
2518 rtspreq = RTSPREQ_SET_PARAMETER;
2519 break;
2520
2521 case CURL_RTSPREQ_RECORD:
2522 rtspreq = RTSPREQ_RECORD;
2523 break;
2524
2525 case CURL_RTSPREQ_RECEIVE:
2526 rtspreq = RTSPREQ_RECEIVE;
2527 break;
2528 default:
2529 rtspreq = RTSPREQ_NONE;
2530 }
2531
2532 data->set.rtspreq = rtspreq;
2533 break;
2534 }
2535
2536
2537 case CURLOPT_RTSP_SESSION_ID:
2538 /*
2539 * Set the RTSP Session ID manually. Useful if the application is
2540 * resuming a previously established RTSP session
2541 */
2542 result = setstropt(&data->set.str[STRING_RTSP_SESSION_ID],
2543 va_arg(param, char *));
2544 break;
2545
2546 case CURLOPT_RTSP_STREAM_URI:
2547 /*
2548 * Set the Stream URI for the RTSP request. Unless the request is
2549 * for generic server options, the application will need to set this.
2550 */
2551 result = setstropt(&data->set.str[STRING_RTSP_STREAM_URI],
2552 va_arg(param, char *));
2553 break;
2554
2555 case CURLOPT_RTSP_TRANSPORT:
2556 /*
2557 * The content of the Transport: header for the RTSP request
2558 */
2559 result = setstropt(&data->set.str[STRING_RTSP_TRANSPORT],
2560 va_arg(param, char *));
2561 break;
2562
2563 case CURLOPT_RTSP_CLIENT_CSEQ:
2564 /*
2565 * Set the CSEQ number to issue for the next RTSP request. Useful if the
2566 * application is resuming a previously broken connection. The CSEQ
2567 * will increment from this new number henceforth.
2568 */
2569 data->state.rtsp_next_client_CSeq = va_arg(param, long);
2570 break;
2571
2572 case CURLOPT_RTSP_SERVER_CSEQ:
2573 /* Same as the above, but for server-initiated requests */
2574 data->state.rtsp_next_client_CSeq = va_arg(param, long);
2575 break;
2576
2577 case CURLOPT_INTERLEAVEDATA:
2578 data->set.rtp_out = va_arg(param, void *);
2579 break;
2580 case CURLOPT_INTERLEAVEFUNCTION:
2581 /* Set the user defined RTP write function */
2582 data->set.fwrite_rtp = va_arg(param, curl_write_callback);
2583 break;
2584
2585 case CURLOPT_WILDCARDMATCH:
2586 data->set.wildcardmatch = (0 != va_arg(param, long)) ? TRUE : FALSE;
2587 break;
2588 case CURLOPT_CHUNK_BGN_FUNCTION:
2589 data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
2590 break;
2591 case CURLOPT_CHUNK_END_FUNCTION:
2592 data->set.chunk_end = va_arg(param, curl_chunk_end_callback);
2593 break;
2594 case CURLOPT_FNMATCH_FUNCTION:
2595 data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
2596 break;
2597 case CURLOPT_CHUNK_DATA:
2598 data->wildcard.customptr = va_arg(param, void *);
2599 break;
2600 case CURLOPT_FNMATCH_DATA:
2601 data->set.fnmatch_data = va_arg(param, void *);
2602 break;
2603 #ifdef USE_TLS_SRP
2604 case CURLOPT_TLSAUTH_USERNAME:
2605 result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
2606 va_arg(param, char *));
2607 if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
2608 data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
2609 break;
2610 case CURLOPT_TLSAUTH_PASSWORD:
2611 result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
2612 va_arg(param, char *));
2613 if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
2614 data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
2615 break;
2616 case CURLOPT_TLSAUTH_TYPE:
2617 if(strnequal((char *)va_arg(param, char *), "SRP", strlen("SRP")))
2618 data->set.ssl.authtype = CURL_TLSAUTH_SRP;
2619 else
2620 data->set.ssl.authtype = CURL_TLSAUTH_NONE;
2621 break;
2622 #endif
2623 case CURLOPT_DNS_SERVERS:
2624 result = Curl_set_dns_servers(data, va_arg(param, char *));
2625 break;
2626 case CURLOPT_DNS_INTERFACE:
2627 result = Curl_set_dns_interface(data, va_arg(param, char *));
2628 break;
2629 case CURLOPT_DNS_LOCAL_IP4:
2630 result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
2631 break;
2632 case CURLOPT_DNS_LOCAL_IP6:
2633 result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
2634 break;
2635
2636 case CURLOPT_TCP_KEEPALIVE:
2637 data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE;
2638 break;
2639 case CURLOPT_TCP_KEEPIDLE:
2640 data->set.tcp_keepidle = va_arg(param, long);
2641 break;
2642 case CURLOPT_TCP_KEEPINTVL:
2643 data->set.tcp_keepintvl = va_arg(param, long);
2644 break;
2645 case CURLOPT_TCP_FASTOPEN:
2646 #if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN)
2647 data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE;
2648 #else
2649 result = CURLE_NOT_BUILT_IN;
2650 #endif
2651 break;
2652 case CURLOPT_SSL_ENABLE_NPN:
2653 data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE;
2654 break;
2655 case CURLOPT_SSL_ENABLE_ALPN:
2656 data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
2657 break;
2658
2659 #ifdef USE_UNIX_SOCKETS
2660 case CURLOPT_UNIX_SOCKET_PATH:
2661 result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
2662 va_arg(param, char *));
2663 break;
2664 #endif
2665
2666 case CURLOPT_PATH_AS_IS:
2667 data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE;
2668 break;
2669 case CURLOPT_PIPEWAIT:
2670 data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE;
2671 break;
2672 case CURLOPT_STREAM_WEIGHT:
2673 #ifndef USE_NGHTTP2
2674 return CURLE_NOT_BUILT_IN;
2675 #else
2676 arg = va_arg(param, long);
2677 if((arg>=1) && (arg <= 256))
2678 data->set.stream_weight = (int)arg;
2679 break;
2680 #endif
2681 case CURLOPT_STREAM_DEPENDS:
2682 case CURLOPT_STREAM_DEPENDS_E:
2683 {
2684 #ifndef USE_NGHTTP2
2685 return CURLE_NOT_BUILT_IN;
2686 #else
2687 struct SessionHandle *dep = va_arg(param, struct SessionHandle *);
2688 if(dep && GOOD_EASY_HANDLE(dep)) {
2689 data->set.stream_depends_on = dep;
2690 data->set.stream_depends_e = (option == CURLOPT_STREAM_DEPENDS_E);
2691 }
2692 break;
2693 #endif
2694 }
2695 case CURLOPT_CONNECT_TO:
2696 data->set.connect_to = va_arg(param, struct curl_slist *);
2697 break;
2698 default:
2699 /* unknown tag and its companion, just ignore: */
2700 result = CURLE_UNKNOWN_OPTION;
2701 break;
2702 }
2703
2704 return result;
2705 }
2706
2707 #ifdef USE_RECV_BEFORE_SEND_WORKAROUND
conn_reset_postponed_data(struct connectdata * conn,int num)2708 static void conn_reset_postponed_data(struct connectdata *conn, int num)
2709 {
2710 struct postponed_data * const psnd = &(conn->postponed[num]);
2711 if(psnd->buffer) {
2712 DEBUGASSERT(psnd->allocated_size > 0);
2713 DEBUGASSERT(psnd->recv_size <= psnd->allocated_size);
2714 DEBUGASSERT(psnd->recv_size ?
2715 (psnd->recv_processed < psnd->recv_size) :
2716 (psnd->recv_processed == 0));
2717 DEBUGASSERT(psnd->bindsock != CURL_SOCKET_BAD);
2718 free(psnd->buffer);
2719 psnd->buffer = NULL;
2720 psnd->allocated_size = 0;
2721 psnd->recv_size = 0;
2722 psnd->recv_processed = 0;
2723 #ifdef DEBUGBUILD
2724 psnd->bindsock = CURL_SOCKET_BAD; /* used only for DEBUGASSERT */
2725 #endif /* DEBUGBUILD */
2726 }
2727 else {
2728 DEBUGASSERT (psnd->allocated_size == 0);
2729 DEBUGASSERT (psnd->recv_size == 0);
2730 DEBUGASSERT (psnd->recv_processed == 0);
2731 DEBUGASSERT (psnd->bindsock == CURL_SOCKET_BAD);
2732 }
2733 }
2734
conn_reset_all_postponed_data(struct connectdata * conn)2735 static void conn_reset_all_postponed_data(struct connectdata *conn)
2736 {
2737 conn_reset_postponed_data(conn, 0);
2738 conn_reset_postponed_data(conn, 1);
2739 }
2740 #else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
2741 /* Use "do-nothing" macros instead of functions when workaround not used */
2742 #define conn_reset_postponed_data(c,n) do {} WHILE_FALSE
2743 #define conn_reset_all_postponed_data(c) do {} WHILE_FALSE
2744 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
2745
conn_free(struct connectdata * conn)2746 static void conn_free(struct connectdata *conn)
2747 {
2748 if(!conn)
2749 return;
2750
2751 /* possible left-overs from the async name resolvers */
2752 Curl_resolver_cancel(conn);
2753
2754 /* close the SSL stuff before we close any sockets since they will/may
2755 write to the sockets */
2756 Curl_ssl_close(conn, FIRSTSOCKET);
2757 Curl_ssl_close(conn, SECONDARYSOCKET);
2758
2759 /* close possibly still open sockets */
2760 if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
2761 Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
2762 if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
2763 Curl_closesocket(conn, conn->sock[FIRSTSOCKET]);
2764 if(CURL_SOCKET_BAD != conn->tempsock[0])
2765 Curl_closesocket(conn, conn->tempsock[0]);
2766 if(CURL_SOCKET_BAD != conn->tempsock[1])
2767 Curl_closesocket(conn, conn->tempsock[1]);
2768
2769 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
2770 defined(NTLM_WB_ENABLED)
2771 Curl_ntlm_wb_cleanup(conn);
2772 #endif
2773
2774 Curl_safefree(conn->user);
2775 Curl_safefree(conn->passwd);
2776 Curl_safefree(conn->oauth_bearer);
2777 Curl_safefree(conn->options);
2778 Curl_safefree(conn->proxyuser);
2779 Curl_safefree(conn->proxypasswd);
2780 Curl_safefree(conn->allocptr.proxyuserpwd);
2781 Curl_safefree(conn->allocptr.uagent);
2782 Curl_safefree(conn->allocptr.userpwd);
2783 Curl_safefree(conn->allocptr.accept_encoding);
2784 Curl_safefree(conn->allocptr.te);
2785 Curl_safefree(conn->allocptr.rangeline);
2786 Curl_safefree(conn->allocptr.ref);
2787 Curl_safefree(conn->allocptr.host);
2788 Curl_safefree(conn->allocptr.cookiehost);
2789 Curl_safefree(conn->allocptr.rtsp_transport);
2790 Curl_safefree(conn->trailer);
2791 Curl_safefree(conn->host.rawalloc); /* host name buffer */
2792 Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
2793 Curl_safefree(conn->proxy.rawalloc); /* proxy name buffer */
2794 Curl_safefree(conn->master_buffer);
2795
2796 conn_reset_all_postponed_data(conn);
2797
2798 Curl_llist_destroy(conn->send_pipe, NULL);
2799 Curl_llist_destroy(conn->recv_pipe, NULL);
2800
2801 conn->send_pipe = NULL;
2802 conn->recv_pipe = NULL;
2803
2804 Curl_safefree(conn->localdev);
2805 Curl_free_ssl_config(&conn->ssl_config);
2806
2807 free(conn); /* free all the connection oriented data */
2808 }
2809
2810 /*
2811 * Disconnects the given connection. Note the connection may not be the
2812 * primary connection, like when freeing room in the connection cache or
2813 * killing of a dead old connection.
2814 *
2815 * This function MUST NOT reset state in the SessionHandle struct if that
2816 * isn't strictly bound to the life-time of *this* particular connection.
2817 *
2818 */
2819
Curl_disconnect(struct connectdata * conn,bool dead_connection)2820 CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
2821 {
2822 struct SessionHandle *data;
2823 if(!conn)
2824 return CURLE_OK; /* this is closed and fine already */
2825 data = conn->data;
2826
2827 if(!data) {
2828 DEBUGF(fprintf(stderr, "DISCONNECT without easy handle, ignoring\n"));
2829 return CURLE_OK;
2830 }
2831
2832 if(conn->dns_entry != NULL) {
2833 Curl_resolv_unlock(data, conn->dns_entry);
2834 conn->dns_entry = NULL;
2835 }
2836
2837 Curl_hostcache_prune(data); /* kill old DNS cache entries */
2838
2839 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM)
2840 /* Cleanup NTLM connection-related data */
2841 Curl_http_ntlm_cleanup(conn);
2842 #endif
2843
2844 if(conn->handler->disconnect)
2845 /* This is set if protocol-specific cleanups should be made */
2846 conn->handler->disconnect(conn, dead_connection);
2847
2848 /* unlink ourselves! */
2849 infof(data, "Closing connection %ld\n", conn->connection_id);
2850 Curl_conncache_remove_conn(data->state.conn_cache, conn);
2851
2852 free_fixed_hostname(&conn->host);
2853 free_fixed_hostname(&conn->conn_to_host);
2854 free_fixed_hostname(&conn->proxy);
2855
2856 Curl_ssl_close(conn, FIRSTSOCKET);
2857
2858 /* Indicate to all handles on the pipe that we're dead */
2859 if(Curl_pipeline_wanted(data->multi, CURLPIPE_ANY)) {
2860 signalPipeClose(conn->send_pipe, TRUE);
2861 signalPipeClose(conn->recv_pipe, TRUE);
2862 }
2863
2864 conn_free(conn);
2865
2866 return CURLE_OK;
2867 }
2868
2869 /*
2870 * This function should return TRUE if the socket is to be assumed to
2871 * be dead. Most commonly this happens when the server has closed the
2872 * connection due to inactivity.
2873 */
SocketIsDead(curl_socket_t sock)2874 static bool SocketIsDead(curl_socket_t sock)
2875 {
2876 int sval;
2877 bool ret_val = TRUE;
2878
2879 sval = Curl_socket_ready(sock, CURL_SOCKET_BAD, 0);
2880 if(sval == 0)
2881 /* timeout */
2882 ret_val = FALSE;
2883
2884 return ret_val;
2885 }
2886
2887 /*
2888 * IsPipeliningPossible() returns TRUE if the options set would allow
2889 * pipelining/multiplexing and the connection is using a HTTP protocol.
2890 */
IsPipeliningPossible(const struct SessionHandle * handle,const struct connectdata * conn)2891 static bool IsPipeliningPossible(const struct SessionHandle *handle,
2892 const struct connectdata *conn)
2893 {
2894 /* If a HTTP protocol and pipelining is enabled */
2895 if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
2896
2897 if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
2898 (handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
2899 (handle->set.httpreq == HTTPREQ_GET ||
2900 handle->set.httpreq == HTTPREQ_HEAD))
2901 /* didn't ask for HTTP/1.0 and a GET or HEAD */
2902 return TRUE;
2903
2904 if(Curl_pipeline_wanted(handle->multi, CURLPIPE_MULTIPLEX) &&
2905 (handle->set.httpversion >= CURL_HTTP_VERSION_2))
2906 /* allows HTTP/2 */
2907 return TRUE;
2908 }
2909 return FALSE;
2910 }
2911
Curl_removeHandleFromPipeline(struct SessionHandle * handle,struct curl_llist * pipeline)2912 int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
2913 struct curl_llist *pipeline)
2914 {
2915 if(pipeline) {
2916 struct curl_llist_element *curr;
2917
2918 curr = pipeline->head;
2919 while(curr) {
2920 if(curr->ptr == handle) {
2921 Curl_llist_remove(pipeline, curr, NULL);
2922 return 1; /* we removed a handle */
2923 }
2924 curr = curr->next;
2925 }
2926 }
2927
2928 return 0;
2929 }
2930
2931 #if 0 /* this code is saved here as it is useful for debugging purposes */
2932 static void Curl_printPipeline(struct curl_llist *pipeline)
2933 {
2934 struct curl_llist_element *curr;
2935
2936 curr = pipeline->head;
2937 while(curr) {
2938 struct SessionHandle *data = (struct SessionHandle *) curr->ptr;
2939 infof(data, "Handle in pipeline: %s\n", data->state.path);
2940 curr = curr->next;
2941 }
2942 }
2943 #endif
2944
gethandleathead(struct curl_llist * pipeline)2945 static struct SessionHandle* gethandleathead(struct curl_llist *pipeline)
2946 {
2947 struct curl_llist_element *curr = pipeline->head;
2948 if(curr) {
2949 return (struct SessionHandle *) curr->ptr;
2950 }
2951
2952 return NULL;
2953 }
2954
2955 /* remove the specified connection from all (possible) pipelines and related
2956 queues */
Curl_getoff_all_pipelines(struct SessionHandle * data,struct connectdata * conn)2957 void Curl_getoff_all_pipelines(struct SessionHandle *data,
2958 struct connectdata *conn)
2959 {
2960 bool recv_head = (conn->readchannel_inuse &&
2961 Curl_recvpipe_head(data, conn));
2962 bool send_head = (conn->writechannel_inuse &&
2963 Curl_sendpipe_head(data, conn));
2964
2965 if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && recv_head)
2966 Curl_pipeline_leave_read(conn);
2967 if(Curl_removeHandleFromPipeline(data, conn->send_pipe) && send_head)
2968 Curl_pipeline_leave_write(conn);
2969 }
2970
signalPipeClose(struct curl_llist * pipeline,bool pipe_broke)2971 static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke)
2972 {
2973 struct curl_llist_element *curr;
2974
2975 if(!pipeline)
2976 return;
2977
2978 curr = pipeline->head;
2979 while(curr) {
2980 struct curl_llist_element *next = curr->next;
2981 struct SessionHandle *data = (struct SessionHandle *) curr->ptr;
2982
2983 #ifdef DEBUGBUILD /* debug-only code */
2984 if(data->magic != CURLEASY_MAGIC_NUMBER) {
2985 /* MAJOR BADNESS */
2986 infof(data, "signalPipeClose() found BAAD easy handle\n");
2987 }
2988 #endif
2989
2990 if(pipe_broke)
2991 data->state.pipe_broke = TRUE;
2992 Curl_multi_handlePipeBreak(data);
2993 Curl_llist_remove(pipeline, curr, NULL);
2994 curr = next;
2995 }
2996 }
2997
2998 /*
2999 * This function finds the connection in the connection
3000 * cache that has been unused for the longest time.
3001 *
3002 * Returns the pointer to the oldest idle connection, or NULL if none was
3003 * found.
3004 */
3005 struct connectdata *
Curl_oldest_idle_connection(struct SessionHandle * data)3006 Curl_oldest_idle_connection(struct SessionHandle *data)
3007 {
3008 struct conncache *bc = data->state.conn_cache;
3009 struct curl_hash_iterator iter;
3010 struct curl_llist_element *curr;
3011 struct curl_hash_element *he;
3012 long highscore=-1;
3013 long score;
3014 struct timeval now;
3015 struct connectdata *conn_candidate = NULL;
3016 struct connectbundle *bundle;
3017
3018 now = Curl_tvnow();
3019
3020 Curl_hash_start_iterate(&bc->hash, &iter);
3021
3022 he = Curl_hash_next_element(&iter);
3023 while(he) {
3024 struct connectdata *conn;
3025
3026 bundle = he->ptr;
3027
3028 curr = bundle->conn_list->head;
3029 while(curr) {
3030 conn = curr->ptr;
3031
3032 if(!conn->inuse) {
3033 /* Set higher score for the age passed since the connection was used */
3034 score = Curl_tvdiff(now, conn->now);
3035
3036 if(score > highscore) {
3037 highscore = score;
3038 conn_candidate = conn;
3039 }
3040 }
3041 curr = curr->next;
3042 }
3043
3044 he = Curl_hash_next_element(&iter);
3045 }
3046
3047 return conn_candidate;
3048 }
3049
3050 /*
3051 * This function finds the connection in the connection
3052 * bundle that has been unused for the longest time.
3053 *
3054 * Returns the pointer to the oldest idle connection, or NULL if none was
3055 * found.
3056 */
3057 static struct connectdata *
find_oldest_idle_connection_in_bundle(struct SessionHandle * data,struct connectbundle * bundle)3058 find_oldest_idle_connection_in_bundle(struct SessionHandle *data,
3059 struct connectbundle *bundle)
3060 {
3061 struct curl_llist_element *curr;
3062 long highscore=-1;
3063 long score;
3064 struct timeval now;
3065 struct connectdata *conn_candidate = NULL;
3066 struct connectdata *conn;
3067
3068 (void)data;
3069
3070 now = Curl_tvnow();
3071
3072 curr = bundle->conn_list->head;
3073 while(curr) {
3074 conn = curr->ptr;
3075
3076 if(!conn->inuse) {
3077 /* Set higher score for the age passed since the connection was used */
3078 score = Curl_tvdiff(now, conn->now);
3079
3080 if(score > highscore) {
3081 highscore = score;
3082 conn_candidate = conn;
3083 }
3084 }
3085 curr = curr->next;
3086 }
3087
3088 return conn_candidate;
3089 }
3090
3091 /*
3092 * This function checks if given connection is dead and disconnects if so.
3093 * (That also removes it from the connection cache.)
3094 *
3095 * Returns TRUE if the connection actually was dead and disconnected.
3096 */
disconnect_if_dead(struct connectdata * conn,struct SessionHandle * data)3097 static bool disconnect_if_dead(struct connectdata *conn,
3098 struct SessionHandle *data)
3099 {
3100 size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
3101 if(!pipeLen && !conn->inuse) {
3102 /* The check for a dead socket makes sense only if there are no
3103 handles in pipeline and the connection isn't already marked in
3104 use */
3105 bool dead;
3106 if(conn->handler->protocol & CURLPROTO_RTSP)
3107 /* RTSP is a special case due to RTP interleaving */
3108 dead = Curl_rtsp_connisdead(conn);
3109 else
3110 dead = SocketIsDead(conn->sock[FIRSTSOCKET]);
3111
3112 if(dead) {
3113 conn->data = data;
3114 infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
3115
3116 /* disconnect resources */
3117 Curl_disconnect(conn, /* dead_connection */TRUE);
3118 return TRUE;
3119 }
3120 }
3121 return FALSE;
3122 }
3123
3124 /*
3125 * Wrapper to use disconnect_if_dead() function in Curl_conncache_foreach()
3126 *
3127 * Returns always 0.
3128 */
call_disconnect_if_dead(struct connectdata * conn,void * param)3129 static int call_disconnect_if_dead(struct connectdata *conn,
3130 void *param)
3131 {
3132 struct SessionHandle* data = (struct SessionHandle*)param;
3133 disconnect_if_dead(conn, data);
3134 return 0; /* continue iteration */
3135 }
3136
3137 /*
3138 * This function scans the connection cache for half-open/dead connections,
3139 * closes and removes them.
3140 * The cleanup is done at most once per second.
3141 */
prune_dead_connections(struct SessionHandle * data)3142 static void prune_dead_connections(struct SessionHandle *data)
3143 {
3144 struct timeval now = Curl_tvnow();
3145 long elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
3146
3147 if(elapsed >= 1000L) {
3148 Curl_conncache_foreach(data->state.conn_cache, data,
3149 call_disconnect_if_dead);
3150 data->state.conn_cache->last_cleanup = now;
3151 }
3152 }
3153
3154
max_pipeline_length(struct Curl_multi * multi)3155 static size_t max_pipeline_length(struct Curl_multi *multi)
3156 {
3157 return multi ? multi->max_pipeline_length : 0;
3158 }
3159
3160
3161 /*
3162 * Given one filled in connection struct (named needle), this function should
3163 * detect if there already is one that has all the significant details
3164 * exactly the same and thus should be used instead.
3165 *
3166 * If there is a match, this function returns TRUE - and has marked the
3167 * connection as 'in-use'. It must later be called with ConnectionDone() to
3168 * return back to 'idle' (unused) state.
3169 *
3170 * The force_reuse flag is set if the connection must be used, even if
3171 * the pipelining strategy wants to open a new connection instead of reusing.
3172 */
3173 static bool
ConnectionExists(struct SessionHandle * data,struct connectdata * needle,struct connectdata ** usethis,bool * force_reuse,bool * waitpipe)3174 ConnectionExists(struct SessionHandle *data,
3175 struct connectdata *needle,
3176 struct connectdata **usethis,
3177 bool *force_reuse,
3178 bool *waitpipe)
3179 {
3180 struct connectdata *check;
3181 struct connectdata *chosen = 0;
3182 bool foundPendingCandidate = FALSE;
3183 bool canPipeline = IsPipeliningPossible(data, needle);
3184 struct connectbundle *bundle;
3185
3186 #ifdef USE_NTLM
3187 bool wantNTLMhttp = ((data->state.authhost.want &
3188 (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
3189 (needle->handler->protocol & PROTO_FAMILY_HTTP));
3190 bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd &&
3191 ((data->state.authproxy.want &
3192 (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
3193 (needle->handler->protocol & PROTO_FAMILY_HTTP)));
3194 #endif
3195
3196 *force_reuse = FALSE;
3197 *waitpipe = FALSE;
3198
3199 /* We can't pipe if the site is blacklisted */
3200 if(canPipeline && Curl_pipeline_site_blacklisted(data, needle)) {
3201 canPipeline = FALSE;
3202 }
3203
3204 /* Look up the bundle with all the connections to this
3205 particular host */
3206 bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache);
3207 if(bundle) {
3208 /* Max pipe length is zero (unlimited) for multiplexed connections */
3209 size_t max_pipe_len = (bundle->multiuse != BUNDLE_MULTIPLEX)?
3210 max_pipeline_length(data->multi):0;
3211 size_t best_pipe_len = max_pipe_len;
3212 struct curl_llist_element *curr;
3213 const char *hostname;
3214
3215 if(needle->bits.conn_to_host)
3216 hostname = needle->conn_to_host.name;
3217 else
3218 hostname = needle->host.name;
3219
3220 infof(data, "Found bundle for host %s: %p [%s]\n",
3221 hostname, (void *)bundle,
3222 (bundle->multiuse== BUNDLE_PIPELINING?
3223 "can pipeline":
3224 (bundle->multiuse== BUNDLE_MULTIPLEX?
3225 "can multiplex":"serially")));
3226
3227 /* We can't pipe if we don't know anything about the server */
3228 if(canPipeline) {
3229 if(bundle->multiuse <= BUNDLE_UNKNOWN) {
3230 if((bundle->multiuse == BUNDLE_UNKNOWN) && data->set.pipewait) {
3231 infof(data, "Server doesn't support multi-use yet, wait\n");
3232 *waitpipe = TRUE;
3233 return FALSE; /* no re-use */
3234 }
3235
3236 infof(data, "Server doesn't support multi-use (yet)\n");
3237 canPipeline = FALSE;
3238 }
3239 if((bundle->multiuse == BUNDLE_PIPELINING) &&
3240 !Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1)) {
3241 /* not asked for, switch off */
3242 infof(data, "Could pipeline, but not asked to!\n");
3243 canPipeline = FALSE;
3244 }
3245 else if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
3246 !Curl_pipeline_wanted(data->multi, CURLPIPE_MULTIPLEX)) {
3247 infof(data, "Could multiplex, but not asked to!\n");
3248 canPipeline = FALSE;
3249 }
3250 }
3251
3252 curr = bundle->conn_list->head;
3253 while(curr) {
3254 bool match = FALSE;
3255 size_t pipeLen;
3256
3257 /*
3258 * Note that if we use a HTTP proxy in normal mode (no tunneling), we
3259 * check connections to that proxy and not to the actual remote server.
3260 */
3261 check = curr->ptr;
3262 curr = curr->next;
3263
3264 if(disconnect_if_dead(check, data))
3265 continue;
3266
3267 pipeLen = check->send_pipe->size + check->recv_pipe->size;
3268
3269 if(canPipeline) {
3270
3271 if(!check->bits.multiplex) {
3272 /* If not multiplexing, make sure the pipe has only GET requests */
3273 struct SessionHandle* sh = gethandleathead(check->send_pipe);
3274 struct SessionHandle* rh = gethandleathead(check->recv_pipe);
3275 if(sh) {
3276 if(!IsPipeliningPossible(sh, check))
3277 continue;
3278 }
3279 else if(rh) {
3280 if(!IsPipeliningPossible(rh, check))
3281 continue;
3282 }
3283 }
3284 }
3285 else {
3286 if(pipeLen > 0) {
3287 /* can only happen within multi handles, and means that another easy
3288 handle is using this connection */
3289 continue;
3290 }
3291
3292 if(Curl_resolver_asynch()) {
3293 /* ip_addr_str[0] is NUL only if the resolving of the name hasn't
3294 completed yet and until then we don't re-use this connection */
3295 if(!check->ip_addr_str[0]) {
3296 infof(data,
3297 "Connection #%ld is still name resolving, can't reuse\n",
3298 check->connection_id);
3299 continue;
3300 }
3301 }
3302
3303 if((check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) ||
3304 check->bits.close) {
3305 if(!check->bits.close)
3306 foundPendingCandidate = TRUE;
3307 /* Don't pick a connection that hasn't connected yet or that is going
3308 to get closed. */
3309 infof(data, "Connection #%ld isn't open enough, can't reuse\n",
3310 check->connection_id);
3311 #ifdef DEBUGBUILD
3312 if(check->recv_pipe->size > 0) {
3313 infof(data,
3314 "BAD! Unconnected #%ld has a non-empty recv pipeline!\n",
3315 check->connection_id);
3316 }
3317 #endif
3318 continue;
3319 }
3320 }
3321
3322 if((needle->handler->flags&PROTOPT_SSL) !=
3323 (check->handler->flags&PROTOPT_SSL))
3324 /* don't do mixed SSL and non-SSL connections */
3325 if(get_protocol_family(check->handler->protocol) !=
3326 needle->handler->protocol || !check->tls_upgraded)
3327 /* except protocols that have been upgraded via TLS */
3328 continue;
3329
3330 if(needle->handler->flags&PROTOPT_SSL) {
3331 if((data->set.ssl.verifypeer != check->verifypeer) ||
3332 (data->set.ssl.verifyhost != check->verifyhost))
3333 continue;
3334 }
3335
3336 if(needle->bits.proxy != check->bits.proxy)
3337 /* don't do mixed proxy and non-proxy connections */
3338 continue;
3339
3340 if(needle->bits.proxy &&
3341 (needle->proxytype != check->proxytype ||
3342 needle->bits.httpproxy != check->bits.httpproxy ||
3343 needle->bits.tunnel_proxy != check->bits.tunnel_proxy ||
3344 !Curl_raw_equal(needle->proxy.name, check->proxy.name) ||
3345 needle->port != check->port))
3346 /* don't mix connections that use different proxies */
3347 continue;
3348
3349 if(needle->bits.conn_to_host != check->bits.conn_to_host)
3350 /* don't mix connections that use the "connect to host" feature and
3351 * connections that don't use this feature */
3352 continue;
3353
3354 if(needle->bits.conn_to_port != check->bits.conn_to_port)
3355 /* don't mix connections that use the "connect to port" feature and
3356 * connections that don't use this feature */
3357 continue;
3358
3359 if(!canPipeline && check->inuse)
3360 /* this request can't be pipelined but the checked connection is
3361 already in use so we skip it */
3362 continue;
3363
3364 if(needle->localdev || needle->localport) {
3365 /* If we are bound to a specific local end (IP+port), we must not
3366 re-use a random other one, although if we didn't ask for a
3367 particular one we can reuse one that was bound.
3368
3369 This comparison is a bit rough and too strict. Since the input
3370 parameters can be specified in numerous ways and still end up the
3371 same it would take a lot of processing to make it really accurate.
3372 Instead, this matching will assume that re-uses of bound connections
3373 will most likely also re-use the exact same binding parameters and
3374 missing out a few edge cases shouldn't hurt anyone very much.
3375 */
3376 if((check->localport != needle->localport) ||
3377 (check->localportrange != needle->localportrange) ||
3378 !check->localdev ||
3379 !needle->localdev ||
3380 strcmp(check->localdev, needle->localdev))
3381 continue;
3382 }
3383
3384 if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
3385 /* This protocol requires credentials per connection,
3386 so verify that we're using the same name and password as well */
3387 if(!strequal(needle->user, check->user) ||
3388 !strequal(needle->passwd, check->passwd)) {
3389 /* one of them was different */
3390 continue;
3391 }
3392 }
3393
3394 if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) ||
3395 (needle->bits.httpproxy && needle->bits.tunnel_proxy)) {
3396 /* The requested connection does not use a HTTP proxy or it uses SSL or
3397 it is a non-SSL protocol tunneled over the same HTTP proxy name and
3398 port number */
3399 if((Curl_raw_equal(needle->handler->scheme, check->handler->scheme) ||
3400 (get_protocol_family(check->handler->protocol) ==
3401 needle->handler->protocol && check->tls_upgraded)) &&
3402 (!needle->bits.conn_to_host || Curl_raw_equal(
3403 needle->conn_to_host.name, check->conn_to_host.name)) &&
3404 (!needle->bits.conn_to_port ||
3405 needle->conn_to_port == check->conn_to_port) &&
3406 Curl_raw_equal(needle->host.name, check->host.name) &&
3407 needle->remote_port == check->remote_port) {
3408 /* The schemes match or the the protocol family is the same and the
3409 previous connection was TLS upgraded, and the hostname and host
3410 port match */
3411 if(needle->handler->flags & PROTOPT_SSL) {
3412 /* This is a SSL connection so verify that we're using the same
3413 SSL options as well */
3414 if(!Curl_ssl_config_matches(&needle->ssl_config,
3415 &check->ssl_config)) {
3416 DEBUGF(infof(data,
3417 "Connection #%ld has different SSL parameters, "
3418 "can't reuse\n",
3419 check->connection_id));
3420 continue;
3421 }
3422 else if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) {
3423 foundPendingCandidate = TRUE;
3424 DEBUGF(infof(data,
3425 "Connection #%ld has not started SSL connect, "
3426 "can't reuse\n",
3427 check->connection_id));
3428 continue;
3429 }
3430 }
3431 match = TRUE;
3432 }
3433 }
3434 else {
3435 /* The requested connection is using the same HTTP proxy in normal
3436 mode (no tunneling) */
3437 match = TRUE;
3438 }
3439
3440 if(match) {
3441 #if defined(USE_NTLM)
3442 /* If we are looking for an HTTP+NTLM connection, check if this is
3443 already authenticating with the right credentials. If not, keep
3444 looking so that we can reuse NTLM connections if
3445 possible. (Especially we must not reuse the same connection if
3446 partway through a handshake!) */
3447 if(wantNTLMhttp) {
3448 if(!strequal(needle->user, check->user) ||
3449 !strequal(needle->passwd, check->passwd))
3450 continue;
3451 }
3452 else if(check->ntlm.state != NTLMSTATE_NONE) {
3453 /* Connection is using NTLM auth but we don't want NTLM */
3454 continue;
3455 }
3456
3457 /* Same for Proxy NTLM authentication */
3458 if(wantProxyNTLMhttp) {
3459 /* Both check->proxyuser and check->proxypasswd can be NULL */
3460 if(!check->proxyuser || !check->proxypasswd)
3461 continue;
3462
3463 if(!strequal(needle->proxyuser, check->proxyuser) ||
3464 !strequal(needle->proxypasswd, check->proxypasswd))
3465 continue;
3466 }
3467 else if(check->proxyntlm.state != NTLMSTATE_NONE) {
3468 /* Proxy connection is using NTLM auth but we don't want NTLM */
3469 continue;
3470 }
3471
3472 if(wantNTLMhttp || wantProxyNTLMhttp) {
3473 /* Credentials are already checked, we can use this connection */
3474 chosen = check;
3475
3476 if((wantNTLMhttp &&
3477 (check->ntlm.state != NTLMSTATE_NONE)) ||
3478 (wantProxyNTLMhttp &&
3479 (check->proxyntlm.state != NTLMSTATE_NONE))) {
3480 /* We must use this connection, no other */
3481 *force_reuse = TRUE;
3482 break;
3483 }
3484
3485 /* Continue look up for a better connection */
3486 continue;
3487 }
3488 #endif
3489 if(canPipeline) {
3490 /* We can pipeline if we want to. Let's continue looking for
3491 the optimal connection to use, i.e the shortest pipe that is not
3492 blacklisted. */
3493
3494 if(pipeLen == 0) {
3495 /* We have the optimal connection. Let's stop looking. */
3496 chosen = check;
3497 break;
3498 }
3499
3500 /* We can't use the connection if the pipe is full */
3501 if(max_pipe_len && (pipeLen >= max_pipe_len)) {
3502 infof(data, "Pipe is full, skip (%zu)\n", pipeLen);
3503 continue;
3504 }
3505 #ifdef USE_NGHTTP2
3506 /* If multiplexed, make sure we don't go over concurrency limit */
3507 if(check->bits.multiplex) {
3508 /* Multiplexed connections can only be HTTP/2 for now */
3509 struct http_conn *httpc = &check->proto.httpc;
3510 if(pipeLen >= httpc->settings.max_concurrent_streams) {
3511 infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)\n",
3512 pipeLen);
3513 continue;
3514 }
3515 }
3516 #endif
3517 /* We can't use the connection if the pipe is penalized */
3518 if(Curl_pipeline_penalized(data, check)) {
3519 infof(data, "Penalized, skip\n");
3520 continue;
3521 }
3522
3523 if(max_pipe_len) {
3524 if(pipeLen < best_pipe_len) {
3525 /* This connection has a shorter pipe so far. We'll pick this
3526 and continue searching */
3527 chosen = check;
3528 best_pipe_len = pipeLen;
3529 continue;
3530 }
3531 }
3532 else {
3533 /* When not pipelining (== multiplexed), we have a match here! */
3534 chosen = check;
3535 infof(data, "Multiplexed connection found!\n");
3536 break;
3537 }
3538 }
3539 else {
3540 /* We have found a connection. Let's stop searching. */
3541 chosen = check;
3542 break;
3543 }
3544 }
3545 }
3546 }
3547
3548 if(chosen) {
3549 *usethis = chosen;
3550 return TRUE; /* yes, we found one to use! */
3551 }
3552
3553 if(foundPendingCandidate && data->set.pipewait) {
3554 infof(data,
3555 "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set\n");
3556 *waitpipe = TRUE;
3557 }
3558
3559 return FALSE; /* no matching connecting exists */
3560 }
3561
3562 /* after a TCP connection to the proxy has been verified, this function does
3563 the next magic step.
3564
3565 Note: this function's sub-functions call failf()
3566
3567 */
Curl_connected_proxy(struct connectdata * conn,int sockindex)3568 CURLcode Curl_connected_proxy(struct connectdata *conn,
3569 int sockindex)
3570 {
3571 if(!conn->bits.proxy || sockindex)
3572 /* this magic only works for the primary socket as the secondary is used
3573 for FTP only and it has FTP specific magic in ftp.c */
3574 return CURLE_OK;
3575
3576 switch(conn->proxytype) {
3577 #ifndef CURL_DISABLE_PROXY
3578 case CURLPROXY_SOCKS5:
3579 case CURLPROXY_SOCKS5_HOSTNAME:
3580 return Curl_SOCKS5(conn->proxyuser, conn->proxypasswd,
3581 conn->bits.conn_to_host ? conn->conn_to_host.name :
3582 conn->host.name,
3583 conn->bits.conn_to_port ? conn->conn_to_port :
3584 conn->remote_port,
3585 FIRSTSOCKET, conn);
3586
3587 case CURLPROXY_SOCKS4:
3588 return Curl_SOCKS4(conn->proxyuser,
3589 conn->bits.conn_to_host ? conn->conn_to_host.name :
3590 conn->host.name,
3591 conn->bits.conn_to_port ? conn->conn_to_port :
3592 conn->remote_port,
3593 FIRSTSOCKET, conn, FALSE);
3594
3595 case CURLPROXY_SOCKS4A:
3596 return Curl_SOCKS4(conn->proxyuser,
3597 conn->bits.conn_to_host ? conn->conn_to_host.name :
3598 conn->host.name,
3599 conn->bits.conn_to_port ? conn->conn_to_port :
3600 conn->remote_port,
3601 FIRSTSOCKET, conn, TRUE);
3602
3603 #endif /* CURL_DISABLE_PROXY */
3604 case CURLPROXY_HTTP:
3605 case CURLPROXY_HTTP_1_0:
3606 /* do nothing here. handled later. */
3607 break;
3608 default:
3609 break;
3610 } /* switch proxytype */
3611
3612 return CURLE_OK;
3613 }
3614
3615 /*
3616 * verboseconnect() displays verbose information after a connect
3617 */
3618 #ifndef CURL_DISABLE_VERBOSE_STRINGS
Curl_verboseconnect(struct connectdata * conn)3619 void Curl_verboseconnect(struct connectdata *conn)
3620 {
3621 if(conn->data->set.verbose)
3622 infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
3623 conn->bits.proxy ? conn->proxy.dispname : conn->host.dispname,
3624 conn->ip_addr_str, conn->port, conn->connection_id);
3625 }
3626 #endif
3627
Curl_protocol_getsock(struct connectdata * conn,curl_socket_t * socks,int numsocks)3628 int Curl_protocol_getsock(struct connectdata *conn,
3629 curl_socket_t *socks,
3630 int numsocks)
3631 {
3632 if(conn->handler->proto_getsock)
3633 return conn->handler->proto_getsock(conn, socks, numsocks);
3634 return GETSOCK_BLANK;
3635 }
3636
Curl_doing_getsock(struct connectdata * conn,curl_socket_t * socks,int numsocks)3637 int Curl_doing_getsock(struct connectdata *conn,
3638 curl_socket_t *socks,
3639 int numsocks)
3640 {
3641 if(conn && conn->handler->doing_getsock)
3642 return conn->handler->doing_getsock(conn, socks, numsocks);
3643 return GETSOCK_BLANK;
3644 }
3645
3646 /*
3647 * We are doing protocol-specific connecting and this is being called over and
3648 * over from the multi interface until the connection phase is done on
3649 * protocol layer.
3650 */
3651
Curl_protocol_connecting(struct connectdata * conn,bool * done)3652 CURLcode Curl_protocol_connecting(struct connectdata *conn,
3653 bool *done)
3654 {
3655 CURLcode result=CURLE_OK;
3656
3657 if(conn && conn->handler->connecting) {
3658 *done = FALSE;
3659 result = conn->handler->connecting(conn, done);
3660 }
3661 else
3662 *done = TRUE;
3663
3664 return result;
3665 }
3666
3667 /*
3668 * We are DOING this is being called over and over from the multi interface
3669 * until the DOING phase is done on protocol layer.
3670 */
3671
Curl_protocol_doing(struct connectdata * conn,bool * done)3672 CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done)
3673 {
3674 CURLcode result=CURLE_OK;
3675
3676 if(conn && conn->handler->doing) {
3677 *done = FALSE;
3678 result = conn->handler->doing(conn, done);
3679 }
3680 else
3681 *done = TRUE;
3682
3683 return result;
3684 }
3685
3686 /*
3687 * We have discovered that the TCP connection has been successful, we can now
3688 * proceed with some action.
3689 *
3690 */
Curl_protocol_connect(struct connectdata * conn,bool * protocol_done)3691 CURLcode Curl_protocol_connect(struct connectdata *conn,
3692 bool *protocol_done)
3693 {
3694 CURLcode result=CURLE_OK;
3695
3696 *protocol_done = FALSE;
3697
3698 if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) {
3699 /* We already are connected, get back. This may happen when the connect
3700 worked fine in the first call, like when we connect to a local server
3701 or proxy. Note that we don't know if the protocol is actually done.
3702
3703 Unless this protocol doesn't have any protocol-connect callback, as
3704 then we know we're done. */
3705 if(!conn->handler->connecting)
3706 *protocol_done = TRUE;
3707
3708 return CURLE_OK;
3709 }
3710
3711 if(!conn->bits.protoconnstart) {
3712
3713 result = Curl_proxy_connect(conn);
3714 if(result)
3715 return result;
3716
3717 if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
3718 (conn->tunnel_state[FIRSTSOCKET] != TUNNEL_COMPLETE))
3719 /* when using an HTTP tunnel proxy, await complete tunnel establishment
3720 before proceeding further. Return CURLE_OK so we'll be called again */
3721 return CURLE_OK;
3722
3723 if(conn->handler->connect_it) {
3724 /* is there a protocol-specific connect() procedure? */
3725
3726 /* Call the protocol-specific connect function */
3727 result = conn->handler->connect_it(conn, protocol_done);
3728 }
3729 else
3730 *protocol_done = TRUE;
3731
3732 /* it has started, possibly even completed but that knowledge isn't stored
3733 in this bit! */
3734 if(!result)
3735 conn->bits.protoconnstart = TRUE;
3736 }
3737
3738 return result; /* pass back status */
3739 }
3740
3741 /*
3742 * Helpers for IDNA convertions.
3743 */
is_ASCII_name(const char * hostname)3744 static bool is_ASCII_name(const char *hostname)
3745 {
3746 const unsigned char *ch = (const unsigned char*)hostname;
3747
3748 while(*ch) {
3749 if(*ch++ & 0x80)
3750 return FALSE;
3751 }
3752 return TRUE;
3753 }
3754
3755 #ifdef USE_LIBIDN
3756 /*
3757 * Check if characters in hostname is allowed in Top Level Domain.
3758 */
tld_check_name(struct SessionHandle * data,const char * ace_hostname)3759 static bool tld_check_name(struct SessionHandle *data,
3760 const char *ace_hostname)
3761 {
3762 size_t err_pos;
3763 char *uc_name = NULL;
3764 int rc;
3765 #ifndef CURL_DISABLE_VERBOSE_STRINGS
3766 const char *tld_errmsg = "<no msg>";
3767 #else
3768 (void)data;
3769 #endif
3770
3771 /* Convert (and downcase) ACE-name back into locale's character set */
3772 rc = idna_to_unicode_lzlz(ace_hostname, &uc_name, 0);
3773 if(rc != IDNA_SUCCESS)
3774 return FALSE;
3775
3776 /* Warning: err_pos receives "the decoded character offset rather than the
3777 byte position in the string." And as of libidn 1.32 that character offset
3778 is for UTF-8, even if the passed in string is another locale. */
3779 rc = tld_check_lz(uc_name, &err_pos, NULL);
3780 #ifndef CURL_DISABLE_VERBOSE_STRINGS
3781 #ifdef HAVE_TLD_STRERROR
3782 if(rc != TLD_SUCCESS)
3783 tld_errmsg = tld_strerror((Tld_rc)rc);
3784 #endif
3785 if(rc != TLD_SUCCESS)
3786 infof(data, "WARNING: TLD check for %s failed; %s\n",
3787 uc_name, tld_errmsg);
3788 #endif /* CURL_DISABLE_VERBOSE_STRINGS */
3789 if(uc_name)
3790 idn_free(uc_name);
3791 if(rc != TLD_SUCCESS)
3792 return FALSE;
3793
3794 return TRUE;
3795 }
3796 #endif
3797
3798 /*
3799 * Perform any necessary IDN conversion of hostname
3800 */
fix_hostname(struct SessionHandle * data,struct connectdata * conn,struct hostname * host)3801 static void fix_hostname(struct SessionHandle *data,
3802 struct connectdata *conn, struct hostname *host)
3803 {
3804 size_t len;
3805
3806 #ifndef USE_LIBIDN
3807 (void)data;
3808 (void)conn;
3809 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
3810 (void)conn;
3811 #endif
3812
3813 /* set the name we use to display the host name */
3814 host->dispname = host->name;
3815
3816 len = strlen(host->name);
3817 if(len && (host->name[len-1] == '.'))
3818 /* strip off a single trailing dot if present, primarily for SNI but
3819 there's no use for it */
3820 host->name[len-1]=0;
3821
3822 /* Check name for non-ASCII and convert hostname to ACE form if we can */
3823 if(!is_ASCII_name(host->name)) {
3824 #ifdef USE_LIBIDN
3825 if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) {
3826 char *ace_hostname = NULL;
3827
3828 int rc = idna_to_ascii_lz(host->name, &ace_hostname, 0);
3829 infof(data, "Input domain encoded as `%s'\n",
3830 stringprep_locale_charset());
3831 if(rc == IDNA_SUCCESS) {
3832 /* tld_check_name() displays a warning if the host name contains
3833 "illegal" characters for this TLD */
3834 (void)tld_check_name(data, ace_hostname);
3835
3836 host->encalloc = ace_hostname;
3837 /* change the name pointer to point to the encoded hostname */
3838 host->name = host->encalloc;
3839 }
3840 else
3841 infof(data, "Failed to convert %s to ACE; %s\n", host->name,
3842 Curl_idn_strerror(conn, rc));
3843 }
3844 #elif defined(USE_WIN32_IDN)
3845 char *ace_hostname = NULL;
3846
3847 if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
3848 host->encalloc = ace_hostname;
3849 /* change the name pointer to point to the encoded hostname */
3850 host->name = host->encalloc;
3851 }
3852 else
3853 infof(data, "Failed to convert %s to ACE;\n", host->name);
3854 #else
3855 infof(data, "IDN support not present, can't parse Unicode domains\n");
3856 #endif
3857 }
3858 }
3859
3860 /*
3861 * Frees data allocated by fix_hostname()
3862 */
free_fixed_hostname(struct hostname * host)3863 static void free_fixed_hostname(struct hostname *host)
3864 {
3865 #if defined(USE_LIBIDN)
3866 if(host->encalloc) {
3867 idn_free(host->encalloc); /* must be freed with idn_free() since this was
3868 allocated by libidn */
3869 host->encalloc = NULL;
3870 }
3871 #elif defined(USE_WIN32_IDN)
3872 free(host->encalloc); /* must be freed withidn_free() since this was
3873 allocated by curl_win32_idn_to_ascii */
3874 host->encalloc = NULL;
3875 #else
3876 (void)host;
3877 #endif
3878 }
3879
llist_dtor(void * user,void * element)3880 static void llist_dtor(void *user, void *element)
3881 {
3882 (void)user;
3883 (void)element;
3884 /* Do nothing */
3885 }
3886
3887 /*
3888 * Allocate and initialize a new connectdata object.
3889 */
allocate_conn(struct SessionHandle * data)3890 static struct connectdata *allocate_conn(struct SessionHandle *data)
3891 {
3892 struct connectdata *conn = calloc(1, sizeof(struct connectdata));
3893 if(!conn)
3894 return NULL;
3895
3896 conn->handler = &Curl_handler_dummy; /* Be sure we have a handler defined
3897 already from start to avoid NULL
3898 situations and checks */
3899
3900 /* and we setup a few fields in case we end up actually using this struct */
3901
3902 conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
3903 conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
3904 conn->tempsock[0] = CURL_SOCKET_BAD; /* no file descriptor */
3905 conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
3906 conn->connection_id = -1; /* no ID */
3907 conn->port = -1; /* unknown at this point */
3908 conn->remote_port = -1; /* unknown */
3909 #if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD)
3910 conn->postponed[0].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
3911 conn->postponed[1].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
3912 #endif /* USE_RECV_BEFORE_SEND_WORKAROUND && DEBUGBUILD */
3913
3914 /* Default protocol-independent behavior doesn't support persistent
3915 connections, so we set this to force-close. Protocols that support
3916 this need to set this to FALSE in their "curl_do" functions. */
3917 connclose(conn, "Default to force-close");
3918
3919 /* Store creation time to help future close decision making */
3920 conn->created = Curl_tvnow();
3921
3922 conn->data = data; /* Setup the association between this connection
3923 and the SessionHandle */
3924
3925 conn->proxytype = data->set.proxytype; /* type */
3926
3927 #ifdef CURL_DISABLE_PROXY
3928
3929 conn->bits.proxy = FALSE;
3930 conn->bits.httpproxy = FALSE;
3931 conn->bits.proxy_user_passwd = FALSE;
3932 conn->bits.tunnel_proxy = FALSE;
3933
3934 #else /* CURL_DISABLE_PROXY */
3935
3936 /* note that these two proxy bits are now just on what looks to be
3937 requested, they may be altered down the road */
3938 conn->bits.proxy = (data->set.str[STRING_PROXY] &&
3939 *data->set.str[STRING_PROXY]) ? TRUE : FALSE;
3940 conn->bits.httpproxy = (conn->bits.proxy &&
3941 (conn->proxytype == CURLPROXY_HTTP ||
3942 conn->proxytype == CURLPROXY_HTTP_1_0)) ?
3943 TRUE : FALSE;
3944 conn->bits.proxy_user_passwd = (data->set.str[STRING_PROXYUSERNAME]) ?
3945 TRUE : FALSE;
3946 conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
3947
3948 #endif /* CURL_DISABLE_PROXY */
3949
3950 conn->bits.user_passwd = (data->set.str[STRING_USERNAME]) ? TRUE : FALSE;
3951 conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
3952 conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
3953
3954 conn->verifypeer = data->set.ssl.verifypeer;
3955 conn->verifyhost = data->set.ssl.verifyhost;
3956
3957 conn->ip_version = data->set.ipver;
3958
3959 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
3960 defined(NTLM_WB_ENABLED)
3961 conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
3962 conn->ntlm_auth_hlpr_pid = 0;
3963 conn->challenge_header = NULL;
3964 conn->response_header = NULL;
3965 #endif
3966
3967 if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
3968 !conn->master_buffer) {
3969 /* Allocate master_buffer to be used for HTTP/1 pipelining */
3970 conn->master_buffer = calloc(BUFSIZE, sizeof (char));
3971 if(!conn->master_buffer)
3972 goto error;
3973 }
3974
3975 /* Initialize the pipeline lists */
3976 conn->send_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
3977 conn->recv_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
3978 if(!conn->send_pipe || !conn->recv_pipe)
3979 goto error;
3980
3981 #ifdef HAVE_GSSAPI
3982 conn->data_prot = PROT_CLEAR;
3983 #endif
3984
3985 /* Store the local bind parameters that will be used for this connection */
3986 if(data->set.str[STRING_DEVICE]) {
3987 conn->localdev = strdup(data->set.str[STRING_DEVICE]);
3988 if(!conn->localdev)
3989 goto error;
3990 }
3991 conn->localportrange = data->set.localportrange;
3992 conn->localport = data->set.localport;
3993
3994 /* the close socket stuff needs to be copied to the connection struct as
3995 it may live on without (this specific) SessionHandle */
3996 conn->fclosesocket = data->set.fclosesocket;
3997 conn->closesocket_client = data->set.closesocket_client;
3998
3999 return conn;
4000 error:
4001
4002 Curl_llist_destroy(conn->send_pipe, NULL);
4003 Curl_llist_destroy(conn->recv_pipe, NULL);
4004
4005 conn->send_pipe = NULL;
4006 conn->recv_pipe = NULL;
4007
4008 free(conn->master_buffer);
4009 free(conn->localdev);
4010 free(conn);
4011 return NULL;
4012 }
4013
findprotocol(struct SessionHandle * data,struct connectdata * conn,const char * protostr)4014 static CURLcode findprotocol(struct SessionHandle *data,
4015 struct connectdata *conn,
4016 const char *protostr)
4017 {
4018 const struct Curl_handler * const *pp;
4019 const struct Curl_handler *p;
4020
4021 /* Scan protocol handler table and match against 'protostr' to set a few
4022 variables based on the URL. Now that the handler may be changed later
4023 when the protocol specific setup function is called. */
4024 for(pp = protocols; (p = *pp) != NULL; pp++) {
4025 if(Curl_raw_equal(p->scheme, protostr)) {
4026 /* Protocol found in table. Check if allowed */
4027 if(!(data->set.allowed_protocols & p->protocol))
4028 /* nope, get out */
4029 break;
4030
4031 /* it is allowed for "normal" request, now do an extra check if this is
4032 the result of a redirect */
4033 if(data->state.this_is_a_follow &&
4034 !(data->set.redir_protocols & p->protocol))
4035 /* nope, get out */
4036 break;
4037
4038 /* Perform setup complement if some. */
4039 conn->handler = conn->given = p;
4040
4041 /* 'port' and 'remote_port' are set in setup_connection_internals() */
4042 return CURLE_OK;
4043 }
4044 }
4045
4046
4047 /* The protocol was not found in the table, but we don't have to assign it
4048 to anything since it is already assigned to a dummy-struct in the
4049 create_conn() function when the connectdata struct is allocated. */
4050 failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME,
4051 protostr);
4052
4053 return CURLE_UNSUPPORTED_PROTOCOL;
4054 }
4055
4056 /*
4057 * Parse URL and fill in the relevant members of the connection struct.
4058 */
parseurlandfillconn(struct SessionHandle * data,struct connectdata * conn,bool * prot_missing,char ** userp,char ** passwdp,char ** optionsp)4059 static CURLcode parseurlandfillconn(struct SessionHandle *data,
4060 struct connectdata *conn,
4061 bool *prot_missing,
4062 char **userp, char **passwdp,
4063 char **optionsp)
4064 {
4065 char *at;
4066 char *fragment;
4067 char *path = data->state.path;
4068 char *query;
4069 int rc;
4070 char protobuf[16] = "";
4071 const char *protop = "";
4072 CURLcode result;
4073 bool rebuild_url = FALSE;
4074
4075 *prot_missing = FALSE;
4076
4077 /* We might pass the entire URL into the request so we need to make sure
4078 * there are no bad characters in there.*/
4079 if(strpbrk(data->change.url, "\r\n")) {
4080 failf(data, "Illegal characters found in URL");
4081 return CURLE_URL_MALFORMAT;
4082 }
4083
4084 /*************************************************************
4085 * Parse the URL.
4086 *
4087 * We need to parse the url even when using the proxy, because we will need
4088 * the hostname and port in case we are trying to SSL connect through the
4089 * proxy -- and we don't know if we will need to use SSL until we parse the
4090 * url ...
4091 ************************************************************/
4092 if((2 == sscanf(data->change.url, "%15[^:]:%[^\n]",
4093 protobuf, path)) &&
4094 Curl_raw_equal(protobuf, "file")) {
4095 if(path[0] == '/' && path[1] == '/') {
4096 /* Allow omitted hostname (e.g. file:/<path>). This is not strictly
4097 * speaking a valid file: URL by RFC 1738, but treating file:/<path> as
4098 * file://localhost/<path> is similar to how other schemes treat missing
4099 * hostnames. See RFC 1808. */
4100
4101 /* This cannot be done with strcpy() in a portable manner, since the
4102 memory areas overlap! */
4103 memmove(path, path + 2, strlen(path + 2)+1);
4104 }
4105 /*
4106 * we deal with file://<host>/<path> differently since it supports no
4107 * hostname other than "localhost" and "127.0.0.1", which is unique among
4108 * the URL protocols specified in RFC 1738
4109 */
4110 if(path[0] != '/') {
4111 /* the URL included a host name, we ignore host names in file:// URLs
4112 as the standards don't define what to do with them */
4113 char *ptr=strchr(path, '/');
4114 if(ptr) {
4115 /* there was a slash present
4116
4117 RFC1738 (section 3.1, page 5) says:
4118
4119 The rest of the locator consists of data specific to the scheme,
4120 and is known as the "url-path". It supplies the details of how the
4121 specified resource can be accessed. Note that the "/" between the
4122 host (or port) and the url-path is NOT part of the url-path.
4123
4124 As most agents use file://localhost/foo to get '/foo' although the
4125 slash preceding foo is a separator and not a slash for the path,
4126 a URL as file://localhost//foo must be valid as well, to refer to
4127 the same file with an absolute path.
4128 */
4129
4130 if(ptr[1] && ('/' == ptr[1]))
4131 /* if there was two slashes, we skip the first one as that is then
4132 used truly as a separator */
4133 ptr++;
4134
4135 /* This cannot be made with strcpy, as the memory chunks overlap! */
4136 memmove(path, ptr, strlen(ptr)+1);
4137 }
4138 }
4139
4140 protop = "file"; /* protocol string */
4141 }
4142 else {
4143 /* clear path */
4144 path[0]=0;
4145
4146 if(2 > sscanf(data->change.url,
4147 "%15[^\n:]://%[^\n/?]%[^\n]",
4148 protobuf,
4149 conn->host.name, path)) {
4150
4151 /*
4152 * The URL was badly formatted, let's try the browser-style _without_
4153 * protocol specified like 'http://'.
4154 */
4155 rc = sscanf(data->change.url, "%[^\n/?]%[^\n]", conn->host.name, path);
4156 if(1 > rc) {
4157 /*
4158 * We couldn't even get this format.
4159 * djgpp 2.04 has a sscanf() bug where 'conn->host.name' is
4160 * assigned, but the return value is EOF!
4161 */
4162 #if defined(__DJGPP__) && (DJGPP_MINOR == 4)
4163 if(!(rc == -1 && *conn->host.name))
4164 #endif
4165 {
4166 failf(data, "<url> malformed");
4167 return CURLE_URL_MALFORMAT;
4168 }
4169 }
4170
4171 /*
4172 * Since there was no protocol part specified in the URL use the
4173 * user-specified default protocol. If we weren't given a default make a
4174 * guess by matching some protocols against the host's outermost
4175 * sub-domain name. Finally if there was no match use HTTP.
4176 */
4177
4178 protop = data->set.str[STRING_DEFAULT_PROTOCOL];
4179 if(!protop) {
4180 /* Note: if you add a new protocol, please update the list in
4181 * lib/version.c too! */
4182 if(checkprefix("FTP.", conn->host.name))
4183 protop = "ftp";
4184 else if(checkprefix("DICT.", conn->host.name))
4185 protop = "DICT";
4186 else if(checkprefix("LDAP.", conn->host.name))
4187 protop = "LDAP";
4188 else if(checkprefix("IMAP.", conn->host.name))
4189 protop = "IMAP";
4190 else if(checkprefix("SMTP.", conn->host.name))
4191 protop = "smtp";
4192 else if(checkprefix("POP3.", conn->host.name))
4193 protop = "pop3";
4194 else
4195 protop = "http";
4196 }
4197
4198 *prot_missing = TRUE; /* not given in URL */
4199 }
4200 else
4201 protop = protobuf;
4202 }
4203
4204 /* We search for '?' in the host name (but only on the right side of a
4205 * @-letter to allow ?-letters in username and password) to handle things
4206 * like http://example.com?param= (notice the missing '/').
4207 */
4208 at = strchr(conn->host.name, '@');
4209 if(at)
4210 query = strchr(at+1, '?');
4211 else
4212 query = strchr(conn->host.name, '?');
4213
4214 if(query) {
4215 /* We must insert a slash before the '?'-letter in the URL. If the URL had
4216 a slash after the '?', that is where the path currently begins and the
4217 '?string' is still part of the host name.
4218
4219 We must move the trailing part from the host name and put it first in
4220 the path. And have it all prefixed with a slash.
4221 */
4222
4223 size_t hostlen = strlen(query);
4224 size_t pathlen = strlen(path);
4225
4226 /* move the existing path plus the zero byte forward, to make room for
4227 the host-name part */
4228 memmove(path+hostlen+1, path, pathlen+1);
4229
4230 /* now copy the trailing host part in front of the existing path */
4231 memcpy(path+1, query, hostlen);
4232
4233 path[0]='/'; /* prepend the missing slash */
4234 rebuild_url = TRUE;
4235
4236 *query=0; /* now cut off the hostname at the ? */
4237 }
4238 else if(!path[0]) {
4239 /* if there's no path set, use a single slash */
4240 strcpy(path, "/");
4241 rebuild_url = TRUE;
4242 }
4243
4244 /* If the URL is malformatted (missing a '/' after hostname before path) we
4245 * insert a slash here. The only letter except '/' we accept to start a path
4246 * is '?'.
4247 */
4248 if(path[0] == '?') {
4249 /* We need this function to deal with overlapping memory areas. We know
4250 that the memory area 'path' points to is 'urllen' bytes big and that
4251 is bigger than the path. Use +1 to move the zero byte too. */
4252 memmove(&path[1], path, strlen(path)+1);
4253 path[0] = '/';
4254 rebuild_url = TRUE;
4255 }
4256 else if(!data->set.path_as_is) {
4257 /* sanitise paths and remove ../ and ./ sequences according to RFC3986 */
4258 char *newp = Curl_dedotdotify(path);
4259 if(!newp)
4260 return CURLE_OUT_OF_MEMORY;
4261
4262 if(strcmp(newp, path)) {
4263 rebuild_url = TRUE;
4264 free(data->state.pathbuffer);
4265 data->state.pathbuffer = newp;
4266 data->state.path = newp;
4267 path = newp;
4268 }
4269 else
4270 free(newp);
4271 }
4272
4273 /*
4274 * "rebuild_url" means that one or more URL components have been modified so
4275 * we need to generate an updated full version. We need the corrected URL
4276 * when communicating over HTTP proxy and we don't know at this point if
4277 * we're using a proxy or not.
4278 */
4279 if(rebuild_url) {
4280 char *reurl;
4281
4282 size_t plen = strlen(path); /* new path, should be 1 byte longer than
4283 the original */
4284 size_t urllen = strlen(data->change.url); /* original URL length */
4285
4286 size_t prefixlen = strlen(conn->host.name);
4287
4288 if(!*prot_missing)
4289 prefixlen += strlen(protop) + strlen("://");
4290
4291 reurl = malloc(urllen + 2); /* 2 for zerobyte + slash */
4292 if(!reurl)
4293 return CURLE_OUT_OF_MEMORY;
4294
4295 /* copy the prefix */
4296 memcpy(reurl, data->change.url, prefixlen);
4297
4298 /* append the trailing piece + zerobyte */
4299 memcpy(&reurl[prefixlen], path, plen + 1);
4300
4301 /* possible free the old one */
4302 if(data->change.url_alloc) {
4303 Curl_safefree(data->change.url);
4304 data->change.url_alloc = FALSE;
4305 }
4306
4307 infof(data, "Rebuilt URL to: %s\n", reurl);
4308
4309 data->change.url = reurl;
4310 data->change.url_alloc = TRUE; /* free this later */
4311 }
4312
4313 /*
4314 * Parse the login details from the URL and strip them out of
4315 * the host name
4316 */
4317 result = parse_url_login(data, conn, userp, passwdp, optionsp);
4318 if(result)
4319 return result;
4320
4321 if(conn->host.name[0] == '[') {
4322 /* This looks like an IPv6 address literal. See if there is an address
4323 scope if there is no location header */
4324 char *percent = strchr(conn->host.name, '%');
4325 if(percent) {
4326 unsigned int identifier_offset = 3;
4327 char *endp;
4328 unsigned long scope;
4329 if(strncmp("%25", percent, 3) != 0) {
4330 infof(data,
4331 "Please URL encode %% as %%25, see RFC 6874.\n");
4332 identifier_offset = 1;
4333 }
4334 scope = strtoul(percent + identifier_offset, &endp, 10);
4335 if(*endp == ']') {
4336 /* The address scope was well formed. Knock it out of the
4337 hostname. */
4338 memmove(percent, endp, strlen(endp)+1);
4339 conn->scope_id = (unsigned int)scope;
4340 }
4341 else {
4342 /* Zone identifier is not numeric */
4343 #if defined(HAVE_NET_IF_H) && defined(IFNAMSIZ) && defined(HAVE_IF_NAMETOINDEX)
4344 char ifname[IFNAMSIZ + 2];
4345 char *square_bracket;
4346 unsigned int scopeidx = 0;
4347 strncpy(ifname, percent + identifier_offset, IFNAMSIZ + 2);
4348 /* Ensure nullbyte termination */
4349 ifname[IFNAMSIZ + 1] = '\0';
4350 square_bracket = strchr(ifname, ']');
4351 if(square_bracket) {
4352 /* Remove ']' */
4353 *square_bracket = '\0';
4354 scopeidx = if_nametoindex(ifname);
4355 if(scopeidx == 0) {
4356 infof(data, "Invalid network interface: %s; %s\n", ifname,
4357 strerror(errno));
4358 }
4359 }
4360 if(scopeidx > 0) {
4361 char *p = percent + identifier_offset + strlen(ifname);
4362
4363 /* Remove zone identifier from hostname */
4364 memmove(percent, p, strlen(p) + 1);
4365 conn->scope_id = scopeidx;
4366 }
4367 else
4368 #endif /* HAVE_NET_IF_H && IFNAMSIZ */
4369 infof(data, "Invalid IPv6 address format\n");
4370 }
4371 }
4372 }
4373
4374 if(data->set.scope_id)
4375 /* Override any scope that was set above. */
4376 conn->scope_id = data->set.scope_id;
4377
4378 /* Remove the fragment part of the path. Per RFC 2396, this is always the
4379 last part of the URI. We are looking for the first '#' so that we deal
4380 gracefully with non conformant URI such as http://example.com#foo#bar. */
4381 fragment = strchr(path, '#');
4382 if(fragment) {
4383 *fragment = 0;
4384
4385 /* we know the path part ended with a fragment, so we know the full URL
4386 string does too and we need to cut it off from there so it isn't used
4387 over proxy */
4388 fragment = strchr(data->change.url, '#');
4389 if(fragment)
4390 *fragment = 0;
4391 }
4392
4393 /*
4394 * So if the URL was A://B/C#D,
4395 * protop is A
4396 * conn->host.name is B
4397 * data->state.path is /C
4398 */
4399
4400 return findprotocol(data, conn, protop);
4401 }
4402
4403 /*
4404 * If we're doing a resumed transfer, we need to setup our stuff
4405 * properly.
4406 */
setup_range(struct SessionHandle * data)4407 static CURLcode setup_range(struct SessionHandle *data)
4408 {
4409 struct UrlState *s = &data->state;
4410 s->resume_from = data->set.set_resume_from;
4411 if(s->resume_from || data->set.str[STRING_SET_RANGE]) {
4412 if(s->rangestringalloc)
4413 free(s->range);
4414
4415 if(s->resume_from)
4416 s->range = aprintf("%" CURL_FORMAT_CURL_OFF_TU "-", s->resume_from);
4417 else
4418 s->range = strdup(data->set.str[STRING_SET_RANGE]);
4419
4420 s->rangestringalloc = (s->range) ? TRUE : FALSE;
4421
4422 if(!s->range)
4423 return CURLE_OUT_OF_MEMORY;
4424
4425 /* tell ourselves to fetch this range */
4426 s->use_range = TRUE; /* enable range download */
4427 }
4428 else
4429 s->use_range = FALSE; /* disable range download */
4430
4431 return CURLE_OK;
4432 }
4433
4434
4435 /*
4436 * setup_connection_internals() -
4437 *
4438 * Setup connection internals specific to the requested protocol in the
4439 * SessionHandle. This is inited and setup before the connection is made but
4440 * is about the particular protocol that is to be used.
4441 *
4442 * This MUST get called after proxy magic has been figured out.
4443 */
setup_connection_internals(struct connectdata * conn)4444 static CURLcode setup_connection_internals(struct connectdata *conn)
4445 {
4446 const struct Curl_handler * p;
4447 CURLcode result;
4448 struct SessionHandle *data = conn->data;
4449
4450 /* in some case in the multi state-machine, we go back to the CONNECT state
4451 and then a second (or third or...) call to this function will be made
4452 without doing a DISCONNECT or DONE in between (since the connection is
4453 yet in place) and therefore this function needs to first make sure
4454 there's no lingering previous data allocated. */
4455 Curl_free_request_state(data);
4456
4457 memset(&data->req, 0, sizeof(struct SingleRequest));
4458 data->req.maxdownload = -1;
4459
4460 conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
4461
4462 /* Perform setup complement if some. */
4463 p = conn->handler;
4464
4465 if(p->setup_connection) {
4466 result = (*p->setup_connection)(conn);
4467
4468 if(result)
4469 return result;
4470
4471 p = conn->handler; /* May have changed. */
4472 }
4473
4474 if(conn->port < 0)
4475 /* we check for -1 here since if proxy was detected already, this
4476 was very likely already set to the proxy port */
4477 conn->port = p->defport;
4478
4479 return CURLE_OK;
4480 }
4481
4482 /*
4483 * Curl_free_request_state() should free temp data that was allocated in the
4484 * SessionHandle for this single request.
4485 */
4486
Curl_free_request_state(struct SessionHandle * data)4487 void Curl_free_request_state(struct SessionHandle *data)
4488 {
4489 Curl_safefree(data->req.protop);
4490 Curl_safefree(data->req.newurl);
4491 }
4492
4493
4494 #ifndef CURL_DISABLE_PROXY
4495 /****************************************************************
4496 * Checks if the host is in the noproxy list. returns true if it matches
4497 * and therefore the proxy should NOT be used.
4498 ****************************************************************/
check_noproxy(const char * name,const char * no_proxy)4499 static bool check_noproxy(const char* name, const char* no_proxy)
4500 {
4501 /* no_proxy=domain1.dom,host.domain2.dom
4502 * (a comma-separated list of hosts which should
4503 * not be proxied, or an asterisk to override
4504 * all proxy variables)
4505 */
4506 size_t tok_start;
4507 size_t tok_end;
4508 const char* separator = ", ";
4509 size_t no_proxy_len;
4510 size_t namelen;
4511 char *endptr;
4512
4513 if(no_proxy && no_proxy[0]) {
4514 if(Curl_raw_equal("*", no_proxy)) {
4515 return TRUE;
4516 }
4517
4518 /* NO_PROXY was specified and it wasn't just an asterisk */
4519
4520 no_proxy_len = strlen(no_proxy);
4521 endptr = strchr(name, ':');
4522 if(endptr)
4523 namelen = endptr - name;
4524 else
4525 namelen = strlen(name);
4526
4527 for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
4528 while(tok_start < no_proxy_len &&
4529 strchr(separator, no_proxy[tok_start]) != NULL) {
4530 /* Look for the beginning of the token. */
4531 ++tok_start;
4532 }
4533
4534 if(tok_start == no_proxy_len)
4535 break; /* It was all trailing separator chars, no more tokens. */
4536
4537 for(tok_end = tok_start; tok_end < no_proxy_len &&
4538 strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end)
4539 /* Look for the end of the token. */
4540 ;
4541
4542 /* To match previous behaviour, where it was necessary to specify
4543 * ".local.com" to prevent matching "notlocal.com", we will leave
4544 * the '.' off.
4545 */
4546 if(no_proxy[tok_start] == '.')
4547 ++tok_start;
4548
4549 if((tok_end - tok_start) <= namelen) {
4550 /* Match the last part of the name to the domain we are checking. */
4551 const char *checkn = name + namelen - (tok_end - tok_start);
4552 if(Curl_raw_nequal(no_proxy + tok_start, checkn,
4553 tok_end - tok_start)) {
4554 if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
4555 /* We either have an exact match, or the previous character is a .
4556 * so it is within the same domain, so no proxy for this host.
4557 */
4558 return TRUE;
4559 }
4560 }
4561 } /* if((tok_end - tok_start) <= namelen) */
4562 } /* for(tok_start = 0; tok_start < no_proxy_len;
4563 tok_start = tok_end + 1) */
4564 } /* NO_PROXY was specified and it wasn't just an asterisk */
4565
4566 return FALSE;
4567 }
4568
4569 /****************************************************************
4570 * Detect what (if any) proxy to use. Remember that this selects a host
4571 * name and is not limited to HTTP proxies only.
4572 * The returned pointer must be freed by the caller (unless NULL)
4573 ****************************************************************/
detect_proxy(struct connectdata * conn)4574 static char *detect_proxy(struct connectdata *conn)
4575 {
4576 char *proxy = NULL;
4577
4578 #ifndef CURL_DISABLE_HTTP
4579 /* If proxy was not specified, we check for default proxy environment
4580 * variables, to enable i.e Lynx compliance:
4581 *
4582 * http_proxy=http://some.server.dom:port/
4583 * https_proxy=http://some.server.dom:port/
4584 * ftp_proxy=http://some.server.dom:port/
4585 * no_proxy=domain1.dom,host.domain2.dom
4586 * (a comma-separated list of hosts which should
4587 * not be proxied, or an asterisk to override
4588 * all proxy variables)
4589 * all_proxy=http://some.server.dom:port/
4590 * (seems to exist for the CERN www lib. Probably
4591 * the first to check for.)
4592 *
4593 * For compatibility, the all-uppercase versions of these variables are
4594 * checked if the lowercase versions don't exist.
4595 */
4596 char *no_proxy=NULL;
4597 char proxy_env[128];
4598
4599 no_proxy=curl_getenv("no_proxy");
4600 if(!no_proxy)
4601 no_proxy=curl_getenv("NO_PROXY");
4602
4603 if(!check_noproxy(conn->host.name, no_proxy)) {
4604 /* It was not listed as without proxy */
4605 const char *protop = conn->handler->scheme;
4606 char *envp = proxy_env;
4607 char *prox;
4608
4609 /* Now, build <protocol>_proxy and check for such a one to use */
4610 while(*protop)
4611 *envp++ = (char)tolower((int)*protop++);
4612
4613 /* append _proxy */
4614 strcpy(envp, "_proxy");
4615
4616 /* read the protocol proxy: */
4617 prox=curl_getenv(proxy_env);
4618
4619 /*
4620 * We don't try the uppercase version of HTTP_PROXY because of
4621 * security reasons:
4622 *
4623 * When curl is used in a webserver application
4624 * environment (cgi or php), this environment variable can
4625 * be controlled by the web server user by setting the
4626 * http header 'Proxy:' to some value.
4627 *
4628 * This can cause 'internal' http/ftp requests to be
4629 * arbitrarily redirected by any external attacker.
4630 */
4631 if(!prox && !Curl_raw_equal("http_proxy", proxy_env)) {
4632 /* There was no lowercase variable, try the uppercase version: */
4633 Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
4634 prox=curl_getenv(proxy_env);
4635 }
4636
4637 if(prox)
4638 proxy = prox; /* use this */
4639 else {
4640 proxy = curl_getenv("all_proxy"); /* default proxy to use */
4641 if(!proxy)
4642 proxy=curl_getenv("ALL_PROXY");
4643 }
4644 } /* if(!check_noproxy(conn->host.name, no_proxy)) - it wasn't specified
4645 non-proxy */
4646 free(no_proxy);
4647
4648 #else /* !CURL_DISABLE_HTTP */
4649
4650 (void)conn;
4651 #endif /* CURL_DISABLE_HTTP */
4652
4653 return proxy;
4654 }
4655
4656 /*
4657 * If this is supposed to use a proxy, we need to figure out the proxy
4658 * host name, so that we can re-use an existing connection
4659 * that may exist registered to the same proxy host.
4660 */
parse_proxy(struct SessionHandle * data,struct connectdata * conn,char * proxy)4661 static CURLcode parse_proxy(struct SessionHandle *data,
4662 struct connectdata *conn, char *proxy)
4663 {
4664 char *prox_portno;
4665 char *endofprot;
4666
4667 /* We use 'proxyptr' to point to the proxy name from now on... */
4668 char *proxyptr;
4669 char *portptr;
4670 char *atsign;
4671
4672 /* We do the proxy host string parsing here. We want the host name and the
4673 * port name. Accept a protocol:// prefix
4674 */
4675
4676 /* Parse the protocol part if present */
4677 endofprot = strstr(proxy, "://");
4678 if(endofprot) {
4679 proxyptr = endofprot+3;
4680 if(checkprefix("socks5h", proxy))
4681 conn->proxytype = CURLPROXY_SOCKS5_HOSTNAME;
4682 else if(checkprefix("socks5", proxy))
4683 conn->proxytype = CURLPROXY_SOCKS5;
4684 else if(checkprefix("socks4a", proxy))
4685 conn->proxytype = CURLPROXY_SOCKS4A;
4686 else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy))
4687 conn->proxytype = CURLPROXY_SOCKS4;
4688 /* Any other xxx:// : change to http proxy */
4689 }
4690 else
4691 proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
4692
4693 /* Is there a username and password given in this proxy url? */
4694 atsign = strchr(proxyptr, '@');
4695 if(atsign) {
4696 char *proxyuser = NULL;
4697 char *proxypasswd = NULL;
4698 CURLcode result =
4699 parse_login_details(proxyptr, atsign - proxyptr,
4700 &proxyuser, &proxypasswd, NULL);
4701 if(!result) {
4702 /* found user and password, rip them out. note that we are
4703 unescaping them, as there is otherwise no way to have a
4704 username or password with reserved characters like ':' in
4705 them. */
4706 Curl_safefree(conn->proxyuser);
4707 if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH)
4708 conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
4709 else
4710 conn->proxyuser = strdup("");
4711
4712 if(!conn->proxyuser)
4713 result = CURLE_OUT_OF_MEMORY;
4714 else {
4715 Curl_safefree(conn->proxypasswd);
4716 if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
4717 conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
4718 else
4719 conn->proxypasswd = strdup("");
4720
4721 if(!conn->proxypasswd)
4722 result = CURLE_OUT_OF_MEMORY;
4723 }
4724
4725 if(!result) {
4726 conn->bits.proxy_user_passwd = TRUE; /* enable it */
4727 atsign++; /* the right side of the @-letter */
4728
4729 proxyptr = atsign; /* now use this instead */
4730 }
4731 }
4732
4733 free(proxyuser);
4734 free(proxypasswd);
4735
4736 if(result)
4737 return result;
4738 }
4739
4740 /* start scanning for port number at this point */
4741 portptr = proxyptr;
4742
4743 /* detect and extract RFC6874-style IPv6-addresses */
4744 if(*proxyptr == '[') {
4745 char *ptr = ++proxyptr; /* advance beyond the initial bracket */
4746 while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
4747 ptr++;
4748 if(*ptr == '%') {
4749 /* There might be a zone identifier */
4750 if(strncmp("%25", ptr, 3))
4751 infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
4752 ptr++;
4753 /* Allow unreserved characters as defined in RFC 3986 */
4754 while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
4755 (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
4756 ptr++;
4757 }
4758 if(*ptr == ']')
4759 /* yeps, it ended nicely with a bracket as well */
4760 *ptr++ = 0;
4761 else
4762 infof(data, "Invalid IPv6 address format\n");
4763 portptr = ptr;
4764 /* Note that if this didn't end with a bracket, we still advanced the
4765 * proxyptr first, but I can't see anything wrong with that as no host
4766 * name nor a numeric can legally start with a bracket.
4767 */
4768 }
4769
4770 /* Get port number off proxy.server.com:1080 */
4771 prox_portno = strchr(portptr, ':');
4772 if(prox_portno) {
4773 char *endp = NULL;
4774 long port = 0;
4775 *prox_portno = 0x0; /* cut off number from host name */
4776 prox_portno ++;
4777 /* now set the local port number */
4778 port = strtol(prox_portno, &endp, 10);
4779 if((endp && *endp && (*endp != '/') && (*endp != ' ')) ||
4780 (port < 0) || (port > 65535)) {
4781 /* meant to detect for example invalid IPv6 numerical addresses without
4782 brackets: "2a00:fac0:a000::7:13". Accept a trailing slash only
4783 because we then allow "URL style" with the number followed by a
4784 slash, used in curl test cases already. Space is also an acceptable
4785 terminating symbol. */
4786 infof(data, "No valid port number in proxy string (%s)\n",
4787 prox_portno);
4788 }
4789 else
4790 conn->port = port;
4791 }
4792 else {
4793 if(proxyptr[0]=='/')
4794 /* If the first character in the proxy string is a slash, fail
4795 immediately. The following code will otherwise clear the string which
4796 will lead to code running as if no proxy was set! */
4797 return CURLE_COULDNT_RESOLVE_PROXY;
4798
4799 /* without a port number after the host name, some people seem to use
4800 a slash so we strip everything from the first slash */
4801 atsign = strchr(proxyptr, '/');
4802 if(atsign)
4803 *atsign = '\0'; /* cut off path part from host name */
4804
4805 if(data->set.proxyport)
4806 /* None given in the proxy string, then get the default one if it is
4807 given */
4808 conn->port = data->set.proxyport;
4809 }
4810
4811 /* now, clone the cleaned proxy host name */
4812 conn->proxy.rawalloc = strdup(proxyptr);
4813 conn->proxy.name = conn->proxy.rawalloc;
4814
4815 if(!conn->proxy.rawalloc)
4816 return CURLE_OUT_OF_MEMORY;
4817
4818 return CURLE_OK;
4819 }
4820
4821 /*
4822 * Extract the user and password from the authentication string
4823 */
parse_proxy_auth(struct SessionHandle * data,struct connectdata * conn)4824 static CURLcode parse_proxy_auth(struct SessionHandle *data,
4825 struct connectdata *conn)
4826 {
4827 char proxyuser[MAX_CURL_USER_LENGTH]="";
4828 char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
4829
4830 if(data->set.str[STRING_PROXYUSERNAME] != NULL) {
4831 strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME],
4832 MAX_CURL_USER_LENGTH);
4833 proxyuser[MAX_CURL_USER_LENGTH-1] = '\0'; /*To be on safe side*/
4834 }
4835 if(data->set.str[STRING_PROXYPASSWORD] != NULL) {
4836 strncpy(proxypasswd, data->set.str[STRING_PROXYPASSWORD],
4837 MAX_CURL_PASSWORD_LENGTH);
4838 proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
4839 }
4840
4841 conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
4842 if(!conn->proxyuser)
4843 return CURLE_OUT_OF_MEMORY;
4844
4845 conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
4846 if(!conn->proxypasswd)
4847 return CURLE_OUT_OF_MEMORY;
4848
4849 return CURLE_OK;
4850 }
4851 #endif /* CURL_DISABLE_PROXY */
4852
4853 /*
4854 * parse_url_login()
4855 *
4856 * Parse the login details (user name, password and options) from the URL and
4857 * strip them out of the host name
4858 *
4859 * Inputs: data->set.use_netrc (CURLOPT_NETRC)
4860 * conn->host.name
4861 *
4862 * Outputs: (almost :- all currently undefined)
4863 * conn->bits.user_passwd - non-zero if non-default passwords exist
4864 * user - non-zero length if defined
4865 * passwd - non-zero length if defined
4866 * options - non-zero length if defined
4867 * conn->host.name - remove user name and password
4868 */
parse_url_login(struct SessionHandle * data,struct connectdata * conn,char ** user,char ** passwd,char ** options)4869 static CURLcode parse_url_login(struct SessionHandle *data,
4870 struct connectdata *conn,
4871 char **user, char **passwd, char **options)
4872 {
4873 CURLcode result = CURLE_OK;
4874 char *userp = NULL;
4875 char *passwdp = NULL;
4876 char *optionsp = NULL;
4877
4878 /* At this point, we're hoping all the other special cases have
4879 * been taken care of, so conn->host.name is at most
4880 * [user[:password][;options]]@]hostname
4881 *
4882 * We need somewhere to put the embedded details, so do that first.
4883 */
4884
4885 char *ptr = strchr(conn->host.name, '@');
4886 char *login = conn->host.name;
4887
4888 DEBUGASSERT(!**user);
4889 DEBUGASSERT(!**passwd);
4890 DEBUGASSERT(!**options);
4891
4892 if(!ptr)
4893 goto out;
4894
4895 /* We will now try to extract the
4896 * possible login information in a string like:
4897 * ftp://user:password@ftp.my.site:8021/README */
4898 conn->host.name = ++ptr;
4899
4900 /* So the hostname is sane. Only bother interpreting the
4901 * results if we could care. It could still be wasted
4902 * work because it might be overtaken by the programmatically
4903 * set user/passwd, but doing that first adds more cases here :-(
4904 */
4905
4906 if(data->set.use_netrc == CURL_NETRC_REQUIRED)
4907 goto out;
4908
4909 /* We could use the login information in the URL so extract it */
4910 result = parse_login_details(login, ptr - login - 1,
4911 &userp, &passwdp, &optionsp);
4912 if(result)
4913 goto out;
4914
4915 if(userp) {
4916 char *newname;
4917
4918 /* We have a user in the URL */
4919 conn->bits.userpwd_in_url = TRUE;
4920 conn->bits.user_passwd = TRUE; /* enable user+password */
4921
4922 /* Decode the user */
4923 newname = curl_easy_unescape(data, userp, 0, NULL);
4924 if(!newname) {
4925 result = CURLE_OUT_OF_MEMORY;
4926 goto out;
4927 }
4928
4929 free(*user);
4930 *user = newname;
4931 }
4932
4933 if(passwdp) {
4934 /* We have a password in the URL so decode it */
4935 char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL);
4936 if(!newpasswd) {
4937 result = CURLE_OUT_OF_MEMORY;
4938 goto out;
4939 }
4940
4941 free(*passwd);
4942 *passwd = newpasswd;
4943 }
4944
4945 if(optionsp) {
4946 /* We have an options list in the URL so decode it */
4947 char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL);
4948 if(!newoptions) {
4949 result = CURLE_OUT_OF_MEMORY;
4950 goto out;
4951 }
4952
4953 free(*options);
4954 *options = newoptions;
4955 }
4956
4957
4958 out:
4959
4960 free(userp);
4961 free(passwdp);
4962 free(optionsp);
4963
4964 return result;
4965 }
4966
4967 /*
4968 * parse_login_details()
4969 *
4970 * This is used to parse a login string for user name, password and options in
4971 * the following formats:
4972 *
4973 * user
4974 * user:password
4975 * user:password;options
4976 * user;options
4977 * user;options:password
4978 * :password
4979 * :password;options
4980 * ;options
4981 * ;options:password
4982 *
4983 * Parameters:
4984 *
4985 * login [in] - The login string.
4986 * len [in] - The length of the login string.
4987 * userp [in/out] - The address where a pointer to newly allocated memory
4988 * holding the user will be stored upon completion.
4989 * passdwp [in/out] - The address where a pointer to newly allocated memory
4990 * holding the password will be stored upon completion.
4991 * optionsp [in/out] - The address where a pointer to newly allocated memory
4992 * holding the options will be stored upon completion.
4993 *
4994 * Returns CURLE_OK on success.
4995 */
parse_login_details(const char * login,const size_t len,char ** userp,char ** passwdp,char ** optionsp)4996 static CURLcode parse_login_details(const char *login, const size_t len,
4997 char **userp, char **passwdp,
4998 char **optionsp)
4999 {
5000 CURLcode result = CURLE_OK;
5001 char *ubuf = NULL;
5002 char *pbuf = NULL;
5003 char *obuf = NULL;
5004 const char *psep = NULL;
5005 const char *osep = NULL;
5006 size_t ulen;
5007 size_t plen;
5008 size_t olen;
5009
5010 /* Attempt to find the password separator */
5011 if(passwdp) {
5012 psep = strchr(login, ':');
5013
5014 /* Within the constraint of the login string */
5015 if(psep >= login + len)
5016 psep = NULL;
5017 }
5018
5019 /* Attempt to find the options separator */
5020 if(optionsp) {
5021 osep = strchr(login, ';');
5022
5023 /* Within the constraint of the login string */
5024 if(osep >= login + len)
5025 osep = NULL;
5026 }
5027
5028 /* Calculate the portion lengths */
5029 ulen = (psep ?
5030 (size_t)(osep && psep > osep ? osep - login : psep - login) :
5031 (osep ? (size_t)(osep - login) : len));
5032 plen = (psep ?
5033 (osep && osep > psep ? (size_t)(osep - psep) :
5034 (size_t)(login + len - psep)) - 1 : 0);
5035 olen = (osep ?
5036 (psep && psep > osep ? (size_t)(psep - osep) :
5037 (size_t)(login + len - osep)) - 1 : 0);
5038
5039 /* Allocate the user portion buffer */
5040 if(userp && ulen) {
5041 ubuf = malloc(ulen + 1);
5042 if(!ubuf)
5043 result = CURLE_OUT_OF_MEMORY;
5044 }
5045
5046 /* Allocate the password portion buffer */
5047 if(!result && passwdp && plen) {
5048 pbuf = malloc(plen + 1);
5049 if(!pbuf) {
5050 free(ubuf);
5051 result = CURLE_OUT_OF_MEMORY;
5052 }
5053 }
5054
5055 /* Allocate the options portion buffer */
5056 if(!result && optionsp && olen) {
5057 obuf = malloc(olen + 1);
5058 if(!obuf) {
5059 free(pbuf);
5060 free(ubuf);
5061 result = CURLE_OUT_OF_MEMORY;
5062 }
5063 }
5064
5065 if(!result) {
5066 /* Store the user portion if necessary */
5067 if(ubuf) {
5068 memcpy(ubuf, login, ulen);
5069 ubuf[ulen] = '\0';
5070 Curl_safefree(*userp);
5071 *userp = ubuf;
5072 }
5073
5074 /* Store the password portion if necessary */
5075 if(pbuf) {
5076 memcpy(pbuf, psep + 1, plen);
5077 pbuf[plen] = '\0';
5078 Curl_safefree(*passwdp);
5079 *passwdp = pbuf;
5080 }
5081
5082 /* Store the options portion if necessary */
5083 if(obuf) {
5084 memcpy(obuf, osep + 1, olen);
5085 obuf[olen] = '\0';
5086 Curl_safefree(*optionsp);
5087 *optionsp = obuf;
5088 }
5089 }
5090
5091 return result;
5092 }
5093
5094 /*************************************************************
5095 * Figure out the remote port number and fix it in the URL
5096 *
5097 * No matter if we use a proxy or not, we have to figure out the remote
5098 * port number of various reasons.
5099 *
5100 * To be able to detect port number flawlessly, we must not confuse them
5101 * IPv6-specified addresses in the [0::1] style. (RFC2732)
5102 *
5103 * The conn->host.name is currently [user:passwd@]host[:port] where host
5104 * could be a hostname, IPv4 address or IPv6 address.
5105 *
5106 * The port number embedded in the URL is replaced, if necessary.
5107 *************************************************************/
parse_remote_port(struct SessionHandle * data,struct connectdata * conn)5108 static CURLcode parse_remote_port(struct SessionHandle *data,
5109 struct connectdata *conn)
5110 {
5111 char *portptr;
5112 char endbracket;
5113
5114 /* Note that at this point, the IPv6 address cannot contain any scope
5115 suffix as that has already been removed in the parseurlandfillconn()
5116 function */
5117 if((1 == sscanf(conn->host.name, "[%*45[0123456789abcdefABCDEF:.]%c",
5118 &endbracket)) &&
5119 (']' == endbracket)) {
5120 /* this is a RFC2732-style specified IP-address */
5121 conn->bits.ipv6_ip = TRUE;
5122
5123 conn->host.name++; /* skip over the starting bracket */
5124 portptr = strchr(conn->host.name, ']');
5125 if(portptr) {
5126 *portptr++ = '\0'; /* zero terminate, killing the bracket */
5127 if(':' != *portptr)
5128 portptr = NULL; /* no port number available */
5129 }
5130 }
5131 else {
5132 #ifdef ENABLE_IPV6
5133 struct in6_addr in6;
5134 if(Curl_inet_pton(AF_INET6, conn->host.name, &in6) > 0) {
5135 /* This is a numerical IPv6 address, meaning this is a wrongly formatted
5136 URL */
5137 failf(data, "IPv6 numerical address used in URL without brackets");
5138 return CURLE_URL_MALFORMAT;
5139 }
5140 #endif
5141
5142 portptr = strrchr(conn->host.name, ':');
5143 }
5144
5145 if(data->set.use_port && data->state.allow_port) {
5146 /* if set, we use this and ignore the port possibly given in the URL */
5147 conn->remote_port = (unsigned short)data->set.use_port;
5148 if(portptr)
5149 *portptr = '\0'; /* cut off the name there anyway - if there was a port
5150 number - since the port number is to be ignored! */
5151 if(conn->bits.httpproxy) {
5152 /* we need to create new URL with the new port number */
5153 char *url;
5154 char type[12]="";
5155
5156 if(conn->bits.type_set)
5157 snprintf(type, sizeof(type), ";type=%c",
5158 data->set.prefer_ascii?'A':
5159 (data->set.ftp_list_only?'D':'I'));
5160
5161 /*
5162 * This synthesized URL isn't always right--suffixes like ;type=A are
5163 * stripped off. It would be better to work directly from the original
5164 * URL and simply replace the port part of it.
5165 */
5166 url = aprintf("%s://%s%s%s:%hu%s%s%s", conn->given->scheme,
5167 conn->bits.ipv6_ip?"[":"", conn->host.name,
5168 conn->bits.ipv6_ip?"]":"", conn->remote_port,
5169 data->state.slash_removed?"/":"", data->state.path,
5170 type);
5171 if(!url)
5172 return CURLE_OUT_OF_MEMORY;
5173
5174 if(data->change.url_alloc) {
5175 Curl_safefree(data->change.url);
5176 data->change.url_alloc = FALSE;
5177 }
5178
5179 data->change.url = url;
5180 data->change.url_alloc = TRUE;
5181 }
5182 }
5183 else if(portptr) {
5184 /* no CURLOPT_PORT given, extract the one from the URL */
5185
5186 char *rest;
5187 long port;
5188
5189 port=strtol(portptr+1, &rest, 10); /* Port number must be decimal */
5190
5191 if((port < 0) || (port > 0xffff)) {
5192 /* Single unix standard says port numbers are 16 bits long */
5193 failf(data, "Port number out of range");
5194 return CURLE_URL_MALFORMAT;
5195 }
5196
5197 else if(rest != &portptr[1]) {
5198 *portptr = '\0'; /* cut off the name there */
5199 conn->remote_port = curlx_ultous(port);
5200 }
5201 else
5202 /* Browser behavior adaptation. If there's a colon with no digits after,
5203 just cut off the name there which makes us ignore the colon and just
5204 use the default port. Firefox and Chrome both do that. */
5205 *portptr = '\0';
5206 }
5207
5208 /* only if remote_port was not already parsed off the URL we use the
5209 default port number */
5210 if(conn->remote_port < 0)
5211 conn->remote_port = (unsigned short)conn->given->defport;
5212
5213 return CURLE_OK;
5214 }
5215
5216 /*
5217 * Override the login details from the URL with that in the CURLOPT_USERPWD
5218 * option or a .netrc file, if applicable.
5219 */
override_login(struct SessionHandle * data,struct connectdata * conn,char ** userp,char ** passwdp,char ** optionsp)5220 static CURLcode override_login(struct SessionHandle *data,
5221 struct connectdata *conn,
5222 char **userp, char **passwdp, char **optionsp)
5223 {
5224 if(data->set.str[STRING_USERNAME]) {
5225 free(*userp);
5226 *userp = strdup(data->set.str[STRING_USERNAME]);
5227 if(!*userp)
5228 return CURLE_OUT_OF_MEMORY;
5229 }
5230
5231 if(data->set.str[STRING_PASSWORD]) {
5232 free(*passwdp);
5233 *passwdp = strdup(data->set.str[STRING_PASSWORD]);
5234 if(!*passwdp)
5235 return CURLE_OUT_OF_MEMORY;
5236 }
5237
5238 if(data->set.str[STRING_OPTIONS]) {
5239 free(*optionsp);
5240 *optionsp = strdup(data->set.str[STRING_OPTIONS]);
5241 if(!*optionsp)
5242 return CURLE_OUT_OF_MEMORY;
5243 }
5244
5245 conn->bits.netrc = FALSE;
5246 if(data->set.use_netrc != CURL_NETRC_IGNORED) {
5247 int ret = Curl_parsenetrc(conn->host.name,
5248 userp, passwdp,
5249 data->set.str[STRING_NETRC_FILE]);
5250 if(ret > 0) {
5251 infof(data, "Couldn't find host %s in the "
5252 DOT_CHAR "netrc file; using defaults\n",
5253 conn->host.name);
5254 }
5255 else if(ret < 0) {
5256 return CURLE_OUT_OF_MEMORY;
5257 }
5258 else {
5259 /* set bits.netrc TRUE to remember that we got the name from a .netrc
5260 file, so that it is safe to use even if we followed a Location: to a
5261 different host or similar. */
5262 conn->bits.netrc = TRUE;
5263
5264 conn->bits.user_passwd = TRUE; /* enable user+password */
5265 }
5266 }
5267
5268 return CURLE_OK;
5269 }
5270
5271 /*
5272 * Set the login details so they're available in the connection
5273 */
set_login(struct connectdata * conn,const char * user,const char * passwd,const char * options)5274 static CURLcode set_login(struct connectdata *conn,
5275 const char *user, const char *passwd,
5276 const char *options)
5277 {
5278 CURLcode result = CURLE_OK;
5279
5280 /* If our protocol needs a password and we have none, use the defaults */
5281 if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd) {
5282 /* Store the default user */
5283 conn->user = strdup(CURL_DEFAULT_USER);
5284
5285 /* Store the default password */
5286 if(conn->user)
5287 conn->passwd = strdup(CURL_DEFAULT_PASSWORD);
5288 else
5289 conn->passwd = NULL;
5290
5291 /* This is the default password, so DON'T set conn->bits.user_passwd */
5292 }
5293 else {
5294 /* Store the user, zero-length if not set */
5295 conn->user = strdup(user);
5296
5297 /* Store the password (only if user is present), zero-length if not set */
5298 if(conn->user)
5299 conn->passwd = strdup(passwd);
5300 else
5301 conn->passwd = NULL;
5302 }
5303
5304 if(!conn->user || !conn->passwd)
5305 result = CURLE_OUT_OF_MEMORY;
5306
5307 /* Store the options, null if not set */
5308 if(!result && options[0]) {
5309 conn->options = strdup(options);
5310
5311 if(!conn->options)
5312 result = CURLE_OUT_OF_MEMORY;
5313 }
5314
5315 return result;
5316 }
5317
5318 /*
5319 * Parses a "host:port" string to connect to.
5320 * The hostname and the port may be empty; in this case, NULL is returned for
5321 * the hostname and -1 for the port.
5322 */
parse_connect_to_host_port(struct SessionHandle * data,const char * host,char ** hostname_result,int * port_result)5323 static CURLcode parse_connect_to_host_port(struct SessionHandle *data,
5324 const char *host,
5325 char **hostname_result,
5326 int *port_result)
5327 {
5328 char *host_dup;
5329 char *hostptr;
5330 char *host_portno;
5331 char *portptr;
5332 int port = -1;
5333
5334 *hostname_result = NULL;
5335 *port_result = -1;
5336
5337 if(!host || !*host)
5338 return CURLE_OK;
5339
5340 host_dup = strdup(host);
5341 if(!host_dup)
5342 return CURLE_OUT_OF_MEMORY;
5343
5344 hostptr = host_dup;
5345
5346 /* start scanning for port number at this point */
5347 portptr = hostptr;
5348
5349 /* detect and extract RFC6874-style IPv6-addresses */
5350 if(*hostptr == '[') {
5351 char *ptr = ++hostptr; /* advance beyond the initial bracket */
5352 while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
5353 ptr++;
5354 if(*ptr == '%') {
5355 /* There might be a zone identifier */
5356 if(strncmp("%25", ptr, 3))
5357 infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
5358 ptr++;
5359 /* Allow unreserved characters as defined in RFC 3986 */
5360 while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
5361 (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
5362 ptr++;
5363 }
5364 if(*ptr == ']')
5365 /* yeps, it ended nicely with a bracket as well */
5366 *ptr++ = '\0';
5367 else
5368 infof(data, "Invalid IPv6 address format\n");
5369 portptr = ptr;
5370 /* Note that if this didn't end with a bracket, we still advanced the
5371 * hostptr first, but I can't see anything wrong with that as no host
5372 * name nor a numeric can legally start with a bracket.
5373 */
5374 }
5375
5376 /* Get port number off server.com:1080 */
5377 host_portno = strchr(portptr, ':');
5378 if(host_portno) {
5379 char *endp = NULL;
5380 *host_portno = '\0'; /* cut off number from host name */
5381 host_portno++;
5382 if(*host_portno) {
5383 long portparse = strtol(host_portno, &endp, 10);
5384 if((endp && *endp) || (portparse < 0) || (portparse > 65535)) {
5385 infof(data, "No valid port number in connect to host string (%s)\n",
5386 host_portno);
5387 hostptr = NULL;
5388 port = -1;
5389 }
5390 else
5391 port = (int)portparse; /* we know it will fit */
5392 }
5393 }
5394
5395 /* now, clone the cleaned host name */
5396 if(hostptr) {
5397 *hostname_result = strdup(hostptr);
5398 if(!*hostname_result) {
5399 free(host_dup);
5400 return CURLE_OUT_OF_MEMORY;
5401 }
5402 }
5403
5404 *port_result = port;
5405
5406 free(host_dup);
5407 return CURLE_OK;
5408 }
5409
5410 /*
5411 * Parses one "connect to" string in the form:
5412 * "HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT".
5413 */
parse_connect_to_string(struct SessionHandle * data,struct connectdata * conn,const char * conn_to_host,char ** host_result,int * port_result)5414 static CURLcode parse_connect_to_string(struct SessionHandle *data,
5415 struct connectdata *conn,
5416 const char *conn_to_host,
5417 char **host_result,
5418 int *port_result)
5419 {
5420 CURLcode result = CURLE_OK;
5421 const char *ptr = conn_to_host;
5422 int host_match = FALSE;
5423 int port_match = FALSE;
5424
5425 if(*ptr == ':') {
5426 /* an empty hostname always matches */
5427 host_match = TRUE;
5428 ptr++;
5429 }
5430 else {
5431 /* check whether the URL's hostname matches */
5432 size_t hostname_to_match_len;
5433 char *hostname_to_match = aprintf("%s%s%s",
5434 conn->bits.ipv6_ip ? "[" : "",
5435 conn->host.name,
5436 conn->bits.ipv6_ip ? "]" : "");
5437 if(!hostname_to_match)
5438 return CURLE_OUT_OF_MEMORY;
5439 hostname_to_match_len = strlen(hostname_to_match);
5440 host_match = curl_strnequal(ptr, hostname_to_match, hostname_to_match_len);
5441 free(hostname_to_match);
5442 ptr += hostname_to_match_len;
5443
5444 host_match = host_match && *ptr == ':';
5445 ptr++;
5446 }
5447
5448 if(host_match) {
5449 if(*ptr == ':') {
5450 /* an empty port always matches */
5451 port_match = TRUE;
5452 ptr++;
5453 }
5454 else {
5455 /* check whether the URL's port matches */
5456 char *ptr_next = strchr(ptr, ':');
5457 if(ptr_next) {
5458 char *endp = NULL;
5459 long port_to_match = strtol(ptr, &endp, 10);
5460 if((endp == ptr_next) && (port_to_match == conn->remote_port)) {
5461 port_match = TRUE;
5462 ptr = ptr_next + 1;
5463 }
5464 }
5465 }
5466 }
5467
5468 if(host_match && port_match) {
5469 /* parse the hostname and port to connect to */
5470 result = parse_connect_to_host_port(data, ptr, host_result, port_result);
5471 }
5472
5473 return result;
5474 }
5475
5476 /*
5477 * Processes all strings in the "connect to" slist, and uses the "connect
5478 * to host" and "connect to port" of the first string that matches.
5479 */
parse_connect_to_slist(struct SessionHandle * data,struct connectdata * conn,struct curl_slist * conn_to_host)5480 static CURLcode parse_connect_to_slist(struct SessionHandle *data,
5481 struct connectdata *conn,
5482 struct curl_slist *conn_to_host)
5483 {
5484 CURLcode result = CURLE_OK;
5485 char *host = NULL;
5486 int port = 0;
5487
5488 while(conn_to_host && !host) {
5489 result = parse_connect_to_string(data, conn, conn_to_host->data,
5490 &host, &port);
5491 if(result)
5492 return result;
5493
5494 if(host && *host) {
5495 bool ipv6host;
5496 conn->conn_to_host.rawalloc = host;
5497 conn->conn_to_host.name = host;
5498 conn->bits.conn_to_host = TRUE;
5499
5500 ipv6host = strchr(host, ':') != NULL;
5501 infof(data, "Connecting to hostname: %s%s%s\n",
5502 ipv6host ? "[" : "", host, ipv6host ? "]" : "");
5503 }
5504 else {
5505 /* no "connect to host" */
5506 conn->bits.conn_to_host = FALSE;
5507 free(host);
5508 }
5509
5510 if(port >= 0) {
5511 conn->conn_to_port = port;
5512 conn->bits.conn_to_port = TRUE;
5513 infof(data, "Connecting to port: %d\n", port);
5514 }
5515 else {
5516 /* no "connect to port" */
5517 conn->bits.conn_to_port = FALSE;
5518 }
5519
5520 conn_to_host = conn_to_host->next;
5521 }
5522
5523 return result;
5524 }
5525
5526 /*************************************************************
5527 * Resolve the address of the server or proxy
5528 *************************************************************/
resolve_server(struct SessionHandle * data,struct connectdata * conn,bool * async)5529 static CURLcode resolve_server(struct SessionHandle *data,
5530 struct connectdata *conn,
5531 bool *async)
5532 {
5533 CURLcode result=CURLE_OK;
5534 long timeout_ms = Curl_timeleft(data, NULL, TRUE);
5535
5536 /*************************************************************
5537 * Resolve the name of the server or proxy
5538 *************************************************************/
5539 if(conn->bits.reuse)
5540 /* We're reusing the connection - no need to resolve anything, and
5541 fix_hostname() was called already in create_conn() for the re-use
5542 case. */
5543 *async = FALSE;
5544
5545 else {
5546 /* this is a fresh connect */
5547 int rc;
5548 struct Curl_dns_entry *hostaddr;
5549
5550 #ifdef USE_UNIX_SOCKETS
5551 if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
5552 /* Unix domain sockets are local. The host gets ignored, just use the
5553 * specified domain socket address. Do not cache "DNS entries". There is
5554 * no DNS involved and we already have the filesystem path available */
5555 const char *path = data->set.str[STRING_UNIX_SOCKET_PATH];
5556
5557 hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
5558 if(!hostaddr)
5559 result = CURLE_OUT_OF_MEMORY;
5560 else if((hostaddr->addr = Curl_unix2addr(path)) != NULL)
5561 hostaddr->inuse++;
5562 else {
5563 /* Long paths are not supported for now */
5564 if(strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path)) {
5565 failf(data, "Unix socket path too long: '%s'", path);
5566 result = CURLE_COULDNT_RESOLVE_HOST;
5567 }
5568 else
5569 result = CURLE_OUT_OF_MEMORY;
5570 free(hostaddr);
5571 hostaddr = NULL;
5572 }
5573 }
5574 else
5575 #endif
5576 if(!conn->proxy.name || !*conn->proxy.name) {
5577 struct hostname *connhost;
5578 if(conn->bits.conn_to_host)
5579 connhost = &conn->conn_to_host;
5580 else
5581 connhost = &conn->host;
5582
5583 /* If not connecting via a proxy, extract the port from the URL, if it is
5584 * there, thus overriding any defaults that might have been set above. */
5585 if(conn->bits.conn_to_port)
5586 conn->port = conn->conn_to_port;
5587 else
5588 conn->port = conn->remote_port; /* it is the same port */
5589
5590 /* Resolve target host right on */
5591 rc = Curl_resolv_timeout(conn, connhost->name, (int)conn->port,
5592 &hostaddr, timeout_ms);
5593 if(rc == CURLRESOLV_PENDING)
5594 *async = TRUE;
5595
5596 else if(rc == CURLRESOLV_TIMEDOUT)
5597 result = CURLE_OPERATION_TIMEDOUT;
5598
5599 else if(!hostaddr) {
5600 failf(data, "Couldn't resolve host '%s'", connhost->dispname);
5601 result = CURLE_COULDNT_RESOLVE_HOST;
5602 /* don't return yet, we need to clean up the timeout first */
5603 }
5604 }
5605 else {
5606 /* This is a proxy that hasn't been resolved yet. */
5607
5608 /* resolve proxy */
5609 rc = Curl_resolv_timeout(conn, conn->proxy.name, (int)conn->port,
5610 &hostaddr, timeout_ms);
5611
5612 if(rc == CURLRESOLV_PENDING)
5613 *async = TRUE;
5614
5615 else if(rc == CURLRESOLV_TIMEDOUT)
5616 result = CURLE_OPERATION_TIMEDOUT;
5617
5618 else if(!hostaddr) {
5619 failf(data, "Couldn't resolve proxy '%s'", conn->proxy.dispname);
5620 result = CURLE_COULDNT_RESOLVE_PROXY;
5621 /* don't return yet, we need to clean up the timeout first */
5622 }
5623 }
5624 DEBUGASSERT(conn->dns_entry == NULL);
5625 conn->dns_entry = hostaddr;
5626 }
5627
5628 return result;
5629 }
5630
5631 /*
5632 * Cleanup the connection just allocated before we can move along and use the
5633 * previously existing one. All relevant data is copied over and old_conn is
5634 * ready for freeing once this function returns.
5635 */
reuse_conn(struct connectdata * old_conn,struct connectdata * conn)5636 static void reuse_conn(struct connectdata *old_conn,
5637 struct connectdata *conn)
5638 {
5639 free_fixed_hostname(&old_conn->proxy);
5640 free(old_conn->proxy.rawalloc);
5641
5642 /* free the SSL config struct from this connection struct as this was
5643 allocated in vain and is targeted for destruction */
5644 Curl_free_ssl_config(&old_conn->ssl_config);
5645
5646 conn->data = old_conn->data;
5647
5648 /* get the user+password information from the old_conn struct since it may
5649 * be new for this request even when we re-use an existing connection */
5650 conn->bits.user_passwd = old_conn->bits.user_passwd;
5651 if(conn->bits.user_passwd) {
5652 /* use the new user name and password though */
5653 Curl_safefree(conn->user);
5654 Curl_safefree(conn->passwd);
5655 conn->user = old_conn->user;
5656 conn->passwd = old_conn->passwd;
5657 old_conn->user = NULL;
5658 old_conn->passwd = NULL;
5659 }
5660
5661 conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
5662 if(conn->bits.proxy_user_passwd) {
5663 /* use the new proxy user name and proxy password though */
5664 Curl_safefree(conn->proxyuser);
5665 Curl_safefree(conn->proxypasswd);
5666 conn->proxyuser = old_conn->proxyuser;
5667 conn->proxypasswd = old_conn->proxypasswd;
5668 old_conn->proxyuser = NULL;
5669 old_conn->proxypasswd = NULL;
5670 }
5671
5672 /* host can change, when doing keepalive with a proxy or if the case is
5673 different this time etc */
5674 free_fixed_hostname(&conn->host);
5675 free_fixed_hostname(&conn->conn_to_host);
5676 Curl_safefree(conn->host.rawalloc);
5677 Curl_safefree(conn->conn_to_host.rawalloc);
5678 conn->host=old_conn->host;
5679 conn->bits.conn_to_host = old_conn->bits.conn_to_host;
5680 conn->conn_to_host = old_conn->conn_to_host;
5681 conn->bits.conn_to_port = old_conn->bits.conn_to_port;
5682 conn->conn_to_port = old_conn->conn_to_port;
5683
5684 /* persist connection info in session handle */
5685 Curl_persistconninfo(conn);
5686
5687 conn_reset_all_postponed_data(old_conn); /* free buffers */
5688 conn_reset_all_postponed_data(conn); /* reset unprocessed data */
5689
5690 /* re-use init */
5691 conn->bits.reuse = TRUE; /* yes, we're re-using here */
5692
5693 Curl_safefree(old_conn->user);
5694 Curl_safefree(old_conn->passwd);
5695 Curl_safefree(old_conn->proxyuser);
5696 Curl_safefree(old_conn->proxypasswd);
5697 Curl_safefree(old_conn->localdev);
5698
5699 Curl_llist_destroy(old_conn->send_pipe, NULL);
5700 Curl_llist_destroy(old_conn->recv_pipe, NULL);
5701
5702 old_conn->send_pipe = NULL;
5703 old_conn->recv_pipe = NULL;
5704
5705 Curl_safefree(old_conn->master_buffer);
5706 }
5707
5708 /**
5709 * create_conn() sets up a new connectdata struct, or re-uses an already
5710 * existing one, and resolves host name.
5711 *
5712 * if this function returns CURLE_OK and *async is set to TRUE, the resolve
5713 * response will be coming asynchronously. If *async is FALSE, the name is
5714 * already resolved.
5715 *
5716 * @param data The sessionhandle pointer
5717 * @param in_connect is set to the next connection data pointer
5718 * @param async is set TRUE when an async DNS resolution is pending
5719 * @see Curl_setup_conn()
5720 *
5721 * *NOTE* this function assigns the conn->data pointer!
5722 */
5723
create_conn(struct SessionHandle * data,struct connectdata ** in_connect,bool * async)5724 static CURLcode create_conn(struct SessionHandle *data,
5725 struct connectdata **in_connect,
5726 bool *async)
5727 {
5728 CURLcode result = CURLE_OK;
5729 struct connectdata *conn;
5730 struct connectdata *conn_temp = NULL;
5731 size_t urllen;
5732 char *user = NULL;
5733 char *passwd = NULL;
5734 char *options = NULL;
5735 bool reuse;
5736 char *proxy = NULL;
5737 bool prot_missing = FALSE;
5738 bool connections_available = TRUE;
5739 bool force_reuse = FALSE;
5740 bool waitpipe = FALSE;
5741 size_t max_host_connections = Curl_multi_max_host_connections(data->multi);
5742 size_t max_total_connections = Curl_multi_max_total_connections(data->multi);
5743
5744 *async = FALSE;
5745
5746 /*************************************************************
5747 * Check input data
5748 *************************************************************/
5749
5750 if(!data->change.url) {
5751 result = CURLE_URL_MALFORMAT;
5752 goto out;
5753 }
5754
5755 /* First, split up the current URL in parts so that we can use the
5756 parts for checking against the already present connections. In order
5757 to not have to modify everything at once, we allocate a temporary
5758 connection data struct and fill in for comparison purposes. */
5759 conn = allocate_conn(data);
5760
5761 if(!conn) {
5762 result = CURLE_OUT_OF_MEMORY;
5763 goto out;
5764 }
5765
5766 /* We must set the return variable as soon as possible, so that our
5767 parent can cleanup any possible allocs we may have done before
5768 any failure */
5769 *in_connect = conn;
5770
5771 /* This initing continues below, see the comment "Continue connectdata
5772 * initialization here" */
5773
5774 /***********************************************************
5775 * We need to allocate memory to store the path in. We get the size of the
5776 * full URL to be sure, and we need to make it at least 256 bytes since
5777 * other parts of the code will rely on this fact
5778 ***********************************************************/
5779 #define LEAST_PATH_ALLOC 256
5780 urllen=strlen(data->change.url);
5781 if(urllen < LEAST_PATH_ALLOC)
5782 urllen=LEAST_PATH_ALLOC;
5783
5784 /*
5785 * We malloc() the buffers below urllen+2 to make room for 2 possibilities:
5786 * 1 - an extra terminating zero
5787 * 2 - an extra slash (in case a syntax like "www.host.com?moo" is used)
5788 */
5789
5790 Curl_safefree(data->state.pathbuffer);
5791 data->state.path = NULL;
5792
5793 data->state.pathbuffer = malloc(urllen+2);
5794 if(NULL == data->state.pathbuffer) {
5795 result = CURLE_OUT_OF_MEMORY; /* really bad error */
5796 goto out;
5797 }
5798 data->state.path = data->state.pathbuffer;
5799
5800 conn->host.rawalloc = malloc(urllen+2);
5801 if(NULL == conn->host.rawalloc) {
5802 Curl_safefree(data->state.pathbuffer);
5803 data->state.path = NULL;
5804 result = CURLE_OUT_OF_MEMORY;
5805 goto out;
5806 }
5807
5808 conn->host.name = conn->host.rawalloc;
5809 conn->host.name[0] = 0;
5810
5811 user = strdup("");
5812 passwd = strdup("");
5813 options = strdup("");
5814 if(!user || !passwd || !options) {
5815 result = CURLE_OUT_OF_MEMORY;
5816 goto out;
5817 }
5818
5819 result = parseurlandfillconn(data, conn, &prot_missing, &user, &passwd,
5820 &options);
5821 if(result)
5822 goto out;
5823
5824 /*************************************************************
5825 * No protocol part in URL was used, add it!
5826 *************************************************************/
5827 if(prot_missing) {
5828 /* We're guessing prefixes here and if we're told to use a proxy or if
5829 we're gonna follow a Location: later or... then we need the protocol
5830 part added so that we have a valid URL. */
5831 char *reurl;
5832 char *ch_lower;
5833
5834 reurl = aprintf("%s://%s", conn->handler->scheme, data->change.url);
5835
5836 if(!reurl) {
5837 result = CURLE_OUT_OF_MEMORY;
5838 goto out;
5839 }
5840
5841 /* Change protocol prefix to lower-case */
5842 for(ch_lower = reurl; *ch_lower != ':'; ch_lower++)
5843 *ch_lower = (char)TOLOWER(*ch_lower);
5844
5845 if(data->change.url_alloc) {
5846 Curl_safefree(data->change.url);
5847 data->change.url_alloc = FALSE;
5848 }
5849
5850 data->change.url = reurl;
5851 data->change.url_alloc = TRUE; /* free this later */
5852 }
5853
5854 /*************************************************************
5855 * If the protocol can't handle url query strings, then cut
5856 * off the unhandable part
5857 *************************************************************/
5858 if((conn->given->flags&PROTOPT_NOURLQUERY)) {
5859 char *path_q_sep = strchr(conn->data->state.path, '?');
5860 if(path_q_sep) {
5861 /* according to rfc3986, allow the query (?foo=bar)
5862 also on protocols that can't handle it.
5863
5864 cut the string-part after '?'
5865 */
5866
5867 /* terminate the string */
5868 path_q_sep[0] = 0;
5869 }
5870 }
5871
5872 if(data->set.str[STRING_BEARER]) {
5873 conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]);
5874 if(!conn->oauth_bearer) {
5875 result = CURLE_OUT_OF_MEMORY;
5876 goto out;
5877 }
5878 }
5879
5880 #ifndef CURL_DISABLE_PROXY
5881 /*************************************************************
5882 * Extract the user and password from the authentication string
5883 *************************************************************/
5884 if(conn->bits.proxy_user_passwd) {
5885 result = parse_proxy_auth(data, conn);
5886 if(result)
5887 goto out;
5888 }
5889
5890 /*************************************************************
5891 * Detect what (if any) proxy to use
5892 *************************************************************/
5893 if(data->set.str[STRING_PROXY]) {
5894 proxy = strdup(data->set.str[STRING_PROXY]);
5895 /* if global proxy is set, this is it */
5896 if(NULL == proxy) {
5897 failf(data, "memory shortage");
5898 result = CURLE_OUT_OF_MEMORY;
5899 goto out;
5900 }
5901 }
5902
5903 if(data->set.str[STRING_NOPROXY] &&
5904 check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) {
5905 free(proxy); /* proxy is in exception list */
5906 proxy = NULL;
5907 }
5908 else if(!proxy)
5909 proxy = detect_proxy(conn);
5910
5911 #ifdef USE_UNIX_SOCKETS
5912 if(proxy && data->set.str[STRING_UNIX_SOCKET_PATH]) {
5913 free(proxy); /* Unix domain sockets cannot be proxied, so disable it */
5914 proxy = NULL;
5915 }
5916 #endif
5917
5918 if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
5919 free(proxy); /* Don't bother with an empty proxy string or if the
5920 protocol doesn't work with network */
5921 proxy = NULL;
5922 }
5923
5924 /***********************************************************************
5925 * If this is supposed to use a proxy, we need to figure out the proxy host
5926 * name, proxy type and port number, so that we can re-use an existing
5927 * connection that may exist registered to the same proxy host.
5928 ***********************************************************************/
5929 if(proxy) {
5930 result = parse_proxy(data, conn, proxy);
5931
5932 free(proxy); /* parse_proxy copies the proxy string */
5933 proxy = NULL;
5934
5935 if(result)
5936 goto out;
5937
5938 if((conn->proxytype == CURLPROXY_HTTP) ||
5939 (conn->proxytype == CURLPROXY_HTTP_1_0)) {
5940 #ifdef CURL_DISABLE_HTTP
5941 /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
5942 result = CURLE_UNSUPPORTED_PROTOCOL;
5943 goto out;
5944 #else
5945 /* force this connection's protocol to become HTTP if not already
5946 compatible - if it isn't tunneling through */
5947 if(!(conn->handler->protocol & PROTO_FAMILY_HTTP) &&
5948 !conn->bits.tunnel_proxy)
5949 conn->handler = &Curl_handler_http;
5950
5951 conn->bits.httpproxy = TRUE;
5952 #endif
5953 }
5954 else {
5955 conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
5956 conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
5957 }
5958 conn->bits.proxy = TRUE;
5959 }
5960 else {
5961 /* we aren't using the proxy after all... */
5962 conn->bits.proxy = FALSE;
5963 conn->bits.httpproxy = FALSE;
5964 conn->bits.proxy_user_passwd = FALSE;
5965 conn->bits.tunnel_proxy = FALSE;
5966 }
5967
5968 #endif /* CURL_DISABLE_PROXY */
5969
5970 /*************************************************************
5971 * If the protocol is using SSL and HTTP proxy is used, we set
5972 * the tunnel_proxy bit.
5973 *************************************************************/
5974 if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
5975 conn->bits.tunnel_proxy = TRUE;
5976
5977 /*************************************************************
5978 * Figure out the remote port number and fix it in the URL
5979 *************************************************************/
5980 result = parse_remote_port(data, conn);
5981 if(result)
5982 goto out;
5983
5984 /* Check for overridden login details and set them accordingly so they
5985 they are known when protocol->setup_connection is called! */
5986 result = override_login(data, conn, &user, &passwd, &options);
5987 if(result)
5988 goto out;
5989 result = set_login(conn, user, passwd, options);
5990 if(result)
5991 goto out;
5992
5993 /*************************************************************
5994 * Process the "connect to" linked list of hostname/port mappings.
5995 * Do this after the remote port number has been fixed in the URL.
5996 *************************************************************/
5997 result = parse_connect_to_slist(data, conn, data->set.connect_to);
5998 if(result)
5999 goto out;
6000
6001 /*************************************************************
6002 * IDN-fix the hostnames
6003 *************************************************************/
6004 fix_hostname(data, conn, &conn->host);
6005 if(conn->bits.conn_to_host)
6006 fix_hostname(data, conn, &conn->conn_to_host);
6007 if(conn->proxy.name && *conn->proxy.name)
6008 fix_hostname(data, conn, &conn->proxy);
6009
6010 /*************************************************************
6011 * Check whether the host and the "connect to host" are equal.
6012 * Do this after the hostnames have been IDN-fixed .
6013 *************************************************************/
6014 if(conn->bits.conn_to_host &&
6015 Curl_raw_equal(conn->conn_to_host.name, conn->host.name)) {
6016 conn->bits.conn_to_host = FALSE;
6017 }
6018
6019 /*************************************************************
6020 * Check whether the port and the "connect to port" are equal.
6021 * Do this after the remote port number has been fixed in the URL.
6022 *************************************************************/
6023 if(conn->bits.conn_to_port && conn->conn_to_port == conn->remote_port) {
6024 conn->bits.conn_to_port = FALSE;
6025 }
6026
6027 /*************************************************************
6028 * If the "connect to" feature is used with an HTTP proxy,
6029 * we set the tunnel_proxy bit.
6030 *************************************************************/
6031 if((conn->bits.conn_to_host || conn->bits.conn_to_port) &&
6032 conn->bits.httpproxy)
6033 conn->bits.tunnel_proxy = TRUE;
6034
6035 /*************************************************************
6036 * Setup internals depending on protocol. Needs to be done after
6037 * we figured out what/if proxy to use.
6038 *************************************************************/
6039 result = setup_connection_internals(conn);
6040 if(result)
6041 goto out;
6042
6043 conn->recv[FIRSTSOCKET] = Curl_recv_plain;
6044 conn->send[FIRSTSOCKET] = Curl_send_plain;
6045 conn->recv[SECONDARYSOCKET] = Curl_recv_plain;
6046 conn->send[SECONDARYSOCKET] = Curl_send_plain;
6047
6048 conn->bits.tcp_fastopen = data->set.tcp_fastopen;
6049
6050 /***********************************************************************
6051 * file: is a special case in that it doesn't need a network connection
6052 ***********************************************************************/
6053 #ifndef CURL_DISABLE_FILE
6054 if(conn->handler->flags & PROTOPT_NONETWORK) {
6055 bool done;
6056 /* this is supposed to be the connect function so we better at least check
6057 that the file is present here! */
6058 DEBUGASSERT(conn->handler->connect_it);
6059 result = conn->handler->connect_it(conn, &done);
6060
6061 /* Setup a "faked" transfer that'll do nothing */
6062 if(!result) {
6063 conn->data = data;
6064 conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
6065
6066 Curl_conncache_add_conn(data->state.conn_cache, conn);
6067
6068 /*
6069 * Setup whatever necessary for a resumed transfer
6070 */
6071 result = setup_range(data);
6072 if(result) {
6073 DEBUGASSERT(conn->handler->done);
6074 /* we ignore the return code for the protocol-specific DONE */
6075 (void)conn->handler->done(conn, result, FALSE);
6076 goto out;
6077 }
6078
6079 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
6080 -1, NULL); /* no upload */
6081 }
6082
6083 /* since we skip do_init() */
6084 Curl_init_do(data, conn);
6085
6086 goto out;
6087 }
6088 #endif
6089
6090 /* Get a cloned copy of the SSL config situation stored in the
6091 connection struct. But to get this going nicely, we must first make
6092 sure that the strings in the master copy are pointing to the correct
6093 strings in the session handle strings array!
6094
6095 Keep in mind that the pointers in the master copy are pointing to strings
6096 that will be freed as part of the SessionHandle struct, but all cloned
6097 copies will be separately allocated.
6098 */
6099 data->set.ssl.CApath = data->set.str[STRING_SSL_CAPATH];
6100 data->set.ssl.CAfile = data->set.str[STRING_SSL_CAFILE];
6101 data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
6102 data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
6103 data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
6104 data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
6105 data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
6106 #ifdef USE_TLS_SRP
6107 data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME];
6108 data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
6109 #endif
6110
6111 if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) {
6112 result = CURLE_OUT_OF_MEMORY;
6113 goto out;
6114 }
6115
6116 prune_dead_connections(data);
6117
6118 /*************************************************************
6119 * Check the current list of connections to see if we can
6120 * re-use an already existing one or if we have to create a
6121 * new one.
6122 *************************************************************/
6123
6124 /* reuse_fresh is TRUE if we are told to use a new connection by force, but
6125 we only acknowledge this option if this is not a re-used connection
6126 already (which happens due to follow-location or during a HTTP
6127 authentication phase). */
6128 if(data->set.reuse_fresh && !data->state.this_is_a_follow)
6129 reuse = FALSE;
6130 else
6131 reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);
6132
6133 /* If we found a reusable connection, we may still want to
6134 open a new connection if we are pipelining. */
6135 if(reuse && !force_reuse && IsPipeliningPossible(data, conn_temp)) {
6136 size_t pipelen = conn_temp->send_pipe->size + conn_temp->recv_pipe->size;
6137 if(pipelen > 0) {
6138 infof(data, "Found connection %ld, with requests in the pipe (%zu)\n",
6139 conn_temp->connection_id, pipelen);
6140
6141 if(conn_temp->bundle->num_connections < max_host_connections &&
6142 data->state.conn_cache->num_connections < max_total_connections) {
6143 /* We want a new connection anyway */
6144 reuse = FALSE;
6145
6146 infof(data, "We can reuse, but we want a new connection anyway\n");
6147 }
6148 }
6149 }
6150
6151 if(reuse) {
6152 /*
6153 * We already have a connection for this, we got the former connection
6154 * in the conn_temp variable and thus we need to cleanup the one we
6155 * just allocated before we can move along and use the previously
6156 * existing one.
6157 */
6158 conn_temp->inuse = TRUE; /* mark this as being in use so that no other
6159 handle in a multi stack may nick it */
6160 reuse_conn(conn, conn_temp);
6161 free(conn); /* we don't need this anymore */
6162 conn = conn_temp;
6163 *in_connect = conn;
6164
6165 infof(data, "Re-using existing connection! (#%ld) with %s %s\n",
6166 conn->connection_id,
6167 conn->bits.proxy?"proxy":"host",
6168 conn->proxy.name?conn->proxy.dispname:conn->host.dispname);
6169 }
6170 else {
6171 /* We have decided that we want a new connection. However, we may not
6172 be able to do that if we have reached the limit of how many
6173 connections we are allowed to open. */
6174 struct connectbundle *bundle = NULL;
6175
6176 if(conn->handler->flags & PROTOPT_ALPN_NPN) {
6177 /* The protocol wants it, so set the bits if enabled in the easy handle
6178 (default) */
6179 if(data->set.ssl_enable_alpn)
6180 conn->bits.tls_enable_alpn = TRUE;
6181 if(data->set.ssl_enable_npn)
6182 conn->bits.tls_enable_npn = TRUE;
6183 }
6184
6185 if(waitpipe)
6186 /* There is a connection that *might* become usable for pipelining
6187 "soon", and we wait for that */
6188 connections_available = FALSE;
6189 else
6190 bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache);
6191
6192 if(max_host_connections > 0 && bundle &&
6193 (bundle->num_connections >= max_host_connections)) {
6194 struct connectdata *conn_candidate;
6195
6196 /* The bundle is full. Let's see if we can kill a connection. */
6197 conn_candidate = find_oldest_idle_connection_in_bundle(data, bundle);
6198
6199 if(conn_candidate) {
6200 /* Set the connection's owner correctly, then kill it */
6201 conn_candidate->data = data;
6202 (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
6203 }
6204 else {
6205 infof(data, "No more connections allowed to host: %d\n",
6206 max_host_connections);
6207 connections_available = FALSE;
6208 }
6209 }
6210
6211 if(connections_available &&
6212 (max_total_connections > 0) &&
6213 (data->state.conn_cache->num_connections >= max_total_connections)) {
6214 struct connectdata *conn_candidate;
6215
6216 /* The cache is full. Let's see if we can kill a connection. */
6217 conn_candidate = Curl_oldest_idle_connection(data);
6218
6219 if(conn_candidate) {
6220 /* Set the connection's owner correctly, then kill it */
6221 conn_candidate->data = data;
6222 (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
6223 }
6224 else {
6225 infof(data, "No connections available in cache\n");
6226 connections_available = FALSE;
6227 }
6228 }
6229
6230 if(!connections_available) {
6231 infof(data, "No connections available.\n");
6232
6233 conn_free(conn);
6234 *in_connect = NULL;
6235
6236 result = CURLE_NO_CONNECTION_AVAILABLE;
6237 goto out;
6238 }
6239 else {
6240 /*
6241 * This is a brand new connection, so let's store it in the connection
6242 * cache of ours!
6243 */
6244 Curl_conncache_add_conn(data->state.conn_cache, conn);
6245 }
6246
6247 #if defined(USE_NTLM)
6248 /* If NTLM is requested in a part of this connection, make sure we don't
6249 assume the state is fine as this is a fresh connection and NTLM is
6250 connection based. */
6251 if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
6252 data->state.authhost.done) {
6253 infof(data, "NTLM picked AND auth done set, clear picked!\n");
6254 data->state.authhost.picked = CURLAUTH_NONE;
6255 data->state.authhost.done = FALSE;
6256 }
6257
6258 if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
6259 data->state.authproxy.done) {
6260 infof(data, "NTLM-proxy picked AND auth done set, clear picked!\n");
6261 data->state.authproxy.picked = CURLAUTH_NONE;
6262 data->state.authproxy.done = FALSE;
6263 }
6264 #endif
6265 }
6266
6267 /* Mark the connection as used */
6268 conn->inuse = TRUE;
6269
6270 /* Setup and init stuff before DO starts, in preparing for the transfer. */
6271 Curl_init_do(data, conn);
6272
6273 /*
6274 * Setup whatever necessary for a resumed transfer
6275 */
6276 result = setup_range(data);
6277 if(result)
6278 goto out;
6279
6280 /* Continue connectdata initialization here. */
6281
6282 /*
6283 * Inherit the proper values from the urldata struct AFTER we have arranged
6284 * the persistent connection stuff
6285 */
6286 conn->seek_func = data->set.seek_func;
6287 conn->seek_client = data->set.seek_client;
6288
6289 /*************************************************************
6290 * Resolve the address of the server or proxy
6291 *************************************************************/
6292 result = resolve_server(data, conn, async);
6293
6294 out:
6295
6296 free(options);
6297 free(passwd);
6298 free(user);
6299 free(proxy);
6300 return result;
6301 }
6302
6303 /* Curl_setup_conn() is called after the name resolve initiated in
6304 * create_conn() is all done.
6305 *
6306 * Curl_setup_conn() also handles reused connections
6307 *
6308 * conn->data MUST already have been setup fine (in create_conn)
6309 */
6310
Curl_setup_conn(struct connectdata * conn,bool * protocol_done)6311 CURLcode Curl_setup_conn(struct connectdata *conn,
6312 bool *protocol_done)
6313 {
6314 CURLcode result = CURLE_OK;
6315 struct SessionHandle *data = conn->data;
6316
6317 Curl_pgrsTime(data, TIMER_NAMELOOKUP);
6318
6319 if(conn->handler->flags & PROTOPT_NONETWORK) {
6320 /* nothing to setup when not using a network */
6321 *protocol_done = TRUE;
6322 return result;
6323 }
6324 *protocol_done = FALSE; /* default to not done */
6325
6326 /* set proxy_connect_closed to false unconditionally already here since it
6327 is used strictly to provide extra information to a parent function in the
6328 case of proxy CONNECT failures and we must make sure we don't have it
6329 lingering set from a previous invoke */
6330 conn->bits.proxy_connect_closed = FALSE;
6331
6332 /*
6333 * Set user-agent. Used for HTTP, but since we can attempt to tunnel
6334 * basically anything through a http proxy we can't limit this based on
6335 * protocol.
6336 */
6337 if(data->set.str[STRING_USERAGENT]) {
6338 Curl_safefree(conn->allocptr.uagent);
6339 conn->allocptr.uagent =
6340 aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
6341 if(!conn->allocptr.uagent)
6342 return CURLE_OUT_OF_MEMORY;
6343 }
6344
6345 data->req.headerbytecount = 0;
6346
6347 #ifdef CURL_DO_LINEEND_CONV
6348 data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
6349 #endif /* CURL_DO_LINEEND_CONV */
6350
6351 /* set start time here for timeout purposes in the connect procedure, it
6352 is later set again for the progress meter purpose */
6353 conn->now = Curl_tvnow();
6354
6355 if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
6356 conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
6357 result = Curl_connecthost(conn, conn->dns_entry);
6358 if(result)
6359 return result;
6360 }
6361 else {
6362 Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
6363 Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
6364 conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
6365 *protocol_done = TRUE;
6366 Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]);
6367 Curl_verboseconnect(conn);
6368 }
6369
6370 conn->now = Curl_tvnow(); /* time this *after* the connect is done, we
6371 set this here perhaps a second time */
6372
6373 #ifdef __EMX__
6374 /*
6375 * This check is quite a hack. We're calling _fsetmode to fix the problem
6376 * with fwrite converting newline characters (you get mangled text files,
6377 * and corrupted binary files when you download to stdout and redirect it to
6378 * a file).
6379 */
6380
6381 if((data->set.out)->_handle == NULL) {
6382 _fsetmode(stdout, "b");
6383 }
6384 #endif
6385
6386 return result;
6387 }
6388
Curl_connect(struct SessionHandle * data,struct connectdata ** in_connect,bool * asyncp,bool * protocol_done)6389 CURLcode Curl_connect(struct SessionHandle *data,
6390 struct connectdata **in_connect,
6391 bool *asyncp,
6392 bool *protocol_done)
6393 {
6394 CURLcode result;
6395
6396 *asyncp = FALSE; /* assume synchronous resolves by default */
6397
6398 /* call the stuff that needs to be called */
6399 result = create_conn(data, in_connect, asyncp);
6400
6401 if(!result) {
6402 /* no error */
6403 if((*in_connect)->send_pipe->size || (*in_connect)->recv_pipe->size)
6404 /* pipelining */
6405 *protocol_done = TRUE;
6406 else if(!*asyncp) {
6407 /* DNS resolution is done: that's either because this is a reused
6408 connection, in which case DNS was unnecessary, or because DNS
6409 really did finish already (synch resolver/fast async resolve) */
6410 result = Curl_setup_conn(*in_connect, protocol_done);
6411 }
6412 }
6413
6414 if(result == CURLE_NO_CONNECTION_AVAILABLE) {
6415 *in_connect = NULL;
6416 return result;
6417 }
6418
6419 if(result && *in_connect) {
6420 /* We're not allowed to return failure with memory left allocated
6421 in the connectdata struct, free those here */
6422 Curl_disconnect(*in_connect, FALSE); /* close the connection */
6423 *in_connect = NULL; /* return a NULL */
6424 }
6425
6426 return result;
6427 }
6428
6429 /*
6430 * Curl_init_do() inits the readwrite session. This is inited each time (in
6431 * the DO function before the protocol-specific DO functions are invoked) for
6432 * a transfer, sometimes multiple times on the same SessionHandle. Make sure
6433 * nothing in here depends on stuff that are setup dynamically for the
6434 * transfer.
6435 *
6436 * Allow this function to get called with 'conn' set to NULL.
6437 */
6438
Curl_init_do(struct SessionHandle * data,struct connectdata * conn)6439 CURLcode Curl_init_do(struct SessionHandle *data, struct connectdata *conn)
6440 {
6441 struct SingleRequest *k = &data->req;
6442
6443 if(conn)
6444 conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
6445 * use */
6446
6447 data->state.done = FALSE; /* *_done() is not called yet */
6448 data->state.expect100header = FALSE;
6449
6450 if(data->set.opt_no_body)
6451 /* in HTTP lingo, no body means using the HEAD request... */
6452 data->set.httpreq = HTTPREQ_HEAD;
6453 else if(HTTPREQ_HEAD == data->set.httpreq)
6454 /* ... but if unset there really is no perfect method that is the
6455 "opposite" of HEAD but in reality most people probably think GET
6456 then. The important thing is that we can't let it remain HEAD if the
6457 opt_no_body is set FALSE since then we'll behave wrong when getting
6458 HTTP. */
6459 data->set.httpreq = HTTPREQ_GET;
6460
6461 k->start = Curl_tvnow(); /* start time */
6462 k->now = k->start; /* current time is now */
6463 k->header = TRUE; /* assume header */
6464
6465 k->bytecount = 0;
6466
6467 k->buf = data->state.buffer;
6468 k->uploadbuf = data->state.uploadbuffer;
6469 k->hbufp = data->state.headerbuff;
6470 k->ignorebody=FALSE;
6471
6472 Curl_speedinit(data);
6473
6474 Curl_pgrsSetUploadCounter(data, 0);
6475 Curl_pgrsSetDownloadCounter(data, 0);
6476
6477 return CURLE_OK;
6478 }
6479
6480 /*
6481 * get_protocol_family()
6482 *
6483 * This is used to return the protocol family for a given protocol.
6484 *
6485 * Parameters:
6486 *
6487 * protocol [in] - A single bit protocol identifier such as HTTP or HTTPS.
6488 *
6489 * Returns the family as a single bit protocol identifier.
6490 */
6491
get_protocol_family(unsigned int protocol)6492 unsigned int get_protocol_family(unsigned int protocol)
6493 {
6494 unsigned int family;
6495
6496 switch(protocol) {
6497 case CURLPROTO_HTTP:
6498 case CURLPROTO_HTTPS:
6499 family = CURLPROTO_HTTP;
6500 break;
6501
6502 case CURLPROTO_FTP:
6503 case CURLPROTO_FTPS:
6504 family = CURLPROTO_FTP;
6505 break;
6506
6507 case CURLPROTO_SCP:
6508 family = CURLPROTO_SCP;
6509 break;
6510
6511 case CURLPROTO_SFTP:
6512 family = CURLPROTO_SFTP;
6513 break;
6514
6515 case CURLPROTO_TELNET:
6516 family = CURLPROTO_TELNET;
6517 break;
6518
6519 case CURLPROTO_LDAP:
6520 case CURLPROTO_LDAPS:
6521 family = CURLPROTO_LDAP;
6522 break;
6523
6524 case CURLPROTO_DICT:
6525 family = CURLPROTO_DICT;
6526 break;
6527
6528 case CURLPROTO_FILE:
6529 family = CURLPROTO_FILE;
6530 break;
6531
6532 case CURLPROTO_TFTP:
6533 family = CURLPROTO_TFTP;
6534 break;
6535
6536 case CURLPROTO_IMAP:
6537 case CURLPROTO_IMAPS:
6538 family = CURLPROTO_IMAP;
6539 break;
6540
6541 case CURLPROTO_POP3:
6542 case CURLPROTO_POP3S:
6543 family = CURLPROTO_POP3;
6544 break;
6545
6546 case CURLPROTO_SMTP:
6547 case CURLPROTO_SMTPS:
6548 family = CURLPROTO_SMTP;
6549 break;
6550
6551 case CURLPROTO_RTSP:
6552 family = CURLPROTO_RTSP;
6553 break;
6554
6555 case CURLPROTO_RTMP:
6556 case CURLPROTO_RTMPS:
6557 family = CURLPROTO_RTMP;
6558 break;
6559
6560 case CURLPROTO_RTMPT:
6561 case CURLPROTO_RTMPTS:
6562 family = CURLPROTO_RTMPT;
6563 break;
6564
6565 case CURLPROTO_RTMPE:
6566 family = CURLPROTO_RTMPE;
6567 break;
6568
6569 case CURLPROTO_RTMPTE:
6570 family = CURLPROTO_RTMPTE;
6571 break;
6572
6573 case CURLPROTO_GOPHER:
6574 family = CURLPROTO_GOPHER;
6575 break;
6576
6577 case CURLPROTO_SMB:
6578 case CURLPROTO_SMBS:
6579 family = CURLPROTO_SMB;
6580 break;
6581
6582 default:
6583 family = 0;
6584 break;
6585 }
6586
6587 return family;
6588 }
6589