]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Return SERVFAIL for a too long CNAME chain
authorAram Sargsyan <aram@isc.org>
Thu, 6 Jun 2024 12:06:59 +0000 (12:06 +0000)
committerAram Sargsyan <aram@isc.org>
Wed, 31 Jul 2024 15:14:43 +0000 (15:14 +0000)
Due to the maximum query restart limitation a long CNAME chain
it is cut after 16 queries but named still returns NOERROR.

Return SERVFAIL instead and the partial answer.

(cherry picked from commit b621f1d88e2a8a4e22d871e90e58ef4bd4b6050f)

lib/ns/query.c

index 132a151bedb15ad082a2cf0dacb662448e28f294..866ea9d50904274ae568dedce20d685ed3bed5b2 100644 (file)
@@ -11910,7 +11910,7 @@ isc_result_t
 ns_query_done(query_ctx_t *qctx) {
        isc_result_t result = ISC_R_UNSET;
        const dns_namelist_t *secs = qctx->client->message->sections;
-       bool nodetach;
+       bool nodetach, partial_result_with_servfail = false;
 
        CCTRACE(ISC_LOG_DEBUG(3), "ns_query_done");
 
@@ -11944,13 +11944,36 @@ ns_query_done(query_ctx_t *qctx) {
        /*
         * Do we need to restart the query (e.g. for CNAME chaining)?
         */
-       if (qctx->want_restart && qctx->client->query.restarts < MAX_RESTARTS) {
-               qctx->client->query.restarts++;
-               return (ns__query_start(qctx));
+       if (qctx->want_restart) {
+               if (qctx->client->query.restarts < MAX_RESTARTS) {
+                       qctx->client->query.restarts++;
+                       return (ns__query_start(qctx));
+               } else {
+                       /*
+                        * This is e.g. a long CNAME chain which we cut short.
+                        */
+                       qctx->client->query.attributes |=
+                               NS_QUERYATTR_PARTIALANSWER;
+                       qctx->client->message->rcode = dns_rcode_servfail;
+                       qctx->result = DNS_R_SERVFAIL;
+
+                       /*
+                        * Send the answer back with a SERVFAIL result even
+                        * if recursion was requested.
+                        */
+                       partial_result_with_servfail = true;
+
+                       ns_client_extendederror(qctx->client, 0,
+                                               "max. restarts reached");
+                       ns_client_log(qctx->client, NS_LOGCATEGORY_CLIENT,
+                                     NS_LOGMODULE_QUERY, ISC_LOG_INFO,
+                                     "query iterations limit reached");
+               }
        }
 
        if (qctx->result != ISC_R_SUCCESS &&
-           (!PARTIALANSWER(qctx->client) || WANTRECURSION(qctx->client) ||
+           (!PARTIALANSWER(qctx->client) ||
+            (WANTRECURSION(qctx->client) && !partial_result_with_servfail) ||
             qctx->result == DNS_R_DROP))
        {
                if (qctx->result == DNS_R_DUPLICATE ||