From: Otto Moerbeek Date: Tue, 18 Aug 2020 09:34:01 +0000 (+0200) Subject: Allow IP (netmask) based RPZ trigger to have multiple records. X-Git-Tag: rec-4.4.0-beta1~18^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d8f1f4e662626aead2b74d943e71a386db2ba22b;p=thirdparty%2Fpdns.git Allow IP (netmask) based RPZ trigger to have multiple records. While there, refactor the name based code as well, so name based NS triggers can have multiple records. --- diff --git a/pdns/filterpo.cc b/pdns/filterpo.cc index 2de0102ac2..3c8220721c 100644 --- a/pdns/filterpo.cc +++ b/pdns/filterpo.cc @@ -311,33 +311,47 @@ void DNSFilterEngine::assureZones(size_t zone) d_zones.resize(zone+1); } -void DNSFilterEngine::Zone::addClientTrigger(const Netmask& nm, Policy&& pol) +void DNSFilterEngine::Zone::addToNameMap(std::unordered_map& map, const DNSName& n, Policy&& pol, bool ignoreDuplicate, PolicyType ptype) { - pol.d_zoneData = d_zoneData; - pol.d_type = PolicyType::ClientIP; - d_qpolAddr.insert(nm).second=std::move(pol); -} + auto it = map.find(n); -void DNSFilterEngine::Zone::addResponseTrigger(const Netmask& nm, Policy&& pol) -{ - pol.d_zoneData = d_zoneData; - pol.d_type = PolicyType::ResponseIP; - d_postpolAddr.insert(nm).second=std::move(pol); + if (it != map.end()) { + auto& existingPol = it->second; + + if (pol.d_kind != PolicyKind::Custom && !ignoreDuplicate) { + throw std::runtime_error("Adding a " + getTypeToString(ptype) + "-based filter policy of kind " + getKindToString(pol.d_kind) + " but a policy of kind " + getKindToString(existingPol.d_kind) + " already exists for the following name: " + n.toLogString()); + } + + if (existingPol.d_kind != PolicyKind::Custom && ignoreDuplicate) { + throw std::runtime_error("Adding a " + getTypeToString(ptype) + "-based filter policy of kind " + getKindToString(existingPol.d_kind) + " but there was already an existing policy for the following name: " + n.toLogString()); + } + + existingPol.d_custom.reserve(existingPol.d_custom.size() + pol.d_custom.size()); + + std::move(pol.d_custom.begin(), pol.d_custom.end(), std::back_inserter(existingPol.d_custom)); + } + else { + auto& qpol = map.insert({n, std::move(pol)}).first->second; + qpol.d_zoneData = d_zoneData; + qpol.d_type = ptype; + } } -void DNSFilterEngine::Zone::addQNameTrigger(const DNSName& n, Policy&& pol, bool ignoreDuplicate) +void DNSFilterEngine::Zone::addToNetmaskTree(NetmaskTree& nmt, const Netmask& nm, Policy&& pol, bool ignoreDuplicate, PolicyType ptype) { - auto it = d_qpolName.find(n); + bool exists = nmt.has_key(nm); - if (it != d_qpolName.end()) { - auto& existingPol = it->second; + if (exists) { + // XXX NetMaskTree's node_type has a non-const second, but lookup() returns a const node_type *, so we cannot modify second + // Should look into making lookup) return a non-const node_type *... + auto& existingPol = const_cast(nmt.lookup(nm)->second); if (pol.d_kind != PolicyKind::Custom && !ignoreDuplicate) { - throw std::runtime_error("Adding a QName-based filter policy of kind " + getKindToString(pol.d_kind) + " but a policy of kind " + getKindToString(existingPol.d_kind) + " already exists for the following QName: " + n.toLogString()); + throw std::runtime_error("Adding a " + getTypeToString(ptype) + "-based filter policy of kind " + getKindToString(pol.d_kind) + " but a policy of kind " + getKindToString(existingPol.d_kind) + " already exists for the following netmask: " + nm.toString()); } if (existingPol.d_kind != PolicyKind::Custom && ignoreDuplicate) { - throw std::runtime_error("Adding a QName-based filter policy of kind " + getKindToString(existingPol.d_kind) + " but there was already an existing policy for the following QName: " + n.toLogString()); + throw std::runtime_error("Adding a " + getTypeToString(ptype) + "-based filter policy of kind " + getKindToString(existingPol.d_kind) + " but there was already an existing policy for the following netmask: " + nm.toString()); } existingPol.d_custom.reserve(existingPol.d_custom.size() + pol.d_custom.size()); @@ -345,24 +359,35 @@ void DNSFilterEngine::Zone::addQNameTrigger(const DNSName& n, Policy&& pol, bool std::move(pol.d_custom.begin(), pol.d_custom.end(), std::back_inserter(existingPol.d_custom)); } else { - auto& qpol = d_qpolName.insert({n, std::move(pol)}).first->second; - qpol.d_zoneData = d_zoneData; - qpol.d_type = PolicyType::QName; + pol.d_zoneData = d_zoneData; + pol.d_type = ptype; + nmt.insert(nm).second = std::move(pol); } } -void DNSFilterEngine::Zone::addNSTrigger(const DNSName& n, Policy&& pol) +void DNSFilterEngine::Zone::addClientTrigger(const Netmask& nm, Policy&& pol, bool ignoreDuplicate) +{ + addToNetmaskTree(d_qpolAddr, nm, std::move(pol), ignoreDuplicate, PolicyType::ClientIP); +} + +void DNSFilterEngine::Zone::addResponseTrigger(const Netmask& nm, Policy&& pol, bool ignoreDuplicate) +{ + addToNetmaskTree(d_postpolAddr, nm, std::move(pol), ignoreDuplicate, PolicyType::ResponseIP); +} + +void DNSFilterEngine::Zone::addQNameTrigger(const DNSName& n, Policy&& pol, bool ignoreDuplicate) +{ + addToNameMap(d_qpolName, n, std::move(pol), ignoreDuplicate, PolicyType::QName); +} + +void DNSFilterEngine::Zone::addNSTrigger(const DNSName& n, Policy&& pol, bool ignoreDuplicate) { - pol.d_zoneData = d_zoneData; - pol.d_type = PolicyType::NSDName; - d_propolName.insert({n, std::move(pol)}); + addToNameMap(d_propolName, n, std::move(pol), ignoreDuplicate, PolicyType::NSDName); } -void DNSFilterEngine::Zone::addNSIPTrigger(const Netmask& nm, Policy&& pol) +void DNSFilterEngine::Zone::addNSIPTrigger(const Netmask& nm, Policy&& pol, bool ignoreDuplicate) { - pol.d_zoneData = d_zoneData; - pol.d_type = PolicyType::NSIP; - d_propolNSAddr.insert(nm).second = std::move(pol); + addToNetmaskTree(d_propolNSAddr, nm, std::move(pol), ignoreDuplicate, PolicyType::NSIP); } bool DNSFilterEngine::Zone::rmClientTrigger(const Netmask& nm, const Policy& pol) diff --git a/pdns/filterpo.hh b/pdns/filterpo.hh index fc3287b474..e726968e4e 100644 --- a/pdns/filterpo.hh +++ b/pdns/filterpo.hh @@ -230,11 +230,11 @@ public: void dump(FILE * fp) const; - void addClientTrigger(const Netmask& nm, Policy&& pol); - void addQNameTrigger(const DNSName& nm, Policy&& pol, bool ignoreDuplicate=false); - void addNSTrigger(const DNSName& dn, Policy&& pol); - void addNSIPTrigger(const Netmask& nm, Policy&& pol); - void addResponseTrigger(const Netmask& nm, Policy&& pol); + void addClientTrigger(const Netmask& nm, Policy&& pol, bool ignoreDuplicate = false); + void addQNameTrigger(const DNSName& nm, Policy&& pol, bool ignoreDuplicate = false); + void addNSTrigger(const DNSName& dn, Policy&& pol, bool ignoreDuplicate = false); + void addNSIPTrigger(const Netmask& nm, Policy&& pol, bool ignoreDuplicate = false); + void addResponseTrigger(const Netmask& nm, Policy&& pol, bool ignoreDuplicate = false); bool rmClientTrigger(const Netmask& nm, const Policy& pol); bool rmQNameTrigger(const DNSName& nm, const Policy& pol); @@ -276,6 +276,8 @@ public: } private: + void addToNetmaskTree(NetmaskTree& nmt, const Netmask& nm, Policy&& pol, bool ignoreDuplicate, PolicyType ptype); + void addToNameMap(std::unordered_map& map, const DNSName& n, Policy&& pol, bool ignoreDuplicate, PolicyType ptype); static DNSName maskToRPZ(const Netmask& nm); static bool findExactNamedPolicy(const std::unordered_map& polmap, const DNSName& qname, DNSFilterEngine::Policy& pol); static bool findNamedPolicy(const std::unordered_map& polmap, const DNSName& qname, DNSFilterEngine::Policy& pol); diff --git a/pdns/rpzloader.cc b/pdns/rpzloader.cc index 5814f26296..212c926052 100644 --- a/pdns/rpzloader.cc +++ b/pdns/rpzloader.cc @@ -147,14 +147,14 @@ static void RPZRecordToPolicy(const DNSRecord& dr, std::shared_ptraddNSTrigger(filt, std::move(pol)); + zone->addNSTrigger(filt, std::move(pol), defpolApplied); else zone->rmNSTrigger(filt, std::move(pol)); } else if(dr.d_name.isPartOf(rpzClientIP)) { DNSName filt=dr.d_name.makeRelative(rpzClientIP); auto nm=makeNetmaskFromRPZ(filt); if(addOrRemove) - zone->addClientTrigger(nm, std::move(pol)); + zone->addClientTrigger(nm, std::move(pol), defpolApplied); else zone->rmClientTrigger(nm, std::move(pol)); @@ -163,14 +163,14 @@ static void RPZRecordToPolicy(const DNSRecord& dr, std::shared_ptraddResponseTrigger(nm, std::move(pol)); + zone->addResponseTrigger(nm, std::move(pol), defpolApplied); else zone->rmResponseTrigger(nm, std::move(pol)); } else if(dr.d_name.isPartOf(rpzNSIP)) { DNSName filt=dr.d_name.makeRelative(rpzNSIP); auto nm=makeNetmaskFromRPZ(filt); if(addOrRemove) - zone->addNSIPTrigger(nm, std::move(pol)); + zone->addNSIPTrigger(nm, std::move(pol), defpolApplied); else zone->rmNSIPTrigger(nm, std::move(pol)); } else {