From ab1b3268d00a0ded29efe4a63c57046fa04b8e70 Mon Sep 17 00:00:00 2001 From: Satya Rohith Date: Tue, 26 Oct 2021 14:52:31 +0530 Subject: [PATCH 1/8] init --- Cargo.toml | 11 ++++++----- src/connect.rs | 11 +++++------ src/tls.rs | 35 +++++++++++++++++------------------ 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e50bf7a24..683c4bf69 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ features = [ ] [features] -default = ["default-tls"] +default = ["__rustls"] # Note: this doesn't enable the 'native-tls' feature, which adds specific # functionality for it. @@ -112,11 +112,12 @@ native-tls-crate = { version = "0.2.8", optional = true, package = "native-tls" tokio-native-tls = { version = "0.3.0", optional = true } # rustls-tls -hyper-rustls = { version = "0.22.1", default-features = false, optional = true } -rustls = { version = "0.19", features = ["dangerous_configuration"], optional = true } -tokio-rustls = { version = "0.22", optional = true } +hyper-rustls = { version = "0.22.1", default-features = false, optional = true, git = "https://github.com/g2p/hyper-rustls", rev = "344d4934b5b3ccb43f99cf242f4c84cf3ecd6264"} +rustls = { version = "0.20", features = ["dangerous_configuration"], optional = true } +tokio-rustls = { version = "0.23", optional = true } webpki-roots = { version = "0.21", optional = true } -rustls-native-certs = { version = "0.5", optional = true } +rustls-native-certs = { version = "0.6.0", optional = true } +rustls-pemfile = "0.2.1" ## cookies cookie_crate = { version = "0.15", package = "cookie", optional = true } diff --git a/src/connect.rs b/src/connect.rs index 7662a47ef..c2b553587 100644 --- a/src/connect.rs +++ b/src/connect.rs @@ -325,13 +325,13 @@ impl Connector { #[cfg(feature = "__rustls")] Inner::RustlsTls { tls_proxy, .. } => { if dst.scheme() == Some(&Scheme::HTTPS) { - use tokio_rustls::webpki::DNSNameRef; + use tokio_rustls::webpki::DnsNameRef; use tokio_rustls::TlsConnector as RustlsConnector; let tls = tls_proxy.clone(); let host = dst.host().ok_or("no host in url")?.to_string(); let conn = socks::connect(proxy, dst, dns).await?; - let dnsname = DNSNameRef::try_from_ascii_str(&host) + let dnsname = DnsNameRef::try_from_ascii_str(&host) .map(|dnsname| dnsname.to_owned()) .map_err(|_| "Invalid DNS Name")?; let io = RustlsConnector::from(tls) @@ -479,7 +479,7 @@ impl Connector { tls_proxy, } => { if dst.scheme() == Some(&Scheme::HTTPS) { - use tokio_rustls::webpki::DNSNameRef; + use tokio_rustls::webpki::DnsNameRef; use tokio_rustls::TlsConnector as RustlsConnector; let host = dst.host().ok_or("no host in url")?.to_string(); @@ -489,7 +489,7 @@ impl Connector { let tls = tls.clone(); let conn = http.call(proxy_dst).await?; log::trace!("tunneling HTTPS over proxy"); - let maybe_dnsname = DNSNameRef::try_from_ascii_str(&host) + let maybe_dnsname = DnsNameRef::try_from_ascii_str(&host) .map(|dnsname| dnsname.to_owned()) .map_err(|_| "Invalid DNS Name"); let tunneled = tunnel(conn, host, port, self.user_agent.clone(), auth).await?; @@ -820,7 +820,6 @@ mod native_tls_conn { mod rustls_tls_conn { use hyper::client::connect::{Connected, Connection}; use pin_project_lite::pin_project; - use rustls::Session; use std::{ io::{self, IoSlice}, pin::Pin, @@ -837,7 +836,7 @@ mod rustls_tls_conn { impl Connection for RustlsTlsConn { fn connected(&self) -> Connected { - if self.inner.get_ref().1.get_alpn_protocol() == Some(b"h2") { + if self.inner.get_ref().1.alpn_protocol() == Some(b"h2") { self.inner.get_ref().0.connected().negotiated_h2() } else { self.inner.get_ref().0.connected() diff --git a/src/tls.rs b/src/tls.rs index 4a92dfa01..b7c06ff86 100644 --- a/src/tls.rs +++ b/src/tls.rs @@ -12,13 +12,11 @@ //! `ClientBuilder`. #[cfg(feature = "__rustls")] -use rustls::{ - internal::msgs::handshake::DigitallySignedStruct, HandshakeSignatureValid, RootCertStore, - ServerCertVerified, ServerCertVerifier, TLSError, -}; +use rustls::client::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; +use rustls::{internal::msgs::handshake::DigitallySignedStruct, RootCertStore}; use std::fmt; #[cfg(feature = "__rustls")] -use tokio_rustls::webpki::DNSNameRef; +use tokio_rustls::webpki::DnsNameRef; /// Represents a server X509 certificate. #[derive(Clone)] @@ -112,7 +110,7 @@ impl Certificate { #[cfg(feature = "__rustls")] pub(crate) fn add_to_rustls(self, tls: &mut rustls::ClientConfig) -> crate::Result<()> { - use rustls::internal::pemfile; + use std::io::Cursor; match self.original { @@ -122,7 +120,7 @@ impl Certificate { .map_err(|e| crate::error::builder(TLSError::WebPKIError(e)))?, Cert::Pem(buf) => { let mut pem = Cursor::new(buf); - let certs = pemfile::certs(&mut pem).map_err(|_| { + let certs = rustls_pemfile::certs(&mut pem).map_err(|_| { crate::error::builder(TLSError::General(String::from( "No valid certificate was found", ))) @@ -207,16 +205,15 @@ impl Identity { /// This requires the `rustls-tls(-...)` Cargo feature enabled. #[cfg(feature = "__rustls")] pub fn from_pem(buf: &[u8]) -> crate::Result { - use rustls::internal::pemfile; use std::io::Cursor; let (key, certs) = { let mut pem = Cursor::new(buf); - let certs = pemfile::certs(&mut pem) + let certs = rustls_pemfile::certs(&mut pem) .map_err(|_| TLSError::General(String::from("No valid certificate was found"))) .map_err(crate::error::builder)?; pem.set_position(0); - let mut sk = pemfile::pkcs8_private_keys(&mut pem) + let mut sk = rustls_pemfile::pkcs8_private_keys(&mut pem) .and_then(|pkcs8_keys| { if pkcs8_keys.is_empty() { Err(()) @@ -226,7 +223,7 @@ impl Identity { }) .or_else(|_| { pem.set_position(0); - pemfile::rsa_private_keys(&mut pem) + rustls_pemfile::rsa_private_keys(&mut pem) }) .map_err(|_| TLSError::General(String::from("No valid private key was found"))) .map_err(crate::error::builder)?; @@ -385,12 +382,14 @@ pub(crate) struct NoVerifier; impl ServerCertVerifier for NoVerifier { fn verify_server_cert( &self, - _roots: &RootCertStore, - _presented_certs: &[rustls::Certificate], - _dns_name: DNSNameRef, + _end_entity: &rustls::Certificate, + _intermediates: &[rustls::Certificate], + _server_name: &rustls::ServerName, + _scts: &mut dyn Iterator, _ocsp_response: &[u8], - ) -> Result { - Ok(ServerCertVerified::assertion()) + _now: std::time::SystemTime, + ) -> Result { + Ok(rustls::client::ServerCertVerified::assertion()) } fn verify_tls12_signature( @@ -398,7 +397,7 @@ impl ServerCertVerifier for NoVerifier { _message: &[u8], _cert: &rustls::Certificate, _dss: &DigitallySignedStruct, - ) -> Result { + ) -> Result { Ok(HandshakeSignatureValid::assertion()) } @@ -407,7 +406,7 @@ impl ServerCertVerifier for NoVerifier { _message: &[u8], _cert: &rustls::Certificate, _dss: &DigitallySignedStruct, - ) -> Result { + ) -> Result { Ok(HandshakeSignatureValid::assertion()) } } From c4fdc7209fa73b9aa54691efea6fa78b175ada63 Mon Sep 17 00:00:00 2001 From: Satya Rohith Date: Tue, 26 Oct 2021 16:26:33 +0530 Subject: [PATCH 2/8] fix connect.rs --- src/connect.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/connect.rs b/src/connect.rs index c2b553587..83cbec2e9 100644 --- a/src/connect.rs +++ b/src/connect.rs @@ -13,6 +13,7 @@ use native_tls_crate::{TlsConnector, TlsConnectorBuilder}; use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; use pin_project_lite::pin_project; +use std::convert::TryFrom; use std::io::IoSlice; use std::net::IpAddr; use std::pin::Pin; @@ -479,23 +480,22 @@ impl Connector { tls_proxy, } => { if dst.scheme() == Some(&Scheme::HTTPS) { - use tokio_rustls::webpki::DnsNameRef; use tokio_rustls::TlsConnector as RustlsConnector; - let host = dst.host().ok_or("no host in url")?.to_string(); + let host = dst.host().ok_or("no host in url")?; let port = dst.port().map(|r| r.as_u16()).unwrap_or(443); let http = http.clone(); let mut http = hyper_rustls::HttpsConnector::from((http, tls_proxy.clone())); let tls = tls.clone(); let conn = http.call(proxy_dst).await?; log::trace!("tunneling HTTPS over proxy"); - let maybe_dnsname = DnsNameRef::try_from_ascii_str(&host) - .map(|dnsname| dnsname.to_owned()) + let maybe_server_name = rustls::ServerName::try_from(host) + .map(|serve_name| serve_name.to_owned()) .map_err(|_| "Invalid DNS Name"); - let tunneled = tunnel(conn, host, port, self.user_agent.clone(), auth).await?; - let dnsname = maybe_dnsname?; + let tunneled = tunnel(conn, host.to_string(), port, self.user_agent.clone(), auth).await?; + let serve_name = maybe_server_name?; let io = RustlsConnector::from(tls) - .connect(dnsname.as_ref(), tunneled) + .connect(serve_name, tunneled) .await?; return Ok(Conn { From 1010f9fb4221ca5472b30f87d4075562778d50f6 Mon Sep 17 00:00:00 2001 From: Satya Rohith Date: Fri, 12 Nov 2021 12:14:44 +0530 Subject: [PATCH 3/8] fix everything --- Cargo.toml | 2 +- src/async_impl/client.rs | 108 +++++++++++++++++++++++---------------- src/connect.rs | 2 +- src/tls.rs | 58 +++++++++++---------- tests/client.rs | 6 ++- 5 files changed, 100 insertions(+), 76 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 683c4bf69..7bba89360 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ features = [ ] [features] -default = ["__rustls"] +default = ["__rustls", "rustls-tls-webpki-roots"] # Note: this doesn't enable the 'native-tls' feature, which adds specific # functionality for it. diff --git a/src/async_impl/client.rs b/src/async_impl/client.rs index 1da696160..2356db9dd 100644 --- a/src/async_impl/client.rs +++ b/src/async_impl/client.rs @@ -17,6 +17,7 @@ use hyper::client::ResponseFuture; #[cfg(feature = "native-tls-crate")] use native_tls_crate::TlsConnector; use pin_project_lite::pin_project; +use rustls::OwnedTrustAnchor; #[cfg(feature = "rustls-tls-native-roots")] use rustls::RootCertStore; use std::future::Future; @@ -322,40 +323,81 @@ impl ClientBuilder { TlsBackend::Rustls => { use crate::tls::NoVerifier; - let mut tls = rustls::ClientConfig::new(); - match config.http_version_pref { - HttpVersionPref::Http1 => { - tls.set_protocols(&["http/1.1".into()]); - } - HttpVersionPref::Http2 => { - tls.set_protocols(&["h2".into()]); - } - HttpVersionPref::All => { - tls.set_protocols(&["h2".into(), "http/1.1".into()]); - } + // Set root certificates. + let mut root_store = rustls::RootCertStore::empty(); + for cert in config.root_certs { + cert.add_to_rustls(&mut root_store)?; } #[cfg(feature = "rustls-tls-webpki-roots")] if config.tls_built_in_root_certs { - tls.root_store - .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); + let mut trust_anchors = Vec::with_capacity(webpki_roots::TLS_SERVER_ROOTS.0.len()); + for cert in webpki_roots::TLS_SERVER_ROOTS.0 { + trust_anchors.push( + OwnedTrustAnchor::from_subject_spki_name_constraints( + cert.subject, + cert.spki, + cert.name_constraints + ) + ); + } + root_store.add_server_trust_anchors(trust_anchors.into_iter()); } #[cfg(feature = "rustls-tls-native-roots")] if config.tls_built_in_root_certs { - let roots_slice = NATIVE_ROOTS.as_ref().unwrap().roots.as_slice(); - tls.root_store.roots.extend_from_slice(roots_slice); + for cert in rustls_native_certs::load_native_certs().unwrap() { + root_store.add(&rustls::Certificate(cert.0)) + .map_err(|e| crate::error::builder(e))? + } } + // Set supported TLS versions. + let mut versions = rustls::ALL_VERSIONS.to_vec(); + if let Some(min_tls_version) = config.min_tls_version { + versions + .retain(|&supported_version| match tls::Version::from_rustls(supported_version.version) { + Some(version) => version >= min_tls_version, + // Assume it's so new we don't know about it, allow it + // (as of writing this is unreachable) + None => true, + }); + } + if let Some(max_tls_version) = config.max_tls_version { + versions + .retain(|&supported_version| match tls::Version::from_rustls(supported_version.version) { + Some(version) => version <= max_tls_version, + None => false, + }); + } + + let config_builder = rustls::ClientConfig::builder() + .with_safe_default_cipher_suites() + .with_safe_default_kx_groups() + .with_protocol_versions(&versions) + .unwrap() + .with_root_certificates(root_store); + + let mut tls = if let Some(id) = config.identity { + let (key, certs) = id.get_pem()?; + config_builder.with_single_cert(certs, key).unwrap() + } else { + config_builder.with_no_client_auth() + }; + if !config.certs_verification { tls.dangerous() .set_certificate_verifier(Arc::new(NoVerifier)); } - for cert in config.root_certs { - cert.add_to_rustls(&mut tls)?; - } - - if let Some(id) = config.identity { - id.add_to_rustls(&mut tls)?; + match config.http_version_pref { + HttpVersionPref::Http1 => { + tls.alpn_protocols = vec!["http/1.1".into()]; + } + HttpVersionPref::Http2 => { + tls.alpn_protocols = vec!["h2".into()]; + } + HttpVersionPref::All => { + tls.alpn_protocols = vec!["h2".into(), "http/1.1".into()]; + } } // rustls does not support TLS versions <1.2 and this is unlikely to change. @@ -368,24 +410,6 @@ impl ClientBuilder { // For now we assume the default tls.versions matches the future ALL_VERSIONS and // act based on that. - if let Some(min_tls_version) = config.min_tls_version { - tls.versions - .retain(|&version| match tls::Version::from_rustls(version) { - Some(version) => version >= min_tls_version, - // Assume it's so new we don't know about it, allow it - // (as of writing this is unreachable) - None => true, - }); - } - - if let Some(max_tls_version) = config.max_tls_version { - tls.versions - .retain(|&version| match tls::Version::from_rustls(version) { - Some(version) => version <= max_tls_version, - None => false, - }); - } - Connector::new_rustls_tls( http, tls, @@ -1848,12 +1872,6 @@ fn add_cookie_header(headers: &mut HeaderMap, cookie_store: &dyn cookie::CookieS } } -#[cfg(feature = "rustls-tls-native-roots")] -lazy_static! { - static ref NATIVE_ROOTS: std::io::Result = - rustls_native_certs::load_native_certs().map_err(|e| e.1); -} - #[cfg(test)] mod tests { #[tokio::test] diff --git a/src/connect.rs b/src/connect.rs index 83cbec2e9..b9e6051d3 100644 --- a/src/connect.rs +++ b/src/connect.rs @@ -490,7 +490,7 @@ impl Connector { let conn = http.call(proxy_dst).await?; log::trace!("tunneling HTTPS over proxy"); let maybe_server_name = rustls::ServerName::try_from(host) - .map(|serve_name| serve_name.to_owned()) + .map(|serve_name| serve_name) .map_err(|_| "Invalid DNS Name"); let tunneled = tunnel(conn, host.to_string(), port, self.user_agent.clone(), auth).await?; let serve_name = maybe_server_name?; diff --git a/src/tls.rs b/src/tls.rs index b7c06ff86..8ddf4e673 100644 --- a/src/tls.rs +++ b/src/tls.rs @@ -12,11 +12,9 @@ //! `ClientBuilder`. #[cfg(feature = "__rustls")] -use rustls::client::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; -use rustls::{internal::msgs::handshake::DigitallySignedStruct, RootCertStore}; +use rustls::client::HandshakeSignatureValid; +use rustls::{client::ServerCertVerifier, internal::msgs::handshake::DigitallySignedStruct}; use std::fmt; -#[cfg(feature = "__rustls")] -use tokio_rustls::webpki::DnsNameRef; /// Represents a server X509 certificate. #[derive(Clone)] @@ -109,26 +107,24 @@ impl Certificate { } #[cfg(feature = "__rustls")] - pub(crate) fn add_to_rustls(self, tls: &mut rustls::ClientConfig) -> crate::Result<()> { - + pub(crate) fn add_to_rustls(self, root_store: &mut rustls::RootCertStore) -> crate::Result<()> { use std::io::Cursor; match self.original { - Cert::Der(buf) => tls - .root_store - .add(&::rustls::Certificate(buf)) - .map_err(|e| crate::error::builder(TLSError::WebPKIError(e)))?, - Cert::Pem(buf) => { + Cert::Der(buf) => { + root_store + .add(&rustls::Certificate(buf)) + .map_err(|e| crate::error::builder(e))? + }, + Cert::Pem(buf) => { let mut pem = Cursor::new(buf); let certs = rustls_pemfile::certs(&mut pem).map_err(|_| { - crate::error::builder(TLSError::General(String::from( + crate::error::builder(rustls::Error::General(String::from( "No valid certificate was found", ))) })?; for c in certs { - tls.root_store - .add(&c) - .map_err(|e| crate::error::builder(TLSError::WebPKIError(e)))?; + root_store.add(&rustls::Certificate(c)).map_err(|e| crate::error::builder(e.to_string()))?; } } } @@ -209,14 +205,18 @@ impl Identity { let (key, certs) = { let mut pem = Cursor::new(buf); - let certs = rustls_pemfile::certs(&mut pem) - .map_err(|_| TLSError::General(String::from("No valid certificate was found"))) - .map_err(crate::error::builder)?; + let mut certs = Vec::new(); + for cert in rustls_pemfile::certs(&mut pem) + .map_err(|_| rustls::Error::General(String::from("No valid certificate was found"))) + .map_err(crate::error::builder)? { + certs.push(rustls::Certificate(cert)); + } pem.set_position(0); - let mut sk = rustls_pemfile::pkcs8_private_keys(&mut pem) + let mut sks = Vec::new(); + for sk in rustls_pemfile::pkcs8_private_keys(&mut pem) .and_then(|pkcs8_keys| { if pkcs8_keys.is_empty() { - Err(()) + Err(std::io::Error::new(std::io::ErrorKind::NotFound, "No valid private key was found")) } else { Ok(pkcs8_keys) } @@ -225,12 +225,15 @@ impl Identity { pem.set_position(0); rustls_pemfile::rsa_private_keys(&mut pem) }) - .map_err(|_| TLSError::General(String::from("No valid private key was found"))) - .map_err(crate::error::builder)?; - if let (Some(sk), false) = (sk.pop(), certs.is_empty()) { + .map_err(|_| rustls::Error::General(String::from("No valid private key was found"))) + .map_err(crate::error::builder)? { + sks.push(rustls::PrivateKey(sk)); + } + + if let (Some(sk), false) = (sks.pop(), certs.is_empty()) { (sk, certs) } else { - return Err(crate::error::builder(TLSError::General(String::from( + return Err(crate::error::builder(rustls::Error::General(String::from( "private key or certificate not found", )))); } @@ -241,6 +244,7 @@ impl Identity { }) } + #[cfg(feature = "native-tls")] pub(crate) fn add_to_native_tls( self, @@ -257,12 +261,10 @@ impl Identity { } #[cfg(feature = "__rustls")] - pub(crate) fn add_to_rustls(self, tls: &mut rustls::ClientConfig) -> crate::Result<()> { + pub(crate) fn get_pem(self) -> crate::Result<(rustls::PrivateKey, Vec)> { match self.inner { ClientCert::Pem { key, certs } => { - tls.set_single_client_cert(certs, key) - .map_err(|e| crate::error::builder(e))?; - Ok(()) + Ok((key, certs)) } #[cfg(feature = "native-tls")] ClientCert::Pkcs12(..) => Err(crate::error::builder("incompatible TLS identity type")), diff --git a/tests/client.rs b/tests/client.rs index 6219d03f8..993cf7451 100644 --- a/tests/client.rs +++ b/tests/client.rs @@ -246,7 +246,11 @@ fn use_preconfigured_native_tls_default() { fn use_preconfigured_rustls_default() { extern crate rustls; - let tls = rustls::ClientConfig::new(); + let root_store = rustls::RootCertStore::empty(); + let tls = rustls::ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates(root_store) + .with_no_client_auth(); reqwest::Client::builder() .use_preconfigured_tls(tls) From cb3068bb185ad31b1cf7a3ed808d24df03fd7df5 Mon Sep 17 00:00:00 2001 From: Satya Rohith Date: Fri, 12 Nov 2021 12:16:07 +0530 Subject: [PATCH 4/8] restore default feature --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 7bba89360..b29f1af01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ features = [ ] [features] -default = ["__rustls", "rustls-tls-webpki-roots"] +default = ["default-tls"] # Note: this doesn't enable the 'native-tls' feature, which adds specific # functionality for it. From eaec0241628cce447ed3736ba4f492897754f303 Mon Sep 17 00:00:00 2001 From: Satya Rohith Date: Fri, 12 Nov 2021 12:34:49 +0530 Subject: [PATCH 5/8] fix more --- src/async_impl/client.rs | 4 +--- src/connect.rs | 2 +- src/tls.rs | 5 +++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/async_impl/client.rs b/src/async_impl/client.rs index 2356db9dd..80e9ad442 100644 --- a/src/async_impl/client.rs +++ b/src/async_impl/client.rs @@ -17,9 +17,6 @@ use hyper::client::ResponseFuture; #[cfg(feature = "native-tls-crate")] use native_tls_crate::TlsConnector; use pin_project_lite::pin_project; -use rustls::OwnedTrustAnchor; -#[cfg(feature = "rustls-tls-native-roots")] -use rustls::RootCertStore; use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; @@ -330,6 +327,7 @@ impl ClientBuilder { } #[cfg(feature = "rustls-tls-webpki-roots")] if config.tls_built_in_root_certs { + use rustls::OwnedTrustAnchor; let mut trust_anchors = Vec::with_capacity(webpki_roots::TLS_SERVER_ROOTS.0.len()); for cert in webpki_roots::TLS_SERVER_ROOTS.0 { trust_anchors.push( diff --git a/src/connect.rs b/src/connect.rs index b9e6051d3..bf8495b0c 100644 --- a/src/connect.rs +++ b/src/connect.rs @@ -13,7 +13,6 @@ use native_tls_crate::{TlsConnector, TlsConnectorBuilder}; use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; use pin_project_lite::pin_project; -use std::convert::TryFrom; use std::io::IoSlice; use std::net::IpAddr; use std::pin::Pin; @@ -481,6 +480,7 @@ impl Connector { } => { if dst.scheme() == Some(&Scheme::HTTPS) { use tokio_rustls::TlsConnector as RustlsConnector; + use std::convert::TryFrom; let host = dst.host().ok_or("no host in url")?; let port = dst.port().map(|r| r.as_u16()).unwrap_or(443); diff --git a/src/tls.rs b/src/tls.rs index 8ddf4e673..b68490fcb 100644 --- a/src/tls.rs +++ b/src/tls.rs @@ -12,8 +12,9 @@ //! `ClientBuilder`. #[cfg(feature = "__rustls")] -use rustls::client::HandshakeSignatureValid; -use rustls::{client::ServerCertVerifier, internal::msgs::handshake::DigitallySignedStruct}; +use rustls::{ + client::HandshakeSignatureValid, client::ServerCertVerifier, internal::msgs::handshake::DigitallySignedStruct +}; use std::fmt; /// Represents a server X509 certificate. From 5f3992ecd731d3612d3672516912440ea2c7ae33 Mon Sep 17 00:00:00 2001 From: Satya Rohith Date: Fri, 12 Nov 2021 13:06:21 +0530 Subject: [PATCH 6/8] fmt --- Cargo.toml | 2 +- src/async_impl/client.rs | 12 +----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b29f1af01..04027fc2c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -117,7 +117,7 @@ rustls = { version = "0.20", features = ["dangerous_configuration"], optional = tokio-rustls = { version = "0.23", optional = true } webpki-roots = { version = "0.21", optional = true } rustls-native-certs = { version = "0.6.0", optional = true } -rustls-pemfile = "0.2.1" +rustls-pemfile = { version = "0.2.1", optional = true } ## cookies cookie_crate = { version = "0.15", package = "cookie", optional = true } diff --git a/src/async_impl/client.rs b/src/async_impl/client.rs index 80e9ad442..099c1b03a 100644 --- a/src/async_impl/client.rs +++ b/src/async_impl/client.rs @@ -348,7 +348,7 @@ impl ClientBuilder { } } - // Set supported TLS versions. + // Set TLS versions. let mut versions = rustls::ALL_VERSIONS.to_vec(); if let Some(min_tls_version) = config.min_tls_version { versions @@ -398,16 +398,6 @@ impl ClientBuilder { } } - // rustls does not support TLS versions <1.2 and this is unlikely to change. - // https://github.com/rustls/rustls/issues/33 - - // As of writing, TLS 1.2 and 1.3 are the only implemented versions and are both - // enabled by default. - // rustls 0.20 will add ALL_VERSIONS and DEFAULT_VERSIONS. That will enable a more - // sophisticated approach. - // For now we assume the default tls.versions matches the future ALL_VERSIONS and - // act based on that. - Connector::new_rustls_tls( http, tls, From 63d6e64c8866e43bf4b71b8c71930108026253c2 Mon Sep 17 00:00:00 2001 From: Satya Rohith Date: Sat, 13 Nov 2021 00:56:55 +0530 Subject: [PATCH 7/8] rustfmt --- src/async_impl/client.rs | 46 ++++++++++++++++++++++------------------ src/connect.rs | 5 +++-- src/tls.rs | 39 ++++++++++++++++++---------------- 3 files changed, 49 insertions(+), 41 deletions(-) diff --git a/src/async_impl/client.rs b/src/async_impl/client.rs index 099c1b03a..f4e387a9f 100644 --- a/src/async_impl/client.rs +++ b/src/async_impl/client.rs @@ -328,14 +328,15 @@ impl ClientBuilder { #[cfg(feature = "rustls-tls-webpki-roots")] if config.tls_built_in_root_certs { use rustls::OwnedTrustAnchor; - let mut trust_anchors = Vec::with_capacity(webpki_roots::TLS_SERVER_ROOTS.0.len()); + let mut trust_anchors = + Vec::with_capacity(webpki_roots::TLS_SERVER_ROOTS.0.len()); for cert in webpki_roots::TLS_SERVER_ROOTS.0 { trust_anchors.push( OwnedTrustAnchor::from_subject_spki_name_constraints( cert.subject, cert.spki, - cert.name_constraints - ) + cert.name_constraints, + ), ); } root_store.add_server_trust_anchors(trust_anchors.into_iter()); @@ -343,40 +344,43 @@ impl ClientBuilder { #[cfg(feature = "rustls-tls-native-roots")] if config.tls_built_in_root_certs { for cert in rustls_native_certs::load_native_certs().unwrap() { - root_store.add(&rustls::Certificate(cert.0)) - .map_err(|e| crate::error::builder(e))? + root_store + .add(&rustls::Certificate(cert.0)) + .map_err(|e| crate::error::builder(e))? } } // Set TLS versions. let mut versions = rustls::ALL_VERSIONS.to_vec(); if let Some(min_tls_version) = config.min_tls_version { - versions - .retain(|&supported_version| match tls::Version::from_rustls(supported_version.version) { + versions.retain(|&supported_version| { + match tls::Version::from_rustls(supported_version.version) { Some(version) => version >= min_tls_version, // Assume it's so new we don't know about it, allow it // (as of writing this is unreachable) None => true, - }); + } + }); } if let Some(max_tls_version) = config.max_tls_version { - versions - .retain(|&supported_version| match tls::Version::from_rustls(supported_version.version) { + versions.retain(|&supported_version| { + match tls::Version::from_rustls(supported_version.version) { Some(version) => version <= max_tls_version, None => false, - }); + } + }); } let config_builder = rustls::ClientConfig::builder() - .with_safe_default_cipher_suites() - .with_safe_default_kx_groups() - .with_protocol_versions(&versions) - .unwrap() - .with_root_certificates(root_store); - - let mut tls = if let Some(id) = config.identity { - let (key, certs) = id.get_pem()?; - config_builder.with_single_cert(certs, key).unwrap() + .with_safe_default_cipher_suites() + .with_safe_default_kx_groups() + .with_protocol_versions(&versions) + .unwrap() + .with_root_certificates(root_store); + + let mut tls = if let Some(id) = config.identity { + let (key, certs) = id.get_pem()?; + config_builder.with_single_cert(certs, key).unwrap() } else { config_builder.with_no_client_auth() }; @@ -388,7 +392,7 @@ impl ClientBuilder { match config.http_version_pref { HttpVersionPref::Http1 => { - tls.alpn_protocols = vec!["http/1.1".into()]; + tls.alpn_protocols = vec!["http/1.1".into()]; } HttpVersionPref::Http2 => { tls.alpn_protocols = vec!["h2".into()]; diff --git a/src/connect.rs b/src/connect.rs index bf8495b0c..582c27d35 100644 --- a/src/connect.rs +++ b/src/connect.rs @@ -479,8 +479,8 @@ impl Connector { tls_proxy, } => { if dst.scheme() == Some(&Scheme::HTTPS) { - use tokio_rustls::TlsConnector as RustlsConnector; use std::convert::TryFrom; + use tokio_rustls::TlsConnector as RustlsConnector; let host = dst.host().ok_or("no host in url")?; let port = dst.port().map(|r| r.as_u16()).unwrap_or(443); @@ -492,7 +492,8 @@ impl Connector { let maybe_server_name = rustls::ServerName::try_from(host) .map(|serve_name| serve_name) .map_err(|_| "Invalid DNS Name"); - let tunneled = tunnel(conn, host.to_string(), port, self.user_agent.clone(), auth).await?; + let tunneled = + tunnel(conn, host.to_string(), port, self.user_agent.clone(), auth).await?; let serve_name = maybe_server_name?; let io = RustlsConnector::from(tls) .connect(serve_name, tunneled) diff --git a/src/tls.rs b/src/tls.rs index b68490fcb..f561962a9 100644 --- a/src/tls.rs +++ b/src/tls.rs @@ -13,7 +13,8 @@ #[cfg(feature = "__rustls")] use rustls::{ - client::HandshakeSignatureValid, client::ServerCertVerifier, internal::msgs::handshake::DigitallySignedStruct + client::HandshakeSignatureValid, client::ServerCertVerifier, + internal::msgs::handshake::DigitallySignedStruct, }; use std::fmt; @@ -112,12 +113,10 @@ impl Certificate { use std::io::Cursor; match self.original { - Cert::Der(buf) => { - root_store + Cert::Der(buf) => root_store .add(&rustls::Certificate(buf)) - .map_err(|e| crate::error::builder(e))? - }, - Cert::Pem(buf) => { + .map_err(|e| crate::error::builder(e))?, + Cert::Pem(buf) => { let mut pem = Cursor::new(buf); let certs = rustls_pemfile::certs(&mut pem).map_err(|_| { crate::error::builder(rustls::Error::General(String::from( @@ -125,7 +124,9 @@ impl Certificate { ))) })?; for c in certs { - root_store.add(&rustls::Certificate(c)).map_err(|e| crate::error::builder(e.to_string()))?; + root_store + .add(&rustls::Certificate(c)) + .map_err(|e| crate::error::builder(e.to_string()))?; } } } @@ -209,15 +210,19 @@ impl Identity { let mut certs = Vec::new(); for cert in rustls_pemfile::certs(&mut pem) .map_err(|_| rustls::Error::General(String::from("No valid certificate was found"))) - .map_err(crate::error::builder)? { - certs.push(rustls::Certificate(cert)); - } + .map_err(crate::error::builder)? + { + certs.push(rustls::Certificate(cert)); + } pem.set_position(0); let mut sks = Vec::new(); for sk in rustls_pemfile::pkcs8_private_keys(&mut pem) .and_then(|pkcs8_keys| { if pkcs8_keys.is_empty() { - Err(std::io::Error::new(std::io::ErrorKind::NotFound, "No valid private key was found")) + Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + "No valid private key was found", + )) } else { Ok(pkcs8_keys) } @@ -227,9 +232,10 @@ impl Identity { rustls_pemfile::rsa_private_keys(&mut pem) }) .map_err(|_| rustls::Error::General(String::from("No valid private key was found"))) - .map_err(crate::error::builder)? { - sks.push(rustls::PrivateKey(sk)); - } + .map_err(crate::error::builder)? + { + sks.push(rustls::PrivateKey(sk)); + } if let (Some(sk), false) = (sks.pop(), certs.is_empty()) { (sk, certs) @@ -245,7 +251,6 @@ impl Identity { }) } - #[cfg(feature = "native-tls")] pub(crate) fn add_to_native_tls( self, @@ -264,9 +269,7 @@ impl Identity { #[cfg(feature = "__rustls")] pub(crate) fn get_pem(self) -> crate::Result<(rustls::PrivateKey, Vec)> { match self.inner { - ClientCert::Pem { key, certs } => { - Ok((key, certs)) - } + ClientCert::Pem { key, certs } => Ok((key, certs)), #[cfg(feature = "native-tls")] ClientCert::Pkcs12(..) => Err(crate::error::builder("incompatible TLS identity type")), } From 0d87e16ba43985ab74de17f2c679bfe05fad2391 Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Wed, 24 Nov 2021 09:35:44 -0800 Subject: [PATCH 8/8] Use hyper-rustls release Co-authored-by: Paolo Barbolini --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 04027fc2c..44e2dc259 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -112,7 +112,7 @@ native-tls-crate = { version = "0.2.8", optional = true, package = "native-tls" tokio-native-tls = { version = "0.3.0", optional = true } # rustls-tls -hyper-rustls = { version = "0.22.1", default-features = false, optional = true, git = "https://github.com/g2p/hyper-rustls", rev = "344d4934b5b3ccb43f99cf242f4c84cf3ecd6264"} +hyper-rustls = { version = "0.23", default-features = false, optional = true } rustls = { version = "0.20", features = ["dangerous_configuration"], optional = true } tokio-rustls = { version = "0.23", optional = true } webpki-roots = { version = "0.21", optional = true }