rm -f ns*/named.run.prev
rm -f ns1/*dom*example.db
rm -f ns2/__catz__*db
+rm -f ns2/catalog-bad*.db
rm -f ns2/named.conf.tmp
rm -f ns3/dom2.example.db ns3/dom13.example.db ns3/dom14.example.db ns3/dom17.example.db ns3/dom18.example.db
rm -f nsupdate.out.*
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; 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.
+
+@ 3600 SOA . . 1 86400 3600 86400 3600
+@ 3600 IN NS invalid.
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; 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.
+
+@ 3600 SOA . . 1 86400 3600 86400 3600
+@ 3600 IN NS invalid.
+version IN TXT "99"
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; 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.
+
+@ 3600 SOA . . 1 86400 3600 86400 3600
+@ 3600 IN NS invalid.
+version IN TXT "1"
+version IN TXT "2"
/* catalog5 is missing on purpose */
+# No "version" property
+zone "catalog-bad1.example" {
+ type primary;
+ file "catalog-bad1.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+};
+
+# Unsupported "version" property
+zone "catalog-bad2.example" {
+ type primary;
+ file "catalog-bad2.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+};
+
+# Two RRs in TXT RRset for the "version" property
+zone "catalog-bad3.example" {
+ type primary;
+ file "catalog-bad3.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+};
+
key tsig_key. {
secret "LSAnCU+Z";
algorithm hmac-md5;
#T1 default-masters { 10.53.0.1; };
#T2 zone "catalog5.example"
#T2 default-primaries { 10.53.0.1; };
+ zone "catalog-bad1.example"
+ default-masters { 10.53.0.1; }
+ in-memory yes;
+ zone "catalog-bad2.example"
+ default-masters { 10.53.0.1; }
+ in-memory yes;
+ zone "catalog-bad3.example"
+ default-masters { 10.53.0.1; }
+ in-memory yes;
};
};
primaries { 10.53.0.1; };
};
+zone "catalog-bad1.example" {
+ type secondary;
+ file "catalog-bad1.example.db";
+ primaries { 10.53.0.1; };
+};
+
+zone "catalog-bad2.example" {
+ type secondary;
+ file "catalog-bad2.example.db";
+ primaries { 10.53.0.1; };
+};
+
+zone "catalog-bad3.example" {
+ type secondary;
+ file "catalog-bad3.example.db";
+ primaries { 10.53.0.1; };
+};
+
key tsig_key. {
secret "LSAnCU+Z";
algorithm hmac-md5;
primaries { 10.53.0.1; };
};
+zone "catalog-bad1.example" {
+ type secondary;
+ file "catalog-bad1.example.db";
+ primaries { 10.53.0.1; };
+};
+
+zone "catalog-bad2.example" {
+ type secondary;
+ file "catalog-bad2.example.db";
+ primaries { 10.53.0.1; };
+};
+
+zone "catalog-bad3.example" {
+ type secondary;
+ file "catalog-bad3.example.db";
+ primaries { 10.53.0.1; };
+};
+
key tsig_key. {
secret "LSAnCU+Z";
algorithm hmac-md5;
status=0
n=0
+
+##########################################################################
+n=$((n+1))
+echo_i "checking that catalog-bad1.example (with no version) has failed to load ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: zone 'catalog-bad1.example' has no 'version' record" &&
+wait_for_message ns2/named.run "catz: new catalog zone 'catalog-bad1.example' is broken and will not be processed" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that catalog-bad2.example (with unsupported version) has failed to load ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: zone 'catalog-bad2.example' unsupported version '99'" &&
+wait_for_message ns2/named.run "catz: new catalog zone 'catalog-bad2.example' is broken and will not be processed" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that catalog-bad3.example (with two supported version records) has failed to load ($n)"
+ret=0
+wait_for_message ns2/named.run "catz: 'version' property TXT RRset contains more than one record, which is invalid" &&
+wait_for_message ns2/named.run "catz: invalid record in catalog zone - version.catalog-bad3.example IN TXT (failure) - ignoring" &&
+wait_for_message ns2/named.run "catz: zone 'catalog-bad3.example' version is not set" &&
+wait_for_message ns2/named.run "catz: new catalog zone 'catalog-bad3.example' is broken and will not be processed" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
##########################################################################
echo_i "Testing adding/removing of domain in catalog zone"
n=$((n+1))
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
+nextpart ns2/named.run >/dev/null
+
n=$((n+1))
echo_i "update dom1.example. ($n)"
ret=0
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
+nextpart ns2/named.run >/dev/null
+
n=$((n+1))
echo_i "update catalog zone serial ($n)"
ret=0
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
+nextpart ns2/named.run >/dev/null
+
n=$((n+1))
echo_i "update dom1.example. again ($n)"
ret=0
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
+nextpart ns2/named.run >/dev/null
+
##########################################################################
echo_i "Testing various simple operations on domains, including using multiple catalog zones and garbage in zone"
n=$((n+1))
$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
server 10.53.0.1 ${PORT}
update add 636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR dom2.example.
+ update add coo.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN TXT "catalog2.example."
update add b901f492f3ebf6c1e5b597e51766f02f0479eb03.zones.catalog1.example. 3600 IN PTR dom3.example.
update add e721433b6160b450260d4f54b3ec8bab30cb3b83.zones.catalog1.example. 3600 IN NS foo.bar.
update add trash.catalog1.example. 3600 IN A 1.2.3.4
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
-
n=$((n+1))
echo_i "waiting for secondary to sync up ($n)"
ret=0
+wait_for_message ns2/named.run "catz: adding zone 'dom2.example' from catalog 'catalog1.example'" &&
+wait_for_message ns2/named.run "catz: adding zone 'dom3.example' from catalog 'catalog1.example'" &&
wait_for_message ns2/named.run "catz: adding zone 'dom4.example' from catalog 'catalog2.example'" &&
wait_for_message ns2/named.run "transfer of 'dom4.example/IN' from 10.53.0.1#${EXTRAPORT1}: Transfer status: success" || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
-
n=$((n+1))
echo_i "checking that dom3.example. is not served by primary ($n)"
ret=0
n=$((n+1))
echo_i "waiting for secondary to sync up ($n)"
ret=0
-wait_for_message ns2/named.run "catz: adding zone 'dom2.example' from catalog 'catalog1.example'" &&
-wait_for_message ns2/named.run "catz: adding zone 'dom3.example' from catalog 'catalog1.example'" &&
wait_for_message ns2/named.run "transfer of 'dom2.example/IN' from 10.53.0.1#${PORT}: Transfer status: success" &&
wait_for_message ns2/named.run "transfer of 'dom3.example/IN' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
nextpart ns2/named.run >/dev/null
+# The member zone's PTR RRset must have only one record in it.
+# Check that adding a second record to the RRset is caught and such a
+# catalog zone is not processed.
+n=$((n+1))
+echo_i "adding domain dom4-reused-label.example. to catalog2 zone, reusing a label ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.3 ${PORT}
+ update add de26b88d855397a03f77ff1162fd055d8b419584.zones.catalog2.example. 3600 IN PTR dom4-reused-label.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "waiting for secondary to sync up, and checking that the reused label has been caught ($n)"
+ret=0
+wait_for_message ns2/named.run "de26b88d855397a03f77ff1162fd055d8b419584.zones.catalog2.example IN PTR (failure)" &&
+wait_for_message ns2/named.run "catz: new catalog zone 'catalog2.example' is broken and will not be processed" || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n+1))
+echo_i "deleting domain dom4-reused-label.example. from catalog2 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.3 ${PORT}
+ update delete de26b88d855397a03f77ff1162fd055d8b419584.zones.catalog2.example. 3600 IN PTR dom4-reused-label.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+nextpart ns2/named.run >/dev/null
+
n=$((n+1))
echo_i "adding domain dom2.example. to catalog2 zone to test change of ownership ($n)"
ret=0
$NSUPDATE -d <<END >> nsupdate.out.test$n 2>&1 || ret=1
server 10.53.0.1 ${PORT}
update delete 636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR dom2.example.
+ update delete coo.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN TXT "catalog2.example."
update delete b901f492f3ebf6c1e5b597e51766f02f0479eb03.zones.catalog1.example. 3600 IN PTR dom3.example.
update delete e721433b6160b450260d4f54b3ec8bab30cb3b83.zones.catalog1.example. 3600 IN NS foo.bar.
update delete trash.catalog1.example. 3600 IN A 1.2.3.4
n=$((n+1))
echo_i "waiting for secondary to sync up ($n)"
ret=0
-wait_for_message ns2/named.run "catz: unknown record in catalog zone - primaries.dom17.zones.catalog1.example IN A(failure) - ignoring" &&
+wait_for_message ns2/named.run "catz: invalid record in catalog zone - primaries.dom17.zones.catalog1.example IN A (failure) - ignoring" &&
wait_for_message ns2/named.run "catz: adding zone 'dom17.example' from catalog 'catalog1.example'" &&
wait_for_message ns2/named.run "catz: adding zone 'dom18.example' from catalog 'catalog1.example'" &&
wait_for_message ns2/named.run "transfer of 'dom17.example/IN' from 10.53.0.1#${PORT}: Transfer status: success" &&
n=$((n+1))
echo_i "waiting for secondary to sync up ($n)"
ret=0
-wait_for_message ns2/named.run "catz: unknown record in catalog zone - primaries.ext.dom18.zones.catalog2.example IN A(failure) - ignoring" &&
+wait_for_message ns2/named.run "catz: invalid record in catalog zone - primaries.ext.dom18.zones.catalog2.example IN A (failure) - ignoring" &&
wait_for_message ns2/named.run "catz: adding zone 'dom17.example' from catalog 'catalog2.example'" &&
wait_for_message ns2/named.run "catz: adding zone 'dom18.example' from catalog 'catalog2.example'" &&
wait_for_message ns2/named.run "transfer of 'dom17.example/IN' from 10.53.0.3#${PORT}: Transfer status: success" &&
bool active;
bool db_registered;
+ bool broken;
isc_refcount_t refs;
};
return (ISC_R_FAILURE);
}
+ if (dns_rdataset_count(value) != 1) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_WARNING,
+ "catz: 'coo' property PTR RRset contains "
+ "more than one record, which is invalid");
+ zone->broken = true;
+ return (ISC_R_FAILURE);
+ }
+
result = dns_rdataset_first(value);
if (result != ISC_R_SUCCESS) {
return (result);
dns_rdata_ptr_t ptr;
dns_catz_entry_t *entry = NULL;
- /*
- * We only take -first- value, as mhash must be
- * different.
- */
- if (value->type != dns_rdatatype_ptr) {
+ if (value->rdclass != dns_rdataclass_in ||
+ value->type != dns_rdatatype_ptr) {
+ return (ISC_R_FAILURE);
+ }
+
+ if (dns_rdataset_count(value) != 1) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_WARNING,
+ "catz: member zone PTR RRset contains "
+ "more than one record, which is invalid");
+ zone->broken = true;
return (ISC_R_FAILURE);
}
result = dns_rdataset_first(value);
if (result != ISC_R_SUCCESS) {
- return (ISC_R_FAILURE);
+ return (result);
}
dns_rdata_init(&rdata);
dns_rdataset_current(value, &rdata);
result = dns_rdata_tostruct(&rdata, &ptr, NULL);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
result = isc_ht_find(zone->entries, mhash->base, mhash->length,
(void **)&entry);
return (ISC_R_FAILURE);
}
+ if (dns_rdataset_count(value) != 1) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_WARNING,
+ "catz: 'version' property TXT RRset contains "
+ "more than one record, which is invalid");
+ zone->broken = true;
+ return (ISC_R_FAILURE);
+ }
+
result = dns_rdataset_first(value);
if (result != ISC_R_SUCCESS) {
return (result);
dns_rdataset_current(value, &rdata);
result = dns_rdata_tostruct(&rdata, &rdatatxt, NULL);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
result = dns_rdata_txt_first(&rdatatxt);
if (result != ISC_R_SUCCESS) {
cleanup:
dns_rdata_freestruct(&rdatatxt);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_WARNING,
+ "catz: invalid record for the catalog "
+ "zone version property");
+ zone->broken = true;
+ }
return (result);
}
REQUIRE(DNS_CATZ_ZONE_VALID(zone));
REQUIRE(ISC_MAGIC_VALID(src_name, DNS_NAME_MAGIC));
+ if (rdataset->rdclass != dns_rdataclass_in) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
+ "catz: RR found which has a non-IN class");
+ zone->broken = true;
+ return (ISC_R_FAILURE);
+ }
+
nrres = dns_name_fullcompare(src_name, &zone->name, &order, &nlabels);
if (nrres == dns_namereln_equal) {
if (rdataset->type == dns_rdatatype_soa) {
dns_rdatasetiter_t *rdsiter = NULL;
dns_rdataset_t rdataset;
char bname[DNS_NAME_FORMATSIZE];
+ char cname[DNS_NAME_FORMATSIZE];
bool is_vers_processed = false;
uint32_t vers;
+ uint32_t catz_vers;
REQUIRE(DNS_DB_VALID(db));
REQUIRE(DNS_CATZ_ZONES_VALID(catzs));
result = dns_dbiterator_seek(it, name);
if (result != ISC_R_SUCCESS) {
dns_dbiterator_destroy(&it);
- dns_catz_zone_detach(&newzone);
dns_db_closeversion(db, &oldzone->dbversion, false);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
"catz: zone '%s' has no 'version' record (%s)",
bname, isc_result_totext(result));
- return;
+ newzone->broken = true;
+ goto final;
}
name = dns_fixedname_initname(&fixname);
result = dns_catz_update_process(catzs, newzone, name,
&rdataset);
if (result != ISC_R_SUCCESS) {
- char cname[DNS_NAME_FORMATSIZE];
char typebuf[DNS_RDATATYPE_FORMATSIZE];
char classbuf[DNS_RDATACLASS_FORMATSIZE];
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_MASTER,
ISC_LOG_WARNING,
- "catz: unknown record in catalog "
- "zone - %s %s %s(%s) - ignoring",
+ "catz: invalid record in catalog "
+ "zone - %s %s %s (%s) - ignoring",
cname, classbuf, typebuf,
isc_result_totext(result));
}
ISC_LOG_DEBUG(3),
"catz: update_from_db: iteration finished");
+ /*
+ * Check catalog zone version compatibilites.
+ */
+ catz_vers = (newzone->version == DNS_CATZ_VERSION_UNDEFINED)
+ ? oldzone->version
+ : newzone->version;
+ if (catz_vers == DNS_CATZ_VERSION_UNDEFINED) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_WARNING,
+ "catz: zone '%s' version is not set", bname);
+ newzone->broken = true;
+ } else if (catz_vers != 1 && catz_vers != 2) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_WARNING,
+ "catz: zone '%s' unsupported version "
+ "'%" PRIu32 "'",
+ bname, catz_vers);
+ newzone->broken = true;
+ } else {
+ oldzone->version = catz_vers;
+ }
+
+final:
+ if (newzone->broken) {
+ dns_name_format(name, cname, DNS_NAME_FORMATSIZE);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
+ "catz: new catalog zone '%s' is broken and "
+ "will not be processed",
+ bname);
+ dns_catz_zone_detach(&newzone);
+ return;
+ }
+
/*
* Finally merge new zone into old zone.
*/