From 3cb47b3558925de3a8a72d3b4e39e17d91f52232 Mon Sep 17 00:00:00 2001 From: Otto Moerbeek Date: Mon, 24 Jan 2022 13:18:17 +0100 Subject: [PATCH] Process denial of ZONEMD in the NSEC3 case --- pdns/recursordist/rec-zonetocache.cc | 6 +++--- pdns/zonemd.cc | 24 +++++++++++++++++++++++- pdns/zonemd.hh | 5 +++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/pdns/recursordist/rec-zonetocache.cc b/pdns/recursordist/rec-zonetocache.cc index fbcc221184..2aee2c3191 100644 --- a/pdns/recursordist/rec-zonetocache.cc +++ b/pdns/recursordist/rec-zonetocache.cc @@ -287,9 +287,9 @@ vState ZoneData::dnssecValidate(pdns::ZoneMD& zonemd, size_t& zonemdCount) const nsecValidationStatus = validateWithKeySet(d_now, d_zone, nsecs.records, nsecs.signatures, validKeys); csp.emplace(std::make_pair(d_zone, QType::NSEC), nsecs); } - else if (nsec3s.records.size() > 0 && nsec3s.signatures.size() > 0) { - nsecValidationStatus = validateWithKeySet(d_now, d_zone, nsec3s.records, nsec3s.signatures, validKeys); - csp.emplace(std::make_pair(d_zone, QType::NSEC3), nsec3s); + else if (nsec3s.records.size() > 0 && nsec3s.signatures.size() > 0 && !zonemd.getNSEC3Label().empty()) { + nsecValidationStatus = validateWithKeySet(d_now, zonemd.getNSEC3Label(), nsec3s.records, nsec3s.signatures, validKeys); + csp.emplace(std::make_pair(zonemd.getNSEC3Label(), QType::NSEC3), nsec3s); } else { d_log->info("No NSEC(3) records and/or RRSIGS found to deny ZONEMD"); diff --git a/pdns/zonemd.cc b/pdns/zonemd.cc index 8aa876a1c4..5a604fb1e2 100644 --- a/pdns/zonemd.cc +++ b/pdns/zonemd.cc @@ -4,6 +4,7 @@ #include "dnssecinfra.hh" #include "sha.hh" #include "zoneparser-tng.hh" +#include "base32.hh" void pdns::ZoneMD::readRecords(ZoneParserTNG& zpt) { @@ -61,10 +62,12 @@ void pdns::ZoneMD::readRecords(ZoneParserTNG& zpt) d_nsecs.records.emplace(std::dynamic_pointer_cast(drc)); break; case QType::NSEC3: - d_nsecs3.records.emplace(std::dynamic_pointer_cast(drc)); break; } } + if (dnsResourceRecord.qtype == QType::NSEC3) { + d_nsecs3.records.emplace(std::dynamic_pointer_cast(drc)); + } RRSetKey_t key = std::pair(dnsResourceRecord.qname, dnsResourceRecord.qtype); d_resourceRecordSets[key].push_back(drc); d_resourceRecordSetTTLs[key] = dnsResourceRecord.ttl; @@ -118,9 +121,28 @@ void pdns::ZoneMD::readRecord(const DNSRecord& record) case QType::NSEC: d_nsecs.records.emplace(std::dynamic_pointer_cast(record.d_content)); break; + case QType::NSEC3: + // Handled below + break; + case QType::NSEC3PARAM: + auto param = *std::dynamic_pointer_cast(record.d_content); + d_nsec3label = d_zone; + d_nsec3label.prependRawLabel(toBase32Hex(hashQNameWithSalt(param, d_zone))); + // XXX We could filter the collected NSEC3 and their RRSIGs in d_nsecs3 at this point as we now know the right label + break; + } + } + if (d_nsec3label.empty() || record.d_name == d_nsec3label) { + switch (record.d_type) { case QType::NSEC3: d_nsecs3.records.emplace(std::dynamic_pointer_cast(record.d_content)); break; + case QType::RRSIG: + auto rrsig = std::dynamic_pointer_cast(record.d_content); + if (rrsig->d_type == QType::NSEC3) { + d_nsecs3.signatures.emplace_back(rrsig); + } + break; } } RRSetKey_t key = std::pair(record.d_name, record.d_type); diff --git a/pdns/zonemd.hh b/pdns/zonemd.hh index ea76663aae..df834130c1 100644 --- a/pdns/zonemd.hh +++ b/pdns/zonemd.hh @@ -92,6 +92,10 @@ public: return d_nsecs3; } + const DNSName& getNSEC3Label() const { + return d_nsec3label; + } + private: typedef std::pair RRSetKey_t; typedef std::vector> RRVector_t; @@ -130,6 +134,7 @@ private: std::vector> d_rrsigs; ContentSigPair d_nsecs; ContentSigPair d_nsecs3; + DNSName d_nsec3label; const DNSName d_zone; }; -- 2.47.2