From: Aram Sargsyan Date: Mon, 18 May 2026 09:17:51 +0000 (+0000) Subject: Fix a 'deny-answer-aliases' bug when using a cached DNAME X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=45c1d760a89d6d680c33935a53d718d1ecbd0e43;p=thirdparty%2Fbind9.git Fix a 'deny-answer-aliases' bug when using a cached DNAME When using a cached DNAME to resolve a name, make sure to consult the denied answers lists, otherwise it is possible to consutruct a restricted alias by caching a DNAME that is a parent of the denied alias. See the comments in the tests case from the previous commit an example. --- diff --git a/lib/ns/query.c b/lib/ns/query.c index ca76df4f3d5..4fd70e6fbcd 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -10137,6 +10138,7 @@ query_cname(query_ctx_t *qctx) { dns_name_copy(&cname.cname, tname); dns_rdata_freestruct(&cname); + ns_client_qnamereplace(qctx->client, tname); qctx->want_restart = true; if (!WANTRECURSION(qctx->client)) { @@ -10260,6 +10262,37 @@ query_dname(query_ctx_t *qctx) { goto cleanup; } + /* + * If the target is a denied alias, and both the `except-from` list + * and the subdomain rule of the `deny-answer-aliases` + * configuration option (see ARM) don't give an exception, then + * answer with a SERVFAIL. + */ + dns_fixedname_t fdeniedname; + dns_name_t *deniedname = dns_fixedname_initname(&fdeniedname); + if (qctx->view->denyanswernames != NULL && + dns_nametree_covered(qctx->view->denyanswernames, qctx->fname, + deniedname, 0) && + !dns_nametree_covered(qctx->view->answernames_exclude, + qctx->client->query.qname, NULL, 0) && + !dns_name_issubdomain(qctx->client->query.qname, deniedname)) + { + char qnamebuf[DNS_NAME_FORMATSIZE]; + char tnamebuf[DNS_NAME_FORMATSIZE]; + + dns_name_format(qctx->client->query.qname, qnamebuf, + sizeof(qnamebuf)); + dns_name_format(qctx->fname, tnamebuf, sizeof(tnamebuf)); + ns_client_log(qctx->client, NS_LOGCATEGORY_QUERIES, + NS_LOGMODULE_QUERY, ISC_LOG_NOTICE, + "DNAME target %s denied for %s (cache)", tnamebuf, + qnamebuf); + QUERY_ERROR(qctx, DNS_R_SERVFAIL); + ns_client_releasename(qctx->client, &qctx->fname); + (void)ns_query_done(qctx); + goto cleanup; + } + ns_client_keepname(qctx->client, qctx->fname, qctx->dbuf); /*