diff --git a/CHANGES b/CHANGES index 589528fe19..8010c50c1d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +4864. [bug] named acting as a slave for a catalog zone crashed if + the latter contained a master definition without an IP + address. [RT #45999] + 4863. [bug] Fix various other bugs reported by Valgrind's memcheck tool. [RT #46978] diff --git a/bin/named/server.c b/bin/named/server.c index 8c0668dd6b..c22a6e7ec6 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -2548,11 +2548,17 @@ catz_addmodzone_taskaction(isc_task_t *task, isc_event_t *event0) { RUNTIME_CHECK(zone == NULL); /* Create a config for new zone */ confbuf = NULL; - dns_catz_generate_zonecfg(ev->origin, ev->entry, &confbuf); - cfg_parser_reset(cfg->add_parser); - result = cfg_parse_buffer3(cfg->add_parser, confbuf, "catz", 0, - &cfg_type_addzoneconf, &zoneconf); - isc_buffer_free(&confbuf); + result = dns_catz_generate_zonecfg(ev->origin, ev->entry, &confbuf); + if (result == ISC_R_SUCCESS) { + cfg_parser_reset(cfg->add_parser); + result = cfg_parse_buffer3(cfg->add_parser, confbuf, "catz", 0, + &cfg_type_addzoneconf, &zoneconf); + isc_buffer_free(&confbuf); + } + /* + * Fail if either dns_catz_generate_zonecfg() or cfg_parse_buffer3() + * failed. + */ if (result != ISC_R_SUCCESS) { isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, diff --git a/bin/tests/system/catz/tests.sh b/bin/tests/system/catz/tests.sh index 11b1fc8c62..0896cc41e2 100644 --- a/bin/tests/system/catz/tests.sh +++ b/bin/tests/system/catz/tests.sh @@ -341,7 +341,7 @@ status=`expr $status + $ret` ########################################################################## echo "I:Testing masters suboption and random labels" n=`expr $n + 1` -echo "I: adding dom5.example with 'masters' suboption set and a random label ($n)" +echo "I: adding dom5.example with a valid masters suboption (IP without TSIG) and a random label ($n)" ret=0 $NSUPDATE -d <> nsupdate.out.test$n 2>&1 || ret=1 server 10.53.0.1 5300 @@ -433,7 +433,7 @@ status=`expr $status + $ret` ########################################################################## echo "I:Testing masters global option" n=`expr $n + 1` -echo "I: adding dom6.example and global masters option ($n)" +echo "I: adding dom6.example and a valid global masters option (IP without TSIG) ($n)" ret=0 $NSUPDATE -d <> nsupdate.out.test$n 2>&1 || ret=1 server 10.53.0.1 5300 @@ -526,6 +526,77 @@ grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I: failed"; fi status=`expr $status + $ret` +cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run` + +n=`expr $n + 1` +echo "I: adding dom6.example and an invalid global masters option (TSIG without IP) ($n)" +ret=0 +$NSUPDATE -d <> nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 5300 + update add label1.masters.catalog1.example 3600 IN TXT "tsig_key" + update add 4346f565b4d63ddb99e5d2497ff22d04e878e8f8.zones.catalog1.example 3600 IN PTR dom6.example. + send +END +if [ $ret != 0 ]; then echo "I: failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I: waiting for slave to sync up ($n)" +ret=1 +try=0 +while test $try -lt 45 +do + sleep 1 + sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom6.example' from catalog 'catalog1.example'" > /dev/null && { + ret=0 + break + } + try=`expr $try + 1` +done +if [ $ret = 0 ]; then + ret=1 + try=0 + while test $try -lt 45 + do + sleep 1 + sed -n "$cur,"'$p' < ns2/named.run | grep "error .* while trying to generate config for zone \"dom6.example\"" > /dev/null && { + + ret=0 + break + } + try=`expr $try + 1` + done +fi +if [ $ret != 0 ]; then echo "I: failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I: removing dom6.example ($n)" +ret=0 +$NSUPDATE -d <> nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 5300 + update delete label1.masters.catalog1.example 3600 IN TXT "tsig_key" + update delete 4346f565b4d63ddb99e5d2497ff22d04e878e8f8.zones.catalog1.example 3600 IN PTR dom6.example. + send +END +if [ $ret != 0 ]; then echo "I: failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I: waiting for slave to sync up ($n)" +ret=1 +try=0 +while test $try -lt 45 +do + sleep 1 + sed -n "$cur,"'$p' < ns2/named.run | grep "catz: deleting zone 'dom6.example' from catalog 'catalog1.example'" > /dev/null && { + ret=0 + break + } + try=`expr $try + 1` +done +if [ $ret != 0 ]; then echo "I: failed"; fi +status=`expr $status + $ret` ########################################################################## n=`expr $n + 1` @@ -769,7 +840,7 @@ status=`expr $status + $ret` cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run` n=`expr $n + 1` -echo "I: adding domain dom9.example to catalog1 zone with masters and tsig key($n)" +echo "I: adding domain dom9.example to catalog1 zone with a valid masters suboption (IP with TSIG) ($n)" ret=0 $NSUPDATE -d <> nsupdate.out.test$n 2>&1 || ret=1 server 10.53.0.1 5300 @@ -819,7 +890,7 @@ if [ $ret != 0 ]; then echo "I: failed"; fi status=`expr $status + $ret` n=`expr $n + 1` -echo "I: deleting domain dom9.example from catalog1 zone($n)" +echo "I: deleting domain dom9.example from catalog1 zone ($n)" ret=0 $NSUPDATE -d <> nsupdate.out.test$n 2>&1 || ret=1 server 10.53.0.1 5300 @@ -855,6 +926,78 @@ grep "status: REFUSED" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I: failed"; fi status=`expr $status + $ret` +cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run` + +n=`expr $n + 1` +echo "I: adding domain dom9.example to catalog1 zone with an invalid masters suboption (TSIG without IP) ($n)" +ret=0 +$NSUPDATE -d <> nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 5300 + update add f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example 3600 IN PTR dom9.example. + update add label1.masters.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example 3600 IN TXT "tsig_key" + send +END +if [ $ret != 0 ]; then echo "I: failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I: waiting for slave to sync up ($n)" +ret=1 +try=0 +while test $try -lt 45 +do + sleep 1 + sed -n "$cur,"'$p' < ns2/named.run | grep "catz: adding zone 'dom9.example' from catalog 'catalog1.example'" > /dev/null && { + ret=0 + break + } + try=`expr $try + 1` +done +if [ $ret = 0 ]; then + ret=1 + try=0 + while test $try -lt 45 + do + sleep 1 + sed -n "$cur,"'$p' < ns2/named.run | grep "error .* while trying to generate config for zone \"dom9.example\"" > /dev/null && { + + ret=0 + break + } + try=`expr $try + 1` + done +fi +if [ $ret != 0 ]; then echo "I: failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I: deleting domain dom9.example from catalog1 zone ($n)" +ret=0 +$NSUPDATE -d <> nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 5300 + update delete f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example 3600 IN PTR dom9.example. + update delete label1.masters.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example 3600 IN TXT "tsig_key" + send +END +if [ $ret != 0 ]; then echo "I: failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I: waiting for slave to sync up ($n)" +ret=1 +try=0 +while test $try -lt 45 +do + sleep 1 + sed -n "$cur,"'$p' < ns2/named.run | grep "catz: deleting zone 'dom9.example' from catalog 'catalog1.example'" > /dev/null && { + ret=0 + break + } + try=`expr $try + 1` +done +if [ $ret != 0 ]; then echo "I: failed"; fi +status=`expr $status + $ret` + ########################################################################## echo "I:Testing very long domain in catalog" n=`expr $n + 1` @@ -933,7 +1076,7 @@ if [ $ret != 0 ]; then echo "I: failed"; fi status=`expr $status + $ret` n=`expr $n + 1` -echo "I: checking that zone-directory is populated with a hashed filename($n)" +echo "I: checking that zone-directory is populated with a hashed filename ($n)" ret=0 [ -f "ns2/zonedir/__catz__4d70696f2335687069467f11f5d5378c480383f97782e553fb2d04a7bb2a23ed.db" ] || ret=1 if [ $ret != 0 ]; then echo "I: failed"; fi @@ -1329,7 +1472,15 @@ if [ $ret != 0 ]; then echo "I: failed"; fi status=`expr $status + $ret` n=`expr $n + 1` -echo "I: reconfiguring slave - removing catalog4 catalog zone ($n)" +echo "I: reconfiguring slave - removing catalog4 catalog zone, adding non-existent catalog5 catalog zone ($n)" +ret=0 +cat ns2/named.conf.in | sed -e "s/^#T2//" > ns2/named.conf +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reconfig > /dev/null 2>&1 && ret=1 +if [ $ret != 0 ]; then echo "I: failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I: reconfiguring slave - removing non-existent catalog5 catalog zone ($n)" ret=0 cat ns2/named.conf.in > ns2/named.conf $RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reconfig || ret=1 @@ -1405,7 +1556,7 @@ status=`expr $status + $ret` cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run` n=`expr $n + 1` -echo "I: Adding domain dom13.example to catalog1 zone with ns1 as master($n)" +echo "I: Adding domain dom13.example to catalog1 zone with ns1 as master ($n)" ret=0 $NSUPDATE -d <> nsupdate.out.test$n 2>&1 || ret=1 server 10.53.0.1 5300 @@ -1457,7 +1608,7 @@ if [ $ret != 0 ]; then echo "I: failed"; fi status=`expr $status + $ret` n=`expr $n + 1` -echo "I: Adding domain dom13.example to catalog2 zone with ns3 as master($n)" +echo "I: Adding domain dom13.example to catalog2 zone with ns3 as master ($n)" ret=0 $NSUPDATE -d <> nsupdate.out.test$n 2>&1 || ret=1 server 10.53.0.3 5300 @@ -1617,7 +1768,7 @@ status=`expr $status + $ret` cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run` n=`expr $n + 1` -echo "I: Adding domain dom14.example with rndc with ns1 as master($n)" +echo "I: Adding domain dom14.example with rndc with ns1 as master ($n)" ret=0 $RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 addzone dom14.example '{type slave; masters {10.53.0.1;};};' || ret=1 if [ $ret != 0 ]; then echo "I: failed"; fi @@ -1651,7 +1802,7 @@ if [ $ret != 0 ]; then echo "I: failed"; fi status=`expr $status + $ret` n=`expr $n + 1` -echo "I: Adding domain dom14.example to catalog2 zone with ns3 as master($n)" +echo "I: Adding domain dom14.example to catalog2 zone with ns3 as master ($n)" ret=0 $NSUPDATE -d <> nsupdate.out.test$n 2>&1 || ret=1 server 10.53.0.3 5300 @@ -1784,7 +1935,7 @@ status=`expr $status + $ret` sleep 3 n=`expr $n + 1` -echo "I: checking that dom15.example is served by slave($n)" +echo "I: checking that dom15.example is served by slave ($n)" for try in 0 1 2 3 4 5 6 7 8 9; do $DIG soa dom15.example @10.53.0.2 -p 5300 > dig.out.test$n ret=0 diff --git a/lib/dns/catz.c b/lib/dns/catz.c index eaa30c2a30..ab830cc44d 100644 --- a/lib/dns/catz.c +++ b/lib/dns/catz.c @@ -1517,6 +1517,7 @@ dns_catz_generate_zonecfg(dns_catz_zone_t *zone, dns_catz_entry_t *entry, isc_uint32_t i; isc_netaddr_t netaddr; char pbuf[sizeof("65535")]; /* used both for port number and DSCP */ + char zname[DNS_NAME_FORMATSIZE]; REQUIRE(zone != NULL); REQUIRE(entry != NULL); @@ -1552,6 +1553,24 @@ dns_catz_generate_zonecfg(dns_catz_zone_t *zone, dns_catz_entry_t *entry, isc_buffer_putstr(buffer, " { "); for (i = 0; i < entry->opts.masters.count; i++) { + /* + * Every master must have an IP address assigned. + */ + switch (entry->opts.masters.addrs[i].type.sa.sa_family) { + case AF_INET: + case AF_INET6: + break; + default: + dns_name_format(&entry->name, zname, + DNS_NAME_FORMATSIZE); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_MASTER, ISC_LOG_ERROR, + "catz: zone '%s' uses an invalid master " + "(no IP address assigned)", + zname); + result = ISC_R_FAILURE; + goto cleanup; + } isc_netaddr_fromsockaddr(&netaddr, &entry->opts.masters.addrs[i]); isc_buffer_reserve(&buffer, INET6_ADDRSTRLEN); @@ -1572,26 +1591,26 @@ dns_catz_generate_zonecfg(dns_catz_zone_t *zone, dns_catz_entry_t *entry, } isc_buffer_putstr(buffer, "; "); } - isc_buffer_putstr(buffer, "};"); + isc_buffer_putstr(buffer, "}; "); if (entry->opts.in_memory == ISC_FALSE) { isc_buffer_putstr(buffer, "file \""); result = dns_catz_generate_masterfilename(zone, entry, &buffer); if (result != ISC_R_SUCCESS) goto cleanup; - isc_buffer_putstr(buffer, "\";"); + isc_buffer_putstr(buffer, "\"; "); } if (entry->opts.allow_query != NULL) { isc_buffer_putstr(buffer, "allow-query { "); isc_buffer_usedregion(entry->opts.allow_query, ®ion); isc_buffer_copyregion(buffer, ®ion); - isc_buffer_putstr(buffer, "};"); + isc_buffer_putstr(buffer, "}; "); } if (entry->opts.allow_transfer != NULL) { isc_buffer_putstr(buffer, "allow-transfer { "); isc_buffer_usedregion(entry->opts.allow_transfer, ®ion); isc_buffer_copyregion(buffer, ®ion); - isc_buffer_putstr(buffer, "};"); + isc_buffer_putstr(buffer, "}; "); } isc_buffer_putstr(buffer, "};"); @@ -1599,12 +1618,11 @@ dns_catz_generate_zonecfg(dns_catz_zone_t *zone, dns_catz_entry_t *entry, return (ISC_R_SUCCESS); cleanup: - if (buffer) + if (buffer != NULL) isc_buffer_free(&buffer); return (result); } - void dns_catz_update_taskaction(isc_task_t *task, isc_event_t *event) { isc_result_t result;