]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
4531. [security] 'is_zone' was not being properly updated by redirect2
authorMark Andrews <marka@isc.org>
Fri, 9 Dec 2016 04:40:37 +0000 (15:40 +1100)
committerMark Andrews <marka@isc.org>
Fri, 9 Dec 2016 04:42:26 +0000 (15:42 +1100)
                        and subsequently preserved leading to an assertion
                        failure. (CVE-2016-9778) [RT #43837]

(cherry picked from commit b1cb2f851a1e946680686868593e660650403393)

CHANGES
bin/named/include/named/query.h
bin/named/query.c

diff --git a/CHANGES b/CHANGES
index 7e6e1615ed8fb7fd0c8076620206cebba4f55eb6..25643113c4cac011eb1a8b6887cc0af942f6d5db 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,9 @@
        --- 9.11.0-P2 released ---
 
+4531.  [security]      'is_zone' was not being properly updated by redirect2
+                       and subsequently preserved leading to an assertion
+                       failure. (CVE-2016-9778) [RT #43837]
+
 4530.  [bug]           Change 4489 broke the handling of CNAME -> DNAME
                        in responses resulting in SERVFAIL being returned.
                        [RT #43779]
index 9640b19fd718709a9561949b6589168d7b2f6a0e..8f20c9af02745420d8a20f975083e06c7f220202 100644 (file)
@@ -69,6 +69,7 @@ struct ns_query {
                dns_rdataset_t *        rdataset;
                dns_rdataset_t *        sigrdataset;
                isc_boolean_t           authoritative;
+               isc_boolean_t           is_zone;
        } redirect;
 
 };
index e4753941adcc2479d832e15ac88f76d5ffc1fa98..fe6c733e60ba6ee503ace1fe7ee67e13f41ea91c 100644 (file)
@@ -701,6 +701,8 @@ ns_query_init(ns_client_t *client) {
        client->query.redirect.result = ISC_R_SUCCESS;
        client->query.redirect.rdataset = NULL;
        client->query.redirect.sigrdataset = NULL;
+       client->query.redirect.authoritative = ISC_FALSE;
+       client->query.redirect.is_zone  = ISC_FALSE;
        dns_fixedname_init(&client->query.redirect.fixed);
        client->query.redirect.fname =
                dns_fixedname_name(&client->query.redirect.fixed);
@@ -1176,7 +1178,6 @@ query_getcachedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
        return (result);
 }
 
-
 static inline isc_result_t
 query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
            unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
@@ -6306,7 +6307,7 @@ redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
 static isc_result_t
 redirect2(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
          dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp,
-         dns_rdatatype_t qtype)
+         dns_rdatatype_t qtype, isc_boolean_t *is_zonep)
 {
        dns_db_t *db = NULL;
        dns_dbnode_t *node = NULL;
@@ -6320,8 +6321,8 @@ redirect2(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
        dns_clientinfo_t ci;
        dns_dbversion_t *version = NULL;
        dns_zone_t *zone = NULL;
+       isc_boolean_t is_zone;
        unsigned int options;
-       isc_boolean_t is_zonep = ISC_FALSE;
 
        CTRACE(ISC_LOG_DEBUG(3), "redirect2");
 
@@ -6381,7 +6382,7 @@ redirect2(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
 
        options = 0;
        result = query_getdb(client, redirectname, qtype, options, &zone,
-                            &db, &version, &is_zonep);
+                            &db, &version, &is_zone);
        if (result != ISC_R_SUCCESS)
                return (ISC_R_NOTFOUND);
        if (zone != NULL)
@@ -6459,6 +6460,7 @@ redirect2(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
        dns_db_attach(db, dbp);
        dns_db_detachnode(db, &node);
        dns_db_detach(&db);
+       *is_zonep = is_zone;
        *versionp = version;
 
        client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
@@ -6651,6 +6653,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                        RESTORE(node, client->query.redirect.node);
                        RESTORE(zone, client->query.redirect.zone);
                        authoritative = client->query.redirect.authoritative;
+                       is_zone = client->query.redirect.is_zone;
 
                        /*
                         * Free resources used while recursing.
@@ -6746,7 +6749,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                        isc_event_free(ISC_EVENT_PTR(&event));
                } else if (REDIRECT(client)) {
                        result = client->query.redirect.result;
-                       is_zone = ISC_TF(result == DNS_R_NXDOMAIN);
+                       is_zone = client->query.redirect.is_zone;
                } else {
                        result = event->result;
                }
@@ -7785,7 +7788,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                /* FALLTHROUGH */
 
        case DNS_R_NXDOMAIN:
-               INSIST(is_zone);
+               INSIST(is_zone || REDIRECT(client));
                if (!empty_wild) {
                        tresult = redirect(client, fname, rdataset, &node,
                                           &db, &version, type);
@@ -7804,7 +7807,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                                goto ncache_nxrrset;
                        }
                        tresult = redirect2(client, fname, rdataset, &node,
-                                           &db, &version, type);
+                                           &db, &version, type, &is_zone);
                        if (tresult == DNS_R_CONTINUE) {
                                inc_stats(client,
                                          dns_nsstatscounter_nxdomainredirect_rlookup);
@@ -7822,6 +7825,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                                              NULL);
                                client->query.redirect.authoritative =
                                        authoritative;
+                               client->query.redirect.is_zone = is_zone;
                                goto cleanup;
                        }
                        if (tresult == ISC_R_SUCCESS) {
@@ -7919,7 +7923,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                        goto ncache_nxrrset;
                }
                tresult = redirect2(client, fname, rdataset, &node,
-                                   &db, &version, type);
+                                   &db, &version, type, &is_zone);
                if (tresult == DNS_R_CONTINUE) {
                        inc_stats(client,
                                  dns_nsstatscounter_nxdomainredirect_rlookup);
@@ -7934,6 +7938,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                        dns_name_copy(fname, client->query.redirect.fname,
                                      NULL);
                        client->query.redirect.authoritative = authoritative;
+                       client->query.redirect.is_zone = is_zone;
                        goto cleanup;
                }
                if (tresult == ISC_R_SUCCESS) {