]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3023. [bug] Named could be left in an inconsistent state when
authorMark Andrews <marka@isc.org>
Fri, 22 Jul 2011 06:24:01 +0000 (06:24 +0000)
committerMark Andrews <marka@isc.org>
Fri, 22 Jul 2011 06:24:01 +0000 (06:24 +0000)
                        receiving multiple AXFR response messages that were
                        not all TSIG-signed. [RT #23254]

CHANGES
lib/dns/xfrin.c

diff --git a/CHANGES b/CHANGES
index 15764f68b4352ae13d4e0939bbdcffd2a0c6a3ee..86d88abf874eaf15999989daf3ad815b415429b9 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,10 @@
                        See http://www.freebsd.org/cgi/query-pr.cgi?pr=158307
                        [RT #24950]
 
+3023.  [bug]           Named could be left in an inconsistent state when
+                       receiving multiple AXFR response messages that were
+                       not all TSIG-signed. [RT #23254]
+
        --- 9.4-ESV-R5rc1 released ---
 
 3124.  [bug]           Use an rdataset attribute flag to indicate
index 7171a37ef111b6356c86c76cc93cef0f8231cd0a..e2a0fb9451633e4d2c8b0cbdf4323be4e7a84aa6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008, 2011  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: xfrin.c,v 1.135.18.23 2008/09/25 04:15:52 marka Exp $ */
+/* $Id: xfrin.c,v 1.135.18.24 2011/07/22 06:24:01 marka Exp $ */
 
 /*! \file */
 
@@ -83,8 +83,9 @@ typedef enum {
        XFRST_IXFR_DEL,
        XFRST_IXFR_ADDSOA,
        XFRST_IXFR_ADD,
+       XFRST_IXFR_END,
        XFRST_AXFR,
-       XFRST_END
+       XFRST_AXFR_END
 } xfrin_state_t;
 
 /*%
@@ -198,6 +199,7 @@ static isc_result_t axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
                                   dns_rdata_t *rdata);
 static isc_result_t axfr_apply(dns_xfrin_ctx_t *xfr);
 static isc_result_t axfr_commit(dns_xfrin_ctx_t *xfr);
+static isc_result_t axfr_finalize(dns_xfrin_ctx_t *xfr);
 
 static isc_result_t ixfr_init(dns_xfrin_ctx_t *xfr);
 static isc_result_t ixfr_apply(dns_xfrin_ctx_t *xfr);
@@ -313,6 +315,16 @@ axfr_commit(dns_xfrin_ctx_t *xfr) {
 
        CHECK(axfr_apply(xfr));
        CHECK(dns_db_endload(xfr->db, &xfr->axfr.add_private));
+
+       result = ISC_R_SUCCESS;
+ failure:
+       return (result);
+}
+
+static isc_result_t
+axfr_finalize(dns_xfrin_ctx_t *xfr) {
+       isc_result_t result;
+
        CHECK(dns_zone_replacedb(xfr->zone, xfr->db, ISC_TRUE));
 
        result = ISC_R_SUCCESS;
@@ -534,7 +546,7 @@ xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl,
                        isc_uint32_t soa_serial = dns_soa_getserial(rdata);
                        if (soa_serial == xfr->end_serial) {
                                CHECK(ixfr_commit(xfr));
-                               xfr->state = XFRST_END;
+                               xfr->state = XFRST_IXFR_END;
                                break;
                        } else if (soa_serial != xfr->ixfr.current_serial) {
                                xfrin_log(xfr, ISC_LOG_ERROR,
@@ -565,11 +577,12 @@ xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl,
                CHECK(axfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
                if (rdata->type == dns_rdatatype_soa) {
                        CHECK(axfr_commit(xfr));
-                       xfr->state = XFRST_END;
+                       xfr->state = XFRST_AXFR_END;
                        break;
                }
                break;
-       case XFRST_END:
+       case XFRST_AXFR_END:
+       case XFRST_IXFR_END:
                FAIL(DNS_R_EXTRADATA);
        default:
                INSIST(0);
@@ -908,8 +921,7 @@ static void
 xfrin_connect_done(isc_task_t *task, isc_event_t *event) {
        isc_socket_connev_t *cev = (isc_socket_connev_t *) event;
        dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
-       isc_result_t evresult = cev->result;
-       isc_result_t result;
+       isc_result_t result = cev->result;
        char sourcetext[ISC_SOCKADDR_FORMATSIZE];
        isc_sockaddr_t sockaddr;
 
@@ -926,7 +938,9 @@ xfrin_connect_done(isc_task_t *task, isc_event_t *event) {
                return;
        }
 
-       CHECK(evresult);
+       if (result != ISC_R_SUCCESS)
+               goto failure;
+
        result = isc_socket_getsockname(xfr->socket, &sockaddr);
        if (result == ISC_R_SUCCESS) {
                isc_sockaddr_format(&sockaddr, sourcetext, sizeof(sourcetext));
@@ -1210,7 +1224,7 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
                        result = DNS_R_UNEXPECTEDID;
                if (xfr->reqtype == dns_rdatatype_axfr ||
                    xfr->reqtype == dns_rdatatype_soa)
-                       FAIL(result);
+                       goto failure;
                xfrin_log(xfr, ISC_LOG_DEBUG(3), "got %s, retrying with AXFR",
                       isc_result_totext(result));
  try_axfr:
@@ -1246,7 +1260,7 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
        if (result != ISC_R_SUCCESS) {
                xfrin_log(xfr, ISC_LOG_DEBUG(3), "TSIG check failed: %s",
                       isc_result_totext(result));
-               FAIL(result);
+               goto failure;
        }
 
        for (result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
@@ -1294,8 +1308,9 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
 
        } else if (dns_message_gettsigkey(msg) != NULL) {
                xfr->sincetsig++;
-               if (xfr->sincetsig > 100 ||
-                   xfr->nmsg == 0 || xfr->state == XFRST_END)
+               if (xfr->sincetsig > 100 || xfr->nmsg == 0 ||
+                   xfr->state == XFRST_AXFR_END ||
+                   xfr->state == XFRST_IXFR_END)
                {
                        result = DNS_R_EXPECTEDTSIG;
                        goto failure;
@@ -1316,16 +1331,22 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
 
        dns_message_destroy(&msg);
 
-       if (xfr->state == XFRST_GOTSOA) {
+       switch (xfr->state) {
+       case XFRST_GOTSOA:
                xfr->reqtype = dns_rdatatype_axfr;
                xfr->state = XFRST_INITIALSOA;
                CHECK(xfrin_send_request(xfr));
-       } else if (xfr->state == XFRST_END) {
+               break;
+       case XFRST_AXFR_END:
+               CHECK(axfr_finalize(xfr));
+               /* FALLTHROUGH */
+       case XFRST_IXFR_END:
                /*
                 * Close the journal.
                 */
                if (xfr->ixfr.journal != NULL)
                        dns_journal_destroy(&xfr->ixfr.journal);
+
                /*
                 * Inform the caller we succeeded.
                 */
@@ -1339,7 +1360,8 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
                 */
                xfr->shuttingdown = ISC_TRUE;
                maybe_free(xfr);
-       } else {
+               break;
+       default:
                /*
                 * Read the next message.
                 */