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