diff --git a/libs/tls/src/danger.rs b/libs/tls/src/danger.rs new file mode 100644 index 000000000..b7c606788 --- /dev/null +++ b/libs/tls/src/danger.rs @@ -0,0 +1,37 @@ +use rustls::client::{ServerCertVerified, WebPkiVerifier}; +use rustls::{CertificateError, Error, RootCertStore}; + +pub struct StifledCertificateVerification { + pub roots: RootCertStore, +} + +impl rustls::client::ServerCertVerifier for StifledCertificateVerification { + /// Will verify the certificate with the default rustls WebPkiVerifier, + /// BUT specifically overrides a `CertificateError::UnknownIssuer` and + /// return ServerCertVerified::assertion() + fn verify_server_cert( + &self, + end_entity: &rustls::Certificate, + intermediates: &[rustls::Certificate], + server_name: &rustls::ServerName, + scts: &mut dyn Iterator, + ocsp: &[u8], + now: std::time::SystemTime, + ) -> Result { + let rustls_default_verifier = WebPkiVerifier::new(self.roots.clone(), None); + match rustls_default_verifier.verify_server_cert( + end_entity, + intermediates, + server_name, + scts, + ocsp, + now, + ) { + Ok(ok) => Ok(ok), + Err(Error::InvalidCertificate(CertificateError::UnknownIssuer)) => { + Ok(ServerCertVerified::assertion()) + } + Err(e) => Err(e), + } + } +} diff --git a/libs/tls/src/lib.rs b/libs/tls/src/lib.rs index 3bd08d188..51c22b970 100644 --- a/libs/tls/src/lib.rs +++ b/libs/tls/src/lib.rs @@ -1,3 +1,5 @@ +pub mod danger; + use modals::Modals; use rkyv::{ de::deserializers::AllocDeserializer, @@ -93,6 +95,8 @@ impl Iterator for Trusted { } } } + + // presents a modal to the user to select trusted tls certificates // and saves the selected certificates to the pddb // returns false if no certificates are trusted - and true otherwise diff --git a/services/shellchat/src/cmds/net_cmd.rs b/services/shellchat/src/cmds/net_cmd.rs index 14b2af4a2..b5f4346d7 100644 --- a/services/shellchat/src/cmds/net_cmd.rs +++ b/services/shellchat/src/cmds/net_cmd.rs @@ -471,22 +471,14 @@ impl<'a> ShellCmdApi<'a> for NetCmd { "probe" => { log::set_max_level(log::LevelFilter::Info); log::info!("starting TLS probe"); + // Attempt to open the tls connection with an empty root_store let mut root_store = rustls::RootCertStore::empty(); - root_store.add_server_trust_anchors( - webpki_roots::TLS_SERVER_ROOTS - .0 - .iter() - .map(|ta| { - rustls::OwnedTrustAnchor::from_subject_spki_name_constraints( - ta.subject, - ta.spki, - ta.name_constraints, - ) - }) - ); + // Stifle the default rustls certificate verification's complaint about an + // unknown/untrusted CA root certificate so that we get to see the certificate chain + let stifled_verifier = Arc::new(danger::StifledCertificateVerification{ roots: root_store }); let config = rustls::ClientConfig::builder() .with_safe_defaults() - .with_root_certificates(root_store) + .with_custom_certificate_verifier(stifled_verifier) .with_no_client_auth(); let target = match tokens.next() { Some(target) => target,