]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
2800. [func] Reject zones which have NS records which refer to
authorMark Andrews <marka@isc.org>
Fri, 4 Dec 2009 03:33:15 +0000 (03:33 +0000)
committerMark Andrews <marka@isc.org>
Fri, 4 Dec 2009 03:33:15 +0000 (03:33 +0000)
                        CNAMEs, DNAMEs or don't have address record (class IN
                        only).  Reject UPDATEs which would cause the zone
                        to fail the above checks if committed. [RT #20678]

CHANGES
bin/named/update.c
bin/tests/system/nsupdate/setup.sh
bin/tests/system/zonechecks/tests.sh
lib/dns/include/dns/zone.h
lib/dns/zone.c

diff --git a/CHANGES b/CHANGES
index d3549c72ff5b487656446d8c6f5e9bf917e40f00..b10379a2399d85211bacca3bb44f63f9382684d3 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+2800.  [func]          Reject zones which have NS records which refer to
+                       CNAMEs, DNAMEs or don't have address record (class IN
+                       only).  Reject UPDATEs which would cause the zone
+                       to fail the above checks if committed. [RT #20678]
+
 2799.  [cleanup]       Changed the "secure-to-insecure" option to
                        "dnssec-secure-to-insecure", and "dnskey-ksk-only"
                        to "dnssec-dnskey-kskonly", for clarity. [RT #20586]
index 32feb5a11f3a967a83ac9710b121212dfb2cc56e..ad03826eb89c8bb2baa7434d11fa5c8e96d7be49 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: update.c,v 1.173 2009/12/03 23:48:22 tbox Exp $ */
+/* $Id: update.c,v 1.174 2009/12/04 03:33:14 marka Exp $ */
 
 #include <config.h>
 
@@ -4088,6 +4088,18 @@ update_action(isc_task_t *task, isc_event_t *event) {
        if (! ISC_LIST_EMPTY(diff.tuples))
                CHECK(check_dnssec(client, zone, db, ver, &diff));
 
+       if (! ISC_LIST_EMPTY(diff.tuples)) {
+               unsigned int errors = 0;
+               CHECK(dns_zone_nscheck(zone, db, ver, &errors));
+               if (errors != 0) {
+                       update_log(client, zone, LOGLEVEL_PROTOCOL,
+                                  "update rejected: post update name server "
+                                  "sanity check failed");
+                       result = DNS_R_REFUSED;
+                       goto failure;
+               }
+       }
+
        /*
         * If any changes were made, increment the SOA serial number,
         * update RRSIGs and NSECs (if zone is secure), and write the update
index c051b1ce3d6e1a6df45dc8282093b5aa149d43fc..8ade441e84e2fc2584edd7ae1d8ea460637f7024 100644 (file)
@@ -15,7 +15,7 @@
 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 
-# $Id: setup.sh,v 1.13 2009/07/30 15:11:41 each Exp $
+# $Id: setup.sh,v 1.14 2009/12/04 03:33:15 marka Exp $
 
 SYSTEMTESTTOP=..
 . $SYSTEMTESTTOP/conf.sh
@@ -43,6 +43,7 @@ update.nil              IN SOA  ns1.example.nil. hostmaster.example.nil. (
                                 )
 update.nil.             NS      ns1.update.nil.
 ns1.update.nil.         A       10.53.0.2
+ns2.update.nil.                AAAA    ::1
 EOF
 
 ../../../tools/genrandom 400 random.data
index 2a1b850f59462b0361eabbfcacb13aed20da1a3d..0875b723509f1f80c4fe6830d0060f9415e2c15a 100644 (file)
@@ -14,7 +14,7 @@
 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 
-# $Id: tests.sh,v 1.4 2007/06/19 23:47:07 tbox Exp $
+# $Id: tests.sh,v 1.5 2009/12/04 03:33:15 marka Exp $
 
 SYSTEMTESTTOP=..
 . $SYSTEMTESTTOP/conf.sh
@@ -161,4 +161,4 @@ else
        echo "I:failed (status)"; status=1
 fi
 echo "I:exit status: $status"
-exit $?
+exit $status
index 0be5b633a88687ff3b892962279d2bef7778804b..4ee5d32e06cc37ee64db4a9f07561ba9fedc52ce 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: zone.h,v 1.171 2009/12/03 23:18:17 each Exp $ */
+/* $Id: zone.h,v 1.172 2009/12/04 03:33:15 marka Exp $ */
 
 #ifndef DNS_ZONE_H
 #define DNS_ZONE_H 1
@@ -1782,6 +1782,25 @@ dns_zone_rekey(dns_zone_t *zone);
  * Update the zone's DNSKEY set from the key repository.
  */
 
+isc_result_t
+dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
+                 unsigned int *errors);
+/*%
+ * Check if the name servers for the zone are sane (have address, don't
+ * refer to CNAMEs/DNAMEs.  The number of constiancy errors detected in
+ * returned in '*errors'
+ *
+ * Requires:
+ * \li 'zone' to be valid.
+ * \li 'db' to be valid.
+ * \li 'version' to be valid or NULL.
+ * \li 'errors' to be non NULL.
+ *
+ * Returns:
+ *     ISC_R_SUCCESS if there were no errors examining the zone contents.
+ */
+
+
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_ZONE_H */
index dc4e6419e0d7b51ce64f9524603ad01abac6016b..83b156133752f6ee1d38b55fbb87a10328df28d2 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: zone.c,v 1.534 2009/12/03 15:40:02 each Exp $ */
+/* $Id: zone.c,v 1.535 2009/12/04 03:33:15 marka Exp $ */
 
 /*! \file */
 
@@ -3540,7 +3540,9 @@ exit_check(dns_zone_t *zone) {
 }
 
 static isc_boolean_t
-zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_name_t *name) {
+zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
+             isc_boolean_t logit)
+{
        isc_result_t result;
        char namebuf[DNS_NAME_FORMATSIZE];
        char altbuf[DNS_NAME_FORMATSIZE];
@@ -3571,30 +3573,33 @@ zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_name_t *name) {
                        return (ISC_TRUE);
        }
 
-       dns_name_format(name, namebuf, sizeof namebuf);
        if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
            result == DNS_R_EMPTYNAME) {
-               dns_zone_log(zone, level,
-                            "NS '%s' has no address records (A or AAAA)",
-                            namebuf);
-               /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
-               return (ISC_TRUE);
+               if (logit) {
+                       dns_name_format(name, namebuf, sizeof namebuf);
+                       dns_zone_log(zone, level, "NS '%s' has no address "
+                                    "records (A or AAAA)", namebuf);
+               }
+               return (ISC_FALSE);
        }
 
        if (result == DNS_R_CNAME) {
-               dns_zone_log(zone, level, "NS '%s' is a CNAME (illegal)",
-                            namebuf);
-               /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
-               return (ISC_TRUE);
+               if (logit) {
+                       dns_name_format(name, namebuf, sizeof namebuf);
+                       dns_zone_log(zone, level, "NS '%s' is a CNAME "
+                                    "(illegal)", namebuf);
+               }
+               return (ISC_FALSE);
        }
 
        if (result == DNS_R_DNAME) {
-               dns_name_format(foundname, altbuf, sizeof altbuf);
-               dns_zone_log(zone, level,
-                            "NS '%s' is below a DNAME '%s' (illegal)",
-                            namebuf, altbuf);
-               /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
-               return (ISC_TRUE);
+               if (logit) {
+                       dns_name_format(name, namebuf, sizeof namebuf);
+                       dns_name_format(foundname, altbuf, sizeof altbuf);
+                       dns_zone_log(zone, level, "NS '%s' is below a DNAME "
+                                    "'%s' (illegal)", namebuf, altbuf);
+               }
+               return (ISC_FALSE);
        }
 
        return (ISC_TRUE);
@@ -3603,7 +3608,7 @@ zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_name_t *name) {
 static isc_result_t
 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
                 dns_dbversion_t *version, unsigned int *nscount,
-                unsigned int *errors)
+                unsigned int *errors, isc_boolean_t logit)
 {
        isc_result_t result;
        unsigned int count = 0;
@@ -3634,7 +3639,7 @@ zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
                        result = dns_rdata_tostruct(&rdata, &ns, NULL);
                        RUNTIME_CHECK(result == ISC_R_SUCCESS);
                        if (dns_name_issubdomain(&ns.name, &zone->origin) &&
-                           !zone_check_ns(zone, db, &ns.name))
+                           !zone_check_ns(zone, db, &ns.name, logit))
                                ecount++;
                }
                count++;
@@ -3763,7 +3768,7 @@ zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
 
        if (nscount != NULL || errors != NULL) {
                result = zone_count_ns_rr(zone, db, node, version,
-                                         nscount, errors);
+                                         nscount, errors, ISC_TRUE);
                if (result != ISC_R_SUCCESS)
                        answer = result;
        }
@@ -13607,3 +13612,22 @@ dns_zone_rekey(dns_zone_t *zone) {
        UNLOCK_ZONE(zone);
        return (result);
 }
+
+isc_result_t
+dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
+                unsigned int *errors)
+{
+       isc_result_t result;
+       dns_dbnode_t *node = NULL;
+
+       REQUIRE(DNS_ZONE_VALID(zone));
+       REQUIRE(errors != NULL);
+
+       result = dns_db_getoriginnode(db, &node);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+       result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
+                                 ISC_FALSE);
+       dns_db_detachnode(db, &node);
+       return (result);
+}