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