diff --git a/CHANGES b/CHANGES index 8aa352925c..90a7585b92 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 a6c98de41c..a61c88229e 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 f9daf43426..ecfd451ad5 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 2a784e95fd..412993e09f 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 33c7b6a2db..e329b55e4c 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);