From ad5e037b4bfcdbb43713ef08aa0bf0ee02e94fb1 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Wed, 14 Feb 2024 14:07:58 +0100 Subject: [PATCH] Add support for rustls-platform-verifier --- .github/workflows/ci.yml | 2 ++ Cargo.toml | 2 ++ src/async_impl/client.rs | 16 ++++++++++++++-- src/async_impl/request.rs | 1 + src/lib.rs | 2 ++ tests/badssl.rs | 16 ++++++++++++---- tests/client.rs | 2 +- tests/proxy.rs | 2 +- tests/redirect.rs | 2 +- tests/timeouts.rs | 2 +- tests/upgrade.rs | 2 +- 11 files changed, 38 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 74fbae5ee..904fe925b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -127,6 +127,8 @@ jobs: features: "--no-default-features" - name: "feat.: rustls-tls" features: "--no-default-features --features rustls-tls" + - name: "feat.: rustls-tls-platform-verifier" + features: "--no-default-features --features rustls-tls-platform-verifier" - name: "feat.: rustls-tls-manual-roots" features: "--no-default-features --features rustls-tls-manual-roots" - name: "feat.: rustls-tls-native-roots" diff --git a/Cargo.toml b/Cargo.toml index 10a0e8815..68cb104a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ native-tls-vendored = ["native-tls", "native-tls-crate?/vendored"] rustls-tls = ["rustls-tls-webpki-roots"] rustls-tls-manual-roots = ["__rustls"] +rustls-tls-platform-verifier = ["dep:rustls-platform-verifier", "__rustls"] rustls-tls-webpki-roots = ["dep:webpki-roots", "__rustls"] rustls-tls-native-roots = ["dep:rustls-native-certs", "__rustls"] @@ -140,6 +141,7 @@ rustls-pki-types = { version = "1.1.0", features = ["alloc"] ,optional = true } tokio-rustls = { version = "0.25", optional = true } webpki-roots = { version = "0.26.0", optional = true } rustls-native-certs = { version = "0.7", optional = true } +rustls-platform-verifier = { version = "0.2", optional = true } ## cookies cookie_crate = { version = "0.18.0", package = "cookie", optional = true } diff --git a/src/async_impl/client.rs b/src/async_impl/client.rs index 22519f535..91fc86d54 100644 --- a/src/async_impl/client.rs +++ b/src/async_impl/client.rs @@ -565,10 +565,21 @@ impl ClientBuilder { return Err(crate::error::builder("empty supported tls versions")); } + #[cfg(feature = "rustls-tls-platform-verifier")] + let verifier = Arc::new(rustls_platform_verifier::Verifier::new()); + #[cfg(not(feature = "rustls-tls-platform-verifier"))] + let verifier = + rustls::client::WebPkiServerVerifier::builder(Arc::new(root_cert_store)) + .build() + .map_err(|_| { + crate::error::builder("no trust anchors have been provided") + })?; + // Build TLS config let config_builder = rustls::ClientConfig::builder_with_protocol_versions(&versions) - .with_root_certificates(root_cert_store); + .dangerous() + .with_custom_certificate_verifier(verifier); // Finalize TLS config let mut tls = if let Some(id) = config.identity { @@ -1304,7 +1315,7 @@ impl ClientBuilder { /// /// # Example /// - /// ``` + /// ```no_run /// use std::net::IpAddr; /// let local_addr = IpAddr::from([12, 4, 1, 8]); /// let client = reqwest::Client::builder() @@ -2745,6 +2756,7 @@ fn add_cookie_header(headers: &mut HeaderMap, cookie_store: &dyn cookie::CookieS } } +#[cfg(not(feature = "rustls-tls-manual-roots"))] // Building a client fails without roots #[cfg(test)] mod tests { #[tokio::test] diff --git a/src/async_impl/request.rs b/src/async_impl/request.rs index 665710430..fa34fc2dd 100644 --- a/src/async_impl/request.rs +++ b/src/async_impl/request.rs @@ -647,6 +647,7 @@ impl TryFrom for HttpRequest { } } +#[cfg(not(feature = "rustls-tls-manual-roots"))] // Building a client fails without roots #[cfg(test)] mod tests { use super::{Client, HttpRequest, Request, RequestBuilder, Version}; diff --git a/src/lib.rs b/src/lib.rs index d62cb8210..25536ee43 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -192,6 +192,8 @@ //! while using root certificates from the `webpki-roots` crate. //! - **rustls-tls-native-roots**: Enables TLS functionality provided by `rustls`, //! while using root certificates from the `rustls-native-certs` crate. +//! - **rustls-tls-platform-verifier**: Enables TLS functionality provided by `rustls`, +//! while using the platform's native certificate verifier. //! - **blocking**: Provides the [blocking][] client API. //! - **charset** *(enabled by default)*: Improved support for decoding text. //! - **cookies**: Provides cookie session support. diff --git a/tests/badssl.rs b/tests/badssl.rs index 9b001d070..5854b380c 100644 --- a/tests/badssl.rs +++ b/tests/badssl.rs @@ -40,7 +40,7 @@ async fn test_rustls_badssl_modern() { assert!(text.contains("mozilla-modern.badssl.com")); } -#[cfg(feature = "__tls")] +#[cfg(all(feature = "__tls", not(feature = "rustls-tls-manual-roots")))] #[tokio::test] async fn test_badssl_self_signed() { let text = reqwest::Client::builder() @@ -59,14 +59,22 @@ async fn test_badssl_self_signed() { assert!(text.contains("self-signed.badssl.com")); } -#[cfg(feature = "__tls")] +// For the platform verifier, there is no concept of available roots +#[cfg(all(feature = "__tls", not(feature = "rustls-tls-platform-verifier")))] #[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() + .build(); + + // Some configurations will fail to build a client without roots + let client = match result { + Ok(client) => client, + Err(_) => return, + }; + + let result = client .get("https://mozilla-modern.badssl.com/") .send() .await; diff --git a/tests/client.rs b/tests/client.rs index 1639d68a0..5eda747c9 100644 --- a/tests/client.rs +++ b/tests/client.rs @@ -1,4 +1,4 @@ -#![cfg(not(target_arch = "wasm32"))] +#![cfg(not(any(target_arch = "wasm32", feature = "rustls-tls-manual-roots")))] mod support; use support::server; diff --git a/tests/proxy.rs b/tests/proxy.rs index 231de25d8..40baf112a 100644 --- a/tests/proxy.rs +++ b/tests/proxy.rs @@ -1,4 +1,4 @@ -#![cfg(not(target_arch = "wasm32"))] +#![cfg(not(any(target_arch = "wasm32", feature = "rustls-tls-manual-roots")))] mod support; use support::server; diff --git a/tests/redirect.rs b/tests/redirect.rs index c98c799ef..224531182 100644 --- a/tests/redirect.rs +++ b/tests/redirect.rs @@ -1,4 +1,4 @@ -#![cfg(not(target_arch = "wasm32"))] +#![cfg(not(any(target_arch = "wasm32", feature = "rustls-tls-manual-roots")))] mod support; use http_body_util::BodyExt; use reqwest::Body; diff --git a/tests/timeouts.rs b/tests/timeouts.rs index c18fecdbe..417141afa 100644 --- a/tests/timeouts.rs +++ b/tests/timeouts.rs @@ -1,4 +1,4 @@ -#![cfg(not(target_arch = "wasm32"))] +#![cfg(not(any(target_arch = "wasm32", feature = "rustls-tls-manual-roots")))] mod support; use support::server; diff --git a/tests/upgrade.rs b/tests/upgrade.rs index 5ea72acc2..118ef6648 100644 --- a/tests/upgrade.rs +++ b/tests/upgrade.rs @@ -1,4 +1,4 @@ -#![cfg(not(target_arch = "wasm32"))] +#![cfg(not(any(target_arch = "wasm32", feature = "rustls-tls-manual-roots")))] mod support; use support::server; use tokio::io::{AsyncReadExt, AsyncWriteExt};