summaryrefslogtreecommitdiff
path: root/validator/validator.c
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2024-10-18 13:52:55 +0000
committerCy Schubert <cy@FreeBSD.org>2024-10-18 13:52:55 +0000
commit0a6d797cf6eb751d7eb613900cd19803e05d905f (patch)
treec52b0ffbf8879fbe81816528e0fc7c3dd0f64e1f /validator/validator.c
parent9b8db746ac608ff7cdad3c9ac7ac395319e4ea0f (diff)
Diffstat (limited to 'validator/validator.c')
-rw-r--r--validator/validator.c81
1 files changed, 75 insertions, 6 deletions
diff --git a/validator/validator.c b/validator/validator.c
index e6d19a2c9f06..857510b655e7 100644
--- a/validator/validator.c
+++ b/validator/validator.c
@@ -97,8 +97,8 @@ fill_nsec3_iter(struct val_env* ve, char* s, int c)
int i;
free(ve->nsec3_keysize);
free(ve->nsec3_maxiter);
- ve->nsec3_keysize = (size_t*)calloc(sizeof(size_t), (size_t)c);
- ve->nsec3_maxiter = (size_t*)calloc(sizeof(size_t), (size_t)c);
+ ve->nsec3_keysize = (size_t*)calloc((size_t)c, sizeof(size_t));
+ ve->nsec3_maxiter = (size_t*)calloc((size_t)c, sizeof(size_t));
if(!ve->nsec3_keysize || !ve->nsec3_maxiter) {
log_err("out of memory");
return 0;
@@ -2435,6 +2435,8 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
/* if the result is bogus - set message ttl to bogus ttl to avoid
* endless bogus revalidation */
if(vq->orig_msg->rep->security == sec_status_bogus) {
+ struct msgreply_entry* e;
+
/* see if we can try again to fetch data */
if(vq->restart_count < ve->max_restart) {
verbose(VERB_ALGO, "validation failed, "
@@ -2449,10 +2451,51 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
return 0;
}
+ if(qstate->env->cfg->serve_expired &&
+ (e=msg_cache_lookup(qstate->env, qstate->qinfo.qname,
+ qstate->qinfo.qname_len, qstate->qinfo.qtype,
+ qstate->qinfo.qclass, qstate->query_flags,
+ 0 /*now; allow expired*/,
+ 1 /*wr; we may update the data*/))) {
+ struct reply_info* rep = (struct reply_info*)e->entry.data;
+ if(rep && rep->security > sec_status_bogus &&
+ (!qstate->env->cfg->serve_expired_ttl ||
+ qstate->env->cfg->serve_expired_ttl_reset ||
+ *qstate->env->now <= rep->serve_expired_ttl)) {
+ verbose(VERB_ALGO, "validation failed but "
+ "previously cached valid response "
+ "exists; set serve-expired-norec-ttl "
+ "for response in cache");
+ rep->serve_expired_norec_ttl = NORR_TTL +
+ *qstate->env->now;
+ if(qstate->env->cfg->serve_expired_ttl_reset &&
+ *qstate->env->now + qstate->env->cfg->serve_expired_ttl
+ > rep->serve_expired_ttl) {
+ verbose(VERB_ALGO, "reset serve-expired-ttl for "
+ "valid response in cache");
+ rep->serve_expired_ttl = *qstate->env->now +
+ qstate->env->cfg->serve_expired_ttl;
+ }
+ /* Return an error response.
+ * If serve-expired-client-timeout is enabled,
+ * the client-timeout logic will try to find an
+ * (expired) answer in the cache as last
+ * resort. If it is not enabled, expired
+ * answers are already used before the mesh
+ * activation. */
+ qstate->return_rcode = LDNS_RCODE_SERVFAIL;
+ qstate->return_msg = NULL;
+ qstate->ext_state[id] = module_finished;
+ lock_rw_unlock(&e->entry.lock);
+ return 0;
+ }
+ lock_rw_unlock(&e->entry.lock);
+ }
+
vq->orig_msg->rep->ttl = ve->bogus_ttl;
vq->orig_msg->rep->prefetch_ttl =
PREFETCH_TTL_CALC(vq->orig_msg->rep->ttl);
- vq->orig_msg->rep->serve_expired_ttl =
+ vq->orig_msg->rep->serve_expired_ttl =
vq->orig_msg->rep->ttl + qstate->env->cfg->serve_expired_ttl;
if((qstate->env->cfg->val_log_level >= 1 ||
qstate->env->cfg->log_servfail) &&
@@ -2518,8 +2561,9 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
* to check if from parentNS */
if(!qstate->no_cache_store) {
if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo,
- vq->orig_msg->rep, 0, qstate->prefetch_leeway, 0, NULL,
- qstate->query_flags, qstate->qstarttime)) {
+ vq->orig_msg->rep, 0, qstate->prefetch_leeway,
+ 0, qstate->region, qstate->query_flags,
+ qstate->qstarttime)) {
log_err("out of memory caching validator results");
}
}
@@ -2527,7 +2571,7 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
/* for a referral, store the verified RRsets */
/* and this does not get prefetched, so no leeway */
if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo,
- vq->orig_msg->rep, 1, 0, 0, NULL,
+ vq->orig_msg->rep, 1, 0, 0, qstate->region,
qstate->query_flags, qstate->qstarttime)) {
log_err("out of memory caching validator results");
}
@@ -2617,6 +2661,14 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id,
qstate->ext_state[id] = module_finished;
return;
}
+ if(qstate->rpz_applied) {
+ verbose(VERB_ALGO, "rpz applied, mark it as insecure");
+ if(qstate->return_msg)
+ qstate->return_msg->rep->security =
+ sec_status_insecure;
+ qstate->ext_state[id] = module_finished;
+ return;
+ }
/* qclass ANY should have validation result from spawned
* queries. If we get here, it is bogus or an internal error */
if(qstate->qinfo.qclass == LDNS_RR_CLASS_ANY) {
@@ -3053,6 +3105,14 @@ process_ds_response(struct module_qstate* qstate, struct val_qstate* vq,
int ret;
*suspend = 0;
vq->empty_DS_name = NULL;
+ if(sub_qstate && sub_qstate->rpz_applied) {
+ verbose(VERB_ALGO, "rpz was applied to the DS lookup, "
+ "make it insecure");
+ vq->key_entry = NULL;
+ vq->state = VAL_FINISHED_STATE;
+ vq->chase_reply->security = sec_status_insecure;
+ return;
+ }
ret = ds_response_to_ke(qstate, vq, id, rcode, msg, qinfo, &dske,
sub_qstate);
if(ret != 0) {
@@ -3146,6 +3206,15 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
char* reason = NULL;
sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
+ if(sub_qstate && sub_qstate->rpz_applied) {
+ verbose(VERB_ALGO, "rpz was applied to the DNSKEY lookup, "
+ "make it insecure");
+ vq->key_entry = NULL;
+ vq->state = VAL_FINISHED_STATE;
+ vq->chase_reply->security = sec_status_insecure;
+ return;
+ }
+
if(rcode == LDNS_RCODE_NOERROR)
dnskey = reply_find_answer_rrset(qinfo, msg->rep);