Fix DANE: Treat DNSSEC bogus as a temporary failures to prevent downgrade attacks

This commit is contained in:
Maurus Decimus
2026-06-25 19:24:10 +02:00
parent 0b520b6334
commit 0eb08b9fb3
63 changed files with 948 additions and 614 deletions

View File

@@ -1,6 +1,6 @@
[package]
name = "http"
version = "0.16.11"
version = "0.16.12"
edition = "2024"
[dependencies]
@@ -23,7 +23,7 @@ registry = { path = "../registry" }
smtp-proto = { version = "0.2" }
mail-parser = { version = "0.11", features = ["full_encoding", "rkyv"] }
mail-builder = { version = "0.4" }
mail-auth = { version = "0.9", features = ["generate"] }
mail-auth = { version = "0.10", features = ["generate"] }
tokio = { version = "1.47", features = ["rt"] }
hyper = { version = "1.0.1", features = ["server", "http1", "http2"] }
hyper-util = { version = "0.1.1", features = ["tokio"] }

View File

@@ -16,7 +16,10 @@ use mail_auth::{IpLookupStrategy, mta_sts::TlsRpt};
use serde::{Deserialize, Serialize};
use smtp::outbound::{
client::{SmtpClient, StartTlsResult},
dane::{dnssec::TlsaLookup, verify::TlsaVerify},
dane::{
dnssec::{TlsaLookup, TlsaResult},
verify::TlsaVerify,
},
error::ClientError,
lookup::{DnsLookup, SourceIp, ToNextHop},
mta_sts::{lookup::MtaStsLookup, verify::VerifyPolicy},
@@ -249,13 +252,14 @@ async fn delivery_diagnose(
// Obtain remote host list
let mx_config = MxConfig {
max_mx: mxs.len(),
max_mx: mxs.rrset.len(),
max_multi_homed: 10,
ip_lookup_strategy: IpLookupStrategy::Ipv4thenIpv6,
};
let hosts = if let Some(hosts) = mxs.to_remote_hosts(&domain, &mx_config) {
tx.send(DeliveryStage::MxLookupSuccess {
mxs: mxs
.rrset
.iter()
.map(|mx| MX {
exchanges: mx.exchanges.iter().map(|e| e.to_string()).collect(),
@@ -385,7 +389,7 @@ async fn delivery_diagnose(
let now = Instant::now();
let dane_policy = match server.tlsa_lookup(format!("_25._tcp.{hostname}.")).await {
Ok(Some(tlsa)) if tlsa.has_end_entities => {
Ok(TlsaResult::Secure(tlsa)) if tlsa.has_end_entities => {
tx.send(DeliveryStage::TlsaLookupSuccess {
record: tlsa.as_ref().clone(),
elapsed: now.elapsed_ms(),
@@ -394,7 +398,7 @@ async fn delivery_diagnose(
Some(tlsa)
}
Ok(Some(_)) => {
Ok(TlsaResult::Secure(_)) => {
tx.send(DeliveryStage::TlsaLookupError {
elapsed: now.elapsed_ms(),
reason: "TLSA record does not have end entities".to_string(),
@@ -403,7 +407,16 @@ async fn delivery_diagnose(
None
}
Ok(None) => {
Ok(TlsaResult::Bogus) => {
tx.send(DeliveryStage::TlsaLookupError {
elapsed: now.elapsed_ms(),
reason: "Bogus TLSA record".to_string(),
})
.await?;
None
}
Ok(TlsaResult::Missing) => {
tx.send(DeliveryStage::TlsaNotFound {
elapsed: now.elapsed_ms(),
reason: "No TLSA DNSSEC records found".to_string(),