]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: More wildcard denial tests, check DNAME
authorRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 31 Dec 2020 12:43:32 +0000 (13:43 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 22 Feb 2021 17:42:04 +0000 (18:42 +0100)
pdns/recursordist/aggressive_nsec.cc
pdns/recursordist/test-syncres_cc8.cc
pdns/validate.cc

index 984b627e8b77f9faccad81ea19d2d5eacd8a5575..ffc3071399cb103c71fee43f9a15a36bbd6cfab1 100644 (file)
@@ -112,6 +112,7 @@ void AggressiveNSECCache::insertNSEC(const DNSName& zone, const DNSName& owner,
         return;
       }
 
+#warning Ponder storing everything in raw form, without the zone instead. It still needs to be a DNSName for NSEC, though
       next = DNSName(toBase32Hex(content->d_nexthash)) + zone;
       entry->d_iterations = content->d_iterations;
       entry->d_salt = content->d_salt;
@@ -477,6 +478,11 @@ bool AggressiveNSECCache::getDenial(time_t now, const DNSName& name, const QType
       denial = matchesNSEC(wc, type.getCode(), wcEntry.d_owner, nsecContent, wcEntry.d_signatures);
       if (denial == dState::NODENIAL) {
         /* too complicated for now */
+        /* we would need:
+           - to store wildcard entries in the non-expanded form in the record cache, in addition to their expanded form ;
+           - do a lookup to retrieve them ;
+           - expand them and the NSEC
+        */
         return false;
       }
       else if (denial == dState::NXQTYPE) {
@@ -491,30 +497,6 @@ bool AggressiveNSECCache::getDenial(time_t now, const DNSName& name, const QType
       if (wcEntry.d_owner != wc) {
         needWildcard = true;
       }
-#if 0
-      if (wcEntry.d_owner == wc) {
-        if (!nsecContent) {
-          return false;
-        }
-        if (nsecContent->isSet(type.getCode())) {
-          /* too complicated for now */
-          return false;
-        }
-        if (nsecContent->isSet(QType::CNAME)) {
-          /* too complicated for now */
-          return false;
-        }
-
-        covered = true;
-        res = RCode::NoError;
-      }
-      else if (isCoveredByNSEC(wc, wcEntry.d_owner, wcEntry.d_next)) {
-        cerr<<"next is "<<wcEntry.d_next<<endl;
-        covered = true;
-        res = RCode::NXDomain;
-        needWildcard = true;
-      }
-#endif
     }
   }
 
index efc33e9a28ee3bf0802d1b17647831c8db31ac9e..ff1d0a4fbb74ab7a9db46f999c786b9415cf73da 100644 (file)
@@ -425,6 +425,37 @@ BOOST_AUTO_TEST_CASE(test_nsec3_nxdomain_denial_missing_wildcard)
   BOOST_CHECK_EQUAL(denialState, dState::NODENIAL);
 }
 
+BOOST_AUTO_TEST_CASE(test_nsec_expanded_wildcard_proof)
+{
+  initSR();
+
+  testkeysset_t keys;
+  generateKeyMaterial(DNSName("example.org."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
+
+  vector<DNSRecord> records;
+
+  sortedRecords_t recordContents;
+  vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+
+  /* proves that a.example.com does exist, and has been generated from a wildcard (see the RRSIG below) */
+  addNSECRecordToLW(DNSName("a.example.org."), DNSName("d.example.org"), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC}, 600, records);
+  recordContents.insert(records.at(0).d_content);
+  addRRSIG(keys, records, DNSName("example.org."), 300, false, boost::none, DNSName("example.org."));
+  signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
+  records.clear();
+
+  ContentSigPair pair;
+  pair.records = recordContents;
+  pair.signatures = signatureContents;
+  cspmap_t denialMap;
+  denialMap[std::make_pair(DNSName("a.example.org."), QType::NSEC)] = pair;
+
+  /* This is an expanded wildcard proof, meaning that it does prove that the exact name
+     does not exist so the wildcard can apply */
+  dState denialState = getDenial(denialMap, DNSName("a.example.org."), QType(0).getCode(), false, false, false, /* normally retrieved from the RRSIG's d_labels */ 2);
+  BOOST_CHECK_EQUAL(denialState, dState::NXDOMAIN);
+}
+
 BOOST_AUTO_TEST_CASE(test_nsec_wildcard_with_cname)
 {
   initSR();
index b36acf9dea827b88c4e8f5bc6bdcda821102c5d4..c991dbe9dc54a85af095c17760a310f01d1f5014 100644 (file)
@@ -271,7 +271,7 @@ static bool provesNoDataWildCard(const DNSName& qname, const uint16_t qtype, con
 
         if (qname.isPartOf(wildcard)) {
           LOG("\tWildcard matches");
-          if (qtype == 0 || (!nsec->isSet(qtype) && !nsec->isSet(QType::CNAME))) {
+          if (qtype == 0 || (!nsec->isSet(qtype) && !nsec->isSet(QType::CNAME) && !nsec->isSet(QType::DNAME))) {
             LOG(" and proves that the type did not exist"<<endl);
             return true;
           }
@@ -368,7 +368,7 @@ static bool provesNSEC3NoWildCard(DNSName wildcard, uint16_t const qtype, const
           if (wildcardExists) {
             *wildcardExists = true;
           }
-          if (qtype == 0 || (!nsec3->isSet(qtype) && !nsec3->isSet(QType::CNAME))) {
+          if (qtype == 0 || (!nsec3->isSet(qtype) && !nsec3->isSet(QType::CNAME) && !nsec3->isSet(QType::DNAME))) {
             LOG(" and proves that the type did not exist"<<endl);
             return true;
           }
@@ -419,6 +419,10 @@ dState matchesNSEC(const DNSName& name, uint16_t qtype, const DNSName& nsecOwner
       return dState::NODENIAL;
     }
 
+    if (nsec->isSet(QType::DNAME)) {
+      return dState::NODENIAL;
+    }
+
     return dState::NXQTYPE;
   }
 
@@ -500,6 +504,11 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16
             return dState::NODENIAL;
           }
 
+          if (nsec->isSet(QType::DNAME)) {
+            LOG("However a CNAME exists"<<endl);
+            return dState::NODENIAL;
+          }
+
           /*
            * RFC 4035 Section 2.3:
            * The bitmap for the NSEC RR at a delegation point requires special
@@ -622,6 +631,11 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16
             return dState::NODENIAL;
           }
 
+          if (nsec3->isSet(QType::DNAME)) {
+            LOG("However a CNAME exists"<<endl);
+            return dState::NODENIAL;
+          }
+
           /*
            * RFC 5155 section 8.9:
            * If there is an NSEC3 RR present in the response that matches the