VirtualBox

source: vbox/trunk/src/libs/curl-7.83.1/lib/url.c@ 97138

最後變更 在這個檔案從97138是 95312,由 vboxsync 提交於 3 年 前

libs/{curl,libxml2}: OSE export fixes, bugref:8515

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette