diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index c7b1c3aab8..6ef6b1d84e 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -386,9 +386,9 @@ status=$((status + ret)) echo_i "checking negative validation NXDOMAIN NSEC3 ($n)" ret=0 -dig_with_opts +noauth q.nsec3.example. \ +dig_with_opts +noauth a.b.c.d.e.f.g.h.i.j.nsec3.example. \ @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth q.nsec3.example. \ +dig_with_opts +noauth a.b.c.d.e.f.g.h.i.j.nsec3.example. \ @10.53.0.4 a >dig.out.ns4.test$n || ret=1 digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index 07ff9a43d5..5cc563884d 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -244,6 +244,7 @@ struct dns_dbonupdatelistener { #define DNS_DBFIND_FORCENSEC3 0x0080 #define DNS_DBFIND_ADDITIONALOK 0x0100 #define DNS_DBFIND_NOZONECUT 0x0200 +#define DNS_DBFIND_WANTPARTIAL 0x0400 /* * DNS_DBFIND_STALEOK: This flag is set when BIND fails to refresh a RRset due diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 5c2f0b252d..bb184f7ed8 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -4134,7 +4134,11 @@ zone_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, : DNS_R_NXDOMAIN; } } else { - result = active ? DNS_R_EMPTYNAME : DNS_R_NXDOMAIN; + bool wantpartial = (options & DNS_DBFIND_WANTPARTIAL) != + 0; + result = active ? DNS_R_EMPTYNAME + : wantpartial ? DNS_R_PARTIALMATCH + : DNS_R_NXDOMAIN; } goto tree_exit; } else if (result != ISC_R_SUCCESS) { diff --git a/lib/ns/query.c b/lib/ns/query.c index 58a9d436fc..0d5274226c 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -11569,6 +11569,7 @@ again: * Find the closest encloser. */ dns_name_copy(name, cname); + bool once = true; while (result == DNS_R_NXDOMAIN) { labels = dns_name_countlabels(cname) - 1; /* @@ -11578,10 +11579,21 @@ again: goto cleanup; } dns_name_split(cname, labels, NULL, cname); - result = dns_db_findext(qctx->db, cname, qctx->version, - dns_rdatatype_nsec, options, 0, - NULL, fname, &cm, &ci, NULL, - NULL); + result = dns_db_findext( + qctx->db, cname, qctx->version, + dns_rdatatype_nsec, + options | (once ? DNS_DBFIND_WANTPARTIAL : 0), + 0, NULL, fname, &cm, &ci, NULL, NULL); + if (result == DNS_R_PARTIALMATCH && once) { + unsigned int flabels = + dns_name_countlabels(fname); + if (labels > flabels + 1) { + dns_name_split(cname, flabels + 1, NULL, + cname); + } + result = DNS_R_NXDOMAIN; + } + once = false; } /* * Add closest (provable) encloser NSEC3.