]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Introduce TSIGTriple struct, hook up IXFR config in recursor to TSIG code for IXFR
authorbert hubert <bert.hubert@netherlabs.nl>
Thu, 7 Jan 2016 22:13:43 +0000 (23:13 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Thu, 7 Jan 2016 22:13:43 +0000 (23:13 +0100)
merge the triplet 'tsigname, tsigalgo, tsigsecret' into a handy TSIGTriplet, and move most of the TSIG apis to this struct.

pdns/dns.hh
pdns/ixfr.cc
pdns/ixfr.hh
pdns/ixplore.cc
pdns/rec-lua-conf.cc
pdns/reczones.cc
pdns/resolver.cc
pdns/resolver.hh
pdns/rpzloader.cc
pdns/rpzloader.hh
pdns/slavecommunicator.cc

index cdd8fa042bcf952df0a9ee1054bf8275fadfe2e8..1125b8d2af634f4a1974c585f26b3002baa85229 100644 (file)
@@ -1,6 +1,6 @@
 /*
     PowerDNS Versatile Database Driven Nameserver
-    Copyright (C) 2002 - 2011 PowerDNS.COM BV
+    Copyright (C) 2002 - 2016 PowerDNS.COM BV
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2
@@ -19,8 +19,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
-// $Id$ 
-/* (C) 2002 POWERDNS.COM BV */
+
 #pragma once
 #include <boost/multi_index_container.hpp>
 #include <boost/multi_index/ordered_index.hpp>
@@ -32,7 +31,6 @@
 #include <time.h>
 #include <sys/types.h>
 class DNSBackend;
-class DNSName; // FIXME400
 
 struct SOAData
 {
@@ -330,6 +328,12 @@ inline bool dnspacketLessThan(const std::string& a, const std::string& b)
 }
 
 
+struct TSIGTriplet
+{
+  DNSName name, algo;
+  string secret;
+};
+
 /** for use by DNSPacket, converts a SOAData class to a ascii line again */
 string serializeSOAData(const SOAData &data);
 string &attodot(string &str);  //!< for when you need to insert an email address in the SOA
index ca31143ce446da265fd1c45f6ab94317e0b97782..c9bb5e48fe14f3b6f1187ca2677f454bdf58f44f 100644 (file)
@@ -4,7 +4,7 @@
 #include "dnsrecords.hh"
 #include "dnssecinfra.hh"
 
-vector<pair<vector<DNSRecord>, vector<DNSRecord> > >   getIXFRDeltas(const ComboAddress& master, const DNSName& zone, const DNSRecord& oursr, const DNSName& tsigalgo, const DNSName& tsigname, const std::string& tsigsecret)
+vector<pair<vector<DNSRecord>, vector<DNSRecord> > >   getIXFRDeltas(const ComboAddress& master, const DNSName& zone, const DNSRecord& oursr, const TSIGTriplet& tt)
 {
   vector<pair<vector<DNSRecord>, vector<DNSRecord> > >  ret;
   vector<uint8_t> packet;
@@ -16,14 +16,14 @@ vector<pair<vector<DNSRecord>, vector<DNSRecord> > >   getIXFRDeltas(const Combo
   oursr.d_content->toPacket(pw);
 
   pw.commit();
-  if(!tsigalgo.empty()) {
+  if(!tt.algo.empty()) {
     TSIGRecordContent trc;
-    trc.d_algoName = tsigalgo;
+    trc.d_algoName = tt.algo;
     trc.d_time = time((time_t*)NULL);
     trc.d_fudge = 300;
     trc.d_origID=ntohs(pw.getHeader()->id);
     trc.d_eRcode=0;
-    addTSIG(pw, &trc, tsigname, tsigsecret, "", false);
+    addTSIG(pw, &trc, tt.name, tt.secret, "", false);
   }
   uint16_t len=htons(packet.size());
   string msg((const char*)&len, 2);
index 40d70659c3292ce8a8e1ba68e08dd828a9e7480f..db708586c723a72543d13f90ac0eddb05b8dcca6 100644 (file)
@@ -3,4 +3,4 @@
 #include "dnsparser.hh"
 
 vector<pair<vector<DNSRecord>, vector<DNSRecord> > >   getIXFRDeltas(const ComboAddress& master, const DNSName& zone, const DNSRecord& sr,
-                                                                     const DNSName& tsigalgo=DNSName(), const DNSName& tsigname=DNSName(), const std::string& tsigsecret="");
+                                                                     const TSIGTriplet& tt=TSIGTriplet());
index 4e77c22de0a11b4e72f917a7afe519cae0bb4974..ca663495ea5c6c4f8d944656c8afa8d48f20bea3 100644 (file)
@@ -56,18 +56,18 @@ typedef multi_index_container<
     >
   >records_t;
 
-uint32_t getSerialFromMaster(const ComboAddress& master, const DNSName& zone, shared_ptr<SOARecordContent>& sr, const DNSName& tsigalgo=DNSName(), const DNSName& tsigname=DNSName(), const std::string& tsigsecret="")
+uint32_t getSerialFromMaster(const ComboAddress& master, const DNSName& zone, shared_ptr<SOARecordContent>& sr, const TSIGTriplet& tt = TSIGTriplet())
 {
   vector<uint8_t> packet;
   DNSPacketWriter pw(packet, zone, QType::SOA);
-  if(!tsigalgo.empty()) {
+  if(!tt.algo.empty()) {
     TSIGRecordContent trc;
-    trc.d_algoName = tsigalgo;
+    trc.d_algoName = tt.algo;
     trc.d_time = time((time_t*)NULL);
     trc.d_fudge = 300;
     trc.d_origID=ntohs(pw.getHeader()->id);
     trc.d_eRcode=0;
-    addTSIG(pw, &trc, tsigname, tsigsecret, "", false);
+    addTSIG(pw, &trc, tt.name, tt.secret, "", false);
   }
   
   Socket s(master.sin4.sin_family, SOCK_DGRAM);
@@ -229,14 +229,14 @@ try
 
   cout<<"Loading zone, our highest available serial is "<< ourSerial<<endl;
 
-  DNSName tsigkey, tsigalgo;
+  TSIGTriplet tt;
   if(argc > 6)
-    tsigkey=DNSName(toLower(argv[6]));
+    tt.name=DNSName(toLower(argv[6]));
   if(argc > 7)
-    tsigalgo=DNSName(toLower(argv[7]));
-  string tsigsecret;
+    tt.algo=DNSName(toLower(argv[7]));
+
   if(argc > 8) {
-    if(B64Decode(argv[8], tsigsecret) < 0) {
+    if(B64Decode(argv[8], tt.secret) < 0) {
       cerr<<"Could not decode tsig secret!"<<endl;
       exit(EXIT_FAILURE);
     }
@@ -253,7 +253,7 @@ try
     cout<<"Could not load zone from disk: "<<e.what()<<endl;
     cout<<"Retrieving latest from master "<<master.toStringWithPort()<<endl;
     ComboAddress local = master.sin4.sin_family == AF_INET ? ComboAddress("0.0.0.0") : ComboAddress("::");
-    AXFRRetriever axfr(master, zone, tsigkey, tsigalgo, tsigsecret, &local);
+    AXFRRetriever axfr(master, zone, tt, &local);
     unsigned int nrecords=0;
     Resolver::res_t nop;
     vector<DNSRecord> chunk;
@@ -288,7 +288,7 @@ try
     cout<<"Checking for update, our serial number is "<<ourSerial<<".. ";
     cout.flush();
     shared_ptr<SOARecordContent> sr;
-    uint32_t serial = getSerialFromMaster(master, zone, sr, tsigalgo, tsigkey, tsigsecret);
+    uint32_t serial = getSerialFromMaster(master, zone, sr, tt);
     if(ourSerial == serial) {
       cout<<"still up to date, their serial is "<<serial<<", sleeping "<<sr->d_st.refresh<<" seconds"<<endl;
       sleep(sr->d_st.refresh);
@@ -296,7 +296,7 @@ try
     }
 
     cout<<"got new serial: "<<serial<<", initiating IXFR!"<<endl;
-    auto deltas = getIXFRDeltas(master, zone, ourSoa, tsigalgo, tsigkey, tsigsecret);
+    auto deltas = getIXFRDeltas(master, zone, ourSoa, tt);
     cout<<"Got "<<deltas.size()<<" deltas, applying.."<<endl;
 
     for(const auto& delta : deltas) {
index f66d0ed31acab57eb3bb20b52fc303251e1ca73d..e05349f37bd2d6c5d85dbe1d7398fb2a88f9fa5c 100644 (file)
@@ -12,6 +12,7 @@
 #include "filterpo.hh"
 #include "syncres.hh"
 #include "rpzloader.hh"
+#include "base64.hh"
 
 GlobalStateHolder<LuaConfigItems> g_luaconfs; 
 
@@ -119,8 +120,11 @@ void loadRecursorLuaConfig(const std::string& fname)
   Lua.writeFunction("rpzMaster", [&lci](const string& master_, const string& zone_, const boost::optional<std::unordered_map<string,boost::variant<int, string>>>& options) {
       try {
        boost::optional<DNSFilterEngine::Policy> defpol;
+        TSIGTriplet tt;
+        int refresh=0;
        if(options) {
          auto& have = *options;
+
          if(have.count("defpol")) {
            //      cout<<"Set a default policy"<<endl;
            defpol=DNSFilterEngine::Policy();
@@ -140,12 +144,23 @@ void loadRecursorLuaConfig(const std::string& fname)
 
            }
          }
-           
+         if(have.count("tsigname")) {
+            tt.name=DNSName(toLower(boost::get<string>(constGet(have, "tsigname"))));
+            tt.algo=DNSName(toLower(boost::get<string>(constGet(have, "tsigalgo"))));
+            if(B64Decode(boost::get<string>(constGet(have, "tsigsecret")), tt.secret))
+              throw std::runtime_error("TSIG secret is not valid Base-64 encoded");
+          }
+          if(have.count("refresh")) {
+            refresh = boost::get<int>(constGet(have,"refresh"));
+          }
        }
        ComboAddress master(master_, 53);
        DNSName zone(zone_);
-       auto sr=loadRPZFromServer(master,zone, lci.dfe, defpol, 0);
-       std::thread t(RPZIXFRTracker, master, zone, sr);
+
+       auto sr=loadRPZFromServer(master,zone, lci.dfe, defpol, 0, tt);
+        if(refresh)
+          sr->d_st.refresh=refresh;
+       std::thread t(RPZIXFRTracker, master, zone, tt, sr);
        t.detach();
       }
       catch(std::exception& e) {
index 8590c5ae32579db58f9789d125dfe9e595ce4119..9861a718336a241adac1ceed53df5f021bcc0e7e 100644 (file)
@@ -317,17 +317,18 @@ string reloadAuthAndForwards()
 }
 
 
-void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, shared_ptr<SOARecordContent> oursr) 
+void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, const TSIGTriplet& tt, shared_ptr<SOARecordContent> oursr) 
 {
+  int refresh = oursr->d_st.refresh;
   for(;;) {
     DNSRecord dr;
     dr.d_content=oursr;
 
-    sleep(oursr->d_st.refresh);
+    sleep(refresh);
     
     L<<Logger::Info<<"Getting IXFR deltas for "<<zone<<" from "<<master.toStringWithPort()<<", our serial: "<<std::dynamic_pointer_cast<SOARecordContent>(dr.d_content)->d_st.serial<<endl;
 
-    auto deltas = getIXFRDeltas(master, zone, dr);
+    auto deltas = getIXFRDeltas(master, zone, dr, tt);
     if(deltas.empty())
       continue;
     L<<Logger::Info<<"Processing "<<deltas.size()<<" delta"<<addS(deltas)<<" for RPZ "<<zone<<endl;
index d0eafe6ecbae74dd5baf88ca259d844834b282b0..20dbab372d8e344c5436f2ad8ae8aaf0e77ad628 100644 (file)
@@ -364,12 +364,10 @@ void Resolver::getSoaSerial(const string &ipport, const DNSName &domain, uint32_
 }
 
 AXFRRetriever::AXFRRetriever(const ComboAddress& remote,
-        const DNSName& domain,
-        const DNSName& tsigkeyname,
-        const DNSName& tsigalgorithm, 
-        const string& tsigsecret,
-        const ComboAddress* laddr)
-: d_tsigkeyname(tsigkeyname), d_tsigsecret(tsigsecret), d_tsigPos(0), d_nonSignedMessages(0)
+                             const DNSName& domain,
+                             const TSIGTriplet& tt, 
+                             const ComboAddress* laddr)
+  : d_tt(tt), d_tsigPos(0), d_nonSignedMessages(0)
 {
   ComboAddress local;
   if (laddr != NULL) {
@@ -394,16 +392,16 @@ AXFRRetriever::AXFRRetriever(const ComboAddress& remote,
     DNSPacketWriter pw(packet, domain, QType::AXFR);
     pw.getHeader()->id = dns_random(0xffff);
   
-    if(!tsigkeyname.empty()) {
-      if (tsigalgorithm == DNSName("hmac-md5"))
-        d_trc.d_algoName = tsigalgorithm + DNSName("sig-alg.reg.int");
+    if(!tt.name.empty()) {
+      if (tt.algo == DNSName("hmac-md5"))
+        d_trc.d_algoName = tt.algo + DNSName("sig-alg.reg.int");
       else
-        d_trc.d_algoName = tsigalgorithm;
+        d_trc.d_algoName = tt.algo;
       d_trc.d_time = time(0);
       d_trc.d_fudge = 300;
       d_trc.d_origID=ntohs(pw.getHeader()->id);
       d_trc.d_eRcode=0;
-      addTSIG(pw, &d_trc, tsigkeyname, tsigsecret, "", false);
+      addTSIG(pw, &d_trc, tt.name, tt.secret, "", false);
     }
   
     uint16_t replen=htons(packet.size());
@@ -471,7 +469,7 @@ int AXFRRetriever::getChunk(Resolver::res_t &res, vector<DNSRecord>* records) //
     if (answer.first.d_type == QType::SOA)
       d_soacount++;
  
-  if(!d_tsigkeyname.empty()) { // TSIG verify message
+  if(!d_tt.name.empty()) { // TSIG verify message
     // If we have multiple messages, we need to concatenate them together. We also need to make sure we know the location of 
     // the TSIG record so we can remove it in makeTSIGMessageFromTSIGPacket
     d_signData.append(d_buf.get(), len);
@@ -501,13 +499,13 @@ int AXFRRetriever::getChunk(Resolver::res_t &res, vector<DNSRecord>* records) //
 
     if (checkTSIG) {
       if (theirMac.empty())
-        throw ResolverException("No TSIG on AXFR response from "+d_remote.toStringWithPort()+" , should be signed with TSIG key '"+d_tsigkeyname.toString()+"'");
+        throw ResolverException("No TSIG on AXFR response from "+d_remote.toStringWithPort()+" , should be signed with TSIG key '"+d_tt.name.toString()+"'");
 
       string message;
       if (!d_prevMac.empty()) {
-        message = makeTSIGMessageFromTSIGPacket(d_signData, d_tsigPos, d_tsigkeyname, d_trc, d_prevMac, true, d_signData.size()-len);
+        message = makeTSIGMessageFromTSIGPacket(d_signData, d_tsigPos, d_tt.name, d_trc, d_prevMac, true, d_signData.size()-len);
       } else {
-        message = makeTSIGMessageFromTSIGPacket(d_signData, d_tsigPos, d_tsigkeyname, d_trc, d_trc.d_mac, false);
+        message = makeTSIGMessageFromTSIGPacket(d_signData, d_tsigPos, d_tt.name, d_trc, d_trc.d_mac, false);
       }
 
       TSIGHashEnum algo;
@@ -516,16 +514,16 @@ int AXFRRetriever::getChunk(Resolver::res_t &res, vector<DNSRecord>* records) //
       }
 
       if (algo == TSIG_GSS) {
-        GssContext gssctx(d_tsigkeyname);
-        if (!gss_verify_signature(d_tsigkeyname, message, theirMac)) {
-          throw ResolverException("Signature failed to validate on AXFR response from "+d_remote.toStringWithPort()+" signed with TSIG key '"+d_tsigkeyname.toString()+"'");
+        GssContext gssctx(d_tt.name);
+        if (!gss_verify_signature(d_tt.name, message, theirMac)) {
+          throw ResolverException("Signature failed to validate on AXFR response from "+d_remote.toStringWithPort()+" signed with TSIG key '"+d_tt.name.toString()+"'");
         }
       } else {
-        string ourMac=calculateHMAC(d_tsigsecret, message, algo);
+        string ourMac=calculateHMAC(d_tt.secret, message, algo);
 
         // ourMac[0]++; // sabotage == for testing :-)
         if(ourMac != theirMac) {
-          throw ResolverException("Signature failed to validate on AXFR response from "+d_remote.toStringWithPort()+" signed with TSIG key '"+d_tsigkeyname.toString()+"'");
+          throw ResolverException("Signature failed to validate on AXFR response from "+d_remote.toStringWithPort()+" signed with TSIG key '"+d_tt.name.toString()+"'");
         }
       }
 
index 1a234c682787f251cb47a38ff46ed506f57ccb48..24e45454db998870ee1d79b21d9c49166f7e1155 100644 (file)
@@ -84,11 +84,9 @@ class AXFRRetriever : public boost::noncopyable
 {
   public:
     AXFRRetriever(const ComboAddress& remote,
-        const DNSName& zone,
-        const DNSName& tsigkeyname=DNSName(),
-        const DNSName& tsigalgorithm=DNSName(),
-        const string& tsigsecret=string(),
-        const ComboAddress* laddr = NULL);
+                  const DNSName& zone,
+                  const TSIGTriplet& tt = TSIGTriplet(),
+                  const ComboAddress* laddr = NULL);
        ~AXFRRetriever();
     int getChunk(Resolver::res_t &res, vector<DNSRecord>* records=0);  
   
@@ -103,8 +101,7 @@ class AXFRRetriever : public boost::noncopyable
     int d_soacount;
     ComboAddress d_remote;
     
-    DNSName d_tsigkeyname;
-    string d_tsigsecret;
+    TSIGTriplet d_tt;
     string d_prevMac; // RFC2845 4.4
     string d_signData;
     uint32_t d_tsigPos;
index 0784b1c32e685f41f7c28eb3b589a8854c6337f5..1cc909f184684567b34d4abdb2723bceef52d369 100644 (file)
@@ -97,11 +97,14 @@ void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrR
   }
 }
 
-shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, int place)
+shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, int place,  const TSIGTriplet& tt)
 {
   L<<Logger::Warning<<"Loading RPZ zone '"<<zone<<"' from "<<master.toStringWithPort()<<endl;
-  ComboAddress local("0.0.0.0");
-  AXFRRetriever axfr(master, zone, DNSName(), DNSName(), "", &local);
+  if(!tt.name.empty())
+    L<<Logger::Warning<<"With TSIG key '"<<tt.name<<"' of algorithm '"<<tt.algo<<"'"<<endl;
+
+  ComboAddress local= master.sin4.sin_family == AF_INET ? ComboAddress("0.0.0.0") : ComboAddress("::"); // should be configurable
+  AXFRRetriever axfr(master, zone, tt, &local);
   unsigned int nrecords=0;
   Resolver::res_t nop;
   vector<DNSRecord> chunk;
@@ -109,14 +112,15 @@ shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const
   shared_ptr<SOARecordContent> sr;
   while(axfr.getChunk(nop, &chunk)) {
     for(auto& dr : chunk) {
+      if(dr.d_type==QType::NS || dr.d_type==QType::TSIG) {
+       continue;
+      }
+
       dr.d_name.makeUsRelative(zone);
       if(dr.d_type==QType::SOA) {
        sr = std::dynamic_pointer_cast<SOARecordContent>(dr.d_content);
        continue;
       }
-      if(dr.d_type==QType::NS) {
-       continue;
-      }
 
       RPZRecordToPolicy(dr, target, true, defpol, place);
       nrecords++;
index 42b8fba11e803620253260284b59e8b476f5a453..113410188ea889cd48d174184c7d19989c45aad9 100644 (file)
@@ -4,6 +4,6 @@
 #include "dnsrecords.hh"
 
 int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, int place);
-std::shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, int place);
+std::shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, int place, const TSIGTriplet& tt);
 void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, int place);
-void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, shared_ptr<SOARecordContent> oursr);
+void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, const TSIGTriplet &tt, shared_ptr<SOARecordContent> oursr);
index 0e261a8a9fc90a23fd215836868945d60b64e9cf..c4956410da5db6a1683a262bf252d410f806b38a 100644 (file)
@@ -81,15 +81,16 @@ void CommunicatorClass::suck(const DNSName &domain,const string &remote)
     }
     uint32_t domain_id=di.id;
 
-
-    DNSName tsigkeyname, tsigalgorithm;
-    string tsigsecret;
-    if(dk.getTSIGForAccess(domain, remote, &tsigkeyname)) {
+    TSIGTriplet tt;
+    if(dk.getTSIGForAccess(domain, remote, &tt.name)) {
       string tsigsecret64;
-      if(B.getTSIGKey(tsigkeyname, &tsigalgorithm, &tsigsecret64)) {
-        B64Decode(tsigsecret64, tsigsecret);
+      if(B.getTSIGKey(tt.name, &tt.algo, &tsigsecret64)) {
+        if(B64Decode(tsigsecret64, tt.secret)) {
+          L<<Logger::Error<<"Unable to Base-64 decode TSIG key '"<<tt.name<<"' for domain '"<<domain<<"' not found"<<endl;
+          return;
+        }
       } else {
-        L<<Logger::Error<<"TSIG key '"<<tsigkeyname<<"' for domain '"<<domain<<"' not found"<<endl;
+        L<<Logger::Error<<"TSIG key '"<<tt.name<<"' for domain '"<<domain<<"' not found"<<endl;
         return;
       }
     }
@@ -151,7 +152,7 @@ void CommunicatorClass::suck(const DNSName &domain,const string &remote)
     vector<DNSResourceRecord> rrs;
 
     ComboAddress raddr(remote, 53);
-    AXFRRetriever retriever(raddr, domain, tsigkeyname, tsigalgorithm, tsigsecret, (laddr.sin4.sin_family == 0) ? NULL : &laddr);
+    AXFRRetriever retriever(raddr, domain, tt, (laddr.sin4.sin_family == 0) ? NULL : &laddr);
     Resolver::res_t recs;
     while(retriever.getChunk(recs)) {
       if(first) {