mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 14:35:26 +00:00
1448. [bug] Handle empty wildcards labels.
developer: marka reviewer: explorer
This commit is contained in:
2
CHANGES
2
CHANGES
@@ -1,3 +1,5 @@
|
||||
1448. [bug] Handle empty wildcards labels.
|
||||
|
||||
1447. [bug] We were casting (unsigned int) to and from (void *).
|
||||
rdataset->private4 is now rdataset->privateuint4
|
||||
to reflect a type change.
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: query.c,v 1.242 2003/01/31 12:07:56 marka Exp $ */
|
||||
/* $Id: query.c,v 1.243 2003/02/27 00:19:03 marka Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -1899,7 +1899,7 @@ query_addwildcardproof(ns_client_t *client, dns_db_t *db,
|
||||
*/
|
||||
if (result == ISC_R_SUCCESS && ispositive)
|
||||
break;
|
||||
if (result == DNS_R_NXDOMAIN) {
|
||||
if (result == DNS_R_NXDOMAIN || result == DNS_R_EMPTYNAME) {
|
||||
if (!ispositive &&
|
||||
dns_name_issubdomain(name, fname))
|
||||
done = ISC_TRUE;
|
||||
@@ -2269,6 +2269,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
dns_rdata_cname_t cname;
|
||||
dns_rdata_dname_t dname;
|
||||
unsigned int options;
|
||||
isc_boolean_t empty_wild;
|
||||
|
||||
CTRACE("query_find");
|
||||
|
||||
@@ -2292,6 +2293,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
version = NULL;
|
||||
zone = NULL;
|
||||
need_wildcardproof = ISC_FALSE;
|
||||
empty_wild = ISC_FALSE;
|
||||
options = 0;
|
||||
|
||||
if (event != NULL) {
|
||||
@@ -2745,6 +2747,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
&rdataset, &sigrdataset);
|
||||
}
|
||||
goto cleanup;
|
||||
case DNS_R_EMPTYWILD:
|
||||
empty_wild = ISC_TRUE;
|
||||
/* FALLTHROUGH */
|
||||
case DNS_R_NXDOMAIN:
|
||||
INSIST(is_zone);
|
||||
if (dns_rdataset_isassociated(rdataset)) {
|
||||
@@ -2792,7 +2797,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
/*
|
||||
* Set message rcode.
|
||||
*/
|
||||
client->message->rcode = dns_rcode_nxdomain;
|
||||
if (empty_wild)
|
||||
client->message->rcode = dns_rcode_noerror;
|
||||
else
|
||||
client->message->rcode = dns_rcode_nxdomain;
|
||||
goto cleanup;
|
||||
case DNS_R_NCACHENXDOMAIN:
|
||||
case DNS_R_NCACHENXRRSET:
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: result.h,v 1.96 2003/01/18 03:18:31 marka Exp $ */
|
||||
/* $Id: result.h,v 1.97 2003/02/27 00:19:04 marka Exp $ */
|
||||
|
||||
#ifndef DNS_RESULT_H
|
||||
#define DNS_RESULT_H 1
|
||||
@@ -134,8 +134,9 @@
|
||||
#define DNS_R_UNEXPECTEDOPCODE (ISC_RESULTCLASS_DNS + 90)
|
||||
#define DNS_R_CHASEDSSERVERS (ISC_RESULTCLASS_DNS + 91)
|
||||
#define DNS_R_EMPTYNAME (ISC_RESULTCLASS_DNS + 92)
|
||||
#define DNS_R_EMPTYWILD (ISC_RESULTCLASS_DNS + 93)
|
||||
|
||||
#define DNS_R_NRESULTS 93 /* Number of results */
|
||||
#define DNS_R_NRESULTS 94 /* Number of results */
|
||||
|
||||
/*
|
||||
* DNS wire format rcodes.
|
||||
|
168
lib/dns/rbtdb.c
168
lib/dns/rbtdb.c
@@ -15,7 +15,7 @@
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: rbtdb.c,v 1.185 2003/02/26 23:52:29 marka Exp $ */
|
||||
/* $Id: rbtdb.c,v 1.186 2003/02/27 00:19:03 marka Exp $ */
|
||||
|
||||
/*
|
||||
* Principal Author: Bob Halley
|
||||
@@ -1086,6 +1086,34 @@ add_wildcard_magic(dns_rbtdb_t *rbtdb, dns_name_t *name) {
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
add_empty_wildcards(dns_rbtdb_t *rbtdb, dns_name_t *name) {
|
||||
isc_result_t result;
|
||||
dns_name_t foundname;
|
||||
dns_offsets_t offsets;
|
||||
unsigned int n, l, i;
|
||||
|
||||
dns_name_init(&foundname, offsets);
|
||||
n = dns_name_countlabels(name);
|
||||
l = dns_name_countlabels(&rbtdb->common.origin);
|
||||
i = l + 1;
|
||||
while (i < n) {
|
||||
dns_rbtnode_t *node = NULL; /* dummy */
|
||||
dns_name_getlabelsequence(name, n - i, i, &foundname);
|
||||
if (dns_name_iswildcard(&foundname)) {
|
||||
result = add_wildcard_magic(rbtdb, &foundname);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
result = dns_rbt_addnode(rbtdb->tree, &foundname,
|
||||
&node);
|
||||
if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS)
|
||||
return (result);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
|
||||
dns_dbnode_t **nodep)
|
||||
@@ -1126,6 +1154,8 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
|
||||
node->locknum = dns_name_hash(&nodename, ISC_TRUE) %
|
||||
rbtdb->node_lock_count;
|
||||
#endif
|
||||
add_empty_wildcards(rbtdb, name);
|
||||
|
||||
if (dns_name_iswildcard(name)) {
|
||||
result = add_wildcard_magic(rbtdb, name);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
@@ -1436,6 +1466,56 @@ valid_glue(rbtdb_search_t *search, dns_name_t *name, rbtdb_rdatatype_t type,
|
||||
return (valid);
|
||||
}
|
||||
|
||||
static inline isc_boolean_t
|
||||
activeempty(rbtdb_search_t *search, dns_rbtnodechain_t *chain,
|
||||
dns_name_t *name)
|
||||
{
|
||||
dns_fixedname_t fnext;
|
||||
dns_fixedname_t forigin;
|
||||
dns_name_t *next;
|
||||
dns_name_t *origin;
|
||||
dns_name_t prefix;
|
||||
dns_rbtdb_t *rbtdb;
|
||||
dns_rbtnode_t *node;
|
||||
isc_result_t result;
|
||||
isc_boolean_t answer = ISC_FALSE;
|
||||
rdatasetheader_t *header;
|
||||
|
||||
rbtdb = search->rbtdb;
|
||||
|
||||
dns_name_init(&prefix, NULL);
|
||||
dns_fixedname_init(&fnext);
|
||||
next = dns_fixedname_name(&fnext);
|
||||
dns_fixedname_init(&forigin);
|
||||
origin = dns_fixedname_name(&forigin);
|
||||
|
||||
result = dns_rbtnodechain_next(chain, NULL, NULL);
|
||||
while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
|
||||
node = NULL;
|
||||
result = dns_rbtnodechain_current(chain, &prefix,
|
||||
origin, &node);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
break;
|
||||
LOCK(&(rbtdb->node_locks[node->locknum].lock));
|
||||
for (header = node->data;
|
||||
header != NULL;
|
||||
header = header->next) {
|
||||
if (header->serial <= search->serial &&
|
||||
!IGNORE(header) && EXISTS(header))
|
||||
break;
|
||||
}
|
||||
UNLOCK(&(rbtdb->node_locks[node->locknum].lock));
|
||||
if (header != NULL)
|
||||
break;
|
||||
result = dns_rbtnodechain_next(chain, NULL, NULL);
|
||||
}
|
||||
if (result == ISC_R_SUCCESS)
|
||||
result = dns_name_concatenate(&prefix, origin, next, NULL);
|
||||
if (result == ISC_R_SUCCESS && dns_name_issubdomain(next, name))
|
||||
answer = ISC_TRUE;
|
||||
return (answer);
|
||||
}
|
||||
|
||||
static inline isc_boolean_t
|
||||
activeemtpynode(rbtdb_search_t *search, dns_name_t *qname, dns_name_t *wname) {
|
||||
dns_fixedname_t fnext;
|
||||
@@ -1452,6 +1532,7 @@ activeemtpynode(rbtdb_search_t *search, dns_name_t *qname, dns_name_t *wname) {
|
||||
dns_rbtnodechain_t chain;
|
||||
isc_boolean_t check_next = ISC_TRUE;
|
||||
isc_boolean_t check_prev = ISC_TRUE;
|
||||
isc_boolean_t answer = ISC_FALSE;
|
||||
isc_result_t result;
|
||||
rdatasetheader_t *header;
|
||||
unsigned int n;
|
||||
@@ -1533,15 +1614,17 @@ activeemtpynode(rbtdb_search_t *search, dns_name_t *qname, dns_name_t *wname) {
|
||||
|
||||
do {
|
||||
if ((check_prev && dns_name_issubdomain(prev, &rname)) ||
|
||||
(check_next && dns_name_issubdomain(next, &rname)))
|
||||
return (ISC_TRUE);
|
||||
(check_next && dns_name_issubdomain(next, &rname))) {
|
||||
answer = ISC_TRUE;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Remove the left hand label.
|
||||
*/
|
||||
n = dns_name_countlabels(&rname);
|
||||
dns_name_getlabelsequence(&rname, 1, n - 1, &rname);
|
||||
} while (!dns_name_equal(&rname, &tname));
|
||||
return (ISC_FALSE);
|
||||
return (answer);
|
||||
}
|
||||
|
||||
static inline isc_result_t
|
||||
@@ -1557,6 +1640,7 @@ find_wildcard(rbtdb_search_t *search, dns_rbtnode_t **nodep,
|
||||
dns_fixedname_t fwname;
|
||||
dns_rbtdb_t *rbtdb;
|
||||
isc_boolean_t done, wild, active;
|
||||
dns_rbtnodechain_t wchain;
|
||||
|
||||
/*
|
||||
* Caller must be holding the tree lock and MUST NOT be holding
|
||||
@@ -1630,8 +1714,9 @@ find_wildcard(rbtdb_search_t *search, dns_rbtnode_t **nodep,
|
||||
break;
|
||||
|
||||
wnode = NULL;
|
||||
dns_rbtnodechain_init(&wchain, NULL);
|
||||
result = dns_rbt_findnode(rbtdb->tree, wname,
|
||||
NULL, &wnode, NULL,
|
||||
NULL, &wnode, &wchain,
|
||||
DNS_RBTFIND_EMPTYDATA,
|
||||
NULL, NULL);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
@@ -1649,7 +1734,8 @@ find_wildcard(rbtdb_search_t *search, dns_rbtnode_t **nodep,
|
||||
break;
|
||||
}
|
||||
UNLOCK(&(rbtdb->node_locks[wnode->locknum].lock));
|
||||
if (header != NULL) {
|
||||
if (header != NULL ||
|
||||
activeempty(search, &wchain, wname)) {
|
||||
if (activeemtpynode(search, qname, wname))
|
||||
return (ISC_R_NOTFOUND);
|
||||
/*
|
||||
@@ -1846,9 +1932,6 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
|
||||
rdatasetheader_t *header, *header_next, *found, *nxtheader;
|
||||
rdatasetheader_t *foundsig, *cnamesig, *nxtsig;
|
||||
rbtdb_rdatatype_t sigtype;
|
||||
dns_fixedname_t fnext;
|
||||
dns_fixedname_t forigin;
|
||||
dns_name_t nname, *next, *origin;
|
||||
isc_boolean_t active;
|
||||
dns_rbtnodechain_t chain;
|
||||
|
||||
@@ -1925,45 +2008,9 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
|
||||
goto tree_exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find if this is a active empty node (next active node is
|
||||
* subdomain if 'name'). This is a simpler test than is
|
||||
* required for activeemptynode() where name is not as
|
||||
* constained.
|
||||
*/
|
||||
active = ISC_FALSE;
|
||||
dns_fixedname_init(&fnext);
|
||||
next = dns_fixedname_name(&fnext);
|
||||
dns_fixedname_init(&forigin);
|
||||
origin = dns_fixedname_name(&forigin);
|
||||
dns_name_init(&nname, NULL);
|
||||
chain = search.chain;
|
||||
result = dns_rbtnodechain_next(&chain, NULL, NULL);
|
||||
while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
|
||||
node = NULL;
|
||||
result = dns_rbtnodechain_current(&chain, &nname,
|
||||
origin, &node);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
break;
|
||||
LOCK(&(search.rbtdb->node_locks[node->locknum].lock));
|
||||
for (header = node->data;
|
||||
header != NULL;
|
||||
header = header->next) {
|
||||
if (header->serial <= search.serial &&
|
||||
!IGNORE(header) && EXISTS(header))
|
||||
break;
|
||||
}
|
||||
UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock));
|
||||
if (header != NULL) {
|
||||
result = dns_name_concatenate(&nname, origin,
|
||||
next, NULL);
|
||||
if (result == ISC_R_SUCCESS &&
|
||||
dns_name_issubdomain(next, name))
|
||||
active = ISC_TRUE;
|
||||
break;
|
||||
}
|
||||
result = dns_rbtnodechain_next(&chain, NULL, NULL);
|
||||
}
|
||||
active = activeempty(&search, &chain, name);
|
||||
|
||||
/*
|
||||
* If we're here, then the name does not exist, is not
|
||||
* beneath a zonecut, and there's no matching wildcard.
|
||||
@@ -2162,14 +2209,11 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
|
||||
* active rdatasets in the desired version. That means that
|
||||
* this node doesn't exist in the desired version, and that
|
||||
* we really have a partial match.
|
||||
*
|
||||
* If the node is the result of a wildcard match, then
|
||||
* it must be active in the desired version, and hence
|
||||
* empty_node should never be true. We INSIST upon it.
|
||||
*/
|
||||
INSIST(!wild);
|
||||
UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock));
|
||||
goto partial_match;
|
||||
if (!wild) {
|
||||
UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock));
|
||||
goto partial_match;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2198,8 +2242,18 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
|
||||
* The zone is secure but there's no NXT,
|
||||
* or the NXT has no signature!
|
||||
*/
|
||||
result = DNS_R_BADDB;
|
||||
goto node_exit;
|
||||
if (!wild) {
|
||||
result = DNS_R_BADDB;
|
||||
goto node_exit;
|
||||
}
|
||||
|
||||
UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock));
|
||||
result = find_closest_nxt(&search, nodep, foundname,
|
||||
rdataset, sigrdataset,
|
||||
search.rbtdb->secure);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
result = DNS_R_EMPTYWILD;
|
||||
goto tree_exit;
|
||||
}
|
||||
if ((search.options & DNS_DBFIND_FORCENXT) != 0 &&
|
||||
nxtheader == NULL)
|
||||
@@ -4138,6 +4192,8 @@ loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) {
|
||||
!IS_CACHE(rbtdb) && !dns_name_equal(name, &rbtdb->common.origin))
|
||||
return (DNS_R_NOTZONETOP);
|
||||
|
||||
add_empty_wildcards(rbtdb, name);
|
||||
|
||||
if (dns_name_iswildcard(name)) {
|
||||
/*
|
||||
* NS record owners cannot legally be wild cards.
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: result.c,v 1.106 2003/01/18 03:18:30 marka Exp $ */
|
||||
/* $Id: result.c,v 1.107 2003/02/27 00:19:03 marka Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -140,7 +140,8 @@ static const char *text[DNS_R_NRESULTS] = {
|
||||
|
||||
"unexpected OPCODE", /* 90 DNS_R_UNEXPECTEDOPCODE */
|
||||
"chase DS servers", /* 91 DNS_R_CHASEDSSERVERS */
|
||||
"empty name" /* 92 DNS_R_EMPTYNAME */
|
||||
"empty name", /* 92 DNS_R_EMPTYNAME */
|
||||
"empty wild" /* 93 DNS_R_EMPTYWILD */
|
||||
};
|
||||
|
||||
static const char *rcode_text[DNS_R_NRCODERESULTS] = {
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: validator.c,v 1.111 2003/01/18 03:18:30 marka Exp $ */
|
||||
/* $Id: validator.c,v 1.112 2003/02/27 00:19:04 marka Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -441,7 +441,7 @@ nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
|
||||
isc_boolean_t isnxdomain;
|
||||
isc_result_t result;
|
||||
dns_namereln_t relation;
|
||||
unsigned int labels, bits;
|
||||
unsigned int olabels, nlabels, labels, bits;
|
||||
|
||||
INSIST(DNS_MESSAGE_VALID(val->event->message));
|
||||
|
||||
@@ -459,7 +459,8 @@ nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
|
||||
dns_rdataset_current(nxtset, &rdata);
|
||||
|
||||
validator_log(val, ISC_LOG_DEBUG(3), "looking for relevant nxt");
|
||||
order = dns_name_compare(val->event->name, nxtname);
|
||||
relation = dns_name_fullcompare(val->event->name, nxtname,
|
||||
&order, &olabels, &bits);
|
||||
if (order == 0) {
|
||||
/*
|
||||
* The names are the same. Look for the type present bit.
|
||||
@@ -495,16 +496,39 @@ nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
relation = dns_name_fullcompare(&nxt.next,
|
||||
val->event->name,
|
||||
&order, &labels, &bits);
|
||||
dns_rdata_freestruct(&nxt);
|
||||
if (order <= 0 || relation != dns_namereln_subdomain) {
|
||||
&order, &nlabels,
|
||||
&bits);
|
||||
if (order > 0 && relation == dns_namereln_subdomain) {
|
||||
dns_rdata_freestruct(&nxt);
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"missing NXT record at name");
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"nxt proves empty node, ok");
|
||||
return (ISC_TRUE);
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
/*
|
||||
* Look for empty wildcard matches.
|
||||
*/
|
||||
labels = dns_name_countlabels(&nxt.next);
|
||||
if (nlabels >= olabels && nlabels + 1 < labels) {
|
||||
dns_name_t wild;
|
||||
dns_name_init(&wild, NULL);
|
||||
dns_name_getlabelsequence(&nxt.next,
|
||||
labels - 1 - nlabels,
|
||||
nlabels + 1,
|
||||
&wild);
|
||||
if (dns_name_iswildcard(&wild)) {
|
||||
dns_rdata_freestruct(&nxt);
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"nxt proves empty wildcard, ok");
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* We are not a empty name.
|
||||
*/
|
||||
dns_rdata_freestruct(&nxt);
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"missing NXT record at name");
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
if (dns_name_issubdomain(val->event->name, nxtname) &&
|
||||
dns_nxt_typepresent(&rdata, dns_rdatatype_ns) &&
|
||||
@@ -524,7 +548,7 @@ nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
|
||||
return (ISC_FALSE);
|
||||
dns_rdata_reset(&rdata);
|
||||
relation = dns_name_fullcompare(&nxt.next, val->event->name,
|
||||
&order, &labels, &bits);
|
||||
&order, &nlabels, &bits);
|
||||
if (order <= 0) {
|
||||
/*
|
||||
* The NXT next name is less than the nonexistent
|
||||
|
Reference in New Issue
Block a user