From 77154daea8663b9fd5263e70119ad145a050895e Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Wed, 15 Nov 2023 14:47:35 -0500 Subject: [PATCH] Remove undocumented panic in with_native_roots --- examples/client.rs | 2 +- src/config.rs | 21 +++++++++++++++++---- src/connector/builder.rs | 8 ++++---- src/lib.rs | 2 ++ 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/examples/client.rs b/examples/client.rs index 4659b6d..9f9da94 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -60,7 +60,7 @@ async fn run_client() -> io::Result<()> { // Default TLS client config with native roots None => rustls::ClientConfig::builder() .with_safe_defaults() - .with_native_roots() + .with_native_roots()? .with_no_client_auth(), }; // Prepare the HTTPS connector diff --git a/src/config.rs b/src/config.rs index 256856c..1c74c45 100644 --- a/src/config.rs +++ b/src/config.rs @@ -8,9 +8,14 @@ use rustls::{ClientConfig, ConfigBuilder, WantsVerifier}; pub trait ConfigBuilderExt { /// This configures the platform's trusted certs, as implemented by /// rustls-native-certs + /// + /// This will return an error if no valid certs were found. In that case, + /// it's recommended to use `with_webpki_roots`. #[cfg(feature = "rustls-native-certs")] #[cfg_attr(docsrs, doc(cfg(feature = "rustls-native-certs")))] - fn with_native_roots(self) -> ConfigBuilder; + fn with_native_roots( + self, + ) -> std::io::Result>; /// This configures the webpki roots, which are Mozilla's set of /// trusted roots as packaged by webpki-roots. @@ -23,7 +28,9 @@ impl ConfigBuilderExt for ConfigBuilder { #[cfg(feature = "rustls-native-certs")] #[cfg_attr(docsrs, doc(cfg(feature = "rustls-native-certs")))] #[cfg_attr(not(feature = "logging"), allow(unused_variables))] - fn with_native_roots(self) -> ConfigBuilder { + fn with_native_roots( + self, + ) -> std::io::Result> { let mut roots = rustls::RootCertStore::empty(); let mut valid_count = 0; let mut invalid_count = 0; @@ -45,9 +52,15 @@ impl ConfigBuilderExt for ConfigBuilder { valid_count, invalid_count ); - assert!(!roots.is_empty(), "no CA certificates found"); + if roots.is_empty() { + crate::log::debug!("no valid native root CA certificates found"); + Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + format!("no valid native root CA certificates found ({invalid_count} invalid)"), + ))? + } - self.with_root_certificates(roots) + Ok(self.with_root_certificates(roots)) } #[cfg(feature = "webpki-roots")] diff --git a/src/connector/builder.rs b/src/connector/builder.rs index a505e44..e0f06d0 100644 --- a/src/connector/builder.rs +++ b/src/connector/builder.rs @@ -59,13 +59,13 @@ impl ConnectorBuilder { /// [with_safe_defaults]: rustls::ConfigBuilder::with_safe_defaults #[cfg(feature = "rustls-native-certs")] #[cfg_attr(docsrs, doc(cfg(feature = "rustls-native-certs")))] - pub fn with_native_roots(self) -> ConnectorBuilder { - self.with_tls_config( + pub fn with_native_roots(self) -> std::io::Result> { + Ok(self.with_tls_config( ClientConfig::builder() .with_safe_defaults() - .with_native_roots() + .with_native_roots()? .with_no_client_auth(), - ) + )) } /// Shorthand for using rustls' [safe defaults][with_safe_defaults] diff --git a/src/lib.rs b/src/lib.rs index 308f71e..d2b8ab4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ //! let url = ("https://hyper.rs").parse().unwrap(); //! let https = hyper_rustls::HttpsConnectorBuilder::new() //! .with_native_roots() +//! .expect("no native root CA certificates found") //! .https_only() //! .enable_http1() //! .build(); @@ -59,6 +60,7 @@ //! let key = rustls::PrivateKey(keys[0].clone()); //! let https = hyper_rustls::HttpsConnectorBuilder::new() //! .with_native_roots() +//! .expect("no native root CA certificates found") //! .https_only() //! .enable_http1() //! .build();