From 86e65f317a608a397057b50d9f27003590764aeb Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Fri, 20 Dec 2024 20:24:05 +1100 Subject: [PATCH] Re-fetch pending records that failed validation If a deferred validation on data that was originally queried with CD=1 fails, we now repeat the query, since the zone data may have changed in the meantime. (cherry picked from commit 04b1484ed8308baede372e642d1ed7c05c523a94) --- bin/tests/system/dnssec/tests.sh | 6 ---- lib/dns/validator.c | 61 +++++++++++++++++++------------- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index 9f29018c06..061a27262a 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -196,9 +196,6 @@ cp ns2/dnskey-rrsigs-stripped.db.next ns2/dnskey-rrsigs-stripped.db.signed nextpart ns2/named.run >/dev/null rndccmd 10.53.0.2 reload dnskey-rrsigs-stripped | sed 's/^/ns2 /' | cat_i wait_for_log 5 "zone dnskey-rrsigs-stripped/IN: loaded serial 2000042408" ns2/named.run || ret=1 -# make a query that flushes the unsigned DNSKEY RRset -dig_with_opts +noauth a.dnskey-rrsigs-stripped. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -# make a second query that should now validate dig_with_opts +noauth b.dnskey-rrsigs-stripped. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 dig_with_opts +noauth b.dnskey-rrsigs-stripped. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 @@ -219,9 +216,6 @@ cp ns2/ds-rrsigs-stripped.db.next ns2/ds-rrsigs-stripped.db.signed nextpart ns2/named.run >/dev/null rndccmd 10.53.0.2 reload ds-rrsigs-stripped | sed 's/^/ns2 /' | cat_i wait_for_log 5 "zone ds-rrsigs-stripped/IN: loaded serial 2000042408" ns2/named.run || ret=1 -# make a query that flushes the unsigned DS RRset -dig_with_opts +noauth a.child.ds-rrsigs-stripped. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -# make a second query that should now validate dig_with_opts +noauth b.child.ds-rrsigs-stripped. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 dig_with_opts +noauth b.child.ds-rrsigs-stripped. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 diff --git a/lib/dns/validator.c b/lib/dns/validator.c index 1313c9f854..b76f1c53a3 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -137,6 +137,10 @@ validator_logcreate(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, const char *caller, const char *operation); +static isc_result_t +create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, + isc_taskaction_t callback, const char *caller); + /*% * Ensure the validator's rdatasets are marked as expired. */ @@ -641,7 +645,6 @@ validator_callback_dnskey(isc_task_t *task, isc_event_t *event) { dns_validator_t *val; bool want_destroy; isc_result_t result; - isc_result_t eresult; isc_result_t saved_result; UNUSED(task); @@ -649,7 +652,7 @@ validator_callback_dnskey(isc_task_t *task, isc_event_t *event) { devent = (dns_validatorevent_t *)event; val = devent->ev_arg; - eresult = devent->result; + result = devent->result; isc_event_free(&event); dns_validator_destroy(&val->subvalidator); @@ -659,8 +662,8 @@ validator_callback_dnskey(isc_task_t *task, isc_event_t *event) { validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_dnskey"); LOCK(&val->lock); if (CANCELED(val)) { - validator_done(val, ISC_R_CANCELED); - } else if (eresult == ISC_R_SUCCESS) { + result = ISC_R_CANCELED; + } else if (result == ISC_R_SUCCESS) { validator_log(val, ISC_LOG_DEBUG(3), "keyset with trust %s", dns_trust_totext(val->frdataset.trust)); /* @@ -681,17 +684,23 @@ validator_callback_dnskey(isc_task_t *task, isc_event_t *event) { result = saved_result; } } - if (result != DNS_R_WAIT) { - validator_done(val, result); - } } else { - if (eresult != DNS_R_BROKENCHAIN) { - expire_rdatasets(val); - } validator_log(val, ISC_LOG_DEBUG(3), "validator_callback_dnskey: got %s", - isc_result_totext(eresult)); - validator_done(val, DNS_R_BROKENCHAIN); + isc_result_totext(result)); + if (result != DNS_R_BROKENCHAIN) { + expire_rdatasets(val); + result = create_fetch(val, &val->siginfo->signer, + dns_rdatatype_dnskey, + fetch_callback_dnskey, + "validator_callback_dnskey"); + if (result == ISC_R_SUCCESS) { + result = DNS_R_WAIT; + } + } + } + if (result != DNS_R_WAIT) { + validator_done(val, result); } want_destroy = exit_check(val); @@ -712,14 +721,13 @@ validator_callback_ds(isc_task_t *task, isc_event_t *event) { dns_validator_t *val; bool want_destroy; isc_result_t result; - isc_result_t eresult; UNUSED(task); INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE); devent = (dns_validatorevent_t *)event; val = devent->ev_arg; - eresult = devent->result; + result = devent->result; isc_event_free(&event); dns_validator_destroy(&val->subvalidator); @@ -729,8 +737,8 @@ validator_callback_ds(isc_task_t *task, isc_event_t *event) { validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_ds"); LOCK(&val->lock); if (CANCELED(val)) { - validator_done(val, ISC_R_CANCELED); - } else if (eresult == ISC_R_SUCCESS) { + result = ISC_R_CANCELED; + } else if (result == ISC_R_SUCCESS) { bool have_dsset; dns_name_t *name; validator_log(val, ISC_LOG_DEBUG(3), "%s with trust %s", @@ -754,17 +762,22 @@ validator_callback_ds(isc_task_t *task, isc_event_t *event) { } else { result = validate_dnskey(val); } - if (result != DNS_R_WAIT) { - validator_done(val, result); - } } else { - if (eresult != DNS_R_BROKENCHAIN) { - expire_rdatasets(val); - } validator_log(val, ISC_LOG_DEBUG(3), "validator_callback_ds: got %s", - isc_result_totext(eresult)); - validator_done(val, DNS_R_BROKENCHAIN); + isc_result_totext(result)); + if (result != DNS_R_BROKENCHAIN) { + expire_rdatasets(val); + result = create_fetch( + val, val->event->name, dns_rdatatype_ds, + fetch_callback_ds, "validator_callback_ds"); + if (result == ISC_R_SUCCESS) { + result = DNS_R_WAIT; + } + } + } + if (result != DNS_R_WAIT) { + validator_done(val, result); } want_destroy = exit_check(val);