]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3964. [func] nsupdate now performs check-names processing.
authorMark Andrews <marka@isc.org>
Wed, 1 Oct 2014 23:35:43 +0000 (09:35 +1000)
committerMark Andrews <marka@isc.org>
Wed, 1 Oct 2014 23:35:43 +0000 (09:35 +1000)
                        [RT #36266]

CHANGES
README
bin/nsupdate/nsupdate.c
bin/nsupdate/nsupdate.docbook
bin/tests/system/checknames/tests.sh
bin/tests/system/nsupdate/tests.sh
lib/dns/master.c

diff --git a/CHANGES b/CHANGES
index b2be41e234d6d648cc65580ff3466e4d129408bb..cdec5f95b948ccf038bd762326026dee5a3cfbe3 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+3964.  [func]          nsupdate now performs check-names processing.
+                       [RT #36266]
+
 3963.  [test]          Added NXRRSET test cases to the "dlzexternal"
                        system test. [RT #37344]
 
diff --git a/README b/README
index e63637b00ccd31acb7c39721fd80cc93b9b4536a..eac77426c7b7e8469e567c60795897c1776513f1 100644 (file)
--- a/README
+++ b/README
@@ -97,6 +97,8 @@ BIND 9.11.0
        - dig can now set yet-to-be-defined EDNS flags on requests (+ednsflags).
        - serial-query-rate no longer covers NOTIFY messages.  These are
          separately controlled by notify-rate and startup-notify-rate.
+       - nsupdate now performs check-names processing by default on records
+         to be added.  This can be disabled with "check-names no".
 
        This release addresses the security flaw described in
        CVE-2014-3214 and CVE-2014-3859.
index 183162487f3b9374b720dc341f33b359d5c59472..ef9fcae7106fc6e1b7b39011eaca77e1487613f6 100644 (file)
@@ -182,6 +182,7 @@ static dns_rdataclass_t zoneclass = dns_rdataclass_none;
 static dns_message_t *answer = NULL;
 static isc_uint32_t default_ttl = 0;
 static isc_boolean_t default_ttl_set = ISC_FALSE;
+static isc_boolean_t checknames = ISC_TRUE;
 
 typedef struct nsu_requestinfo {
        dns_message_t *msg;
@@ -1827,6 +1828,33 @@ update_addordelete(char *cmdline, isc_boolean_t isdelete) {
                }
        }
 
+       if (!isdelete && checknames) {
+               dns_fixedname_t fixed;
+               dns_name_t *bad;
+
+               if (!dns_rdata_checkowner(name, rdata->rdclass, rdata->type,
+                                         ISC_TRUE))
+               {
+                       char namebuf[DNS_NAME_FORMATSIZE];
+
+                       dns_name_format(name, namebuf, sizeof(namebuf));
+                       fprintf(stderr, "check-names failed: bad owner '%s'\n",
+                               namebuf);
+                       goto failure;
+               }
+
+               dns_fixedname_init(&fixed);
+               bad = dns_fixedname_name(&fixed);
+               if (!dns_rdata_checknames(rdata, name, bad)) {
+                       char namebuf[DNS_NAME_FORMATSIZE];
+
+                       dns_name_format(bad, namebuf, sizeof(namebuf));
+                       fprintf(stderr, "check-names failed: bad name '%s'\n",
+                               namebuf);
+                       goto failure;
+               }
+       }
+
  doneparsing:
 
        result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
@@ -1878,6 +1906,31 @@ evaluate_update(char *cmdline) {
        return (update_addordelete(cmdline, isdelete));
 }
 
+static isc_uint16_t
+evaluate_checknames(char *cmdline) {
+       char *word;
+
+       ddebug("evaluate_checknames()");
+       word = nsu_strsep(&cmdline, " \t\r\n");
+       if (word == NULL || *word == 0) {
+               fprintf(stderr, "could not read check-names directive\n");
+               return (STATUS_SYNTAX);
+       }
+       if (strcasecmp(word, "yes") == 0 ||
+           strcasecmp(word, "true") == 0 ||
+           strcasecmp(word, "on") == 0) {
+               checknames = ISC_TRUE;
+       } else if (strcasecmp(word, "no") == 0 ||
+                strcasecmp(word, "false") == 0 ||
+                strcasecmp(word, "off") == 0) {
+               checknames = ISC_FALSE;
+       } else {
+               fprintf(stderr, "incorrect check-names directive: %s\n", word);
+               return (STATUS_SYNTAX);
+       }
+       return (STATUS_MORE);
+}
+
 static void
 setzone(dns_name_t *zonename) {
        isc_result_t result;
@@ -2012,6 +2065,9 @@ do_next_command(char *cmdline) {
        }
        if (strcasecmp(word, "realm") == 0)
                return (evaluate_realm(cmdline));
+       if (strcasecmp(word, "check-names") == 0 ||
+           strcasecmp(word, "checknames") == 0)
+               return (evaluate_checknames(cmdline));
        if (strcasecmp(word, "gsstsig") == 0) {
 #ifdef GSSAPI
                usegsstsig = ISC_TRUE;
@@ -2045,6 +2101,7 @@ do_next_command(char *cmdline) {
 "oldgsstsig                (use Microsoft's GSS_TSIG to sign the request)\n"
 "zone name                 (set the zone to be updated)\n"
 "class CLASS               (set the zone's DNS class, e.g. IN (default), CH)\n"
+"check-names { on | off }  (enable / disable check-names)\n"
 "[prereq] nxdomain name    (does this name not exist)\n"
 "[prereq] yxdomain name    (does this name exist)\n"
 "[prereq] nxrrset ....     (does this RRset exist)\n"
index 7b006a64aa2d46305b1c4bcb9e01540699ca1d43..ad44204a6e7fc96848d60546c4c7a7207491f87a 100644 (file)
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term>
+            <command>check-names</command>
+            <arg choice="req"><optional>yes_or_no</optional></arg>
+          </term>
+         <listitem>
+           <para>
+             Turn on or off check-names processing on records to
+             be added.  Check-names has no effect on prerequisites
+             or records to be deleted.  By default check-names
+             processing is on.  If check-names processing fails
+             the record will not be added to the UPDATE message.
+           </para>
+         </listitem>
+       </varlistentry>
+
         <varlistentry>
           <term>
               <command><optional>prereq</optional> nxdomain</command>
index 2b4f07c667f6819cfc1eae99212e6dbc863bf2a8..e8eca7e1163a14819b1e313ff684ed53b5fcbadf 100644 (file)
@@ -89,6 +89,7 @@ echo "I: check that updates to 'check-names fail;' are rejected ($n)"
 ret=0
 not=1
 $NSUPDATE -d <<END> nsupdate.out.test$n 2>&1 || not=0
+check-names off
 server 10.53.0.1 5300
 update add xxx_xxx.fail.update. 600 A 10.10.10.1
 send
@@ -104,6 +105,7 @@ n=`expr $n + 1`
 echo "I: check that updates to 'check-names warn;' succeed and are logged ($n)"
 ret=0
 $NSUPDATE -d <<END> nsupdate.out.test$n  2>&1|| ret=1
+check-names off
 server 10.53.0.1 5300
 update add xxx_xxx.warn.update. 600 A 10.10.10.1
 send
@@ -119,6 +121,7 @@ echo "I: check that updates to 'check-names ignore;' succeed and are not logged
 ret=0
 not=1
 $NSUPDATE -d <<END> nsupdate.out.test$n 2>&1 || ret=1
+check-names off
 server 10.53.0.1 5300
 update add xxx_xxx.ignore.update. 600 A 10.10.10.1
 send
@@ -135,6 +138,7 @@ echo "I: check that updates to 'check-names master ignore;' succeed and are not
 ret=0
 not=1
 $NSUPDATE -d <<END> nsupdate.out.test$n 2>&1 || ret=1
+check-names off
 server 10.53.0.4 5300
 update add xxx_xxx.master-ignore.update. 600 A 10.10.10.1
 send
index 609088f6e4c510880ad2b36256a0a3b13173b19b..abf2b042a86141774717cfac7fe604adfd1f2c1c 100755 (executable)
@@ -629,5 +629,32 @@ test ${lines:-0} -eq 64 || ret=1
 [ $ret = 0 ] || { echo I:failed; status=1; }
 fi
 
+n=`expr $n + 1`
+echo "I:check check-names processing ($n)"
+ret=0
+$NSUPDATE << EOF > nsupdate.out1-$n 2>&1
+update add # 0 in a 1.2.3.4
+EOF
+grep "bad owner" nsupdate.out1-$n > /dev/null || ret=1
+
+$NSUPDATE << EOF > nsupdate.out2-$n 2>&1
+check-names off
+update add # 0 in a 1.2.3.4
+EOF
+grep "bad owner" nsupdate.out2-$n > /dev/null && ret=1
+
+$NSUPDATE << EOF > nsupdate.out3-$n 2>&1
+update add . 0 in mx 0 #
+EOF
+grep "bad name" nsupdate.out3-$n > /dev/null || ret=1
+
+$NSUPDATE << EOF > nsupdate.out4-$n 2>&1
+check-names off
+update add . 0 in mx 0 #
+EOF
+grep "bad name" nsupdate.out4-$n > /dev/null && ret=1
+
+[ $ret = 0 ] || { echo I:failed; status=1; }
+
 echo "I:exit status: $status"
 exit $status
index a2eef3f2fd2ca16464e09540106eeea5a213e982..98ec9280dc92c3cf60fbced89603fa7c796ba7a0 100644 (file)
@@ -1833,7 +1833,6 @@ load_text(dns_loadctx_t *lctx) {
                                goto insist_and_cleanup;
                }
 
-
                if (type == dns_rdatatype_rrsig ||
                    type == dns_rdatatype_sig)
                        covers = dns_rdata_covers(&rdata[rdcount]);