summaryrefslogtreecommitdiff
path: root/validator/validator.c
diff options
context:
space:
mode:
Diffstat (limited to 'validator/validator.c')
-rw-r--r--validator/validator.c61
1 files changed, 51 insertions, 10 deletions
diff --git a/validator/validator.c b/validator/validator.c
index 456bffd005f30..5ed45e9bdefd4 100644
--- a/validator/validator.c
+++ b/validator/validator.c
@@ -51,6 +51,7 @@
#include "validator/val_sigcrypt.h"
#include "validator/autotrust.h"
#include "services/cache/dns.h"
+#include "services/cache/rrset.h"
#include "util/data/dname.h"
#include "util/module.h"
#include "util/log.h"
@@ -461,7 +462,7 @@ generate_keytag_query(struct module_qstate* qstate, int id,
return 0;
}
- log_nametypeclass(VERB_ALGO, "keytag query", keytagdname,
+ log_nametypeclass(VERB_OPS, "generate keytag query", keytagdname,
LDNS_RR_TYPE_NULL, ta->dclass);
if(!generate_request(qstate, id, keytagdname, dnamebuf_len,
LDNS_RR_TYPE_NULL, ta->dclass, 0, &newq, 1)) {
@@ -745,6 +746,8 @@ validate_positive_response(struct module_env* env, struct val_env* ve,
struct key_entry_key* kkey)
{
uint8_t* wc = NULL;
+ size_t wl;
+ int wc_cached = 0;
int wc_NSEC_ok = 0;
int nsec3s_seen = 0;
size_t i;
@@ -757,13 +760,19 @@ validate_positive_response(struct module_env* env, struct val_env* ve,
/* Check to see if the rrset is the result of a wildcard
* expansion. If so, an additional check will need to be
* made in the authority section. */
- if(!val_rrset_wildcard(s, &wc)) {
+ if(!val_rrset_wildcard(s, &wc, &wl)) {
log_nametypeclass(VERB_QUERY, "Positive response has "
"inconsistent wildcard sigs:", s->rk.dname,
ntohs(s->rk.type), ntohs(s->rk.rrset_class));
chase_reply->security = sec_status_bogus;
return;
}
+ if(wc && !wc_cached && env->cfg->aggressive_nsec) {
+ rrset_cache_update_wildcard(env->rrset_cache, s, wc, wl,
+ env->alloc, *env->now);
+ wc_cached = 1;
+ }
+
}
/* validate the AUTHORITY section as well - this will generally be
@@ -944,6 +953,9 @@ validate_nameerror_response(struct module_env* env, struct val_env* ve,
int nsec3s_seen = 0;
struct ub_packed_rrset_key* s;
size_t i;
+ uint8_t* ce;
+ int ce_labs = 0;
+ int prev_ce_labs = 0;
for(i=chase_reply->an_numrrsets; i<chase_reply->an_numrrsets+
chase_reply->ns_numrrsets; i++) {
@@ -951,9 +963,19 @@ validate_nameerror_response(struct module_env* env, struct val_env* ve,
if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC) {
if(val_nsec_proves_name_error(s, qchase->qname))
has_valid_nsec = 1;
- if(val_nsec_proves_no_wc(s, qchase->qname,
- qchase->qname_len))
- has_valid_wnsec = 1;
+ ce = nsec_closest_encloser(qchase->qname, s);
+ ce_labs = dname_count_labels(ce);
+ /* Use longest closest encloser to prove wildcard. */
+ if(ce_labs > prev_ce_labs ||
+ (ce_labs == prev_ce_labs &&
+ has_valid_wnsec == 0)) {
+ if(val_nsec_proves_no_wc(s, qchase->qname,
+ qchase->qname_len))
+ has_valid_wnsec = 1;
+ else
+ has_valid_wnsec = 0;
+ }
+ prev_ce_labs = ce_labs;
if(val_nsec_proves_insecuredelegation(s, qchase)) {
verbose(VERB_ALGO, "delegation is insecure");
chase_reply->security = sec_status_insecure;
@@ -1068,6 +1090,7 @@ validate_any_response(struct module_env* env, struct val_env* ve,
/* but check if a wildcard response is given, then check NSEC/NSEC3
* for qname denial to see if wildcard is applicable */
uint8_t* wc = NULL;
+ size_t wl;
int wc_NSEC_ok = 0;
int nsec3s_seen = 0;
size_t i;
@@ -1086,7 +1109,7 @@ validate_any_response(struct module_env* env, struct val_env* ve,
/* Check to see if the rrset is the result of a wildcard
* expansion. If so, an additional check will need to be
* made in the authority section. */
- if(!val_rrset_wildcard(s, &wc)) {
+ if(!val_rrset_wildcard(s, &wc, &wl)) {
log_nametypeclass(VERB_QUERY, "Positive ANY response"
" has inconsistent wildcard sigs:",
s->rk.dname, ntohs(s->rk.type),
@@ -1175,6 +1198,7 @@ validate_cname_response(struct module_env* env, struct val_env* ve,
struct key_entry_key* kkey)
{
uint8_t* wc = NULL;
+ size_t wl;
int wc_NSEC_ok = 0;
int nsec3s_seen = 0;
size_t i;
@@ -1187,7 +1211,7 @@ validate_cname_response(struct module_env* env, struct val_env* ve,
/* Check to see if the rrset is the result of a wildcard
* expansion. If so, an additional check will need to be
* made in the authority section. */
- if(!val_rrset_wildcard(s, &wc)) {
+ if(!val_rrset_wildcard(s, &wc, &wl)) {
log_nametypeclass(VERB_QUERY, "Cname response has "
"inconsistent wildcard sigs:", s->rk.dname,
ntohs(s->rk.type), ntohs(s->rk.rrset_class));
@@ -1296,6 +1320,9 @@ validate_cname_noanswer_response(struct module_env* env, struct val_env* ve,
int nsec3s_seen = 0; /* nsec3s seen */
struct ub_packed_rrset_key* s;
size_t i;
+ uint8_t* nsec_ce; /* Used to find the NSEC with the longest ce */
+ int ce_labs = 0;
+ int prev_ce_labs = 0;
/* the AUTHORITY section */
for(i=chase_reply->an_numrrsets; i<chase_reply->an_numrrsets+
@@ -1314,9 +1341,19 @@ validate_cname_noanswer_response(struct module_env* env, struct val_env* ve,
ce = nsec_closest_encloser(qchase->qname, s);
nxdomain_valid_nsec = 1;
}
- if(val_nsec_proves_no_wc(s, qchase->qname,
- qchase->qname_len))
- nxdomain_valid_wnsec = 1;
+ nsec_ce = nsec_closest_encloser(qchase->qname, s);
+ ce_labs = dname_count_labels(nsec_ce);
+ /* Use longest closest encloser to prove wildcard. */
+ if(ce_labs > prev_ce_labs ||
+ (ce_labs == prev_ce_labs &&
+ nxdomain_valid_wnsec == 0)) {
+ if(val_nsec_proves_no_wc(s, qchase->qname,
+ qchase->qname_len))
+ nxdomain_valid_wnsec = 1;
+ else
+ nxdomain_valid_wnsec = 0;
+ }
+ prev_ce_labs = ce_labs;
if(val_nsec_proves_insecuredelegation(s, qchase)) {
verbose(VERB_ALGO, "delegation is insecure");
chase_reply->security = sec_status_insecure;
@@ -2134,6 +2171,10 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
if(vq->orig_msg->rep->security == sec_status_secure) {
log_query_info(VERB_DETAIL, "validation success",
&qstate->qinfo);
+ if(!qstate->no_cache_store) {
+ val_neg_addreply(qstate->env->neg_cache,
+ vq->orig_msg->rep);
+ }
}
}