diff --git a/src/tls/cert/mod.rs b/src/tls/cert/mod.rs index 2ee244eb..58d06a1b 100644 --- a/src/tls/cert/mod.rs +++ b/src/tls/cert/mod.rs @@ -1,8 +1,11 @@ pub mod compression; #[cfg(any(feature = "webpki-roots", feature = "native-roots"))] -pub mod load; +mod load; -use boring2::x509::store::X509Store; +use super::{sv_handler, TlsResult}; +use boring2::{ssl::SslConnectorBuilder, x509::store::X509Store}; +use boring_sys2 as ffi; +use foreign_types::ForeignTypeRef; /// The root certificate store. #[allow(missing_debug_implementations)] @@ -20,6 +23,50 @@ pub enum RootCertStore { } /// ====== impl RootCertsStore ====== +impl RootCertStore { + /// Applies the root certificate store to the TLS builder. + pub(crate) fn apply(self, builder: &mut SslConnectorBuilder) -> TlsResult<()> { + // Conditionally configure the TLS builder based on the "native-roots" feature. + // If no custom CA cert store, use the system's native certificate store if the feature is enabled. + match self { + RootCertStore::Default => { + // WebPKI root certificates are enabled (regardless of whether native-roots is also enabled). + #[cfg(any(feature = "webpki-roots", feature = "native-roots"))] + { + if let Some(cert_store) = load::LOAD_CERTS.as_deref() { + log::debug!("Using CA certs from webpki/native roots"); + sv_handler(unsafe { + ffi::SSL_CTX_set1_verify_cert_store( + builder.as_ptr(), + cert_store.as_ptr(), + ) + })?; + } else { + log::debug!("No CA certs provided, using system default"); + builder.set_default_verify_paths()?; + } + } + + // Neither native-roots nor WebPKI roots are enabled, proceed with the default builder. + #[cfg(not(any(feature = "webpki-roots", feature = "native-roots")))] + { + builder.set_default_verify_paths()?; + } + } + RootCertStore::Owned(cert_store) => { + builder.set_verify_cert_store(cert_store)?; + } + RootCertStore::Borrowed(cert_store) => { + sv_handler(unsafe { + ffi::SSL_CTX_set1_verify_cert_store(builder.as_ptr(), cert_store.as_ptr()) + })?; + } + } + + Ok(()) + } +} + macro_rules! impl_root_cert_store { ($($type:ty => $variant:ident),* $(,)?) => { $( diff --git a/src/tls/ext.rs b/src/tls/ext.rs index 10c0f2e0..96e41cb1 100644 --- a/src/tls/ext.rs +++ b/src/tls/ext.rs @@ -1,20 +1,10 @@ -use super::cert::{compression::CertCompressionAlgorithm, load, RootCertStore}; -use super::{AlpnProtos, AlpsProtos, TlsResult, TlsVersion}; -use ::std::os::raw::c_int; -use boring2::error::ErrorStack; +use super::cert::{compression::CertCompressionAlgorithm, RootCertStore}; +use super::{sv_handler, AlpnProtos, AlpsProtos, TlsResult, TlsVersion}; + use boring2::ssl::{ConnectConfiguration, SslConnectorBuilder, SslRef, SslVerifyMode}; use boring_sys2 as ffi; use foreign_types::ForeignTypeRef; -/// Error handler for the boringssl functions. -fn sv_handler(r: c_int) -> TlsResult { - if r == 0 { - Err(ErrorStack::get()) - } else { - Ok(r) - } -} - /// SslConnectorBuilderExt trait for `SslConnectorBuilder`. pub trait SslConnectorBuilderExt { /// Configure the certificate verification for the given `SslConnectorBuilder`. @@ -42,7 +32,7 @@ pub trait SslConnectorBuilderExt { ) -> TlsResult; /// Configure the RootCertsStore for the given `SslConnectorBuilder`. - fn root_certs_store(self, stroe: RootCertStore) -> TlsResult; + fn root_cert_store(self, stroe: RootCertStore) -> TlsResult; } /// SslRefExt trait for `SslRef`. @@ -114,41 +104,8 @@ impl SslConnectorBuilderExt for SslConnectorBuilder { } #[inline] - fn root_certs_store(mut self, store: RootCertStore) -> TlsResult { - // Conditionally configure the TLS builder based on the "native-roots" feature. - // If no custom CA cert store, use the system's native certificate store if the feature is enabled. - match store { - RootCertStore::Default => { - // WebPKI root certificates are enabled (regardless of whether native-roots is also enabled). - #[cfg(any(feature = "webpki-roots", feature = "native-roots"))] - { - if let Some(cert_store) = load::LOAD_CERTS.as_deref() { - log::debug!("Using CA certs from webpki/native roots"); - sv_handler(unsafe { - ffi::SSL_CTX_set1_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) - })?; - } else { - log::debug!("No CA certs provided, using system default"); - self.set_default_verify_paths()?; - } - } - - // Neither native-roots nor WebPKI roots are enabled, proceed with the default builder. - #[cfg(not(any(feature = "webpki-roots", feature = "native-roots")))] - { - self.set_default_verify_paths()?; - } - } - RootCertStore::Owned(cert_store) => { - self.set_verify_cert_store(cert_store)?; - } - RootCertStore::Borrowed(cert_store) => { - sv_handler(unsafe { - ffi::SSL_CTX_set1_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) - })?; - } - } - + fn root_cert_store(mut self, store: RootCertStore) -> TlsResult { + store.apply(&mut self)?; Ok(self) } } diff --git a/src/tls/mod.rs b/src/tls/mod.rs index 8fd28bc7..b142dd47 100644 --- a/src/tls/mod.rs +++ b/src/tls/mod.rs @@ -25,6 +25,15 @@ pub use ext::{ConnectConfigurationExt, SslConnectorBuilderExt, SslRefExt}; type TlsResult = Result; +/// Error handler for the boringssl functions. +fn sv_handler(r: ::std::os::raw::c_int) -> TlsResult<::std::os::raw::c_int> { + if r == 0 { + Err(ErrorStack::get()) + } else { + Ok(r) + } +} + /// A wrapper around a `HttpsLayer` that allows for additional settings. #[derive(Clone)] pub(crate) struct BoringTlsConnector(HttpsLayer); @@ -34,7 +43,7 @@ impl BoringTlsConnector { #[inline] pub fn new(settings: TlsSettings) -> TlsResult { let mut connector = SslConnector::no_default_verify_builder(SslMethod::tls_client())? - .root_certs_store(settings.root_certs_store)? + .root_cert_store(settings.root_certs_store)? .cert_verification(settings.certs_verification)? .alpn_protos(settings.alpn_protos)? .min_tls_version(settings.min_tls_version)?