From: Otto Moerbeek Date: Tue, 30 May 2023 11:49:03 +0000 (+0200) Subject: rec: add SOA to RPZ result if configured to do so X-Git-Tag: rec-4.10.0-alpha0~7^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=46572de5ba3365fe446e24457299bbd00b5f2d3e;p=thirdparty%2Fpdns.git rec: add SOA to RPZ result if configured to do so Fixes #8232 --- diff --git a/pdns/recursordist/filterpo.hh b/pdns/recursordist/filterpo.hh index 4d11af52cc..b5aa306bf7 100644 --- a/pdns/recursordist/filterpo.hh +++ b/pdns/recursordist/filterpo.hh @@ -28,6 +28,7 @@ #include #include #include +#include /* This class implements a filtering policy that is able to fully implement RPZ, but is not bound to it. In other words, it is generic enough to support RPZ, but could get its data from other places. @@ -96,9 +97,11 @@ public: std::unordered_set d_tags; std::string d_name; std::string d_extendedErrorExtra; + DNSRecord d_soa{}; boost::optional d_extendedErrorCode{boost::none}; Priority d_priority{maximumPriority}; bool d_policyOverridesGettag{true}; + bool d_includeSOA{false}; }; struct Policy @@ -168,6 +171,23 @@ public: return true; } + [[nodiscard]] bool getSOA(DNSRecord& rec) const + { + if (d_zoneData) { + rec = d_zoneData->d_soa; + return true; + } + return false; + } + + [[nodiscard]] bool includeSOA() const + { + if (d_zoneData) { + return d_zoneData->d_includeSOA; + } + return false; + } + bool wasHit() const { return (d_type != DNSFilterEngine::PolicyType::None && d_kind != DNSFilterEngine::PolicyKind::NoAction); @@ -187,6 +207,15 @@ public: PolicyKind d_kind; PolicyType d_type; + void addSOAtoRPZResult(vector& ret) const + { + DNSRecord soa{}; + if (includeSOA() && getSOA(soa)) { + soa.d_place = DNSResourceRecord::ADDITIONAL; + ret.emplace_back(soa); + } + } + private: DNSRecord getRecordFromCustom(const DNSName& qname, const std::shared_ptr& custom) const; }; @@ -243,7 +272,10 @@ public: { d_zoneData->d_extendedErrorExtra = extra; } - + void setSOA(DNSRecord soa) + { + d_zoneData->d_soa = std::move(soa); + } const std::string& getName() const { return d_zoneData->d_name; @@ -269,6 +301,11 @@ public: return d_qpolAddr.size() + d_postpolAddr.size() + d_propolName.size() + d_propolNSAddr.size() + d_qpolName.size(); } + void setIncludeSOA(bool flag) + { + d_zoneData->d_includeSOA = flag; + } + void dump(FILE* fp) const; void addClientTrigger(const Netmask& nm, Policy&& pol, bool ignoreDuplicate = false); diff --git a/pdns/recursordist/pdns_recursor.cc b/pdns/recursordist/pdns_recursor.cc index e1dbcf7bd4..9df794155c 100644 --- a/pdns/recursordist/pdns_recursor.cc +++ b/pdns/recursordist/pdns_recursor.cc @@ -524,17 +524,20 @@ static PolicyResult handlePolicyHit(const DNSFilterEngine::Policy& appliedPolicy case DNSFilterEngine::PolicyKind::NXDOMAIN: ret.clear(); + appliedPolicy.addSOAtoRPZResult(ret); res = RCode::NXDomain; return PolicyResult::HaveAnswer; case DNSFilterEngine::PolicyKind::NODATA: ret.clear(); + appliedPolicy.addSOAtoRPZResult(ret); res = RCode::NoError; return PolicyResult::HaveAnswer; case DNSFilterEngine::PolicyKind::Truncate: if (!dc->d_tcp) { ret.clear(); + appliedPolicy.addSOAtoRPZResult(ret); res = RCode::NoError; pw.getHeader()->tc = 1; return PolicyResult::HaveAnswer; @@ -570,6 +573,7 @@ static PolicyResult handlePolicyHit(const DNSFilterEngine::Policy& appliedPolicy } } + appliedPolicy.addSOAtoRPZResult(ret); return PolicyResult::HaveAnswer; } } diff --git a/pdns/recursordist/rec-lua-conf.cc b/pdns/recursordist/rec-lua-conf.cc index c384bd65b2..78e5cb90f3 100644 --- a/pdns/recursordist/rec-lua-conf.cc +++ b/pdns/recursordist/rec-lua-conf.cc @@ -153,6 +153,9 @@ static void parseRPZParameters(rpzOptions_t& have, std::shared_ptrsetExtendedErrorExtra(boost::get(have["extendedErrorExtra"])); } } + if (have.count("includeSOA")) { + zone->setIncludeSOA(boost::get(have["includeSOA"])); + } } typedef std::unordered_map>>> protobufOptions_t; diff --git a/pdns/recursordist/rpzloader.cc b/pdns/recursordist/rpzloader.cc index f81ef2fbce..c99480fea3 100644 --- a/pdns/recursordist/rpzloader.cc +++ b/pdns/recursordist/rpzloader.cc @@ -226,6 +226,7 @@ static shared_ptr loadRPZFromServer(Logr::log_t plogger, dr.d_name.makeUsRelative(zoneName); if (dr.d_type == QType::SOA) { sr = getRR(dr); + zone->setSOA(dr); continue; } @@ -293,6 +294,7 @@ std::shared_ptr loadRPZFromFile(const std::string& fname zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps")); zpt.setMaxIncludes(::arg().asNum("max-include-depth")); DNSResourceRecord drr; + DNSRecord soaRecord; DNSName domain; auto log = g_slog->withName("rpz")->withValues("file", Logging::Loggable(fname), "zone", Logging::Loggable(zone->getName())); while (zpt.get(drr)) { @@ -304,6 +306,7 @@ std::shared_ptr loadRPZFromFile(const std::string& fname sr = getRR(dr); domain = dr.d_name; zone->setDomain(domain); + soaRecord = dr; } else if (dr.d_type == QType::NS) { continue; @@ -320,6 +323,7 @@ std::shared_ptr loadRPZFromFile(const std::string& fname if (sr != nullptr) { zone->setRefresh(sr->d_st.refresh); + zone->setSOA(soaRecord); setRPZZoneNewState(zone->getName(), sr->d_st.serial, zone->size(), true, false); } return sr; diff --git a/pdns/recursordist/syncres.cc b/pdns/recursordist/syncres.cc index a2cba559bf..1472266b89 100644 --- a/pdns/recursordist/syncres.cc +++ b/pdns/recursordist/syncres.cc @@ -3230,12 +3230,14 @@ void SyncRes::handlePolicyHit(const std::string& prefix, const DNSName& qname, c case DNSFilterEngine::PolicyKind::NXDOMAIN: ret.clear(); + d_appliedPolicy.addSOAtoRPZResult(ret); rcode = RCode::NXDomain; done = true; return; case DNSFilterEngine::PolicyKind::NODATA: ret.clear(); + d_appliedPolicy.addSOAtoRPZResult(ret); rcode = RCode::NoError; done = true; return; @@ -3243,6 +3245,7 @@ void SyncRes::handlePolicyHit(const std::string& prefix, const DNSName& qname, c case DNSFilterEngine::PolicyKind::Truncate: if (!d_queryReceivedOverTCP) { ret.clear(); + d_appliedPolicy.addSOAtoRPZResult(ret); rcode = RCode::NoError; throw SendTruncatedAnswerException(); } @@ -3270,6 +3273,7 @@ void SyncRes::handlePolicyHit(const std::string& prefix, const DNSName& qname, c } } } + d_appliedPolicy.addSOAtoRPZResult(ret); } } }