aboutsummaryrefslogtreecommitdiff
path: root/validator/val_neg.c
diff options
context:
space:
mode:
Diffstat (limited to 'validator/val_neg.c')
-rw-r--r--validator/val_neg.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/validator/val_neg.c b/validator/val_neg.c
index e82f335b9ad9..63f380ad9ecf 100644
--- a/validator/val_neg.c
+++ b/validator/val_neg.c
@@ -938,6 +938,10 @@ void val_neg_addreply(struct val_neg_cache* neg, struct reply_info* rep)
continue;
if(!dname_subdomain_c(rep->rrsets[i]->rk.dname,
zone->name)) continue;
+ if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC &&
+ !nsec_nextowner_subdomain(rep->rrsets[i], zone->name)) {
+ continue; /* nextowner not in zone */
+ }
/* insert NSEC into this zone's tree */
neg_insert_data(neg, zone, rep->rrsets[i]);
}
@@ -1022,6 +1026,10 @@ void val_neg_addreferral(struct val_neg_cache* neg, struct reply_info* rep,
continue;
if(!dname_subdomain_c(rep->rrsets[i]->rk.dname,
zone->name)) continue;
+ if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC &&
+ !nsec_nextowner_subdomain(rep->rrsets[i], zone->name)) {
+ continue; /* nextowner not in zone */
+ }
/* insert NSEC into this zone's tree */
neg_insert_data(neg, zone, rep->rrsets[i]);
}
@@ -1110,12 +1118,14 @@ grab_nsec(struct rrset_cache* rrset_cache, uint8_t* qname, size_t qname_len,
* @param rrset_cache: rrset cache
* @param now: to check ttl against
* @param region: where to alloc result
+ * @param topname: do not look higher than this name, so that the
+ * result cannot be taken from a zone above the current trust anchor.
* @return rrset or NULL
*/
static struct ub_packed_rrset_key*
neg_find_nsec(struct val_neg_cache* neg_cache, uint8_t* qname, size_t qname_len,
uint16_t qclass, struct rrset_cache* rrset_cache, time_t now,
- struct regional* region)
+ struct regional* region, uint8_t* topname)
{
int labs;
uint32_t flags;
@@ -1133,6 +1143,11 @@ neg_find_nsec(struct val_neg_cache* neg_cache, uint8_t* qname, size_t qname_len,
lock_basic_unlock(&neg_cache->lock);
return NULL;
}
+ if(topname && !dname_subdomain_c(zone->name, topname)) {
+ /* Reject NSEC not within trust anchor's bailiwick */
+ lock_basic_unlock(&neg_cache->lock);
+ return NULL;
+ }
/* NSEC only for now */
if(zone->nsec3_hash) {
@@ -1223,8 +1238,8 @@ neg_params_ok(struct val_neg_zone* zone, struct ub_packed_rrset_key* rrset)
return 0;
return (h == zone->nsec3_hash && it == zone->nsec3_iter &&
slen == zone->nsec3_saltlen &&
- (slen != 0 && zone->nsec3_salt && s
- && memcmp(zone->nsec3_salt, s, slen) == 0));
+ (slen == 0 || (slen != 0 && zone->nsec3_salt && s
+ && memcmp(zone->nsec3_salt, s, slen) == 0)));
}
/** get next closer for nsec3 proof */
@@ -1313,7 +1328,7 @@ neg_nsec3_proof_ds(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len,
!nsec3_has_type(ce_rrset, 0, LDNS_RR_TYPE_NS))
return NULL;
if(!(msg = dns_msg_create(qname, qname_len,
- LDNS_RR_TYPE_DS, zone->dclass, region, 1)))
+ LDNS_RR_TYPE_DS, zone->dclass, region, 2))) /* ce + soa */
return NULL;
/* The cache response means recursion is available. */
msg->rep->flags |= BIT_RA;
@@ -1430,7 +1445,7 @@ val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo,
/* Get best available NSEC for qname */
nsec = neg_find_nsec(neg, qinfo->qname, qinfo->qname_len, qinfo->qclass,
- rrset_cache, now, region);
+ rrset_cache, now, region, topname);
/* Matching NSEC, use to generate No Data answer. Not creating answers
* yet for No Data proven using wildcard. */
@@ -1510,7 +1525,7 @@ val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo,
* proof */
if(!(wcrr = neg_find_nsec(neg, wc_qinfo.qname,
wc_qinfo.qname_len, qinfo->qclass,
- rrset_cache, now, region)))
+ rrset_cache, now, region, topname)))
return NULL;
nodata_wc = NULL;