Disable DANE when there are no TCP resolvers configured

This commit is contained in:
Maurus Decimus
2026-07-09 09:48:05 +02:00
parent 448f735d55
commit e2d0505013
3 changed files with 19 additions and 10 deletions

View File

@@ -73,7 +73,7 @@ impl SmtpConfig {
concat!(
"The configured DNS resolver cannot validate DNSSEC. ",
"DANE has been disabled to avoid deferring mail. ",
"Configure a DNSSEC-validating resolver to enable DANE."
"Ensure the resolver is DNSSEC-capable and reachable over TCP."
),
);
}

View File

@@ -4,6 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
use ahash::AHashMap;
use mail_auth::{
MessageAuthenticator,
hickory_resolver::{
@@ -25,6 +26,7 @@ use serde::{Deserialize, Serialize};
use std::{
fmt::Display,
hash::{DefaultHasher, Hash, Hasher},
net::IpAddr,
str::FromStr,
sync::Arc,
};
@@ -139,6 +141,7 @@ impl Resolvers {
},
DnsResolver::Custom(resolver) => {
resolver_config = ResolverConfig::default();
let mut nameservers: AHashMap<IpAddr, Vec<ConnectionConfig>> = AHashMap::new();
for server in resolver.servers {
let ip = server.address.into_inner();
@@ -152,11 +155,11 @@ impl Resolvers {
};
let mut connection = ConnectionConfig::new(protocol);
connection.port = port;
resolver_config.add_name_server(NameServerConfig::new(
ip,
true,
vec![connection],
));
nameservers.entry(ip).or_default().push(connection);
}
for (ip, connections) in nameservers {
resolver_config.add_name_server(NameServerConfig::new(ip, true, connections));
}
opts.num_concurrent_reqs = resolver.concurrency as usize;
@@ -223,19 +226,24 @@ impl Resolvers {
};
Resolvers {
dns: MessageAuthenticator::new(resolver_config, opts).unwrap(),
#[cfg(not(feature = "test_mode"))]
dnssec_available: dnssec_capable(&dnssec.resolver).await,
dnssec_available: ensure_dnssec(&resolver_config, &dnssec.resolver).await,
#[cfg(feature = "test_mode")]
dnssec_available: true,
dns: MessageAuthenticator::new(resolver_config, opts).unwrap(),
dnssec,
}
}
}
#[cfg(not(feature = "test_mode"))]
async fn dnssec_capable(resolver: &TokioResolver) -> bool {
resolver
async fn ensure_dnssec(config: &ResolverConfig, resolver: &TokioResolver) -> bool {
config.name_servers().iter().any(|name_server| {
name_server
.connections
.iter()
.any(|connection| !matches!(connection.protocol, ProtocolConfig::Udp))
}) && resolver
.lookup(
hickory_proto::rr::Name::root(),
hickory_proto::rr::RecordType::DNSKEY,