fix(SECURITY): return error on failed DANE verification

and add raw cert caching in DANE verificator
This commit is contained in:
DarkCat09 2024-08-28 17:02:56 +04:00
parent c3b50e4ecc
commit 32b888b3c1
Signed by: DarkCat09
GPG key ID: BD3CE9B65916CD82
2 changed files with 18 additions and 10 deletions

View file

@ -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);
}

View file

@ -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<CertFingerprint, LibError> {
let mut dns = dns.clone();
// TODO: maybe kinda Iterator or HashMap?
// what if we needed one more algorithm to add?
let mut sha256: Option<CertFingerprint> = None;
let mut sha512: Option<CertFingerprint> = None;
let mut raw: Option<CertFingerprint> = 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)
}
}