]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
4558. [bug] Synthesised CNAME before matching DNAME was still
authorMark Andrews <marka@isc.org>
Tue, 24 Jan 2017 06:40:12 +0000 (17:40 +1100)
committerMark Andrews <marka@isc.org>
Tue, 24 Jan 2017 06:40:12 +0000 (17:40 +1100)
                        being cached when it should have been.  [RT #44318]

CHANGES
lib/dns/resolver.c

diff --git a/CHANGES b/CHANGES
index ba10babb2bade1eca753a919fde3ae0494a932eb..189e7e481f07b6761a7729b15a34e1f79a293111 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+4558.  [bug]           Synthesised CNAME before matching DNAME was still
+                       being cached when it should have been.  [RT #44318]
+
 4557.  [security]      Combining dns64 and rpz can result in dereferencing
                        a NULL pointer (read).  (CVE-2017-3135) [RT#44434]
 
index 397048e06884ea429b70589d070d2c1d6e928b8a..d02a5e761a68536842d6ef125143618e764f92b7 100644 (file)
@@ -6834,10 +6834,10 @@ answer_response(fetchctx_t *fctx) {
        dns_name_t *name, *dname = NULL, *qname, tname, *ns_name;
        dns_name_t *cname = NULL;
        dns_rdataset_t *rdataset, *ns_rdataset;
-       isc_boolean_t done, external, chaining, aa, found, want_chaining;
+       isc_boolean_t done, external, aa, found, want_chaining;
        isc_boolean_t have_answer, found_cname, found_dname, found_type;
        isc_boolean_t wanted_chaining;
-       unsigned int aflag;
+       unsigned int aflag, chaining;
        dns_rdatatype_t type;
        dns_fixedname_t fdname, fqname;
        dns_view_t *view;
@@ -6855,9 +6855,9 @@ answer_response(fetchctx_t *fctx) {
        found_cname = ISC_FALSE;
        found_dname = ISC_FALSE;
        found_type = ISC_FALSE;
-       chaining = ISC_FALSE;
        have_answer = ISC_FALSE;
        want_chaining = ISC_FALSE;
+       chaining = 0;
        POST(want_chaining);
        if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
                aa = ISC_TRUE;
@@ -7004,7 +7004,7 @@ answer_response(fetchctx_t *fctx) {
                                        rdataset->attributes |=
                                                DNS_RDATASETATTR_CACHE;
                                        rdataset->trust = dns_trust_answer;
-                                       if (!chaining) {
+                                       if (chaining == 0) {
                                                /*
                                                 * This data is "the" answer
                                                 * to our question only if
@@ -7081,8 +7081,8 @@ answer_response(fetchctx_t *fctx) {
                         * cause us to ignore the signatures of
                         * CNAMEs.
                         */
-                       if (wanted_chaining)
-                               chaining = ISC_TRUE;
+                       if (wanted_chaining && chaining < 2U)
+                               chaining++;
                } else {
                        dns_rdataset_t *dnameset = NULL;
 
@@ -7113,7 +7113,7 @@ answer_response(fetchctx_t *fctx) {
                                 * If we're not chaining, then the DNAME and
                                 * its signature should not be external.
                                 */
-                               if (!chaining && external) {
+                               if (chaining == 0 && external) {
                                        char qbuf[DNS_NAME_FORMATSIZE];
                                        char obuf[DNS_NAME_FORMATSIZE];
 
@@ -7197,7 +7197,14 @@ answer_response(fetchctx_t *fctx) {
                                name->attributes |= DNS_NAMEATTR_CACHE;
                                rdataset->attributes |= DNS_RDATASETATTR_CACHE;
                                rdataset->trust = dns_trust_answer;
-                               if (!chaining) {
+                               /*
+                                * If we are not chaining or the first CNAME
+                                * is a synthesised CNAME before the DNAME.
+                                */
+                               if ((chaining == 0) ||
+                                   (chaining == 1U &&
+                                    namereln == dns_namereln_commonancestor))
+                               {
                                        /*
                                         * This data is "the" answer to
                                         * our question only if we're
@@ -7245,8 +7252,12 @@ answer_response(fetchctx_t *fctx) {
                                dnameset->attributes |=
                                            DNS_RDATASETATTR_CHAINING;
                        }
-                       if (wanted_chaining)
-                               chaining = ISC_TRUE;
+                       /*
+                        * Ensure that we can't ever get chaining == 1
+                        * above if we have processed a DNAME.
+                        */
+                       if (wanted_chaining && chaining < 2U)
+                               chaining += 2;
                }
                result = dns_message_nextname(message, DNS_SECTION_ANSWER);
        }
@@ -7271,7 +7282,7 @@ answer_response(fetchctx_t *fctx) {
        /*
         * Did chaining end before we got the final answer?
         */
-       if (chaining) {
+       if (chaining != 0) {
                /*
                 * Yes.  This may be a negative reply, so hand off
                 * authority section processing to the noanswer code.
@@ -7320,7 +7331,7 @@ answer_response(fetchctx_t *fctx) {
                                                DNS_NAMEATTR_CACHE;
                                        rdataset->attributes |=
                                                DNS_RDATASETATTR_CACHE;
-                                       if (aa && !chaining)
+                                       if (aa && chaining == 0)
                                                rdataset->trust =
                                                    dns_trust_authauthority;
                                        else