From d934db6b7a3229244aa803d9aec97b98c4bc26fd Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Sat, 17 Sep 2022 18:19:15 +0300 Subject: [PATCH 1/7] Allow overriding server name Signed-off-by: Mikail Bagishov --- src/connector.rs | 23 ++++++++++++++++------- src/connector/builder.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/connector.rs b/src/connector.rs index e97be1d..b50bf4c 100644 --- a/src/connector.rs +++ b/src/connector.rs @@ -21,6 +21,7 @@ pub struct HttpsConnector { force_https: bool, http: T, tls_config: Arc, + server_name_override: Option, } impl fmt::Debug for HttpsConnector { @@ -40,6 +41,7 @@ where force_https: false, http, tls_config: cfg.into(), + server_name_override: None, } } } @@ -83,10 +85,19 @@ where Box::pin(f) } else if sch == &http::uri::Scheme::HTTPS { let cfg = self.tls_config.clone(); - let hostname = dst - .host() - .unwrap_or_default() - .to_string(); + let hostname = match self.server_name_override.as_deref() { + Some(h) => h, + None => dst.host().unwrap_or_default(), + }; + let hostname = match rustls::ServerName::try_from(hostname) { + Ok(dnsname) => dnsname, + Err(_) => { + let err = io::Error::new(io::ErrorKind::Other, "invalid dnsname"); + let err: Box = Box::new(err); + let res = std::future::ready(Err(err)); + return Box::pin(res); + } + }; let connecting_future = self.http.call(dst); let f = async move { @@ -94,10 +105,8 @@ where .await .map_err(Into::into)?; let connector = TlsConnector::from(cfg); - let dnsname = rustls::ServerName::try_from(hostname.as_str()) - .map_err(|_| io::Error::new(io::ErrorKind::Other, "invalid dnsname"))?; let tls = connector - .connect(dnsname, tcp) + .connect(hostname, tcp) .await .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; Ok(MaybeHttpsStream::Https(tls)) diff --git a/src/connector/builder.rs b/src/connector/builder.rs index 0398f8b..faf0084 100644 --- a/src/connector/builder.rs +++ b/src/connector/builder.rs @@ -106,6 +106,7 @@ impl ConnectorBuilder { ConnectorBuilder(WantsProtocols1 { tls_config: self.0.tls_config, https_only: true, + server_name_override: None, }) } @@ -117,6 +118,7 @@ impl ConnectorBuilder { ConnectorBuilder(WantsProtocols1 { tls_config: self.0.tls_config, https_only: false, + server_name_override: None, }) } } @@ -128,6 +130,7 @@ impl ConnectorBuilder { pub struct WantsProtocols1 { tls_config: ClientConfig, https_only: bool, + server_name_override: Option, } impl WantsProtocols1 { @@ -136,6 +139,7 @@ impl WantsProtocols1 { force_https: self.https_only, http: conn, tls_config: std::sync::Arc::new(self.tls_config), + server_name_override: None, } } @@ -169,6 +173,15 @@ impl ConnectorBuilder { enable_http1: false, }) } + + /// Override expected server name + /// + /// If called, server certificates will be validated against `server_name_override`, + /// and host portion of URL will not be used for server authentication. + pub fn override_server_name(mut self, server_name_override: String) -> Self { + self.0.server_name_override = Some(server_name_override); + self + } } /// State of a builder with HTTP1 enabled, that may have some other @@ -195,6 +208,15 @@ impl ConnectorBuilder { }) } + /// Override expected server name + /// + /// If called, server certificates will be validated against `server_name_override`, + /// and host portion of URL will not be used for server authentication. + pub fn override_server_name(mut self, server_name_override: String) -> Self { + self.0.inner.server_name_override = Some(server_name_override); + self + } + /// This builds an [`HttpsConnector`] built on hyper's default [`HttpConnector`] #[cfg(feature = "tokio-runtime")] pub fn build(self) -> HttpsConnector { @@ -226,6 +248,15 @@ pub struct WantsProtocols3 { #[cfg(feature = "http2")] impl ConnectorBuilder { + /// Override expected server name + /// + /// If called, server certificates will be validated against `server_name_override`, + /// and host portion of URL will not be used for server authentication. + pub fn override_server_name(mut self, server_name_override: String) -> Self { + self.0.inner.server_name_override = Some(server_name_override); + self + } + /// This builds an [`HttpsConnector`] built on hyper's default [`HttpConnector`] #[cfg(feature = "tokio-runtime")] pub fn build(self) -> HttpsConnector { From dbcade29c53ce4c83e437e34972d782997858ab4 Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Mon, 17 Oct 2022 00:07:36 +0300 Subject: [PATCH 2/7] Rename field --- src/connector.rs | 6 +++--- src/connector/builder.rs | 26 +++++++++++++------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/connector.rs b/src/connector.rs index b50bf4c..a982017 100644 --- a/src/connector.rs +++ b/src/connector.rs @@ -21,7 +21,7 @@ pub struct HttpsConnector { force_https: bool, http: T, tls_config: Arc, - server_name_override: Option, + override_server_name: Option, } impl fmt::Debug for HttpsConnector { @@ -41,7 +41,7 @@ where force_https: false, http, tls_config: cfg.into(), - server_name_override: None, + override_server_name: None, } } } @@ -85,7 +85,7 @@ where Box::pin(f) } else if sch == &http::uri::Scheme::HTTPS { let cfg = self.tls_config.clone(); - let hostname = match self.server_name_override.as_deref() { + let hostname = match self.override_server_name.as_deref() { Some(h) => h, None => dst.host().unwrap_or_default(), }; diff --git a/src/connector/builder.rs b/src/connector/builder.rs index faf0084..dc278f3 100644 --- a/src/connector/builder.rs +++ b/src/connector/builder.rs @@ -106,7 +106,7 @@ impl ConnectorBuilder { ConnectorBuilder(WantsProtocols1 { tls_config: self.0.tls_config, https_only: true, - server_name_override: None, + override_server_name: None, }) } @@ -118,7 +118,7 @@ impl ConnectorBuilder { ConnectorBuilder(WantsProtocols1 { tls_config: self.0.tls_config, https_only: false, - server_name_override: None, + override_server_name: None, }) } } @@ -130,7 +130,7 @@ impl ConnectorBuilder { pub struct WantsProtocols1 { tls_config: ClientConfig, https_only: bool, - server_name_override: Option, + override_server_name: Option, } impl WantsProtocols1 { @@ -139,7 +139,7 @@ impl WantsProtocols1 { force_https: self.https_only, http: conn, tls_config: std::sync::Arc::new(self.tls_config), - server_name_override: None, + override_server_name: self.override_server_name, } } @@ -176,10 +176,10 @@ impl ConnectorBuilder { /// Override expected server name /// - /// If called, server certificates will be validated against `server_name_override`, + /// If called, server certificates will be validated against `override_server_name`, /// and host portion of URL will not be used for server authentication. - pub fn override_server_name(mut self, server_name_override: String) -> Self { - self.0.server_name_override = Some(server_name_override); + pub fn override_server_name(mut self, override_server_name: String) -> Self { + self.0.override_server_name = Some(override_server_name); self } } @@ -210,10 +210,10 @@ impl ConnectorBuilder { /// Override expected server name /// - /// If called, server certificates will be validated against `server_name_override`, + /// If called, server certificates will be validated against `override_server_name`, /// and host portion of URL will not be used for server authentication. - pub fn override_server_name(mut self, server_name_override: String) -> Self { - self.0.inner.server_name_override = Some(server_name_override); + pub fn override_server_name(mut self, override_server_name: String) -> Self { + self.0.inner.override_server_name = Some(override_server_name); self } @@ -250,10 +250,10 @@ pub struct WantsProtocols3 { impl ConnectorBuilder { /// Override expected server name /// - /// If called, server certificates will be validated against `server_name_override`, + /// If called, server certificates will be validated against `override_server_name`, /// and host portion of URL will not be used for server authentication. - pub fn override_server_name(mut self, server_name_override: String) -> Self { - self.0.inner.server_name_override = Some(server_name_override); + pub fn override_server_name(mut self, override_server_name: String) -> Self { + self.0.inner.override_server_name = Some(override_server_name); self } From 8a053d02ea51ce04f371cedcf8cd959d38f7c62c Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Mon, 17 Oct 2022 00:08:23 +0300 Subject: [PATCH 3/7] Retain only one stage --- src/connector/builder.rs | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/connector/builder.rs b/src/connector/builder.rs index dc278f3..fc7f30f 100644 --- a/src/connector/builder.rs +++ b/src/connector/builder.rs @@ -207,16 +207,7 @@ impl ConnectorBuilder { enable_http1: true, }) } - - /// Override expected server name - /// - /// If called, server certificates will be validated against `override_server_name`, - /// and host portion of URL will not be used for server authentication. - pub fn override_server_name(mut self, override_server_name: String) -> Self { - self.0.inner.override_server_name = Some(override_server_name); - self - } - + /// This builds an [`HttpsConnector`] built on hyper's default [`HttpConnector`] #[cfg(feature = "tokio-runtime")] pub fn build(self) -> HttpsConnector { @@ -248,15 +239,6 @@ pub struct WantsProtocols3 { #[cfg(feature = "http2")] impl ConnectorBuilder { - /// Override expected server name - /// - /// If called, server certificates will be validated against `override_server_name`, - /// and host portion of URL will not be used for server authentication. - pub fn override_server_name(mut self, override_server_name: String) -> Self { - self.0.inner.override_server_name = Some(override_server_name); - self - } - /// This builds an [`HttpsConnector`] built on hyper's default [`HttpConnector`] #[cfg(feature = "tokio-runtime")] pub fn build(self) -> HttpsConnector { From ec052459bac45d3d7d510f71f3a5e051e61b39a4 Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Mon, 17 Oct 2022 00:14:03 +0300 Subject: [PATCH 4/7] Add more words to documentation and rename --- src/connector/builder.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/connector/builder.rs b/src/connector/builder.rs index fc7f30f..8133ddb 100644 --- a/src/connector/builder.rs +++ b/src/connector/builder.rs @@ -174,11 +174,16 @@ impl ConnectorBuilder { }) } - /// Override expected server name + /// Override server name for the purposes of TLS connection establishment /// - /// If called, server certificates will be validated against `override_server_name`, - /// and host portion of URL will not be used for server authentication. - pub fn override_server_name(mut self, override_server_name: String) -> Self { + /// By default, for each connection hyper-rustls will extract host portion + /// of the destination URL and verify that server certificate contains + /// this value. + /// + /// If this method is called, hyper-rustls will instead verify that server + /// certificate contains `override_server_name`. Domain name included in + /// the URL will not affect certificate validation. + pub fn with_server_name(mut self, override_server_name: String) -> Self { self.0.override_server_name = Some(override_server_name); self } From b072b62af01525fbe3c8a821b99444adc45a22af Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Mon, 17 Oct 2022 00:15:58 +0300 Subject: [PATCH 5/7] Simplify --- src/connector.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/connector.rs b/src/connector.rs index a982017..ed9f426 100644 --- a/src/connector.rs +++ b/src/connector.rs @@ -93,9 +93,7 @@ where Ok(dnsname) => dnsname, Err(_) => { let err = io::Error::new(io::ErrorKind::Other, "invalid dnsname"); - let err: Box = Box::new(err); - let res = std::future::ready(Err(err)); - return Box::pin(res); + return Box::pin(std::future::ready(Err(Box::new(err) as BoxError))); } }; let connecting_future = self.http.call(dst); From 96c4bd1778743491d3b8c366500ac4fb87229331 Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Mon, 17 Oct 2022 00:21:27 +0300 Subject: [PATCH 6/7] Simplify wording --- src/connector/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/connector/builder.rs b/src/connector/builder.rs index 8133ddb..e5c4f7e 100644 --- a/src/connector/builder.rs +++ b/src/connector/builder.rs @@ -174,7 +174,7 @@ impl ConnectorBuilder { }) } - /// Override server name for the purposes of TLS connection establishment + /// Override server name for the TLS stack /// /// By default, for each connection hyper-rustls will extract host portion /// of the destination URL and verify that server certificate contains From e433021163cb018cad634c0cf9c71a58af02b29d Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Wed, 19 Oct 2022 22:53:26 +0300 Subject: [PATCH 7/7] Simplify --- src/connector.rs | 2 +- src/connector/builder.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/connector.rs b/src/connector.rs index ed9f426..076870e 100644 --- a/src/connector.rs +++ b/src/connector.rs @@ -93,7 +93,7 @@ where Ok(dnsname) => dnsname, Err(_) => { let err = io::Error::new(io::ErrorKind::Other, "invalid dnsname"); - return Box::pin(std::future::ready(Err(Box::new(err) as BoxError))); + return Box::pin(async move { Err(Box::new(err).into()) }); } }; let connecting_future = self.http.call(dst); diff --git a/src/connector/builder.rs b/src/connector/builder.rs index e5c4f7e..dd4f48c 100644 --- a/src/connector/builder.rs +++ b/src/connector/builder.rs @@ -179,7 +179,7 @@ impl ConnectorBuilder { /// By default, for each connection hyper-rustls will extract host portion /// of the destination URL and verify that server certificate contains /// this value. - /// + /// /// If this method is called, hyper-rustls will instead verify that server /// certificate contains `override_server_name`. Domain name included in /// the URL will not affect certificate validation. @@ -212,7 +212,7 @@ impl ConnectorBuilder { enable_http1: true, }) } - + /// This builds an [`HttpsConnector`] built on hyper's default [`HttpConnector`] #[cfg(feature = "tokio-runtime")] pub fn build(self) -> HttpsConnector {