From: Mark Andrews Date: Fri, 22 Jul 2011 06:24:01 +0000 (+0000) Subject: 3023. [bug] Named could be left in an inconsistent state when X-Git-Tag: v9.4-ESV-R5~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e25e67f69737c6e9f2ef15489937509d3654faea;p=thirdparty%2Fbind9.git 3023. [bug] Named could be left in an inconsistent state when receiving multiple AXFR response messages that were not all TSIG-signed. [RT #23254] --- diff --git a/CHANGES b/CHANGES index 15764f68b43..86d88abf874 100644 --- 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 diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index 7171a37ef11..e2a0fb94516 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -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. */