diff options
Diffstat (limited to 'validator/val_neg.c')
| -rw-r--r-- | validator/val_neg.c | 27 |
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; |
