From: Mark Andrews Date: Tue, 17 Nov 2020 00:03:21 +0000 (+1100) Subject: Fix DNAME when QTYPE is CNAME or ANY X-Git-Tag: v9.17.8~37^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e980affba0ed40476d977d284d142988633b6a7d;p=thirdparty%2Fbind9.git Fix DNAME when QTYPE is CNAME or ANY The synthesised CNAME is not supposed to be followed when the QTYPE is CNAME or ANY as the lookup is satisfied by the CNAME record. --- diff --git a/CHANGES b/CHANGES index 8aa352925c2..90a7585b92e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +5534. [bug] The synthesised CNAME from a DNAME was incorrectly + followed when the QTYPE was CNAME or ANY. [GL #2280] + 5533. [func] Add "stale-refresh-time" option, a time window that starts after a failed lookup, during which stale rrset will be served directly from cache before a new diff --git a/bin/tests/system/auth/ns1/example.com.db b/bin/tests/system/auth/ns1/example.com.db index a6c98de41c2..a61c88229e0 100644 --- a/bin/tests/system/auth/ns1/example.com.db +++ b/bin/tests/system/auth/ns1/example.com.db @@ -20,3 +20,4 @@ ns A 10.53.0.1 www CNAME server.example.net. inzone CNAME a.example.com. a A 10.53.0.1 +dname DNAME @ diff --git a/bin/tests/system/auth/tests.sh b/bin/tests/system/auth/tests.sh index f9daf434264..ecfd451ad59 100644 --- a/bin/tests/system/auth/tests.sh +++ b/bin/tests/system/auth/tests.sh @@ -127,6 +127,54 @@ grep "a.example.com.*A.*10.53.0.1" dig.out.test$n > /dev/null || ret=1 [ $ret -eq 0 ] || echo_i "failed" status=`expr $status + $ret` +n=`expr $n + 1` +echo_i "check that in-zone CNAME records does not return target data when QTYPE is CNAME (rd=1/ra=1) ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -t cname inzone.example.com > dig.out.test$n || ret=1 +grep 'ANSWER: 1,' dig.out.test$n > /dev/null || ret=1 +grep 'flags: qr aa rd ra;' dig.out.test$n > /dev/null || ret=1 +grep 'inzone\.example\.com\..*CNAME.a\.example\.com\.' dig.out.test$n > /dev/null || ret=1 +grep 'a\.example\.com\..*A.10\.53\.0\.1' dig.out.test$n > /dev/null && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=`expr $status + $ret` + +n=`expr $n + 1` +echo_i "check that in-zone CNAME records does not return target data when QTYPE is ANY (rd=1/ra=1) ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -t any inzone.example.com > dig.out.test$n || ret=1 +grep 'ANSWER: 1,' dig.out.test$n > /dev/null || ret=1 +grep 'flags: qr aa rd ra;' dig.out.test$n > /dev/null || ret=1 +grep 'inzone\.example\.com\..*CNAME.a\.example\.com\.' dig.out.test$n > /dev/null || ret=1 +grep 'a\.example\.com\..*A.10\.53\.0\.1' dig.out.test$n > /dev/null && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=`expr $status + $ret` + +n=`expr $n + 1` +echo_i "check that in-zone DNAME records does not return target data when QTYPE is CNAME (rd=1/ra=1) ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -t cname inzone.dname.example.com > dig.out.test$n || ret=1 +grep 'ANSWER: 2,' dig.out.test$n > /dev/null || ret=1 +grep 'flags: qr aa rd ra;' dig.out.test$n > /dev/null || ret=1 +grep 'dname\.example\.com\..*DNAME.example\.com\.' dig.out.test$n > /dev/null || ret=1 +grep 'inzone\.dname\.example\.com\..*CNAME.inzone\.example\.com\.' dig.out.test$n > /dev/null || ret=1 +grep 'inzone\.example\.com\..*CNAME.a\.example\.com\.' dig.out.test$n > /dev/null && ret=1 +grep 'a\.example\.com\..*A.10\.53\.0\.1' dig.out.test$n > /dev/null && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=`expr $status + $ret` + +n=`expr $n + 1` +echo_i "check that in-zone DNAME records does not return target data when QTYPE is ANY (rd=1/ra=1) ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -t any inzone.dname.example.com > dig.out.test$n || ret=1 +grep 'ANSWER: 2,' dig.out.test$n > /dev/null || ret=1 +grep 'flags: qr aa rd ra;' dig.out.test$n > /dev/null || ret=1 +grep 'dname\.example\.com\..*DNAME.example\.com\.' dig.out.test$n > /dev/null || ret=1 +grep 'inzone\.dname\.example\.com\..*CNAME.inzone\.example\.com\.' dig.out.test$n > /dev/null || ret=1 +grep 'inzone\.example\.com.*CNAME.a\.example\.com\.' dig.out.test$n > /dev/null && ret=1 +grep 'a\.example\.com.*A.10\.53\.0\.1' dig.out.test$n > /dev/null && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=`expr $status + $ret` + n=`expr $n + 1` echo_i "check that CHAOS addresses are compared correctly ($n)" ret=0 diff --git a/doc/notes/notes-current.rst b/doc/notes/notes-current.rst index 2a784e95fdf..412993e09f4 100644 --- a/doc/notes/notes-current.rst +++ b/doc/notes/notes-current.rst @@ -65,3 +65,6 @@ Bug Fixes - ``named`` could crash with an assertion failure if a TCP connection is closed while the request is still processing. [GL #2227] + +- The synthesised CNAME from a DNAME was incorrectly followed when the QTYPE + was CNAME or ANY. [GL #2280] diff --git a/lib/ns/query.c b/lib/ns/query.c index 33c7b6a2db2..e329b55e4cf 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -9897,13 +9897,20 @@ query_dname(query_ctx_t *qctx) { } /* - * Switch to the new qname and restart. + * If the original query was not for a CNAME or ANY then follow the + * CNAME. */ - ns_client_qnamereplace(qctx->client, qctx->fname); - qctx->fname = NULL; - qctx->want_restart = true; - if (!WANTRECURSION(qctx->client)) { - qctx->options |= DNS_GETDB_NOLOG; + if (qctx->qtype != dns_rdatatype_cname && + qctx->qtype != dns_rdatatype_any) { + /* + * Switch to the new qname and restart. + */ + ns_client_qnamereplace(qctx->client, qctx->fname); + qctx->fname = NULL; + qctx->want_restart = true; + if (!WANTRECURSION(qctx->client)) { + qctx->options |= DNS_GETDB_NOLOG; + } } query_addauth(qctx);