From 1eb395f29cc0c3cd3eebdae92f784c5c7015125b Mon Sep 17 00:00:00 2001 From: Oleksandr Kylymnychenko Date: Wed, 22 Jul 2020 15:55:44 +0200 Subject: [PATCH] Add possibility to set the SNI host for the connections Sometimes the URI and the exact host which we want to connect have different domains. And we need to have a way to set the domain for the TLS connection which will be used to verify the TLS cert. The domain from the URI will still be used to create a underlying TCP connection. For example: Target host: example.com Target host's TLS: example.net with setting the SNI host to `example.net` we can still easily connect to `example.com` and get the correct resources as for `example.net` --- Cargo.toml | 2 +- src/client.rs | 37 ++++++++++++++++++++++++++++--------- src/lib.rs | 2 +- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 94b54d9..f01f4da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hyper-tls" -version = "0.4.3" # don't forget html_root_url in lib.rs +version = "0.4.4" # don't forget html_root_url in lib.rs description = "Default TLS implementation for use with hyper" authors = ["Sean McArthur "] license = "MIT/Apache-2.0" diff --git a/src/client.rs b/src/client.rs index a0cf624..02f4259 100644 --- a/src/client.rs +++ b/src/client.rs @@ -15,6 +15,7 @@ type BoxError = Box; #[derive(Clone)] pub struct HttpsConnector { force_https: bool, + sni_host: Option, http: T, tls: TlsConnector, } @@ -65,13 +66,25 @@ impl HttpsConnector { pub fn https_only(&mut self, enable: bool) { self.force_https = enable; } - + + /// Set the host which should be used for Server Name Indication (SNI). + /// + /// if the `sni_host` is not set the default host from URI will be used + pub fn sni_host(&mut self, host: &str) { + self.sni_host = Some(String::from(host)); + } + /// With connector constructor - /// + /// pub fn new_with_connector(http: T) -> Self { native_tls::TlsConnector::new() .map(|tls| HttpsConnector::from((http, tls.into()))) - .unwrap_or_else(|e| panic!("HttpsConnector::new_with_connector() failure: {}", e)) + .unwrap_or_else(|e| { + panic!( + "HttpsConnector::new_with_connector() failure: {}", + e + ) + }) } } @@ -79,6 +92,7 @@ impl From<(T, TlsConnector)> for HttpsConnector { fn from(args: (T, TlsConnector)) -> HttpsConnector { HttpsConnector { force_https: false, + sni_host: None, http: args.0, tls: args.1, } @@ -120,15 +134,21 @@ where return err(ForceHttpsButUriNotHttps.into()); } - let host = dst.host().unwrap_or("").trim_matches(|c| c == '[' || c == ']').to_owned(); + let host = match self.sni_host.as_ref() { + Some(host) => host.to_owned(), + None => dst + .host() + .unwrap_or("") + .trim_matches(|c| c == '[' || c == ']') + .to_owned(), + }; + let connecting = self.http.call(dst); let tls = self.tls.clone(); let fut = async move { let tcp = connecting.await.map_err(Into::into)?; let maybe = if is_https { - let tls = tls - .connect(&host, tcp) - .await?; + let tls = tls.connect(&host, tcp).await?; MaybeHttpsStream::Https(tls) } else { MaybeHttpsStream::Http(tcp) @@ -143,8 +163,7 @@ fn err(e: BoxError) -> HttpsConnecting { HttpsConnecting(Box::pin(async { Err(e) })) } -type BoxedFut = - Pin, BoxError>> + Send>>; +type BoxedFut = Pin, BoxError>> + Send>>; /// A Future representing work to connect to a URL, and a TLS handshake. pub struct HttpsConnecting(BoxedFut); diff --git a/src/lib.rs b/src/lib.rs index 92d0290..a5fec98 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,7 @@ //! Ok(()) //! } //! ``` -#![doc(html_root_url = "https://docs.rs/hyper-tls/0.4.3")] +#![doc(html_root_url = "https://docs.rs/hyper-tls/0.4.4")] #![cfg_attr(test, deny(warnings))] #![deny(missing_docs)] #![deny(missing_debug_implementations)]