Control: tags 868952 + patch
Control: tags 868952 + pending

Dear maintainer,

I've prepared an NMU for bind9 (versioned as 1:9.10.3.dfsg.P4-12.5) and
uploaded it to DELAYED/2. Please feel free to tell me if I
should delay it longer.

Regards,
Salvatore
diff -Nru bind9-9.10.3.dfsg.P4/debian/changelog bind9-9.10.3.dfsg.P4/debian/changelog
--- bind9-9.10.3.dfsg.P4/debian/changelog	2017-07-16 22:13:21.000000000 +0200
+++ bind9-9.10.3.dfsg.P4/debian/changelog	2017-07-21 22:28:32.000000000 +0200
@@ -1,3 +1,13 @@
+bind9 (1:9.10.3.dfsg.P4-12.5) unstable; urgency=medium
+
+  * Non-maintainer upload.
+  * Change to fix CVE-2017-3142 and CVE-2017-3143 broke verification of TSIG
+    signed TCP message sequences where not all the messages contain TSIG
+    records. These may be used in AXFR and IXFR responses.
+    (Closes: #868952)
+
+ -- Salvatore Bonaccorso <car...@debian.org>  Fri, 21 Jul 2017 22:28:32 +0200
+
 bind9 (1:9.10.3.dfsg.P4-12.4) unstable; urgency=high
 
   * Non-maintainer upload.
diff -Nru bind9-9.10.3.dfsg.P4/debian/patches/4647.-bug-Change-4643-broke-verification-of-TSIG-sig.patch bind9-9.10.3.dfsg.P4/debian/patches/4647.-bug-Change-4643-broke-verification-of-TSIG-sig.patch
--- bind9-9.10.3.dfsg.P4/debian/patches/4647.-bug-Change-4643-broke-verification-of-TSIG-sig.patch	1970-01-01 01:00:00.000000000 +0100
+++ bind9-9.10.3.dfsg.P4/debian/patches/4647.-bug-Change-4643-broke-verification-of-TSIG-sig.patch	2017-07-21 22:28:32.000000000 +0200
@@ -0,0 +1,565 @@
+From e66fca127cd907e73ca7accd49e42d7a24503242 Mon Sep 17 00:00:00 2001
+From: Mark Andrews <ma...@isc.org>
+Date: Fri, 7 Jul 2017 23:19:05 +1000
+Subject: [PATCH] 4647.   [bug]           Change 4643 broke verification of
+ TSIG signed TCP                         message sequences where not all the
+ messages contain                         TSIG records.  These may be used in
+ AXFR and IXFR                         responses.  [RT #45509]
+
+---
+ lib/dns/tests/Makefile.in |   7 +
+ lib/dns/tests/tsig_test.c | 489 ++++++++++++++++++++++++++++++++++++++++++++++
+ lib/dns/tsig.c            |  10 +-
+ 4 files changed, 509 insertions(+), 2 deletions(-)
+ create mode 100644 lib/dns/tests/tsig_test.c
+
+
+--- a/lib/dns/tests/Makefile.in
++++ b/lib/dns/tests/Makefile.in
+@@ -57,6 +57,7 @@ SRCS =		db_test.c \
+ 		rdataset_test.c \
+ 		rdatasetstats_test.c \
+ 		time_test.c \
++		tsig_test.c \
+ 		update_test.c \
+ 		zonemgr_test.c \
+ 		zt_test.c 
+@@ -81,6 +82,7 @@ TARGETS =	db_test@EXEEXT@ \
+ 		rdataset_test@EXEEXT@ \
+ 		rdatasetstats_test@EXEEXT@ \
+ 		time_test@EXEEXT@ \
++		tsig_test@EXEEXT@ \
+ 		update_test@EXEEXT@ \
+ 		zonemgr_test@EXEEXT@ \
+ 		zt_test@EXEEXT@
+@@ -206,6 +208,11 @@ dh_test@EXEEXT@: dh_test.@O@ dnstest.@O@
+ 			dh_test.@O@ dnstest.@O@ ${DNSLIBS} \
+ 			${ISCLIBS} ${LIBS}
+ 
++tsig_test@EXEEXT@: tsig_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
++	${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
++			tsig_test.@O@ dnstest.@O@ ${DNSLIBS} \
++			${ISCLIBS} ${LIBS}
++
+ unit::
+ 	sh ${top_srcdir}/unit/unittest.sh
+ 
+--- /dev/null
++++ b/lib/dns/tests/tsig_test.c
+@@ -0,0 +1,489 @@
++/*
++ * Copyright (C) 2017  Internet Systems Consortium, Inc. ("ISC")
++ *
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
++ */
++
++/* ! \file */
++
++#include <config.h>
++#include <atf-c.h>
++#include <isc/mem.h>
++
++#include <dns/rdatalist.h>
++#include <dns/rdataset.h>
++#include <dns/tsig.h>
++
++#include "dnstest.h"
++
++#ifdef HAVE_INTTYPES_H
++#include <inttypes.h> /* uintptr_t */
++#endif
++
++static int debug = 0;
++
++static isc_result_t
++add_mac(dst_context_t *tsigctx, isc_buffer_t *buf) {
++	dns_rdata_any_tsig_t tsig;
++	dns_rdata_t rdata = DNS_RDATA_INIT;
++	isc_buffer_t databuf;
++	isc_region_t r;
++	isc_result_t result;
++	unsigned char tsigbuf[1024];
++
++	isc_buffer_usedregion(buf, &r);
++	dns_rdata_fromregion(&rdata, dns_rdataclass_any,
++			     dns_rdatatype_tsig, &r);
++	isc_buffer_init(&databuf, tsigbuf, sizeof(tsigbuf));
++	CHECK(dns_rdata_tostruct(&rdata, &tsig, NULL));
++	isc_buffer_putuint16(&databuf, tsig.siglen);
++	isc_buffer_putmem(&databuf, tsig.signature, tsig.siglen);
++	isc_buffer_usedregion(&databuf, &r);
++	result = dst_context_adddata(tsigctx, &r);
++	dns_rdata_freestruct(&tsig);
++ cleanup:
++	return (result);
++}
++
++static isc_result_t
++add_tsig(dst_context_t *tsigctx, dns_tsigkey_t *key, isc_buffer_t *target) {
++	dns_compress_t cctx;
++	dns_rdata_any_tsig_t tsig;
++	dns_rdata_t rdata = DNS_RDATA_INIT;
++	dns_rdatalist_t rdatalist;
++	dns_rdataset_t rdataset;
++	isc_buffer_t *dynbuf = NULL;
++	isc_buffer_t databuf;
++	isc_buffer_t sigbuf;
++	isc_region_t r;
++	isc_result_t result = ISC_R_SUCCESS;
++	isc_stdtime_t now;
++	unsigned char tsigbuf[1024];
++	unsigned int count;
++	unsigned int sigsize;
++	isc_boolean_t invalidate_ctx = ISC_FALSE;
++
++	CHECK(dns_compress_init(&cctx, -1, mctx));
++	invalidate_ctx = ISC_TRUE;
++
++	memset(&tsig, 0, sizeof(tsig));
++	       tsig.common.rdclass = dns_rdataclass_any;
++	tsig.common.rdtype = dns_rdatatype_tsig;
++	ISC_LINK_INIT(&tsig.common, link);
++	dns_name_init(&tsig.algorithm, NULL);
++	dns_name_clone(key->algorithm, &tsig.algorithm);
++
++	isc_stdtime_get(&now);
++	tsig.timesigned = now;
++	tsig.fudge = DNS_TSIG_FUDGE;
++	tsig.originalid = 50;
++	tsig.error = dns_rcode_noerror;
++	tsig.otherlen = 0;
++	tsig.other = NULL;
++
++	isc_buffer_init(&databuf, tsigbuf, sizeof(tsigbuf));
++	isc_buffer_putuint48(&databuf, tsig.timesigned);
++	isc_buffer_putuint16(&databuf, tsig.fudge);
++	isc_buffer_usedregion(&databuf, &r);
++	CHECK(dst_context_adddata(tsigctx, &r));
++
++	CHECK(dst_key_sigsize(key->key, &sigsize));
++	tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize);
++	if (tsig.signature == NULL)
++		CHECK(ISC_R_NOMEMORY);
++	isc_buffer_init(&sigbuf, tsig.signature, sigsize);
++	CHECK(dst_context_sign(tsigctx, &sigbuf));
++	tsig.siglen = isc_buffer_usedlength(&sigbuf);
++
++	CHECK(isc_buffer_allocate(mctx, &dynbuf, 512));
++	CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_any,
++				   dns_rdatatype_tsig, &tsig, dynbuf));
++	dns_rdatalist_init(&rdatalist);
++	rdatalist.rdclass = dns_rdataclass_any;
++	rdatalist.type = dns_rdatatype_tsig;
++	ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
++	dns_rdataset_init(&rdataset);
++	CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset));
++	CHECK(dns_rdataset_towire(&rdataset, &key->name, &cctx,
++				  target, 0, &count));
++
++	/*
++	 * Fixup additional record count.
++	 */
++	((unsigned char*)target->base)[11]++;
++	if (((unsigned char*)target->base)[11] == 0)
++		((unsigned char*)target->base)[10]++;
++ cleanup:
++	if (tsig.signature != NULL)
++		isc_mem_put(mctx, tsig.signature, sigsize);
++	if (dynbuf != NULL)
++		isc_buffer_free(&dynbuf);
++	if (invalidate_ctx)
++		dns_compress_invalidate(&cctx);
++
++	return (result);
++}
++
++static void
++printmessage(dns_message_t *msg) {
++	isc_buffer_t b;
++	char *buf = NULL;
++	int len = 1024;
++	isc_result_t result = ISC_R_SUCCESS;
++
++	if (!debug)
++		return;
++
++	do {
++		buf = isc_mem_get(mctx, len);
++		if (buf == NULL) {
++			result = ISC_R_NOMEMORY;
++			break;
++		}
++
++		isc_buffer_init(&b, buf, len);
++		result = dns_message_totext(msg, &dns_master_style_debug,
++					    0, &b);
++		if (result == ISC_R_NOSPACE) {
++			isc_mem_put(mctx, buf, len);
++			len *= 2;
++		} else if (result == ISC_R_SUCCESS)
++			printf("%.*s\n", (int) isc_buffer_usedlength(&b), buf);
++	} while (result == ISC_R_NOSPACE);
++
++	if (buf != NULL)
++		isc_mem_put(mctx, buf, len);
++}
++
++static void
++render(isc_buffer_t *buf, unsigned flags, dns_tsigkey_t *key,
++       isc_buffer_t **tsigin, isc_buffer_t **tsigout,
++       dst_context_t *tsigctx)
++{
++	dns_message_t *msg = NULL;
++	dns_compress_t cctx;
++	isc_result_t result;
++
++	result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &msg);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_create: %s",
++			 dns_result_totext(result));
++
++	msg->id = 50;
++	msg->rcode = dns_rcode_noerror;
++	msg->flags = flags;
++
++	if (tsigin == tsigout)
++		msg->tcp_continuation = 1;
++
++	if (tsigctx == NULL) {
++		result = dns_message_settsigkey(msg, key);
++		ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++				 "dns_message_settsigkey: %s",
++				 dns_result_totext(result));
++
++		result = dns_message_setquerytsig(msg, *tsigin);
++		ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++				 "dns_message_setquerytsig: %s",
++				 dns_result_totext(result));
++	}
++
++	result = dns_compress_init(&cctx, -1, mctx);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_compress_init: %s",
++			 dns_result_totext(result));
++
++	result = dns_message_renderbegin(msg, &cctx, buf);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_renderbegin: %s",
++			 dns_result_totext(result));
++
++	result = dns_message_renderend(msg);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_renderend: %s",
++			 dns_result_totext(result));
++
++	if (tsigctx != NULL) {
++		isc_region_t r;
++
++		isc_buffer_usedregion(buf, &r);
++		result = dst_context_adddata(tsigctx, &r);
++	} else {
++		if (tsigin == tsigout && *tsigin != NULL)
++			isc_buffer_free(tsigin);
++
++		result = dns_message_getquerytsig(msg, mctx, tsigout);
++		ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++				 "dns_message_getquerytsig: %s",
++				 dns_result_totext(result));
++	}
++
++	dns_compress_invalidate(&cctx);
++	dns_message_destroy(&msg);
++}
++
++/*
++ * Check that a simulated three message TCP sequence where the first
++ * and last messages contain TSIGs but the intermediate message doesn't
++ * correctly verifies.
++ */
++ATF_TC(tsig_tcp);
++ATF_TC_HEAD(tsig_tcp, tc) {
++	atf_tc_set_md_var(tc, "descr", "test tsig tcp-continuation validation");
++}
++ATF_TC_BODY(tsig_tcp, tc) {
++	dns_name_t *tsigowner = NULL;
++	dns_fixedname_t fkeyname;
++	dns_message_t *msg = NULL;
++	dns_name_t *keyname;
++	dns_tsig_keyring_t *ring = NULL;
++	dns_tsigkey_t *key = NULL;
++	isc_buffer_t *buf = NULL;
++	isc_buffer_t *querytsig = NULL;
++	isc_buffer_t *tsigin = NULL;
++	isc_buffer_t *tsigout = NULL;
++	isc_result_t result;
++	unsigned char secret[16] = { 0 };
++	dst_context_t *tsigctx = NULL;
++	dst_context_t *outctx = NULL;
++
++	UNUSED(tc);
++
++	result = dns_test_begin(stderr, ISC_FALSE);
++	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
++
++	/* isc_log_setdebuglevel(lctx, 99); */
++
++	dns_fixedname_init(&fkeyname);
++	keyname = dns_fixedname_name(&fkeyname);
++	result = dns_name_fromstring(keyname, "test", 0, NULL);
++	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
++
++	result = dns_tsigkeyring_create(mctx, &ring);
++	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
++
++	result = dns_tsigkey_create(keyname, dns_tsig_hmacsha256_name,
++				    secret, sizeof(secret), ISC_FALSE,
++				    NULL, 0, 0, mctx, ring, &key);
++	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
++
++	/*
++	 * Create request.
++	 */
++	result = isc_buffer_allocate(mctx, &buf, 65535);
++	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
++	render(buf, 0, key, &tsigout, &querytsig, NULL);
++	isc_buffer_free(&buf);
++
++	/*
++	 * Create response message 1.
++	 */
++	result = isc_buffer_allocate(mctx, &buf, 65535);
++	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
++	render(buf, DNS_MESSAGEFLAG_QR, key, &querytsig, &tsigout, NULL);
++
++	/*
++	 * Process response message 1.
++	 */
++	result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_create: %s",
++			 dns_result_totext(result));
++
++	result = dns_message_settsigkey(msg, key);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_settsigkey: %s",
++			 dns_result_totext(result));
++
++	result = dns_message_parse(msg, buf, 0);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_parse: %s",
++			 dns_result_totext(result));
++
++	printmessage(msg);
++
++	result = dns_message_setquerytsig(msg, querytsig);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_setquerytsig: %s",
++			 dns_result_totext(result));
++
++	result = dns_tsig_verify(buf, msg, NULL, NULL);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_tsig_verify: %s",
++			 dns_result_totext(result));
++	ATF_CHECK_EQ(msg->verified_sig, 1);
++	ATF_CHECK_EQ(msg->tsigstatus, dns_rcode_noerror);
++
++	/*
++	 * Check that we have a TSIG in the first message.
++	 */
++	ATF_REQUIRE(dns_message_gettsig(msg, &tsigowner) != NULL);
++
++	result = dns_message_getquerytsig(msg, mctx, &tsigin);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_getquerytsig: %s",
++			 dns_result_totext(result));
++
++	tsigctx = msg->tsigctx;
++	msg->tsigctx = NULL;
++	isc_buffer_free(&buf);
++	dns_message_destroy(&msg);
++
++	result = dst_context_create3(key->key, mctx, DNS_LOGCATEGORY_DNSSEC,
++				     ISC_FALSE, &outctx);
++	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
++
++	/*
++	 * Start digesting.
++	 */
++	result = add_mac(outctx, tsigout);
++	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
++
++	/*
++	 * Create response message 2.
++	 */
++	result = isc_buffer_allocate(mctx, &buf, 65535);
++	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
++
++	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
++	render(buf, DNS_MESSAGEFLAG_QR, key, &tsigout, &tsigout, outctx);
++
++	/*
++	 * Process response message 2.
++	 */
++	result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_create: %s",
++			 dns_result_totext(result));
++
++	msg->tcp_continuation = 1;
++	msg->tsigctx = tsigctx;
++	tsigctx = NULL;
++
++	result = dns_message_settsigkey(msg, key);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_settsigkey: %s",
++			 dns_result_totext(result));
++
++	result = dns_message_parse(msg, buf, 0);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_parse: %s",
++			 dns_result_totext(result));
++
++	printmessage(msg);
++
++	result = dns_message_setquerytsig(msg, tsigin);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_setquerytsig: %s",
++			 dns_result_totext(result));
++
++	result = dns_tsig_verify(buf, msg, NULL, NULL);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_tsig_verify: %s",
++			 dns_result_totext(result));
++	ATF_CHECK_EQ(msg->verified_sig, 1);
++	ATF_CHECK_EQ(msg->tsigstatus, dns_rcode_noerror);
++
++	/*
++	 * Check that we don't have a TSIG in the second message.
++	 */
++	tsigowner = NULL;
++	ATF_REQUIRE(dns_message_gettsig(msg, &tsigowner) == NULL);
++
++	tsigctx = msg->tsigctx;
++	msg->tsigctx = NULL;
++	isc_buffer_free(&buf);
++	dns_message_destroy(&msg);
++
++	/*
++	 * Create response message 3.
++	 */
++	result = isc_buffer_allocate(mctx, &buf, 65535);
++	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
++	render(buf, DNS_MESSAGEFLAG_QR, key, &tsigout, &tsigout, outctx);
++
++	result = add_tsig(outctx, key, buf);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "add_tsig: %s",
++			 dns_result_totext(result));
++
++	/*
++	 * Process response message 3.
++	 */
++	result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_create: %s",
++			 dns_result_totext(result));
++
++	msg->tcp_continuation = 1;
++	msg->tsigctx = tsigctx;
++	tsigctx = NULL;
++
++	result = dns_message_settsigkey(msg, key);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_settsigkey: %s",
++			 dns_result_totext(result));
++
++	result = dns_message_parse(msg, buf, 0);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_parse: %s",
++			 dns_result_totext(result));
++
++	printmessage(msg);
++
++	/*
++	 * Check that we had a TSIG in the third message.
++	 */
++	ATF_REQUIRE(dns_message_gettsig(msg, &tsigowner) != NULL);
++
++	result = dns_message_setquerytsig(msg, tsigin);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_setquerytsig: %s",
++			 dns_result_totext(result));
++
++	result = dns_tsig_verify(buf, msg, NULL, NULL);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_tsig_verify: %s",
++			 dns_result_totext(result));
++	ATF_CHECK_EQ(msg->verified_sig, 1);
++	ATF_CHECK_EQ(msg->tsigstatus, dns_rcode_noerror);
++
++	if (tsigin != NULL)
++		isc_buffer_free(&tsigin);
++
++	result = dns_message_getquerytsig(msg, mctx, &tsigin);
++	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
++			 "dns_message_getquerytsig: %s",
++			 dns_result_totext(result));
++
++	isc_buffer_free(&buf);
++	dns_message_destroy(&msg);
++
++	if (outctx != NULL)
++		dst_context_destroy(&outctx);
++	if (querytsig != NULL)
++		isc_buffer_free(&querytsig);
++	if (tsigin != NULL)
++		isc_buffer_free(&tsigin);
++	if (tsigout != NULL)
++		isc_buffer_free(&tsigout);
++	if (buf != NULL)
++		isc_buffer_free(&buf);
++	if (msg != NULL)
++		dns_message_destroy(&msg);
++	if (key != NULL)
++		dns_tsigkey_detach(&key);
++	if (ring != NULL)
++		dns_tsigkeyring_detach(&ring);
++	dns_test_end();
++}
++
++/*
++ * Main
++ */
++ATF_TP_ADD_TCS(tp) {
++	ATF_TP_ADD_TC(tp, tsig_tcp);
++	return (atf_no_error());
++}
+--- a/lib/dns/tsig.c
++++ b/lib/dns/tsig.c
+@@ -1535,7 +1535,7 @@ dns_tsig_verify(isc_buffer_t *source, dn
+ 	msg->verified_sig = 1;
+ 	ret = ISC_R_SUCCESS;
+ 
+-cleanup_context:
++ cleanup_context:
+ 	if (ctx != NULL)
+ 		dst_context_destroy(&ctx);
+ 
+@@ -1862,8 +1862,14 @@ tsig_verify_tcp(isc_buffer_t *source, dn
+ 	ret = ISC_R_SUCCESS;
+ 
+  cleanup_context:
+-	if (msg->tsigctx != NULL)
++	/*
++	 * Except in error conditions, don't destroy the DST context
++	 * for unsigned messages; it is a running sum till the next
++	 * TSIG signed message.
++	 */
++	if ((ret != ISC_R_SUCCESS || has_tsig) && msg->tsigctx != NULL) {
+ 		dst_context_destroy(&msg->tsigctx);
++	}
+ 
+  cleanup_querystruct:
+ 	dns_rdata_freestruct(&querytsig);
diff -Nru bind9-9.10.3.dfsg.P4/debian/patches/series bind9-9.10.3.dfsg.P4/debian/patches/series
--- bind9-9.10.3.dfsg.P4/debian/patches/series	2017-06-30 16:20:29.000000000 +0200
+++ bind9-9.10.3.dfsg.P4/debian/patches/series	2017-07-21 22:28:32.000000000 +0200
@@ -31,3 +31,4 @@
 
 CVE-2017-3138.patch
 CVE-2017-3142+CVE-2017-3143.patch
+4647.-bug-Change-4643-broke-verification-of-TSIG-sig.patch

Reply via email to