]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: Don't follow referral from the parent to the child for DS queries
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 31 May 2021 15:00:18 +0000 (17:00 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 31 May 2021 15:15:01 +0000 (17:15 +0200)
It happens if the server does not know about the DS special case.
Treat the delegation as a unsigned NODATA answer in that case.

For example for sthc.nordlo.cloud we go from the existing:

```
[1]   sthc.nordlo.cloud: Resolved 'nordlo.cloud' NS ns2.zetup.se to: 159.253.27.75
[1]   sthc.nordlo.cloud: Trying IP 159.253.27.75:53, asking 'sthc.nordlo.cloud|DS'
[1]   sthc.nordlo.cloud: Got 3 answers from ns2.zetup.se (159.253.27.75), rcode=0 (No Error), aa=0, in 35ms
[1]   sthc.nordlo.cloud: accept answer 'sthc.nordlo.cloud|NS|ns2.loopia.se.' from 'nordlo.cloud' nameservers? ttl=3600, place=2 YES!
[1]   sthc.nordlo.cloud: accept answer 'sthc.nordlo.cloud|NS|ns1.loopia.se.' from 'nordlo.cloud' nameservers? ttl=3600, place=2 YES!
[1]   sthc.nordlo.cloud: OPT answer '.' from 'nordlo.cloud' nameservers
[1]   sthc.nordlo.cloud: determining status after receiving this packet
[1]   sthc.nordlo.cloud: got NS record 'sthc.nordlo.cloud' -> 'ns2.loopia.se.'
[1]   sthc.nordlo.cloud: got NS record 'sthc.nordlo.cloud' -> 'ns1.loopia.se.'
[1]   sthc.nordlo.cloud: status=did not resolve, got 2 NS, looping to them
[1]   sthc.nordlo.cloud.: Nameservers: ns1.loopia.se(37.85ms), ns2.loopia.se(38.26ms)
[1]   sthc.nordlo.cloud: Trying to resolve NS 'ns1.loopia.se' (1/2)
[1]   Nameserver ns1.loopia.se IPs: 93.188.0.20(37.85ms)
[1]   sthc.nordlo.cloud: Resolved 'sthc.nordlo.cloud' NS ns1.loopia.se to: 93.188.0.20
[1]   sthc.nordlo.cloud: Trying IP 93.188.0.20:53, asking 'sthc.nordlo.cloud|DS'
```

to:

```
[1]   sthc.nordlo.cloud: Resolved 'nordlo.cloud' NS ns2.zetup.se to: 159.253.27.75
[1]   sthc.nordlo.cloud: Trying IP 159.253.27.75:53, asking 'sthc.nordlo.cloud|DS'
[1]   sthc.nordlo.cloud: Got 3 answers from ns2.zetup.se (159.253.27.75), rcode=0 (No Error), aa=0, in 35ms
[1]   sthc.nordlo.cloud: accept answer 'sthc.nordlo.cloud|NS|ns2.loopia.se.' from 'nordlo.cloud' nameservers? ttl=3600, place=2 YES!
[1]   sthc.nordlo.cloud: accept answer 'sthc.nordlo.cloud|NS|ns1.loopia.se.' from 'nordlo.cloud' nameservers? ttl=3600, place=2 YES!
[1]   sthc.nordlo.cloud: OPT answer '.' from 'nordlo.cloud' nameservers
[1]   sthc.nordlo.cloud: determining status after receiving this packet
[1]   sthc.nordlo.cloud: got NS record 'sthc.nordlo.cloud' -> 'ns2.loopia.se.'
[1]   sthc.nordlo.cloud: got (implicit) negative indication of DS record for 'sthc.nordlo.cloud'
[1]   sthc.nordlo.cloud: got NS record 'sthc.nordlo.cloud' -> 'ns1.loopia.se.'
[1]   sthc.nordlo.cloud: status=noerror, other types may exist, but we are done (have negative SOA)
[1] : no signatures for sthc.nordlo.cloud, we likely missed a cut between cloud and nordlo.cloud, looking for it
```

pdns/syncres.cc

index 486db97452519dec6026409044cfa331279e9786..106abef503bdf1873d87ca1a4898bfccd0aeb03c 100644 (file)
@@ -3590,13 +3590,25 @@ bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, co
       if (moreSpecificThan(rec.d_name,auth)) {
         newauth = rec.d_name;
         LOG(prefix<<qname<<": got NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
-        realreferral = true;
+
+        if (!negindic && qtype == QType::DS && qname == newauth) {
+          /* just got a referral from the parent zone when asking for a DS, looks like this server did not get the DNSSE memo.. */
+          LOG(prefix<<qname<<": got (implicit) negative indication of DS record for '"<<qname<<"'"<<endl);
+          negindic = true;
+          negIndicHasSignatures = false;
+          nsset.clear();
+        }
+        else {
+          realreferral = true;
+        }
       }
       else {
         LOG(prefix<<qname<<": got upwards/level NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"', had '"<<auth<<"'"<<endl);
       }
-      if (auto content = getRR<NSRecordContent>(rec)) {
-        nsset.insert(content->getNS());
+      if (!negindic) {
+        if (auto content = getRR<NSRecordContent>(rec)) {
+          nsset.insert(content->getNS());
+        }
       }
     }
     else if (rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::DS && qname.isPartOf(rec.d_name)) {
@@ -3631,7 +3643,7 @@ bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, co
               g_negCache->add(ne);
             }
 
-            if (qname == newauth && qtype == QType::DS) {
+            if (qtype == QType::DS && qname == newauth) {
               /* we are actually done! */
               negindic = true;
               negIndicHasSignatures = !ne.authoritySOA.signatures.empty() || !ne.DNSSECRecords.signatures.empty();