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