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 = "common"
version = "0.16.11"
version = "0.16.12"
edition = "2024"
build = "build.rs"
@@ -18,7 +18,7 @@ imap_proto = { path = "../imap-proto" }
sieve-rs = { version = "0.7", features = ["rkyv", "serde"] }
mail-parser = { version = "0.11", features = ["full_encoding"] }
mail-builder = { version = "0.4" }
mail-auth = { version = "0.9", features = ["generate"] }
mail-auth = { version = "0.10", features = ["generate"] }
smtp-proto = { version = "0.2", features = ["rkyv"] }
dns-update = { version = "0.5" }
calcard = { version = "0.3", features = ["rkyv"] }

View File

@@ -22,7 +22,7 @@ use crate::{
};
use ahash::{AHashMap, AHashSet};
use arc_swap::ArcSwap;
use mail_auth::{MX, Parameters, Txt};
use mail_auth::{MX, Parameters, RecordSet, Txt};
use parking_lot::RwLock;
use registry::schema::{prelude::ObjectType, structs};
use std::{
@@ -178,10 +178,6 @@ impl Caches {
((std::mem::size_of::<Ipv6Addr>() + 255) * 2) as u64,
),
dns_tlsa: CacheWithTtl::new(cache.dns_tlsa, (std::mem::size_of::<Tlsa>() + 255) as u64),
dns_dnssec: CacheWithTtl::new(
cache.dns_tlsa,
(std::mem::size_of::<bool>() + 255) as u64,
),
dns_mta_sts: CacheWithTtl::new(
cache.dns_mta_sts,
(std::mem::size_of::<Policy>() + 255) as u64,
@@ -203,10 +199,10 @@ impl Caches {
'_,
T,
CacheWithTtl<Box<str>, Txt>,
CacheWithTtl<Box<str>, Arc<[MX]>>,
CacheWithTtl<Box<str>, Arc<[Ipv4Addr]>>,
CacheWithTtl<Box<str>, Arc<[Ipv6Addr]>>,
CacheWithTtl<IpAddr, Arc<[Box<str>]>>,
CacheWithTtl<Box<str>, RecordSet<MX>>,
CacheWithTtl<Box<str>, RecordSet<Ipv4Addr>>,
CacheWithTtl<Box<str>, RecordSet<Ipv6Addr>>,
CacheWithTtl<IpAddr, RecordSet<Box<str>>>,
> {
Parameters {
params,

View File

@@ -218,6 +218,7 @@ impl Server {
.map_err(|err| trc::Error::from(err).caused_by(trc::location!()))
.map(|result| {
result
.rrset
.iter()
.flat_map(|mx| {
mx.exchanges.iter().map(|host| {
@@ -256,6 +257,7 @@ impl Server {
.map_err(|err| trc::Error::from(err).caused_by(trc::location!()))
.map(|result| {
result
.rrset
.iter()
.map(|host| Variable::from(host.to_compact_string()))
.collect::<Vec<_>>()
@@ -271,6 +273,7 @@ impl Server {
.map_err(|err| trc::Error::from(err).caused_by(trc::location!()))
.map(|result| {
result
.rrset
.iter()
.map(|ip| Variable::from(ip.to_compact_string()))
.collect::<Vec<_>>()
@@ -286,6 +289,7 @@ impl Server {
.map_err(|err| trc::Error::from(err).caused_by(trc::location!()))
.map(|result| {
result
.rrset
.iter()
.map(|ip| Variable::from(ip.to_compact_string()))
.collect::<Vec<_>>()

View File

@@ -39,7 +39,7 @@ use config::{
telemetry::Metrics,
};
use ipc::{BroadcastEvent, PushEvent, QueueEvent, ReportingEvent};
use mail_auth::{MX, Txt};
use mail_auth::{MX, RecordSet, Txt};
use manager::application::Resource;
use parking_lot::{Mutex, RwLock};
use rustls::sign::CertifiedKey;
@@ -196,12 +196,11 @@ pub struct Caches {
pub dkim_signers: Cache<u32, Arc<[DkimSigner]>>,
pub dns_txt: CacheWithTtl<Box<str>, Txt>,
pub dns_mx: CacheWithTtl<Box<str>, Arc<[MX]>>,
pub dns_ptr: CacheWithTtl<IpAddr, Arc<[Box<str>]>>,
pub dns_ipv4: CacheWithTtl<Box<str>, Arc<[Ipv4Addr]>>,
pub dns_ipv6: CacheWithTtl<Box<str>, Arc<[Ipv6Addr]>>,
pub dns_mx: CacheWithTtl<Box<str>, RecordSet<MX>>,
pub dns_ptr: CacheWithTtl<IpAddr, RecordSet<Box<str>>>,
pub dns_ipv4: CacheWithTtl<Box<str>, RecordSet<Ipv4Addr>>,
pub dns_ipv6: CacheWithTtl<Box<str>, RecordSet<Ipv6Addr>>,
pub dns_tlsa: CacheWithTtl<Box<str>, Arc<Tlsa>>,
pub dns_dnssec: CacheWithTtl<Box<str>, bool>,
pub dns_mta_sts: CacheWithTtl<Box<str>, Arc<Policy>>,
pub dns_rbl: CacheWithTtl<Box<str>, Option<Arc<IpResolver>>>,

View File

@@ -18,7 +18,7 @@ impl Server {
.mx_lookup(entry, Some(&self.inner.cache.dns_mx))
.await
{
Ok(result) => Ok(result.iter().any(|mx| !mx.exchanges.is_empty())),
Ok(result) => Ok(result.rrset.iter().any(|mx| !mx.exchanges.is_empty())),
Err(Error::DnsRecordNotFound(_)) => Ok(false),
Err(err) => Err(err.into()),
}
@@ -55,7 +55,7 @@ impl Server {
.ptr_lookup(addr, Some(&self.inner.cache.dns_ptr))
.await
{
Ok(result) => Ok(!result.is_empty()),
Ok(result) => Ok(!result.rrset.is_empty()),
Err(Error::DnsRecordNotFound(_)) => Ok(false),
Err(err) => Err(err.into()),
}
@@ -73,7 +73,7 @@ impl Server {
.ipv4_lookup(entry, Some(&self.inner.cache.dns_ipv4))
.await
{
Ok(result) => Ok(!result.is_empty()),
Ok(result) => Ok(!result.rrset.is_empty()),
Err(Error::DnsRecordNotFound(_)) => Ok(false),
Err(err) => Err(err.into()),
}
@@ -88,7 +88,7 @@ impl Server {
.ipv6_lookup(entry, Some(&self.inner.cache.dns_ipv6))
.await
{
Ok(result) => Ok(!result.is_empty()),
Ok(result) => Ok(!result.rrset.is_empty()),
Err(Error::DnsRecordNotFound(_)) => Ok(false),
Err(err) => Err(err.into()),
}

View File

@@ -57,6 +57,7 @@ pub async fn exec(ctx: PluginContext<'_>) -> trc::Result<Variable> {
.await
{
Ok(result) => result
.rrset
.iter()
.flat_map(|mx| {
mx.exchanges
@@ -99,6 +100,7 @@ pub async fn exec(ctx: PluginContext<'_>) -> trc::Result<Variable> {
.await
{
Ok(result) => result
.rrset
.iter()
.map(|host| Variable::from(host.to_string()))
.collect::<Vec<_>>()
@@ -127,6 +129,7 @@ pub async fn exec(ctx: PluginContext<'_>) -> trc::Result<Variable> {
.await
{
Ok(result) => result
.rrset
.iter()
.map(|ip| Variable::from(ip.to_string()))
.collect::<Vec<_>>()
@@ -144,6 +147,7 @@ pub async fn exec(ctx: PluginContext<'_>) -> trc::Result<Variable> {
.await
{
Ok(result) => result
.rrset
.iter()
.map(|ip| Variable::from(ip.to_string()))
.collect::<Vec<_>>()