From b4c491a6ffa10418d8bfaa49fc38f2175312f90c Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Mon, 1 Apr 2024 17:00:50 -0400 Subject: [PATCH] feat: allow fine-grained root certs for rustls (#2232) --- src/async_impl/client.rs | 52 ++++++++++++++++++++++++++++++++++++++-- src/blocking/client.rs | 18 ++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/async_impl/client.rs b/src/async_impl/client.rs index 079bd259d..0d2361a92 100644 --- a/src/async_impl/client.rs +++ b/src/async_impl/client.rs @@ -113,6 +113,10 @@ struct Config { root_certs: Vec, #[cfg(feature = "__tls")] tls_built_in_root_certs: bool, + #[cfg(feature = "rustls-tls-webpki-roots")] + tls_built_in_certs_webpki: bool, + #[cfg(feature = "rustls-tls-native-roots")] + tls_built_in_certs_native: bool, #[cfg(feature = "__tls")] min_tls_version: Option, #[cfg(feature = "__tls")] @@ -205,6 +209,10 @@ impl ClientBuilder { root_certs: Vec::new(), #[cfg(feature = "__tls")] tls_built_in_root_certs: true, + #[cfg(feature = "rustls-tls-webpki-roots")] + tls_built_in_certs_webpki: true, + #[cfg(feature = "rustls-tls-native-roots")] + tls_built_in_certs_native: true, #[cfg(any(feature = "native-tls", feature = "__rustls"))] identity: None, #[cfg(feature = "__tls")] @@ -499,12 +507,12 @@ impl ClientBuilder { } #[cfg(feature = "rustls-tls-webpki-roots")] - if config.tls_built_in_root_certs { + if config.tls_built_in_certs_webpki { root_cert_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned()); } #[cfg(feature = "rustls-tls-native-roots")] - if config.tls_built_in_root_certs { + if config.tls_built_in_certs_native { let mut valid_count = 0; let mut invalid_count = 0; for cert in rustls_native_certs::load_native_certs() @@ -1333,6 +1341,15 @@ impl ClientBuilder { /// /// Defaults to `true` -- built-in system certs will be used. /// + /// # Bulk Option + /// + /// If this value is `true`, _all_ enabled system certs configured with Cargo + /// features will be loaded. + /// + /// You can set this to `false`, and enable only a specific source with + /// individual methods. Do that will prevent other sources from being loaded + /// even if their feature Cargo feature is enabled. + /// /// # Optional /// /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)` @@ -1348,6 +1365,37 @@ impl ClientBuilder { )] pub fn tls_built_in_root_certs(mut self, tls_built_in_root_certs: bool) -> ClientBuilder { self.config.tls_built_in_root_certs = tls_built_in_root_certs; + + #[cfg(feature = "rustls-tls-webpki-roots")] + { + self.config.tls_built_in_certs_webpki = tls_built_in_root_certs; + } + + #[cfg(feature = "rustls-tls-native-roots")] + { + self.config.tls_built_in_certs_native = tls_built_in_root_certs; + } + + self + } + + /// Sets whether to load webpki root certs with rustls. + /// + /// If the feature is enabled, this value is `true` by default. + #[cfg(feature = "rustls-tls-webpki-roots")] + #[cfg_attr(docsrs, doc(cfg(feature = "rustls-tls-webpki-roots")))] + pub fn tls_built_in_webpki_certs(mut self, enabled: bool) -> ClientBuilder { + self.config.tls_built_in_certs_webpki = enabled; + self + } + + /// Sets whether to load native root certs with rustls. + /// + /// If the feature is enabled, this value is `true` by default. + #[cfg(feature = "rustls-tls-native-roots")] + #[cfg_attr(docsrs, doc(cfg(feature = "rustls-tls-native-roots")))] + pub fn tls_built_in_native_certs(mut self, enabled: bool) -> ClientBuilder { + self.config.tls_built_in_certs_native = enabled; self } diff --git a/src/blocking/client.rs b/src/blocking/client.rs index 5b861cb3e..d0825b42e 100644 --- a/src/blocking/client.rs +++ b/src/blocking/client.rs @@ -615,6 +615,24 @@ impl ClientBuilder { self.with_inner(move |inner| inner.tls_built_in_root_certs(tls_built_in_root_certs)) } + /// Sets whether to load webpki root certs with rustls. + /// + /// If the feature is enabled, this value is `true` by default. + #[cfg(feature = "rustls-tls-webpki-roots")] + #[cfg_attr(docsrs, doc(cfg(feature = "rustls-tls-webpki-roots")))] + pub fn tls_built_in_webpki_certs(mut self, enabled: bool) -> ClientBuilder { + self.with_inner(move |inner| inner.tls_built_in_webpki_certs(enabled)) + } + + /// Sets whether to load native root certs with rustls. + /// + /// If the feature is enabled, this value is `true` by default. + #[cfg(feature = "rustls-tls-native-roots")] + #[cfg_attr(docsrs, doc(cfg(feature = "rustls-tls-native-roots")))] + pub fn tls_built_in_native_certs(mut self, enabled: bool) -> ClientBuilder { + self.with_inner(move |inner| inner.tls_built_in_native_certs(enabled)) + } + /// Sets the identity to be used for client certificate authentication. /// /// # Optional