• 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 
940   /* curl_strequal does a case insentive comparison, so do not use it here! */
941   if(Curl_timestrcmp(data->user, needle->user) ||
942      Curl_timestrcmp(data->passwd, needle->passwd))
943     return FALSE;
944   return TRUE;
945 }
946 #else
947 /* disabled, won't get called */
948 #define proxy_info_matches(x,y) FALSE
949 #define socks_proxy_info_matches(x,y) FALSE
950 #endif
951 
952 /* A connection has to have been idle for a shorter time than 'maxage_conn' to
953    be subject for reuse. The success rate is just too low after this. */
954 
conn_maxage(struct Curl_easy * data,struct connectdata * conn,struct curltime now)955 static bool conn_maxage(struct Curl_easy *data,
956                         struct connectdata *conn,
957                         struct curltime now)
958 {
959   timediff_t idletime = Curl_timediff(now, conn->lastused);
960   idletime /= 1000; /* integer seconds is fine */
961 
962   if(idletime > data->set.maxage_conn) {
963     infof(data, "Too old connection (%ld seconds), disconnect it",
964           idletime);
965     return TRUE;
966   }
967   return FALSE;
968 }
969 
970 /*
971  * This function checks if the given connection is dead and extracts it from
972  * the connection cache if so.
973  *
974  * When this is called as a Curl_conncache_foreach() callback, the connection
975  * cache lock is held!
976  *
977  * Returns TRUE if the connection was dead and extracted.
978  */
extract_if_dead(struct connectdata * conn,struct Curl_easy * data)979 static bool extract_if_dead(struct connectdata *conn,
980                             struct Curl_easy *data)
981 {
982   if(!CONN_INUSE(conn)) {
983     /* The check for a dead socket makes sense only if the connection isn't in
984        use */
985     bool dead;
986     struct curltime now = Curl_now();
987     if(conn_maxage(data, conn, now)) {
988       /* avoid check if already too old */
989       dead = TRUE;
990     }
991     else if(conn->handler->connection_check) {
992       /* The protocol has a special method for checking the state of the
993          connection. Use it to check if the connection is dead. */
994       unsigned int state;
995 
996       /* briefly attach the connection to this transfer for the purpose of
997          checking it */
998       Curl_attach_connnection(data, conn);
999 
1000       state = conn->handler->connection_check(data, conn, CONNCHECK_ISDEAD);
1001       dead = (state & CONNRESULT_DEAD);
1002       /* detach the connection again */
1003       Curl_detach_connnection(data);
1004 
1005     }
1006     else {
1007       /* Use the general method for determining the death of a connection */
1008       dead = SocketIsDead(conn->sock[FIRSTSOCKET]);
1009     }
1010 
1011     if(dead) {
1012       infof(data, "Connection %ld seems to be dead!", conn->connection_id);
1013       Curl_conncache_remove_conn(data, conn, FALSE);
1014       return TRUE;
1015     }
1016   }
1017   return FALSE;
1018 }
1019 
1020 struct prunedead {
1021   struct Curl_easy *data;
1022   struct connectdata *extracted;
1023 };
1024 
1025 /*
1026  * Wrapper to use extract_if_dead() function in Curl_conncache_foreach()
1027  *
1028  */
call_extract_if_dead(struct Curl_easy * data,struct connectdata * conn,void * param)1029 static int call_extract_if_dead(struct Curl_easy *data,
1030                                 struct connectdata *conn, void *param)
1031 {
1032   struct prunedead *p = (struct prunedead *)param;
1033   if(extract_if_dead(conn, data)) {
1034     /* stop the iteration here, pass back the connection that was extracted */
1035     p->extracted = conn;
1036     return 1;
1037   }
1038   return 0; /* continue iteration */
1039 }
1040 
1041 /*
1042  * This function scans the connection cache for half-open/dead connections,
1043  * closes and removes them. The cleanup is done at most once per second.
1044  *
1045  * When called, this transfer has no connection attached.
1046  */
prune_dead_connections(struct Curl_easy * data)1047 static void prune_dead_connections(struct Curl_easy *data)
1048 {
1049   struct curltime now = Curl_now();
1050   timediff_t elapsed;
1051 
1052   DEBUGASSERT(!data->conn); /* no connection */
1053   CONNCACHE_LOCK(data);
1054   elapsed =
1055     Curl_timediff(now, data->state.conn_cache->last_cleanup);
1056   CONNCACHE_UNLOCK(data);
1057 
1058   if(elapsed >= 1000L) {
1059     struct prunedead prune;
1060     prune.data = data;
1061     prune.extracted = NULL;
1062     while(Curl_conncache_foreach(data, data->state.conn_cache, &prune,
1063                                  call_extract_if_dead)) {
1064       /* unlocked */
1065 
1066       /* remove connection from cache */
1067       Curl_conncache_remove_conn(data, prune.extracted, TRUE);
1068 
1069       /* disconnect it */
1070       (void)Curl_disconnect(data, prune.extracted, TRUE);
1071     }
1072     CONNCACHE_LOCK(data);
1073     data->state.conn_cache->last_cleanup = now;
1074     CONNCACHE_UNLOCK(data);
1075   }
1076 }
1077 
ssh_config_matches(struct connectdata * one,struct connectdata * two)1078 static bool ssh_config_matches(struct connectdata *one,
1079                                struct connectdata *two)
1080 {
1081   return (Curl_safecmp(one->proto.sshc.rsa, two->proto.sshc.rsa) &&
1082           Curl_safecmp(one->proto.sshc.rsa_pub, two->proto.sshc.rsa_pub));
1083 }
1084 /*
1085  * Given one filled in connection struct (named needle), this function should
1086  * detect if there already is one that has all the significant details
1087  * exactly the same and thus should be used instead.
1088  *
1089  * If there is a match, this function returns TRUE - and has marked the
1090  * connection as 'in-use'. It must later be called with ConnectionDone() to
1091  * return back to 'idle' (unused) state.
1092  *
1093  * The force_reuse flag is set if the connection must be used.
1094  */
1095 static bool
ConnectionExists(struct Curl_easy * data,struct connectdata * needle,struct connectdata ** usethis,bool * force_reuse,bool * waitpipe)1096 ConnectionExists(struct Curl_easy *data,
1097                  struct connectdata *needle,
1098                  struct connectdata **usethis,
1099                  bool *force_reuse,
1100                  bool *waitpipe)
1101 {
1102   struct connectdata *check;
1103   struct connectdata *chosen = 0;
1104   bool foundPendingCandidate = FALSE;
1105   bool canmultiplex = IsMultiplexingPossible(data, needle);
1106   struct connectbundle *bundle;
1107   const char *hostbundle;
1108 
1109 #ifdef USE_NTLM
1110   bool wantNTLMhttp = ((data->state.authhost.want &
1111                         (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
1112                        (needle->handler->protocol & PROTO_FAMILY_HTTP));
1113 #ifndef CURL_DISABLE_PROXY
1114   bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd &&
1115                             ((data->state.authproxy.want &
1116                               (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
1117                              (needle->handler->protocol & PROTO_FAMILY_HTTP)));
1118 #else
1119   bool wantProxyNTLMhttp = FALSE;
1120 #endif
1121 #endif
1122 
1123   *force_reuse = FALSE;
1124   *waitpipe = FALSE;
1125 
1126   /* Look up the bundle with all the connections to this particular host.
1127      Locks the connection cache, beware of early returns! */
1128   bundle = Curl_conncache_find_bundle(data, needle, data->state.conn_cache,
1129                                       &hostbundle);
1130   if(bundle) {
1131     /* Max pipe length is zero (unlimited) for multiplexed connections */
1132     struct Curl_llist_element *curr;
1133 
1134     infof(data, "Found bundle for host %s: %p [%s]",
1135           hostbundle, (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ?
1136                                        "can multiplex" : "serially"));
1137 
1138     /* We can't multiplex if we don't know anything about the server */
1139     if(canmultiplex) {
1140       if(bundle->multiuse == BUNDLE_UNKNOWN) {
1141         if(data->set.pipewait) {
1142           infof(data, "Server doesn't support multiplex yet, wait");
1143           *waitpipe = TRUE;
1144           CONNCACHE_UNLOCK(data);
1145           return FALSE; /* no re-use */
1146         }
1147 
1148         infof(data, "Server doesn't support multiplex (yet)");
1149         canmultiplex = FALSE;
1150       }
1151       if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
1152          !Curl_multiplex_wanted(data->multi)) {
1153         infof(data, "Could multiplex, but not asked to!");
1154         canmultiplex = FALSE;
1155       }
1156       if(bundle->multiuse == BUNDLE_NO_MULTIUSE) {
1157         infof(data, "Can not multiplex, even if we wanted to!");
1158         canmultiplex = FALSE;
1159       }
1160     }
1161 
1162     curr = bundle->conn_list.head;
1163     while(curr) {
1164       bool match = FALSE;
1165       size_t multiplexed = 0;
1166 
1167       /*
1168        * Note that if we use a HTTP proxy in normal mode (no tunneling), we
1169        * check connections to that proxy and not to the actual remote server.
1170        */
1171       check = curr->ptr;
1172       curr = curr->next;
1173 
1174       if(check->bits.connect_only || check->bits.close)
1175         /* connect-only or to-be-closed connections will not be reused */
1176         continue;
1177 
1178       if(extract_if_dead(check, data)) {
1179         /* disconnect it */
1180         (void)Curl_disconnect(data, check, TRUE);
1181         continue;
1182       }
1183 
1184       if(data->set.ipver != CURL_IPRESOLVE_WHATEVER
1185           && data->set.ipver != check->ip_version) {
1186         /* skip because the connection is not via the requested IP version */
1187         continue;
1188       }
1189 
1190       if(bundle->multiuse == BUNDLE_MULTIPLEX)
1191         multiplexed = CONN_INUSE(check);
1192 
1193       if(!canmultiplex) {
1194         if(multiplexed) {
1195           /* can only happen within multi handles, and means that another easy
1196              handle is using this connection */
1197           continue;
1198         }
1199 
1200         if(Curl_resolver_asynch()) {
1201           /* primary_ip[0] is NUL only if the resolving of the name hasn't
1202              completed yet and until then we don't re-use this connection */
1203           if(!check->primary_ip[0]) {
1204             infof(data,
1205                   "Connection #%ld is still name resolving, can't reuse",
1206                   check->connection_id);
1207             continue;
1208           }
1209         }
1210 
1211         if(check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) {
1212           foundPendingCandidate = TRUE;
1213           /* Don't pick a connection that hasn't connected yet */
1214           infof(data, "Connection #%ld isn't open enough, can't reuse",
1215                 check->connection_id);
1216           continue;
1217         }
1218       }
1219 
1220 #ifdef USE_UNIX_SOCKETS
1221       if(needle->unix_domain_socket) {
1222         if(!check->unix_domain_socket)
1223           continue;
1224         if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
1225           continue;
1226         if(needle->bits.abstract_unix_socket !=
1227            check->bits.abstract_unix_socket)
1228           continue;
1229       }
1230       else if(check->unix_domain_socket)
1231         continue;
1232 #endif
1233 
1234       if((needle->handler->flags&PROTOPT_SSL) !=
1235          (check->handler->flags&PROTOPT_SSL))
1236         /* don't do mixed SSL and non-SSL connections */
1237         if(get_protocol_family(check->handler) !=
1238            needle->handler->protocol || !check->bits.tls_upgraded)
1239           /* except protocols that have been upgraded via TLS */
1240           continue;
1241 
1242 #ifndef CURL_DISABLE_PROXY
1243       if(needle->bits.httpproxy != check->bits.httpproxy ||
1244          needle->bits.socksproxy != check->bits.socksproxy)
1245         continue;
1246 
1247       if(needle->bits.socksproxy &&
1248         !socks_proxy_info_matches(&needle->socks_proxy,
1249                                   &check->socks_proxy))
1250         continue;
1251 #endif
1252       if(needle->bits.conn_to_host != check->bits.conn_to_host)
1253         /* don't mix connections that use the "connect to host" feature and
1254          * connections that don't use this feature */
1255         continue;
1256 
1257       if(needle->bits.conn_to_port != check->bits.conn_to_port)
1258         /* don't mix connections that use the "connect to port" feature and
1259          * connections that don't use this feature */
1260         continue;
1261 
1262 #ifndef CURL_DISABLE_PROXY
1263       if(needle->bits.httpproxy) {
1264         if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
1265           continue;
1266 
1267         if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
1268           continue;
1269 
1270         if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) {
1271           /* use https proxy */
1272           if(needle->handler->flags&PROTOPT_SSL) {
1273             /* use double layer ssl */
1274             if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
1275                                         &check->proxy_ssl_config))
1276               continue;
1277             if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete)
1278               continue;
1279           }
1280           else {
1281             if(!Curl_ssl_config_matches(&needle->ssl_config,
1282                                         &check->ssl_config))
1283               continue;
1284             if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete)
1285               continue;
1286           }
1287         }
1288       }
1289 #endif
1290 
1291       if(!canmultiplex && CONN_INUSE(check))
1292         /* this request can't be multiplexed but the checked connection is
1293            already in use so we skip it */
1294         continue;
1295 
1296       if(CONN_INUSE(check)) {
1297         /* Subject for multiplex use if 'checks' belongs to the same multi
1298            handle as 'data' is. */
1299         struct Curl_llist_element *e = check->easyq.head;
1300         struct Curl_easy *entry = e->ptr;
1301         if(entry->multi != data->multi)
1302           continue;
1303       }
1304 
1305       if(needle->localdev || needle->localport) {
1306         /* If we are bound to a specific local end (IP+port), we must not
1307            re-use a random other one, although if we didn't ask for a
1308            particular one we can reuse one that was bound.
1309 
1310            This comparison is a bit rough and too strict. Since the input
1311            parameters can be specified in numerous ways and still end up the
1312            same it would take a lot of processing to make it really accurate.
1313            Instead, this matching will assume that re-uses of bound connections
1314            will most likely also re-use the exact same binding parameters and
1315            missing out a few edge cases shouldn't hurt anyone very much.
1316         */
1317         if((check->localport != needle->localport) ||
1318            (check->localportrange != needle->localportrange) ||
1319            (needle->localdev &&
1320             (!check->localdev || strcmp(check->localdev, needle->localdev))))
1321           continue;
1322       }
1323 
1324       if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
1325         /* This protocol requires credentials per connection,
1326            so verify that we're using the same name and password as well */
1327         if(Curl_timestrcmp(needle->user, check->user) ||
1328            Curl_timestrcmp(needle->passwd, check->passwd) ||
1329            Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) ||
1330            Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) {
1331           /* one of them was different */
1332           continue;
1333         }
1334       }
1335 
1336       /* GSS delegation differences do not actually affect every connection
1337          and auth method, but this check takes precaution before efficiency */
1338       if(needle->gssapi_delegation != check->gssapi_delegation)
1339         continue;
1340 
1341       /* If multiplexing isn't enabled on the h2 connection and h1 is
1342          explicitly requested, handle it: */
1343       if((needle->handler->protocol & PROTO_FAMILY_HTTP) &&
1344          (check->httpversion >= 20) &&
1345          (data->state.httpwant < CURL_HTTP_VERSION_2_0))
1346         continue;
1347 #ifdef USE_SSH
1348       else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) {
1349         if(!ssh_config_matches(needle, check))
1350           continue;
1351       }
1352 #endif
1353 #ifndef CURL_DISABLE_FTP
1354       else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) {
1355         /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */
1356         if(Curl_timestrcmp(needle->proto.ftpc.account,
1357                            check->proto.ftpc.account) ||
1358            Curl_timestrcmp(needle->proto.ftpc.alternative_to_user,
1359                            check->proto.ftpc.alternative_to_user) ||
1360            (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) ||
1361            (needle->proto.ftpc.ccc != check->proto.ftpc.ccc))
1362           continue;
1363       }
1364 #endif
1365 
1366       if((needle->handler->flags&PROTOPT_SSL)
1367 #ifndef CURL_DISABLE_PROXY
1368          || !needle->bits.httpproxy || needle->bits.tunnel_proxy
1369 #endif
1370         ) {
1371         /* The requested connection does not use a HTTP proxy or it uses SSL or
1372            it is a non-SSL protocol tunneled or it is a non-SSL protocol which
1373            is allowed to be upgraded via TLS */
1374 
1375         if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
1376             (get_protocol_family(check->handler) ==
1377              needle->handler->protocol && check->bits.tls_upgraded)) &&
1378            (!needle->bits.conn_to_host || strcasecompare(
1379             needle->conn_to_host.name, check->conn_to_host.name)) &&
1380            (!needle->bits.conn_to_port ||
1381              needle->conn_to_port == check->conn_to_port) &&
1382            strcasecompare(needle->host.name, check->host.name) &&
1383            needle->remote_port == check->remote_port) {
1384           /* The schemes match or the protocol family is the same and the
1385              previous connection was TLS upgraded, and the hostname and host
1386              port match */
1387           if(needle->handler->flags & PROTOPT_SSL) {
1388             /* This is a SSL connection so verify that we're using the same
1389                SSL options as well */
1390             if(!Curl_ssl_config_matches(&needle->ssl_config,
1391                                         &check->ssl_config)) {
1392               DEBUGF(infof(data,
1393                            "Connection #%ld has different SSL parameters, "
1394                            "can't reuse",
1395                            check->connection_id));
1396               continue;
1397             }
1398             if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) {
1399               foundPendingCandidate = TRUE;
1400               DEBUGF(infof(data,
1401                            "Connection #%ld has not started SSL connect, "
1402                            "can't reuse",
1403                            check->connection_id));
1404               continue;
1405             }
1406           }
1407           match = TRUE;
1408         }
1409       }
1410       else {
1411         /* The requested connection is using the same HTTP proxy in normal
1412            mode (no tunneling) */
1413         match = TRUE;
1414       }
1415 
1416       if(match) {
1417 #if defined(USE_NTLM)
1418         /* If we are looking for an HTTP+NTLM connection, check if this is
1419            already authenticating with the right credentials. If not, keep
1420            looking so that we can reuse NTLM connections if
1421            possible. (Especially we must not reuse the same connection if
1422            partway through a handshake!) */
1423         if(wantNTLMhttp) {
1424           if(Curl_timestrcmp(needle->user, check->user) ||
1425              Curl_timestrcmp(needle->passwd, check->passwd)) {
1426 
1427             /* we prefer a credential match, but this is at least a connection
1428                that can be reused and "upgraded" to NTLM */
1429             if(check->http_ntlm_state == NTLMSTATE_NONE)
1430               chosen = check;
1431             continue;
1432           }
1433         }
1434         else if(check->http_ntlm_state != NTLMSTATE_NONE) {
1435           /* Connection is using NTLM auth but we don't want NTLM */
1436           continue;
1437         }
1438 
1439 #ifndef CURL_DISABLE_PROXY
1440         /* Same for Proxy NTLM authentication */
1441         if(wantProxyNTLMhttp) {
1442           /* Both check->http_proxy.user and check->http_proxy.passwd can be
1443            * NULL */
1444           if(!check->http_proxy.user || !check->http_proxy.passwd)
1445             continue;
1446 
1447           if(Curl_timestrcmp(needle->http_proxy.user,
1448                              check->http_proxy.user) ||
1449              Curl_timestrcmp(needle->http_proxy.passwd,
1450                              check->http_proxy.passwd))
1451             continue;
1452         }
1453         else if(check->proxy_ntlm_state != NTLMSTATE_NONE) {
1454           /* Proxy connection is using NTLM auth but we don't want NTLM */
1455           continue;
1456         }
1457 #endif
1458         if(wantNTLMhttp || wantProxyNTLMhttp) {
1459           /* Credentials are already checked, we can use this connection */
1460           chosen = check;
1461 
1462           if((wantNTLMhttp &&
1463              (check->http_ntlm_state != NTLMSTATE_NONE)) ||
1464               (wantProxyNTLMhttp &&
1465                (check->proxy_ntlm_state != NTLMSTATE_NONE))) {
1466             /* We must use this connection, no other */
1467             *force_reuse = TRUE;
1468             break;
1469           }
1470 
1471           /* Continue look up for a better connection */
1472           continue;
1473         }
1474 #endif
1475         if(canmultiplex) {
1476           /* We can multiplex if we want to. Let's continue looking for
1477              the optimal connection to use. */
1478 
1479           if(!multiplexed) {
1480             /* We have the optimal connection. Let's stop looking. */
1481             chosen = check;
1482             break;
1483           }
1484 
1485 #ifdef USE_NGHTTP2
1486           /* If multiplexed, make sure we don't go over concurrency limit */
1487           if(check->bits.multiplex) {
1488             /* Multiplexed connections can only be HTTP/2 for now */
1489             struct http_conn *httpc = &check->proto.httpc;
1490             if(multiplexed >= httpc->settings.max_concurrent_streams) {
1491               infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)",
1492                     multiplexed);
1493               continue;
1494             }
1495             else if(multiplexed >=
1496                     Curl_multi_max_concurrent_streams(data->multi)) {
1497               infof(data, "client side MAX_CONCURRENT_STREAMS reached"
1498                     ", skip (%zu)",
1499                     multiplexed);
1500               continue;
1501             }
1502           }
1503 #endif
1504           /* When not multiplexed, we have a match here! */
1505           chosen = check;
1506           infof(data, "Multiplexed connection found!");
1507           break;
1508         }
1509         else {
1510           /* We have found a connection. Let's stop searching. */
1511           chosen = check;
1512           break;
1513         }
1514       }
1515     }
1516   }
1517 
1518   if(chosen) {
1519     /* mark it as used before releasing the lock */
1520     Curl_attach_connnection(data, chosen);
1521     CONNCACHE_UNLOCK(data);
1522     *usethis = chosen;
1523     return TRUE; /* yes, we found one to use! */
1524   }
1525   CONNCACHE_UNLOCK(data);
1526 
1527   if(foundPendingCandidate && data->set.pipewait) {
1528     infof(data,
1529           "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set");
1530     *waitpipe = TRUE;
1531   }
1532 
1533   return FALSE; /* no matching connecting exists */
1534 }
1535 
1536 /*
1537  * verboseconnect() displays verbose information after a connect
1538  */
1539 #ifndef CURL_DISABLE_VERBOSE_STRINGS
Curl_verboseconnect(struct Curl_easy * data,struct connectdata * conn)1540 void Curl_verboseconnect(struct Curl_easy *data,
1541                          struct connectdata *conn)
1542 {
1543   if(data->set.verbose)
1544     infof(data, "Connected to %s (%s) port %u (#%ld)",
1545 #ifndef CURL_DISABLE_PROXY
1546           conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
1547           conn->bits.httpproxy ? conn->http_proxy.host.dispname :
1548 #endif
1549           conn->bits.conn_to_host ? conn->conn_to_host.dispname :
1550           conn->host.dispname,
1551           conn->primary_ip, conn->port, conn->connection_id);
1552 }
1553 #endif
1554 
1555 /*
1556  * Helpers for IDNA conversions.
1557  */
Curl_is_ASCII_name(const char * hostname)1558 bool Curl_is_ASCII_name(const char *hostname)
1559 {
1560   /* get an UNSIGNED local version of the pointer */
1561   const unsigned char *ch = (const unsigned char *)hostname;
1562 
1563   if(!hostname) /* bad input, consider it ASCII! */
1564     return TRUE;
1565 
1566   while(*ch) {
1567     if(*ch++ & 0x80)
1568       return FALSE;
1569   }
1570   return TRUE;
1571 }
1572 
1573 /*
1574  * Strip single trailing dot in the hostname,
1575  * primarily for SNI and http host header.
1576  */
strip_trailing_dot(struct hostname * host)1577 static void strip_trailing_dot(struct hostname *host)
1578 {
1579   size_t len;
1580   if(!host || !host->name)
1581     return;
1582   len = strlen(host->name);
1583   if(len && (host->name[len-1] == '.'))
1584     host->name[len-1] = 0;
1585 }
1586 
1587 /*
1588  * Perform any necessary IDN conversion of hostname
1589  */
Curl_idnconvert_hostname(struct Curl_easy * data,struct hostname * host)1590 CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
1591                                   struct hostname *host)
1592 {
1593 #ifndef USE_LIBIDN2
1594   (void)data;
1595   (void)data;
1596 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
1597   (void)data;
1598 #endif
1599 
1600   /* set the name we use to display the host name */
1601   host->dispname = host->name;
1602 
1603   /* Check name for non-ASCII and convert hostname to ACE form if we can */
1604   if(!Curl_is_ASCII_name(host->name)) {
1605 #ifdef USE_LIBIDN2
1606     if(idn2_check_version(IDN2_VERSION)) {
1607       char *ace_hostname = NULL;
1608 #if IDN2_VERSION_NUMBER >= 0x00140000
1609       /* IDN2_NFC_INPUT: Normalize input string using normalization form C.
1610          IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional
1611          processing. */
1612       int flags = IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL;
1613 #else
1614       int flags = IDN2_NFC_INPUT;
1615 #endif
1616       int rc = IDN2_LOOKUP(host->name, &ace_hostname, flags);
1617       if(rc != IDN2_OK)
1618         /* fallback to TR46 Transitional mode for better IDNA2003
1619            compatibility */
1620         rc = IDN2_LOOKUP(host->name, &ace_hostname,
1621                          IDN2_TRANSITIONAL);
1622       if(rc == IDN2_OK) {
1623         host->encalloc = (char *)ace_hostname;
1624         /* change the name pointer to point to the encoded hostname */
1625         host->name = host->encalloc;
1626       }
1627       else {
1628         failf(data, "Failed to convert %s to ACE; %s", host->name,
1629               idn2_strerror(rc));
1630         return CURLE_URL_MALFORMAT;
1631       }
1632     }
1633 #elif defined(USE_WIN32_IDN)
1634     char *ace_hostname = NULL;
1635 
1636     if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
1637       host->encalloc = ace_hostname;
1638       /* change the name pointer to point to the encoded hostname */
1639       host->name = host->encalloc;
1640     }
1641     else {
1642       char buffer[STRERROR_LEN];
1643       failf(data, "Failed to convert %s to ACE; %s", host->name,
1644             Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
1645       return CURLE_URL_MALFORMAT;
1646     }
1647 #else
1648     infof(data, "IDN support not present, can't parse Unicode domains");
1649 #endif
1650   }
1651   return CURLE_OK;
1652 }
1653 
1654 /*
1655  * Frees data allocated by idnconvert_hostname()
1656  */
Curl_free_idnconverted_hostname(struct hostname * host)1657 void Curl_free_idnconverted_hostname(struct hostname *host)
1658 {
1659 #if defined(USE_LIBIDN2)
1660   if(host->encalloc) {
1661     idn2_free(host->encalloc); /* must be freed with idn2_free() since this was
1662                                  allocated by libidn */
1663     host->encalloc = NULL;
1664   }
1665 #elif defined(USE_WIN32_IDN)
1666   free(host->encalloc); /* must be freed with free() since this was
1667                            allocated by curl_win32_idn_to_ascii */
1668   host->encalloc = NULL;
1669 #else
1670   (void)host;
1671 #endif
1672 }
1673 
1674 /*
1675  * Allocate and initialize a new connectdata object.
1676  */
allocate_conn(struct Curl_easy * data)1677 static struct connectdata *allocate_conn(struct Curl_easy *data)
1678 {
1679   struct connectdata *conn = calloc(1, sizeof(struct connectdata));
1680   if(!conn)
1681     return NULL;
1682 
1683 #ifdef USE_SSL
1684   /* The SSL backend-specific data (ssl_backend_data) objects are allocated as
1685      a separate array to ensure suitable alignment.
1686      Note that these backend pointers can be swapped by vtls (eg ssl backend
1687      data becomes proxy backend data). */
1688   {
1689     size_t sslsize = Curl_ssl->sizeof_ssl_backend_data;
1690     char *ssl = calloc(4, sslsize);
1691     if(!ssl) {
1692       free(conn);
1693       return NULL;
1694     }
1695     conn->ssl_extra = ssl;
1696     conn->ssl[0].backend = (void *)ssl;
1697     conn->ssl[1].backend = (void *)(ssl + sslsize);
1698 #ifndef CURL_DISABLE_PROXY
1699     conn->proxy_ssl[0].backend = (void *)(ssl + 2 * sslsize);
1700     conn->proxy_ssl[1].backend = (void *)(ssl + 3 * sslsize);
1701 #endif
1702   }
1703 #endif
1704 
1705   conn->handler = &Curl_handler_dummy;  /* Be sure we have a handler defined
1706                                            already from start to avoid NULL
1707                                            situations and checks */
1708 
1709   /* and we setup a few fields in case we end up actually using this struct */
1710 
1711   conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;     /* no file descriptor */
1712   conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
1713   conn->tempsock[0] = CURL_SOCKET_BAD; /* no file descriptor */
1714   conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
1715   conn->connection_id = -1;    /* no ID */
1716   conn->port = -1; /* unknown at this point */
1717   conn->remote_port = -1; /* unknown at this point */
1718 #if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD)
1719   conn->postponed[0].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
1720   conn->postponed[1].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
1721 #endif /* USE_RECV_BEFORE_SEND_WORKAROUND && DEBUGBUILD */
1722 
1723   /* Default protocol-independent behavior doesn't support persistent
1724      connections, so we set this to force-close. Protocols that support
1725      this need to set this to FALSE in their "curl_do" functions. */
1726   connclose(conn, "Default to force-close");
1727 
1728   /* Store creation time to help future close decision making */
1729   conn->created = Curl_now();
1730 
1731   /* Store current time to give a baseline to keepalive connection times. */
1732   conn->keepalive = Curl_now();
1733 
1734 #ifndef CURL_DISABLE_PROXY
1735   conn->http_proxy.proxytype = data->set.proxytype;
1736   conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;
1737 
1738   /* note that these two proxy bits are now just on what looks to be
1739      requested, they may be altered down the road */
1740   conn->bits.proxy = (data->set.str[STRING_PROXY] &&
1741                       *data->set.str[STRING_PROXY]) ? TRUE : FALSE;
1742   conn->bits.httpproxy = (conn->bits.proxy &&
1743                           (conn->http_proxy.proxytype == CURLPROXY_HTTP ||
1744                            conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 ||
1745                            conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ?
1746                            TRUE : FALSE;
1747   conn->bits.socksproxy = (conn->bits.proxy &&
1748                            !conn->bits.httpproxy) ? TRUE : FALSE;
1749 
1750   if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) {
1751     conn->bits.proxy = TRUE;
1752     conn->bits.socksproxy = TRUE;
1753   }
1754 
1755   conn->bits.proxy_user_passwd =
1756     (data->state.aptr.proxyuser) ? TRUE : FALSE;
1757   conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
1758 #endif /* CURL_DISABLE_PROXY */
1759 
1760   conn->bits.user_passwd = (data->state.aptr.user) ? TRUE : FALSE;
1761 #ifndef CURL_DISABLE_FTP
1762   conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
1763   conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
1764 #endif
1765   conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus;
1766   conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
1767   conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
1768   conn->ssl_config.ssl_options = data->set.ssl.primary.ssl_options;
1769 #ifdef USE_TLS_SRP
1770 #endif
1771 #ifndef CURL_DISABLE_PROXY
1772   conn->proxy_ssl_config.verifystatus =
1773     data->set.proxy_ssl.primary.verifystatus;
1774   conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
1775   conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
1776   conn->proxy_ssl_config.ssl_options = data->set.proxy_ssl.primary.ssl_options;
1777 #ifdef USE_TLS_SRP
1778 #endif
1779 #endif
1780   conn->ip_version = data->set.ipver;
1781   conn->bits.connect_only = data->set.connect_only;
1782   conn->transport = TRNSPRT_TCP; /* most of them are TCP streams */
1783 
1784 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
1785     defined(NTLM_WB_ENABLED)
1786   conn->ntlm.ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
1787   conn->proxyntlm.ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
1788 #endif
1789 
1790   /* Initialize the easy handle list */
1791   Curl_llist_init(&conn->easyq, NULL);
1792 
1793 #ifdef HAVE_GSSAPI
1794   conn->data_prot = PROT_CLEAR;
1795 #endif
1796 
1797   /* Store the local bind parameters that will be used for this connection */
1798   if(data->set.str[STRING_DEVICE]) {
1799     conn->localdev = strdup(data->set.str[STRING_DEVICE]);
1800     if(!conn->localdev)
1801       goto error;
1802   }
1803   conn->localportrange = data->set.localportrange;
1804   conn->localport = data->set.localport;
1805 
1806   /* the close socket stuff needs to be copied to the connection struct as
1807      it may live on without (this specific) Curl_easy */
1808   conn->fclosesocket = data->set.fclosesocket;
1809   conn->closesocket_client = data->set.closesocket_client;
1810   conn->lastused = Curl_now(); /* used now */
1811   conn->gssapi_delegation = data->set.gssapi_delegation;
1812 
1813   return conn;
1814   error:
1815 
1816   Curl_llist_destroy(&conn->easyq, NULL);
1817   free(conn->localdev);
1818 #ifdef USE_SSL
1819   free(conn->ssl_extra);
1820 #endif
1821   free(conn);
1822   return NULL;
1823 }
1824 
1825 /* returns the handler if the given scheme is built-in */
Curl_builtin_scheme(const char * scheme)1826 const struct Curl_handler *Curl_builtin_scheme(const char *scheme)
1827 {
1828   const struct Curl_handler * const *pp;
1829   const struct Curl_handler *p;
1830   /* Scan protocol handler table and match against 'scheme'. The handler may
1831      be changed later when the protocol specific setup function is called. */
1832   for(pp = protocols; (p = *pp) != NULL; pp++)
1833     if(strcasecompare(p->scheme, scheme))
1834       /* Protocol found in table. Check if allowed */
1835       return p;
1836   return NULL; /* not found */
1837 }
1838 
1839 
findprotocol(struct Curl_easy * data,struct connectdata * conn,const char * protostr)1840 static CURLcode findprotocol(struct Curl_easy *data,
1841                              struct connectdata *conn,
1842                              const char *protostr)
1843 {
1844   const struct Curl_handler *p = Curl_builtin_scheme(protostr);
1845 
1846   if(p && /* Protocol found in table. Check if allowed */
1847      (data->set.allowed_protocols & p->protocol)) {
1848 
1849     /* it is allowed for "normal" request, now do an extra check if this is
1850        the result of a redirect */
1851     if(data->state.this_is_a_follow &&
1852        !(data->set.redir_protocols & p->protocol))
1853       /* nope, get out */
1854       ;
1855     else {
1856       /* Perform setup complement if some. */
1857       conn->handler = conn->given = p;
1858 
1859       /* 'port' and 'remote_port' are set in setup_connection_internals() */
1860       return CURLE_OK;
1861     }
1862   }
1863 
1864   /* The protocol was not found in the table, but we don't have to assign it
1865      to anything since it is already assigned to a dummy-struct in the
1866      create_conn() function when the connectdata struct is allocated. */
1867   failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME,
1868         protostr);
1869 
1870   return CURLE_UNSUPPORTED_PROTOCOL;
1871 }
1872 
1873 
Curl_uc_to_curlcode(CURLUcode uc)1874 CURLcode Curl_uc_to_curlcode(CURLUcode uc)
1875 {
1876   switch(uc) {
1877   default:
1878     return CURLE_URL_MALFORMAT;
1879   case CURLUE_UNSUPPORTED_SCHEME:
1880     return CURLE_UNSUPPORTED_PROTOCOL;
1881   case CURLUE_OUT_OF_MEMORY:
1882     return CURLE_OUT_OF_MEMORY;
1883   case CURLUE_USER_NOT_ALLOWED:
1884     return CURLE_LOGIN_DENIED;
1885   }
1886 }
1887 
1888 /*
1889  * If the URL was set with an IPv6 numerical address with a zone id part, set
1890  * the scope_id based on that!
1891  */
1892 
zonefrom_url(CURLU * uh,struct Curl_easy * data,struct connectdata * conn)1893 static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
1894                          struct connectdata *conn)
1895 {
1896   char *zoneid;
1897   CURLUcode uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0);
1898 #ifdef CURL_DISABLE_VERBOSE_STRINGS
1899   (void)data;
1900 #endif
1901 
1902   if(!uc && zoneid) {
1903     char *endp;
1904     unsigned long scope = strtoul(zoneid, &endp, 10);
1905     if(!*endp && (scope < UINT_MAX))
1906       /* A plain number, use it directly as a scope id. */
1907       conn->scope_id = (unsigned int)scope;
1908 #if defined(HAVE_IF_NAMETOINDEX)
1909     else {
1910 #elif defined(WIN32)
1911     else if(Curl_if_nametoindex) {
1912 #endif
1913 
1914 #if defined(HAVE_IF_NAMETOINDEX) || defined(WIN32)
1915       /* Zone identifier is not numeric */
1916       unsigned int scopeidx = 0;
1917 #if defined(WIN32)
1918       scopeidx = Curl_if_nametoindex(zoneid);
1919 #else
1920       scopeidx = if_nametoindex(zoneid);
1921 #endif
1922       if(!scopeidx)
1923         infof(data, "Invalid zoneid: %s; %s", zoneid,
1924               strerror(errno));
1925       else
1926         conn->scope_id = scopeidx;
1927     }
1928 #endif /* HAVE_IF_NAMETOINDEX || WIN32 */
1929 
1930     free(zoneid);
1931   }
1932 }
1933 
1934 /*
1935  * Parse URL and fill in the relevant members of the connection struct.
1936  */
1937 static CURLcode parseurlandfillconn(struct Curl_easy *data,
1938                                     struct connectdata *conn)
1939 {
1940   CURLcode result;
1941   CURLU *uh;
1942   CURLUcode uc;
1943   char *hostname;
1944   bool use_set_uh = (data->set.uh && !data->state.this_is_a_follow);
1945 
1946   up_free(data); /* cleanup previous leftovers first */
1947 
1948   /* parse the URL */
1949   if(use_set_uh) {
1950     uh = data->state.uh = curl_url_dup(data->set.uh);
1951   }
1952   else {
1953     uh = data->state.uh = curl_url();
1954   }
1955 
1956   if(!uh)
1957     return CURLE_OUT_OF_MEMORY;
1958 
1959   if(data->set.str[STRING_DEFAULT_PROTOCOL] &&
1960      !Curl_is_absolute_url(data->state.url, NULL, MAX_SCHEME_LEN)) {
1961     char *url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL],
1962                         data->state.url);
1963     if(!url)
1964       return CURLE_OUT_OF_MEMORY;
1965     if(data->state.url_alloc)
1966       free(data->state.url);
1967     data->state.url = url;
1968     data->state.url_alloc = TRUE;
1969   }
1970 
1971   if(!use_set_uh) {
1972     char *newurl;
1973     uc = curl_url_set(uh, CURLUPART_URL, data->state.url,
1974                     CURLU_GUESS_SCHEME |
1975                     CURLU_NON_SUPPORT_SCHEME |
1976                     (data->set.disallow_username_in_url ?
1977                      CURLU_DISALLOW_USER : 0) |
1978                     (data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
1979     if(uc) {
1980       DEBUGF(infof(data, "curl_url_set rejected %s", data->state.url));
1981       return Curl_uc_to_curlcode(uc);
1982     }
1983 
1984     /* after it was parsed, get the generated normalized version */
1985     uc = curl_url_get(uh, CURLUPART_URL, &newurl, 0);
1986     if(uc)
1987       return Curl_uc_to_curlcode(uc);
1988     if(data->state.url_alloc)
1989       free(data->state.url);
1990     data->state.url = newurl;
1991     data->state.url_alloc = TRUE;
1992   }
1993 
1994   uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
1995   if(uc)
1996     return Curl_uc_to_curlcode(uc);
1997 
1998   uc = curl_url_get(uh, CURLUPART_HOST, &data->state.up.hostname, 0);
1999   if(uc) {
2000     if(!strcasecompare("file", data->state.up.scheme))
2001       return CURLE_OUT_OF_MEMORY;
2002   }
2003 
2004   hostname = data->state.up.hostname;
2005 
2006   if(hostname && hostname[0] == '[') {
2007     /* This looks like an IPv6 address literal. See if there is an address
2008        scope. */
2009     size_t hlen;
2010     conn->bits.ipv6_ip = TRUE;
2011     /* cut off the brackets! */
2012     hostname++;
2013     hlen = strlen(hostname);
2014     hostname[hlen - 1] = 0;
2015 
2016     zonefrom_url(uh, data, conn);
2017   }
2018 
2019   /* make sure the connect struct gets its own copy of the host name */
2020   conn->host.rawalloc = strdup(hostname ? hostname : "");
2021   if(!conn->host.rawalloc)
2022     return CURLE_OUT_OF_MEMORY;
2023   conn->host.name = conn->host.rawalloc;
2024 
2025   /*************************************************************
2026    * IDN-convert the hostnames
2027    *************************************************************/
2028   result = Curl_idnconvert_hostname(data, &conn->host);
2029   if(result)
2030     return result;
2031   if(conn->bits.conn_to_host) {
2032     result = Curl_idnconvert_hostname(data, &conn->conn_to_host);
2033     if(result)
2034       return result;
2035   }
2036 #ifndef CURL_DISABLE_PROXY
2037   if(conn->bits.httpproxy) {
2038     result = Curl_idnconvert_hostname(data, &conn->http_proxy.host);
2039     if(result)
2040       return result;
2041   }
2042   if(conn->bits.socksproxy) {
2043     result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host);
2044     if(result)
2045       return result;
2046   }
2047 #endif
2048 
2049 #ifndef CURL_DISABLE_HSTS
2050   /* HSTS upgrade */
2051   if(data->hsts && strcasecompare("http", data->state.up.scheme)) {
2052     /* This MUST use the IDN decoded name */
2053     if(Curl_hsts(data->hsts, conn->host.name, TRUE)) {
2054       char *url;
2055       Curl_safefree(data->state.up.scheme);
2056       uc = curl_url_set(uh, CURLUPART_SCHEME, "https", 0);
2057       if(uc)
2058         return Curl_uc_to_curlcode(uc);
2059       if(data->state.url_alloc)
2060         Curl_safefree(data->state.url);
2061       /* after update, get the updated version */
2062       uc = curl_url_get(uh, CURLUPART_URL, &url, 0);
2063       if(uc)
2064         return Curl_uc_to_curlcode(uc);
2065       uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
2066       if(uc) {
2067         free(url);
2068         return Curl_uc_to_curlcode(uc);
2069       }
2070       data->state.url = url;
2071       data->state.url_alloc = TRUE;
2072       infof(data, "Switched from HTTP to HTTPS due to HSTS => %s",
2073             data->state.url);
2074     }
2075   }
2076 #endif
2077 
2078   result = findprotocol(data, conn, data->state.up.scheme);
2079   if(result)
2080     return result;
2081 
2082   /*
2083    * User name and password set with their own options override the
2084    * credentials possibly set in the URL.
2085    */
2086   if(!data->state.aptr.user) {
2087     /* we don't use the URL API's URL decoder option here since it rejects
2088        control codes and we want to allow them for some schemes in the user
2089        and password fields */
2090     uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, 0);
2091     if(!uc) {
2092       char *decoded;
2093       result = Curl_urldecode(NULL, data->state.up.user, 0, &decoded, NULL,
2094                               conn->handler->flags&PROTOPT_USERPWDCTRL ?
2095                               REJECT_ZERO : REJECT_CTRL);
2096       if(result)
2097         return result;
2098       conn->user = decoded;
2099       conn->bits.user_passwd = TRUE;
2100       result = Curl_setstropt(&data->state.aptr.user, decoded);
2101       if(result)
2102         return result;
2103     }
2104     else if(uc != CURLUE_NO_USER)
2105       return Curl_uc_to_curlcode(uc);
2106   }
2107 
2108   if(!data->state.aptr.passwd) {
2109     uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
2110     if(!uc) {
2111       char *decoded;
2112       result = Curl_urldecode(NULL, data->state.up.password, 0, &decoded, NULL,
2113                               conn->handler->flags&PROTOPT_USERPWDCTRL ?
2114                               REJECT_ZERO : REJECT_CTRL);
2115       if(result)
2116         return result;
2117       conn->passwd = decoded;
2118       conn->bits.user_passwd = TRUE;
2119       result = Curl_setstropt(&data->state.aptr.passwd, decoded);
2120       if(result)
2121         return result;
2122     }
2123     else if(uc != CURLUE_NO_PASSWORD)
2124       return Curl_uc_to_curlcode(uc);
2125   }
2126 
2127   uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options,
2128                     CURLU_URLDECODE);
2129   if(!uc) {
2130     conn->options = strdup(data->state.up.options);
2131     if(!conn->options)
2132       return CURLE_OUT_OF_MEMORY;
2133   }
2134   else if(uc != CURLUE_NO_OPTIONS)
2135     return Curl_uc_to_curlcode(uc);
2136 
2137   uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path, 0);
2138   if(uc)
2139     return Curl_uc_to_curlcode(uc);
2140 
2141   uc = curl_url_get(uh, CURLUPART_PORT, &data->state.up.port,
2142                     CURLU_DEFAULT_PORT);
2143   if(uc) {
2144     if(!strcasecompare("file", data->state.up.scheme))
2145       return CURLE_OUT_OF_MEMORY;
2146   }
2147   else {
2148     unsigned long port = strtoul(data->state.up.port, NULL, 10);
2149     conn->port = conn->remote_port =
2150       (data->set.use_port && data->state.allow_port) ?
2151       (int)data->set.use_port : curlx_ultous(port);
2152   }
2153 
2154   (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
2155 
2156   if(data->set.scope_id)
2157     /* Override any scope that was set above.  */
2158     conn->scope_id = data->set.scope_id;
2159 
2160   return CURLE_OK;
2161 }
2162 
2163 
2164 /*
2165  * If we're doing a resumed transfer, we need to setup our stuff
2166  * properly.
2167  */
2168 static CURLcode setup_range(struct Curl_easy *data)
2169 {
2170   struct UrlState *s = &data->state;
2171   s->resume_from = data->set.set_resume_from;
2172   if(s->resume_from || data->set.str[STRING_SET_RANGE]) {
2173     if(s->rangestringalloc)
2174       free(s->range);
2175 
2176     if(s->resume_from)
2177       s->range = aprintf("%" CURL_FORMAT_CURL_OFF_T "-", s->resume_from);
2178     else
2179       s->range = strdup(data->set.str[STRING_SET_RANGE]);
2180 
2181     s->rangestringalloc = (s->range) ? TRUE : FALSE;
2182 
2183     if(!s->range)
2184       return CURLE_OUT_OF_MEMORY;
2185 
2186     /* tell ourselves to fetch this range */
2187     s->use_range = TRUE;        /* enable range download */
2188   }
2189   else
2190     s->use_range = FALSE; /* disable range download */
2191 
2192   return CURLE_OK;
2193 }
2194 
2195 
2196 /*
2197  * setup_connection_internals() -
2198  *
2199  * Setup connection internals specific to the requested protocol in the
2200  * Curl_easy. This is inited and setup before the connection is made but
2201  * is about the particular protocol that is to be used.
2202  *
2203  * This MUST get called after proxy magic has been figured out.
2204  */
2205 static CURLcode setup_connection_internals(struct Curl_easy *data,
2206                                            struct connectdata *conn)
2207 {
2208   const struct Curl_handler *p;
2209   CURLcode result;
2210 
2211   /* Perform setup complement if some. */
2212   p = conn->handler;
2213 
2214   if(p->setup_connection) {
2215     result = (*p->setup_connection)(data, conn);
2216 
2217     if(result)
2218       return result;
2219 
2220     p = conn->handler;              /* May have changed. */
2221   }
2222 
2223   if(conn->port < 0)
2224     /* we check for -1 here since if proxy was detected already, this
2225        was very likely already set to the proxy port */
2226     conn->port = p->defport;
2227 
2228   return CURLE_OK;
2229 }
2230 
2231 /*
2232  * Curl_free_request_state() should free temp data that was allocated in the
2233  * Curl_easy for this single request.
2234  */
2235 
2236 void Curl_free_request_state(struct Curl_easy *data)
2237 {
2238   Curl_safefree(data->req.p.http);
2239   Curl_safefree(data->req.newurl);
2240 
2241 #ifndef CURL_DISABLE_DOH
2242   if(data->req.doh) {
2243     Curl_close(&data->req.doh->probe[0].easy);
2244     Curl_close(&data->req.doh->probe[1].easy);
2245   }
2246 #endif
2247 }
2248 
2249 
2250 #ifndef CURL_DISABLE_PROXY
2251 /****************************************************************
2252 * Checks if the host is in the noproxy list. returns true if it matches
2253 * and therefore the proxy should NOT be used.
2254 ****************************************************************/
2255 static bool check_noproxy(const char *name, const char *no_proxy)
2256 {
2257   /* no_proxy=domain1.dom,host.domain2.dom
2258    *   (a comma-separated list of hosts which should
2259    *   not be proxied, or an asterisk to override
2260    *   all proxy variables)
2261    */
2262   if(no_proxy && no_proxy[0]) {
2263     size_t tok_start;
2264     size_t tok_end;
2265     const char *separator = ", ";
2266     size_t no_proxy_len;
2267     size_t namelen;
2268     char *endptr;
2269     if(strcasecompare("*", no_proxy)) {
2270       return TRUE;
2271     }
2272 
2273     /* NO_PROXY was specified and it wasn't just an asterisk */
2274 
2275     no_proxy_len = strlen(no_proxy);
2276     if(name[0] == '[') {
2277       /* IPv6 numerical address */
2278       endptr = strchr(name, ']');
2279       if(!endptr)
2280         return FALSE;
2281       name++;
2282       namelen = endptr - name;
2283     }
2284     else
2285       namelen = strlen(name);
2286 
2287     for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
2288       while(tok_start < no_proxy_len &&
2289             strchr(separator, no_proxy[tok_start]) != NULL) {
2290         /* Look for the beginning of the token. */
2291         ++tok_start;
2292       }
2293 
2294       if(tok_start == no_proxy_len)
2295         break; /* It was all trailing separator chars, no more tokens. */
2296 
2297       for(tok_end = tok_start; tok_end < no_proxy_len &&
2298             strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end)
2299         /* Look for the end of the token. */
2300         ;
2301 
2302       /* To match previous behavior, where it was necessary to specify
2303        * ".local.com" to prevent matching "notlocal.com", we will leave
2304        * the '.' off.
2305        */
2306       if(no_proxy[tok_start] == '.')
2307         ++tok_start;
2308 
2309       if((tok_end - tok_start) <= namelen) {
2310         /* Match the last part of the name to the domain we are checking. */
2311         const char *checkn = name + namelen - (tok_end - tok_start);
2312         if(strncasecompare(no_proxy + tok_start, checkn,
2313                            tok_end - tok_start)) {
2314           if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
2315             /* We either have an exact match, or the previous character is a .
2316              * so it is within the same domain, so no proxy for this host.
2317              */
2318             return TRUE;
2319           }
2320         }
2321       } /* if((tok_end - tok_start) <= namelen) */
2322     } /* for(tok_start = 0; tok_start < no_proxy_len;
2323          tok_start = tok_end + 1) */
2324   } /* NO_PROXY was specified and it wasn't just an asterisk */
2325 
2326   return FALSE;
2327 }
2328 
2329 #ifndef CURL_DISABLE_HTTP
2330 /****************************************************************
2331 * Detect what (if any) proxy to use. Remember that this selects a host
2332 * name and is not limited to HTTP proxies only.
2333 * The returned pointer must be freed by the caller (unless NULL)
2334 ****************************************************************/
2335 static char *detect_proxy(struct Curl_easy *data,
2336                           struct connectdata *conn)
2337 {
2338   char *proxy = NULL;
2339 
2340   /* If proxy was not specified, we check for default proxy environment
2341    * variables, to enable i.e Lynx compliance:
2342    *
2343    * http_proxy=http://some.server.dom:port/
2344    * https_proxy=http://some.server.dom:port/
2345    * ftp_proxy=http://some.server.dom:port/
2346    * no_proxy=domain1.dom,host.domain2.dom
2347    *   (a comma-separated list of hosts which should
2348    *   not be proxied, or an asterisk to override
2349    *   all proxy variables)
2350    * all_proxy=http://some.server.dom:port/
2351    *   (seems to exist for the CERN www lib. Probably
2352    *   the first to check for.)
2353    *
2354    * For compatibility, the all-uppercase versions of these variables are
2355    * checked if the lowercase versions don't exist.
2356    */
2357   char proxy_env[128];
2358   const char *protop = conn->handler->scheme;
2359   char *envp = proxy_env;
2360   char *prox;
2361 #ifdef CURL_DISABLE_VERBOSE_STRINGS
2362   (void)data;
2363 #endif
2364 
2365   /* Now, build <protocol>_proxy and check for such a one to use */
2366   while(*protop)
2367     *envp++ = (char)tolower((int)*protop++);
2368 
2369   /* append _proxy */
2370   strcpy(envp, "_proxy");
2371 
2372   /* read the protocol proxy: */
2373   prox = curl_getenv(proxy_env);
2374 
2375   /*
2376    * We don't try the uppercase version of HTTP_PROXY because of
2377    * security reasons:
2378    *
2379    * When curl is used in a webserver application
2380    * environment (cgi or php), this environment variable can
2381    * be controlled by the web server user by setting the
2382    * http header 'Proxy:' to some value.
2383    *
2384    * This can cause 'internal' http/ftp requests to be
2385    * arbitrarily redirected by any external attacker.
2386    */
2387   if(!prox && !strcasecompare("http_proxy", proxy_env)) {
2388     /* There was no lowercase variable, try the uppercase version: */
2389     Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
2390     prox = curl_getenv(proxy_env);
2391   }
2392 
2393   envp = proxy_env;
2394   if(prox) {
2395     proxy = prox; /* use this */
2396   }
2397   else {
2398     envp = (char *)"all_proxy";
2399     proxy = curl_getenv(envp); /* default proxy to use */
2400     if(!proxy) {
2401       envp = (char *)"ALL_PROXY";
2402       proxy = curl_getenv(envp);
2403     }
2404   }
2405   if(proxy)
2406     infof(data, "Uses proxy env variable %s == '%s'", envp, proxy);
2407 
2408   return proxy;
2409 }
2410 #endif /* CURL_DISABLE_HTTP */
2411 
2412 /*
2413  * If this is supposed to use a proxy, we need to figure out the proxy
2414  * host name, so that we can re-use an existing connection
2415  * that may exist registered to the same proxy host.
2416  */
2417 static CURLcode parse_proxy(struct Curl_easy *data,
2418                             struct connectdata *conn, char *proxy,
2419                             curl_proxytype proxytype)
2420 {
2421   char *portptr = NULL;
2422   int port = -1;
2423   char *proxyuser = NULL;
2424   char *proxypasswd = NULL;
2425   char *host;
2426   bool sockstype;
2427   CURLUcode uc;
2428   struct proxy_info *proxyinfo;
2429   CURLU *uhp = curl_url();
2430   CURLcode result = CURLE_OK;
2431   char *scheme = NULL;
2432 
2433   /* When parsing the proxy, allowing non-supported schemes since we have
2434      these made up ones for proxies. Guess scheme for URLs without it. */
2435   uc = curl_url_set(uhp, CURLUPART_URL, proxy,
2436                     CURLU_NON_SUPPORT_SCHEME|CURLU_GUESS_SCHEME);
2437   if(!uc) {
2438     /* parsed okay as a URL */
2439     uc = curl_url_get(uhp, CURLUPART_SCHEME, &scheme, 0);
2440     if(uc) {
2441       result = CURLE_OUT_OF_MEMORY;
2442       goto error;
2443     }
2444 
2445     if(strcasecompare("https", scheme))
2446       proxytype = CURLPROXY_HTTPS;
2447     else if(strcasecompare("socks5h", scheme))
2448       proxytype = CURLPROXY_SOCKS5_HOSTNAME;
2449     else if(strcasecompare("socks5", scheme))
2450       proxytype = CURLPROXY_SOCKS5;
2451     else if(strcasecompare("socks4a", scheme))
2452       proxytype = CURLPROXY_SOCKS4A;
2453     else if(strcasecompare("socks4", scheme) ||
2454             strcasecompare("socks", scheme))
2455       proxytype = CURLPROXY_SOCKS4;
2456     else if(strcasecompare("http", scheme))
2457       ; /* leave it as HTTP or HTTP/1.0 */
2458     else {
2459       /* Any other xxx:// reject! */
2460       failf(data, "Unsupported proxy scheme for \'%s\'", proxy);
2461       result = CURLE_COULDNT_CONNECT;
2462       goto error;
2463     }
2464   }
2465   else {
2466     failf(data, "Unsupported proxy syntax in \'%s\'", proxy);
2467     result = CURLE_COULDNT_RESOLVE_PROXY;
2468     goto error;
2469   }
2470 
2471 #ifdef USE_SSL
2472   if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
2473 #endif
2474     if(proxytype == CURLPROXY_HTTPS) {
2475       failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
2476                   "HTTPS-proxy support.", proxy);
2477       result = CURLE_NOT_BUILT_IN;
2478       goto error;
2479     }
2480 
2481   sockstype =
2482     proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
2483     proxytype == CURLPROXY_SOCKS5 ||
2484     proxytype == CURLPROXY_SOCKS4A ||
2485     proxytype == CURLPROXY_SOCKS4;
2486 
2487   proxyinfo = sockstype ? &conn->socks_proxy : &conn->http_proxy;
2488   proxyinfo->proxytype = proxytype;
2489 
2490   /* Is there a username and password given in this proxy url? */
2491   uc = curl_url_get(uhp, CURLUPART_USER, &proxyuser, CURLU_URLDECODE);
2492   if(uc && (uc != CURLUE_NO_USER))
2493     goto error;
2494   uc = curl_url_get(uhp, CURLUPART_PASSWORD, &proxypasswd, CURLU_URLDECODE);
2495   if(uc && (uc != CURLUE_NO_PASSWORD))
2496     goto error;
2497 
2498   if(proxyuser || proxypasswd) {
2499     Curl_safefree(proxyinfo->user);
2500     proxyinfo->user = proxyuser;
2501     result = Curl_setstropt(&data->state.aptr.proxyuser, proxyuser);
2502     proxyuser = NULL;
2503     if(result)
2504       goto error;
2505     Curl_safefree(proxyinfo->passwd);
2506     if(!proxypasswd) {
2507       proxypasswd = strdup("");
2508       if(!proxypasswd) {
2509         result = CURLE_OUT_OF_MEMORY;
2510         goto error;
2511       }
2512     }
2513     proxyinfo->passwd = proxypasswd;
2514     result = Curl_setstropt(&data->state.aptr.proxypasswd, proxypasswd);
2515     proxypasswd = NULL;
2516     if(result)
2517       goto error;
2518     conn->bits.proxy_user_passwd = TRUE; /* enable it */
2519   }
2520 
2521   (void)curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);
2522 
2523   if(portptr) {
2524     port = (int)strtol(portptr, NULL, 10);
2525     free(portptr);
2526   }
2527   else {
2528     if(data->set.proxyport)
2529       /* None given in the proxy string, then get the default one if it is
2530          given */
2531       port = (int)data->set.proxyport;
2532     else {
2533       if(proxytype == CURLPROXY_HTTPS)
2534         port = CURL_DEFAULT_HTTPS_PROXY_PORT;
2535       else
2536         port = CURL_DEFAULT_PROXY_PORT;
2537     }
2538   }
2539   if(port >= 0) {
2540     proxyinfo->port = port;
2541     if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc)
2542       conn->port = port;
2543   }
2544 
2545   /* now, clone the proxy host name */
2546   uc = curl_url_get(uhp, CURLUPART_HOST, &host, CURLU_URLDECODE);
2547   if(uc) {
2548     result = CURLE_OUT_OF_MEMORY;
2549     goto error;
2550   }
2551   Curl_safefree(proxyinfo->host.rawalloc);
2552   proxyinfo->host.rawalloc = host;
2553   if(host[0] == '[') {
2554     /* this is a numerical IPv6, strip off the brackets */
2555     size_t len = strlen(host);
2556     host[len-1] = 0; /* clear the trailing bracket */
2557     host++;
2558     zonefrom_url(uhp, data, conn);
2559   }
2560   proxyinfo->host.name = host;
2561 
2562   error:
2563   free(proxyuser);
2564   free(proxypasswd);
2565   free(scheme);
2566   curl_url_cleanup(uhp);
2567   return result;
2568 }
2569 
2570 /*
2571  * Extract the user and password from the authentication string
2572  */
2573 static CURLcode parse_proxy_auth(struct Curl_easy *data,
2574                                  struct connectdata *conn)
2575 {
2576   const char *proxyuser = data->state.aptr.proxyuser ?
2577     data->state.aptr.proxyuser : "";
2578   const char *proxypasswd = data->state.aptr.proxypasswd ?
2579     data->state.aptr.proxypasswd : "";
2580   CURLcode result = CURLE_OK;
2581 
2582   if(proxyuser) {
2583     result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
2584                             REJECT_ZERO);
2585     if(!result)
2586       result = Curl_setstropt(&data->state.aptr.proxyuser,
2587                               conn->http_proxy.user);
2588   }
2589   if(!result && proxypasswd) {
2590     result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
2591                             NULL, REJECT_ZERO);
2592     if(!result)
2593       result = Curl_setstropt(&data->state.aptr.proxypasswd,
2594                               conn->http_proxy.passwd);
2595   }
2596   return result;
2597 }
2598 
2599 /* create_conn helper to parse and init proxy values. to be called after unix
2600    socket init but before any proxy vars are evaluated. */
2601 static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
2602                                               struct connectdata *conn)
2603 {
2604   char *proxy = NULL;
2605   char *socksproxy = NULL;
2606   char *no_proxy = NULL;
2607   CURLcode result = CURLE_OK;
2608 
2609   /*************************************************************
2610    * Extract the user and password from the authentication string
2611    *************************************************************/
2612   if(conn->bits.proxy_user_passwd) {
2613     result = parse_proxy_auth(data, conn);
2614     if(result)
2615       goto out;
2616   }
2617 
2618   /*************************************************************
2619    * Detect what (if any) proxy to use
2620    *************************************************************/
2621   if(data->set.str[STRING_PROXY]) {
2622     proxy = strdup(data->set.str[STRING_PROXY]);
2623     /* if global proxy is set, this is it */
2624     if(NULL == proxy) {
2625       failf(data, "memory shortage");
2626       result = CURLE_OUT_OF_MEMORY;
2627       goto out;
2628     }
2629   }
2630 
2631   if(data->set.str[STRING_PRE_PROXY]) {
2632     socksproxy = strdup(data->set.str[STRING_PRE_PROXY]);
2633     /* if global socks proxy is set, this is it */
2634     if(NULL == socksproxy) {
2635       failf(data, "memory shortage");
2636       result = CURLE_OUT_OF_MEMORY;
2637       goto out;
2638     }
2639   }
2640 
2641   if(!data->set.str[STRING_NOPROXY]) {
2642     const char *p = "no_proxy";
2643     no_proxy = curl_getenv(p);
2644     if(!no_proxy) {
2645       p = "NO_PROXY";
2646       no_proxy = curl_getenv(p);
2647     }
2648     if(no_proxy) {
2649       infof(data, "Uses proxy env variable %s == '%s'", p, no_proxy);
2650     }
2651   }
2652 
2653   if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
2654       data->set.str[STRING_NOPROXY] : no_proxy)) {
2655     Curl_safefree(proxy);
2656     Curl_safefree(socksproxy);
2657   }
2658 #ifndef CURL_DISABLE_HTTP
2659   else if(!proxy && !socksproxy)
2660     /* if the host is not in the noproxy list, detect proxy. */
2661     proxy = detect_proxy(data, conn);
2662 #endif /* CURL_DISABLE_HTTP */
2663 
2664   Curl_safefree(no_proxy);
2665 
2666 #ifdef USE_UNIX_SOCKETS
2667   /* For the time being do not mix proxy and unix domain sockets. See #1274 */
2668   if(proxy && conn->unix_domain_socket) {
2669     free(proxy);
2670     proxy = NULL;
2671   }
2672 #endif
2673 
2674   if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
2675     free(proxy);  /* Don't bother with an empty proxy string or if the
2676                      protocol doesn't work with network */
2677     proxy = NULL;
2678   }
2679   if(socksproxy && (!*socksproxy ||
2680                     (conn->handler->flags & PROTOPT_NONETWORK))) {
2681     free(socksproxy);  /* Don't bother with an empty socks proxy string or if
2682                           the protocol doesn't work with network */
2683     socksproxy = NULL;
2684   }
2685 
2686   /***********************************************************************
2687    * If this is supposed to use a proxy, we need to figure out the proxy host
2688    * name, proxy type and port number, so that we can re-use an existing
2689    * connection that may exist registered to the same proxy host.
2690    ***********************************************************************/
2691   if(proxy || socksproxy) {
2692     if(proxy) {
2693       result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype);
2694       Curl_safefree(proxy); /* parse_proxy copies the proxy string */
2695       if(result)
2696         goto out;
2697     }
2698 
2699     if(socksproxy) {
2700       result = parse_proxy(data, conn, socksproxy,
2701                            conn->socks_proxy.proxytype);
2702       /* parse_proxy copies the socks proxy string */
2703       Curl_safefree(socksproxy);
2704       if(result)
2705         goto out;
2706     }
2707 
2708     if(conn->http_proxy.host.rawalloc) {
2709 #ifdef CURL_DISABLE_HTTP
2710       /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
2711       result = CURLE_UNSUPPORTED_PROTOCOL;
2712       goto out;
2713 #else
2714       /* force this connection's protocol to become HTTP if compatible */
2715       if(!(conn->handler->protocol & PROTO_FAMILY_HTTP)) {
2716         if((conn->handler->flags & PROTOPT_PROXY_AS_HTTP) &&
2717            !conn->bits.tunnel_proxy)
2718           conn->handler = &Curl_handler_http;
2719         else
2720           /* if not converting to HTTP over the proxy, enforce tunneling */
2721           conn->bits.tunnel_proxy = TRUE;
2722       }
2723       conn->bits.httpproxy = TRUE;
2724 #endif
2725     }
2726     else {
2727       conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
2728       conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
2729     }
2730 
2731     if(conn->socks_proxy.host.rawalloc) {
2732       if(!conn->http_proxy.host.rawalloc) {
2733         /* once a socks proxy */
2734         if(!conn->socks_proxy.user) {
2735           conn->socks_proxy.user = conn->http_proxy.user;
2736           conn->http_proxy.user = NULL;
2737           Curl_safefree(conn->socks_proxy.passwd);
2738           conn->socks_proxy.passwd = conn->http_proxy.passwd;
2739           conn->http_proxy.passwd = NULL;
2740         }
2741       }
2742       conn->bits.socksproxy = TRUE;
2743     }
2744     else
2745       conn->bits.socksproxy = FALSE; /* not a socks proxy */
2746   }
2747   else {
2748     conn->bits.socksproxy = FALSE;
2749     conn->bits.httpproxy = FALSE;
2750   }
2751   conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy;
2752 
2753   if(!conn->bits.proxy) {
2754     /* we aren't using the proxy after all... */
2755     conn->bits.proxy = FALSE;
2756     conn->bits.httpproxy = FALSE;
2757     conn->bits.socksproxy = FALSE;
2758     conn->bits.proxy_user_passwd = FALSE;
2759     conn->bits.tunnel_proxy = FALSE;
2760     /* CURLPROXY_HTTPS does not have its own flag in conn->bits, yet we need
2761        to signal that CURLPROXY_HTTPS is not used for this connection */
2762     conn->http_proxy.proxytype = CURLPROXY_HTTP;
2763   }
2764 
2765 out:
2766 
2767   free(socksproxy);
2768   free(proxy);
2769   return result;
2770 }
2771 #endif /* CURL_DISABLE_PROXY */
2772 
2773 /*
2774  * Curl_parse_login_details()
2775  *
2776  * This is used to parse a login string for user name, password and options in
2777  * the following formats:
2778  *
2779  *   user
2780  *   user:password
2781  *   user:password;options
2782  *   user;options
2783  *   user;options:password
2784  *   :password
2785  *   :password;options
2786  *   ;options
2787  *   ;options:password
2788  *
2789  * Parameters:
2790  *
2791  * login    [in]     - The login string.
2792  * len      [in]     - The length of the login string.
2793  * userp    [in/out] - The address where a pointer to newly allocated memory
2794  *                     holding the user will be stored upon completion.
2795  * passwdp  [in/out] - The address where a pointer to newly allocated memory
2796  *                     holding the password will be stored upon completion.
2797  * optionsp [in/out] - The address where a pointer to newly allocated memory
2798  *                     holding the options will be stored upon completion.
2799  *
2800  * Returns CURLE_OK on success.
2801  */
2802 CURLcode Curl_parse_login_details(const char *login, const size_t len,
2803                                   char **userp, char **passwdp,
2804                                   char **optionsp)
2805 {
2806   CURLcode result = CURLE_OK;
2807   char *ubuf = NULL;
2808   char *pbuf = NULL;
2809   char *obuf = NULL;
2810   const char *psep = NULL;
2811   const char *osep = NULL;
2812   size_t ulen;
2813   size_t plen;
2814   size_t olen;
2815 
2816   /* the input length check is because this is called directcly from setopt
2817      and isn't going through the regular string length check */
2818   size_t llen = strlen(login);
2819   if(llen > CURL_MAX_INPUT_LENGTH)
2820     return CURLE_BAD_FUNCTION_ARGUMENT;
2821 
2822   /* Attempt to find the password separator */
2823   if(passwdp) {
2824     psep = strchr(login, ':');
2825 
2826     /* Within the constraint of the login string */
2827     if(psep >= login + len)
2828       psep = NULL;
2829   }
2830 
2831   /* Attempt to find the options separator */
2832   if(optionsp) {
2833     osep = strchr(login, ';');
2834 
2835     /* Within the constraint of the login string */
2836     if(osep >= login + len)
2837       osep = NULL;
2838   }
2839 
2840   /* Calculate the portion lengths */
2841   ulen = (psep ?
2842           (size_t)(osep && psep > osep ? osep - login : psep - login) :
2843           (osep ? (size_t)(osep - login) : len));
2844   plen = (psep ?
2845           (osep && osep > psep ? (size_t)(osep - psep) :
2846                                  (size_t)(login + len - psep)) - 1 : 0);
2847   olen = (osep ?
2848           (psep && psep > osep ? (size_t)(psep - osep) :
2849                                  (size_t)(login + len - osep)) - 1 : 0);
2850 
2851   /* Allocate the user portion buffer */
2852   if(userp && ulen) {
2853     ubuf = malloc(ulen + 1);
2854     if(!ubuf)
2855       result = CURLE_OUT_OF_MEMORY;
2856   }
2857 
2858   /* Allocate the password portion buffer */
2859   if(!result && passwdp && plen) {
2860     pbuf = malloc(plen + 1);
2861     if(!pbuf) {
2862       free(ubuf);
2863       result = CURLE_OUT_OF_MEMORY;
2864     }
2865   }
2866 
2867   /* Allocate the options portion buffer */
2868   if(!result && optionsp && olen) {
2869     obuf = malloc(olen + 1);
2870     if(!obuf) {
2871       free(pbuf);
2872       free(ubuf);
2873       result = CURLE_OUT_OF_MEMORY;
2874     }
2875   }
2876 
2877   if(!result) {
2878     /* Store the user portion if necessary */
2879     if(ubuf) {
2880       memcpy(ubuf, login, ulen);
2881       ubuf[ulen] = '\0';
2882       Curl_safefree(*userp);
2883       *userp = ubuf;
2884     }
2885 
2886     /* Store the password portion if necessary */
2887     if(pbuf) {
2888       memcpy(pbuf, psep + 1, plen);
2889       pbuf[plen] = '\0';
2890       Curl_safefree(*passwdp);
2891       *passwdp = pbuf;
2892     }
2893 
2894     /* Store the options portion if necessary */
2895     if(obuf) {
2896       memcpy(obuf, osep + 1, olen);
2897       obuf[olen] = '\0';
2898       Curl_safefree(*optionsp);
2899       *optionsp = obuf;
2900     }
2901   }
2902 
2903   return result;
2904 }
2905 
2906 /*************************************************************
2907  * Figure out the remote port number and fix it in the URL
2908  *
2909  * No matter if we use a proxy or not, we have to figure out the remote
2910  * port number of various reasons.
2911  *
2912  * The port number embedded in the URL is replaced, if necessary.
2913  *************************************************************/
2914 static CURLcode parse_remote_port(struct Curl_easy *data,
2915                                   struct connectdata *conn)
2916 {
2917 
2918   if(data->set.use_port && data->state.allow_port) {
2919     /* if set, we use this instead of the port possibly given in the URL */
2920     char portbuf[16];
2921     CURLUcode uc;
2922     conn->remote_port = (unsigned short)data->set.use_port;
2923     msnprintf(portbuf, sizeof(portbuf), "%d", conn->remote_port);
2924     uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0);
2925     if(uc)
2926       return CURLE_OUT_OF_MEMORY;
2927   }
2928 
2929   return CURLE_OK;
2930 }
2931 
2932 /*
2933  * Override the login details from the URL with that in the CURLOPT_USERPWD
2934  * option or a .netrc file, if applicable.
2935  */
2936 static CURLcode override_login(struct Curl_easy *data,
2937                                struct connectdata *conn)
2938 {
2939   CURLUcode uc;
2940   char **userp = &conn->user;
2941   char **passwdp = &conn->passwd;
2942   char **optionsp = &conn->options;
2943 
2944 #ifndef CURL_DISABLE_NETRC
2945   if(data->set.use_netrc == CURL_NETRC_REQUIRED && conn->bits.user_passwd) {
2946     Curl_safefree(*userp);
2947     Curl_safefree(*passwdp);
2948     conn->bits.user_passwd = FALSE; /* disable user+password */
2949   }
2950 #endif
2951 
2952   if(data->set.str[STRING_OPTIONS]) {
2953     free(*optionsp);
2954     *optionsp = strdup(data->set.str[STRING_OPTIONS]);
2955     if(!*optionsp)
2956       return CURLE_OUT_OF_MEMORY;
2957   }
2958 
2959 #ifndef CURL_DISABLE_NETRC
2960   conn->bits.netrc = FALSE;
2961   if(data->set.use_netrc && !data->set.str[STRING_USERNAME]) {
2962     bool netrc_user_changed = FALSE;
2963     bool netrc_passwd_changed = FALSE;
2964     int ret;
2965 
2966     ret = Curl_parsenetrc(conn->host.name,
2967                           userp, passwdp,
2968                           &netrc_user_changed, &netrc_passwd_changed,
2969                           data->set.str[STRING_NETRC_FILE]);
2970     if(ret > 0) {
2971       infof(data, "Couldn't find host %s in the %s file; using defaults",
2972             conn->host.name, data->set.str[STRING_NETRC_FILE]);
2973     }
2974     else if(ret < 0) {
2975       return CURLE_OUT_OF_MEMORY;
2976     }
2977     else {
2978       /* set bits.netrc TRUE to remember that we got the name from a .netrc
2979          file, so that it is safe to use even if we followed a Location: to a
2980          different host or similar. */
2981       conn->bits.netrc = TRUE;
2982       conn->bits.user_passwd = TRUE; /* enable user+password */
2983     }
2984   }
2985 #endif
2986 
2987   /* for updated strings, we update them in the URL */
2988   if(*userp) {
2989     CURLcode result = Curl_setstropt(&data->state.aptr.user, *userp);
2990     if(result)
2991       return result;
2992   }
2993   if(data->state.aptr.user) {
2994     uc = curl_url_set(data->state.uh, CURLUPART_USER, data->state.aptr.user,
2995                       CURLU_URLENCODE);
2996     if(uc)
2997       return Curl_uc_to_curlcode(uc);
2998     if(!*userp) {
2999       *userp = strdup(data->state.aptr.user);
3000       if(!*userp)
3001         return CURLE_OUT_OF_MEMORY;
3002     }
3003   }
3004 
3005   if(*passwdp) {
3006     CURLcode result = Curl_setstropt(&data->state.aptr.passwd, *passwdp);
3007     if(result)
3008       return result;
3009   }
3010   if(data->state.aptr.passwd) {
3011     uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD,
3012                       data->state.aptr.passwd, CURLU_URLENCODE);
3013     if(uc)
3014       return Curl_uc_to_curlcode(uc);
3015     if(!*passwdp) {
3016       *passwdp = strdup(data->state.aptr.passwd);
3017       if(!*passwdp)
3018         return CURLE_OUT_OF_MEMORY;
3019     }
3020   }
3021 
3022   return CURLE_OK;
3023 }
3024 
3025 /*
3026  * Set the login details so they're available in the connection
3027  */
3028 static CURLcode set_login(struct connectdata *conn)
3029 {
3030   CURLcode result = CURLE_OK;
3031   const char *setuser = CURL_DEFAULT_USER;
3032   const char *setpasswd = CURL_DEFAULT_PASSWORD;
3033 
3034   /* If our protocol needs a password and we have none, use the defaults */
3035   if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd)
3036     ;
3037   else {
3038     setuser = "";
3039     setpasswd = "";
3040   }
3041   /* Store the default user */
3042   if(!conn->user) {
3043     conn->user = strdup(setuser);
3044     if(!conn->user)
3045       return CURLE_OUT_OF_MEMORY;
3046   }
3047 
3048   /* Store the default password */
3049   if(!conn->passwd) {
3050     conn->passwd = strdup(setpasswd);
3051     if(!conn->passwd)
3052       result = CURLE_OUT_OF_MEMORY;
3053   }
3054 
3055   return result;
3056 }
3057 
3058 /*
3059  * Parses a "host:port" string to connect to.
3060  * The hostname and the port may be empty; in this case, NULL is returned for
3061  * the hostname and -1 for the port.
3062  */
3063 static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
3064                                            const char *host,
3065                                            char **hostname_result,
3066                                            int *port_result)
3067 {
3068   char *host_dup;
3069   char *hostptr;
3070   char *host_portno;
3071   char *portptr;
3072   int port = -1;
3073   CURLcode result = CURLE_OK;
3074 
3075 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
3076   (void) data;
3077 #endif
3078 
3079   *hostname_result = NULL;
3080   *port_result = -1;
3081 
3082   if(!host || !*host)
3083     return CURLE_OK;
3084 
3085   host_dup = strdup(host);
3086   if(!host_dup)
3087     return CURLE_OUT_OF_MEMORY;
3088 
3089   hostptr = host_dup;
3090 
3091   /* start scanning for port number at this point */
3092   portptr = hostptr;
3093 
3094   /* detect and extract RFC6874-style IPv6-addresses */
3095   if(*hostptr == '[') {
3096 #ifdef ENABLE_IPV6
3097     char *ptr = ++hostptr; /* advance beyond the initial bracket */
3098     while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
3099       ptr++;
3100     if(*ptr == '%') {
3101       /* There might be a zone identifier */
3102       if(strncmp("%25", ptr, 3))
3103         infof(data, "Please URL encode %% as %%25, see RFC 6874.");
3104       ptr++;
3105       /* Allow unreserved characters as defined in RFC 3986 */
3106       while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
3107                      (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
3108         ptr++;
3109     }
3110     if(*ptr == ']')
3111       /* yeps, it ended nicely with a bracket as well */
3112       *ptr++ = '\0';
3113     else
3114       infof(data, "Invalid IPv6 address format");
3115     portptr = ptr;
3116     /* Note that if this didn't end with a bracket, we still advanced the
3117      * hostptr first, but I can't see anything wrong with that as no host
3118      * name nor a numeric can legally start with a bracket.
3119      */
3120 #else
3121     failf(data, "Use of IPv6 in *_CONNECT_TO without IPv6 support built-in!");
3122     result = CURLE_NOT_BUILT_IN;
3123     goto error;
3124 #endif
3125   }
3126 
3127   /* Get port number off server.com:1080 */
3128   host_portno = strchr(portptr, ':');
3129   if(host_portno) {
3130     char *endp = NULL;
3131     *host_portno = '\0'; /* cut off number from host name */
3132     host_portno++;
3133     if(*host_portno) {
3134       long portparse = strtol(host_portno, &endp, 10);
3135       if((endp && *endp) || (portparse < 0) || (portparse > 65535)) {
3136         failf(data, "No valid port number in connect to host string (%s)",
3137               host_portno);
3138         result = CURLE_SETOPT_OPTION_SYNTAX;
3139         goto error;
3140       }
3141       else
3142         port = (int)portparse; /* we know it will fit */
3143     }
3144   }
3145 
3146   /* now, clone the cleaned host name */
3147   if(hostptr) {
3148     *hostname_result = strdup(hostptr);
3149     if(!*hostname_result) {
3150       result = CURLE_OUT_OF_MEMORY;
3151       goto error;
3152     }
3153   }
3154 
3155   *port_result = port;
3156 
3157   error:
3158   free(host_dup);
3159   return result;
3160 }
3161 
3162 /*
3163  * Parses one "connect to" string in the form:
3164  * "HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT".
3165  */
3166 static CURLcode parse_connect_to_string(struct Curl_easy *data,
3167                                         struct connectdata *conn,
3168                                         const char *conn_to_host,
3169                                         char **host_result,
3170                                         int *port_result)
3171 {
3172   CURLcode result = CURLE_OK;
3173   const char *ptr = conn_to_host;
3174   int host_match = FALSE;
3175   int port_match = FALSE;
3176 
3177   *host_result = NULL;
3178   *port_result = -1;
3179 
3180   if(*ptr == ':') {
3181     /* an empty hostname always matches */
3182     host_match = TRUE;
3183     ptr++;
3184   }
3185   else {
3186     /* check whether the URL's hostname matches */
3187     size_t hostname_to_match_len;
3188     char *hostname_to_match = aprintf("%s%s%s",
3189                                       conn->bits.ipv6_ip ? "[" : "",
3190                                       conn->host.name,
3191                                       conn->bits.ipv6_ip ? "]" : "");
3192     if(!hostname_to_match)
3193       return CURLE_OUT_OF_MEMORY;
3194     hostname_to_match_len = strlen(hostname_to_match);
3195     host_match = strncasecompare(ptr, hostname_to_match,
3196                                  hostname_to_match_len);
3197     free(hostname_to_match);
3198     ptr += hostname_to_match_len;
3199 
3200     host_match = host_match && *ptr == ':';
3201     ptr++;
3202   }
3203 
3204   if(host_match) {
3205     if(*ptr == ':') {
3206       /* an empty port always matches */
3207       port_match = TRUE;
3208       ptr++;
3209     }
3210     else {
3211       /* check whether the URL's port matches */
3212       char *ptr_next = strchr(ptr, ':');
3213       if(ptr_next) {
3214         char *endp = NULL;
3215         long port_to_match = strtol(ptr, &endp, 10);
3216         if((endp == ptr_next) && (port_to_match == conn->remote_port)) {
3217           port_match = TRUE;
3218           ptr = ptr_next + 1;
3219         }
3220       }
3221     }
3222   }
3223 
3224   if(host_match && port_match) {
3225     /* parse the hostname and port to connect to */
3226     result = parse_connect_to_host_port(data, ptr, host_result, port_result);
3227   }
3228 
3229   return result;
3230 }
3231 
3232 /*
3233  * Processes all strings in the "connect to" slist, and uses the "connect
3234  * to host" and "connect to port" of the first string that matches.
3235  */
3236 static CURLcode parse_connect_to_slist(struct Curl_easy *data,
3237                                        struct connectdata *conn,
3238                                        struct curl_slist *conn_to_host)
3239 {
3240   CURLcode result = CURLE_OK;
3241   char *host = NULL;
3242   int port = -1;
3243 
3244   while(conn_to_host && !host && port == -1) {
3245     result = parse_connect_to_string(data, conn, conn_to_host->data,
3246                                      &host, &port);
3247     if(result)
3248       return result;
3249 
3250     if(host && *host) {
3251       conn->conn_to_host.rawalloc = host;
3252       conn->conn_to_host.name = host;
3253       conn->bits.conn_to_host = TRUE;
3254 
3255       infof(data, "Connecting to hostname: %s", host);
3256     }
3257     else {
3258       /* no "connect to host" */
3259       conn->bits.conn_to_host = FALSE;
3260       Curl_safefree(host);
3261     }
3262 
3263     if(port >= 0) {
3264       conn->conn_to_port = port;
3265       conn->bits.conn_to_port = TRUE;
3266       infof(data, "Connecting to port: %d", port);
3267     }
3268     else {
3269       /* no "connect to port" */
3270       conn->bits.conn_to_port = FALSE;
3271       port = -1;
3272     }
3273 
3274     conn_to_host = conn_to_host->next;
3275   }
3276 
3277 #ifndef CURL_DISABLE_ALTSVC
3278   if(data->asi && !host && (port == -1) &&
3279      ((conn->handler->protocol == CURLPROTO_HTTPS) ||
3280 #ifdef CURLDEBUG
3281       /* allow debug builds to circumvent the HTTPS restriction */
3282       getenv("CURL_ALTSVC_HTTP")
3283 #else
3284       0
3285 #endif
3286        )) {
3287     /* no connect_to match, try alt-svc! */
3288     enum alpnid srcalpnid;
3289     bool hit;
3290     struct altsvc *as;
3291     const int allowed_versions = ( ALPN_h1
3292 #ifdef USE_NGHTTP2
3293       | ALPN_h2
3294 #endif
3295 #ifdef ENABLE_QUIC
3296       | ALPN_h3
3297 #endif
3298       ) & data->asi->flags;
3299 
3300     host = conn->host.rawalloc;
3301 #ifdef USE_NGHTTP2
3302     /* with h2 support, check that first */
3303     srcalpnid = ALPN_h2;
3304     hit = Curl_altsvc_lookup(data->asi,
3305                              srcalpnid, host, conn->remote_port, /* from */
3306                              &as /* to */,
3307                              allowed_versions);
3308     if(!hit)
3309 #endif
3310     {
3311       srcalpnid = ALPN_h1;
3312       hit = Curl_altsvc_lookup(data->asi,
3313                                srcalpnid, host, conn->remote_port, /* from */
3314                                &as /* to */,
3315                                allowed_versions);
3316     }
3317     if(hit) {
3318       char *hostd = strdup((char *)as->dst.host);
3319       if(!hostd)
3320         return CURLE_OUT_OF_MEMORY;
3321       conn->conn_to_host.rawalloc = hostd;
3322       conn->conn_to_host.name = hostd;
3323       conn->bits.conn_to_host = TRUE;
3324       conn->conn_to_port = as->dst.port;
3325       conn->bits.conn_to_port = TRUE;
3326       conn->bits.altused = TRUE;
3327       infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d",
3328             Curl_alpnid2str(srcalpnid), host, conn->remote_port,
3329             Curl_alpnid2str(as->dst.alpnid), hostd, as->dst.port);
3330       if(srcalpnid != as->dst.alpnid) {
3331         /* protocol version switch */
3332         switch(as->dst.alpnid) {
3333         case ALPN_h1:
3334           conn->httpversion = 11;
3335           break;
3336         case ALPN_h2:
3337           conn->httpversion = 20;
3338           break;
3339         case ALPN_h3:
3340           conn->transport = TRNSPRT_QUIC;
3341           conn->httpversion = 30;
3342           break;
3343         default: /* shouldn't be possible */
3344           break;
3345         }
3346       }
3347     }
3348   }
3349 #endif
3350 
3351   return result;
3352 }
3353 
3354 /*************************************************************
3355  * Resolve the address of the server or proxy
3356  *************************************************************/
3357 static CURLcode resolve_server(struct Curl_easy *data,
3358                                struct connectdata *conn,
3359                                bool *async)
3360 {
3361   CURLcode result = CURLE_OK;
3362   timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
3363 
3364   DEBUGASSERT(conn);
3365   DEBUGASSERT(data);
3366   /*************************************************************
3367    * Resolve the name of the server or proxy
3368    *************************************************************/
3369   if(conn->bits.reuse)
3370     /* We're reusing the connection - no need to resolve anything, and
3371        idnconvert_hostname() was called already in create_conn() for the re-use
3372        case. */
3373     *async = FALSE;
3374 
3375   else {
3376     /* this is a fresh connect */
3377     int rc;
3378     struct Curl_dns_entry *hostaddr = NULL;
3379 
3380 #ifdef USE_UNIX_SOCKETS
3381     if(conn->unix_domain_socket) {
3382       /* Unix domain sockets are local. The host gets ignored, just use the
3383        * specified domain socket address. Do not cache "DNS entries". There is
3384        * no DNS involved and we already have the filesystem path available */
3385       const char *path = conn->unix_domain_socket;
3386 
3387       hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
3388       if(!hostaddr)
3389         result = CURLE_OUT_OF_MEMORY;
3390       else {
3391         bool longpath = FALSE;
3392         hostaddr->addr = Curl_unix2addr(path, &longpath,
3393                                         conn->bits.abstract_unix_socket);
3394         if(hostaddr->addr)
3395           hostaddr->inuse++;
3396         else {
3397           /* Long paths are not supported for now */
3398           if(longpath) {
3399             failf(data, "Unix socket path too long: '%s'", path);
3400             result = CURLE_COULDNT_RESOLVE_HOST;
3401           }
3402           else
3403             result = CURLE_OUT_OF_MEMORY;
3404           free(hostaddr);
3405           hostaddr = NULL;
3406         }
3407       }
3408     }
3409     else
3410 #endif
3411 
3412     if(!conn->bits.proxy) {
3413       struct hostname *connhost;
3414       if(conn->bits.conn_to_host)
3415         connhost = &conn->conn_to_host;
3416       else
3417         connhost = &conn->host;
3418 
3419       /* If not connecting via a proxy, extract the port from the URL, if it is
3420        * there, thus overriding any defaults that might have been set above. */
3421       if(conn->bits.conn_to_port)
3422         conn->port = conn->conn_to_port;
3423       else
3424         conn->port = conn->remote_port;
3425 
3426       /* Resolve target host right on */
3427       conn->hostname_resolve = strdup(connhost->name);
3428       if(!conn->hostname_resolve)
3429         return CURLE_OUT_OF_MEMORY;
3430       rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
3431                                &hostaddr, timeout_ms);
3432       if(rc == CURLRESOLV_PENDING)
3433         *async = TRUE;
3434 
3435       else if(rc == CURLRESOLV_TIMEDOUT) {
3436         failf(data, "Failed to resolve host '%s' with timeout after %ld ms",
3437               connhost->dispname,
3438               Curl_timediff(Curl_now(), data->progress.t_startsingle));
3439         result = CURLE_OPERATION_TIMEDOUT;
3440       }
3441       else if(!hostaddr) {
3442         failf(data, "Could not resolve host: %s", connhost->dispname);
3443         result = CURLE_COULDNT_RESOLVE_HOST;
3444         /* don't return yet, we need to clean up the timeout first */
3445       }
3446     }
3447 #ifndef CURL_DISABLE_PROXY
3448     else {
3449       /* This is a proxy that hasn't been resolved yet. */
3450 
3451       struct hostname * const host = conn->bits.socksproxy ?
3452         &conn->socks_proxy.host : &conn->http_proxy.host;
3453 
3454       /* resolve proxy */
3455       conn->hostname_resolve = strdup(host->name);
3456       if(!conn->hostname_resolve)
3457         return CURLE_OUT_OF_MEMORY;
3458       rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
3459                                &hostaddr, timeout_ms);
3460 
3461       if(rc == CURLRESOLV_PENDING)
3462         *async = TRUE;
3463 
3464       else if(rc == CURLRESOLV_TIMEDOUT)
3465         result = CURLE_OPERATION_TIMEDOUT;
3466 
3467       else if(!hostaddr) {
3468         failf(data, "Couldn't resolve proxy '%s'", host->dispname);
3469         result = CURLE_COULDNT_RESOLVE_PROXY;
3470         /* don't return yet, we need to clean up the timeout first */
3471       }
3472     }
3473 #endif
3474     DEBUGASSERT(conn->dns_entry == NULL);
3475     conn->dns_entry = hostaddr;
3476   }
3477 
3478   return result;
3479 }
3480 
3481 /*
3482  * Cleanup the connection just allocated before we can move along and use the
3483  * previously existing one.  All relevant data is copied over and old_conn is
3484  * ready for freeing once this function returns.
3485  */
3486 static void reuse_conn(struct Curl_easy *data,
3487                        struct connectdata *old_conn,
3488                        struct connectdata *conn)
3489 {
3490   /* 'local_ip' and 'local_port' get filled with local's numerical
3491      ip address and port number whenever an outgoing connection is
3492      **established** from the primary socket to a remote address. */
3493   char local_ip[MAX_IPADR_LEN] = "";
3494   int local_port = -1;
3495 #ifndef CURL_DISABLE_PROXY
3496   Curl_free_idnconverted_hostname(&old_conn->http_proxy.host);
3497   Curl_free_idnconverted_hostname(&old_conn->socks_proxy.host);
3498 
3499   free(old_conn->http_proxy.host.rawalloc);
3500   free(old_conn->socks_proxy.host.rawalloc);
3501   Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
3502 #endif
3503   /* free the SSL config struct from this connection struct as this was
3504      allocated in vain and is targeted for destruction */
3505   Curl_free_primary_ssl_config(&old_conn->ssl_config);
3506 
3507   /* get the user+password information from the old_conn struct since it may
3508    * be new for this request even when we re-use an existing connection */
3509   conn->bits.user_passwd = old_conn->bits.user_passwd;
3510   if(conn->bits.user_passwd) {
3511     /* use the new user name and password though */
3512     Curl_safefree(conn->user);
3513     Curl_safefree(conn->passwd);
3514     conn->user = old_conn->user;
3515     conn->passwd = old_conn->passwd;
3516     old_conn->user = NULL;
3517     old_conn->passwd = NULL;
3518   }
3519 
3520 #ifndef CURL_DISABLE_PROXY
3521   conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
3522   if(conn->bits.proxy_user_passwd) {
3523     /* use the new proxy user name and proxy password though */
3524     Curl_safefree(conn->http_proxy.user);
3525     Curl_safefree(conn->socks_proxy.user);
3526     Curl_safefree(conn->http_proxy.passwd);
3527     Curl_safefree(conn->socks_proxy.passwd);
3528     conn->http_proxy.user = old_conn->http_proxy.user;
3529     conn->socks_proxy.user = old_conn->socks_proxy.user;
3530     conn->http_proxy.passwd = old_conn->http_proxy.passwd;
3531     conn->socks_proxy.passwd = old_conn->socks_proxy.passwd;
3532     old_conn->http_proxy.user = NULL;
3533     old_conn->socks_proxy.user = NULL;
3534     old_conn->http_proxy.passwd = NULL;
3535     old_conn->socks_proxy.passwd = NULL;
3536   }
3537   Curl_safefree(old_conn->http_proxy.user);
3538   Curl_safefree(old_conn->socks_proxy.user);
3539   Curl_safefree(old_conn->http_proxy.passwd);
3540   Curl_safefree(old_conn->socks_proxy.passwd);
3541 #endif
3542 
3543   /* host can change, when doing keepalive with a proxy or if the case is
3544      different this time etc */
3545   Curl_free_idnconverted_hostname(&conn->host);
3546   Curl_free_idnconverted_hostname(&conn->conn_to_host);
3547   Curl_safefree(conn->host.rawalloc);
3548   Curl_safefree(conn->conn_to_host.rawalloc);
3549   conn->host = old_conn->host;
3550   conn->conn_to_host = old_conn->conn_to_host;
3551   conn->conn_to_port = old_conn->conn_to_port;
3552   conn->remote_port = old_conn->remote_port;
3553   Curl_safefree(conn->hostname_resolve);
3554 
3555   conn->hostname_resolve = old_conn->hostname_resolve;
3556   old_conn->hostname_resolve = NULL;
3557 
3558   /* persist connection info in session handle */
3559   if(conn->transport == TRNSPRT_TCP) {
3560     Curl_conninfo_local(data, conn->sock[FIRSTSOCKET],
3561                         local_ip, &local_port);
3562   }
3563   Curl_persistconninfo(data, conn, local_ip, local_port);
3564 
3565   conn_reset_all_postponed_data(old_conn); /* free buffers */
3566 
3567   /* re-use init */
3568   conn->bits.reuse = TRUE; /* yes, we're re-using here */
3569 
3570   Curl_safefree(old_conn->user);
3571   Curl_safefree(old_conn->passwd);
3572   Curl_safefree(old_conn->options);
3573   Curl_safefree(old_conn->localdev);
3574   Curl_llist_destroy(&old_conn->easyq, NULL);
3575 
3576 #ifdef USE_UNIX_SOCKETS
3577   Curl_safefree(old_conn->unix_domain_socket);
3578 #endif
3579 }
3580 
3581 /**
3582  * create_conn() sets up a new connectdata struct, or re-uses an already
3583  * existing one, and resolves host name.
3584  *
3585  * if this function returns CURLE_OK and *async is set to TRUE, the resolve
3586  * response will be coming asynchronously. If *async is FALSE, the name is
3587  * already resolved.
3588  *
3589  * @param data The sessionhandle pointer
3590  * @param in_connect is set to the next connection data pointer
3591  * @param async is set TRUE when an async DNS resolution is pending
3592  * @see Curl_setup_conn()
3593  *
3594  */
3595 
3596 static CURLcode create_conn(struct Curl_easy *data,
3597                             struct connectdata **in_connect,
3598                             bool *async)
3599 {
3600   CURLcode result = CURLE_OK;
3601   struct connectdata *conn;
3602   struct connectdata *conn_temp = NULL;
3603   bool reuse;
3604   bool connections_available = TRUE;
3605   bool force_reuse = FALSE;
3606   bool waitpipe = FALSE;
3607   size_t max_host_connections = Curl_multi_max_host_connections(data->multi);
3608   size_t max_total_connections = Curl_multi_max_total_connections(data->multi);
3609 
3610   *async = FALSE;
3611   *in_connect = NULL;
3612 
3613   /*************************************************************
3614    * Check input data
3615    *************************************************************/
3616   if(!data->state.url) {
3617     result = CURLE_URL_MALFORMAT;
3618     goto out;
3619   }
3620 
3621   /* First, split up the current URL in parts so that we can use the
3622      parts for checking against the already present connections. In order
3623      to not have to modify everything at once, we allocate a temporary
3624      connection data struct and fill in for comparison purposes. */
3625   conn = allocate_conn(data);
3626 
3627   if(!conn) {
3628     result = CURLE_OUT_OF_MEMORY;
3629     goto out;
3630   }
3631 
3632   /* We must set the return variable as soon as possible, so that our
3633      parent can cleanup any possible allocs we may have done before
3634      any failure */
3635   *in_connect = conn;
3636 
3637   result = parseurlandfillconn(data, conn);
3638   if(result)
3639     goto out;
3640 
3641   if(data->set.str[STRING_SASL_AUTHZID]) {
3642     conn->sasl_authzid = strdup(data->set.str[STRING_SASL_AUTHZID]);
3643     if(!conn->sasl_authzid) {
3644       result = CURLE_OUT_OF_MEMORY;
3645       goto out;
3646     }
3647   }
3648 
3649   if(data->set.str[STRING_BEARER]) {
3650     conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]);
3651     if(!conn->oauth_bearer) {
3652       result = CURLE_OUT_OF_MEMORY;
3653       goto out;
3654     }
3655   }
3656 
3657 #ifdef USE_UNIX_SOCKETS
3658   if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
3659     conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
3660     if(!conn->unix_domain_socket) {
3661       result = CURLE_OUT_OF_MEMORY;
3662       goto out;
3663     }
3664     conn->bits.abstract_unix_socket = data->set.abstract_unix_socket;
3665   }
3666 #endif
3667 
3668   /* After the unix socket init but before the proxy vars are used, parse and
3669      initialize the proxy vars */
3670 #ifndef CURL_DISABLE_PROXY
3671   result = create_conn_helper_init_proxy(data, conn);
3672   if(result)
3673     goto out;
3674 
3675   /*************************************************************
3676    * If the protocol is using SSL and HTTP proxy is used, we set
3677    * the tunnel_proxy bit.
3678    *************************************************************/
3679   if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
3680     conn->bits.tunnel_proxy = TRUE;
3681 #endif
3682 
3683   /*************************************************************
3684    * Figure out the remote port number and fix it in the URL
3685    *************************************************************/
3686   result = parse_remote_port(data, conn);
3687   if(result)
3688     goto out;
3689 
3690   /* Check for overridden login details and set them accordingly so that
3691      they are known when protocol->setup_connection is called! */
3692   result = override_login(data, conn);
3693   if(result)
3694     goto out;
3695 
3696   result = set_login(conn); /* default credentials */
3697   if(result)
3698     goto out;
3699 
3700   /*************************************************************
3701    * Process the "connect to" linked list of hostname/port mappings.
3702    * Do this after the remote port number has been fixed in the URL.
3703    *************************************************************/
3704   result = parse_connect_to_slist(data, conn, data->set.connect_to);
3705   if(result)
3706     goto out;
3707 
3708 
3709   /*************************************************************
3710    * Check whether the host and the "connect to host" are equal.
3711    * Do this after the hostnames have been IDN-converted.
3712    *************************************************************/
3713   if(conn->bits.conn_to_host &&
3714      strcasecompare(conn->conn_to_host.name, conn->host.name)) {
3715     conn->bits.conn_to_host = FALSE;
3716   }
3717 
3718   /*************************************************************
3719    * Check whether the port and the "connect to port" are equal.
3720    * Do this after the remote port number has been fixed in the URL.
3721    *************************************************************/
3722   if(conn->bits.conn_to_port && conn->conn_to_port == conn->remote_port) {
3723     conn->bits.conn_to_port = FALSE;
3724   }
3725 
3726 #ifndef CURL_DISABLE_PROXY
3727   /*************************************************************
3728    * If the "connect to" feature is used with an HTTP proxy,
3729    * we set the tunnel_proxy bit.
3730    *************************************************************/
3731   if((conn->bits.conn_to_host || conn->bits.conn_to_port) &&
3732       conn->bits.httpproxy)
3733     conn->bits.tunnel_proxy = TRUE;
3734 #endif
3735 
3736   /*************************************************************
3737    * Setup internals depending on protocol. Needs to be done after
3738    * we figured out what/if proxy to use.
3739    *************************************************************/
3740   result = setup_connection_internals(data, conn);
3741   if(result)
3742     goto out;
3743 
3744   conn->recv[FIRSTSOCKET] = Curl_recv_plain;
3745   conn->send[FIRSTSOCKET] = Curl_send_plain;
3746   conn->recv[SECONDARYSOCKET] = Curl_recv_plain;
3747   conn->send[SECONDARYSOCKET] = Curl_send_plain;
3748 
3749   conn->bits.tcp_fastopen = data->set.tcp_fastopen;
3750 
3751   /***********************************************************************
3752    * file: is a special case in that it doesn't need a network connection
3753    ***********************************************************************/
3754 #ifndef CURL_DISABLE_FILE
3755   if(conn->handler->flags & PROTOPT_NONETWORK) {
3756     bool done;
3757     /* this is supposed to be the connect function so we better at least check
3758        that the file is present here! */
3759     DEBUGASSERT(conn->handler->connect_it);
3760     Curl_persistconninfo(data, conn, NULL, -1);
3761     result = conn->handler->connect_it(data, &done);
3762 
3763     /* Setup a "faked" transfer that'll do nothing */
3764     if(!result) {
3765       conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
3766 
3767       Curl_attach_connnection(data, conn);
3768       result = Curl_conncache_add_conn(data);
3769       if(result)
3770         goto out;
3771 
3772       /*
3773        * Setup whatever necessary for a resumed transfer
3774        */
3775       result = setup_range(data);
3776       if(result) {
3777         DEBUGASSERT(conn->handler->done);
3778         /* we ignore the return code for the protocol-specific DONE */
3779         (void)conn->handler->done(data, result, FALSE);
3780         goto out;
3781       }
3782       Curl_setup_transfer(data, -1, -1, FALSE, -1);
3783     }
3784 
3785     /* since we skip do_init() */
3786     Curl_init_do(data, conn);
3787 
3788     goto out;
3789   }
3790 #endif
3791 
3792   /* Get a cloned copy of the SSL config situation stored in the
3793      connection struct. But to get this going nicely, we must first make
3794      sure that the strings in the master copy are pointing to the correct
3795      strings in the session handle strings array!
3796 
3797      Keep in mind that the pointers in the master copy are pointing to strings
3798      that will be freed as part of the Curl_easy struct, but all cloned
3799      copies will be separately allocated.
3800   */
3801   data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
3802   data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
3803   data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
3804   data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
3805   data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
3806   data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
3807   data->set.ssl.primary.cipher_list =
3808     data->set.str[STRING_SSL_CIPHER_LIST];
3809   data->set.ssl.primary.cipher_list13 =
3810     data->set.str[STRING_SSL_CIPHER13_LIST];
3811   data->set.ssl.primary.pinned_key =
3812     data->set.str[STRING_SSL_PINNEDPUBLICKEY];
3813   data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT];
3814   data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
3815   data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES];
3816 
3817 #ifndef CURL_DISABLE_PROXY
3818   data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
3819   data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
3820   data->set.proxy_ssl.primary.random_file =
3821     data->set.str[STRING_SSL_RANDOM_FILE];
3822   data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
3823   data->set.proxy_ssl.primary.cipher_list =
3824     data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
3825   data->set.proxy_ssl.primary.cipher_list13 =
3826     data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
3827   data->set.proxy_ssl.primary.pinned_key =
3828     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
3829   data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
3830   data->set.proxy_ssl.primary.ca_info_blob =
3831     data->set.blobs[BLOB_CAINFO_PROXY];
3832   data->set.proxy_ssl.primary.issuercert =
3833     data->set.str[STRING_SSL_ISSUERCERT_PROXY];
3834   data->set.proxy_ssl.primary.issuercert_blob =
3835     data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
3836   data->set.proxy_ssl.primary.CRLfile =
3837     data->set.str[STRING_SSL_CRLFILE_PROXY];
3838   data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
3839   data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
3840   data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
3841   data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
3842   data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
3843   data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
3844 #endif
3845   data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
3846   data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
3847   data->set.ssl.key = data->set.str[STRING_KEY];
3848   data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
3849   data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
3850   data->set.ssl.primary.clientcert = data->set.str[STRING_CERT];
3851 #ifdef USE_TLS_SRP
3852   data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME];
3853   data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD];
3854 #ifndef CURL_DISABLE_PROXY
3855   data->set.proxy_ssl.primary.username =
3856     data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
3857   data->set.proxy_ssl.primary.password =
3858     data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
3859 #endif
3860 #endif
3861   data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
3862 
3863   if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
3864                                     &conn->ssl_config)) {
3865     result = CURLE_OUT_OF_MEMORY;
3866     goto out;
3867   }
3868 
3869 #ifndef CURL_DISABLE_PROXY
3870   if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
3871                                     &conn->proxy_ssl_config)) {
3872     result = CURLE_OUT_OF_MEMORY;
3873     goto out;
3874   }
3875 #endif
3876 
3877   prune_dead_connections(data);
3878 
3879   /*************************************************************
3880    * Check the current list of connections to see if we can
3881    * re-use an already existing one or if we have to create a
3882    * new one.
3883    *************************************************************/
3884 
3885   DEBUGASSERT(conn->user);
3886   DEBUGASSERT(conn->passwd);
3887 
3888   /* reuse_fresh is TRUE if we are told to use a new connection by force, but
3889      we only acknowledge this option if this is not a re-used connection
3890      already (which happens due to follow-location or during a HTTP
3891      authentication phase). CONNECT_ONLY transfers also refuse reuse. */
3892   if((data->set.reuse_fresh && !data->state.this_is_a_follow) ||
3893      data->set.connect_only)
3894     reuse = FALSE;
3895   else
3896     reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);
3897 
3898   if(reuse) {
3899     /*
3900      * We already have a connection for this, we got the former connection in
3901      * the conn_temp variable and thus we need to cleanup the one we just
3902      * allocated before we can move along and use the previously existing one.
3903      */
3904     reuse_conn(data, conn, conn_temp);
3905 #ifdef USE_SSL
3906     free(conn->ssl_extra);
3907 #endif
3908     free(conn);          /* we don't need this anymore */
3909     conn = conn_temp;
3910     *in_connect = conn;
3911 
3912 #ifndef CURL_DISABLE_PROXY
3913     infof(data, "Re-using existing connection! (#%ld) with %s %s",
3914           conn->connection_id,
3915           conn->bits.proxy?"proxy":"host",
3916           conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
3917           conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
3918           conn->host.dispname);
3919 #else
3920     infof(data, "Re-using existing connection! (#%ld) with host %s",
3921           conn->connection_id, conn->host.dispname);
3922 #endif
3923   }
3924   else {
3925     /* We have decided that we want a new connection. However, we may not
3926        be able to do that if we have reached the limit of how many
3927        connections we are allowed to open. */
3928 
3929     if(conn->handler->flags & PROTOPT_ALPN_NPN) {
3930       /* The protocol wants it, so set the bits if enabled in the easy handle
3931          (default) */
3932       if(data->set.ssl_enable_alpn)
3933         conn->bits.tls_enable_alpn = TRUE;
3934       if(data->set.ssl_enable_npn)
3935         conn->bits.tls_enable_npn = TRUE;
3936     }
3937 
3938     if(waitpipe)
3939       /* There is a connection that *might* become usable for multiplexing
3940          "soon", and we wait for that */
3941       connections_available = FALSE;
3942     else {
3943       /* this gets a lock on the conncache */
3944       const char *bundlehost;
3945       struct connectbundle *bundle =
3946         Curl_conncache_find_bundle(data, conn, data->state.conn_cache,
3947                                    &bundlehost);
3948 
3949       if(max_host_connections > 0 && bundle &&
3950          (bundle->num_connections >= max_host_connections)) {
3951         struct connectdata *conn_candidate;
3952 
3953         /* The bundle is full. Extract the oldest connection. */
3954         conn_candidate = Curl_conncache_extract_bundle(data, bundle);
3955         CONNCACHE_UNLOCK(data);
3956 
3957         if(conn_candidate)
3958           (void)Curl_disconnect(data, conn_candidate, FALSE);
3959         else {
3960           infof(data, "No more connections allowed to host %s: %zu",
3961                 bundlehost, max_host_connections);
3962           connections_available = FALSE;
3963         }
3964       }
3965       else
3966         CONNCACHE_UNLOCK(data);
3967 
3968     }
3969 
3970     if(connections_available &&
3971        (max_total_connections > 0) &&
3972        (Curl_conncache_size(data) >= max_total_connections)) {
3973       struct connectdata *conn_candidate;
3974 
3975       /* The cache is full. Let's see if we can kill a connection. */
3976       conn_candidate = Curl_conncache_extract_oldest(data);
3977       if(conn_candidate)
3978         (void)Curl_disconnect(data, conn_candidate, FALSE);
3979       else {
3980         infof(data, "No connections available in cache");
3981         connections_available = FALSE;
3982       }
3983     }
3984 
3985     if(!connections_available) {
3986       infof(data, "No connections available.");
3987 
3988       conn_free(conn);
3989       *in_connect = NULL;
3990 
3991       result = CURLE_NO_CONNECTION_AVAILABLE;
3992       goto out;
3993     }
3994     else {
3995       /*
3996        * This is a brand new connection, so let's store it in the connection
3997        * cache of ours!
3998        */
3999       Curl_attach_connnection(data, conn);
4000       result = Curl_conncache_add_conn(data);
4001       if(result)
4002         goto out;
4003     }
4004 
4005 #if defined(USE_NTLM)
4006     /* If NTLM is requested in a part of this connection, make sure we don't
4007        assume the state is fine as this is a fresh connection and NTLM is
4008        connection based. */
4009     if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
4010        data->state.authhost.done) {
4011       infof(data, "NTLM picked AND auth done set, clear picked!");
4012       data->state.authhost.picked = CURLAUTH_NONE;
4013       data->state.authhost.done = FALSE;
4014     }
4015 
4016     if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
4017        data->state.authproxy.done) {
4018       infof(data, "NTLM-proxy picked AND auth done set, clear picked!");
4019       data->state.authproxy.picked = CURLAUTH_NONE;
4020       data->state.authproxy.done = FALSE;
4021     }
4022 #endif
4023   }
4024 
4025   /* Setup and init stuff before DO starts, in preparing for the transfer. */
4026   Curl_init_do(data, conn);
4027 
4028   /*
4029    * Setup whatever necessary for a resumed transfer
4030    */
4031   result = setup_range(data);
4032   if(result)
4033     goto out;
4034 
4035   /* Continue connectdata initialization here. */
4036 
4037   /*
4038    * Inherit the proper values from the urldata struct AFTER we have arranged
4039    * the persistent connection stuff
4040    */
4041   conn->seek_func = data->set.seek_func;
4042   conn->seek_client = data->set.seek_client;
4043 
4044   /*************************************************************
4045    * Resolve the address of the server or proxy
4046    *************************************************************/
4047   result = resolve_server(data, conn, async);
4048 
4049   /* Strip trailing dots. resolve_server copied the name. */
4050   strip_trailing_dot(&conn->host);
4051 #ifndef CURL_DISABLE_PROXY
4052   if(conn->bits.httpproxy)
4053     strip_trailing_dot(&conn->http_proxy.host);
4054   if(conn->bits.socksproxy)
4055     strip_trailing_dot(&conn->socks_proxy.host);
4056 #endif
4057   if(conn->bits.conn_to_host)
4058     strip_trailing_dot(&conn->conn_to_host);
4059 
4060 out:
4061   return result;
4062 }
4063 
4064 /* Curl_setup_conn() is called after the name resolve initiated in
4065  * create_conn() is all done.
4066  *
4067  * Curl_setup_conn() also handles reused connections
4068  */
4069 CURLcode Curl_setup_conn(struct Curl_easy *data,
4070                          bool *protocol_done)
4071 {
4072   CURLcode result = CURLE_OK;
4073   struct connectdata *conn = data->conn;
4074 
4075   Curl_pgrsTime(data, TIMER_NAMELOOKUP);
4076 
4077   if(conn->handler->flags & PROTOPT_NONETWORK) {
4078     /* nothing to setup when not using a network */
4079     *protocol_done = TRUE;
4080     return result;
4081   }
4082   *protocol_done = FALSE; /* default to not done */
4083 
4084 #ifndef CURL_DISABLE_PROXY
4085   /* set proxy_connect_closed to false unconditionally already here since it
4086      is used strictly to provide extra information to a parent function in the
4087      case of proxy CONNECT failures and we must make sure we don't have it
4088      lingering set from a previous invoke */
4089   conn->bits.proxy_connect_closed = FALSE;
4090 #endif
4091 
4092 #ifdef CURL_DO_LINEEND_CONV
4093   data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
4094 #endif /* CURL_DO_LINEEND_CONV */
4095 
4096   /* set start time here for timeout purposes in the connect procedure, it
4097      is later set again for the progress meter purpose */
4098   conn->now = Curl_now();
4099 
4100   if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
4101     conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
4102     result = Curl_connecthost(data, conn, conn->dns_entry);
4103     if(result)
4104       return result;
4105   }
4106   else {
4107     Curl_pgrsTime(data, TIMER_CONNECT);    /* we're connected already */
4108     if(conn->ssl[FIRSTSOCKET].use ||
4109        (conn->handler->protocol & PROTO_FAMILY_SSH))
4110       Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
4111     conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
4112     *protocol_done = TRUE;
4113     Curl_updateconninfo(data, conn, conn->sock[FIRSTSOCKET]);
4114     Curl_verboseconnect(data, conn);
4115   }
4116 
4117   conn->now = Curl_now(); /* time this *after* the connect is done, we set
4118                              this here perhaps a second time */
4119   return result;
4120 }
4121 
4122 CURLcode Curl_connect(struct Curl_easy *data,
4123                       bool *asyncp,
4124                       bool *protocol_done)
4125 {
4126   CURLcode result;
4127   struct connectdata *conn;
4128 
4129   *asyncp = FALSE; /* assume synchronous resolves by default */
4130 
4131   /* init the single-transfer specific data */
4132   Curl_free_request_state(data);
4133   memset(&data->req, 0, sizeof(struct SingleRequest));
4134   data->req.maxdownload = -1;
4135 
4136   /* call the stuff that needs to be called */
4137   result = create_conn(data, &conn, asyncp);
4138 
4139   if(!result) {
4140     if(CONN_INUSE(conn) > 1)
4141       /* multiplexed */
4142       *protocol_done = TRUE;
4143     else if(!*asyncp) {
4144       /* DNS resolution is done: that's either because this is a reused
4145          connection, in which case DNS was unnecessary, or because DNS
4146          really did finish already (synch resolver/fast async resolve) */
4147       result = Curl_setup_conn(data, protocol_done);
4148     }
4149   }
4150 
4151   if(result == CURLE_NO_CONNECTION_AVAILABLE) {
4152     return result;
4153   }
4154   else if(result && conn) {
4155     /* We're not allowed to return failure with memory left allocated in the
4156        connectdata struct, free those here */
4157     Curl_detach_connnection(data);
4158     Curl_conncache_remove_conn(data, conn, TRUE);
4159     Curl_disconnect(data, conn, TRUE);
4160   }
4161 
4162   return result;
4163 }
4164 
4165 /*
4166  * Curl_init_do() inits the readwrite session. This is inited each time (in
4167  * the DO function before the protocol-specific DO functions are invoked) for
4168  * a transfer, sometimes multiple times on the same Curl_easy. Make sure
4169  * nothing in here depends on stuff that are setup dynamically for the
4170  * transfer.
4171  *
4172  * Allow this function to get called with 'conn' set to NULL.
4173  */
4174 
4175 CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
4176 {
4177   struct SingleRequest *k = &data->req;
4178 
4179   /* if this is a pushed stream, we need this: */
4180   CURLcode result = Curl_preconnect(data);
4181   if(result)
4182     return result;
4183 
4184   if(conn) {
4185     conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
4186                                    use */
4187     /* if the protocol used doesn't support wildcards, switch it off */
4188     if(data->state.wildcardmatch &&
4189        !(conn->handler->flags & PROTOPT_WILDCARD))
4190       data->state.wildcardmatch = FALSE;
4191   }
4192 
4193   data->state.done = FALSE; /* *_done() is not called yet */
4194   data->state.expect100header = FALSE;
4195 
4196   if(data->set.opt_no_body)
4197     /* in HTTP lingo, no body means using the HEAD request... */
4198     data->state.httpreq = HTTPREQ_HEAD;
4199 
4200   k->start = Curl_now(); /* start time */
4201   k->now = k->start;   /* current time is now */
4202   k->header = TRUE; /* assume header */
4203   k->bytecount = 0;
4204   k->ignorebody = FALSE;
4205 
4206   Curl_speedinit(data);
4207   Curl_pgrsSetUploadCounter(data, 0);
4208   Curl_pgrsSetDownloadCounter(data, 0);
4209 
4210   return CURLE_OK;
4211 }
4212