diff --git a/src/async_impl/client.rs b/src/async_impl/client.rs index b6adc64..a2ea20b 100644 --- a/src/async_impl/client.rs +++ b/src/async_impl/client.rs @@ -94,6 +94,8 @@ struct Config { #[cfg(feature = "__tls")] root_certs: Vec, #[cfg(feature = "__tls")] + tls_built_in_root_certs: bool, + #[cfg(feature = "__tls")] tls: TlsBackend, http2_only: bool, http1_title_case_headers: bool, @@ -146,6 +148,8 @@ impl ClientBuilder { #[cfg(feature = "__tls")] root_certs: Vec::new(), #[cfg(feature = "__tls")] + tls_built_in_root_certs: true, + #[cfg(feature = "__tls")] identity: None, #[cfg(feature = "__tls")] tls: TlsBackend::default(), @@ -209,6 +213,8 @@ impl ClientBuilder { tls.danger_accept_invalid_certs(!config.certs_verification); + tls.disable_built_in_roots(!config.tls_built_in_root_certs); + for cert in config.root_certs { cert.add_to_native_tls(&mut tls); } @@ -261,10 +267,12 @@ impl ClientBuilder { tls.set_protocols(&["h2".into(), "http/1.1".into()]); } #[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); + } #[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); } @@ -719,6 +727,23 @@ impl ClientBuilder { self } + /// Controls the use of built-in/preloaded certificates during certificate validation. + /// + /// Defaults to `true` -- built-in system certs will be used. + /// + /// # Optional + /// + /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)` + /// feature to be enabled. + #[cfg(feature = "__tls")] + 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; + self + } + /// Sets the identity to be used for client certificate authentication. /// /// # Optional diff --git a/src/blocking/client.rs b/src/blocking/client.rs index de4772d..ea0766e 100644 --- a/src/blocking/client.rs +++ b/src/blocking/client.rs @@ -433,6 +433,22 @@ impl ClientBuilder { self.with_inner(move |inner| inner.add_root_certificate(cert)) } + /// Controls the use of built-in system certificates during certificate validation. + /// + /// Defaults to `true` -- built-in system certs will be used. + /// + /// # Optional + /// + /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)` + /// feature to be enabled. + #[cfg(feature = "__tls")] + pub fn tls_built_in_root_certs( + self, + tls_built_in_root_certs: bool, + ) -> ClientBuilder { + self.with_inner(move |inner| inner.tls_built_in_root_certs(tls_built_in_root_certs)) + } + /// Sets the identity to be used for client certificate authentication. #[cfg(feature = "__tls")] pub fn identity(self, identity: Identity) -> ClientBuilder { diff --git a/tests/badssl.rs b/tests/badssl.rs index 8eec030..9b001d0 100644 --- a/tests/badssl.rs +++ b/tests/badssl.rs @@ -59,6 +59,21 @@ async fn test_badssl_self_signed() { assert!(text.contains("self-signed.badssl.com")); } +#[cfg(feature = "__tls")] +#[tokio::test] +async fn test_badssl_no_built_in_roots() { + let result = reqwest::Client::builder() + .tls_built_in_root_certs(false) + .no_proxy() + .build() + .unwrap() + .get("https://mozilla-modern.badssl.com/") + .send() + .await; + + assert!(result.is_err()); +} + #[cfg(feature = "native-tls")] #[tokio::test] async fn test_badssl_wrong_host() {