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