From 525dc475ee4f1d4f214ad38ca78d59828005acdf Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 5 May 2016 22:27:08 +1000 Subject: [PATCH] 4360. [bug] Silence spurious 'bad key type' message when there is a existing TSIG key. [RT #42195] (cherry picked from commit 5ac427050fa0e303171133ce3855b284ab4cfbb7) --- CHANGES | 3 +++ bin/dnssec/dnssectool.c | 25 ++++++++++++++++++++++++ bin/tests/system/tsig/clean.sh | 2 ++ bin/tests/system/tsig/setup.sh | 17 +++++++++++++++++ bin/tests/system/tsig/tests.sh | 13 +++++++++++-- lib/dns/dnssec.c | 35 ++++++++++++++++++++++++++++++---- 6 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 bin/tests/system/tsig/setup.sh diff --git a/CHANGES b/CHANGES index 142c85408c..d57e5ef08e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +4360. [bug] Silence spurious 'bad key type' message when there is + a existing TSIG key. [RT #42195] + 4359. [bug] Inherited 'also-notify' lists were not being checked by named-checkconf. [RT #42174] diff --git a/bin/dnssec/dnssectool.c b/bin/dnssec/dnssectool.c index 42936414ab..62c42bf45b 100644 --- a/bin/dnssec/dnssectool.c +++ b/bin/dnssec/dnssectool.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -472,6 +473,8 @@ key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir, isc_uint16_t id, oldid; isc_uint32_t rid, roldid; dns_secalg_t alg; + char filename[ISC_DIR_NAMEMAX]; + isc_buffer_t fileb; if (exact != NULL) *exact = ISC_FALSE; @@ -480,6 +483,28 @@ key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir, rid = dst_key_rid(dstkey); alg = dst_key_alg(dstkey); + /* + * For HMAC and Diffie Hellman just check if there is a + * direct collision as they can't be revoked. Additionally + * dns_dnssec_findmatchingkeys only handles DNSKEY which is + * not used for HMAC. + */ + switch (alg) { + case DST_ALG_HMACMD5: + case DST_ALG_HMACSHA1: + case DST_ALG_HMACSHA224: + case DST_ALG_HMACSHA256: + case DST_ALG_HMACSHA384: + case DST_ALG_HMACSHA512: + case DST_ALG_DH: + isc_buffer_init(&fileb, filename, sizeof(filename)); + result = dst_key_buildfilename(dstkey, DST_TYPE_PRIVATE, + dir, &fileb); + if (result != ISC_R_SUCCESS) + return (ISC_TRUE); + return (isc_file_exists(filename)); + } + ISC_LIST_INIT(matchkeys); result = dns_dnssec_findmatchingkeys(name, dir, mctx, &matchkeys); if (result == ISC_R_NOTFOUND) diff --git a/bin/tests/system/tsig/clean.sh b/bin/tests/system/tsig/clean.sh index 0e98b4047b..713d777af6 100644 --- a/bin/tests/system/tsig/clean.sh +++ b/bin/tests/system/tsig/clean.sh @@ -23,3 +23,5 @@ rm -f dig.out.* rm -f */named.memstats rm -f */named.run +rm -f Kexample.net.+163+* +rm -f keygen.out? diff --git a/bin/tests/system/tsig/setup.sh b/bin/tests/system/tsig/setup.sh new file mode 100644 index 0000000000..637ef3e256 --- /dev/null +++ b/bin/tests/system/tsig/setup.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# +# Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +sh clean.sh diff --git a/bin/tests/system/tsig/tests.sh b/bin/tests/system/tsig/tests.sh index 50ac8d23e6..db38c7e30a 100644 --- a/bin/tests/system/tsig/tests.sh +++ b/bin/tests/system/tsig/tests.sh @@ -233,6 +233,15 @@ grep -i "sha1.*TSIG.*NOERROR" dig.out.sha1 > /dev/null || ret=1 if [ $ret -eq 1 ] ; then echo "I: failed"; status=1 fi + +echo "I:check that multiple dnssec-keygen calls don't emit dns_dnssec_findmatchingkeys warning" +ret=0 +$KEYGEN -a hmac-sha256 -b 128 -n host example.net > keygen.out1 2>&1 || ret=1 +grep dns_dnssec_findmatchingkeys keygen.out1 > /dev/null && ret=1 +$KEYGEN -a hmac-sha256 -b 128 -n host example.net > keygen.out2 2>&1 || ret=1 +grep dns_dnssec_findmatchingkeys keygen.out2 > /dev/null && ret=1 +if [ $ret -eq 1 ] ; then + echo "I: failed"; status=1 +fi + exit $status - - diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c index 82ee9d1d79..5a450e65e9 100644 --- a/lib/dns/dnssec.c +++ b/lib/dns/dnssec.c @@ -1311,6 +1311,7 @@ isc_result_t dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory, isc_mem_t *mctx, dns_dnsseckeylist_t *keylist) { + const char *digits = "0123456789"; isc_result_t result = ISC_R_SUCCESS; isc_boolean_t dir_open = ISC_FALSE; dns_dnsseckeylist_t list; @@ -1319,7 +1320,7 @@ dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory, dst_key_t *dstkey = NULL; char namebuf[DNS_NAME_FORMATSIZE]; isc_buffer_t b; - unsigned int len, i; + unsigned int len, i, alg; isc_stdtime_t now; REQUIRE(keylist != NULL); @@ -1345,11 +1346,20 @@ dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory, strncasecmp(dir.entry.name + 1, namebuf, len) != 0) continue; - for (i = len + 1 + 1; i < dir.entry.length ; i++) + alg = 0; + for (i = len + 1 + 1; i < dir.entry.length ; i++) { if (dir.entry.name[i] < '0' || dir.entry.name[i] > '9') break; + alg *= 10; + alg += strchr(digits, dir.entry.name[i]) - digits; + } - if (i == len + 1 + 1 || i >= dir.entry.length || + /* + * Did we not read exactly 3 digits? + * Did we overflow? + * Did we correctly terminate? + */ + if (i != len + 1 + 1 + 3 || i >= dir.entry.length || dir.entry.name[i] != '+') continue; @@ -1357,7 +1367,13 @@ dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory, if (dir.entry.name[i] < '0' || dir.entry.name[i] > '9') break; - if (strcmp(dir.entry.name + i, ".private") != 0) + /* + * Did we not read exactly 5 more digits? + * Did we overflow? + * Did we correctly terminate? + */ + if (i != len + 1 + 1 + 3 + 1 + 5 || i >= dir.entry.length || + strcmp(dir.entry.name + i, ".private") != 0) continue; dstkey = NULL; @@ -1367,6 +1383,17 @@ dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory, DST_TYPE_PRIVATE, mctx, &dstkey); + switch (alg) { + case DST_ALG_HMACMD5: + case DST_ALG_HMACSHA1: + case DST_ALG_HMACSHA224: + case DST_ALG_HMACSHA256: + case DST_ALG_HMACSHA384: + case DST_ALG_HMACSHA512: + if (result == DST_R_BADKEYTYPE) + continue; + } + if (result != ISC_R_SUCCESS) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,