From c255b58596b5d255d43e90dea22b26ac26c6aff2 Mon Sep 17 00:00:00 2001 From: zlepper Date: Fri, 2 Feb 2024 08:25:18 +0100 Subject: [PATCH 1/3] Add support for using webpki for rustls --- src/client/config.rs | 2 ++ src/client/tls_stream/rustls_tls_stream.rs | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/client/config.rs b/src/client/config.rs index b23ad449..ca72b6e2 100644 --- a/src/client/config.rs +++ b/src/client/config.rs @@ -39,6 +39,8 @@ pub(crate) enum TrustConfig { CaCertificateLocation(PathBuf), TrustAll, Default, + #[cfg(feature = "rustls")] + WebPkiRoots } impl Default for Config { diff --git a/src/client/tls_stream/rustls_tls_stream.rs b/src/client/tls_stream/rustls_tls_stream.rs index e417583a..0fb27fc8 100644 --- a/src/client/tls_stream/rustls_tls_stream.rs +++ b/src/client/tls_stream/rustls_tls_stream.rs @@ -132,6 +132,10 @@ impl TlsStream { event!(Level::INFO, "Using default trust configuration."); builder.with_native_roots().with_no_client_auth() } + TrustConfig::WebPkiRoots => { + event!(Level::INFO, "Using webpki trust configuration."); + builder.with_webpki_roots().with_no_client_auth() + } }; let connector = TlsConnector::from(Arc::new(client_config)); From 0a2045669998d9ffcc9bf9f1d2465fea6279c8a0 Mon Sep 17 00:00:00 2001 From: zlepper Date: Fri, 2 Feb 2024 08:35:23 +0100 Subject: [PATCH 2/3] I love dealing with compile errors like this... --- Cargo.toml | 5 +++ src/client/config.rs | 2 +- src/client/tls_stream/rustls_tls_stream.rs | 38 ++++++++++++++++------ 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4f96e962..a3759129 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -130,6 +130,10 @@ optional = true version = "0.6" optional = true +[dependencies.webpki-roots] +version = "0.25" +optional = true + [dependencies.opentls] version = "0.2.1" optional = true @@ -200,5 +204,6 @@ sql-browser-smol = ["async-io", "async-net", "futures-lite"] integrated-auth-gssapi = ["libgssapi"] bigdecimal = ["bigdecimal_"] rustls = ["tokio-rustls", "tokio-util", "rustls-pemfile", "rustls-native-certs"] +rustls-webpki-roots = ["webpki-roots", "rustls"] native-tls = ["async-native-tls"] vendored-openssl = ["opentls"] diff --git a/src/client/config.rs b/src/client/config.rs index ca72b6e2..edf2bc04 100644 --- a/src/client/config.rs +++ b/src/client/config.rs @@ -39,7 +39,7 @@ pub(crate) enum TrustConfig { CaCertificateLocation(PathBuf), TrustAll, Default, - #[cfg(feature = "rustls")] + #[cfg(feature = "rustls-webpki-roots")] WebPkiRoots } diff --git a/src/client/tls_stream/rustls_tls_stream.rs b/src/client/tls_stream/rustls_tls_stream.rs index 0fb27fc8..d21c2a0a 100644 --- a/src/client/tls_stream/rustls_tls_stream.rs +++ b/src/client/tls_stream/rustls_tls_stream.rs @@ -11,17 +11,14 @@ use std::{ task::{Context, Poll}, time::SystemTime, }; -use tokio_rustls::{ - rustls::{ - client::{ - HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier, - WantsTransparencyPolicyOrClientCert, - }, - Certificate, ClientConfig, ConfigBuilder, DigitallySignedStruct, Error as RustlsError, - RootCertStore, ServerName, WantsVerifier, +use tokio_rustls::{rustls::{ + client::{ + HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier, + WantsTransparencyPolicyOrClientCert, }, - TlsConnector, -}; + Certificate, ClientConfig, ConfigBuilder, DigitallySignedStruct, Error as RustlsError, + RootCertStore, ServerName, WantsVerifier, +}, rustls, TlsConnector}; use tokio_util::compat::{Compat, FuturesAsyncReadCompatExt, TokioAsyncReadCompatExt}; use tracing::{event, Level}; @@ -132,6 +129,7 @@ impl TlsStream { event!(Level::INFO, "Using default trust configuration."); builder.with_native_roots().with_no_client_auth() } + #[cfg(feature = "rustls-webpki-roots")] TrustConfig::WebPkiRoots => { event!(Level::INFO, "Using webpki trust configuration."); builder.with_webpki_roots().with_no_client_auth() @@ -186,6 +184,9 @@ impl AsyncWrite for TlsStream { trait ConfigBuilderExt { fn with_native_roots(self) -> ConfigBuilder; + + #[cfg(feature = "rustls-webpki-roots")] + fn with_webpki_roots(self) -> ConfigBuilder; } impl ConfigBuilderExt for ConfigBuilder { @@ -216,4 +217,21 @@ impl ConfigBuilderExt for ConfigBuilder { self.with_root_certificates(roots) } + + #[cfg(feature = "rustls-webpki-roots")] + fn with_webpki_roots(self) -> ConfigBuilder { + let mut roots = rustls::RootCertStore::empty(); + roots.add_trust_anchors( + webpki_roots::TLS_SERVER_ROOTS + .iter() + .map(|ta| { + rustls::OwnedTrustAnchor::from_subject_spki_name_constraints( + ta.subject, + ta.spki, + ta.name_constraints, + ) + }), + ); + self.with_root_certificates(roots) + } } From f1b3d0b80ef85676fb4f9a14393687915b8396e5 Mon Sep 17 00:00:00 2001 From: zlepper Date: Fri, 2 Feb 2024 08:59:36 +0100 Subject: [PATCH 3/3] Add method for enabling webpki --- src/client/config.rs | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/client/config.rs b/src/client/config.rs index edf2bc04..c763bedb 100644 --- a/src/client/config.rs +++ b/src/client/config.rs @@ -34,7 +34,7 @@ pub struct Config { pub(crate) readonly: bool, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub(crate) enum TrustConfig { CaCertificateLocation(PathBuf), TrustAll, @@ -131,12 +131,12 @@ impl Config { /// storage (or use `trust_cert_ca` instead), using this setting is potentially dangerous. /// /// # Panics - /// Will panic in case `trust_cert_ca` was called before. + /// Will panic in case `trust_cert_ca` or `trust_webpki_roots` was called before. /// /// - Defaults to `default`, meaning server certificate is validated against system-truststore. pub fn trust_cert(&mut self) { - if let TrustConfig::CaCertificateLocation(_) = &self.trust { - panic!("'trust_cert' and 'trust_cert_ca' are mutual exclusive! Only use one.") + if TrustConfig::Default != self.trust { + panic!("'trust_webpki_roots'/'trust_cert'/'trust_cert_ca' are mutual exclusive! Only use one.") } self.trust = TrustConfig::TrustAll; } @@ -147,17 +147,30 @@ impl Config { /// trust-chain. /// /// # Panics - /// Will panic in case `trust_cert` was called before. + /// Will panic in case `trust_cert` or `trust_webpki_roots` was called before. /// /// - Defaults to validating the server certificate is validated against system's certificate storage. pub fn trust_cert_ca(&mut self, path: impl ToString) { - if let TrustConfig::TrustAll = &self.trust { - panic!("'trust_cert' and 'trust_cert_ca' are mutual exclusive! Only use one.") + if TrustConfig::Default != self.trust { + panic!("'trust_webpki_roots'/'trust_cert'/'trust_cert_ca' are mutual exclusive! Only use one.") } else { self.trust = TrustConfig::CaCertificateLocation(PathBuf::from(path.to_string())) } } + /// If set, the server certificate will be validated against the webpki-roots. + /// + /// # Panics + /// Will panic in case `trust_cert` or `trust_cert_ca` was called before. + /// + #[cfg(feature = "rustls-webpki-roots")] + pub fn trust_webpki_roots(&mut self) { + if self.trust != TrustConfig::Default { + panic!("'trust_webpki_roots'/'trust_cert'/'trust_cert_ca' are mutual exclusive! Only use one.") + } + self.trust = TrustConfig::WebPkiRoots; + } + /// Sets the authentication method. /// /// - Defaults to `None`.