diff --git a/validator/val_utils.c b/validator/val_utils.c index d32ba0377..e9addfdd5 100644 --- a/validator/val_utils.c +++ b/validator/val_utils.c @@ -963,3 +963,26 @@ void val_errinf_dname(struct module_qstate* qstate, struct val_qstate* vq, snprintf(b, sizeof(b), "%s %s", str, buf); val_errinf(qstate, vq, b); } + +int val_has_signed_nsecs(struct reply_info* rep, char** reason) +{ + size_t i, num_nsec = 0, num_nsec3 = 0; + struct packed_rrset_data* d; + for(i=rep->an_numrrsets; ian_numrrsets+rep->ns_numrrsets; i++) { + if(rep->rrsets[i]->rk.type == htons(LDNS_RR_TYPE_NSEC)) + num_nsec++; + else if(rep->rrsets[i]->rk.type == htons(LDNS_RR_TYPE_NSEC3)) + num_nsec3++; + else continue; + d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data; + if(d && d->rrsig_count != 0) { + return 1; + } + } + if(num_nsec == 0 && num_nsec3 == 0) + *reason = "no DNSSEC records"; + else if(num_nsec != 0) + *reason = "no signatures over NSECs"; + else *reason = "no signatures over NSEC3s"; + return 0; +} diff --git a/validator/val_utils.h b/validator/val_utils.h index f5e865be4..3be69a35f 100644 --- a/validator/val_utils.h +++ b/validator/val_utils.h @@ -358,4 +358,12 @@ void val_errinf_dname(struct module_qstate* qstate, struct val_qstate* vq, */ char* val_errinf_to_str(struct module_qstate* qstate, struct val_qstate* vq); +/** + * check if has dnssec info, and if it has signed nsecs. gives error reason. + * @param rep: reply to check. + * @param reason: returned on fail. + * @return false if message has no signed nsecs. Can not prove negatives. + */ +int val_has_signed_nsecs(struct reply_info* rep, char** reason); + #endif /* VALIDATOR_VAL_UTILS_H */ diff --git a/validator/validator.c b/validator/validator.c index 7d8fb3dfd..75102954f 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -2310,6 +2310,14 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq, /* NODATA means that the qname exists, but that there was * no DS. This is a pretty normal case. */ uint32_t proof_ttl = 0; + enum sec_status sec; + + /* make sure there are NSECs or NSEC3s with signatures */ + if(!val_has_signed_nsecs(msg->rep, &reason)) { + verbose(VERB_ALGO, "no NSECs: %s", reason); + val_errinf(qstate, vq, reason); + goto return_bogus; + } /* For subtype Name Error. * attempt ANS 2.8.1.0 compatibility where it sets rcode @@ -2317,7 +2325,7 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq, * Find and prove the empty nonterminal in that case */ /* Try to prove absence of the DS with NSEC */ - enum sec_status sec = val_nsec_prove_nodata_dsreply( + sec = val_nsec_prove_nodata_dsreply( qstate->env, ve, qinfo, msg->rep, vq->key_entry, &proof_ttl); switch(sec) {