]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: Add a 'prerpz' hook to be able to discard selected RPZ policies
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 12 Aug 2016 16:35:08 +0000 (18:35 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 25 Aug 2016 08:50:25 +0000 (10:50 +0200)
pdns/filterpo.cc
pdns/filterpo.hh
pdns/lua-recursor4.cc
pdns/lua-recursor4.hh
pdns/pdns_recursor.cc
pdns/rec-lua-conf.cc
pdns/reczones.cc
pdns/rpzloader.cc
pdns/rpzloader.hh
pdns/syncres.cc
pdns/syncres.hh

index d24aa83681af03a1c573cb9316d82144d1e66d42..4c5877902829f7827e6c81c20723d3f9c0588210 100644 (file)
@@ -38,7 +38,7 @@ bool findNamedPolicy(const map<DNSName, DNSFilterEngine::Policy>& polmap, const
                 *.com.
                     *.
    */
+
   bool first=true;
   map<DNSName, DNSFilterEngine::Policy>::const_iterator iter;
   do {
@@ -60,11 +60,15 @@ bool findNamedPolicy(const map<DNSName, DNSFilterEngine::Policy>& polmap, const
   return false;
 }
 
-DNSFilterEngine::Policy DNSFilterEngine::getProcessingPolicy(const DNSName& qname) const
+DNSFilterEngine::Policy DNSFilterEngine::getProcessingPolicy(const DNSName& qname, const std::unordered_map<std::string,bool>& discardedPolicies) const
 {
   //  cout<<"Got question for nameserver name "<<qname<<endl;
-  Policy pol{PolicyKind::NoAction, nullptr, "", 0};
+  Policy pol{PolicyKind::NoAction, nullptr, nullptr, 0};
   for(const auto& z : d_zones) {
+    if(z.name && discardedPolicies.find(*z.name) != discardedPolicies.end()) {
+      continue;
+    }
+
     if(findNamedPolicy(z.propolName, qname, pol)) {
       //      cerr<<"Had a hit on the nameserver ("<<qname<<") used to process the query"<<endl;
       return pol;
@@ -73,24 +77,31 @@ DNSFilterEngine::Policy DNSFilterEngine::getProcessingPolicy(const DNSName& qnam
   return pol;
 }
 
-DNSFilterEngine::Policy DNSFilterEngine::getProcessingPolicy(const ComboAddress& address) const
+DNSFilterEngine::Policy DNSFilterEngine::getProcessingPolicy(const ComboAddress& address, const std::unordered_map<std::string,bool>& discardedPolicies) const
 {
   //  cout<<"Got question for nameserver IP "<<address.toString()<<endl;
   for(const auto& z : d_zones) {
+    if(z.name && discardedPolicies.find(*z.name) != discardedPolicies.end()) {
+      continue;
+    }
+
     if(auto fnd=z.propolNSAddr.lookup(address)) {
       //      cerr<<"Had a hit on the nameserver ("<<address.toString()<<") used to process the query"<<endl;
       return fnd->second;;
     }
   }
-  return Policy{PolicyKind::NoAction, nullptr, "", 0};
+  return Policy{PolicyKind::NoAction, nullptr, nullptr, 0};
 }
 
-DNSFilterEngine::Policy DNSFilterEngine::getQueryPolicy(const DNSName& qname, const ComboAddress& ca) const
+DNSFilterEngine::Policy DNSFilterEngine::getQueryPolicy(const DNSName& qname, const ComboAddress& ca, const std::unordered_map<std::string,bool>& discardedPolicies) const
 {
   //  cout<<"Got question for "<<qname<<" from "<<ca.toString()<<endl;
-
-  Policy pol{PolicyKind::NoAction, nullptr, "", 0};
+  Policy pol{PolicyKind::NoAction, nullptr, nullptr, 0};
   for(const auto& z : d_zones) {
+    if(z.name && discardedPolicies.find(*z.name) != discardedPolicies.end()) {
+      continue;
+    }
+
     if(findNamedPolicy(z.qpolName, qname, pol)) {
       //      cerr<<"Had a hit on the name of the query"<<endl;
       return pol;
@@ -105,10 +116,9 @@ DNSFilterEngine::Policy DNSFilterEngine::getQueryPolicy(const DNSName& qname, co
   return pol;
 }
 
-DNSFilterEngine::Policy DNSFilterEngine::getPostPolicy(const vector<DNSRecord>& records) const
+DNSFilterEngine::Policy DNSFilterEngine::getPostPolicy(const vector<DNSRecord>& records, const std::unordered_map<std::string,bool>& discardedPolicies) const
 {
   ComboAddress ca;
-
   for(const auto& r : records) {
     if(r.d_place != DNSResourceRecord::ANSWER) 
       continue;
@@ -126,20 +136,24 @@ DNSFilterEngine::Policy DNSFilterEngine::getPostPolicy(const vector<DNSRecord>&
       continue;
 
     for(const auto& z : d_zones) {
+      if(z.name && discardedPolicies.find(*z.name) != discardedPolicies.end()) {
+        continue;
+      }
+
       if(auto fnd=z.postpolAddr.lookup(ca))
        return fnd->second;
     }
   }
-  return Policy{PolicyKind::NoAction, nullptr, "", 0};
+  return Policy{PolicyKind::NoAction, nullptr, nullptr, 0};
 }
 
-void DNSFilterEngine::assureZones(int zone)
+void DNSFilterEngine::assureZones(size_t zone)
 {
-  if((int)d_zones.size() <= zone)
+  if(d_zones.size() <= zone)
     d_zones.resize(zone+1);
 }
 
-void DNSFilterEngine::clear(int zone)
+void DNSFilterEngine::clear(size_t zone)
 {
   assureZones(zone);
   auto& z = d_zones[zone];
@@ -149,37 +163,42 @@ void DNSFilterEngine::clear(int zone)
   z.qpolName.clear();
 }
 
-void DNSFilterEngine::addClientTrigger(const Netmask& nm, Policy pol, int zone)
+void DNSFilterEngine::addClientTrigger(const Netmask& nm, Policy pol, size_t zone)
 {
   assureZones(zone);
+  pol.d_name = d_zones[zone].name;
   d_zones[zone].qpolAddr.insert(nm).second=pol;
 }
 
-void DNSFilterEngine::addResponseTrigger(const Netmask& nm, Policy pol, int zone)
+void DNSFilterEngine::addResponseTrigger(const Netmask& nm, Policy pol, size_t zone)
 {
   assureZones(zone);
+  pol.d_name = d_zones[zone].name;
   d_zones[zone].postpolAddr.insert(nm).second=pol;
 }
 
-void DNSFilterEngine::addQNameTrigger(const DNSName& n, Policy pol, int zone)
+void DNSFilterEngine::addQNameTrigger(const DNSName& n, Policy pol, size_t zone)
 {
   assureZones(zone);
+  pol.d_name = d_zones[zone].name;
   d_zones[zone].qpolName[n]=pol;
 }
 
-void DNSFilterEngine::addNSTrigger(const DNSName& n, Policy pol, int zone)
+void DNSFilterEngine::addNSTrigger(const DNSName& n, Policy pol, size_t zone)
 {
   assureZones(zone);
+  pol.d_name = d_zones[zone].name;
   d_zones[zone].propolName[n]=pol;
 }
 
-void DNSFilterEngine::addNSIPTrigger(const Netmask& nm, Policy pol, int zone)
+void DNSFilterEngine::addNSIPTrigger(const Netmask& nm, Policy pol, size_t zone)
 {
   assureZones(zone);
+  pol.d_name = d_zones[zone].name;
   d_zones[zone].propolNSAddr.insert(nm).second = pol;
 }
 
-bool DNSFilterEngine::rmClientTrigger(const Netmask& nm, Policy pol, int zone)
+bool DNSFilterEngine::rmClientTrigger(const Netmask& nm, Policy pol, size_t zone)
 {
   assureZones(zone);
 
@@ -188,7 +207,7 @@ bool DNSFilterEngine::rmClientTrigger(const Netmask& nm, Policy pol, int zone)
   return true;
 }
 
-bool DNSFilterEngine::rmResponseTrigger(const Netmask& nm, Policy pol, int zone)
+bool DNSFilterEngine::rmResponseTrigger(const Netmask& nm, Policy pol, size_t zone)
 {
   assureZones(zone);
   auto& postpols = d_zones[zone].postpolAddr;
@@ -196,21 +215,21 @@ bool DNSFilterEngine::rmResponseTrigger(const Netmask& nm, Policy pol, int zone)
   return true;
 }
 
-bool DNSFilterEngine::rmQNameTrigger(const DNSName& n, Policy pol, int zone)
+bool DNSFilterEngine::rmQNameTrigger(const DNSName& n, Policy pol, size_t zone)
 {
   assureZones(zone);
   d_zones[zone].qpolName.erase(n); // XXX verify we had identical policy?
   return true;
 }
 
-bool DNSFilterEngine::rmNSTrigger(const DNSName& n, Policy pol, int zone)
+bool DNSFilterEngine::rmNSTrigger(const DNSName& n, Policy pol, size_t zone)
 {
   assureZones(zone);
   d_zones[zone].propolName.erase(n); // XXX verify policy matched? =pol;
   return true;
 }
 
-bool DNSFilterEngine::rmNSIPTrigger(const Netmask& nm, Policy pol, int zone)
+bool DNSFilterEngine::rmNSIPTrigger(const Netmask& nm, Policy pol, size_t zone)
 {
   assureZones(zone);
   auto& pols = d_zones[zone].propolNSAddr;
index 4cabe524cc8b352e8cef52a52dae6b89c7f431c4..b876f931e539dab8cd2364030c9553437654a6a8 100644 (file)
@@ -24,6 +24,7 @@
 #include "dns.hh"
 #include "dnsparser.hh"
 #include <map>
+#include <unordered_map>
 
 /* 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.
@@ -72,42 +73,48 @@ public:
     }
     PolicyKind d_kind;
     std::shared_ptr<DNSRecordContent> d_custom;
-    std::string d_name;
+    std::shared_ptr<std::string> d_name;
     int d_ttl;
   };
 
   DNSFilterEngine();
   void clear();
-  void clear(int zone);
-  void addClientTrigger(const Netmask& nm, Policy pol, int zone=0);
-  void addQNameTrigger(const DNSName& nm, Policy pol, int zone=0);
-  void addNSTrigger(const DNSName& dn, Policy pol, int zone=0);
-  void addNSIPTrigger(const Netmask& nm, Policy pol, int zone=0);
-  void addResponseTrigger(const Netmask& nm, Policy pol, int zone=0);
+  void clear(size_t zone);
+  void addClientTrigger(const Netmask& nm, Policy pol, size_t zone);
+  void addQNameTrigger(const DNSName& nm, Policy pol, size_t zone);
+  void addNSTrigger(const DNSName& dn, Policy pol, size_t zone);
+  void addNSIPTrigger(const Netmask& nm, Policy pol, size_t zone);
+  void addResponseTrigger(const Netmask& nm, Policy pol, size_t zone);
 
-  bool rmClientTrigger(const Netmask& nm, Policy pol, int zone=0);
-  bool rmQNameTrigger(const DNSName& nm, Policy pol, int zone=0);
-  bool rmNSTrigger(const DNSName& dn, Policy pol, int zone=0);
-  bool rmNSIPTrigger(const Netmask& nm, Policy pol, int zone=0);
-  bool rmResponseTrigger(const Netmask& nm, Policy pol, int zone=0);
+  bool rmClientTrigger(const Netmask& nm, Policy pol, size_t zone);
+  bool rmQNameTrigger(const DNSName& nm, Policy pol, size_t zone);
+  bool rmNSTrigger(const DNSName& dn, Policy pol, size_t zone);
+  bool rmNSIPTrigger(const Netmask& nm, Policy pol, size_t zone);
+  bool rmResponseTrigger(const Netmask& nm, Policy pol, size_t zone);
 
 
-  Policy getQueryPolicy(const DNSName& qname, const ComboAddress& nm) const;
-  Policy getProcessingPolicy(const DNSName& qname) const;
-  Policy getProcessingPolicy(const ComboAddress& address) const;
-  Policy getPostPolicy(const vector<DNSRecord>& records) const;
+  Policy getQueryPolicy(const DNSName& qname, const ComboAddress& nm, const std::unordered_map<std::string,bool>& discardedPolicies) const;
+  Policy getProcessingPolicy(const DNSName& qname, const std::unordered_map<std::string,bool>& discardedPolicies) const;
+  Policy getProcessingPolicy(const ComboAddress& address, const std::unordered_map<std::string,bool>& discardedPolicies) const;
+  Policy getPostPolicy(const vector<DNSRecord>& records, const std::unordered_map<std::string,bool>& discardedPolicies) const;
 
   size_t size() {
     return d_zones.size();
   }
+  void setPolicyName(size_t zoneIdx, std::string name)
+  {
+    assureZones(zoneIdx);
+    d_zones[zoneIdx].name = std::make_shared<std::string>(name);
+  }
 private:
-  void assureZones(int zone);
+  void assureZones(size_t zone);
   struct Zone {
     std::map<DNSName, Policy> qpolName;   // QNAME trigger (RPZ)
     NetmaskTree<Policy> qpolAddr;         // Source address
     std::map<DNSName, Policy> propolName; // NSDNAME (RPZ)
     NetmaskTree<Policy> propolNSAddr;     // NSIP (RPZ)
     NetmaskTree<Policy> postpolAddr;      // IP trigger (RPZ)
+    std::shared_ptr<std::string> name;
   };
   vector<Zone> d_zones;
 
index c3e416f74620e46a260d70b7cc3bff81d7b4a2e5..8afb2c02b97b56eb916f6688b7a2329f462b1225 100644 (file)
@@ -51,6 +51,10 @@ bool RecursorLua4::postresolve(const ComboAddress& remote,const ComboAddress& lo
   return false;
 }
 
+bool RecursorLua4::prerpz(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, int& ret, bool* wantsRPZ, std::unordered_map<std::string,bool>* discardedPolicies)
+{
+}
+
 bool RecursorLua4::preresolve(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& ret, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, DNSFilterEngine::Policy* appliedPolicy, std::vector<std::string>* policyTags, int& res, bool* variable, bool* wantsRPZ)
 {
   return false;
@@ -419,6 +423,12 @@ RecursorLua4::RecursorLua4(const std::string& fname)
       return ret;
     });
 
+  d_lw->registerFunction<void(DNSQuestion::*)(const std::string&)>("discardPolicy", [](DNSQuestion& dq, const std::string& policy) {
+      if (dq.discardedPolicies) {
+        (*dq.discardedPolicies)[policy] = true;
+      }
+    });
+
   d_lw->writeFunction("newDS", []() { return SuffixMatchNode(); });
   d_lw->registerFunction<void(SuffixMatchNode::*)(boost::variant<string,DNSName, vector<pair<unsigned int,string> > >)>(
     "add",
@@ -512,6 +522,7 @@ RecursorLua4::RecursorLua4(const std::string& fname)
   }    
   d_lw->executeCode(ifs);
 
+  d_prerpz = d_lw->readVariable<boost::optional<luacall_t>>("prerpz").get_value_or(0);
   d_preresolve = d_lw->readVariable<boost::optional<luacall_t>>("preresolve").get_value_or(0);
   d_nodata = d_lw->readVariable<boost::optional<luacall_t>>("nodata").get_value_or(0);
   d_nxdomain = d_lw->readVariable<boost::optional<luacall_t>>("nxdomain").get_value_or(0);
@@ -522,29 +533,34 @@ RecursorLua4::RecursorLua4(const std::string& fname)
   d_gettag = d_lw->readVariable<boost::optional<gettag_t>>("gettag").get_value_or(0);
 }
 
+bool RecursorLua4::prerpz(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, int& ret, bool* wantsRPZ, std::unordered_map<std::string,bool>* discardedPolicies)
+{
+  return genhook(d_prerpz, remote, local, query, qtype, isTcp, res, ednsOpts, tag, nullptr, nullptr, ret, nullptr, wantsRPZ, discardedPolicies);
+}
+
 bool RecursorLua4::preresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, DNSFilterEngine::Policy* appliedPolicy, std::vector<std::string>* policyTags, int& ret, bool* variable, bool* wantsRPZ)
 {
-  return genhook(d_preresolve, remote, local, query, qtype, isTcp, res, ednsOpts, tag, appliedPolicy, policyTags, ret, variable, wantsRPZ);
+  return genhook(d_preresolve, remote, local, query, qtype, isTcp, res, ednsOpts, tag, appliedPolicy, policyTags, ret, variable, wantsRPZ, nullptr);
 }
 
 bool RecursorLua4::nxdomain(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret, bool* variable)
 {
-  return genhook(d_nxdomain, remote, local, query, qtype, isTcp, res, 0, 0, nullptr, nullptr, ret, variable, 0);
+  return genhook(d_nxdomain, remote, local, query, qtype, isTcp, res, 0, 0, nullptr, nullptr, ret, variable, 0, nullptr);
 }
 
 bool RecursorLua4::nodata(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret, bool* variable)
 {
-  return genhook(d_nodata, remote, local, query, qtype, isTcp, res, 0, 0, nullptr, nullptr, ret, variable, 0);
+  return genhook(d_nodata, remote, local, query, qtype, isTcp, res, 0, 0, nullptr, nullptr, ret, variable, 0, nullptr);
 }
 
 bool RecursorLua4::postresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, DNSFilterEngine::Policy* appliedPolicy, std::vector<std::string>* policyTags, int& ret, bool* variable)
 {
-  return genhook(d_postresolve, remote, local, query, qtype, isTcp, res, 0, 0, appliedPolicy, policyTags, ret, variable, 0);
+  return genhook(d_postresolve, remote, local, query, qtype, isTcp, res, 0, 0, appliedPolicy, policyTags, ret, variable, 0, nullptr);
 }
 
 bool RecursorLua4::preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret)
 {
-  return genhook(d_preoutquery, ns, requestor, query, qtype, isTcp, res, 0, 0, nullptr, nullptr, ret, 0, 0);
+  return genhook(d_preoutquery, ns, requestor, query, qtype, isTcp, res, 0, 0, nullptr, nullptr, ret, 0, 0, nullptr);
 }
 
 bool RecursorLua4::ipfilter(const ComboAddress& remote, const ComboAddress& local, const struct dnsheader& dh)
@@ -572,7 +588,7 @@ int RecursorLua4::gettag(const ComboAddress& remote, const Netmask& ednssubnet,
   return 0;
 }
 
-bool RecursorLua4::genhook(luacall_t& func, const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, DNSFilterEngine::Policy* appliedPolicy, std::vector<std::string>* policyTags, int& ret, bool* variable, bool* wantsRPZ)
+bool RecursorLua4::genhook(luacall_t& func, const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, DNSFilterEngine::Policy* appliedPolicy, std::vector<std::string>* policyTags, int& ret, bool* variable, bool* wantsRPZ, std::unordered_map<std::string,bool>* discardedPolicies)
 {
   if(!func)
     return false;
@@ -589,10 +605,11 @@ bool RecursorLua4::genhook(luacall_t& func, const ComboAddress& remote,const Com
   dq->rcode = ret;
   dq->policyTags = policyTags;
   dq->appliedPolicy = appliedPolicy;
-  dq->wantsRPZ = wantsRPZ;
+  if(wantsRPZ) dq->wantsRPZ = *wantsRPZ;
+  if(discardedPolicies) dq->discardedPolicies = discardedPolicies;
   bool handled=func(dq);
   if(variable) *variable |= dq->variable; // could still be set to indicate this *name* is variable, even if not 'handled'
-  *wantsRPZ = dq->wantsRPZ; // Even if we did not handle the query, RPZ could be disabled
+  if(wantsRPZ) *wantsRPZ = dq->wantsRPZ; // Even if we did not handle the query, RPZ could be disabled
 
   if(handled) {
 loop:;
index 56e51fff9b5ba8f7ec123b0429c0db3cb647a514..a684ee0ae3563d73d9d4aced21672a31367a1673 100644 (file)
@@ -44,6 +44,7 @@ private:
 public:
   explicit RecursorLua4(const std::string& fname);
   ~RecursorLua4(); // this is so unique_ptr works with an incomplete type
+  bool prerpz(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, int& ret, bool* wantsRPZ, std::unordered_map<std::string,bool>* discardedPolicies);
   bool preresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, DNSFilterEngine::Policy* appliedPolicy, std::vector<std::string>* policyTags, int& ret, bool* variable, bool* wantsRPZ);
   bool nxdomain(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret, bool* variable);
   bool nodata(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret, bool* variable);
@@ -90,13 +91,14 @@ private:
 
     DNSFilterEngine::Policy* appliedPolicy;
     std::vector<std::string>* policyTags;
+    std::unordered_map<std::string,bool>* discardedPolicies;
     bool isTcp;
-    bool wantsRPZ;
+    bool wantsRPZ{true};
   };
 
   typedef std::function<bool(std::shared_ptr<DNSQuestion>)> luacall_t;
-  luacall_t d_preresolve, d_nxdomain, d_nodata, d_postresolve, d_preoutquery, d_postoutquery;
-  bool genhook(luacall_t& func, const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res,  const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, DNSFilterEngine::Policy* appliedPolicy, std::vector<std::string>* policyTags, int& ret, bool* variable, bool* wantsRPZ);
+  luacall_t d_prerpz, d_preresolve, d_nxdomain, d_nodata, d_postresolve, d_preoutquery, d_postoutquery;
+  bool genhook(luacall_t& func, const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res,  const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, DNSFilterEngine::Policy* appliedPolicy, std::vector<std::string>* policyTags, int& ret, bool* variable, bool* wantsRPZ, std::unordered_map<std::string,bool>* discardedPolicies);
   typedef std::function<bool(ComboAddress,ComboAddress, struct dnsheader)> ipfilter_t;
   ipfilter_t d_ipfilter;
 };
index 82faf81453db22d48e67e0388ea12ba35436cdb2..cad6d514e92a9aae33a86df7dfdf1e69ed6113fd 100644 (file)
@@ -618,8 +618,8 @@ static void protobufLogQuery(const std::shared_ptr<RemoteLogger>& logger, uint8_
   RecProtoBufMessage message(DNSProtoBufMessage::Query, uniqueId, &requestor, &local, qname, qtype, qclass, id, tcp, len);
   message.setEDNSSubnet(ednssubnet, ednssubnet.isIpv4() ? maskV4 : maskV6);
 
-  if (!appliedPolicy.d_name.empty()) {
-    message.setAppliedPolicy(appliedPolicy.d_name);
+  if (appliedPolicy.d_name && !appliedPolicy.d_name->empty()) {
+    message.setAppliedPolicy(*appliedPolicy.d_name);
   }
   if (!policyTags.empty()) {
     message.setPolicyTags(policyTags);
@@ -741,8 +741,14 @@ void startDoResolve(void *p)
     if(!dc->d_mdp.d_header.rd)
       sr.setCacheOnly();
 
+    if (t_pdl->get()) {
+      (*t_pdl)->prerpz(dc->d_remote, dc->d_local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_tcp, ret, dc->d_ednsOpts.empty() ? 0 : &dc->d_ednsOpts, dc->d_tag, res, &wantsRPZ, &sr.d_discardedPolicies);
+    }
+
     // Check if the query has a policy attached to it
-    dfepol = luaconfsLocal->dfe.getQueryPolicy(dc->d_mdp.d_qname, dc->d_remote);
+    if (wantsRPZ) {
+      dfepol = luaconfsLocal->dfe.getQueryPolicy(dc->d_mdp.d_qname, dc->d_remote, sr.d_discardedPolicies);
+    }
     appliedPolicy = dfepol;
 
     // if there is a RecursorLua active, and it 'took' the query in preResolve, we don't launch beginResolve
@@ -846,7 +852,7 @@ void startDoResolve(void *p)
       }
 
       if (wantsRPZ) {
-        dfepol = luaconfsLocal->dfe.getPostPolicy(ret);
+        dfepol = luaconfsLocal->dfe.getPostPolicy(ret, sr.d_discardedPolicies);
         appliedPolicy = dfepol;
       }
 
@@ -1047,7 +1053,9 @@ void startDoResolve(void *p)
     if (luaconfsLocal->protobufServer) {
       pbMessage.setBytes(packet.size());
       pbMessage.setResponseCode(pw.getHeader()->rcode);
-      pbMessage.setAppliedPolicy(appliedPolicy.d_name);
+      if (appliedPolicy.d_name) {
+        pbMessage.setAppliedPolicy(*appliedPolicy.d_name);
+      }
       pbMessage.setPolicyTags(dc->d_policyTags);
       pbMessage.setQueryTime(dc->d_now.tv_sec, dc->d_now.tv_usec);
       protobufLogResponse(luaconfsLocal->protobufServer, pbMessage);
index c362f5276ab4e664c0867392e19f979e9a8120b7..d50a4953a999be3185df6d43845dc28dfed0ec37 100644 (file)
@@ -101,7 +101,7 @@ void loadRecursorLuaConfig(const std::string& fname)
          if(have.count("defpol")) {
            defpol=DNSFilterEngine::Policy();
            defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get<int>(constGet(have, "defpol"));
-           defpol->d_name = polName;
+           defpol->d_name = std::make_shared<std::string>(polName);
            if(defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) {
              defpol->d_custom=
                shared_ptr<DNSRecordContent>(
@@ -117,8 +117,10 @@ void loadRecursorLuaConfig(const std::string& fname)
            }
          }
        }
+        const size_t zoneIdx = lci.dfe.size();
         theL()<<Logger::Warning<<"Loading RPZ from file '"<<fname<<"'"<<endl;
-       loadRPZFromFile(fname, lci.dfe, polName, defpol, 0);
+        lci.dfe.setPolicyName(zoneIdx, polName);
+       loadRPZFromFile(fname, lci.dfe, defpol, zoneIdx);
         theL()<<Logger::Warning<<"Done loading RPZ from file '"<<fname<<"'"<<endl;
       }
       catch(std::exception& e) {
@@ -144,7 +146,7 @@ void loadRecursorLuaConfig(const std::string& fname)
            //      cout<<"Set a default policy"<<endl;
            defpol=DNSFilterEngine::Policy();
            defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get<int>(constGet(have, "defpol"));
-           defpol->d_name = polName;
+           defpol->d_name = std::make_shared<std::string>(polName);
            if(defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) {
              //              cout<<"Setting a custom field even!"<<endl;
              defpol->d_custom=
@@ -180,11 +182,13 @@ void loadRecursorLuaConfig(const std::string& fname)
           // We were passed a localAddress, check if its AF matches the master's
           throw PDNSException("Master address("+master.toString()+") is not of the same Address Family as the local address ("+localAddress.toString()+").");
        DNSName zone(zone_);
+        const size_t zoneIdx = lci.dfe.size();
+        lci.dfe.setPolicyName(zoneIdx, polName);
 
-       auto sr=loadRPZFromServer(master, zone, lci.dfe, polName, defpol, 0, tt, maxReceivedXFRMBytes * 1024 * 1024, localAddress);
+       auto sr=loadRPZFromServer(master, zone, lci.dfe, defpol, zoneIdx, tt, maxReceivedXFRMBytes * 1024 * 1024, localAddress);
         if(refresh)
           sr->d_st.refresh=refresh;
-       std::thread t(RPZIXFRTracker, master, zone, polName, tt, sr, maxReceivedXFRMBytes * 1024 * 1024, localAddress);
+       std::thread t(RPZIXFRTracker, master, zone, zoneIdx, tt, sr, maxReceivedXFRMBytes * 1024 * 1024, localAddress);
        t.detach();
       }
       catch(std::exception& e) {
index b63f589f605a38b9265e850faa5f5bafdb4f93e1..63ccb27e3b0745c310a39f345b2aba3beeb5fbf1 100644 (file)
@@ -311,7 +311,7 @@ string reloadAuthAndForwards()
 }
 
 
-void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, const std::string& polName, const TSIGTriplet& tt, shared_ptr<SOARecordContent> oursr, size_t maxReceivedBytes, const ComboAddress& localAddress)
+void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, size_t polZone, const TSIGTriplet& tt, shared_ptr<SOARecordContent> oursr, size_t maxReceivedBytes, const ComboAddress& localAddress)
 {
   int refresh = oursr->d_st.refresh;
   for(;;) {
@@ -358,7 +358,7 @@ void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, const std::
        }
        else {
          L<<Logger::Info<<"Had removal of "<<rr.d_name<<endl;
-         RPZRecordToPolicy(rr, luaconfsCopy.dfe, polName, false, boost::optional<DNSFilterEngine::Policy>(), 0);
+         RPZRecordToPolicy(rr, luaconfsCopy.dfe, false, boost::optional<DNSFilterEngine::Policy>(), polZone);
        }
       }
 
@@ -373,7 +373,7 @@ void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, const std::
        }
        else {
          L<<Logger::Info<<"Had addition of "<<rr.d_name<<endl;
-         RPZRecordToPolicy(rr, luaconfsCopy.dfe, polName, true, boost::optional<DNSFilterEngine::Policy>(), 0);
+         RPZRecordToPolicy(rr, luaconfsCopy.dfe, true, boost::optional<DNSFilterEngine::Policy>(), polZone);
        }
       }
     }
index c98b136f01f432e29afd384e4a6a3b68f6ba62be..8e4b3cb9b2a50bc04074f096bfda7eb90c77dc14 100644 (file)
@@ -58,13 +58,13 @@ static Netmask makeNetmaskFromRPZ(const DNSName& name)
   return Netmask(v6);
 }
 
-void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, const std::string& polName, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, int place)
+void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, size_t place)
 {
   static const DNSName drop("rpz-drop."), truncate("rpz-tcp-only."), noaction("rpz-passthru.");
   static const DNSName rpzClientIP("rpz-client-ip"), rpzIP("rpz-ip"),
     rpzNSDname("rpz-nsdname"), rpzNSIP("rpz-nsip.");
 
-  DNSFilterEngine::Policy pol{DNSFilterEngine::PolicyKind::NoAction, nullptr, polName, 0};
+  DNSFilterEngine::Policy pol{DNSFilterEngine::PolicyKind::NoAction, nullptr, nullptr, 0};
 
   if(dr.d_class != QClass::IN) {
     return;
@@ -123,41 +123,41 @@ void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, const std::
   if(dr.d_name.isPartOf(rpzNSDname)) {
     DNSName filt=dr.d_name.makeRelative(rpzNSDname);
     if(addOrRemove)
-      target.addNSTrigger(filt, pol);
+      target.addNSTrigger(filt, pol, place);
     else
-      target.rmNSTrigger(filt, pol);
+      target.rmNSTrigger(filt, pol, place);
   } else       if(dr.d_name.isPartOf(rpzClientIP)) {
     DNSName filt=dr.d_name.makeRelative(rpzClientIP);
     auto nm=makeNetmaskFromRPZ(filt);
     if(addOrRemove)
-      target.addClientTrigger(nm, pol);
+      target.addClientTrigger(nm, pol, place);
     else
-      target.rmClientTrigger(nm, pol);
+      target.rmClientTrigger(nm, pol, place);
     
   } else       if(dr.d_name.isPartOf(rpzIP)) {
     // cerr<<"Should apply answer content IP policy: "<<dr.d_name<<endl;
     DNSName filt=dr.d_name.makeRelative(rpzIP);
     auto nm=makeNetmaskFromRPZ(filt);
     if(addOrRemove)
-      target.addResponseTrigger(nm, pol);
+      target.addResponseTrigger(nm, pol, place);
     else
-      target.rmResponseTrigger(nm, pol);
+      target.rmResponseTrigger(nm, pol, place);
   } else if(dr.d_name.isPartOf(rpzNSIP)) {
     DNSName filt=dr.d_name.makeRelative(rpzNSIP);
     auto nm=makeNetmaskFromRPZ(filt);
     if(addOrRemove)
-      target.addNSIPTrigger(nm, pol);
+      target.addNSIPTrigger(nm, pol, place);
     else
-      target.rmNSIPTrigger(nm, pol);
+      target.rmNSIPTrigger(nm, pol, place);
   } else {
     if(addOrRemove)
-      target.addQNameTrigger(dr.d_name, pol);
+      target.addQNameTrigger(dr.d_name, pol, place);
     else
-      target.rmQNameTrigger(dr.d_name, pol);
+      target.rmQNameTrigger(dr.d_name, pol, place);
   }
 }
 
-shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, const std::string& polName, boost::optional<DNSFilterEngine::Policy> defpol, int place,  const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress)
+shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, size_t place, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress)
 {
   L<<Logger::Warning<<"Loading RPZ zone '"<<zone<<"' from "<<master.toStringWithPort()<<endl;
   if(!tt.name.empty())
@@ -185,7 +185,7 @@ shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const
        continue;
       }
 
-      RPZRecordToPolicy(dr, target, polName, true, defpol, place);
+      RPZRecordToPolicy(dr, target, true, defpol, place);
       nrecords++;
     } 
     if(last != time(0)) {
@@ -198,7 +198,7 @@ shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const
 }
 
 // this function is silent - you do the logging
-int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, const std::string& polName, boost::optional<DNSFilterEngine::Policy> defpol, int place)
+int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, size_t place)
 {
   ZoneParserTNG zpt(fname);
   DNSResourceRecord drr;
@@ -216,7 +216,7 @@ int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, const std
       }
       else {
        dr.d_name=dr.d_name.makeRelative(domain);
-       RPZRecordToPolicy(dr, target, polName, true, defpol, place);
+       RPZRecordToPolicy(dr, target, true, defpol, place);
       }
     }
     catch(PDNSException& pe) {
index e5acb7a716941a1a7576a6a798665ca4b3fe8139..f0afb5585a5bedcde3ff1deccc4d8b891b153a43 100644 (file)
@@ -24,7 +24,7 @@
 #include <string>
 #include "dnsrecords.hh"
 
-int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, const std::string& policyName, boost::optional<DNSFilterEngine::Policy> defpol, int place);
-std::shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, const std::string& policyName, boost::optional<DNSFilterEngine::Policy> defpol, int place, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress);
-void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, const std::string& policyName, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, int place);
-void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, const std::string& policyName, const TSIGTriplet &tt, shared_ptr<SOARecordContent> oursr, size_t maxReceivedBytes, const ComboAddress& localAddress);
+int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, size_t place);
+std::shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, size_t place, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress);
+void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, size_t place);
+void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, size_t polZone, const TSIGTriplet &tt, shared_ptr<SOARecordContent> oursr, size_t maxReceivedBytes, const ComboAddress& localAddress);
index 7bf5ad9159ffc0ec2fba7b1f8b8e2db6102e53d9..2894f1701dd995280b10cf6b3932060ea2139c5c 100644 (file)
@@ -964,17 +964,17 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con
 
   if(d_wantsRPZ) {
     for (auto const &ns : nameservers) {
-      d_appliedPolicy = g_luaconfs.getLocal()->dfe.getProcessingPolicy(ns.first);
+      d_appliedPolicy = g_luaconfs.getLocal()->dfe.getProcessingPolicy(ns.first, d_discardedPolicies);
       if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
-        LOG(", however nameserver "<<ns.first<<" was blocked by RPZ policy '"<<d_appliedPolicy.d_name<<"'"<<endl);
+        LOG(", however nameserver "<<ns.first<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
         return -2;
       }
 
       // Traverse all IP addresses for this NS to see if they have an RPN NSIP policy
       for (auto const &address : ns.second.first) {
-        d_appliedPolicy = g_luaconfs.getLocal()->dfe.getProcessingPolicy(address);
+        d_appliedPolicy = g_luaconfs.getLocal()->dfe.getProcessingPolicy(address, d_discardedPolicies);
         if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
-          LOG(", however nameserver "<<ns.first<<" IP address "<<address.toString()<<" was blocked by RPZ policy '"<<d_appliedPolicy.d_name<<"'"<<endl);
+          LOG(", however nameserver "<<ns.first<<" IP address "<<address.toString()<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
           return -2;
         }
       }
@@ -1054,10 +1054,10 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con
             }
             LOG(remoteIP->toString());
             if (d_wantsRPZ) {
-              d_appliedPolicy = g_luaconfs.getLocal()->dfe.getProcessingPolicy(*remoteIP);
+              d_appliedPolicy = g_luaconfs.getLocal()->dfe.getProcessingPolicy(*remoteIP, d_discardedPolicies);
               if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) {
                 hitPolicy = true;
-                LOG(" (blocked by RPZ policy '"+d_appliedPolicy.d_name+"')");
+                LOG(" (blocked by RPZ policy '"+(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")+"')");
               }
             }
           }
@@ -1444,9 +1444,9 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con
         nameservers.clear();
         for (auto const &nameserver : nsset) {
           if (d_wantsRPZ) {
-            d_appliedPolicy = g_luaconfs.getLocal()->dfe.getProcessingPolicy(nameserver);
+            d_appliedPolicy = g_luaconfs.getLocal()->dfe.getProcessingPolicy(nameserver, d_discardedPolicies);
             if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
-              LOG("however "<<nameserver<<" was blocked by RPZ policy '"<<d_appliedPolicy.d_name<<"'"<<endl);
+              LOG("however "<<nameserver<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
               return -2;
             }
           }
index 95eef6a5c22ba3624c02a908dc1b0042ad065c3d..7d0ef3826de0eef437cdd75967f7ede64a6579b9 100644 (file)
@@ -357,6 +357,8 @@ public:
   static bool s_doIPv6;
   static unsigned int s_maxqperq;
   static unsigned int s_maxtotusec;
+  std::unordered_map<std::string,bool> d_discardedPolicies;
+  DNSFilterEngine::Policy d_appliedPolicy{DNSFilterEngine::PolicyKind::NoAction, nullptr, nullptr, 0};
   unsigned int d_outqueries;
   unsigned int d_tcpoutqueries;
   unsigned int d_throttledqueries;
@@ -369,7 +371,6 @@ public:
   bool d_wasVariable{false};
   bool d_wasOutOfBand{false};
   bool d_wantsRPZ{true};
-  DNSFilterEngine::Policy d_appliedPolicy{DNSFilterEngine::PolicyKind::NoAction, nullptr, "", 0};
   
   typedef multi_index_container <
     NegCacheEntry,