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::ClientConfig;
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#[cfg(windows)]
19mod windows;
20
21/// Fixures and data to support testing the server
22/// certificate verifier.
23#[cfg(any(test, feature = "ffi-testing"))]
24mod tests;
25
26// Re-export any exported functions that are required for
27// tests to run in a platform-native environment.
28#[cfg(feature = "ffi-testing")]
29#[cfg_attr(feature = "ffi-testing", allow(unused_imports))]
30pub use tests::ffi::*;
31
32/// Creates and returns a `rustls` configuration that verifies TLS
33/// certificates in the best way for the underlying OS platform, using
34/// safe defaults for the `rustls` configuration.
35///
36/// # Example
37///
38/// This example shows how to use the custom verifier with the `reqwest` crate:
39/// ```ignore
40/// # use reqwest::ClientBuilder;
41/// #[tokio::main]
42/// async fn main() {
43/// let client = ClientBuilder::new()
44/// .use_preconfigured_tls(rustls_platform_verifier::tls_config())
45/// .build()
46/// .expect("nothing should fail");
47///
48/// let _response = client.get("https://example.com").send().await;
49/// }
50/// ```
51///
52/// **Important:** You must ensure that your `reqwest` version is using the same Rustls
53/// version as this crate or it will panic when downcasting the `&dyn Any` verifier.
54///
55/// If you require more control over the rustls `ClientConfig`, you can
56/// instantiate a [Verifier] with [Verifier::default] and then use it
57/// with [`DangerousClientConfigBuilder::with_custom_certificate_verifier`][rustls::client::danger::DangerousClientConfigBuilder::with_custom_certificate_verifier].
58///
59/// Refer to the crate level documentation to see what platforms
60/// are currently supported.
61pub fn tls_config() -> ClientConfig {
62 ClientConfig::builder()
63 .dangerous()
64 .with_custom_certificate_verifier(Arc::new(Verifier::new()))
65 .with_no_client_auth()
66}
67
68/// Attempts to construct a `rustls` configuration that verifies TLS certificates in the best way
69/// for the underlying OS platform, using the provided
70/// [`CryptoProvider`][rustls::crypto::CryptoProvider].
71///
72/// See [`tls_config`] for further documentation.
73///
74/// # Errors
75///
76/// Propagates any error returned by [`rustls::ConfigBuilder::with_safe_default_protocol_versions`].
77pub fn tls_config_with_provider(
78 provider: Arc<rustls::crypto::CryptoProvider>,
79) -> Result<ClientConfig, rustls::Error> {
80 Ok(ClientConfig::builder_with_provider(provider.clone())
81 .with_safe_default_protocol_versions()?
82 .dangerous()
83 .with_custom_certificate_verifier(Arc::new(Verifier::new().with_provider(provider)))
84 .with_no_client_auth())
85}
86
87/// Exposed for debugging certificate issues with standalone tools.
88///
89/// This is not intended for production use, you should use [tls_config] instead.
90#[cfg(feature = "dbg")]
91pub fn verifier_for_dbg(root: &[u8]) -> Arc<dyn rustls::client::danger::ServerCertVerifier> {
92 Arc::new(Verifier::new_with_fake_root(root))
93}