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