From ada40193c85276867c6904545601c7c01e3236c3 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 20 Oct 2011 21:42:11 +0000 Subject: [PATCH] 3175. [bug] Fix how DNSSEC positive wildcard responses from a NSEC3 signed zone are validated. Stop sending a unnecessary NSEC3 record when generating such responses. [RT #26200] --- CHANGES | 5 ++++ bin/named/query.c | 7 +++-- bin/tests/system/dnssec/tests.sh | 20 ++++++++++++- lib/dns/validator.c | 49 ++++++++++++++++++++++++++------ 4 files changed, 68 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index f05395176c..4b5089fecf 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +3175. [bug] Fix how DNSSEC positive wildcard responses from a + NSEC3 signed zone are validated. Stop sending a + unnecessary NSEC3 record when generating such + responses. [RT #26200] + 3174. [bug] Always compute to revoked key tag from scratch. [RT #24711] diff --git a/bin/named/query.c b/bin/named/query.c index 2d6c91323f..36850fdf2f 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: query.c,v 1.375 2011/10/13 22:48:23 tbox Exp $ */ +/* $Id: query.c,v 1.376 2011/10/20 21:42:11 marka Exp $ */ /*! \file */ @@ -3378,8 +3378,9 @@ query_addwildcardproof(ns_client_t *client, dns_db_t *db, sigrdataset, fname, ISC_TRUE, cname); if (!dns_rdataset_isassociated(rdataset)) goto cleanup; - query_addrrset(client, &fname, &rdataset, &sigrdataset, - dbuf, DNS_SECTION_AUTHORITY); + if (!ispositive) + query_addrrset(client, &fname, &rdataset, &sigrdataset, + dbuf, DNS_SECTION_AUTHORITY); /* * Replace resources which were consumed by query_addrrset. diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index 8e7c65e4d2..13e1b3cd8a 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -15,7 +15,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: tests.sh,v 1.98 2011/10/15 05:00:15 marka Exp $ +# $Id: tests.sh,v 1.99 2011/10/20 21:42:11 marka Exp $ SYSTEMTESTTOP=.. . $SYSTEMTESTTOP/conf.sh @@ -133,6 +133,24 @@ n=`expr $n + 1` if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` +echo "I:checking positive wildcard answer NSEC3 ($n)" +ret=0 +$DIG $DIGOPTS a.wild.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1 +grep "AUTHORITY: 4," dig.out.ns3.test$n > /dev/null || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:checking positive wildcard answer NSEC3 ($n)" +ret=0 +$DIG $DIGOPTS a.wild.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1 +grep "AUTHORITY: 4," dig.out.ns3.test$n > /dev/null || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + echo "I:checking positive wildcard validation NSEC3 ($n)" ret=0 $DIG $DIGOPTS a.wild.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1 diff --git a/lib/dns/validator.c b/lib/dns/validator.c index 4049b1ccab..0af80177e2 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: validator.c,v 1.205 2011/10/15 05:00:15 marka Exp $ */ +/* $Id: validator.c,v 1.206 2011/10/20 21:42:11 marka Exp $ */ #include @@ -1922,13 +1922,14 @@ verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata, isc_result_t result; dns_fixedname_t fixed; isc_boolean_t ignore = ISC_FALSE; + dns_name_t *wild; val->attributes |= VALATTR_TRIEDVERIFY; dns_fixedname_init(&fixed); + wild = dns_fixedname_name(&fixed); again: result = dns_dnssec_verify2(val->event->name, val->event->rdataset, - key, ignore, val->view->mctx, rdata, - dns_fixedname_name(&fixed)); + key, ignore, val->view->mctx, rdata, wild); if (result == DNS_R_SIGEXPIRED && val->view->acceptexpired) { ignore = ISC_TRUE; goto again; @@ -1943,9 +1944,20 @@ verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata, "verify rdataset (keyid=%u): %s", keyid, isc_result_totext(result)); if (result == DNS_R_FROMWILDCARD) { - if (!dns_name_equal(val->event->name, - dns_fixedname_name(&fixed))) + if (!dns_name_equal(val->event->name, wild)) { + dns_name_t *closest; + unsigned int labels; + + /* + * Compute the closest encloser in case we need it + * for the NSEC3 NOQNAME proof. + */ + closest = dns_fixedname_name(&val->closest); + dns_name_copy(wild, closest, NULL); + labels = dns_name_countlabels(closest) - 1; + dns_name_getlabelsequence(closest, 1, labels, closest); val->attributes |= VALATTR_NEEDNOQNAME; + } result = ISC_R_SUCCESS; } return (result); @@ -2873,9 +2885,9 @@ findnsec3proofs(dns_validator_t *val) { dns_name_t *name, tname; isc_result_t result; isc_boolean_t exists, data, optout, unknown; - isc_boolean_t setclosest, setnearest; + isc_boolean_t setclosest, setnearest, *setclosestp; dns_fixedname_t fclosest, fnearest, fzonename; - dns_name_t *closest, *nearest, *zonename; + dns_name_t *closest, *nearest, *zonename, *closestp; dns_name_t **proofs = val->event->proofs; dns_rdataset_t *rdataset, trdataset; @@ -2922,6 +2934,25 @@ findnsec3proofs(dns_validator_t *val) { if (dns_name_countlabels(zonename) == 0) return (ISC_R_SUCCESS); + /* + * If the val->closest is set then we want to use it otherwise + * we need to discover it. + */ + if (dns_name_countlabels(dns_fixedname_name(&val->closest)) != 0) { + char namebuf[DNS_NAME_FORMATSIZE]; + + dns_name_format(dns_fixedname_name(&val->closest), + namebuf, sizeof(namebuf)); + validator_log(val, ISC_LOG_DEBUG(3), "closest encloser from " + "wildcard signature '%s'", namebuf); + dns_name_copy(dns_fixedname_name(&val->closest), closest, NULL); + closestp = NULL; + setclosestp = NULL; + } else { + closestp = closest; + setclosestp = &setclosest; + } + for (result = val_rdataset_first(val, &name, &rdataset); result == ISC_R_SUCCESS; result = val_rdataset_next(val, &name, &rdataset)) @@ -2939,8 +2970,8 @@ findnsec3proofs(dns_validator_t *val) { unknown = ISC_FALSE; (void)nsec3noexistnodata(val, val->event->name, name, rdataset, zonename, &exists, &data, &optout, - &unknown, &setclosest, &setnearest, - closest, nearest); + &unknown, setclosestp, &setnearest, + closestp, nearest); if (setclosest) proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name; if (unknown)