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