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