From dot@dotat.at Thu May 4 15:57:37 2017 CC: "Tony Finch" MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL autolearn=ham autolearn_force=no version=3.4.0 X-Cam-Antivirus: no malware found content-type: TEXT/PLAIN; charset="utf-8" Message-ID: Received: from mx.pao1.isc.org (mx.pao1.isc.org [IPv6:2001:4f8:0:2::2b]) by bugs.isc.org (Postfix) with ESMTP id 9062771B5A8 for ; Thu, 4 May 2017 15:57:37 +0000 (UTC) Received: from ppsw-30.csi.cam.ac.uk (ppsw-30.csi.cam.ac.uk [131.111.8.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx.pao1.isc.org (Postfix) with ESMTPS id 329553493E0 for ; Thu, 4 May 2017 15:57:32 +0000 (UTC) Received: from grey.csi.cam.ac.uk ([131.111.57.57]:38770) by ppsw-30.csi.cam.ac.uk (ppsw.cam.ac.uk [131.111.8.136]:25) with esmtps (TLSv1:ECDHE-RSA-AES256-SHA:256) id 1d6J8C-000YzR-fC (Exim 4.89) (return-path ); Thu, 04 May 2017 16:57:28 +0100 Delivered-To: bind9-bugs@bugs.isc.org Subject: [PATCH] Alternative NSEC3 mode for nsec3hash User-Agent: Alpine 2.11 (DEB 23 2013-08-11) Return-Path: X-Original-To: bind9-bugs@bugs.isc.org Date: Thu, 4 May 2017 16:57:28 +0100 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mx.pao1.isc.org To: bind9-bugs@isc.org X-Cam-Scannerinfo: http://help.uis.cam.ac.uk/email-scanner-virus From: "Tony Finch" X-RT-Original-Encoding: ascii X-RT-Interface: Email Content-Length: 13940 When nsec3hash is invoked as NSEC3 it takes arguments in the same order as the NSEC3 record presentation format. This makes it easy to invoke the command by copy-and-paste from dig to sh without having to remember the order of arguments. --- bin/tests/system/conf.sh.in | 2 + bin/tests/system/nsec3hash/clean.sh | 12 ++++++ bin/tests/system/nsec3hash/tests.sh | 76 +++++++++++++++++++++++++++++++++++++ bin/tools/.gitignore | 1 + bin/tools/Makefile.in | 11 +++++- bin/tools/nsec3hash.8 | 11 +++++- bin/tools/nsec3hash.c | 70 ++++++++++++++++++++++++++-------- bin/tools/nsec3hash.docbook | 27 +++++++++++++ 8 files changed, 192 insertions(+), 18 deletions(-) create mode 100644 bin/tests/system/nsec3hash/clean.sh create mode 100644 bin/tests/system/nsec3hash/tests.sh diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in index 8e1bbd6..78ac6f4 100644 --- a/bin/tests/system/conf.sh.in +++ b/bin/tests/system/conf.sh.in @@ -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 @@ -156,6 +157,7 @@ export LWTEST export MAKEJOURNAL export MDIG export NAMED +export NSEC3HASH export NSLOOKUP export NSUPDATE export NZD2NZF diff --git a/bin/tests/system/nsec3hash/clean.sh b/bin/tests/system/nsec3hash/clean.sh new file mode 100644 index 0000000..52d57a6 --- /dev/null +++ b/bin/tests/system/nsec3hash/clean.sh @@ -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/nsec3hash/tests.sh b/bin/tests/system/nsec3hash/tests.sh new file mode 100644 index 0000000..8c22e79 --- /dev/null +++ b/bin/tests/system/nsec3hash/tests.sh @@ -0,0 +1,76 @@ +#!/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 + +# work around libtool breaking argv[0] +ltbin=${NSEC3HASH%/*}/.libs/nsec3hash +[ -x $ltbin ] && NSEC3HASH=$ltbin +ln -sf $NSEC3HASH ./nsec3hash +ln -sf $NSEC3HASH ./NSEC3 + +# test cases from RFC 5155 appendix A +rfc5155=../../../../doc/rfc/rfc5155.txt + +grep ' NSEC3PARAM ' $rfc5155 >nsec3param || { + echo "I:failed grep NSEC3PARAM" + exit 1 +} +NSEC3PARAM() { + algo=$1 + flags=$2 + iters=$3 + salt=$4 +} +. ./nsec3param + +$PERL -e ' + undef $/; + my $rfc = <>; + my %hash = $rfc =~ + m{\n ; H\(([^)]+)\)[\s\n;]+= (\S+)}g; + printf "%s %s\n", $_, uc $hash{$_} + for sort keys %hash; +' <$rfc5155 >testcases + +case $(wc -l #include +#include #include #include #include @@ -51,14 +52,18 @@ check_result(isc_result_t result, const char *message) { } static void -usage(void) { - fprintf(stderr, "Usage: %s salt algorithm iterations domain\n", - program); +usage(const char *args) { + fprintf(stderr, "Usage: %s %s\n", program, args); 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 +73,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 +115,39 @@ main(int argc, char **argv) { 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) { + (void)flags; (void)domain; + fprintf(stdout, "%s (salt=%s, hash=%u, iterations=%u)\n", + digest, saltstr, algo, iters); +} + +static void +NSEC3_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[]) { + if (strcmp(isc_file_basename(argv[0]), "NSEC3") == 0) { + program = "NSEC3"; + if (argc != 6) + usage("algo flags iters salt domain"); + nsec3hash(NSEC3_print, + argv[1], argv[2], argv[3], argv[4], argv[5]); + } else { + if (argc != 5) + usage("salt algorithm iterations domain"); + nsec3hash(nsec3hash_print, + argv[2], NULL, argv[3], argv[1], argv[4]); + } return(0); } diff --git a/bin/tools/nsec3hash.docbook b/bin/tools/nsec3hash.docbook index ddc0342..5f19c71 100644 --- a/bin/tools/nsec3hash.docbook +++ b/bin/tools/nsec3hash.docbook @@ -24,6 +24,7 @@ nsec3hash + NSEC3 generate NSEC3 hash @@ -45,6 +46,14 @@ iterations domain + + NSEC3 + algorithm + flags + iterations + salt + domain + DESCRIPTION @@ -54,6 +63,14 @@ a set of NSEC3 parameters. This can be used to check the validity of NSEC3 records in a signed zone. + + + This command can also be invoked as NSEC3, in + which case it takes arguments matching the first four fields of + an NSEC3 record. This makes it convenient to copy and paste an + NSEC3 or NSEC3PARAM record into a command line. + + ARGUMENTS @@ -81,6 +98,16 @@ + flags + + + Provided for compatibility with NSEC3 record presentation + format, but ignored since the flags do not affect the hash. + + + + + iterations -- 2.10.1.445.g3cdd5d1