From: Ondřej Surý Date: Tue, 23 Jun 2026 05:03:43 +0000 (+0200) Subject: Make the per-fetch validation quota terminal in sub-validations X-Git-Tag: v9.21.24~6^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9515482462e2705b3a962a7f122fadea4bb2a9e8;p=thirdparty%2Fbind9.git Make the per-fetch validation quota terminal in sub-validations Negative-proof validation stops once the per-fetch validation quota is exhausted, but the DNSKEY, DS and CNAME sub-validator callbacks did not — they re-fetched the record or relabelled the quota as a broken chain. Treat ISC_R_QUOTA as terminal in all three, as validator_callback_nsec already does. --- diff --git a/lib/dns/validator.c b/lib/dns/validator.c index f36b5c89b62..b6e5f2c66a7 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -693,7 +693,14 @@ validator_callback_dnskey(void *arg) { } validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_dnskey"); - if (result == ISC_R_SUCCESS) { + if (result != ISC_R_SUCCESS) { + validator_log(val, ISC_LOG_DEBUG(3), + "validator_callback_dnskey: got %s", + isc_result_totext(result)); + } + + switch (result) { + case ISC_R_SUCCESS: validator_log(val, ISC_LOG_DEBUG(3), "keyset with trust %s", dns_trust_totext(val->frdataset.trust)); /* @@ -705,20 +712,26 @@ validator_callback_dnskey(void *arg) { } else { result = validate_async_run(val, resume_answer); } - } else { - validator_log(val, ISC_LOG_DEBUG(3), - "validator_callback_dnskey: got %s", - isc_result_totext(result)); - if (result != DNS_R_BROKENCHAIN) { - expire_rdatasets(val); - result = create_fetch(val, &val->siginfo->signer, - dns_rdatatype_dnskey, NULL, NULL, - fetch_callback_dnskey, - "validator_callback_dnskey"); - if (result == ISC_R_SUCCESS) { - result = DNS_R_WAIT; - } + break; + case ISC_R_CANCELED: /* Validation was canceled */ + case ISC_R_SHUTTINGDOWN: /* Server shutting down */ + case ISC_R_QUOTA: /* Validation fails quota reached */ + val->attributes |= subvalidator->attributes & + (VALATTR_MAXVALIDATIONS | + VALATTR_MAXVALIDATIONFAILS); + break; + case DNS_R_BROKENCHAIN: + break; + default: + expire_rdatasets(val); + result = create_fetch(val, &val->siginfo->signer, + dns_rdatatype_dnskey, NULL, NULL, + fetch_callback_dnskey, + "validator_callback_dnskey"); + if (result == ISC_R_SUCCESS) { + result = DNS_R_WAIT; } + break; } cleanup: @@ -746,16 +759,21 @@ validator_callback_ds(void *arg) { } validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_ds"); - if (result == ISC_R_SUCCESS) { - bool have_dsset; - dns_name_t *name; + if (result != ISC_R_SUCCESS) { + validator_log(val, ISC_LOG_DEBUG(3), + "validator_callback_ds: got %s", + isc_result_totext(result)); + } + + switch (result) { + case ISC_R_SUCCESS: validator_log(val, ISC_LOG_DEBUG(3), "%s with trust %s", val->frdataset.type == dns_rdatatype_ds ? "dsset" : "ds non-existence", dns_trust_totext(val->frdataset.trust)); - have_dsset = (val->frdataset.type == dns_rdatatype_ds); - name = dns_fixedname_name(&val->fname); + bool have_dsset = (val->frdataset.type == dns_rdatatype_ds); + dns_name_t *name = dns_fixedname_name(&val->fname); if ((val->attributes & VALATTR_INSECURITY) != 0 && val->frdataset.covers == dns_rdatatype_ds && @@ -770,19 +788,24 @@ validator_callback_ds(void *arg) { } else { result = validate_async_run(val, validate_dnskey); } - } else { - validator_log(val, ISC_LOG_DEBUG(3), - "validator_callback_ds: got %s", - isc_result_totext(result)); - if (result != DNS_R_BROKENCHAIN) { - expire_rdatasets(val); - result = create_ds_fetch(val, val->name, - fetch_callback_ds, - "validator_callback_ds"); - if (result == ISC_R_SUCCESS) { - result = DNS_R_WAIT; - } + break; + case ISC_R_CANCELED: /* Validation was canceled */ + case ISC_R_SHUTTINGDOWN: /* Server shutting down */ + case ISC_R_QUOTA: /* Validation fails quota reached */ + val->attributes |= subvalidator->attributes & + (VALATTR_MAXVALIDATIONS | + VALATTR_MAXVALIDATIONFAILS); + break; + case DNS_R_BROKENCHAIN: + break; + default: + expire_rdatasets(val); + result = create_ds_fetch(val, val->name, fetch_callback_ds, + "validator_callback_ds"); + if (result == ISC_R_SUCCESS) { + result = DNS_R_WAIT; } + break; } cleanup: @@ -801,8 +824,7 @@ static void validator_callback_cname(void *arg) { dns_validator_t *subvalidator = (dns_validator_t *)arg; dns_validator_t *val = subvalidator->parent; - isc_result_t result; - isc_result_t eresult = subvalidator->result; + isc_result_t result = subvalidator->result; INSIST((val->attributes & VALATTR_INSECURITY) != 0); @@ -813,18 +835,30 @@ validator_callback_cname(void *arg) { } validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_cname"); - if (eresult == ISC_R_SUCCESS) { + if (result != ISC_R_SUCCESS) { + validator_log(val, ISC_LOG_DEBUG(3), + "validator_callback_cname: got %s", + isc_result_totext(result)); + } + switch (result) { + case ISC_R_SUCCESS: validator_log(val, ISC_LOG_DEBUG(3), "cname with trust %s", dns_trust_totext(val->frdataset.trust)); result = proveunsecure(val, false, false, true); - } else { - if (eresult != DNS_R_BROKENCHAIN) { - expire_rdatasets(val); - } - validator_log(val, ISC_LOG_DEBUG(3), - "validator_callback_cname: got %s", - isc_result_totext(eresult)); + break; + case ISC_R_CANCELED: /* Validation was canceled */ + case ISC_R_SHUTTINGDOWN: /* Server shutting down */ + case ISC_R_QUOTA: /* Validation fails quota reached */ + val->attributes |= subvalidator->attributes & + (VALATTR_MAXVALIDATIONS | + VALATTR_MAXVALIDATIONFAILS); + break; + case DNS_R_BROKENCHAIN: + break; + default: + expire_rdatasets(val); result = DNS_R_BROKENCHAIN; + break; } cleanup: @@ -846,8 +880,7 @@ validator_callback_nsec(void *arg) { dns_validator_t *subvalidator = (dns_validator_t *)arg; dns_validator_t *val = subvalidator->parent; dns_rdataset_t *rdataset = subvalidator->rdataset; - isc_result_t result; - isc_result_t eresult = subvalidator->result; + isc_result_t result = subvalidator->result; bool exists, data; val->subvalidator = NULL; @@ -857,7 +890,13 @@ validator_callback_nsec(void *arg) { } validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_nsec"); - if (eresult == ISC_R_SUCCESS) { + if (result != ISC_R_SUCCESS) { + validator_log(val, ISC_LOG_DEBUG(3), + "validator_callback_nsec: got %s", + isc_result_totext(result)); + } + switch (result) { + case ISC_R_SUCCESS: { dns_name_t **proofs = val->proofs; dns_name_t *wild = dns_fixedname_name(&val->wild); @@ -911,29 +950,24 @@ validator_callback_nsec(void *arg) { } result = validate_nx(val, true); - } else { - validator_log(val, ISC_LOG_DEBUG(3), - "validator_callback_nsec: got %s", - isc_result_totext(eresult)); - switch (eresult) { - case ISC_R_CANCELED: - case ISC_R_SHUTTINGDOWN: - case ISC_R_QUOTA: - val->attributes |= subvalidator->attributes & - (VALATTR_MAXVALIDATIONS | - VALATTR_MAXVALIDATIONFAILS); - result = eresult; - break; - case DNS_R_BROKENCHAIN: - val->authfail++; - FALLTHROUGH; - default: - if (val->nxset != NULL) { - val->nxset->attributes.ncache = false; - } - result = validate_nx(val, true); - break; + break; + } + case ISC_R_CANCELED: /* Validation was canceled */ + case ISC_R_SHUTTINGDOWN: /* Server shutting down */ + case ISC_R_QUOTA: /* Validation fails quota reached */ + val->attributes |= subvalidator->attributes & + (VALATTR_MAXVALIDATIONS | + VALATTR_MAXVALIDATIONFAILS); + break; + case DNS_R_BROKENCHAIN: + val->authfail++; + FALLTHROUGH; + default: + if (val->nxset != NULL) { + val->nxset->attributes.ncache = false; } + result = validate_nx(val, true); + break; } cleanup: