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