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