diff --git a/CHANGES b/CHANGES index 62241743c7..ddf889645e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +6366. [bug] An assertion could be triggered in the QPDB cache when + encountering a delegation below a DNAME. [GL #4652] + 6365. [placeholder] 6364. [protocol] Add RESOLVER.ARPA to the built in empty zones. diff --git a/bin/tests/system/chain/ans3/ans.pl b/bin/tests/system/chain/ans3/ans.pl index e42240be63..434eaa9809 100644 --- a/bin/tests/system/chain/ans3/ans.pl +++ b/bin/tests/system/chain/ans3/ans.pl @@ -51,22 +51,22 @@ sub reply_handler { STDOUT->flush(); if ($qname eq "example.broken") { - if ($qtype eq "SOA") { + if ($qtype eq "SOA") { my $rr = new Net::DNS::RR("$qname $ttl $qclass SOA . . 0 0 0 0 0"); push @ans, $rr; - } elsif ($qtype eq "NS") { + } elsif ($qtype eq "NS") { my $rr = new Net::DNS::RR("$qname $ttl $qclass NS $nsname"); push @ans, $rr; $rr = new Net::DNS::RR("$nsname $ttl $qclass A $localaddr"); push @add, $rr; - } - $rcode = "NOERROR"; + } + $rcode = "NOERROR"; } elsif ($qname eq "cname-to-$synth2") { - my $rr = new Net::DNS::RR("$qname $ttl $qclass CNAME name.$synth2"); + my $rr = new Net::DNS::RR("$qname $ttl $qclass CNAME name.$synth2"); push @ans, $rr; - $rr = new Net::DNS::RR("name.$synth2 $ttl $qclass CNAME name"); + $rr = new Net::DNS::RR("name.$synth2 $ttl $qclass CNAME name"); push @ans, $rr; - $rr = new Net::DNS::RR("$synth2 $ttl $qclass DNAME ."); + $rr = new Net::DNS::RR("$synth2 $ttl $qclass DNAME ."); push @ans, $rr; $rcode = "NOERROR"; } elsif ($qname eq "$synth" || $qname eq "$synth2") { @@ -115,6 +115,30 @@ sub reply_handler { push @ans, $rr; } $rcode = "NOERROR"; + # The next few branches produce a zone with an illegal NS below a DNAME. + } elsif ($qname eq "jeff.dname") { + if ($qtype eq "SOA") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass SOA . . 0 0 0 0 0"); + push @ans, $rr; + } elsif ($qtype eq "NS") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass NS ns.jeff.dname."); + push @ans, $rr; + $rr = new Net::DNS::RR("$nsname $ttl $qclass A $localaddr"); + push @add, $rr; + } elsif ($qtype eq "DNAME") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass DNAME mutt.example."); + push @ans, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "ns.jeff.dname") { + if ($qtype eq "A") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass A 10.53.0.3"); + push @ans, $rr; + } elsif ($qtype eq "AAAA") { + my $rr = new Net::DNS::RR("jeff.dname. $ttl $qclass SOA . . 0 0 0 0 $ttl"); + push @auth, $rr; + } + $rcode = "NOERROR"; } else { $rcode = "REFUSED"; } diff --git a/bin/tests/system/chain/ns1/root.db b/bin/tests/system/chain/ns1/root.db index 3469fb526b..1c99ba865c 100644 --- a/bin/tests/system/chain/ns1/root.db +++ b/bin/tests/system/chain/ns1/root.db @@ -30,6 +30,10 @@ ns3.example.broken. A 10.53.0.3 example.dname. NS ns3.example.dname. ns3.example.dname. A 10.53.0.3 +; regression test for illegal NS below DNAME +jeff.dname. NS ns.jeff.dname. +ns.jeff.dname. A 10.53.0.3 + domain0.nil. NS ns2.domain0.nil domain1.nil. NS ns2.domain0.nil domain2.nil. NS ns2.domain0.nil diff --git a/bin/tests/system/chain/ns2/example.db b/bin/tests/system/chain/ns2/example.db index c13f2d22d4..a5a4811b1a 100644 --- a/bin/tests/system/chain/ns2/example.db +++ b/bin/tests/system/chain/ns2/example.db @@ -48,6 +48,9 @@ signed-sub2 NS ns2.sub2 signed-sub2 DS 44137 8 2 1CB4F54E0B4F4F85109143113A3C679716A2377D86EB0907846A03FB 0C0A3927 d CNAME d.signed-sub2 +mutt NS ns5.mutt +ns5.mutt A 10.53.0.5 + ; long CNAME loop loop CNAME goop goop CNAME boop diff --git a/bin/tests/system/chain/ns5/named.conf.in b/bin/tests/system/chain/ns5/named.conf.in index ba8cc6f001..00f0de5857 100644 --- a/bin/tests/system/chain/ns5/named.conf.in +++ b/bin/tests/system/chain/ns5/named.conf.in @@ -40,3 +40,8 @@ zone "signed-sub5.example" { type primary; file "sub.db"; }; + +zone "mutt.example" { + type primary; + file "mutt.db"; +}; diff --git a/bin/tests/system/chain/tests.sh b/bin/tests/system/chain/tests.sh index 4957fe769b..dc49ff5141 100644 --- a/bin/tests/system/chain/tests.sh +++ b/bin/tests/system/chain/tests.sh @@ -626,5 +626,16 @@ grep 'status: NOERROR' dig.out.7.$n >/dev/null 2>&1 || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) +# Regression test for GL #4652 +n=$((n + 1)) +echo_i "checking handling of illegal NS below DNAME ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.7 DNAME jeff.dname. >dig.out.ns7.1.$n 2>&1 +grep 'status: NOERROR' dig.out.ns7.1.$n >/dev/null 2>&1 || ret=1 +$DIG $DIGOPTS @10.53.0.7 NS jeff.dname. >dig.out.ns7.2.$n 2>&1 +grep 'status: SERVFAIL' dig.out.ns7.2.$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + echo_i "exit status: $status" [ $status -eq 0 ] || exit 1 diff --git a/lib/dns/qpcache.c b/lib/dns/qpcache.c index 1b5f5ceb7c..36b55d80a6 100644 --- a/lib/dns/qpcache.c +++ b/lib/dns/qpcache.c @@ -1702,6 +1702,8 @@ find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, encloser, (void *)&search DNS__DB_FLARG_PASS); if (zcresult != DNS_R_CONTINUE) { result = DNS_R_PARTIALMATCH; + dns_qpchain_node(&search.chain, i, foundname, + NULL, NULL); search.chain.len = i - 1; node = encloser; break; diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c index 6dba83e781..c78267db89 100644 --- a/lib/dns/qpzone.c +++ b/lib/dns/qpzone.c @@ -3453,6 +3453,8 @@ find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, tresult = check_zonecut(n, &search DNS__DB_FLARG_PASS); if (tresult != DNS_R_CONTINUE) { result = tresult; + dns_qpchain_node(&search.chain, i, foundname, NULL, + NULL); search.chain.len = i - 1; node = n; }