--- /dev/null
+#!/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
* 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>
}
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;
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");
region.length = length;
isc_buffer_init(&buffer, text, sizeof(text));
isc_base32hexnp_totext(®ion, 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);
}
<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>