rustls_platform_verifier/lib.rs
1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![doc = include_str!("../README.md")]
3#![warn(missing_docs)]
4
5use rustls::{client::WantsClientCert, ClientConfig, ConfigBuilder, WantsVerifier};
6use std::sync::Arc;
7
8mod verification;
9pub use verification::Verifier;
10
11// Build the Android module when generating docs so that
12// the Android-specific functions are included regardless of
13// the host.
14#[cfg(any(all(doc, docsrs), target_os = "android"))]
15#[cfg_attr(docsrs, doc(cfg(target_os = "android")))]
16pub mod android;
17
18/// Fixures and data to support testing the server
19/// certificate verifier.
20#[cfg(any(test, feature = "ffi-testing"))]
21mod tests;
22
23// Re-export any exported functions that are required for
24// tests to run in a platform-native environment.
25#[cfg(feature = "ffi-testing")]
26#[cfg_attr(feature = "ffi-testing", allow(unused_imports))]
27pub use tests::ffi::*;
28
29/// Creates and returns a `rustls` configuration that verifies TLS
30/// certificates in the best way for the underlying OS platform, using
31/// safe defaults for the `rustls` configuration.
32///
33/// # Example
34///
35/// This example shows how to use the custom verifier with the `reqwest` crate:
36/// ```ignore
37/// # use reqwest::ClientBuilder;
38/// #[tokio::main]
39/// use rustls_platform_verifier::ConfigVerifierExt;
40///
41/// async fn main() {
42/// let client = ClientBuilder::new()
43/// .use_preconfigured_tls(ClientConfig::with_platform_verifier())
44/// .build()
45/// .expect("nothing should fail");
46///
47/// let _response = client.get("http://example.com").send().await;
48/// }
49/// ```
50///
51/// **Important:** You must ensure that your `reqwest` version is using the same Rustls
52/// version as this crate or it will panic when downcasting the `&dyn Any` verifier.
53///
54/// If you require more control over the rustls [`ClientConfig`], you can import the
55/// [`BuilderVerifierExt`] trait and call `.with_platform_verifier()` on the [`ConfigBuilder`].
56///
57/// Refer to the crate level documentation to see what platforms
58/// are currently supported.
59#[deprecated(since = "0.4.0", note = "use the `ConfigVerifierExt` instead")]
60pub fn tls_config() -> ClientConfig {
61 ClientConfig::with_platform_verifier()
62}
63
64/// Attempts to construct a `rustls` configuration that verifies TLS certificates in the best way
65/// for the underlying OS platform, using the provided
66/// [`CryptoProvider`][rustls::crypto::CryptoProvider].
67///
68/// See [`tls_config`] for further documentation.
69///
70/// # Errors
71///
72/// Propagates any error returned by [`rustls::ConfigBuilder::with_safe_default_protocol_versions`].
73#[deprecated(since = "0.4.0", note = "use the `BuilderVerifierExt` instead")]
74pub fn tls_config_with_provider(
75 provider: Arc<rustls::crypto::CryptoProvider>,
76) -> Result<ClientConfig, rustls::Error> {
77 Ok(ClientConfig::builder_with_provider(provider)
78 .with_safe_default_protocol_versions()?
79 .with_platform_verifier()
80 .with_no_client_auth())
81}
82
83/// Exposed for debugging certificate issues with standalone tools.
84///
85/// This is not intended for production use, you should use [tls_config] instead.
86#[cfg(feature = "dbg")]
87pub fn verifier_for_dbg(root: &[u8]) -> Arc<dyn rustls::client::danger::ServerCertVerifier> {
88 Arc::new(Verifier::new_with_fake_root(root))
89}
90
91/// Extension trait to help configure [`ClientConfig`]s with the platform verifier.
92pub trait BuilderVerifierExt {
93 /// Configures the `ClientConfig` with the platform verifier.
94 ///
95 /// ```rust
96 /// use rustls::ClientConfig;
97 /// use rustls_platform_verifier::BuilderVerifierExt;
98 /// let config = ClientConfig::builder()
99 /// .with_platform_verifier()
100 /// .with_no_client_auth();
101 /// ```
102 fn with_platform_verifier(self) -> ConfigBuilder<ClientConfig, WantsClientCert>;
103}
104
105impl BuilderVerifierExt for ConfigBuilder<ClientConfig, WantsVerifier> {
106 fn with_platform_verifier(self) -> ConfigBuilder<ClientConfig, WantsClientCert> {
107 let provider = self.crypto_provider().clone();
108 self.dangerous()
109 .with_custom_certificate_verifier(Arc::new(Verifier::new().with_provider(provider)))
110 }
111}
112
113/// Extension trait to help build a [`ClientConfig`] with the platform verifier.
114pub trait ConfigVerifierExt {
115 /// Build a [`ClientConfig`] with the platform verifier and the default `CryptoProvider`.
116 ///
117 /// ```rust
118 /// use rustls::ClientConfig;
119 /// use rustls_platform_verifier::ConfigVerifierExt;
120 /// let config = ClientConfig::with_platform_verifier();
121 /// ```
122 fn with_platform_verifier() -> ClientConfig;
123}
124
125impl ConfigVerifierExt for ClientConfig {
126 fn with_platform_verifier() -> ClientConfig {
127 ClientConfig::builder()
128 .with_platform_verifier()
129 .with_no_client_auth()
130 }
131}