From: Mark Andrews Date: Tue, 17 Nov 2020 00:50:42 +0000 (+1100) Subject: Fix DNAME when QTYPE is CNAME or ANY X-Git-Tag: v9.11.26~5^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ca9dc40634f8747857fb07b55f54e6a2e91bf14b;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 5d899f0aff2..da22e43c64c 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,9 @@ 5539. [bug] Tighten handling of missing DNS COOKIE responses over UDP by falling back to TCP. [GL #2275] +5534. [bug] The synthesised CNAME from a DNAME was incorrectly + followed when the QTYPE was CNAME or ANY. [GL #2280] + --- 9.11.25 released --- 5527. [bug] A NULL pointer dereference occurred when creating an NTA diff --git a/bin/named/query.c b/bin/named/query.c index f860d2e20c6..3d196f1277e 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -8651,13 +8651,21 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) if (result != ISC_R_SUCCESS) goto cleanup; /* - * 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(client, fname); - fname = NULL; - want_restart = true; - if (!WANTRECURSION(client)) - options |= DNS_GETDB_NOLOG; + if (qtype != dns_rdatatype_cname && + qtype != dns_rdatatype_any) + { + /* + * Switch to the new qname and restart. + */ + ns_client_qnamereplace(client, fname); + fname = NULL; + want_restart = true; + if (!WANTRECURSION(client)) + options |= DNS_GETDB_NOLOG; + } goto addauth; default: /* diff --git a/bin/tests/system/auth/clean.sh b/bin/tests/system/auth/clean.sh new file mode 100644 index 00000000000..adb9b67e669 --- /dev/null +++ b/bin/tests/system/auth/clean.sh @@ -0,0 +1,16 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +rm -f */named.memstats +rm -f */named.run +rm -f */named.conf +rm -f dig.out.test* +rm -f ns2/example.com.bk +rm -f ns2/example.net.bk +rm -f ns*/managed-keys.bind* ns*/*mkeys* diff --git a/bin/tests/system/auth/ns1/chaos.db b/bin/tests/system/auth/ns1/chaos.db new file mode 100644 index 00000000000..175b84b1f69 --- /dev/null +++ b/bin/tests/system/auth/ns1/chaos.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ CH SOA ns root ( + 2018010100 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A ch-addr.example. 1001 +test A ch-addr.example. 1002 + A ch-addr.example. 1003 diff --git a/bin/tests/system/auth/ns1/example.com.db b/bin/tests/system/auth/ns1/example.com.db new file mode 100644 index 00000000000..542b0d5b5e8 --- /dev/null +++ b/bin/tests/system/auth/ns1/example.com.db @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2018010100 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +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/ns1/example.net.db b/bin/tests/system/auth/ns1/example.net.db new file mode 100644 index 00000000000..13d51527b44 --- /dev/null +++ b/bin/tests/system/auth/ns1/example.net.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2018010100 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.1 +server A 10.53.0.100 diff --git a/bin/tests/system/auth/ns1/named.conf.in b/bin/tests/system/auth/ns1/named.conf.in new file mode 100644 index 00000000000..c004d8a0812 --- /dev/null +++ b/bin/tests/system/auth/ns1/named.conf.in @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; +}; + +view main in { + zone example.net { + type master; + file "example.net.db"; + }; + + zone example.com { + type master; + file "example.com.db"; + }; +}; + +view alt chaos { + zone example.chaos chaos { + type master; + file "chaos.db"; + }; +}; diff --git a/bin/tests/system/auth/ns2/named.conf.in b/bin/tests/system/auth/ns2/named.conf.in new file mode 100644 index 00000000000..c99fb88d175 --- /dev/null +++ b/bin/tests/system/auth/ns2/named.conf.in @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion yes; + notify no; +}; + +zone example.net { + type slave; + masters { 10.53.0.1; }; + file "example.net.bk"; +}; + +zone example.com { + type slave; + masters { 10.53.0.1; }; + file "example.com.bk"; +}; diff --git a/bin/tests/system/auth/setup.sh b/bin/tests/system/auth/setup.sh new file mode 100644 index 00000000000..5c160b922eb --- /dev/null +++ b/bin/tests/system/auth/setup.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf diff --git a/bin/tests/system/auth/tests.sh b/bin/tests/system/auth/tests.sh new file mode 100644 index 00000000000..cc7e11535ba --- /dev/null +++ b/bin/tests/system/auth/tests.sh @@ -0,0 +1,189 @@ +#!/bin/sh +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +DIGOPTS="+tcp -p ${PORT}" + +status=0 +n=0 + +n=`expr $n + 1` +echo_i "wait for zones to finish transferring to ns2 ($n)" +for i in 1 2 3 4 5 6 7 8 9 10 +do + ret=0 + for zone in example.com example.net + do + $DIG $DIGOPTS @10.53.0.2 soa $zone > dig.out.test$n || ret=1 + grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +[ $ret -eq 0 ] || echo_i "failed" +status=`expr $status + $ret` + +# +# Cross zone CNAME behaviour is changed in version 9.12.1 BIND. +# The CNAME is not followed in subsequent versions unless it is a +# recursive query and recursion is allowed (rd=1/ra=1). +# +n=`expr $n + 1` +echo_i "check that cross-zone CNAME records return target data (rd=0/ra=0) ($n)" +ret=0 +$DIG $DIGOPTS +norec @10.53.0.1 www.example.com > dig.out.test$n || ret=1 +grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1 +grep "flags: qr aa;" dig.out.test$n > /dev/null || ret=1 +grep "www.example.com.*CNAME.*server.example.net" dig.out.test$n > /dev/null || ret=1 +grep "server.example.net.*A.*10.53.0.100" 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 cross-zone CNAME records return target data (rd=1/ra=0) ($n)" +ret=0 +$DIG $DIGOPTS +rec @10.53.0.1 www.example.com > dig.out.test$n || ret=1 +grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1 +grep "flags: qr aa rd;" dig.out.test$n > /dev/null || ret=1 +grep "www.example.com.*CNAME.*server.example.net" dig.out.test$n > /dev/null || ret=1 +grep "server.example.net.*A.*10.53.0.100" 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 cross-zone CNAME records return target data (rd=0/ra=1) ($n)" +ret=0 +$DIG $DIGOPTS +norec @10.53.0.2 www.example.com > dig.out.test$n || ret=1 +grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1 +grep "flags: qr aa ra;" dig.out.test$n > /dev/null || ret=1 +grep "www.example.com.*CNAME.*server.example.net" dig.out.test$n > /dev/null || ret=1 +grep "server.example.net.*A.*10.53.0.100" 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 cross-zone CNAME records return target data (rd=1/ra=1) ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 www.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 "www.example.com.*CNAME.*server.example.net" dig.out.test$n > /dev/null || ret=1 +grep "server.example.net.*A.*10.53.0.100" dig.out.test$n > /dev/null || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=`expr $status + $ret` + +# +# In-zone CNAME records should always be followed regardless of RD and RA. +# +n=`expr $n + 1` +echo_i "check that in-zone CNAME records return target data (rd=0/ra=0) ($n)" +ret=0 +$DIG $DIGOPTS +norec @10.53.0.1 inzone.example.com > dig.out.test$n || ret=1 +grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1 +grep "flags: qr aa;" 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 return target data (rd=1/ra=0) ($n)" +ret=0 +$DIG $DIGOPTS +rec @10.53.0.1 inzone.example.com > dig.out.test$n || ret=1 +grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1 +grep "flags: qr aa rd;" 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 return target data (rd=0/ra=1) ($n)" +ret=0 +$DIG $DIGOPTS +norec @10.53.0.2 inzone.example.com > dig.out.test$n || ret=1 +grep "ANSWER: 2," dig.out.test$n > /dev/null || ret=1 +grep "flags: qr aa 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 return target data (rd=1/ra=1) ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 inzone.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 "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 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 +$DIG $DIGOPTS @10.53.0.1 +noall +answer ch test.example.chaos > dig.out.test$n +lines=`wc -l < dig.out.test$n` +[ ${lines:-0} -eq 2 ] || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=`expr $status + $ret` + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in index 095f8fbca45..a4daa223526 100644 --- a/bin/tests/system/conf.sh.in +++ b/bin/tests/system/conf.sh.in @@ -111,7 +111,7 @@ SEQUENTIALDIRS="ecdsa eddsa gost lwresd @PKCS11_TEST@ tkey" # Note: some of the longer-running tests are scheduled first, # in order to get more benefit from parallelism. PARALLELDIRS="dnssec rpzrecurse \ - acl additional addzone allow-query autosign \ + acl additional addzone allow-query auth autosign \ builtin cacheclean case catz chain \ checkconf checknames checkzone \ @CHECKDS@ @COVERAGE@ @KEYMGR@ \ diff --git a/doc/arm/notes-9.11.26.xml b/doc/arm/notes-9.11.26.xml index b925ccbedd9..6e5c7facfd5 100644 --- a/doc/arm/notes-9.11.26.xml +++ b/doc/arm/notes-9.11.26.xml @@ -76,8 +76,13 @@ #2315] + + + The synthesised CNAME from a DNAME was incorrectly followed + when the QTYPE was CNAME or ANY. [GL #2280] + + - diff --git a/util/copyrights b/util/copyrights index 938ac5c466a..4295f2e55e1 100644 --- a/util/copyrights +++ b/util/copyrights @@ -589,6 +589,14 @@ ./bin/tests/system/allow-query/setup.sh SH 2018,2019,2020 ./bin/tests/system/allow-query/tests.sh SH 2018,2019,2020 ./bin/tests/system/ans.pl PERL 2011,2012,2014,2016,2017,2018,2019,2020 +./bin/tests/system/auth/clean.sh SH 2018,2019,2020 +./bin/tests/system/auth/ns1/chaos.db ZONE 2018,2019,2020 +./bin/tests/system/auth/ns1/example.com.db ZONE 2018,2019,2020 +./bin/tests/system/auth/ns1/example.net.db ZONE 2018,2019,2020 +./bin/tests/system/auth/ns1/named.conf.in CONF-C 2018,2019,2020 +./bin/tests/system/auth/ns2/named.conf.in CONF-C 2018,2019,2020 +./bin/tests/system/auth/setup.sh SH 2018,2019,2020 +./bin/tests/system/auth/tests.sh SH 2018,2019,2020 ./bin/tests/system/autosign/clean.sh SH 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020 ./bin/tests/system/autosign/ns1/keygen.sh SH 2009,2010,2011,2012,2014,2016,2018,2019,2020 ./bin/tests/system/autosign/ns1/named.conf.in CONF-C 2018,2019,2020