diff --git a/Cargo.toml b/Cargo.toml index 6986222..cf10f44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hyper-rustls" -version = "0.27.6" +version = "0.27.7" edition = "2021" rust-version = "1.71" license = "Apache-2.0 OR ISC OR MIT" @@ -29,7 +29,7 @@ hyper-util = { version = "0.1", default-features = false, features = ["client-le log = { version = "0.4.4", optional = true } pki-types = { package = "rustls-pki-types", version = "1" } rustls-native-certs = { version = "0.8", optional = true } -rustls-platform-verifier = { version = "0.5", optional = true } +rustls-platform-verifier = { version = "0.6", optional = true } rustls = { version = "0.23", default-features = false } tokio = "1.0" tokio-rustls = { version = "0.26", default-features = false } diff --git a/src/config.rs b/src/config.rs index 2179d5b..3838261 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,7 +1,5 @@ #[cfg(feature = "rustls-native-certs")] use std::io; -#[cfg(feature = "rustls-platform-verifier")] -use std::sync::Arc; #[cfg(any( feature = "rustls-platform-verifier", @@ -12,20 +10,38 @@ use rustls::client::WantsClientCert; use rustls::{ClientConfig, ConfigBuilder, WantsVerifier}; #[cfg(feature = "rustls-native-certs")] use rustls_native_certs::CertificateResult; +#[cfg(feature = "rustls-platform-verifier")] +use rustls_platform_verifier::BuilderVerifierExt; /// Methods for configuring roots /// /// This adds methods (gated by crate features) for easily configuring /// TLS server roots a rustls ClientConfig will trust. -pub trait ConfigBuilderExt { +pub trait ConfigBuilderExt: sealed::Sealed { /// Use the platform's native verifier to verify server certificates. /// /// See the documentation for [rustls-platform-verifier] for more details. /// + /// # Panics + /// + /// Since 0.27.7, this method will panic if the platform verifier cannot be initialized. + /// Use `try_with_platform_verifier()` instead to handle errors gracefully. + /// /// [rustls-platform-verifier]: https://docs.rs/rustls-platform-verifier + #[deprecated(since = "0.27.7", note = "use `try_with_platform_verifier` instead")] #[cfg(feature = "rustls-platform-verifier")] fn with_platform_verifier(self) -> ConfigBuilder; + /// Use the platform's native verifier to verify server certificates. + /// + /// See the documentation for [rustls-platform-verifier] for more details. + /// + /// [rustls-platform-verifier]: https://docs.rs/rustls-platform-verifier + #[cfg(feature = "rustls-platform-verifier")] + fn try_with_platform_verifier( + self, + ) -> Result, rustls::Error>; + /// This configures the platform's trusted certs, as implemented by /// rustls-native-certs /// @@ -43,11 +59,15 @@ pub trait ConfigBuilderExt { impl ConfigBuilderExt for ConfigBuilder { #[cfg(feature = "rustls-platform-verifier")] fn with_platform_verifier(self) -> ConfigBuilder { - let provider = self.crypto_provider().clone(); - self.dangerous() - .with_custom_certificate_verifier(Arc::new( - rustls_platform_verifier::Verifier::new().with_provider(provider), - )) + self.try_with_platform_verifier() + .expect("failure to initialize platform verifier") + } + + #[cfg(feature = "rustls-platform-verifier")] + fn try_with_platform_verifier( + self, + ) -> Result, rustls::Error> { + BuilderVerifierExt::with_platform_verifier(self) } #[cfg(feature = "rustls-native-certs")] @@ -106,3 +126,11 @@ impl ConfigBuilderExt for ConfigBuilder { self.with_root_certificates(roots) } } + +mod sealed { + use super::*; + + pub trait Sealed {} + + impl Sealed for ConfigBuilder {} +} diff --git a/src/connector.rs b/src/connector.rs index 0ca5c5e..f8abe45 100644 --- a/src/connector.rs +++ b/src/connector.rs @@ -258,7 +258,7 @@ mod tests { let config_builder = rustls::ClientConfig::builder(); cfg_if::cfg_if! { if #[cfg(feature = "rustls-platform-verifier")] { - let config_builder = config_builder.with_platform_verifier(); + let config_builder = config_builder.try_with_platform_verifier()?; } else if #[cfg(feature = "rustls-native-certs")] { let config_builder = config_builder.with_native_roots().unwrap(); } else if #[cfg(feature = "webpki-roots")] { diff --git a/src/connector/builder.rs b/src/connector/builder.rs index 2e47df8..417d130 100644 --- a/src/connector/builder.rs +++ b/src/connector/builder.rs @@ -74,11 +74,26 @@ impl ConnectorBuilder { feature = "rustls-platform-verifier" ))] pub fn with_platform_verifier(self) -> ConnectorBuilder { - self.with_tls_config( + self.try_with_platform_verifier() + .expect("failure to initialize platform verifier") + } + + /// Shorthand for using rustls' default crypto provider and other defaults, and + /// the platform verifier. + /// + /// See [`ConfigBuilderExt::with_platform_verifier()`]. + #[cfg(all( + any(feature = "ring", feature = "aws-lc-rs"), + feature = "rustls-platform-verifier" + ))] + pub fn try_with_platform_verifier( + self, + ) -> Result, rustls::Error> { + Ok(self.with_tls_config( ClientConfig::builder() - .with_platform_verifier() + .try_with_platform_verifier()? .with_no_client_auth(), - ) + )) } /// Shorthand for using a custom [`CryptoProvider`] and the platform verifier. @@ -92,8 +107,8 @@ impl ConnectorBuilder { Ok(self.with_tls_config( ClientConfig::builder_with_provider(provider.into()) .with_safe_default_protocol_versions() + .and_then(|builder| builder.try_with_platform_verifier()) .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))? - .with_platform_verifier() .with_no_client_auth(), )) }