implement tls::danger::StifledCertificateVerification

StifledCertificateVerification::verify_server_cert() will verify the certificate with the default rustls WebPkiVerifier, BUT specifically override a `CertificateError::UnknownIssuer` and return ServerCertVerified::assertion()

This allows us to use rustls to open a tls connection to a host with an untrusted certificate chain. And subsequently get to see the certificate chain, and possibly choose to trust the chain, or links in it.
This commit is contained in:
nworbnhoj 2023-06-25 12:11:30 +10:00
parent fcc4cde41b
commit 4ea0c8457d
3 changed files with 46 additions and 13 deletions

37
libs/tls/src/danger.rs Normal file
View file

@ -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<Item = &[u8]>,
ocsp: &[u8],
now: std::time::SystemTime,
) -> Result<rustls::client::ServerCertVerified, rustls::Error> {
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),
}
}
}

View file

@ -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

View file

@ -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,