fix(SECURITY): return error on failed DANE verification
and add raw cert caching in DANE verificator
This commit is contained in:
parent
c3b50e4ecc
commit
32b888b3c1
2 changed files with 18 additions and 10 deletions
|
@ -149,8 +149,7 @@ impl SelfsignedCertVerifier for CertVerifier {
|
||||||
CertFingerprint::new_sha256(cert)
|
CertFingerprint::new_sha256(cert)
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// some other problem (e.g. DNS server rejected the request),
|
// cert not matched, DNS server rejected request, etc.
|
||||||
// we shouldn't continue
|
|
||||||
eprintln!("DANE verification failed: {:?}", e);
|
eprintln!("DANE verification failed: {:?}", e);
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ use crate::{
|
||||||
LibError,
|
LibError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use tokio_rustls::rustls;
|
||||||
|
|
||||||
pub async fn dane(
|
pub async fn dane(
|
||||||
dns: &DnsClient,
|
dns: &DnsClient,
|
||||||
cert: &CertificateDer<'_>,
|
cert: &CertificateDer<'_>,
|
||||||
|
@ -12,8 +14,11 @@ pub async fn dane(
|
||||||
) -> Result<CertFingerprint, LibError> {
|
) -> Result<CertFingerprint, LibError> {
|
||||||
let mut dns = dns.clone();
|
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 sha256: Option<CertFingerprint> = None;
|
||||||
let mut sha512: 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? {
|
for tlsa_fp in dns.query_tlsa(host, port).await? {
|
||||||
match tlsa_fp {
|
match tlsa_fp {
|
||||||
|
@ -36,19 +41,23 @@ pub async fn dane(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CertFingerprint::Raw(_) => {
|
CertFingerprint::Raw(_) => {
|
||||||
let this_fp = CertFingerprint::new_raw(cert);
|
if raw.is_none() {
|
||||||
if this_fp == tlsa_fp {
|
raw = Some(CertFingerprint::new_raw(cert));
|
||||||
return Ok(CertFingerprint::new_sha256(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 {
|
if sha256.is_some() || sha512.is_some() || raw.is_some() {
|
||||||
Ok(sha256)
|
// we have a hash => we tried to match a cert at least once,
|
||||||
} else if let Some(sha512) = sha512 {
|
// i.e. query_tlsa did not return an empty iterator
|
||||||
Ok(sha512)
|
Err(rustls::CertificateError::ApplicationVerificationFailure.into())
|
||||||
} else {
|
} else {
|
||||||
Ok(CertFingerprint::new_sha256(cert))
|
// iterator was empty, we can't do any verification
|
||||||
|
Err(LibError::HostLookupError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue