1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
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_IPHLPAPI_H
38#include <Iphlpapi.h>
39#endif
40#ifdef HAVE_SYS_IOCTL_H
41#include <sys/ioctl.h>
42#endif
43#ifdef HAVE_SYS_PARAM_H
44#include <sys/param.h>
45#endif
46
47#ifdef __VMS
48#include <in.h>
49#include <inet.h>
50#endif
51
52#ifdef HAVE_SYS_UN_H
53#include <sys/un.h>
54#endif
55
56#ifndef HAVE_SOCKET
57#error "We can't compile without socket() support!"
58#endif
59
60#include <limits.h>
61
62#ifdef USE_LIBIDN2
63#include <idn2.h>
64
65#if defined(WIN32) && defined(UNICODE)
66#define IDN2_LOOKUP(name, host, flags) \
67 idn2_lookup_u8((const uint8_t *)name, (uint8_t **)host, flags)
68#else
69#define IDN2_LOOKUP(name, host, flags) \
70 idn2_lookup_ul((const char *)name, (char **)host, flags)
71#endif
72
73#elif defined(USE_WIN32_IDN)
74/* prototype for curl_win32_idn_to_ascii() */
75bool curl_win32_idn_to_ascii(const char *in, char **out);
76#endif /* USE_LIBIDN2 */
77
78#include "urldata.h"
79#include "netrc.h"
80
81#include "formdata.h"
82#include "mime.h"
83#include "vtls/vtls.h"
84#include "hostip.h"
85#include "transfer.h"
86#include "sendf.h"
87#include "progress.h"
88#include "cookie.h"
89#include "strcase.h"
90#include "strerror.h"
91#include "escape.h"
92#include "strtok.h"
93#include "share.h"
94#include "content_encoding.h"
95#include "http_digest.h"
96#include "http_negotiate.h"
97#include "select.h"
98#include "multiif.h"
99#include "easyif.h"
100#include "speedcheck.h"
101#include "warnless.h"
102#include "non-ascii.h"
103#include "getinfo.h"
104#include "urlapi-int.h"
105#include "system_win32.h"
106#include "hsts.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 "vssh/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_rtmp.h"
124#include "gopher.h"
125#include "mqtt.h"
126#include "http_proxy.h"
127#include "conncache.h"
128#include "multihandle.h"
129#include "dotdot.h"
130#include "strdup.h"
131#include "setopt.h"
132#include "altsvc.h"
133#include "dynbuf.h"
134
135/* The last 3 #include files should be in this order */
136#include "curl_printf.h"
137#include "curl_memory.h"
138#include "memdebug.h"
139
140static void conn_free(struct connectdata *conn);
141
142/* Some parts of the code (e.g. chunked encoding) assume this buffer has at
143 * more than just a few bytes to play with. Don't let it become too small or
144 * bad things will happen.
145 */
146#if READBUFFER_SIZE < READBUFFER_MIN
147# error READBUFFER_SIZE is too small
148#endif
149
150/*
151* get_protocol_family()
152*
153* This is used to return the protocol family for a given protocol.
154*
155* Parameters:
156*
157* 'h' [in] - struct Curl_handler pointer.
158*
159* Returns the family as a single bit protocol identifier.
160*/
161static unsigned int get_protocol_family(const struct Curl_handler *h)
162{
163 DEBUGASSERT(h);
164 DEBUGASSERT(h->family);
165 return h->family;
166}
167
168
169/*
170 * Protocol table. Schemes (roughly) in 2019 popularity order:
171 *
172 * HTTPS, HTTP, FTP, FTPS, SFTP, FILE, SCP, SMTP, LDAP, IMAPS, TELNET, IMAP,
173 * LDAPS, SMTPS, TFTP, SMB, POP3, GOPHER POP3S, RTSP, RTMP, SMBS, DICT
174 */
175static const struct Curl_handler * const protocols[] = {
176
177#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
178 &Curl_handler_https,
179#endif
180
181#ifndef CURL_DISABLE_HTTP
182 &Curl_handler_http,
183#endif
184
185#ifndef CURL_DISABLE_FTP
186 &Curl_handler_ftp,
187#endif
188
189#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
190 &Curl_handler_ftps,
191#endif
192
193#if defined(USE_SSH)
194 &Curl_handler_sftp,
195#endif
196
197#ifndef CURL_DISABLE_FILE
198 &Curl_handler_file,
199#endif
200
201#if defined(USE_SSH) && !defined(USE_WOLFSSH)
202 &Curl_handler_scp,
203#endif
204
205#ifndef CURL_DISABLE_SMTP
206 &Curl_handler_smtp,
207#ifdef USE_SSL
208 &Curl_handler_smtps,
209#endif
210#endif
211
212#ifndef CURL_DISABLE_LDAP
213 &Curl_handler_ldap,
214#if !defined(CURL_DISABLE_LDAPS) && \
215 ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
216 (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
217 &Curl_handler_ldaps,
218#endif
219#endif
220
221#ifndef CURL_DISABLE_IMAP
222 &Curl_handler_imap,
223#ifdef USE_SSL
224 &Curl_handler_imaps,
225#endif
226#endif
227
228#ifndef CURL_DISABLE_TELNET
229 &Curl_handler_telnet,
230#endif
231
232#ifndef CURL_DISABLE_TFTP
233 &Curl_handler_tftp,
234#endif
235
236#ifndef CURL_DISABLE_POP3
237 &Curl_handler_pop3,
238#ifdef USE_SSL
239 &Curl_handler_pop3s,
240#endif
241#endif
242
243#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
244 (SIZEOF_CURL_OFF_T > 4)
245 &Curl_handler_smb,
246#ifdef USE_SSL
247 &Curl_handler_smbs,
248#endif
249#endif
250
251#ifndef CURL_DISABLE_RTSP
252 &Curl_handler_rtsp,
253#endif
254
255#ifndef CURL_DISABLE_MQTT
256 &Curl_handler_mqtt,
257#endif
258
259#ifndef CURL_DISABLE_GOPHER
260 &Curl_handler_gopher,
261#ifdef USE_SSL
262 &Curl_handler_gophers,
263#endif
264#endif
265
266#ifdef USE_LIBRTMP
267 &Curl_handler_rtmp,
268 &Curl_handler_rtmpt,
269 &Curl_handler_rtmpe,
270 &Curl_handler_rtmpte,
271 &Curl_handler_rtmps,
272 &Curl_handler_rtmpts,
273#endif
274
275#ifndef CURL_DISABLE_DICT
276 &Curl_handler_dict,
277#endif
278
279 (struct Curl_handler *) NULL
280};
281
282/*
283 * Dummy handler for undefined protocol schemes.
284 */
285
286static const struct Curl_handler Curl_handler_dummy = {
287 "<no protocol>", /* scheme */
288 ZERO_NULL, /* setup_connection */
289 ZERO_NULL, /* do_it */
290 ZERO_NULL, /* done */
291 ZERO_NULL, /* do_more */
292 ZERO_NULL, /* connect_it */
293 ZERO_NULL, /* connecting */
294 ZERO_NULL, /* doing */
295 ZERO_NULL, /* proto_getsock */
296 ZERO_NULL, /* doing_getsock */
297 ZERO_NULL, /* domore_getsock */
298 ZERO_NULL, /* perform_getsock */
299 ZERO_NULL, /* disconnect */
300 ZERO_NULL, /* readwrite */
301 ZERO_NULL, /* connection_check */
302 ZERO_NULL, /* attach connection */
303 0, /* defport */
304 0, /* protocol */
305 0, /* family */
306 PROTOPT_NONE /* flags */
307};
308
309void Curl_freeset(struct Curl_easy *data)
310{
311 /* Free all dynamic strings stored in the data->set substructure. */
312 enum dupstring i;
313 enum dupblob j;
314
315 for(i = (enum dupstring)0; i < STRING_LAST; i++) {
316 Curl_safefree(data->set.str[i]);
317 }
318
319 for(j = (enum dupblob)0; j < BLOB_LAST; j++) {
320 Curl_safefree(data->set.blobs[j]);
321 }
322
323 if(data->state.referer_alloc) {
324 Curl_safefree(data->state.referer);
325 data->state.referer_alloc = FALSE;
326 }
327 data->state.referer = NULL;
328 if(data->state.url_alloc) {
329 Curl_safefree(data->state.url);
330 data->state.url_alloc = FALSE;
331 }
332 data->state.url = NULL;
333
334 Curl_mime_cleanpart(&data->set.mimepost);
335}
336
337/* free the URL pieces */
338static void up_free(struct Curl_easy *data)
339{
340 struct urlpieces *up = &data->state.up;
341 Curl_safefree(up->scheme);
342 Curl_safefree(up->hostname);
343 Curl_safefree(up->port);
344 Curl_safefree(up->user);
345 Curl_safefree(up->password);
346 Curl_safefree(up->options);
347 Curl_safefree(up->path);
348 Curl_safefree(up->query);
349 curl_url_cleanup(data->state.uh);
350 data->state.uh = NULL;
351}
352
353/*
354 * This is the internal function curl_easy_cleanup() calls. This should
355 * cleanup and free all resources associated with this sessionhandle.
356 *
357 * NOTE: if we ever add something that attempts to write to a socket or
358 * similar here, we must ignore SIGPIPE first. It is currently only done
359 * when curl_easy_perform() is invoked.
360 */
361
362CURLcode Curl_close(struct Curl_easy **datap)
363{
364 struct Curl_multi *m;
365 struct Curl_easy *data;
366
367 if(!datap || !*datap)
368 return CURLE_OK;
369
370 data = *datap;
371 *datap = NULL;
372
373 Curl_expire_clear(data); /* shut off timers */
374
375 /* Detach connection if any is left. This should not be normal, but can be
376 the case for example with CONNECT_ONLY + recv/send (test 556) */
377 Curl_detach_connnection(data);
378 m = data->multi;
379 if(m)
380 /* This handle is still part of a multi handle, take care of this first
381 and detach this handle from there. */
382 curl_multi_remove_handle(data->multi, data);
383
384 if(data->multi_easy) {
385 /* when curl_easy_perform() is used, it creates its own multi handle to
386 use and this is the one */
387 curl_multi_cleanup(data->multi_easy);
388 data->multi_easy = NULL;
389 }
390
391 /* Destroy the timeout list that is held in the easy handle. It is
392 /normally/ done by curl_multi_remove_handle() but this is "just in
393 case" */
394 Curl_llist_destroy(&data->state.timeoutlist, NULL);
395
396 data->magic = 0; /* force a clear AFTER the possibly enforced removal from
397 the multi handle, since that function uses the magic
398 field! */
399
400 if(data->state.rangestringalloc)
401 free(data->state.range);
402
403 /* freed here just in case DONE wasn't called */
404 Curl_free_request_state(data);
405
406 /* Close down all open SSL info and sessions */
407 Curl_ssl_close_all(data);
408 Curl_safefree(data->state.first_host);
409 Curl_safefree(data->state.scratch);
410 Curl_ssl_free_certinfo(data);
411
412 /* Cleanup possible redirect junk */
413 free(data->req.newurl);
414 data->req.newurl = NULL;
415
416 if(data->state.referer_alloc) {
417 Curl_safefree(data->state.referer);
418 data->state.referer_alloc = FALSE;
419 }
420 data->state.referer = NULL;
421
422 up_free(data);
423 Curl_safefree(data->state.buffer);
424 Curl_dyn_free(&data->state.headerb);
425 Curl_safefree(data->state.ulbuf);
426 Curl_flush_cookies(data, TRUE);
427 Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]);
428 Curl_altsvc_cleanup(&data->asi);
429 Curl_hsts_save(data, data->hsts, data->set.str[STRING_HSTS]);
430 Curl_hsts_cleanup(&data->hsts);
431#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
432 Curl_http_auth_cleanup_digest(data);
433#endif
434 Curl_safefree(data->info.contenttype);
435 Curl_safefree(data->info.wouldredirect);
436
437 /* this destroys the channel and we cannot use it anymore after this */
438 Curl_resolver_cleanup(data->state.async.resolver);
439
440 Curl_http2_cleanup_dependencies(data);
441 Curl_convert_close(data);
442
443 /* No longer a dirty share, if it exists */
444 if(data->share) {
445 Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
446 data->share->dirty--;
447 Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
448 }
449
450 Curl_safefree(data->state.aptr.proxyuserpwd);
451 Curl_safefree(data->state.aptr.uagent);
452 Curl_safefree(data->state.aptr.userpwd);
453 Curl_safefree(data->state.aptr.accept_encoding);
454 Curl_safefree(data->state.aptr.te);
455 Curl_safefree(data->state.aptr.rangeline);
456 Curl_safefree(data->state.aptr.ref);
457 Curl_safefree(data->state.aptr.host);
458 Curl_safefree(data->state.aptr.cookiehost);
459 Curl_safefree(data->state.aptr.rtsp_transport);
460 Curl_safefree(data->state.aptr.user);
461 Curl_safefree(data->state.aptr.passwd);
462 Curl_safefree(data->state.aptr.proxyuser);
463 Curl_safefree(data->state.aptr.proxypasswd);
464
465#ifndef CURL_DISABLE_DOH
466 if(data->req.doh) {
467 Curl_dyn_free(&data->req.doh->probe[0].serverdoh);
468 Curl_dyn_free(&data->req.doh->probe[1].serverdoh);
469 curl_slist_free_all(data->req.doh->headers);
470 Curl_safefree(data->req.doh);
471 }
472#endif
473
474 /* destruct wildcard structures if it is needed */
475 Curl_wildcard_dtor(&data->wildcard);
476 Curl_freeset(data);
477 free(data);
478 return CURLE_OK;
479}
480
481/*
482 * Initialize the UserDefined fields within a Curl_easy.
483 * This may be safely called on a new or existing Curl_easy.
484 */
485CURLcode Curl_init_userdefined(struct Curl_easy *data)
486{
487 struct UserDefined *set = &data->set;
488 CURLcode result = CURLE_OK;
489
490 set->out = stdout; /* default output to stdout */
491 set->in_set = stdin; /* default input from stdin */
492 set->err = stderr; /* default stderr to stderr */
493
494 /* use fwrite as default function to store output */
495 set->fwrite_func = (curl_write_callback)fwrite;
496
497 /* use fread as default function to read input */
498 set->fread_func_set = (curl_read_callback)fread;
499 set->is_fread_set = 0;
500 set->is_fwrite_set = 0;
501
502 set->seek_func = ZERO_NULL;
503 set->seek_client = ZERO_NULL;
504
505 /* conversion callbacks for non-ASCII hosts */
506 set->convfromnetwork = ZERO_NULL;
507 set->convtonetwork = ZERO_NULL;
508 set->convfromutf8 = ZERO_NULL;
509
510 set->filesize = -1; /* we don't know the size */
511 set->postfieldsize = -1; /* unknown size */
512 set->maxredirs = -1; /* allow any amount by default */
513
514 set->method = HTTPREQ_GET; /* Default HTTP request */
515 set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */
516#ifndef CURL_DISABLE_FTP
517 set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
518 set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
519 set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */
520 set->ftp_filemethod = FTPFILE_MULTICWD;
521 set->ftp_skip_ip = TRUE; /* skip PASV IP by default */
522#endif
523 set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
524
525 /* Set the default size of the SSL session ID cache */
526 set->general_ssl.max_ssl_sessions = 5;
527
528 set->proxyport = 0;
529 set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
530 set->httpauth = CURLAUTH_BASIC; /* defaults to basic */
531 set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
532
533 /* SOCKS5 proxy auth defaults to username/password + GSS-API */
534 set->socks5auth = CURLAUTH_BASIC | CURLAUTH_GSSAPI;
535
536 /* make libcurl quiet by default: */
537 set->hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
538
539 Curl_mime_initpart(&set->mimepost, data);
540
541 /*
542 * libcurl 7.10 introduced SSL verification *by default*! This needs to be
543 * switched off unless wanted.
544 */
545 set->doh_verifyhost = TRUE;
546 set->doh_verifypeer = TRUE;
547 set->ssl.primary.verifypeer = TRUE;
548 set->ssl.primary.verifyhost = TRUE;
549#ifdef USE_TLS_SRP
550 set->ssl.authtype = CURL_TLSAUTH_NONE;
551#endif
552 set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
553 type */
554 set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by
555 default */
556#ifndef CURL_DISABLE_PROXY
557 set->proxy_ssl = set->ssl;
558#endif
559
560 set->new_file_perms = 0644; /* Default permissions */
561 set->new_directory_perms = 0755; /* Default permissions */
562
563 /* for the *protocols fields we don't use the CURLPROTO_ALL convenience
564 define since we internally only use the lower 16 bits for the passed
565 in bitmask to not conflict with the private bits */
566 set->allowed_protocols = CURLPROTO_ALL;
567 set->redir_protocols = CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP |
568 CURLPROTO_FTPS;
569
570#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
571 /*
572 * disallow unprotected protection negotiation NEC reference implementation
573 * seem not to follow rfc1961 section 4.3/4.4
574 */
575 set->socks5_gssapi_nec = FALSE;
576#endif
577
578 /* Set the default CA cert bundle/path detected/specified at build time.
579 *
580 * If Schannel is the selected SSL backend then these locations are
581 * ignored. We allow setting CA location for schannel only when explicitly
582 * specified by the user via CURLOPT_CAINFO / --cacert.
583 */
584 if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
585#if defined(CURL_CA_BUNDLE)
586 result = Curl_setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
587 if(result)
588 return result;
589
590 result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY],
591 CURL_CA_BUNDLE);
592 if(result)
593 return result;
594#endif
595#if defined(CURL_CA_PATH)
596 result = Curl_setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
597 if(result)
598 return result;
599
600 result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
601 if(result)
602 return result;
603#endif
604 }
605
606 set->wildcard_enabled = FALSE;
607 set->chunk_bgn = ZERO_NULL;
608 set->chunk_end = ZERO_NULL;
609 set->tcp_keepalive = FALSE;
610 set->tcp_keepintvl = 60;
611 set->tcp_keepidle = 60;
612 set->tcp_fastopen = FALSE;
613 set->tcp_nodelay = TRUE;
614 set->ssl_enable_npn = TRUE;
615 set->ssl_enable_alpn = TRUE;
616 set->expect_100_timeout = 1000L; /* Wait for a second by default. */
617 set->sep_headers = TRUE; /* separated header lists by default */
618 set->buffer_size = READBUFFER_SIZE;
619 set->upload_buffer_size = UPLOADBUFFER_DEFAULT;
620 set->happy_eyeballs_timeout = CURL_HET_DEFAULT;
621 set->fnmatch = ZERO_NULL;
622 set->upkeep_interval_ms = CURL_UPKEEP_INTERVAL_DEFAULT;
623 set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
624 set->maxage_conn = 118;
625 set->http09_allowed = FALSE;
626 set->httpwant =
627#ifdef USE_NGHTTP2
628 CURL_HTTP_VERSION_2TLS
629#else
630 CURL_HTTP_VERSION_1_1
631#endif
632 ;
633 Curl_http2_init_userset(set);
634 return result;
635}
636
637/**
638 * Curl_open()
639 *
640 * @param curl is a pointer to a sessionhandle pointer that gets set by this
641 * function.
642 * @return CURLcode
643 */
644
645CURLcode Curl_open(struct Curl_easy **curl)
646{
647 CURLcode result;
648 struct Curl_easy *data;
649
650 /* Very simple start-up: alloc the struct, init it with zeroes and return */
651 data = calloc(1, sizeof(struct Curl_easy));
652 if(!data) {
653 /* this is a very serious error */
654 DEBUGF(fprintf(stderr, "Error: calloc of Curl_easy failed\n"));
655 return CURLE_OUT_OF_MEMORY;
656 }
657
658 data->magic = CURLEASY_MAGIC_NUMBER;
659
660 result = Curl_resolver_init(data, &data->state.async.resolver);
661 if(result) {
662 DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
663 free(data);
664 return result;
665 }
666
667 result = Curl_init_userdefined(data);
668 if(!result) {
669 Curl_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER);
670 Curl_convert_init(data);
671 Curl_initinfo(data);
672
673 /* most recent connection is not yet defined */
674 data->state.lastconnect_id = -1;
675
676 data->progress.flags |= PGRS_HIDE;
677 data->state.current_speed = -1; /* init to negative == impossible */
678 }
679
680 if(result) {
681 Curl_resolver_cleanup(data->state.async.resolver);
682 Curl_dyn_free(&data->state.headerb);
683 Curl_freeset(data);
684 free(data);
685 data = NULL;
686 }
687 else
688 *curl = data;
689
690 return result;
691}
692
693#ifdef USE_RECV_BEFORE_SEND_WORKAROUND
694static void conn_reset_postponed_data(struct connectdata *conn, int num)
695{
696 struct postponed_data * const psnd = &(conn->postponed[num]);
697 if(psnd->buffer) {
698 DEBUGASSERT(psnd->allocated_size > 0);
699 DEBUGASSERT(psnd->recv_size <= psnd->allocated_size);
700 DEBUGASSERT(psnd->recv_size ?
701 (psnd->recv_processed < psnd->recv_size) :
702 (psnd->recv_processed == 0));
703 DEBUGASSERT(psnd->bindsock != CURL_SOCKET_BAD);
704 free(psnd->buffer);
705 psnd->buffer = NULL;
706 psnd->allocated_size = 0;
707 psnd->recv_size = 0;
708 psnd->recv_processed = 0;
709#ifdef DEBUGBUILD
710 psnd->bindsock = CURL_SOCKET_BAD; /* used only for DEBUGASSERT */
711#endif /* DEBUGBUILD */
712 }
713 else {
714 DEBUGASSERT(psnd->allocated_size == 0);
715 DEBUGASSERT(psnd->recv_size == 0);
716 DEBUGASSERT(psnd->recv_processed == 0);
717 DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD);
718 }
719}
720
721static void conn_reset_all_postponed_data(struct connectdata *conn)
722{
723 conn_reset_postponed_data(conn, 0);
724 conn_reset_postponed_data(conn, 1);
725}
726#else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
727/* Use "do-nothing" macro instead of function when workaround not used */
728#define conn_reset_all_postponed_data(c) do {} while(0)
729#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
730
731
732static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn)
733{
734 DEBUGASSERT(conn);
735 DEBUGASSERT(data);
736 infof(data, "Closing connection %ld", conn->connection_id);
737
738#ifndef USE_HYPER
739 if(conn->connect_state && conn->connect_state->prot_save) {
740 /* If this was closed with a CONNECT in progress, cleanup this temporary
741 struct arrangement */
742 data->req.p.http = NULL;
743 Curl_safefree(conn->connect_state->prot_save);
744 }
745#endif
746
747 /* possible left-overs from the async name resolvers */
748 Curl_resolver_cancel(data);
749
750 /* close the SSL stuff before we close any sockets since they will/may
751 write to the sockets */
752 Curl_ssl_close(data, conn, FIRSTSOCKET);
753 Curl_ssl_close(data, conn, SECONDARYSOCKET);
754
755 /* close possibly still open sockets */
756 if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
757 Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]);
758 if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
759 Curl_closesocket(data, conn, conn->sock[FIRSTSOCKET]);
760 if(CURL_SOCKET_BAD != conn->tempsock[0])
761 Curl_closesocket(data, conn, conn->tempsock[0]);
762 if(CURL_SOCKET_BAD != conn->tempsock[1])
763 Curl_closesocket(data, conn, conn->tempsock[1]);
764}
765
766static void conn_free(struct connectdata *conn)
767{
768 DEBUGASSERT(conn);
769
770 Curl_free_idnconverted_hostname(&conn->host);
771 Curl_free_idnconverted_hostname(&conn->conn_to_host);
772#ifndef CURL_DISABLE_PROXY
773 Curl_free_idnconverted_hostname(&conn->http_proxy.host);
774 Curl_free_idnconverted_hostname(&conn->socks_proxy.host);
775 Curl_safefree(conn->http_proxy.user);
776 Curl_safefree(conn->socks_proxy.user);
777 Curl_safefree(conn->http_proxy.passwd);
778 Curl_safefree(conn->socks_proxy.passwd);
779 Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
780 Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
781 Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
782#endif
783 Curl_safefree(conn->user);
784 Curl_safefree(conn->passwd);
785 Curl_safefree(conn->sasl_authzid);
786 Curl_safefree(conn->options);
787 Curl_dyn_free(&conn->trailer);
788 Curl_safefree(conn->host.rawalloc); /* host name buffer */
789 Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
790 Curl_safefree(conn->hostname_resolve);
791 Curl_safefree(conn->secondaryhostname);
792 Curl_safefree(conn->connect_state);
793
794 conn_reset_all_postponed_data(conn);
795 Curl_llist_destroy(&conn->easyq, NULL);
796 Curl_safefree(conn->localdev);
797 Curl_free_primary_ssl_config(&conn->ssl_config);
798
799#ifdef USE_UNIX_SOCKETS
800 Curl_safefree(conn->unix_domain_socket);
801#endif
802
803#ifdef USE_SSL
804 Curl_safefree(conn->ssl_extra);
805#endif
806 free(conn); /* free all the connection oriented data */
807}
808
809/*
810 * Disconnects the given connection. Note the connection may not be the
811 * primary connection, like when freeing room in the connection cache or
812 * killing of a dead old connection.
813 *
814 * A connection needs an easy handle when closing down. We support this passed
815 * in separately since the connection to get closed here is often already
816 * disassociated from an easy handle.
817 *
818 * This function MUST NOT reset state in the Curl_easy struct if that
819 * isn't strictly bound to the life-time of *this* particular connection.
820 *
821 */
822
823CURLcode Curl_disconnect(struct Curl_easy *data,
824 struct connectdata *conn, bool dead_connection)
825{
826 /* there must be a connection to close */
827 DEBUGASSERT(conn);
828
829 /* it must be removed from the connection cache */
830 DEBUGASSERT(!conn->bundle);
831
832 /* there must be an associated transfer */
833 DEBUGASSERT(data);
834
835 /* the transfer must be detached from the connection */
836 DEBUGASSERT(!data->conn);
837
838 /*
839 * If this connection isn't marked to force-close, leave it open if there
840 * are other users of it
841 */
842 if(CONN_INUSE(conn) && !dead_connection) {
843 DEBUGF(infof(data, "Curl_disconnect when inuse: %zu", CONN_INUSE(conn)));
844 return CURLE_OK;
845 }
846
847 if(conn->dns_entry != NULL) {
848 Curl_resolv_unlock(data, conn->dns_entry);
849 conn->dns_entry = NULL;
850 }
851
852 /* Cleanup NTLM connection-related data */
853 Curl_http_auth_cleanup_ntlm(conn);
854
855 /* Cleanup NEGOTIATE connection-related data */
856 Curl_http_auth_cleanup_negotiate(conn);
857
858 if(conn->bits.connect_only)
859 /* treat the connection as dead in CONNECT_ONLY situations */
860 dead_connection = TRUE;
861
862 /* temporarily attach the connection to this transfer handle for the
863 disconnect and shutdown */
864 Curl_attach_connnection(data, conn);
865
866 if(conn->handler->disconnect)
867 /* This is set if protocol-specific cleanups should be made */
868 conn->handler->disconnect(data, conn, dead_connection);
869
870 conn_shutdown(data, conn);
871
872 /* detach it again */
873 Curl_detach_connnection(data);
874
875 conn_free(conn);
876 return CURLE_OK;
877}
878
879/*
880 * This function should return TRUE if the socket is to be assumed to
881 * be dead. Most commonly this happens when the server has closed the
882 * connection due to inactivity.
883 */
884static bool SocketIsDead(curl_socket_t sock)
885{
886 int sval;
887 bool ret_val = TRUE;
888
889 sval = SOCKET_READABLE(sock, 0);
890 if(sval == 0)
891 /* timeout */
892 ret_val = FALSE;
893
894 return ret_val;
895}
896
897/*
898 * IsMultiplexingPossible()
899 *
900 * Return a bitmask with the available multiplexing options for the given
901 * requested connection.
902 */
903static int IsMultiplexingPossible(const struct Curl_easy *handle,
904 const struct connectdata *conn)
905{
906 int avail = 0;
907
908 /* If a HTTP protocol and multiplexing is enabled */
909 if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
910 (!conn->bits.protoconnstart || !conn->bits.close)) {
911
912 if(Curl_multiplex_wanted(handle->multi) &&
913 (handle->state.httpwant >= CURL_HTTP_VERSION_2))
914 /* allows HTTP/2 */
915 avail |= CURLPIPE_MULTIPLEX;
916 }
917 return avail;
918}
919
920#ifndef CURL_DISABLE_PROXY
921static bool
922proxy_info_matches(const struct proxy_info *data,
923 const struct proxy_info *needle)
924{
925 if((data->proxytype == needle->proxytype) &&
926 (data->port == needle->port) &&
927 Curl_safe_strcasecompare(data->host.name, needle->host.name))
928 return TRUE;
929
930 return FALSE;
931}
932
933static bool
934socks_proxy_info_matches(const struct proxy_info *data,
935 const struct proxy_info *needle)
936{
937 if(!proxy_info_matches(data, needle))
938 return FALSE;
939
940 /* the user information is case-sensitive
941 or at least it is not defined as case-insensitive
942 see https://tools.ietf.org/html/rfc3986#section-3.2.1 */
943 if(!data->user != !needle->user)
944 return FALSE;
945 /* curl_strequal does a case insentive comparison, so do not use it here! */
946 if(data->user &&
947 needle->user &&
948 strcmp(data->user, needle->user) != 0)
949 return FALSE;
950 if(!data->passwd != !needle->passwd)
951 return FALSE;
952 /* curl_strequal does a case insentive comparison, so do not use it here! */
953 if(data->passwd &&
954 needle->passwd &&
955 strcmp(data->passwd, needle->passwd) != 0)
956 return FALSE;
957 return TRUE;
958}
959#else
960/* disabled, won't get called */
961#define proxy_info_matches(x,y) FALSE
962#define socks_proxy_info_matches(x,y) FALSE
963#endif
964
965/* A connection has to have been idle for a shorter time than 'maxage_conn' to
966 be subject for reuse. The success rate is just too low after this. */
967
968static bool conn_maxage(struct Curl_easy *data,
969 struct connectdata *conn,
970 struct curltime now)
971{
972 timediff_t idletime = Curl_timediff(now, conn->lastused);
973 idletime /= 1000; /* integer seconds is fine */
974
975 if(idletime > data->set.maxage_conn) {
976 infof(data, "Too old connection (%ld seconds), disconnect it",
977 idletime);
978 return TRUE;
979 }
980 return FALSE;
981}
982
983/*
984 * This function checks if the given connection is dead and extracts it from
985 * the connection cache if so.
986 *
987 * When this is called as a Curl_conncache_foreach() callback, the connection
988 * cache lock is held!
989 *
990 * Returns TRUE if the connection was dead and extracted.
991 */
992static bool extract_if_dead(struct connectdata *conn,
993 struct Curl_easy *data)
994{
995 if(!CONN_INUSE(conn)) {
996 /* The check for a dead socket makes sense only if the connection isn't in
997 use */
998 bool dead;
999 struct curltime now = Curl_now();
1000 if(conn_maxage(data, conn, now)) {
1001 /* avoid check if already too old */
1002 dead = TRUE;
1003 }
1004 else if(conn->handler->connection_check) {
1005 /* The protocol has a special method for checking the state of the
1006 connection. Use it to check if the connection is dead. */
1007 unsigned int state;
1008
1009 /* briefly attach the connection to this transfer for the purpose of
1010 checking it */
1011 Curl_attach_connnection(data, conn);
1012
1013 state = conn->handler->connection_check(data, conn, CONNCHECK_ISDEAD);
1014 dead = (state & CONNRESULT_DEAD);
1015 /* detach the connection again */
1016 Curl_detach_connnection(data);
1017
1018 }
1019 else {
1020 /* Use the general method for determining the death of a connection */
1021 dead = SocketIsDead(conn->sock[FIRSTSOCKET]);
1022 }
1023
1024 if(dead) {
1025 infof(data, "Connection %ld seems to be dead!", conn->connection_id);
1026 Curl_conncache_remove_conn(data, conn, FALSE);
1027 return TRUE;
1028 }
1029 }
1030 return FALSE;
1031}
1032
1033struct prunedead {
1034 struct Curl_easy *data;
1035 struct connectdata *extracted;
1036};
1037
1038/*
1039 * Wrapper to use extract_if_dead() function in Curl_conncache_foreach()
1040 *
1041 */
1042static int call_extract_if_dead(struct Curl_easy *data,
1043 struct connectdata *conn, void *param)
1044{
1045 struct prunedead *p = (struct prunedead *)param;
1046 if(extract_if_dead(conn, data)) {
1047 /* stop the iteration here, pass back the connection that was extracted */
1048 p->extracted = conn;
1049 return 1;
1050 }
1051 return 0; /* continue iteration */
1052}
1053
1054/*
1055 * This function scans the connection cache for half-open/dead connections,
1056 * closes and removes them. The cleanup is done at most once per second.
1057 *
1058 * When called, this transfer has no connection attached.
1059 */
1060static void prune_dead_connections(struct Curl_easy *data)
1061{
1062 struct curltime now = Curl_now();
1063 timediff_t elapsed;
1064
1065 DEBUGASSERT(!data->conn); /* no connection */
1066 CONNCACHE_LOCK(data);
1067 elapsed =
1068 Curl_timediff(now, data->state.conn_cache->last_cleanup);
1069 CONNCACHE_UNLOCK(data);
1070
1071 if(elapsed >= 1000L) {
1072 struct prunedead prune;
1073 prune.data = data;
1074 prune.extracted = NULL;
1075 while(Curl_conncache_foreach(data, data->state.conn_cache, &prune,
1076 call_extract_if_dead)) {
1077 /* unlocked */
1078
1079 /* remove connection from cache */
1080 Curl_conncache_remove_conn(data, prune.extracted, TRUE);
1081
1082 /* disconnect it */
1083 (void)Curl_disconnect(data, prune.extracted, TRUE);
1084 }
1085 CONNCACHE_LOCK(data);
1086 data->state.conn_cache->last_cleanup = now;
1087 CONNCACHE_UNLOCK(data);
1088 }
1089}
1090
1091/*
1092 * Given one filled in connection struct (named needle), this function should
1093 * detect if there already is one that has all the significant details
1094 * exactly the same and thus should be used instead.
1095 *
1096 * If there is a match, this function returns TRUE - and has marked the
1097 * connection as 'in-use'. It must later be called with ConnectionDone() to
1098 * return back to 'idle' (unused) state.
1099 *
1100 * The force_reuse flag is set if the connection must be used.
1101 */
1102static bool
1103ConnectionExists(struct Curl_easy *data,
1104 struct connectdata *needle,
1105 struct connectdata **usethis,
1106 bool *force_reuse,
1107 bool *waitpipe)
1108{
1109 struct connectdata *check;
1110 struct connectdata *chosen = 0;
1111 bool foundPendingCandidate = FALSE;
1112 bool canmultiplex = IsMultiplexingPossible(data, needle);
1113 struct connectbundle *bundle;
1114 const char *hostbundle;
1115
1116#ifdef USE_NTLM
1117 bool wantNTLMhttp = ((data->state.authhost.want &
1118 (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
1119 (needle->handler->protocol & PROTO_FAMILY_HTTP));
1120#ifndef CURL_DISABLE_PROXY
1121 bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd &&
1122 ((data->state.authproxy.want &
1123 (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
1124 (needle->handler->protocol & PROTO_FAMILY_HTTP)));
1125#else
1126 bool wantProxyNTLMhttp = FALSE;
1127#endif
1128#endif
1129
1130 *force_reuse = FALSE;
1131 *waitpipe = FALSE;
1132
1133 /* Look up the bundle with all the connections to this particular host.
1134 Locks the connection cache, beware of early returns! */
1135 bundle = Curl_conncache_find_bundle(data, needle, data->state.conn_cache,
1136 &hostbundle);
1137 if(bundle) {
1138 /* Max pipe length is zero (unlimited) for multiplexed connections */
1139 struct Curl_llist_element *curr;
1140
1141 infof(data, "Found bundle for host %s: %p [%s]",
1142 hostbundle, (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ?
1143 "can multiplex" : "serially"));
1144
1145 /* We can't multiplex if we don't know anything about the server */
1146 if(canmultiplex) {
1147 if(bundle->multiuse == BUNDLE_UNKNOWN) {
1148 if(data->set.pipewait) {
1149 infof(data, "Server doesn't support multiplex yet, wait");
1150 *waitpipe = TRUE;
1151 CONNCACHE_UNLOCK(data);
1152 return FALSE; /* no re-use */
1153 }
1154
1155 infof(data, "Server doesn't support multiplex (yet)");
1156 canmultiplex = FALSE;
1157 }
1158 if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
1159 !Curl_multiplex_wanted(data->multi)) {
1160 infof(data, "Could multiplex, but not asked to!");
1161 canmultiplex = FALSE;
1162 }
1163 if(bundle->multiuse == BUNDLE_NO_MULTIUSE) {
1164 infof(data, "Can not multiplex, even if we wanted to!");
1165 canmultiplex = FALSE;
1166 }
1167 }
1168
1169 curr = bundle->conn_list.head;
1170 while(curr) {
1171 bool match = FALSE;
1172 size_t multiplexed = 0;
1173
1174 /*
1175 * Note that if we use a HTTP proxy in normal mode (no tunneling), we
1176 * check connections to that proxy and not to the actual remote server.
1177 */
1178 check = curr->ptr;
1179 curr = curr->next;
1180
1181 if(check->bits.connect_only || check->bits.close)
1182 /* connect-only or to-be-closed connections will not be reused */
1183 continue;
1184
1185 if(extract_if_dead(check, data)) {
1186 /* disconnect it */
1187 (void)Curl_disconnect(data, check, TRUE);
1188 continue;
1189 }
1190
1191 if(data->set.ipver != CURL_IPRESOLVE_WHATEVER
1192 && data->set.ipver != check->ip_version) {
1193 /* skip because the connection is not via the requested IP version */
1194 continue;
1195 }
1196
1197 if(bundle->multiuse == BUNDLE_MULTIPLEX)
1198 multiplexed = CONN_INUSE(check);
1199
1200 if(!canmultiplex) {
1201 if(multiplexed) {
1202 /* can only happen within multi handles, and means that another easy
1203 handle is using this connection */
1204 continue;
1205 }
1206
1207 if(Curl_resolver_asynch()) {
1208 /* primary_ip[0] is NUL only if the resolving of the name hasn't
1209 completed yet and until then we don't re-use this connection */
1210 if(!check->primary_ip[0]) {
1211 infof(data,
1212 "Connection #%ld is still name resolving, can't reuse",
1213 check->connection_id);
1214 continue;
1215 }
1216 }
1217
1218 if(check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) {
1219 foundPendingCandidate = TRUE;
1220 /* Don't pick a connection that hasn't connected yet */
1221 infof(data, "Connection #%ld isn't open enough, can't reuse",
1222 check->connection_id);
1223 continue;
1224 }
1225 }
1226
1227#ifdef USE_UNIX_SOCKETS
1228 if(needle->unix_domain_socket) {
1229 if(!check->unix_domain_socket)
1230 continue;
1231 if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
1232 continue;
1233 if(needle->bits.abstract_unix_socket !=
1234 check->bits.abstract_unix_socket)
1235 continue;
1236 }
1237 else if(check->unix_domain_socket)
1238 continue;
1239#endif
1240
1241 if((needle->handler->flags&PROTOPT_SSL) !=
1242 (check->handler->flags&PROTOPT_SSL))
1243 /* don't do mixed SSL and non-SSL connections */
1244 if(get_protocol_family(check->handler) !=
1245 needle->handler->protocol || !check->bits.tls_upgraded)
1246 /* except protocols that have been upgraded via TLS */
1247 continue;
1248
1249#ifndef CURL_DISABLE_PROXY
1250 if(needle->bits.httpproxy != check->bits.httpproxy ||
1251 needle->bits.socksproxy != check->bits.socksproxy)
1252 continue;
1253
1254 if(needle->bits.socksproxy &&
1255 !socks_proxy_info_matches(&needle->socks_proxy,
1256 &check->socks_proxy))
1257 continue;
1258#endif
1259 if(needle->bits.conn_to_host != check->bits.conn_to_host)
1260 /* don't mix connections that use the "connect to host" feature and
1261 * connections that don't use this feature */
1262 continue;
1263
1264 if(needle->bits.conn_to_port != check->bits.conn_to_port)
1265 /* don't mix connections that use the "connect to port" feature and
1266 * connections that don't use this feature */
1267 continue;
1268
1269#ifndef CURL_DISABLE_PROXY
1270 if(needle->bits.httpproxy) {
1271 if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
1272 continue;
1273
1274 if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
1275 continue;
1276
1277 if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) {
1278 /* use https proxy */
1279 if(needle->handler->flags&PROTOPT_SSL) {
1280 /* use double layer ssl */
1281 if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
1282 &check->proxy_ssl_config))
1283 continue;
1284 if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete)
1285 continue;
1286 }
1287 else {
1288 if(!Curl_ssl_config_matches(&needle->ssl_config,
1289 &check->ssl_config))
1290 continue;
1291 if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete)
1292 continue;
1293 }
1294 }
1295 }
1296#endif
1297
1298 if(!canmultiplex && CONN_INUSE(check))
1299 /* this request can't be multiplexed but the checked connection is
1300 already in use so we skip it */
1301 continue;
1302
1303 if(CONN_INUSE(check)) {
1304 /* Subject for multiplex use if 'checks' belongs to the same multi
1305 handle as 'data' is. */
1306 struct Curl_llist_element *e = check->easyq.head;
1307 struct Curl_easy *entry = e->ptr;
1308 if(entry->multi != data->multi)
1309 continue;
1310 }
1311
1312 if(needle->localdev || needle->localport) {
1313 /* If we are bound to a specific local end (IP+port), we must not
1314 re-use a random other one, although if we didn't ask for a
1315 particular one we can reuse one that was bound.
1316
1317 This comparison is a bit rough and too strict. Since the input
1318 parameters can be specified in numerous ways and still end up the
1319 same it would take a lot of processing to make it really accurate.
1320 Instead, this matching will assume that re-uses of bound connections
1321 will most likely also re-use the exact same binding parameters and
1322 missing out a few edge cases shouldn't hurt anyone very much.
1323 */
1324 if((check->localport != needle->localport) ||
1325 (check->localportrange != needle->localportrange) ||
1326 (needle->localdev &&
1327 (!check->localdev || strcmp(check->localdev, needle->localdev))))
1328 continue;
1329 }
1330
1331 if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
1332 /* This protocol requires credentials per connection,
1333 so verify that we're using the same name and password as well */
1334 if(strcmp(needle->user, check->user) ||
1335 strcmp(needle->passwd, check->passwd)) {
1336 /* one of them was different */
1337 continue;
1338 }
1339 }
1340
1341 /* If multiplexing isn't enabled on the h2 connection and h1 is
1342 explicitly requested, handle it: */
1343 if((needle->handler->protocol & PROTO_FAMILY_HTTP) &&
1344 (check->httpversion >= 20) &&
1345 (data->state.httpwant < CURL_HTTP_VERSION_2_0))
1346 continue;
1347
1348 if((needle->handler->flags&PROTOPT_SSL)
1349#ifndef CURL_DISABLE_PROXY
1350 || !needle->bits.httpproxy || needle->bits.tunnel_proxy
1351#endif
1352 ) {
1353 /* The requested connection does not use a HTTP proxy or it uses SSL or
1354 it is a non-SSL protocol tunneled or it is a non-SSL protocol which
1355 is allowed to be upgraded via TLS */
1356
1357 if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
1358 (get_protocol_family(check->handler) ==
1359 needle->handler->protocol && check->bits.tls_upgraded)) &&
1360 (!needle->bits.conn_to_host || strcasecompare(
1361 needle->conn_to_host.name, check->conn_to_host.name)) &&
1362 (!needle->bits.conn_to_port ||
1363 needle->conn_to_port == check->conn_to_port) &&
1364 strcasecompare(needle->host.name, check->host.name) &&
1365 needle->remote_port == check->remote_port) {
1366 /* The schemes match or the protocol family is the same and the
1367 previous connection was TLS upgraded, and the hostname and host
1368 port match */
1369 if(needle->handler->flags & PROTOPT_SSL) {
1370 /* This is a SSL connection so verify that we're using the same
1371 SSL options as well */
1372 if(!Curl_ssl_config_matches(&needle->ssl_config,
1373 &check->ssl_config)) {
1374 DEBUGF(infof(data,
1375 "Connection #%ld has different SSL parameters, "
1376 "can't reuse",
1377 check->connection_id));
1378 continue;
1379 }
1380 if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) {
1381 foundPendingCandidate = TRUE;
1382 DEBUGF(infof(data,
1383 "Connection #%ld has not started SSL connect, "
1384 "can't reuse",
1385 check->connection_id));
1386 continue;
1387 }
1388 }
1389 match = TRUE;
1390 }
1391 }
1392 else {
1393 /* The requested connection is using the same HTTP proxy in normal
1394 mode (no tunneling) */
1395 match = TRUE;
1396 }
1397
1398 if(match) {
1399#if defined(USE_NTLM)
1400 /* If we are looking for an HTTP+NTLM connection, check if this is
1401 already authenticating with the right credentials. If not, keep
1402 looking so that we can reuse NTLM connections if
1403 possible. (Especially we must not reuse the same connection if
1404 partway through a handshake!) */
1405 if(wantNTLMhttp) {
1406 if(strcmp(needle->user, check->user) ||
1407 strcmp(needle->passwd, check->passwd)) {
1408
1409 /* we prefer a credential match, but this is at least a connection
1410 that can be reused and "upgraded" to NTLM */
1411 if(check->http_ntlm_state == NTLMSTATE_NONE)
1412 chosen = check;
1413 continue;
1414 }
1415 }
1416 else if(check->http_ntlm_state != NTLMSTATE_NONE) {
1417 /* Connection is using NTLM auth but we don't want NTLM */
1418 continue;
1419 }
1420
1421#ifndef CURL_DISABLE_PROXY
1422 /* Same for Proxy NTLM authentication */
1423 if(wantProxyNTLMhttp) {
1424 /* Both check->http_proxy.user and check->http_proxy.passwd can be
1425 * NULL */
1426 if(!check->http_proxy.user || !check->http_proxy.passwd)
1427 continue;
1428
1429 if(strcmp(needle->http_proxy.user, check->http_proxy.user) ||
1430 strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
1431 continue;
1432 }
1433 else if(check->proxy_ntlm_state != NTLMSTATE_NONE) {
1434 /* Proxy connection is using NTLM auth but we don't want NTLM */
1435 continue;
1436 }
1437#endif
1438 if(wantNTLMhttp || wantProxyNTLMhttp) {
1439 /* Credentials are already checked, we can use this connection */
1440 chosen = check;
1441
1442 if((wantNTLMhttp &&
1443 (check->http_ntlm_state != NTLMSTATE_NONE)) ||
1444 (wantProxyNTLMhttp &&
1445 (check->proxy_ntlm_state != NTLMSTATE_NONE))) {
1446 /* We must use this connection, no other */
1447 *force_reuse = TRUE;
1448 break;
1449 }
1450
1451 /* Continue look up for a better connection */
1452 continue;
1453 }
1454#endif
1455 if(canmultiplex) {
1456 /* We can multiplex if we want to. Let's continue looking for
1457 the optimal connection to use. */
1458
1459 if(!multiplexed) {
1460 /* We have the optimal connection. Let's stop looking. */
1461 chosen = check;
1462 break;
1463 }
1464
1465#ifdef USE_NGHTTP2
1466 /* If multiplexed, make sure we don't go over concurrency limit */
1467 if(check->bits.multiplex) {
1468 /* Multiplexed connections can only be HTTP/2 for now */
1469 struct http_conn *httpc = &check->proto.httpc;
1470 if(multiplexed >= httpc->settings.max_concurrent_streams) {
1471 infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)",
1472 multiplexed);
1473 continue;
1474 }
1475 else if(multiplexed >=
1476 Curl_multi_max_concurrent_streams(data->multi)) {
1477 infof(data, "client side MAX_CONCURRENT_STREAMS reached"
1478 ", skip (%zu)",
1479 multiplexed);
1480 continue;
1481 }
1482 }
1483#endif
1484 /* When not multiplexed, we have a match here! */
1485 chosen = check;
1486 infof(data, "Multiplexed connection found!");
1487 break;
1488 }
1489 else {
1490 /* We have found a connection. Let's stop searching. */
1491 chosen = check;
1492 break;
1493 }
1494 }
1495 }
1496 }
1497
1498 if(chosen) {
1499 /* mark it as used before releasing the lock */
1500 Curl_attach_connnection(data, chosen);
1501 CONNCACHE_UNLOCK(data);
1502 *usethis = chosen;
1503 return TRUE; /* yes, we found one to use! */
1504 }
1505 CONNCACHE_UNLOCK(data);
1506
1507 if(foundPendingCandidate && data->set.pipewait) {
1508 infof(data,
1509 "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set");
1510 *waitpipe = TRUE;
1511 }
1512
1513 return FALSE; /* no matching connecting exists */
1514}
1515
1516/*
1517 * verboseconnect() displays verbose information after a connect
1518 */
1519#ifndef CURL_DISABLE_VERBOSE_STRINGS
1520void Curl_verboseconnect(struct Curl_easy *data,
1521 struct connectdata *conn)
1522{
1523 if(data->set.verbose)
1524 infof(data, "Connected to %s (%s) port %u (#%ld)",
1525#ifndef CURL_DISABLE_PROXY
1526 conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
1527 conn->bits.httpproxy ? conn->http_proxy.host.dispname :
1528#endif
1529 conn->bits.conn_to_host ? conn->conn_to_host.dispname :
1530 conn->host.dispname,
1531 conn->primary_ip, conn->port, conn->connection_id);
1532}
1533#endif
1534
1535/*
1536 * Helpers for IDNA conversions.
1537 */
1538bool Curl_is_ASCII_name(const char *hostname)
1539{
1540 /* get an UNSIGNED local version of the pointer */
1541 const unsigned char *ch = (const unsigned char *)hostname;
1542
1543 if(!hostname) /* bad input, consider it ASCII! */
1544 return TRUE;
1545
1546 while(*ch) {
1547 if(*ch++ & 0x80)
1548 return FALSE;
1549 }
1550 return TRUE;
1551}
1552
1553/*
1554 * Strip single trailing dot in the hostname,
1555 * primarily for SNI and http host header.
1556 */
1557static void strip_trailing_dot(struct hostname *host)
1558{
1559 size_t len;
1560 if(!host || !host->name)
1561 return;
1562 len = strlen(host->name);
1563 if(len && (host->name[len-1] == '.'))
1564 host->name[len-1] = 0;
1565}
1566
1567/*
1568 * Perform any necessary IDN conversion of hostname
1569 */
1570CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
1571 struct hostname *host)
1572{
1573#ifndef USE_LIBIDN2
1574 (void)data;
1575 (void)data;
1576#elif defined(CURL_DISABLE_VERBOSE_STRINGS)
1577 (void)data;
1578#endif
1579
1580 /* set the name we use to display the host name */
1581 host->dispname = host->name;
1582
1583 /* Check name for non-ASCII and convert hostname to ACE form if we can */
1584 if(!Curl_is_ASCII_name(host->name)) {
1585#ifdef USE_LIBIDN2
1586 if(idn2_check_version(IDN2_VERSION)) {
1587 char *ace_hostname = NULL;
1588#if IDN2_VERSION_NUMBER >= 0x00140000
1589 /* IDN2_NFC_INPUT: Normalize input string using normalization form C.
1590 IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional
1591 processing. */
1592 int flags = IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL;
1593#else
1594 int flags = IDN2_NFC_INPUT;
1595#endif
1596 int rc = IDN2_LOOKUP(host->name, &ace_hostname, flags);
1597 if(rc != IDN2_OK)
1598 /* fallback to TR46 Transitional mode for better IDNA2003
1599 compatibility */
1600 rc = IDN2_LOOKUP(host->name, &ace_hostname,
1601 IDN2_TRANSITIONAL);
1602 if(rc == IDN2_OK) {
1603 host->encalloc = (char *)ace_hostname;
1604 /* change the name pointer to point to the encoded hostname */
1605 host->name = host->encalloc;
1606 }
1607 else {
1608 failf(data, "Failed to convert %s to ACE; %s", host->name,
1609 idn2_strerror(rc));
1610 return CURLE_URL_MALFORMAT;
1611 }
1612 }
1613#elif defined(USE_WIN32_IDN)
1614 char *ace_hostname = NULL;
1615
1616 if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
1617 host->encalloc = ace_hostname;
1618 /* change the name pointer to point to the encoded hostname */
1619 host->name = host->encalloc;
1620 }
1621 else {
1622 char buffer[STRERROR_LEN];
1623 failf(data, "Failed to convert %s to ACE; %s", host->name,
1624 Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
1625 return CURLE_URL_MALFORMAT;
1626 }
1627#else
1628 infof(data, "IDN support not present, can't parse Unicode domains");
1629#endif
1630 }
1631 return CURLE_OK;
1632}
1633
1634/*
1635 * Frees data allocated by idnconvert_hostname()
1636 */
1637void Curl_free_idnconverted_hostname(struct hostname *host)
1638{
1639#if defined(USE_LIBIDN2)
1640 if(host->encalloc) {
1641 idn2_free(host->encalloc); /* must be freed with idn2_free() since this was
1642 allocated by libidn */
1643 host->encalloc = NULL;
1644 }
1645#elif defined(USE_WIN32_IDN)
1646 free(host->encalloc); /* must be freed with free() since this was
1647 allocated by curl_win32_idn_to_ascii */
1648 host->encalloc = NULL;
1649#else
1650 (void)host;
1651#endif
1652}
1653
1654/*
1655 * Allocate and initialize a new connectdata object.
1656 */
1657static struct connectdata *allocate_conn(struct Curl_easy *data)
1658{
1659 struct connectdata *conn = calloc(1, sizeof(struct connectdata));
1660 if(!conn)
1661 return NULL;
1662
1663#ifdef USE_SSL
1664 /* The SSL backend-specific data (ssl_backend_data) objects are allocated as
1665 a separate array to ensure suitable alignment.
1666 Note that these backend pointers can be swapped by vtls (eg ssl backend
1667 data becomes proxy backend data). */
1668 {
1669 size_t sslsize = Curl_ssl->sizeof_ssl_backend_data;
1670 char *ssl = calloc(4, sslsize);
1671 if(!ssl) {
1672 free(conn);
1673 return NULL;
1674 }
1675 conn->ssl_extra = ssl;
1676 conn->ssl[0].backend = (void *)ssl;
1677 conn->ssl[1].backend = (void *)(ssl + sslsize);
1678#ifndef CURL_DISABLE_PROXY
1679 conn->proxy_ssl[0].backend = (void *)(ssl + 2 * sslsize);
1680 conn->proxy_ssl[1].backend = (void *)(ssl + 3 * sslsize);
1681#endif
1682 }
1683#endif
1684
1685 conn->handler = &Curl_handler_dummy; /* Be sure we have a handler defined
1686 already from start to avoid NULL
1687 situations and checks */
1688
1689 /* and we setup a few fields in case we end up actually using this struct */
1690
1691 conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
1692 conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
1693 conn->tempsock[0] = CURL_SOCKET_BAD; /* no file descriptor */
1694 conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
1695 conn->connection_id = -1; /* no ID */
1696 conn->port = -1; /* unknown at this point */
1697 conn->remote_port = -1; /* unknown at this point */
1698#if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD)
1699 conn->postponed[0].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
1700 conn->postponed[1].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
1701#endif /* USE_RECV_BEFORE_SEND_WORKAROUND && DEBUGBUILD */
1702
1703 /* Default protocol-independent behavior doesn't support persistent
1704 connections, so we set this to force-close. Protocols that support
1705 this need to set this to FALSE in their "curl_do" functions. */
1706 connclose(conn, "Default to force-close");
1707
1708 /* Store creation time to help future close decision making */
1709 conn->created = Curl_now();
1710
1711 /* Store current time to give a baseline to keepalive connection times. */
1712 conn->keepalive = Curl_now();
1713
1714#ifndef CURL_DISABLE_PROXY
1715 conn->http_proxy.proxytype = data->set.proxytype;
1716 conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;
1717
1718 /* note that these two proxy bits are now just on what looks to be
1719 requested, they may be altered down the road */
1720 conn->bits.proxy = (data->set.str[STRING_PROXY] &&
1721 *data->set.str[STRING_PROXY]) ? TRUE : FALSE;
1722 conn->bits.httpproxy = (conn->bits.proxy &&
1723 (conn->http_proxy.proxytype == CURLPROXY_HTTP ||
1724 conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 ||
1725 conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ?
1726 TRUE : FALSE;
1727 conn->bits.socksproxy = (conn->bits.proxy &&
1728 !conn->bits.httpproxy) ? TRUE : FALSE;
1729
1730 if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) {
1731 conn->bits.proxy = TRUE;
1732 conn->bits.socksproxy = TRUE;
1733 }
1734
1735 conn->bits.proxy_user_passwd =
1736 (data->state.aptr.proxyuser) ? TRUE : FALSE;
1737 conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
1738#endif /* CURL_DISABLE_PROXY */
1739
1740 conn->bits.user_passwd = (data->state.aptr.user) ? TRUE : FALSE;
1741#ifndef CURL_DISABLE_FTP
1742 conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
1743 conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
1744#endif
1745 conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus;
1746 conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
1747 conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
1748#ifndef CURL_DISABLE_PROXY
1749 conn->proxy_ssl_config.verifystatus =
1750 data->set.proxy_ssl.primary.verifystatus;
1751 conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
1752 conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
1753#endif
1754 conn->ip_version = data->set.ipver;
1755 conn->bits.connect_only = data->set.connect_only;
1756 conn->transport = TRNSPRT_TCP; /* most of them are TCP streams */
1757
1758#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
1759 defined(NTLM_WB_ENABLED)
1760 conn->ntlm.ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
1761 conn->proxyntlm.ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
1762#endif
1763
1764 /* Initialize the easy handle list */
1765 Curl_llist_init(&conn->easyq, NULL);
1766
1767#ifdef HAVE_GSSAPI
1768 conn->data_prot = PROT_CLEAR;
1769#endif
1770
1771 /* Store the local bind parameters that will be used for this connection */
1772 if(data->set.str[STRING_DEVICE]) {
1773 conn->localdev = strdup(data->set.str[STRING_DEVICE]);
1774 if(!conn->localdev)
1775 goto error;
1776 }
1777 conn->localportrange = data->set.localportrange;
1778 conn->localport = data->set.localport;
1779
1780 /* the close socket stuff needs to be copied to the connection struct as
1781 it may live on without (this specific) Curl_easy */
1782 conn->fclosesocket = data->set.fclosesocket;
1783 conn->closesocket_client = data->set.closesocket_client;
1784 conn->lastused = Curl_now(); /* used now */
1785
1786 return conn;
1787 error:
1788
1789 Curl_llist_destroy(&conn->easyq, NULL);
1790 free(conn->localdev);
1791#ifdef USE_SSL
1792 free(conn->ssl_extra);
1793#endif
1794 free(conn);
1795 return NULL;
1796}
1797
1798/* returns the handler if the given scheme is built-in */
1799const struct Curl_handler *Curl_builtin_scheme(const char *scheme)
1800{
1801 const struct Curl_handler * const *pp;
1802 const struct Curl_handler *p;
1803 /* Scan protocol handler table and match against 'scheme'. The handler may
1804 be changed later when the protocol specific setup function is called. */
1805 for(pp = protocols; (p = *pp) != NULL; pp++)
1806 if(strcasecompare(p->scheme, scheme))
1807 /* Protocol found in table. Check if allowed */
1808 return p;
1809 return NULL; /* not found */
1810}
1811
1812
1813static CURLcode findprotocol(struct Curl_easy *data,
1814 struct connectdata *conn,
1815 const char *protostr)
1816{
1817 const struct Curl_handler *p = Curl_builtin_scheme(protostr);
1818
1819 if(p && /* Protocol found in table. Check if allowed */
1820 (data->set.allowed_protocols & p->protocol)) {
1821
1822 /* it is allowed for "normal" request, now do an extra check if this is
1823 the result of a redirect */
1824 if(data->state.this_is_a_follow &&
1825 !(data->set.redir_protocols & p->protocol))
1826 /* nope, get out */
1827 ;
1828 else {
1829 /* Perform setup complement if some. */
1830 conn->handler = conn->given = p;
1831
1832 /* 'port' and 'remote_port' are set in setup_connection_internals() */
1833 return CURLE_OK;
1834 }
1835 }
1836
1837 /* The protocol was not found in the table, but we don't have to assign it
1838 to anything since it is already assigned to a dummy-struct in the
1839 create_conn() function when the connectdata struct is allocated. */
1840 failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME,
1841 protostr);
1842
1843 return CURLE_UNSUPPORTED_PROTOCOL;
1844}
1845
1846
1847CURLcode Curl_uc_to_curlcode(CURLUcode uc)
1848{
1849 switch(uc) {
1850 default:
1851 return CURLE_URL_MALFORMAT;
1852 case CURLUE_UNSUPPORTED_SCHEME:
1853 return CURLE_UNSUPPORTED_PROTOCOL;
1854 case CURLUE_OUT_OF_MEMORY:
1855 return CURLE_OUT_OF_MEMORY;
1856 case CURLUE_USER_NOT_ALLOWED:
1857 return CURLE_LOGIN_DENIED;
1858 }
1859}
1860
1861/*
1862 * If the URL was set with an IPv6 numerical address with a zone id part, set
1863 * the scope_id based on that!
1864 */
1865
1866static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
1867 struct connectdata *conn)
1868{
1869 char *zoneid;
1870 CURLUcode uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0);
1871#ifdef CURL_DISABLE_VERBOSE_STRINGS
1872 (void)data;
1873#endif
1874
1875 if(!uc && zoneid) {
1876 char *endp;
1877 unsigned long scope = strtoul(zoneid, &endp, 10);
1878 if(!*endp && (scope < UINT_MAX))
1879 /* A plain number, use it directly as a scope id. */
1880 conn->scope_id = (unsigned int)scope;
1881#if defined(HAVE_IF_NAMETOINDEX)
1882 else {
1883#elif defined(WIN32)
1884 else if(Curl_if_nametoindex) {
1885#endif
1886
1887#if defined(HAVE_IF_NAMETOINDEX) || defined(WIN32)
1888 /* Zone identifier is not numeric */
1889 unsigned int scopeidx = 0;
1890#if defined(WIN32)
1891 scopeidx = Curl_if_nametoindex(zoneid);
1892#else
1893 scopeidx = if_nametoindex(zoneid);
1894#endif
1895 if(!scopeidx) {
1896#ifndef CURL_DISABLE_VERBOSE_STRINGS
1897 char buffer[STRERROR_LEN];
1898 infof(data, "Invalid zoneid: %s; %s", zoneid,
1899 Curl_strerror(errno, buffer, sizeof(buffer)));
1900#endif
1901 }
1902 else
1903 conn->scope_id = scopeidx;
1904 }
1905#endif /* HAVE_IF_NAMETOINDEX || WIN32 */
1906
1907 free(zoneid);
1908 }
1909}
1910
1911/*
1912 * Parse URL and fill in the relevant members of the connection struct.
1913 */
1914static CURLcode parseurlandfillconn(struct Curl_easy *data,
1915 struct connectdata *conn)
1916{
1917 CURLcode result;
1918 CURLU *uh;
1919 CURLUcode uc;
1920 char *hostname;
1921 bool use_set_uh = (data->set.uh && !data->state.this_is_a_follow);
1922
1923 up_free(data); /* cleanup previous leftovers first */
1924
1925 /* parse the URL */
1926 if(use_set_uh) {
1927 uh = data->state.uh = curl_url_dup(data->set.uh);
1928 }
1929 else {
1930 uh = data->state.uh = curl_url();
1931 }
1932
1933 if(!uh)
1934 return CURLE_OUT_OF_MEMORY;
1935
1936 if(data->set.str[STRING_DEFAULT_PROTOCOL] &&
1937 !Curl_is_absolute_url(data->state.url, NULL, MAX_SCHEME_LEN)) {
1938 char *url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL],
1939 data->state.url);
1940 if(!url)
1941 return CURLE_OUT_OF_MEMORY;
1942 if(data->state.url_alloc)
1943 free(data->state.url);
1944 data->state.url = url;
1945 data->state.url_alloc = TRUE;
1946 }
1947
1948 if(!use_set_uh) {
1949 char *newurl;
1950 uc = curl_url_set(uh, CURLUPART_URL, data->state.url,
1951 CURLU_GUESS_SCHEME |
1952 CURLU_NON_SUPPORT_SCHEME |
1953 (data->set.disallow_username_in_url ?
1954 CURLU_DISALLOW_USER : 0) |
1955 (data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
1956 if(uc) {
1957 DEBUGF(infof(data, "curl_url_set rejected %s", data->state.url));
1958 return Curl_uc_to_curlcode(uc);
1959 }
1960
1961 /* after it was parsed, get the generated normalized version */
1962 uc = curl_url_get(uh, CURLUPART_URL, &newurl, 0);
1963 if(uc)
1964 return Curl_uc_to_curlcode(uc);
1965 if(data->state.url_alloc)
1966 free(data->state.url);
1967 data->state.url = newurl;
1968 data->state.url_alloc = TRUE;
1969 }
1970
1971 uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
1972 if(uc)
1973 return Curl_uc_to_curlcode(uc);
1974
1975 uc = curl_url_get(uh, CURLUPART_HOST, &data->state.up.hostname, 0);
1976 if(uc) {
1977 if(!strcasecompare("file", data->state.up.scheme))
1978 return CURLE_OUT_OF_MEMORY;
1979 }
1980
1981#ifndef CURL_DISABLE_HSTS
1982 if(data->hsts && strcasecompare("http", data->state.up.scheme)) {
1983 if(Curl_hsts(data->hsts, data->state.up.hostname, TRUE)) {
1984 char *url;
1985 Curl_safefree(data->state.up.scheme);
1986 uc = curl_url_set(uh, CURLUPART_SCHEME, "https", 0);
1987 if(uc)
1988 return Curl_uc_to_curlcode(uc);
1989 if(data->state.url_alloc)
1990 Curl_safefree(data->state.url);
1991 /* after update, get the updated version */
1992 uc = curl_url_get(uh, CURLUPART_URL, &url, 0);
1993 if(uc)
1994 return Curl_uc_to_curlcode(uc);
1995 uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
1996 if(uc) {
1997 free(url);
1998 return Curl_uc_to_curlcode(uc);
1999 }
2000 data->state.url = url;
2001 data->state.url_alloc = TRUE;
2002 infof(data, "Switched from HTTP to HTTPS due to HSTS => %s",
2003 data->state.url);
2004 }
2005 }
2006#endif
2007
2008 result = findprotocol(data, conn, data->state.up.scheme);
2009 if(result)
2010 return result;
2011
2012 /*
2013 * User name and password set with their own options override the
2014 * credentials possibly set in the URL.
2015 */
2016 if(!data->state.aptr.user) {
2017 /* we don't use the URL API's URL decoder option here since it rejects
2018 control codes and we want to allow them for some schemes in the user
2019 and password fields */
2020 uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, 0);
2021 if(!uc) {
2022 char *decoded;
2023 result = Curl_urldecode(NULL, data->state.up.user, 0, &decoded, NULL,
2024 conn->handler->flags&PROTOPT_USERPWDCTRL ?
2025 REJECT_ZERO : REJECT_CTRL);
2026 if(result)
2027 return result;
2028 conn->user = decoded;
2029 conn->bits.user_passwd = TRUE;
2030 result = Curl_setstropt(&data->state.aptr.user, decoded);
2031 if(result)
2032 return result;
2033 }
2034 else if(uc != CURLUE_NO_USER)
2035 return Curl_uc_to_curlcode(uc);
2036 }
2037
2038 if(!data->state.aptr.passwd) {
2039 uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
2040 if(!uc) {
2041 char *decoded;
2042 result = Curl_urldecode(NULL, data->state.up.password, 0, &decoded, NULL,
2043 conn->handler->flags&PROTOPT_USERPWDCTRL ?
2044 REJECT_ZERO : REJECT_CTRL);
2045 if(result)
2046 return result;
2047 conn->passwd = decoded;
2048 conn->bits.user_passwd = TRUE;
2049 result = Curl_setstropt(&data->state.aptr.passwd, decoded);
2050 if(result)
2051 return result;
2052 }
2053 else if(uc != CURLUE_NO_PASSWORD)
2054 return Curl_uc_to_curlcode(uc);
2055 }
2056
2057 uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options,
2058 CURLU_URLDECODE);
2059 if(!uc) {
2060 conn->options = strdup(data->state.up.options);
2061 if(!conn->options)
2062 return CURLE_OUT_OF_MEMORY;
2063 }
2064 else if(uc != CURLUE_NO_OPTIONS)
2065 return Curl_uc_to_curlcode(uc);
2066
2067 uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path, 0);
2068 if(uc)
2069 return Curl_uc_to_curlcode(uc);
2070
2071 uc = curl_url_get(uh, CURLUPART_PORT, &data->state.up.port,
2072 CURLU_DEFAULT_PORT);
2073 if(uc) {
2074 if(!strcasecompare("file", data->state.up.scheme))
2075 return CURLE_OUT_OF_MEMORY;
2076 }
2077 else {
2078 unsigned long port = strtoul(data->state.up.port, NULL, 10);
2079 conn->port = conn->remote_port =
2080 (data->set.use_port && data->state.allow_port) ?
2081 (int)data->set.use_port : curlx_ultous(port);
2082 }
2083
2084 (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
2085
2086 hostname = data->state.up.hostname;
2087 if(hostname && hostname[0] == '[') {
2088 /* This looks like an IPv6 address literal. See if there is an address
2089 scope. */
2090 size_t hlen;
2091 conn->bits.ipv6_ip = TRUE;
2092 /* cut off the brackets! */
2093 hostname++;
2094 hlen = strlen(hostname);
2095 hostname[hlen - 1] = 0;
2096
2097 zonefrom_url(uh, data, conn);
2098 }
2099
2100 /* make sure the connect struct gets its own copy of the host name */
2101 conn->host.rawalloc = strdup(hostname ? hostname : "");
2102 if(!conn->host.rawalloc)
2103 return CURLE_OUT_OF_MEMORY;
2104 conn->host.name = conn->host.rawalloc;
2105
2106 if(data->set.scope_id)
2107 /* Override any scope that was set above. */
2108 conn->scope_id = data->set.scope_id;
2109
2110 return CURLE_OK;
2111}
2112
2113
2114/*
2115 * If we're doing a resumed transfer, we need to setup our stuff
2116 * properly.
2117 */
2118static CURLcode setup_range(struct Curl_easy *data)
2119{
2120 struct UrlState *s = &data->state;
2121 s->resume_from = data->set.set_resume_from;
2122 if(s->resume_from || data->set.str[STRING_SET_RANGE]) {
2123 if(s->rangestringalloc)
2124 free(s->range);
2125
2126 if(s->resume_from)
2127 s->range = aprintf("%" CURL_FORMAT_CURL_OFF_T "-", s->resume_from);
2128 else
2129 s->range = strdup(data->set.str[STRING_SET_RANGE]);
2130
2131 s->rangestringalloc = (s->range) ? TRUE : FALSE;
2132
2133 if(!s->range)
2134 return CURLE_OUT_OF_MEMORY;
2135
2136 /* tell ourselves to fetch this range */
2137 s->use_range = TRUE; /* enable range download */
2138 }
2139 else
2140 s->use_range = FALSE; /* disable range download */
2141
2142 return CURLE_OK;
2143}
2144
2145
2146/*
2147 * setup_connection_internals() -
2148 *
2149 * Setup connection internals specific to the requested protocol in the
2150 * Curl_easy. This is inited and setup before the connection is made but
2151 * is about the particular protocol that is to be used.
2152 *
2153 * This MUST get called after proxy magic has been figured out.
2154 */
2155static CURLcode setup_connection_internals(struct Curl_easy *data,
2156 struct connectdata *conn)
2157{
2158 const struct Curl_handler *p;
2159 CURLcode result;
2160
2161 /* Perform setup complement if some. */
2162 p = conn->handler;
2163
2164 if(p->setup_connection) {
2165 result = (*p->setup_connection)(data, conn);
2166
2167 if(result)
2168 return result;
2169
2170 p = conn->handler; /* May have changed. */
2171 }
2172
2173 if(conn->port < 0)
2174 /* we check for -1 here since if proxy was detected already, this
2175 was very likely already set to the proxy port */
2176 conn->port = p->defport;
2177
2178 return CURLE_OK;
2179}
2180
2181/*
2182 * Curl_free_request_state() should free temp data that was allocated in the
2183 * Curl_easy for this single request.
2184 */
2185
2186void Curl_free_request_state(struct Curl_easy *data)
2187{
2188 Curl_safefree(data->req.p.http);
2189 Curl_safefree(data->req.newurl);
2190
2191#ifndef CURL_DISABLE_DOH
2192 if(data->req.doh) {
2193 Curl_close(&data->req.doh->probe[0].easy);
2194 Curl_close(&data->req.doh->probe[1].easy);
2195 }
2196#endif
2197}
2198
2199
2200#ifndef CURL_DISABLE_PROXY
2201/****************************************************************
2202* Checks if the host is in the noproxy list. returns true if it matches
2203* and therefore the proxy should NOT be used.
2204****************************************************************/
2205static bool check_noproxy(const char *name, const char *no_proxy)
2206{
2207 /* no_proxy=domain1.dom,host.domain2.dom
2208 * (a comma-separated list of hosts which should
2209 * not be proxied, or an asterisk to override
2210 * all proxy variables)
2211 */
2212 if(no_proxy && no_proxy[0]) {
2213 size_t tok_start;
2214 size_t tok_end;
2215 const char *separator = ", ";
2216 size_t no_proxy_len;
2217 size_t namelen;
2218 char *endptr;
2219 if(strcasecompare("*", no_proxy)) {
2220 return TRUE;
2221 }
2222
2223 /* NO_PROXY was specified and it wasn't just an asterisk */
2224
2225 no_proxy_len = strlen(no_proxy);
2226 if(name[0] == '[') {
2227 /* IPv6 numerical address */
2228 endptr = strchr(name, ']');
2229 if(!endptr)
2230 return FALSE;
2231 name++;
2232 namelen = endptr - name;
2233 }
2234 else
2235 namelen = strlen(name);
2236
2237 for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
2238 while(tok_start < no_proxy_len &&
2239 strchr(separator, no_proxy[tok_start]) != NULL) {
2240 /* Look for the beginning of the token. */
2241 ++tok_start;
2242 }
2243
2244 if(tok_start == no_proxy_len)
2245 break; /* It was all trailing separator chars, no more tokens. */
2246
2247 for(tok_end = tok_start; tok_end < no_proxy_len &&
2248 strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end)
2249 /* Look for the end of the token. */
2250 ;
2251
2252 /* To match previous behavior, where it was necessary to specify
2253 * ".local.com" to prevent matching "notlocal.com", we will leave
2254 * the '.' off.
2255 */
2256 if(no_proxy[tok_start] == '.')
2257 ++tok_start;
2258
2259 if((tok_end - tok_start) <= namelen) {
2260 /* Match the last part of the name to the domain we are checking. */
2261 const char *checkn = name + namelen - (tok_end - tok_start);
2262 if(strncasecompare(no_proxy + tok_start, checkn,
2263 tok_end - tok_start)) {
2264 if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
2265 /* We either have an exact match, or the previous character is a .
2266 * so it is within the same domain, so no proxy for this host.
2267 */
2268 return TRUE;
2269 }
2270 }
2271 } /* if((tok_end - tok_start) <= namelen) */
2272 } /* for(tok_start = 0; tok_start < no_proxy_len;
2273 tok_start = tok_end + 1) */
2274 } /* NO_PROXY was specified and it wasn't just an asterisk */
2275
2276 return FALSE;
2277}
2278
2279#ifndef CURL_DISABLE_HTTP
2280/****************************************************************
2281* Detect what (if any) proxy to use. Remember that this selects a host
2282* name and is not limited to HTTP proxies only.
2283* The returned pointer must be freed by the caller (unless NULL)
2284****************************************************************/
2285static char *detect_proxy(struct Curl_easy *data,
2286 struct connectdata *conn)
2287{
2288 char *proxy = NULL;
2289
2290 /* If proxy was not specified, we check for default proxy environment
2291 * variables, to enable i.e Lynx compliance:
2292 *
2293 * http_proxy=http://some.server.dom:port/
2294 * https_proxy=http://some.server.dom:port/
2295 * ftp_proxy=http://some.server.dom:port/
2296 * no_proxy=domain1.dom,host.domain2.dom
2297 * (a comma-separated list of hosts which should
2298 * not be proxied, or an asterisk to override
2299 * all proxy variables)
2300 * all_proxy=http://some.server.dom:port/
2301 * (seems to exist for the CERN www lib. Probably
2302 * the first to check for.)
2303 *
2304 * For compatibility, the all-uppercase versions of these variables are
2305 * checked if the lowercase versions don't exist.
2306 */
2307 char proxy_env[128];
2308 const char *protop = conn->handler->scheme;
2309 char *envp = proxy_env;
2310 char *prox;
2311#ifdef CURL_DISABLE_VERBOSE_STRINGS
2312 (void)data;
2313#endif
2314
2315 /* Now, build <protocol>_proxy and check for such a one to use */
2316 while(*protop)
2317 *envp++ = (char)tolower((int)*protop++);
2318
2319 /* append _proxy */
2320 strcpy(envp, "_proxy");
2321
2322 /* read the protocol proxy: */
2323 prox = curl_getenv(proxy_env);
2324
2325 /*
2326 * We don't try the uppercase version of HTTP_PROXY because of
2327 * security reasons:
2328 *
2329 * When curl is used in a webserver application
2330 * environment (cgi or php), this environment variable can
2331 * be controlled by the web server user by setting the
2332 * http header 'Proxy:' to some value.
2333 *
2334 * This can cause 'internal' http/ftp requests to be
2335 * arbitrarily redirected by any external attacker.
2336 */
2337 if(!prox && !strcasecompare("http_proxy", proxy_env)) {
2338 /* There was no lowercase variable, try the uppercase version: */
2339 Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
2340 prox = curl_getenv(proxy_env);
2341 }
2342
2343 envp = proxy_env;
2344 if(prox) {
2345 proxy = prox; /* use this */
2346 }
2347 else {
2348 envp = (char *)"all_proxy";
2349 proxy = curl_getenv(envp); /* default proxy to use */
2350 if(!proxy) {
2351 envp = (char *)"ALL_PROXY";
2352 proxy = curl_getenv(envp);
2353 }
2354 }
2355 if(proxy)
2356 infof(data, "Uses proxy env variable %s == '%s'", envp, proxy);
2357
2358 return proxy;
2359}
2360#endif /* CURL_DISABLE_HTTP */
2361
2362/*
2363 * If this is supposed to use a proxy, we need to figure out the proxy
2364 * host name, so that we can re-use an existing connection
2365 * that may exist registered to the same proxy host.
2366 */
2367static CURLcode parse_proxy(struct Curl_easy *data,
2368 struct connectdata *conn, char *proxy,
2369 curl_proxytype proxytype)
2370{
2371 char *portptr = NULL;
2372 int port = -1;
2373 char *proxyuser = NULL;
2374 char *proxypasswd = NULL;
2375 char *host;
2376 bool sockstype;
2377 CURLUcode uc;
2378 struct proxy_info *proxyinfo;
2379 CURLU *uhp = curl_url();
2380 CURLcode result = CURLE_OK;
2381 char *scheme = NULL;
2382
2383 /* When parsing the proxy, allowing non-supported schemes since we have
2384 these made up ones for proxies. Guess scheme for URLs without it. */
2385 uc = curl_url_set(uhp, CURLUPART_URL, proxy,
2386 CURLU_NON_SUPPORT_SCHEME|CURLU_GUESS_SCHEME);
2387 if(!uc) {
2388 /* parsed okay as a URL */
2389 uc = curl_url_get(uhp, CURLUPART_SCHEME, &scheme, 0);
2390 if(uc) {
2391 result = CURLE_OUT_OF_MEMORY;
2392 goto error;
2393 }
2394
2395 if(strcasecompare("https", scheme))
2396 proxytype = CURLPROXY_HTTPS;
2397 else if(strcasecompare("socks5h", scheme))
2398 proxytype = CURLPROXY_SOCKS5_HOSTNAME;
2399 else if(strcasecompare("socks5", scheme))
2400 proxytype = CURLPROXY_SOCKS5;
2401 else if(strcasecompare("socks4a", scheme))
2402 proxytype = CURLPROXY_SOCKS4A;
2403 else if(strcasecompare("socks4", scheme) ||
2404 strcasecompare("socks", scheme))
2405 proxytype = CURLPROXY_SOCKS4;
2406 else if(strcasecompare("http", scheme))
2407 ; /* leave it as HTTP or HTTP/1.0 */
2408 else {
2409 /* Any other xxx:// reject! */
2410 failf(data, "Unsupported proxy scheme for \'%s\'", proxy);
2411 result = CURLE_COULDNT_CONNECT;
2412 goto error;
2413 }
2414 }
2415 else {
2416 failf(data, "Unsupported proxy syntax in \'%s\'", proxy);
2417 result = CURLE_COULDNT_RESOLVE_PROXY;
2418 goto error;
2419 }
2420
2421#ifdef USE_SSL
2422 if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
2423#endif
2424 if(proxytype == CURLPROXY_HTTPS) {
2425 failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
2426 "HTTPS-proxy support.", proxy);
2427 result = CURLE_NOT_BUILT_IN;
2428 goto error;
2429 }
2430
2431 sockstype =
2432 proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
2433 proxytype == CURLPROXY_SOCKS5 ||
2434 proxytype == CURLPROXY_SOCKS4A ||
2435 proxytype == CURLPROXY_SOCKS4;
2436
2437 proxyinfo = sockstype ? &conn->socks_proxy : &conn->http_proxy;
2438 proxyinfo->proxytype = proxytype;
2439
2440 /* Is there a username and password given in this proxy url? */
2441 uc = curl_url_get(uhp, CURLUPART_USER, &proxyuser, CURLU_URLDECODE);
2442 if(uc && (uc != CURLUE_NO_USER))
2443 goto error;
2444 uc = curl_url_get(uhp, CURLUPART_PASSWORD, &proxypasswd, CURLU_URLDECODE);
2445 if(uc && (uc != CURLUE_NO_PASSWORD))
2446 goto error;
2447
2448 if(proxyuser || proxypasswd) {
2449 Curl_safefree(proxyinfo->user);
2450 proxyinfo->user = proxyuser;
2451 result = Curl_setstropt(&data->state.aptr.proxyuser, proxyuser);
2452 proxyuser = NULL;
2453 if(result)
2454 goto error;
2455 Curl_safefree(proxyinfo->passwd);
2456 if(!proxypasswd) {
2457 proxypasswd = strdup("");
2458 if(!proxypasswd) {
2459 result = CURLE_OUT_OF_MEMORY;
2460 goto error;
2461 }
2462 }
2463 proxyinfo->passwd = proxypasswd;
2464 result = Curl_setstropt(&data->state.aptr.proxypasswd, proxypasswd);
2465 proxypasswd = NULL;
2466 if(result)
2467 goto error;
2468 conn->bits.proxy_user_passwd = TRUE; /* enable it */
2469 }
2470
2471 (void)curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);
2472
2473 if(portptr) {
2474 port = (int)strtol(portptr, NULL, 10);
2475 free(portptr);
2476 }
2477 else {
2478 if(data->set.proxyport)
2479 /* None given in the proxy string, then get the default one if it is
2480 given */
2481 port = (int)data->set.proxyport;
2482 else {
2483 if(proxytype == CURLPROXY_HTTPS)
2484 port = CURL_DEFAULT_HTTPS_PROXY_PORT;
2485 else
2486 port = CURL_DEFAULT_PROXY_PORT;
2487 }
2488 }
2489 if(port >= 0) {
2490 proxyinfo->port = port;
2491 if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc)
2492 conn->port = port;
2493 }
2494
2495 /* now, clone the proxy host name */
2496 uc = curl_url_get(uhp, CURLUPART_HOST, &host, CURLU_URLDECODE);
2497 if(uc) {
2498 result = CURLE_OUT_OF_MEMORY;
2499 goto error;
2500 }
2501 Curl_safefree(proxyinfo->host.rawalloc);
2502 proxyinfo->host.rawalloc = host;
2503 if(host[0] == '[') {
2504 /* this is a numerical IPv6, strip off the brackets */
2505 size_t len = strlen(host);
2506 host[len-1] = 0; /* clear the trailing bracket */
2507 host++;
2508 zonefrom_url(uhp, data, conn);
2509 }
2510 proxyinfo->host.name = host;
2511
2512 error:
2513 free(proxyuser);
2514 free(proxypasswd);
2515 free(scheme);
2516 curl_url_cleanup(uhp);
2517 return result;
2518}
2519
2520/*
2521 * Extract the user and password from the authentication string
2522 */
2523static CURLcode parse_proxy_auth(struct Curl_easy *data,
2524 struct connectdata *conn)
2525{
2526 const char *proxyuser = data->state.aptr.proxyuser ?
2527 data->state.aptr.proxyuser : "";
2528 const char *proxypasswd = data->state.aptr.proxypasswd ?
2529 data->state.aptr.proxypasswd : "";
2530 CURLcode result = CURLE_OK;
2531
2532 if(proxyuser) {
2533 result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
2534 REJECT_ZERO);
2535 if(!result)
2536 result = Curl_setstropt(&data->state.aptr.proxyuser,
2537 conn->http_proxy.user);
2538 }
2539 if(!result && proxypasswd) {
2540 result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
2541 NULL, REJECT_ZERO);
2542 if(!result)
2543 result = Curl_setstropt(&data->state.aptr.proxypasswd,
2544 conn->http_proxy.passwd);
2545 }
2546 return result;
2547}
2548
2549/* create_conn helper to parse and init proxy values. to be called after unix
2550 socket init but before any proxy vars are evaluated. */
2551static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
2552 struct connectdata *conn)
2553{
2554 char *proxy = NULL;
2555 char *socksproxy = NULL;
2556 char *no_proxy = NULL;
2557 CURLcode result = CURLE_OK;
2558
2559 /*************************************************************
2560 * Extract the user and password from the authentication string
2561 *************************************************************/
2562 if(conn->bits.proxy_user_passwd) {
2563 result = parse_proxy_auth(data, conn);
2564 if(result)
2565 goto out;
2566 }
2567
2568 /*************************************************************
2569 * Detect what (if any) proxy to use
2570 *************************************************************/
2571 if(data->set.str[STRING_PROXY]) {
2572 proxy = strdup(data->set.str[STRING_PROXY]);
2573 /* if global proxy is set, this is it */
2574 if(NULL == proxy) {
2575 failf(data, "memory shortage");
2576 result = CURLE_OUT_OF_MEMORY;
2577 goto out;
2578 }
2579 }
2580
2581 if(data->set.str[STRING_PRE_PROXY]) {
2582 socksproxy = strdup(data->set.str[STRING_PRE_PROXY]);
2583 /* if global socks proxy is set, this is it */
2584 if(NULL == socksproxy) {
2585 failf(data, "memory shortage");
2586 result = CURLE_OUT_OF_MEMORY;
2587 goto out;
2588 }
2589 }
2590
2591 if(!data->set.str[STRING_NOPROXY]) {
2592 const char *p = "no_proxy";
2593 no_proxy = curl_getenv(p);
2594 if(!no_proxy) {
2595 p = "NO_PROXY";
2596 no_proxy = curl_getenv(p);
2597 }
2598 if(no_proxy) {
2599 infof(data, "Uses proxy env variable %s == '%s'", p, no_proxy);
2600 }
2601 }
2602
2603 if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
2604 data->set.str[STRING_NOPROXY] : no_proxy)) {
2605 Curl_safefree(proxy);
2606 Curl_safefree(socksproxy);
2607 }
2608#ifndef CURL_DISABLE_HTTP
2609 else if(!proxy && !socksproxy)
2610 /* if the host is not in the noproxy list, detect proxy. */
2611 proxy = detect_proxy(data, conn);
2612#endif /* CURL_DISABLE_HTTP */
2613
2614 Curl_safefree(no_proxy);
2615
2616#ifdef USE_UNIX_SOCKETS
2617 /* For the time being do not mix proxy and unix domain sockets. See #1274 */
2618 if(proxy && conn->unix_domain_socket) {
2619 free(proxy);
2620 proxy = NULL;
2621 }
2622#endif
2623
2624 if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
2625 free(proxy); /* Don't bother with an empty proxy string or if the
2626 protocol doesn't work with network */
2627 proxy = NULL;
2628 }
2629 if(socksproxy && (!*socksproxy ||
2630 (conn->handler->flags & PROTOPT_NONETWORK))) {
2631 free(socksproxy); /* Don't bother with an empty socks proxy string or if
2632 the protocol doesn't work with network */
2633 socksproxy = NULL;
2634 }
2635
2636 /***********************************************************************
2637 * If this is supposed to use a proxy, we need to figure out the proxy host
2638 * name, proxy type and port number, so that we can re-use an existing
2639 * connection that may exist registered to the same proxy host.
2640 ***********************************************************************/
2641 if(proxy || socksproxy) {
2642 if(proxy) {
2643 result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype);
2644 Curl_safefree(proxy); /* parse_proxy copies the proxy string */
2645 if(result)
2646 goto out;
2647 }
2648
2649 if(socksproxy) {
2650 result = parse_proxy(data, conn, socksproxy,
2651 conn->socks_proxy.proxytype);
2652 /* parse_proxy copies the socks proxy string */
2653 Curl_safefree(socksproxy);
2654 if(result)
2655 goto out;
2656 }
2657
2658 if(conn->http_proxy.host.rawalloc) {
2659#ifdef CURL_DISABLE_HTTP
2660 /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
2661 result = CURLE_UNSUPPORTED_PROTOCOL;
2662 goto out;
2663#else
2664 /* force this connection's protocol to become HTTP if compatible */
2665 if(!(conn->handler->protocol & PROTO_FAMILY_HTTP)) {
2666 if((conn->handler->flags & PROTOPT_PROXY_AS_HTTP) &&
2667 !conn->bits.tunnel_proxy)
2668 conn->handler = &Curl_handler_http;
2669 else
2670 /* if not converting to HTTP over the proxy, enforce tunneling */
2671 conn->bits.tunnel_proxy = TRUE;
2672 }
2673 conn->bits.httpproxy = TRUE;
2674#endif
2675 }
2676 else {
2677 conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
2678 conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
2679 }
2680
2681 if(conn->socks_proxy.host.rawalloc) {
2682 if(!conn->http_proxy.host.rawalloc) {
2683 /* once a socks proxy */
2684 if(!conn->socks_proxy.user) {
2685 conn->socks_proxy.user = conn->http_proxy.user;
2686 conn->http_proxy.user = NULL;
2687 Curl_safefree(conn->socks_proxy.passwd);
2688 conn->socks_proxy.passwd = conn->http_proxy.passwd;
2689 conn->http_proxy.passwd = NULL;
2690 }
2691 }
2692 conn->bits.socksproxy = TRUE;
2693 }
2694 else
2695 conn->bits.socksproxy = FALSE; /* not a socks proxy */
2696 }
2697 else {
2698 conn->bits.socksproxy = FALSE;
2699 conn->bits.httpproxy = FALSE;
2700 }
2701 conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy;
2702
2703 if(!conn->bits.proxy) {
2704 /* we aren't using the proxy after all... */
2705 conn->bits.proxy = FALSE;
2706 conn->bits.httpproxy = FALSE;
2707 conn->bits.socksproxy = FALSE;
2708 conn->bits.proxy_user_passwd = FALSE;
2709 conn->bits.tunnel_proxy = FALSE;
2710 /* CURLPROXY_HTTPS does not have its own flag in conn->bits, yet we need
2711 to signal that CURLPROXY_HTTPS is not used for this connection */
2712 conn->http_proxy.proxytype = CURLPROXY_HTTP;
2713 }
2714
2715out:
2716
2717 free(socksproxy);
2718 free(proxy);
2719 return result;
2720}
2721#endif /* CURL_DISABLE_PROXY */
2722
2723/*
2724 * Curl_parse_login_details()
2725 *
2726 * This is used to parse a login string for user name, password and options in
2727 * the following formats:
2728 *
2729 * user
2730 * user:password
2731 * user:password;options
2732 * user;options
2733 * user;options:password
2734 * :password
2735 * :password;options
2736 * ;options
2737 * ;options:password
2738 *
2739 * Parameters:
2740 *
2741 * login [in] - The login string.
2742 * len [in] - The length of the login string.
2743 * userp [in/out] - The address where a pointer to newly allocated memory
2744 * holding the user will be stored upon completion.
2745 * passwdp [in/out] - The address where a pointer to newly allocated memory
2746 * holding the password will be stored upon completion.
2747 * optionsp [in/out] - The address where a pointer to newly allocated memory
2748 * holding the options will be stored upon completion.
2749 *
2750 * Returns CURLE_OK on success.
2751 */
2752CURLcode Curl_parse_login_details(const char *login, const size_t len,
2753 char **userp, char **passwdp,
2754 char **optionsp)
2755{
2756 CURLcode result = CURLE_OK;
2757 char *ubuf = NULL;
2758 char *pbuf = NULL;
2759 char *obuf = NULL;
2760 const char *psep = NULL;
2761 const char *osep = NULL;
2762 size_t ulen;
2763 size_t plen;
2764 size_t olen;
2765
2766 /* the input length check is because this is called directcly from setopt
2767 and isn't going through the regular string length check */
2768 size_t llen = strlen(login);
2769 if(llen > CURL_MAX_INPUT_LENGTH)
2770 return CURLE_BAD_FUNCTION_ARGUMENT;
2771
2772 /* Attempt to find the password separator */
2773 if(passwdp) {
2774 psep = strchr(login, ':');
2775
2776 /* Within the constraint of the login string */
2777 if(psep >= login + len)
2778 psep = NULL;
2779 }
2780
2781 /* Attempt to find the options separator */
2782 if(optionsp) {
2783 osep = strchr(login, ';');
2784
2785 /* Within the constraint of the login string */
2786 if(osep >= login + len)
2787 osep = NULL;
2788 }
2789
2790 /* Calculate the portion lengths */
2791 ulen = (psep ?
2792 (size_t)(osep && psep > osep ? osep - login : psep - login) :
2793 (osep ? (size_t)(osep - login) : len));
2794 plen = (psep ?
2795 (osep && osep > psep ? (size_t)(osep - psep) :
2796 (size_t)(login + len - psep)) - 1 : 0);
2797 olen = (osep ?
2798 (psep && psep > osep ? (size_t)(psep - osep) :
2799 (size_t)(login + len - osep)) - 1 : 0);
2800
2801 /* Allocate the user portion buffer */
2802 if(userp && ulen) {
2803 ubuf = malloc(ulen + 1);
2804 if(!ubuf)
2805 result = CURLE_OUT_OF_MEMORY;
2806 }
2807
2808 /* Allocate the password portion buffer */
2809 if(!result && passwdp && plen) {
2810 pbuf = malloc(plen + 1);
2811 if(!pbuf) {
2812 free(ubuf);
2813 result = CURLE_OUT_OF_MEMORY;
2814 }
2815 }
2816
2817 /* Allocate the options portion buffer */
2818 if(!result && optionsp && olen) {
2819 obuf = malloc(olen + 1);
2820 if(!obuf) {
2821 free(pbuf);
2822 free(ubuf);
2823 result = CURLE_OUT_OF_MEMORY;
2824 }
2825 }
2826
2827 if(!result) {
2828 /* Store the user portion if necessary */
2829 if(ubuf) {
2830 memcpy(ubuf, login, ulen);
2831 ubuf[ulen] = '\0';
2832 Curl_safefree(*userp);
2833 *userp = ubuf;
2834 }
2835
2836 /* Store the password portion if necessary */
2837 if(pbuf) {
2838 memcpy(pbuf, psep + 1, plen);
2839 pbuf[plen] = '\0';
2840 Curl_safefree(*passwdp);
2841 *passwdp = pbuf;
2842 }
2843
2844 /* Store the options portion if necessary */
2845 if(obuf) {
2846 memcpy(obuf, osep + 1, olen);
2847 obuf[olen] = '\0';
2848 Curl_safefree(*optionsp);
2849 *optionsp = obuf;
2850 }
2851 }
2852
2853 return result;
2854}
2855
2856/*************************************************************
2857 * Figure out the remote port number and fix it in the URL
2858 *
2859 * No matter if we use a proxy or not, we have to figure out the remote
2860 * port number of various reasons.
2861 *
2862 * The port number embedded in the URL is replaced, if necessary.
2863 *************************************************************/
2864static CURLcode parse_remote_port(struct Curl_easy *data,
2865 struct connectdata *conn)
2866{
2867
2868 if(data->set.use_port && data->state.allow_port) {
2869 /* if set, we use this instead of the port possibly given in the URL */
2870 char portbuf[16];
2871 CURLUcode uc;
2872 conn->remote_port = (unsigned short)data->set.use_port;
2873 msnprintf(portbuf, sizeof(portbuf), "%d", conn->remote_port);
2874 uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0);
2875 if(uc)
2876 return CURLE_OUT_OF_MEMORY;
2877 }
2878
2879 return CURLE_OK;
2880}
2881
2882/*
2883 * Override the login details from the URL with that in the CURLOPT_USERPWD
2884 * option or a .netrc file, if applicable.
2885 */
2886static CURLcode override_login(struct Curl_easy *data,
2887 struct connectdata *conn)
2888{
2889 CURLUcode uc;
2890 char **userp = &conn->user;
2891 char **passwdp = &conn->passwd;
2892 char **optionsp = &conn->options;
2893
2894#ifndef CURL_DISABLE_NETRC
2895 if(data->set.use_netrc == CURL_NETRC_REQUIRED && conn->bits.user_passwd) {
2896 Curl_safefree(*userp);
2897 Curl_safefree(*passwdp);
2898 conn->bits.user_passwd = FALSE; /* disable user+password */
2899 }
2900#endif
2901
2902 if(data->set.str[STRING_OPTIONS]) {
2903 free(*optionsp);
2904 *optionsp = strdup(data->set.str[STRING_OPTIONS]);
2905 if(!*optionsp)
2906 return CURLE_OUT_OF_MEMORY;
2907 }
2908
2909#ifndef CURL_DISABLE_NETRC
2910 conn->bits.netrc = FALSE;
2911 if(data->set.use_netrc && !data->set.str[STRING_USERNAME]) {
2912 bool netrc_user_changed = FALSE;
2913 bool netrc_passwd_changed = FALSE;
2914 int ret;
2915
2916 ret = Curl_parsenetrc(conn->host.name,
2917 userp, passwdp,
2918 &netrc_user_changed, &netrc_passwd_changed,
2919 data->set.str[STRING_NETRC_FILE]);
2920 if(ret > 0) {
2921 infof(data, "Couldn't find host %s in the %s file; using defaults",
2922 conn->host.name, data->set.str[STRING_NETRC_FILE]);
2923 }
2924 else if(ret < 0) {
2925 return CURLE_OUT_OF_MEMORY;
2926 }
2927 else {
2928 /* set bits.netrc TRUE to remember that we got the name from a .netrc
2929 file, so that it is safe to use even if we followed a Location: to a
2930 different host or similar. */
2931 conn->bits.netrc = TRUE;
2932 conn->bits.user_passwd = TRUE; /* enable user+password */
2933 }
2934 }
2935#endif
2936
2937 /* for updated strings, we update them in the URL */
2938 if(*userp) {
2939 CURLcode result = Curl_setstropt(&data->state.aptr.user, *userp);
2940 if(result)
2941 return result;
2942 }
2943 if(data->state.aptr.user) {
2944 uc = curl_url_set(data->state.uh, CURLUPART_USER, data->state.aptr.user,
2945 CURLU_URLENCODE);
2946 if(uc)
2947 return Curl_uc_to_curlcode(uc);
2948 if(!*userp) {
2949 *userp = strdup(data->state.aptr.user);
2950 if(!*userp)
2951 return CURLE_OUT_OF_MEMORY;
2952 }
2953 }
2954
2955 if(*passwdp) {
2956 CURLcode result = Curl_setstropt(&data->state.aptr.passwd, *passwdp);
2957 if(result)
2958 return result;
2959 }
2960 if(data->state.aptr.passwd) {
2961 uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD,
2962 data->state.aptr.passwd, CURLU_URLENCODE);
2963 if(uc)
2964 return Curl_uc_to_curlcode(uc);
2965 if(!*passwdp) {
2966 *passwdp = strdup(data->state.aptr.passwd);
2967 if(!*passwdp)
2968 return CURLE_OUT_OF_MEMORY;
2969 }
2970 }
2971
2972 return CURLE_OK;
2973}
2974
2975/*
2976 * Set the login details so they're available in the connection
2977 */
2978static CURLcode set_login(struct connectdata *conn)
2979{
2980 CURLcode result = CURLE_OK;
2981 const char *setuser = CURL_DEFAULT_USER;
2982 const char *setpasswd = CURL_DEFAULT_PASSWORD;
2983
2984 /* If our protocol needs a password and we have none, use the defaults */
2985 if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd)
2986 ;
2987 else {
2988 setuser = "";
2989 setpasswd = "";
2990 }
2991 /* Store the default user */
2992 if(!conn->user) {
2993 conn->user = strdup(setuser);
2994 if(!conn->user)
2995 return CURLE_OUT_OF_MEMORY;
2996 }
2997
2998 /* Store the default password */
2999 if(!conn->passwd) {
3000 conn->passwd = strdup(setpasswd);
3001 if(!conn->passwd)
3002 result = CURLE_OUT_OF_MEMORY;
3003 }
3004
3005 return result;
3006}
3007
3008/*
3009 * Parses a "host:port" string to connect to.
3010 * The hostname and the port may be empty; in this case, NULL is returned for
3011 * the hostname and -1 for the port.
3012 */
3013static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
3014 const char *host,
3015 char **hostname_result,
3016 int *port_result)
3017{
3018 char *host_dup;
3019 char *hostptr;
3020 char *host_portno;
3021 char *portptr;
3022 int port = -1;
3023 CURLcode result = CURLE_OK;
3024
3025#if defined(CURL_DISABLE_VERBOSE_STRINGS)
3026 (void) data;
3027#endif
3028
3029 *hostname_result = NULL;
3030 *port_result = -1;
3031
3032 if(!host || !*host)
3033 return CURLE_OK;
3034
3035 host_dup = strdup(host);
3036 if(!host_dup)
3037 return CURLE_OUT_OF_MEMORY;
3038
3039 hostptr = host_dup;
3040
3041 /* start scanning for port number at this point */
3042 portptr = hostptr;
3043
3044 /* detect and extract RFC6874-style IPv6-addresses */
3045 if(*hostptr == '[') {
3046#ifdef ENABLE_IPV6
3047 char *ptr = ++hostptr; /* advance beyond the initial bracket */
3048 while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
3049 ptr++;
3050 if(*ptr == '%') {
3051 /* There might be a zone identifier */
3052 if(strncmp("%25", ptr, 3))
3053 infof(data, "Please URL encode %% as %%25, see RFC 6874.");
3054 ptr++;
3055 /* Allow unreserved characters as defined in RFC 3986 */
3056 while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
3057 (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
3058 ptr++;
3059 }
3060 if(*ptr == ']')
3061 /* yeps, it ended nicely with a bracket as well */
3062 *ptr++ = '\0';
3063 else
3064 infof(data, "Invalid IPv6 address format");
3065 portptr = ptr;
3066 /* Note that if this didn't end with a bracket, we still advanced the
3067 * hostptr first, but I can't see anything wrong with that as no host
3068 * name nor a numeric can legally start with a bracket.
3069 */
3070#else
3071 failf(data, "Use of IPv6 in *_CONNECT_TO without IPv6 support built-in!");
3072 result = CURLE_NOT_BUILT_IN;
3073 goto error;
3074#endif
3075 }
3076
3077 /* Get port number off server.com:1080 */
3078 host_portno = strchr(portptr, ':');
3079 if(host_portno) {
3080 char *endp = NULL;
3081 *host_portno = '\0'; /* cut off number from host name */
3082 host_portno++;
3083 if(*host_portno) {
3084 long portparse = strtol(host_portno, &endp, 10);
3085 if((endp && *endp) || (portparse < 0) || (portparse > 65535)) {
3086 failf(data, "No valid port number in connect to host string (%s)",
3087 host_portno);
3088 result = CURLE_SETOPT_OPTION_SYNTAX;
3089 goto error;
3090 }
3091 else
3092 port = (int)portparse; /* we know it will fit */
3093 }
3094 }
3095
3096 /* now, clone the cleaned host name */
3097 if(hostptr) {
3098 *hostname_result = strdup(hostptr);
3099 if(!*hostname_result) {
3100 result = CURLE_OUT_OF_MEMORY;
3101 goto error;
3102 }
3103 }
3104
3105 *port_result = port;
3106
3107 error:
3108 free(host_dup);
3109 return result;
3110}
3111
3112/*
3113 * Parses one "connect to" string in the form:
3114 * "HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT".
3115 */
3116static CURLcode parse_connect_to_string(struct Curl_easy *data,
3117 struct connectdata *conn,
3118 const char *conn_to_host,
3119 char **host_result,
3120 int *port_result)
3121{
3122 CURLcode result = CURLE_OK;
3123 const char *ptr = conn_to_host;
3124 int host_match = FALSE;
3125 int port_match = FALSE;
3126
3127 *host_result = NULL;
3128 *port_result = -1;
3129
3130 if(*ptr == ':') {
3131 /* an empty hostname always matches */
3132 host_match = TRUE;
3133 ptr++;
3134 }
3135 else {
3136 /* check whether the URL's hostname matches */
3137 size_t hostname_to_match_len;
3138 char *hostname_to_match = aprintf("%s%s%s",
3139 conn->bits.ipv6_ip ? "[" : "",
3140 conn->host.name,
3141 conn->bits.ipv6_ip ? "]" : "");
3142 if(!hostname_to_match)
3143 return CURLE_OUT_OF_MEMORY;
3144 hostname_to_match_len = strlen(hostname_to_match);
3145 host_match = strncasecompare(ptr, hostname_to_match,
3146 hostname_to_match_len);
3147 free(hostname_to_match);
3148 ptr += hostname_to_match_len;
3149
3150 host_match = host_match && *ptr == ':';
3151 ptr++;
3152 }
3153
3154 if(host_match) {
3155 if(*ptr == ':') {
3156 /* an empty port always matches */
3157 port_match = TRUE;
3158 ptr++;
3159 }
3160 else {
3161 /* check whether the URL's port matches */
3162 char *ptr_next = strchr(ptr, ':');
3163 if(ptr_next) {
3164 char *endp = NULL;
3165 long port_to_match = strtol(ptr, &endp, 10);
3166 if((endp == ptr_next) && (port_to_match == conn->remote_port)) {
3167 port_match = TRUE;
3168 ptr = ptr_next + 1;
3169 }
3170 }
3171 }
3172 }
3173
3174 if(host_match && port_match) {
3175 /* parse the hostname and port to connect to */
3176 result = parse_connect_to_host_port(data, ptr, host_result, port_result);
3177 }
3178
3179 return result;
3180}
3181
3182/*
3183 * Processes all strings in the "connect to" slist, and uses the "connect
3184 * to host" and "connect to port" of the first string that matches.
3185 */
3186static CURLcode parse_connect_to_slist(struct Curl_easy *data,
3187 struct connectdata *conn,
3188 struct curl_slist *conn_to_host)
3189{
3190 CURLcode result = CURLE_OK;
3191 char *host = NULL;
3192 int port = -1;
3193
3194 while(conn_to_host && !host && port == -1) {
3195 result = parse_connect_to_string(data, conn, conn_to_host->data,
3196 &host, &port);
3197 if(result)
3198 return result;
3199
3200 if(host && *host) {
3201 conn->conn_to_host.rawalloc = host;
3202 conn->conn_to_host.name = host;
3203 conn->bits.conn_to_host = TRUE;
3204
3205 infof(data, "Connecting to hostname: %s", host);
3206 }
3207 else {
3208 /* no "connect to host" */
3209 conn->bits.conn_to_host = FALSE;
3210 Curl_safefree(host);
3211 }
3212
3213 if(port >= 0) {
3214 conn->conn_to_port = port;
3215 conn->bits.conn_to_port = TRUE;
3216 infof(data, "Connecting to port: %d", port);
3217 }
3218 else {
3219 /* no "connect to port" */
3220 conn->bits.conn_to_port = FALSE;
3221 port = -1;
3222 }
3223
3224 conn_to_host = conn_to_host->next;
3225 }
3226
3227#ifndef CURL_DISABLE_ALTSVC
3228 if(data->asi && !host && (port == -1) &&
3229 ((conn->handler->protocol == CURLPROTO_HTTPS) ||
3230#ifdef CURLDEBUG
3231 /* allow debug builds to circumvent the HTTPS restriction */
3232 getenv("CURL_ALTSVC_HTTP")
3233#else
3234 0
3235#endif
3236 )) {
3237 /* no connect_to match, try alt-svc! */
3238 enum alpnid srcalpnid;
3239 bool hit;
3240 struct altsvc *as;
3241 const int allowed_versions = ( ALPN_h1
3242#ifdef USE_NGHTTP2
3243 | ALPN_h2
3244#endif
3245#ifdef ENABLE_QUIC
3246 | ALPN_h3
3247#endif
3248 ) & data->asi->flags;
3249
3250 host = conn->host.rawalloc;
3251#ifdef USE_NGHTTP2
3252 /* with h2 support, check that first */
3253 srcalpnid = ALPN_h2;
3254 hit = Curl_altsvc_lookup(data->asi,
3255 srcalpnid, host, conn->remote_port, /* from */
3256 &as /* to */,
3257 allowed_versions);
3258 if(!hit)
3259#endif
3260 {
3261 srcalpnid = ALPN_h1;
3262 hit = Curl_altsvc_lookup(data->asi,
3263 srcalpnid, host, conn->remote_port, /* from */
3264 &as /* to */,
3265 allowed_versions);
3266 }
3267 if(hit) {
3268 char *hostd = strdup((char *)as->dst.host);
3269 if(!hostd)
3270 return CURLE_OUT_OF_MEMORY;
3271 conn->conn_to_host.rawalloc = hostd;
3272 conn->conn_to_host.name = hostd;
3273 conn->bits.conn_to_host = TRUE;
3274 conn->conn_to_port = as->dst.port;
3275 conn->bits.conn_to_port = TRUE;
3276 conn->bits.altused = TRUE;
3277 infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d",
3278 Curl_alpnid2str(srcalpnid), host, conn->remote_port,
3279 Curl_alpnid2str(as->dst.alpnid), hostd, as->dst.port);
3280 if(srcalpnid != as->dst.alpnid) {
3281 /* protocol version switch */
3282 switch(as->dst.alpnid) {
3283 case ALPN_h1:
3284 conn->httpversion = 11;
3285 break;
3286 case ALPN_h2:
3287 conn->httpversion = 20;
3288 break;
3289 case ALPN_h3:
3290 conn->transport = TRNSPRT_QUIC;
3291 conn->httpversion = 30;
3292 break;
3293 default: /* shouldn't be possible */
3294 break;
3295 }
3296 }
3297 }
3298 }
3299#endif
3300
3301 return result;
3302}
3303
3304/*************************************************************
3305 * Resolve the address of the server or proxy
3306 *************************************************************/
3307static CURLcode resolve_server(struct Curl_easy *data,
3308 struct connectdata *conn,
3309 bool *async)
3310{
3311 CURLcode result = CURLE_OK;
3312 timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
3313
3314 DEBUGASSERT(conn);
3315 DEBUGASSERT(data);
3316 /*************************************************************
3317 * Resolve the name of the server or proxy
3318 *************************************************************/
3319 if(conn->bits.reuse)
3320 /* We're reusing the connection - no need to resolve anything, and
3321 idnconvert_hostname() was called already in create_conn() for the re-use
3322 case. */
3323 *async = FALSE;
3324
3325 else {
3326 /* this is a fresh connect */
3327 int rc;
3328 struct Curl_dns_entry *hostaddr = NULL;
3329
3330#ifdef USE_UNIX_SOCKETS
3331 if(conn->unix_domain_socket) {
3332 /* Unix domain sockets are local. The host gets ignored, just use the
3333 * specified domain socket address. Do not cache "DNS entries". There is
3334 * no DNS involved and we already have the filesystem path available */
3335 const char *path = conn->unix_domain_socket;
3336
3337 hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
3338 if(!hostaddr)
3339 result = CURLE_OUT_OF_MEMORY;
3340 else {
3341 bool longpath = FALSE;
3342 hostaddr->addr = Curl_unix2addr(path, &longpath,
3343 conn->bits.abstract_unix_socket);
3344 if(hostaddr->addr)
3345 hostaddr->inuse++;
3346 else {
3347 /* Long paths are not supported for now */
3348 if(longpath) {
3349 failf(data, "Unix socket path too long: '%s'", path);
3350 result = CURLE_COULDNT_RESOLVE_HOST;
3351 }
3352 else
3353 result = CURLE_OUT_OF_MEMORY;
3354 free(hostaddr);
3355 hostaddr = NULL;
3356 }
3357 }
3358 }
3359 else
3360#endif
3361
3362 if(!conn->bits.proxy) {
3363 struct hostname *connhost;
3364 if(conn->bits.conn_to_host)
3365 connhost = &conn->conn_to_host;
3366 else
3367 connhost = &conn->host;
3368
3369 /* If not connecting via a proxy, extract the port from the URL, if it is
3370 * there, thus overriding any defaults that might have been set above. */
3371 if(conn->bits.conn_to_port)
3372 conn->port = conn->conn_to_port;
3373 else
3374 conn->port = conn->remote_port;
3375
3376 /* Resolve target host right on */
3377 conn->hostname_resolve = strdup(connhost->name);
3378 if(!conn->hostname_resolve)
3379 return CURLE_OUT_OF_MEMORY;
3380 rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
3381 &hostaddr, timeout_ms);
3382 if(rc == CURLRESOLV_PENDING)
3383 *async = TRUE;
3384
3385 else if(rc == CURLRESOLV_TIMEDOUT) {
3386 failf(data, "Failed to resolve host '%s' with timeout after %ld ms",
3387 connhost->dispname,
3388 Curl_timediff(Curl_now(), data->progress.t_startsingle));
3389 result = CURLE_OPERATION_TIMEDOUT;
3390 }
3391 else if(!hostaddr) {
3392 failf(data, "Could not resolve host: %s", connhost->dispname);
3393 result = CURLE_COULDNT_RESOLVE_HOST;
3394 /* don't return yet, we need to clean up the timeout first */
3395 }
3396 }
3397#ifndef CURL_DISABLE_PROXY
3398 else {
3399 /* This is a proxy that hasn't been resolved yet. */
3400
3401 struct hostname * const host = conn->bits.socksproxy ?
3402 &conn->socks_proxy.host : &conn->http_proxy.host;
3403
3404 /* resolve proxy */
3405 conn->hostname_resolve = strdup(host->name);
3406 if(!conn->hostname_resolve)
3407 return CURLE_OUT_OF_MEMORY;
3408 rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
3409 &hostaddr, timeout_ms);
3410
3411 if(rc == CURLRESOLV_PENDING)
3412 *async = TRUE;
3413
3414 else if(rc == CURLRESOLV_TIMEDOUT)
3415 result = CURLE_OPERATION_TIMEDOUT;
3416
3417 else if(!hostaddr) {
3418 failf(data, "Couldn't resolve proxy '%s'", host->dispname);
3419 result = CURLE_COULDNT_RESOLVE_PROXY;
3420 /* don't return yet, we need to clean up the timeout first */
3421 }
3422 }
3423#endif
3424 DEBUGASSERT(conn->dns_entry == NULL);
3425 conn->dns_entry = hostaddr;
3426 }
3427
3428 return result;
3429}
3430
3431/*
3432 * Cleanup the connection just allocated before we can move along and use the
3433 * previously existing one. All relevant data is copied over and old_conn is
3434 * ready for freeing once this function returns.
3435 */
3436static void reuse_conn(struct Curl_easy *data,
3437 struct connectdata *old_conn,
3438 struct connectdata *conn)
3439{
3440 /* 'local_ip' and 'local_port' get filled with local's numerical
3441 ip address and port number whenever an outgoing connection is
3442 **established** from the primary socket to a remote address. */
3443 char local_ip[MAX_IPADR_LEN] = "";
3444 int local_port = -1;
3445#ifndef CURL_DISABLE_PROXY
3446 Curl_free_idnconverted_hostname(&old_conn->http_proxy.host);
3447 Curl_free_idnconverted_hostname(&old_conn->socks_proxy.host);
3448
3449 free(old_conn->http_proxy.host.rawalloc);
3450 free(old_conn->socks_proxy.host.rawalloc);
3451 Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
3452#endif
3453 /* free the SSL config struct from this connection struct as this was
3454 allocated in vain and is targeted for destruction */
3455 Curl_free_primary_ssl_config(&old_conn->ssl_config);
3456
3457 /* get the user+password information from the old_conn struct since it may
3458 * be new for this request even when we re-use an existing connection */
3459 conn->bits.user_passwd = old_conn->bits.user_passwd;
3460 if(conn->bits.user_passwd) {
3461 /* use the new user name and password though */
3462 Curl_safefree(conn->user);
3463 Curl_safefree(conn->passwd);
3464 conn->user = old_conn->user;
3465 conn->passwd = old_conn->passwd;
3466 old_conn->user = NULL;
3467 old_conn->passwd = NULL;
3468 }
3469
3470#ifndef CURL_DISABLE_PROXY
3471 conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
3472 if(conn->bits.proxy_user_passwd) {
3473 /* use the new proxy user name and proxy password though */
3474 Curl_safefree(conn->http_proxy.user);
3475 Curl_safefree(conn->socks_proxy.user);
3476 Curl_safefree(conn->http_proxy.passwd);
3477 Curl_safefree(conn->socks_proxy.passwd);
3478 conn->http_proxy.user = old_conn->http_proxy.user;
3479 conn->socks_proxy.user = old_conn->socks_proxy.user;
3480 conn->http_proxy.passwd = old_conn->http_proxy.passwd;
3481 conn->socks_proxy.passwd = old_conn->socks_proxy.passwd;
3482 old_conn->http_proxy.user = NULL;
3483 old_conn->socks_proxy.user = NULL;
3484 old_conn->http_proxy.passwd = NULL;
3485 old_conn->socks_proxy.passwd = NULL;
3486 }
3487 Curl_safefree(old_conn->http_proxy.user);
3488 Curl_safefree(old_conn->socks_proxy.user);
3489 Curl_safefree(old_conn->http_proxy.passwd);
3490 Curl_safefree(old_conn->socks_proxy.passwd);
3491#endif
3492
3493 /* host can change, when doing keepalive with a proxy or if the case is
3494 different this time etc */
3495 Curl_free_idnconverted_hostname(&conn->host);
3496 Curl_free_idnconverted_hostname(&conn->conn_to_host);
3497 Curl_safefree(conn->host.rawalloc);
3498 Curl_safefree(conn->conn_to_host.rawalloc);
3499 conn->host = old_conn->host;
3500 conn->conn_to_host = old_conn->conn_to_host;
3501 conn->conn_to_port = old_conn->conn_to_port;
3502 conn->remote_port = old_conn->remote_port;
3503 Curl_safefree(conn->hostname_resolve);
3504
3505 conn->hostname_resolve = old_conn->hostname_resolve;
3506 old_conn->hostname_resolve = NULL;
3507
3508 /* persist connection info in session handle */
3509 if(conn->transport == TRNSPRT_TCP) {
3510 Curl_conninfo_local(data, conn->sock[FIRSTSOCKET],
3511 local_ip, &local_port);
3512 }
3513 Curl_persistconninfo(data, conn, local_ip, local_port);
3514
3515 conn_reset_all_postponed_data(old_conn); /* free buffers */
3516
3517 /* re-use init */
3518 conn->bits.reuse = TRUE; /* yes, we're re-using here */
3519
3520 Curl_safefree(old_conn->user);
3521 Curl_safefree(old_conn->passwd);
3522 Curl_safefree(old_conn->options);
3523 Curl_safefree(old_conn->localdev);
3524 Curl_llist_destroy(&old_conn->easyq, NULL);
3525
3526#ifdef USE_UNIX_SOCKETS
3527 Curl_safefree(old_conn->unix_domain_socket);
3528#endif
3529}
3530
3531/**
3532 * create_conn() sets up a new connectdata struct, or re-uses an already
3533 * existing one, and resolves host name.
3534 *
3535 * if this function returns CURLE_OK and *async is set to TRUE, the resolve
3536 * response will be coming asynchronously. If *async is FALSE, the name is
3537 * already resolved.
3538 *
3539 * @param data The sessionhandle pointer
3540 * @param in_connect is set to the next connection data pointer
3541 * @param async is set TRUE when an async DNS resolution is pending
3542 * @see Curl_setup_conn()
3543 *
3544 */
3545
3546static CURLcode create_conn(struct Curl_easy *data,
3547 struct connectdata **in_connect,
3548 bool *async)
3549{
3550 CURLcode result = CURLE_OK;
3551 struct connectdata *conn;
3552 struct connectdata *conn_temp = NULL;
3553 bool reuse;
3554 bool connections_available = TRUE;
3555 bool force_reuse = FALSE;
3556 bool waitpipe = FALSE;
3557 size_t max_host_connections = Curl_multi_max_host_connections(data->multi);
3558 size_t max_total_connections = Curl_multi_max_total_connections(data->multi);
3559
3560 *async = FALSE;
3561 *in_connect = NULL;
3562
3563 /*************************************************************
3564 * Check input data
3565 *************************************************************/
3566 if(!data->state.url) {
3567 result = CURLE_URL_MALFORMAT;
3568 goto out;
3569 }
3570
3571 /* First, split up the current URL in parts so that we can use the
3572 parts for checking against the already present connections. In order
3573 to not have to modify everything at once, we allocate a temporary
3574 connection data struct and fill in for comparison purposes. */
3575 conn = allocate_conn(data);
3576
3577 if(!conn) {
3578 result = CURLE_OUT_OF_MEMORY;
3579 goto out;
3580 }
3581
3582 /* We must set the return variable as soon as possible, so that our
3583 parent can cleanup any possible allocs we may have done before
3584 any failure */
3585 *in_connect = conn;
3586
3587 result = parseurlandfillconn(data, conn);
3588 if(result)
3589 goto out;
3590
3591 if(data->set.str[STRING_SASL_AUTHZID]) {
3592 conn->sasl_authzid = strdup(data->set.str[STRING_SASL_AUTHZID]);
3593 if(!conn->sasl_authzid) {
3594 result = CURLE_OUT_OF_MEMORY;
3595 goto out;
3596 }
3597 }
3598
3599#ifdef USE_UNIX_SOCKETS
3600 if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
3601 conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
3602 if(!conn->unix_domain_socket) {
3603 result = CURLE_OUT_OF_MEMORY;
3604 goto out;
3605 }
3606 conn->bits.abstract_unix_socket = data->set.abstract_unix_socket;
3607 }
3608#endif
3609
3610 /* After the unix socket init but before the proxy vars are used, parse and
3611 initialize the proxy vars */
3612#ifndef CURL_DISABLE_PROXY
3613 result = create_conn_helper_init_proxy(data, conn);
3614 if(result)
3615 goto out;
3616
3617 /*************************************************************
3618 * If the protocol is using SSL and HTTP proxy is used, we set
3619 * the tunnel_proxy bit.
3620 *************************************************************/
3621 if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
3622 conn->bits.tunnel_proxy = TRUE;
3623#endif
3624
3625 /*************************************************************
3626 * Figure out the remote port number and fix it in the URL
3627 *************************************************************/
3628 result = parse_remote_port(data, conn);
3629 if(result)
3630 goto out;
3631
3632 /* Check for overridden login details and set them accordingly so that
3633 they are known when protocol->setup_connection is called! */
3634 result = override_login(data, conn);
3635 if(result)
3636 goto out;
3637
3638 result = set_login(conn); /* default credentials */
3639 if(result)
3640 goto out;
3641
3642 /*************************************************************
3643 * Process the "connect to" linked list of hostname/port mappings.
3644 * Do this after the remote port number has been fixed in the URL.
3645 *************************************************************/
3646 result = parse_connect_to_slist(data, conn, data->set.connect_to);
3647 if(result)
3648 goto out;
3649
3650 /*************************************************************
3651 * IDN-convert the hostnames
3652 *************************************************************/
3653 result = Curl_idnconvert_hostname(data, &conn->host);
3654 if(result)
3655 goto out;
3656 if(conn->bits.conn_to_host) {
3657 result = Curl_idnconvert_hostname(data, &conn->conn_to_host);
3658 if(result)
3659 goto out;
3660 }
3661#ifndef CURL_DISABLE_PROXY
3662 if(conn->bits.httpproxy) {
3663 result = Curl_idnconvert_hostname(data, &conn->http_proxy.host);
3664 if(result)
3665 goto out;
3666 }
3667 if(conn->bits.socksproxy) {
3668 result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host);
3669 if(result)
3670 goto out;
3671 }
3672#endif
3673
3674 /*************************************************************
3675 * Check whether the host and the "connect to host" are equal.
3676 * Do this after the hostnames have been IDN-converted.
3677 *************************************************************/
3678 if(conn->bits.conn_to_host &&
3679 strcasecompare(conn->conn_to_host.name, conn->host.name)) {
3680 conn->bits.conn_to_host = FALSE;
3681 }
3682
3683 /*************************************************************
3684 * Check whether the port and the "connect to port" are equal.
3685 * Do this after the remote port number has been fixed in the URL.
3686 *************************************************************/
3687 if(conn->bits.conn_to_port && conn->conn_to_port == conn->remote_port) {
3688 conn->bits.conn_to_port = FALSE;
3689 }
3690
3691#ifndef CURL_DISABLE_PROXY
3692 /*************************************************************
3693 * If the "connect to" feature is used with an HTTP proxy,
3694 * we set the tunnel_proxy bit.
3695 *************************************************************/
3696 if((conn->bits.conn_to_host || conn->bits.conn_to_port) &&
3697 conn->bits.httpproxy)
3698 conn->bits.tunnel_proxy = TRUE;
3699#endif
3700
3701 /*************************************************************
3702 * Setup internals depending on protocol. Needs to be done after
3703 * we figured out what/if proxy to use.
3704 *************************************************************/
3705 result = setup_connection_internals(data, conn);
3706 if(result)
3707 goto out;
3708
3709 conn->recv[FIRSTSOCKET] = Curl_recv_plain;
3710 conn->send[FIRSTSOCKET] = Curl_send_plain;
3711 conn->recv[SECONDARYSOCKET] = Curl_recv_plain;
3712 conn->send[SECONDARYSOCKET] = Curl_send_plain;
3713
3714 conn->bits.tcp_fastopen = data->set.tcp_fastopen;
3715
3716 /***********************************************************************
3717 * file: is a special case in that it doesn't need a network connection
3718 ***********************************************************************/
3719#ifndef CURL_DISABLE_FILE
3720 if(conn->handler->flags & PROTOPT_NONETWORK) {
3721 bool done;
3722 /* this is supposed to be the connect function so we better at least check
3723 that the file is present here! */
3724 DEBUGASSERT(conn->handler->connect_it);
3725 Curl_persistconninfo(data, conn, NULL, -1);
3726 result = conn->handler->connect_it(data, &done);
3727
3728 /* Setup a "faked" transfer that'll do nothing */
3729 if(!result) {
3730 conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
3731
3732 Curl_attach_connnection(data, conn);
3733 result = Curl_conncache_add_conn(data);
3734 if(result)
3735 goto out;
3736
3737 /*
3738 * Setup whatever necessary for a resumed transfer
3739 */
3740 result = setup_range(data);
3741 if(result) {
3742 DEBUGASSERT(conn->handler->done);
3743 /* we ignore the return code for the protocol-specific DONE */
3744 (void)conn->handler->done(data, result, FALSE);
3745 goto out;
3746 }
3747 Curl_setup_transfer(data, -1, -1, FALSE, -1);
3748 }
3749
3750 /* since we skip do_init() */
3751 Curl_init_do(data, conn);
3752
3753 goto out;
3754 }
3755#endif
3756
3757 /* Get a cloned copy of the SSL config situation stored in the
3758 connection struct. But to get this going nicely, we must first make
3759 sure that the strings in the master copy are pointing to the correct
3760 strings in the session handle strings array!
3761
3762 Keep in mind that the pointers in the master copy are pointing to strings
3763 that will be freed as part of the Curl_easy struct, but all cloned
3764 copies will be separately allocated.
3765 */
3766 data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
3767 data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
3768 data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
3769 data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
3770 data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
3771 data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
3772 data->set.ssl.primary.cipher_list =
3773 data->set.str[STRING_SSL_CIPHER_LIST];
3774 data->set.ssl.primary.cipher_list13 =
3775 data->set.str[STRING_SSL_CIPHER13_LIST];
3776 data->set.ssl.primary.pinned_key =
3777 data->set.str[STRING_SSL_PINNEDPUBLICKEY];
3778 data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT];
3779 data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
3780 data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES];
3781
3782#ifndef CURL_DISABLE_PROXY
3783 data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
3784 data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
3785 data->set.proxy_ssl.primary.random_file =
3786 data->set.str[STRING_SSL_RANDOM_FILE];
3787 data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
3788 data->set.proxy_ssl.primary.cipher_list =
3789 data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
3790 data->set.proxy_ssl.primary.cipher_list13 =
3791 data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
3792 data->set.proxy_ssl.primary.pinned_key =
3793 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
3794 data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
3795 data->set.proxy_ssl.primary.ca_info_blob =
3796 data->set.blobs[BLOB_CAINFO_PROXY];
3797 data->set.proxy_ssl.primary.issuercert =
3798 data->set.str[STRING_SSL_ISSUERCERT_PROXY];
3799 data->set.proxy_ssl.primary.issuercert_blob =
3800 data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
3801 data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
3802 data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
3803 data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
3804 data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
3805 data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
3806 data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
3807 data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
3808#endif
3809 data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
3810 data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
3811 data->set.ssl.key = data->set.str[STRING_KEY];
3812 data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
3813 data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
3814 data->set.ssl.primary.clientcert = data->set.str[STRING_CERT];
3815#ifdef USE_TLS_SRP
3816 data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME];
3817 data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
3818#ifndef CURL_DISABLE_PROXY
3819 data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
3820 data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
3821#endif
3822#endif
3823 data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
3824
3825 if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
3826 &conn->ssl_config)) {
3827 result = CURLE_OUT_OF_MEMORY;
3828 goto out;
3829 }
3830
3831#ifndef CURL_DISABLE_PROXY
3832 if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
3833 &conn->proxy_ssl_config)) {
3834 result = CURLE_OUT_OF_MEMORY;
3835 goto out;
3836 }
3837#endif
3838
3839 prune_dead_connections(data);
3840
3841 /*************************************************************
3842 * Check the current list of connections to see if we can
3843 * re-use an already existing one or if we have to create a
3844 * new one.
3845 *************************************************************/
3846
3847 DEBUGASSERT(conn->user);
3848 DEBUGASSERT(conn->passwd);
3849
3850 /* reuse_fresh is TRUE if we are told to use a new connection by force, but
3851 we only acknowledge this option if this is not a re-used connection
3852 already (which happens due to follow-location or during a HTTP
3853 authentication phase). CONNECT_ONLY transfers also refuse reuse. */
3854 if((data->set.reuse_fresh && !data->state.this_is_a_follow) ||
3855 data->set.connect_only)
3856 reuse = FALSE;
3857 else
3858 reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);
3859
3860 if(reuse) {
3861 /*
3862 * We already have a connection for this, we got the former connection in
3863 * the conn_temp variable and thus we need to cleanup the one we just
3864 * allocated before we can move along and use the previously existing one.
3865 */
3866 reuse_conn(data, conn, conn_temp);
3867#ifdef USE_SSL
3868 free(conn->ssl_extra);
3869#endif
3870 free(conn); /* we don't need this anymore */
3871 conn = conn_temp;
3872 *in_connect = conn;
3873
3874#ifndef CURL_DISABLE_PROXY
3875 infof(data, "Re-using existing connection! (#%ld) with %s %s",
3876 conn->connection_id,
3877 conn->bits.proxy?"proxy":"host",
3878 conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
3879 conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
3880 conn->host.dispname);
3881#else
3882 infof(data, "Re-using existing connection! (#%ld) with host %s",
3883 conn->connection_id, conn->host.dispname);
3884#endif
3885 }
3886 else {
3887 /* We have decided that we want a new connection. However, we may not
3888 be able to do that if we have reached the limit of how many
3889 connections we are allowed to open. */
3890
3891 if(conn->handler->flags & PROTOPT_ALPN_NPN) {
3892 /* The protocol wants it, so set the bits if enabled in the easy handle
3893 (default) */
3894 if(data->set.ssl_enable_alpn)
3895 conn->bits.tls_enable_alpn = TRUE;
3896 if(data->set.ssl_enable_npn)
3897 conn->bits.tls_enable_npn = TRUE;
3898 }
3899
3900 if(waitpipe)
3901 /* There is a connection that *might* become usable for multiplexing
3902 "soon", and we wait for that */
3903 connections_available = FALSE;
3904 else {
3905 /* this gets a lock on the conncache */
3906 const char *bundlehost;
3907 struct connectbundle *bundle =
3908 Curl_conncache_find_bundle(data, conn, data->state.conn_cache,
3909 &bundlehost);
3910
3911 if(max_host_connections > 0 && bundle &&
3912 (bundle->num_connections >= max_host_connections)) {
3913 struct connectdata *conn_candidate;
3914
3915 /* The bundle is full. Extract the oldest connection. */
3916 conn_candidate = Curl_conncache_extract_bundle(data, bundle);
3917 CONNCACHE_UNLOCK(data);
3918
3919 if(conn_candidate)
3920 (void)Curl_disconnect(data, conn_candidate, FALSE);
3921 else {
3922 infof(data, "No more connections allowed to host %s: %zu",
3923 bundlehost, max_host_connections);
3924 connections_available = FALSE;
3925 }
3926 }
3927 else
3928 CONNCACHE_UNLOCK(data);
3929
3930 }
3931
3932 if(connections_available &&
3933 (max_total_connections > 0) &&
3934 (Curl_conncache_size(data) >= max_total_connections)) {
3935 struct connectdata *conn_candidate;
3936
3937 /* The cache is full. Let's see if we can kill a connection. */
3938 conn_candidate = Curl_conncache_extract_oldest(data);
3939 if(conn_candidate)
3940 (void)Curl_disconnect(data, conn_candidate, FALSE);
3941 else {
3942 infof(data, "No connections available in cache");
3943 connections_available = FALSE;
3944 }
3945 }
3946
3947 if(!connections_available) {
3948 infof(data, "No connections available.");
3949
3950 conn_free(conn);
3951 *in_connect = NULL;
3952
3953 result = CURLE_NO_CONNECTION_AVAILABLE;
3954 goto out;
3955 }
3956 else {
3957 /*
3958 * This is a brand new connection, so let's store it in the connection
3959 * cache of ours!
3960 */
3961 Curl_attach_connnection(data, conn);
3962 result = Curl_conncache_add_conn(data);
3963 if(result)
3964 goto out;
3965 }
3966
3967#if defined(USE_NTLM)
3968 /* If NTLM is requested in a part of this connection, make sure we don't
3969 assume the state is fine as this is a fresh connection and NTLM is
3970 connection based. */
3971 if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
3972 data->state.authhost.done) {
3973 infof(data, "NTLM picked AND auth done set, clear picked!");
3974 data->state.authhost.picked = CURLAUTH_NONE;
3975 data->state.authhost.done = FALSE;
3976 }
3977
3978 if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
3979 data->state.authproxy.done) {
3980 infof(data, "NTLM-proxy picked AND auth done set, clear picked!");
3981 data->state.authproxy.picked = CURLAUTH_NONE;
3982 data->state.authproxy.done = FALSE;
3983 }
3984#endif
3985 }
3986
3987 /* Setup and init stuff before DO starts, in preparing for the transfer. */
3988 Curl_init_do(data, conn);
3989
3990 /*
3991 * Setup whatever necessary for a resumed transfer
3992 */
3993 result = setup_range(data);
3994 if(result)
3995 goto out;
3996
3997 /* Continue connectdata initialization here. */
3998
3999 /*
4000 * Inherit the proper values from the urldata struct AFTER we have arranged
4001 * the persistent connection stuff
4002 */
4003 conn->seek_func = data->set.seek_func;
4004 conn->seek_client = data->set.seek_client;
4005
4006 /*************************************************************
4007 * Resolve the address of the server or proxy
4008 *************************************************************/
4009 result = resolve_server(data, conn, async);
4010
4011 /* Strip trailing dots. resolve_server copied the name. */
4012 strip_trailing_dot(&conn->host);
4013#ifndef CURL_DISABLE_PROXY
4014 if(conn->bits.httpproxy)
4015 strip_trailing_dot(&conn->http_proxy.host);
4016 if(conn->bits.socksproxy)
4017 strip_trailing_dot(&conn->socks_proxy.host);
4018#endif
4019 if(conn->bits.conn_to_host)
4020 strip_trailing_dot(&conn->conn_to_host);
4021
4022out:
4023 return result;
4024}
4025
4026/* Curl_setup_conn() is called after the name resolve initiated in
4027 * create_conn() is all done.
4028 *
4029 * Curl_setup_conn() also handles reused connections
4030 */
4031CURLcode Curl_setup_conn(struct Curl_easy *data,
4032 bool *protocol_done)
4033{
4034 CURLcode result = CURLE_OK;
4035 struct connectdata *conn = data->conn;
4036
4037 Curl_pgrsTime(data, TIMER_NAMELOOKUP);
4038
4039 if(conn->handler->flags & PROTOPT_NONETWORK) {
4040 /* nothing to setup when not using a network */
4041 *protocol_done = TRUE;
4042 return result;
4043 }
4044 *protocol_done = FALSE; /* default to not done */
4045
4046#ifndef CURL_DISABLE_PROXY
4047 /* set proxy_connect_closed to false unconditionally already here since it
4048 is used strictly to provide extra information to a parent function in the
4049 case of proxy CONNECT failures and we must make sure we don't have it
4050 lingering set from a previous invoke */
4051 conn->bits.proxy_connect_closed = FALSE;
4052#endif
4053
4054#ifdef CURL_DO_LINEEND_CONV
4055 data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
4056#endif /* CURL_DO_LINEEND_CONV */
4057
4058 /* set start time here for timeout purposes in the connect procedure, it
4059 is later set again for the progress meter purpose */
4060 conn->now = Curl_now();
4061
4062 if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
4063 conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
4064 result = Curl_connecthost(data, conn, conn->dns_entry);
4065 if(result)
4066 return result;
4067 }
4068 else {
4069 Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
4070 if(conn->ssl[FIRSTSOCKET].use ||
4071 (conn->handler->protocol & PROTO_FAMILY_SSH))
4072 Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
4073 conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
4074 *protocol_done = TRUE;
4075 Curl_updateconninfo(data, conn, conn->sock[FIRSTSOCKET]);
4076 Curl_verboseconnect(data, conn);
4077 }
4078
4079 conn->now = Curl_now(); /* time this *after* the connect is done, we set
4080 this here perhaps a second time */
4081 return result;
4082}
4083
4084CURLcode Curl_connect(struct Curl_easy *data,
4085 bool *asyncp,
4086 bool *protocol_done)
4087{
4088 CURLcode result;
4089 struct connectdata *conn;
4090
4091 *asyncp = FALSE; /* assume synchronous resolves by default */
4092
4093 /* init the single-transfer specific data */
4094 Curl_free_request_state(data);
4095 memset(&data->req, 0, sizeof(struct SingleRequest));
4096 data->req.maxdownload = -1;
4097
4098 /* call the stuff that needs to be called */
4099 result = create_conn(data, &conn, asyncp);
4100
4101 if(!result) {
4102 if(CONN_INUSE(conn) > 1)
4103 /* multiplexed */
4104 *protocol_done = TRUE;
4105 else if(!*asyncp) {
4106 /* DNS resolution is done: that's either because this is a reused
4107 connection, in which case DNS was unnecessary, or because DNS
4108 really did finish already (synch resolver/fast async resolve) */
4109 result = Curl_setup_conn(data, protocol_done);
4110 }
4111 }
4112
4113 if(result == CURLE_NO_CONNECTION_AVAILABLE) {
4114 return result;
4115 }
4116 else if(result && conn) {
4117 /* We're not allowed to return failure with memory left allocated in the
4118 connectdata struct, free those here */
4119 Curl_detach_connnection(data);
4120 Curl_conncache_remove_conn(data, conn, TRUE);
4121 Curl_disconnect(data, conn, TRUE);
4122 }
4123
4124 return result;
4125}
4126
4127/*
4128 * Curl_init_do() inits the readwrite session. This is inited each time (in
4129 * the DO function before the protocol-specific DO functions are invoked) for
4130 * a transfer, sometimes multiple times on the same Curl_easy. Make sure
4131 * nothing in here depends on stuff that are setup dynamically for the
4132 * transfer.
4133 *
4134 * Allow this function to get called with 'conn' set to NULL.
4135 */
4136
4137CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
4138{
4139 struct SingleRequest *k = &data->req;
4140
4141 /* if this is a pushed stream, we need this: */
4142 CURLcode result = Curl_preconnect(data);
4143 if(result)
4144 return result;
4145
4146 if(conn) {
4147 conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
4148 use */
4149 /* if the protocol used doesn't support wildcards, switch it off */
4150 if(data->state.wildcardmatch &&
4151 !(conn->handler->flags & PROTOPT_WILDCARD))
4152 data->state.wildcardmatch = FALSE;
4153 }
4154
4155 data->state.done = FALSE; /* *_done() is not called yet */
4156 data->state.expect100header = FALSE;
4157
4158 if(data->set.opt_no_body)
4159 /* in HTTP lingo, no body means using the HEAD request... */
4160 data->state.httpreq = HTTPREQ_HEAD;
4161
4162 k->start = Curl_now(); /* start time */
4163 k->now = k->start; /* current time is now */
4164 k->header = TRUE; /* assume header */
4165 k->bytecount = 0;
4166 k->ignorebody = FALSE;
4167
4168 Curl_speedinit(data);
4169 Curl_pgrsSetUploadCounter(data, 0);
4170 Curl_pgrsSetDownloadCounter(data, 0);
4171
4172 return CURLE_OK;
4173}
4174