Apply XFR-out quota after ACL is checked

Unauthorized clients can consume XFR-out quota and block authorized
XFR clients. Apply the quota after ACL is checked.

(cherry picked from commit 5615e6c47a2cd00d82d48b568cc55a4b89daa330)
This commit is contained in:
Aram Sargsyan 2026-03-31 13:00:00 +00:00 committed by Michał Kępień
parent 85edb6b184
commit 69fb85d994
No known key found for this signature in database

View file

@ -744,6 +744,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
bool is_poll = false;
bool is_dlz = false;
bool is_ixfr = false;
bool is_quota_applied = false;
bool useviewacl = false;
uint32_t begin_serial = 0, current_serial;
@ -760,16 +761,6 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
ISC_LOG_DEBUG(6), "%s request", mnemonic);
/*
* Apply quota.
*/
result = isc_quota_acquire(&client->manager->sctx->xfroutquota);
if (result != ISC_R_SUCCESS) {
isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,
"%s request denied: %s", mnemonic,
isc_result_totext(result));
goto max_quota;
}
/*
* Interpret the question section.
@ -940,6 +931,19 @@ got_soa:
FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");
}
/*
* Apply quota after ACL is checked, so that unauthorized clients
* can not starve the authorized clients.
*/
result = isc_quota_acquire(&client->manager->sctx->xfroutquota);
if (result != ISC_R_SUCCESS) {
isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,
"%s request denied: %s", mnemonic,
isc_result_totext(result));
goto cleanup;
}
is_quota_applied = true;
/*
* Look up the requesting server in the peer table.
*/
@ -1078,7 +1082,7 @@ have_stream:
CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));
/*
* Create the xfrout context object. This transfers the ownership
* of "stream", "db", "ver", and "quota" to the xfrout context object.
* of "stream", "db" and "ver" to the xfrout context object.
*/
if (is_dlz) {
@ -1193,10 +1197,13 @@ cleanup:
}
if (xfr != NULL) {
/* The quota will be released in xfrout_ctx_destroy(). */
INSIST(is_quota_applied);
xfrout_fail(xfr, result, "setting up zone transfer");
} else if (result != ISC_R_SUCCESS) {
isc_quota_release(&client->manager->sctx->xfroutquota);
max_quota:
if (is_quota_applied) {
isc_quota_release(&client->manager->sctx->xfroutquota);
}
ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
NS_LOGMODULE_XFER_OUT, ISC_LOG_DEBUG(3),
"zone transfer setup failed");