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