]> granicus.if.org Git - pdns/commitdiff
auth: keep slave dnssec status in sync with the master
authorKees Monshouwer <mind04@monshouwer.org>
Thu, 1 Jun 2017 23:08:27 +0000 (01:08 +0200)
committermind04 <mind04@monshouwer.org>
Sun, 4 Jun 2017 12:36:29 +0000 (14:36 +0200)
pdns/dbdnsseckeeper.cc
pdns/dnsseckeeper.hh
pdns/slavecommunicator.cc
pdns/ueberbackend.cc
pdns/ueberbackend.hh

index a62784fbe17cb4b56b8f557a6d5f201c794702cb..f5ba7a60b86adf97a3e98868bbb8e25363c5bfc6 100644 (file)
@@ -51,6 +51,11 @@ pthread_rwlock_t DNSSECKeeper::s_keycachelock = PTHREAD_RWLOCK_INITIALIZER;
 AtomicCounter DNSSECKeeper::s_ops;
 time_t DNSSECKeeper::s_last_prune;
 
+bool DNSSECKeeper::doesDNSSEC()
+{
+  return d_keymetadb->doesDNSSEC();
+}
+
 bool DNSSECKeeper::isSecuredZone(const DNSName& zone) 
 {
   if(isPresigned(zone))
index 9c8582f3cfda4fbb6dc3aa4d41e589c804ce135d..c6d2249d199cb53800264fc1f2af19e4f4f21ac8 100644 (file)
@@ -156,6 +156,7 @@ public:
     if(d_ourDB)
       delete d_keymetadb;
   }
+  bool doesDNSSEC();
   bool isSecuredZone(const DNSName& zone);
   static uint64_t dbdnssecCacheSizes(const std::string& str);
   keyset_t getEntryPoints(const DNSName& zname);
index d4b3901001d9cfb2c72f16e1d7e461672d2d114b..16ee70ad09c883d35bf35f025425c3bb0822f8f0 100644 (file)
@@ -773,7 +773,7 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
 
       DomainNotificationInfo dni;
       dni.di=di;
-      dni.dnssecOk = dk.isPresigned(di.zone);
+      dni.dnssecOk = dk.doesDNSSEC();
 
       if(dk.getTSIGForAccess(di.zone, sr.master, &dni.tsigkeyname)) {
         string secret64;
@@ -836,6 +836,7 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
   L<<Logger::Warning<<"Received serial number updates for "<<ssr.d_freshness.size()<<" zone"<<addS(ssr.d_freshness.size())<<", had "<<ifl.getTimeouts()<<" timeout"<<addS(ifl.getTimeouts())<<endl;
 
   typedef DomainNotificationInfo val_t;
+  unsigned int now = time(0);
   for(val_t& val :  sdomains) {
     DomainInfo& di(val.di);
     // might've come from the packethandler
@@ -853,14 +854,10 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
       di.backend->setFresh(di.id);
     }
     else if(theirserial == ourserial) {
-      if(!dk.isPresigned(di.zone)) {
-        L<<Logger::Info<<"Domain '"<< di.zone<<"' is fresh (not presigned, no RRSIG check)"<<endl;
-        di.backend->setFresh(di.id);
-      }
-      else {
+      uint32_t maxExpire=0, maxInception=0;
+      if(dk.isPresigned(di.zone)) {
         B->lookup(QType(QType::RRSIG), di.zone); // can't use DK before we are done with this lookup!
         DNSResourceRecord rr;
-        uint32_t maxExpire=0, maxInception=0;
         while(B->get(rr)) {
           RRSIGRecordContent rrc(rr.content);
           if(rrc.d_type == QType::SOA) {
@@ -868,14 +865,30 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
             maxExpire = std::max(maxExpire, rrc.d_sigexpire);
           }
         }
-        if(maxInception == ssr.d_freshness[di.id].theirInception && maxExpire == ssr.d_freshness[di.id].theirExpire) {
-          L<<Logger::Info<<"Domain '"<< di.zone<<"' is fresh and apex RRSIGs match"<<endl;
-          di.backend->setFresh(di.id);
-        }
-        else {
-          L<<Logger::Warning<<"Domain '"<< di.zone<<"' is fresh, but RRSIGS differ, so DNSSEC stale"<<endl;
-          addSuckRequest(di.zone, *di.masters.begin());
-        }
+      }
+      if(! maxInception && ! ssr.d_freshness[di.id].theirInception) {
+        L<<Logger::Info<<"Domain '"<< di.zone<<"' is fresh (no DNSSEC)"<<endl;
+        di.backend->setFresh(di.id);
+      }
+      else if(maxInception == ssr.d_freshness[di.id].theirInception && maxExpire == ssr.d_freshness[di.id].theirExpire) {
+        L<<Logger::Info<<"Domain '"<< di.zone<<"' is fresh and SOA RRSIGs match"<<endl;
+        di.backend->setFresh(di.id);
+      }
+      else if(maxExpire >= now && ! ssr.d_freshness[di.id].theirInception ) {
+        L<<Logger::Info<<"Domain '"<< di.zone<<"' is fresh, master is no longer signed but (some) signatures are still vallid"<<endl;
+        di.backend->setFresh(di.id);
+      }
+      else if(maxInception && ! ssr.d_freshness[di.id].theirInception ) {
+        L<<Logger::Warning<<"Domain '"<< di.zone<<"' is stale, master is no longer signed and all signatures have expired"<<endl;
+        addSuckRequest(di.zone, *di.masters.begin());
+      }
+      else if(dk.doesDNSSEC() && ! maxInception && ssr.d_freshness[di.id].theirInception) {
+        L<<Logger::Warning<<"Domain '"<< di.zone<<"' is stale, master has signed"<<endl;
+        addSuckRequest(di.zone, *di.masters.begin());
+      }
+      else {
+        L<<Logger::Warning<<"Domain '"<< di.zone<<"' is fresh, but RRSIGs differ, so DNSSEC is stale"<<endl;
+        addSuckRequest(di.zone, *di.masters.begin());
       }
     }
     else {
index efa0e2dd84ece0cdfd7ebe20b179fde1e169159e..8934146d92f142d6b909ec551107d67d2dd732a9 100644 (file)
@@ -99,6 +99,15 @@ bool UeberBackend::createDomain(const DNSName &domain)
   return false;
 }
 
+bool UeberBackend::doesDNSSEC()
+{
+  for(auto* db :  backends) {
+    if(db->doesDNSSEC())
+      return true;
+  }
+  return false;
+}
+
 int UeberBackend::addDomainKey(const DNSName& name, const DNSBackend::KeyData& key)
 {
   int ret;
index 7c1aecd530e48bb306b40421f70a4baf4b000aee..c54279618f5fa6c81676365bd2cd7e41500b0dfe 100644 (file)
@@ -116,6 +116,7 @@ public:
   bool getDomainInfo(const DNSName &domain, DomainInfo &di);
   bool createDomain(const DNSName &domain);
   
+  bool doesDNSSEC();
   int addDomainKey(const DNSName& name, const DNSBackend::KeyData& key);
   bool getDomainKeys(const DNSName& name, unsigned int kind, std::vector<DNSBackend::KeyData>& keys);
   bool getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string> >& meta);