From 32b888b3c1d1d11e6d5aa22b5bbb087fdaf85da0 Mon Sep 17 00:00:00 2001 From: DarkCat09 Date: Wed, 28 Aug 2024 17:02:56 +0400 Subject: [PATCH] fix(SECURITY): return error on failed DANE verification and add raw cert caching in DANE verificator --- examples/main.rs | 3 +-- src/certs/dane.rs | 25 +++++++++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/examples/main.rs b/examples/main.rs index 0fd7c51..349442e 100644 --- a/examples/main.rs +++ b/examples/main.rs @@ -149,8 +149,7 @@ impl SelfsignedCertVerifier for CertVerifier { CertFingerprint::new_sha256(cert) } Err(e) => { - // some other problem (e.g. DNS server rejected the request), - // we shouldn't continue + // cert not matched, DNS server rejected request, etc. eprintln!("DANE verification failed: {:?}", e); return Err(e); } diff --git a/src/certs/dane.rs b/src/certs/dane.rs index e42a953..1f28524 100644 --- a/src/certs/dane.rs +++ b/src/certs/dane.rs @@ -4,6 +4,8 @@ use crate::{ LibError, }; +use tokio_rustls::rustls; + pub async fn dane( dns: &DnsClient, cert: &CertificateDer<'_>, @@ -12,8 +14,11 @@ pub async fn dane( ) -> Result { let mut dns = dns.clone(); + // TODO: maybe kinda Iterator or HashMap? + // what if we needed one more algorithm to add? let mut sha256: Option = None; let mut sha512: Option = None; + let mut raw: Option = None; for tlsa_fp in dns.query_tlsa(host, port).await? { match tlsa_fp { @@ -36,19 +41,23 @@ pub async fn dane( } } CertFingerprint::Raw(_) => { - let this_fp = CertFingerprint::new_raw(cert); - if this_fp == tlsa_fp { - return Ok(CertFingerprint::new_sha256(cert)); + if raw.is_none() { + raw = Some(CertFingerprint::new_raw(cert)); + } + let this_fp = raw.as_ref().unwrap(); + if this_fp == &tlsa_fp { + return Ok(sha256.unwrap_or_else(|| CertFingerprint::new_sha256(cert))); } } } } - if let Some(sha256) = sha256 { - Ok(sha256) - } else if let Some(sha512) = sha512 { - Ok(sha512) + if sha256.is_some() || sha512.is_some() || raw.is_some() { + // we have a hash => we tried to match a cert at least once, + // i.e. query_tlsa did not return an empty iterator + Err(rustls::CertificateError::ApplicationVerificationFailure.into()) } else { - Ok(CertFingerprint::new_sha256(cert)) + // iterator was empty, we can't do any verification + Err(LibError::HostLookupError) } }