]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[master] nsec3hash -r
authorEvan Hunt <each@isc.org>
Tue, 13 Jun 2017 07:38:19 +0000 (00:38 -0700)
committerEvan Hunt <each@isc.org>
Tue, 13 Jun 2017 07:39:10 +0000 (00:39 -0700)
4637. [func] "nsec3hash -r" option ("rdata order") takes arguments
in the same order as they appear in NSEC3 or
NSEC3PARAM records, so that NSEC3 parameters can
be cut and pasted from an existing record. Thanks
to Tony Finch for the contribution. [RT #45183]

CHANGES
bin/tests/system/conf.sh.in
bin/tests/system/tools/clean.sh [new file with mode: 0644]
bin/tests/system/tools/tests.sh [new file with mode: 0644]
bin/tools/Makefile.in
bin/tools/nsec3hash.c
bin/tools/nsec3hash.docbook
doc/arm/notes.xml

diff --git a/CHANGES b/CHANGES
index 28e92d2061dc1fb385a41a47c2e940b60e14decc..8e4793e527f5c16d944a3211dcacd3cd387a0ca5 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+4637.  [func]          "nsec3hash -r" option ("rdata order") takes arguments
+                       in the same order as they appear in NSEC3 or
+                       NSEC3PARAM records, so that NSEC3 parameters can
+                       be cut and pasted from an existing record. Thanks
+                       to Tony Finch for the contribution. [RT #45183]
+
 4636.  [bug]           Normalize rpz policy zone names when checking for
                        existence. [RT #45358]
 
index 9781f95d901fbb1f4921493e6cd06b88c378cde3..9b1d314dfeb4def635bceeba3118357581579496 100644 (file)
@@ -49,6 +49,7 @@ ARPANAME=$TOP/bin/tools/arpaname
 RESOLVE=$TOP/lib/samples/resolve
 RRCHECKER=$TOP/bin/tools/named-rrchecker
 GENRANDOM=$TOP/bin/tools/genrandom
+NSEC3HASH=$TOP/bin/tools/nsec3hash
 NSLOOKUP=$TOP/bin/dig/nslookup
 DNSTAPREAD=$TOP/bin/tools/dnstap-read
 MDIG=$TOP/bin/tools/mdig
@@ -83,7 +84,7 @@ SUBDIRS="acl additional addzone allow_query autosign builtin
         pipelined @PKCS11_TEST@ reclimit redirect resolver rndc
         rpz rpzrecurse rrchecker rrl rrsetorder rsabigexponent
         runtime sfcache smartsign sortlist spf staticstub statistics
-        statschannel stub tcp tkey tsig tsiggss unknown upforwd
+        statschannel stub tcp tkey tools tsig tsiggss unknown upforwd
         verify views wildcard xfer xferquota zero zonechecks"
 
 # Things that are different on Windows
@@ -157,6 +158,7 @@ export LWTEST
 export MAKEJOURNAL
 export MDIG
 export NAMED
+export NSEC3HASH
 export NSLOOKUP
 export NSUPDATE
 export NZD2NZF
diff --git a/bin/tests/system/tools/clean.sh b/bin/tests/system/tools/clean.sh
new file mode 100644 (file)
index 0000000..52d57a6
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+#
+# Copyright (C) 2013-2016  Internet Systems Consortium, Inc. ("ISC")
+#
+# 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 http://mozilla.org/MPL/2.0/.
+
+rm -f NSEC3
+rm -f nsec3hash
+rm -f nsec3param
+rm -f testcases
diff --git a/bin/tests/system/tools/tests.sh b/bin/tests/system/tools/tests.sh
new file mode 100644 (file)
index 0000000..df2850e
--- /dev/null
@@ -0,0 +1,69 @@
+#!/bin/sh
+#
+# Copyright (C) 2013-2016  Internet Systems Consortium, Inc. ("ISC")
+#
+# 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 http://mozilla.org/MPL/2.0/.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+checkhash() {
+       name=$1
+       hash=$2
+       echo "I:checking nsec3hash $name"
+       out=`$NSEC3HASH $salt $algo $iters $1`
+       case $? in
+       0) : ok ;;
+       *) echo "I:failed $cmd"
+          status=`expr $status + 1`
+          continue ;;
+       esac
+       case $out in
+       *$hash*) : ok ;;
+       *) echo "I:expect $hash"
+          echo "I:output $out"
+          echo "I:failed"
+          status=`expr $status + 1` ;;
+       esac
+
+       echo "I:checking nsec3hash -r $name"
+       out=`$NSEC3HASH -r $algo $flags $iters $salt $name`
+       case $? in
+       0) : ok ;;
+       *) echo "I:failed $cmd"
+          status=`expr $status + 1`
+          continue ;;
+       esac
+       case $out in
+       *$hash*) : ok ;;
+       *) echo "I:expect $hash"
+          echo "I:output $out"
+          echo "I:failed"
+          status=`expr $status + 1` ;;
+       esac
+}
+
+# test cases taken from RFC 5155 appendix A
+algo=1 flags=0 iters=12 salt="aabbccdd"
+for testcase in \
+   "*.w.example R53BQ7CC2UVMUBFU5OCMM6PERS9TK9EN" \
+   "2t7b4g4vsa5smi47k61mv5bv1a22bojr.example KOHAR7MBB8DC2CE8A9QVL8HON4K53UHI" \
+   "a.example 35MTHGPGCU1QG68FAB165KLNSNK3DPVL" \
+   "ai.example GJEQE526PLBF1G8MKLP59ENFD789NJGI" \
+   "example 0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM" \
+   "ns1.example 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR" \
+   "ns2.example Q04JKCEVQVMU85R014C7DKBA38O0JI5R" \
+   "w.example K8UDEMVP1J2F7EG6JEBPS17VP3N8I58H" \
+   "x.w.example B4UM86EGHHDS6NEA196SMVMLO4ORS995" \
+   "x.y.w.example 2VPTU5TIMAMQTTGL4LUU9KG21E0AOR3S" \
+   "xx.example T644EBQK9BIBCNA874GIVR6JOJ62MLHV" \
+   "y.w.example JI6NEOAEPV8B5O6K4EV33ABHA8HT9FGC"; do
+       checkhash $testcase
+done
+
+echo "I:exit status: $status"
+[ $status -eq 0 ] || exit 1
index 36d7b8dc01a854627e433fad4c7b32f8c927d0a1..9d86f7b8f3e42994040d5a22da765c30b56d8229 100644 (file)
@@ -40,7 +40,7 @@ SUBDIRS =
 DNSTAPTARGETS =        dnstap-read@EXEEXT@
 NZDTARGETS =   named-nzd2nzf@EXEEXT@
 TARGETS =      arpaname@EXEEXT@ named-journalprint@EXEEXT@ \
-               named-rrchecker@EXEEXT@  nsec3hash@EXEEXT@ \
+               named-rrchecker@EXEEXT@ nsec3hash@EXEEXT@ \
                genrandom@EXEEXT@ isc-hmac-fixup@EXEEXT@ mdig@EXEEXT@ \
                @DNSTAPTARGETS@ @NZDTARGETS@
 
index a0af0d1bf970e533a172a3870a9481016ddf7ede..f3c17183c8ffbe7c7a967ff0e98230712fc15c00 100644 (file)
@@ -6,8 +6,6 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-/* $Id: nsec3hash.c,v 1.8 2011/11/02 23:46:24 tbox Exp $ */
-
 #include <config.h>
 
 #include <stdlib.h>
 
 #include <isc/base32.h>
 #include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/file.h>
 #include <isc/hex.h>
 #include <isc/iterated_hash.h>
 #include <isc/print.h>
 #include <isc/result.h>
 #include <isc/string.h>
 #include <isc/types.h>
+#include <isc/util.h>
 
 #include <dns/fixedname.h>
 #include <dns/name.h>
@@ -51,14 +52,21 @@ check_result(isc_result_t result, const char *message) {
 }
 
 static void
-usage(void) {
+usage() {
        fprintf(stderr, "Usage: %s salt algorithm iterations domain\n",
                program);
+       fprintf(stderr, "       %s -r algorithm flags iterations salt domain\n",
+               program);
        exit(1);
 }
 
-int
-main(int argc, char **argv) {
+typedef void nsec3printer(unsigned algo, unsigned flags, unsigned iters,
+                         char *saltstr, char *domain, char *digest);
+
+static void
+nsec3hash(nsec3printer *nsec3print, char *algostr, char *flagstr,
+         char *iterstr, char *saltstr, char *domain)
+{
        dns_fixedname_t fixed;
        dns_name_t *name;
        isc_buffer_t buffer;
@@ -68,35 +76,36 @@ main(int argc, char **argv) {
        unsigned char salt[DNS_NSEC3_SALTSIZE];
        unsigned char text[1024];
        unsigned int hash_alg;
+       unsigned int flags;
        unsigned int length;
        unsigned int iterations;
        unsigned int salt_length;
 
-       if (argc != 5)
-               usage();
-
-       if (strcmp(argv[1], "-") == 0) {
+       if (strcmp(saltstr, "-") == 0) {
                salt_length = 0;
                salt[0] = 0;
        } else {
                isc_buffer_init(&buffer, salt, sizeof(salt));
-               result = isc_hex_decodestring(argv[1], &buffer);
+               result = isc_hex_decodestring(saltstr, &buffer);
                check_result(result, "isc_hex_decodestring(salt)");
                salt_length = isc_buffer_usedlength(&buffer);
                if (salt_length > DNS_NSEC3_SALTSIZE)
                        fatal("salt too long");
        }
-       hash_alg = atoi(argv[2]);
+       hash_alg = atoi(algostr);
        if (hash_alg > 255U)
                fatal("hash algorithm too large");
-       iterations = atoi(argv[3]);
+       flags = flagstr == NULL ? 0 : atoi(flagstr);
+       if (flags > 255U)
+               fatal("flags too large");
+       iterations = atoi(iterstr);
        if (iterations > 0xffffU)
                fatal("iterations to large");
 
        dns_fixedname_init(&fixed);
        name = dns_fixedname_name(&fixed);
-       isc_buffer_init(&buffer, argv[4], strlen(argv[4]));
-       isc_buffer_add(&buffer, strlen(argv[4]));
+       isc_buffer_init(&buffer, domain, strlen(domain));
+       isc_buffer_add(&buffer, strlen(domain));
        result = dns_name_fromtext(name, &buffer, dns_rootname, 0, NULL);
        check_result(result, "dns_name_fromtext() failed");
 
@@ -109,7 +118,60 @@ main(int argc, char **argv) {
        region.length = length;
        isc_buffer_init(&buffer, text, sizeof(text));
        isc_base32hexnp_totext(&region, 1, "", &buffer);
-       fprintf(stdout, "%.*s (salt=%s, hash=%u, iterations=%u)\n",
-               (int)isc_buffer_usedlength(&buffer), text, argv[1], hash_alg, iterations);
+       isc_buffer_putuint8(&buffer, '\0');
+
+       nsec3print(hash_alg, flags, iterations, saltstr, domain, (char *)text);
+}
+
+static void
+nsec3hash_print(unsigned algo, unsigned flags, unsigned iters,
+               char *saltstr, char *domain, char *digest)
+{
+       UNUSED(flags);
+       UNUSED(domain);
+
+       fprintf(stdout, "%s (salt=%s, hash=%u, iterations=%u)\n",
+               digest, saltstr, algo, iters);
+}
+
+static void
+nsec3hash_rdata_print(unsigned algo, unsigned flags, unsigned iters,
+                     char *saltstr, char *domain, char *digest)
+{
+       fprintf(stdout, "%s NSEC3 %u %u %u %s %s\n",
+               domain, algo, flags, iters, saltstr, digest);
+}
+
+int
+main(int argc, char *argv[]) {
+       isc_boolean_t rdata_format = ISC_FALSE;
+       int ch;
+
+       while ((ch = isc_commandline_parse(argc, argv, "r")) != -1) {
+               switch (ch) {
+               case 'r':
+                       rdata_format = ISC_TRUE;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       argc -= isc_commandline_index;
+       argv += isc_commandline_index;
+
+       if (rdata_format) {
+               if (argc != 5) {
+                       usage();
+               }
+               nsec3hash(nsec3hash_rdata_print,
+                         argv[0], argv[1], argv[2], argv[3], argv[4]);
+       } else {
+               if (argc != 4) {
+                       usage();
+               }
+               nsec3hash(nsec3hash_print,
+                         argv[1], NULL, argv[2], argv[0], argv[3]);
+       }
        return(0);
 }
index ddc034275c8351c8885600bd8ff5ddee7008cdf6..cf53a5cf0c6f1d2e805908c4c28102b4d8d9fa31 100644 (file)
       <arg choice="req" rep="norepeat"><replaceable class="parameter">iterations</replaceable></arg>
       <arg choice="req" rep="norepeat"><replaceable class="parameter">domain</replaceable></arg>
     </cmdsynopsis>
+    <cmdsynopsis sepchar=" ">
+      <command>nsec3hash -r</command>
+      <arg choice="req" rep="norepeat"><replaceable class="parameter">algorithm</replaceable></arg>
+      <arg choice="req" rep="norepeat"><replaceable class="parameter">flags</replaceable></arg>
+      <arg choice="req" rep="norepeat"><replaceable class="parameter">iterations</replaceable></arg>
+      <arg choice="req" rep="norepeat"><replaceable class="parameter">salt</replaceable></arg>
+      <arg choice="req" rep="norepeat"><replaceable class="parameter">domain</replaceable></arg>
+    </cmdsynopsis>
   </refsynopsisdiv>
 
   <refsection><info><title>DESCRIPTION</title></info>
       a set of NSEC3 parameters.  This can be used to check the validity
       of NSEC3 records in a signed zone.
     </para>
+
+    <para>
+      If this command is invoked as <command>nsec3hash -r</command>,
+      it takes arguments in an order matching the first four fields
+      of an NSEC3 record, followed by the domain name: algorithm, flags,
+      iterations, salt, domain.  This makes it convenient to copy and
+      paste a portion of an NSEC3 or NSEC3PARAM record into a command
+      line to confirm the correctness of an NSEC3 hash.
+    </para>
+
   </refsection>
 
   <refsection><info><title>ARGUMENTS</title></info>
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term>flags</term>
+        <listitem>
+          <para>
+            Provided for compatibility with NSEC3 record presentation
+            format, but ignored since the flags do not affect the hash.
+          </para>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term>iterations</term>
         <listitem>
index 6711acaaf831cb4b36bff971e086e90a38487881..02c5bdc5b5bd37862edc91d75efd0195c689edc0 100644 (file)
 
   <section xml:id="relnotes_features"><info><title>New Features</title></info>
     <itemizedlist>
+      <listitem>
+       <para>
+         <command>nsec3hash -r</command> ("rdata order") takes arguments
+         in the same order as they appear in NSEC3 or NSEC3PARAM records.
+         This makes it easier to generate an NSEC3 hash using values cut
+         and pasted from an existing record. Thanks to Tony Finch for
+         the contribution. [RT #45183]
+       </para>
+      </listitem>
       <listitem>
        <para>
          Setting <command>max-journal-size</command> to