]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
enforce '*._er' requirement for error-reporting zones
authorEvan Hunt <each@isc.org>
Sun, 20 Oct 2024 08:04:06 +0000 (01:04 -0700)
committerEvan Hunt <each@isc.org>
Wed, 23 Oct 2024 21:29:32 +0000 (21:29 +0000)
if "log-report-channel" is set to "yes", then the zone must
contain a wildcard name matching '*._er' with a TXT record.

bin/check/named-checkzone.c
bin/check/named-checkzone.rst
bin/check/named-compilezone.rst
bin/tests/system/checkzone/tests.sh
bin/tests/system/checkzone/zones/er-missing.db [new file with mode: 0644]
bin/tests/system/checkzone/zones/er.db [new file with mode: 0644]
doc/arm/reference.rst
lib/dns/zone.c

index f96930d30c083d6ea5c0b43ab31ffe71d20087cf..2770bf5be8b34d23988bccf370d868f742d10f2e 100644 (file)
@@ -159,7 +159,7 @@ main(int argc, char **argv) {
 
        while ((c = isc_commandline_parse(argc, argv,
                                          "c:df:hi:jJ:k:L:l:m:n:qr:s:t:o:vw:C:"
-                                         "DF:M:S:T:W:")) != EOF)
+                                         "DF:M:R:S:T:W:")) != EOF)
        {
                switch (c) {
                case 'c':
@@ -323,6 +323,18 @@ main(int argc, char **argv) {
                        }
                        break;
 
+               case 'R':
+                       if (ARGCMP("fail")) {
+                               zone_options |= DNS_ZONEOPT_LOGREPORTS;
+                       } else if (ARGCMP("ignore")) {
+                               zone_options &= ~DNS_ZONEOPT_LOGREPORTS;
+                       } else {
+                               fprintf(stderr, "invalid argument to -R: %s\n",
+                                       isc_commandline_argument);
+                               exit(EXIT_FAILURE);
+                       }
+                       break;
+
                case 's':
                        if (ARGCMP("full")) {
                                outputstyle = &dns_master_style_full;
index e6ad56f73c1266d131e5053f1760f3820bd00c99..9b8a0909a4daccf65e637d4d36a9a223fcb6bd95 100644 (file)
@@ -23,7 +23,7 @@ named-checkzone - zone file validation tool
 Synopsis
 ~~~~~~~~
 
-:program:`named-checkzone` [**-d**] [**-h**] [**-j**] [**-q**] [**-v**] [**-c** class] [**-C** mode] [**-f** format] [**-F** format] [**-J** filename] [**-i** mode] [**-k** mode] [**-m** mode] [**-M** mode] [**-n** mode] [**-l** ttl] [**-L** serial] [**-o** filename] [**-r** mode] [**-s** style] [**-S** mode] [**-t** directory] [**-T** mode] [**-w** directory] [**-D**] [**-W** mode] {zonename} {filename}
+:program:`named-checkzone` [**-d**] [**-h**] [**-j**] [**-q**] [**-v**] [**-c** class] [**-C** mode] [**-f** format] [**-F** format] [**-J** filename] [**-i** mode] [**-k** mode] [**-m** mode] [**-M** mode] [**-n** mode] [**-l** ttl] [**-L** serial] [**-o** filename] [**-r** mode] [**-R** mode] [**-s** style] [**-S** mode] [**-t** directory] [**-T** mode] [**-w** directory] [**-D**] [**-W** mode] {zonename} {filename}
 
 Description
 ~~~~~~~~~~~
@@ -166,6 +166,12 @@ Options
    semantically equal in plain DNS. Possible modes are ``fail``,
    ``warn`` (the default), and ``ignore``.
 
+.. option:: -R mode
+
+   This option checks whether a TXT wildcard record exists that
+   matches the name format for RFC 9567 error-reporting queries: ``*._er``.
+   Possible modes are ``fail`` and ``ignore`` (the default).
+
 .. option:: -s style
 
    This option specifies the style of the dumped zone file. Possible styles are
index 8c68d0d6d2993f6cb3170126ee021286851d58b8..c0678261941f1e1675bd775134c5243fb93965c3 100644 (file)
@@ -23,7 +23,7 @@ named-compilezone - zone file converting tool
 Synopsis
 ~~~~~~~~
 
-:program:`named-compilezone` [**-d**] [**-h**] [**-j**] [**-q**] [**-v**] [**-c** class] [**-C** mode] [**-f** format] [**-F** format] [**-J** filename] [**-i** mode] [**-k** mode] [**-m** mode] [**-M** mode] [**-n** mode] [**-l** ttl] [**-L** serial] [**-r** mode] [**-s** style] [**-S** mode] [**-t** directory] [**-T** mode] [**-w** directory] [**-D**] [**-W** mode] {**-o** filename} {zonename} {filename}
+:program:`named-compilezone` [**-d**] [**-h**] [**-j**] [**-q**] [**-v**] [**-c** class] [**-C** mode] [**-f** format] [**-F** format] [**-J** filename] [**-i** mode] [**-k** mode] [**-m** mode] [**-M** mode] [**-n** mode] [**-l** ttl] [**-L** serial] [**-r** mode] [**-R** mode] [**-s** style] [**-S** mode] [**-t** directory] [**-T** mode] [**-w** directory] [**-D**] [**-W** mode] {**-o** filename} {zonename} {filename}
 
 Description
 ~~~~~~~~~~~
@@ -175,6 +175,12 @@ Options
    semantically equal in plain DNS. Possible modes are ``fail``,
    ``warn``, and ``ignore`` (the default).
 
+.. option:: -R mode
+
+   This option checks whether a TXT wildcard record exists that
+   matches the name format for RFC 9567 error-reporting queries: ``*._er``.
+   Possible modes are ``fail`` and ``ignore`` (the default).
+
 .. option:: -s style
 
    This option specifies the style of the dumped zone file. Possible styles are
index 1cc8accce4fbcd1074a008f80a549491471b276b..aa26c8fb43ae4d18ac5490ae687998204bfb8de4 100644 (file)
@@ -124,6 +124,16 @@ n=$((n + 1))
 if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status + ret))
 
+echo_i "checking that log-report-channel zones fail if '*._er/TXT' is missing ($n)"
+ret=0
+$CHECKZONE -R fail example zones/er.db >test.out2.$n 2>&1 || ret=1
+grep -F "no '*._er/TXT' wildcard found" test.out4.$n >/dev/null && ret=1
+$CHECKZONE example zones/er-missing.db >test.out3.$n 2>&1 || ret=1
+grep -F "no '*._er/TXT' wildcard found" test.out4.$n >/dev/null && ret=1
+$CHECKZONE -R fail example zones/er-missing.db >test.out4.$n 2>&1 && ret=1
+grep -F "no '*._er/TXT' wildcard found" test.out4.$n >/dev/null || ret=1
+status=$((status + ret))
+
 echo_i "checking that raw zone with bad class is handled ($n)"
 ret=0
 $CHECKZONE -f raw example zones/bad-badclass.raw >test.out.$n 2>&1 && ret=1
diff --git a/bin/tests/system/checkzone/zones/er-missing.db b/bin/tests/system/checkzone/zones/er-missing.db
new file mode 100644 (file)
index 0000000..29885ca
--- /dev/null
@@ -0,0 +1,22 @@
+; 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.
+
+$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/checkzone/zones/er.db b/bin/tests/system/checkzone/zones/er.db
new file mode 100644 (file)
index 0000000..08d3197
--- /dev/null
@@ -0,0 +1,23 @@
+; 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.
+
+$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
+*._er                   TXT     "Report received"
index 4813ccd546179ff12e30e494e43256b76e35e84d..38eeb39ee26c8cae62cd9f738f7dca517434f87b 100644 (file)
@@ -7315,8 +7315,9 @@ Zone Options
    are logged to the ``dns-reporting-agent`` logging category at
    level ``info``.
 
-   The zone should have a wildcard record in place to respond to such
-   queries. For example:
+   The zone must have a wildcard record in place to respond to such
+   queries; it is a configuration error to use this option in a
+   zone without such a record. For example:
 
    ::
 
index 188c23f6b666602f0c0da94bd5518471ac640370..5c71e68be3cb1d42fc32742cdeb0ff8513bef8aa 100644 (file)
@@ -4727,6 +4727,47 @@ process_zone_setnsec3param(dns_zone_t *zone) {
        }
 }
 
+static unsigned char er_offset[] = { 0, 1 };
+static unsigned char er_ndata[] = "\001*\003_er";
+static dns_name_t er = DNS_NAME_INITNONABSOLUTE(er_ndata, er_offset);
+
+static isc_result_t
+check_reportchannel(dns_zone_t *zone, dns_db_t *db) {
+       isc_result_t result;
+       dns_rdataset_t rdataset = DNS_RDATASET_INIT;
+       dns_dbnode_t *node = NULL;
+       dns_dbversion_t *version = NULL;
+       dns_fixedname_t fixed;
+       dns_name_t *name = NULL;
+
+       /*
+        * If this zone isn't logging reports, it's fine.
+        */
+       if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_LOGREPORTS)) {
+               return (ISC_R_SUCCESS);
+       }
+
+       /*
+        * Otherwise, we need a '*._er' wildcard with a TXT rdataset.
+        */
+       name = dns_fixedname_initname(&fixed);
+       CHECK(dns_name_concatenate(&er, &zone->origin, name, NULL));
+       CHECK(dns_db_findnode(db, name, false, &node));
+
+       dns_db_currentversion(db, &version);
+
+       result = dns_db_findrdataset(db, node, version, dns_rdatatype_txt,
+                                    dns_rdatatype_none, 0, &rdataset, NULL);
+       dns_db_closeversion(db, &version, false);
+       dns_db_detachnode(db, &node);
+       if (result == ISC_R_SUCCESS) {
+               dns_rdataset_disassociate(&rdataset);
+       }
+
+failure:
+       return (result);
+}
+
 /*
  * The zone is presumed to be locked.
  * If this is a inline_raw zone the secure version is also locked.
@@ -4972,6 +5013,15 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
                        }
                }
 
+               result = check_reportchannel(zone, db);
+               if (result != ISC_R_SUCCESS) {
+                       dns_zone_log(zone, ISC_LOG_ERROR,
+                                    "'log-report-channel' is set, but no "
+                                    "'*._er/TXT' wildcard found");
+                       result = DNS_R_BADZONE;
+                       goto cleanup;
+               }
+
                result = dns_zone_verifydb(zone, db, NULL);
                if (result != ISC_R_SUCCESS) {
                        goto cleanup;