--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/bind/patches/006-RT9857.patch Sat Apr 02 01:55:18 2016 +0100
@@ -0,0 +1,516 @@
+This patch was derived from ISC source differences between
+bind-9.9.8-p3 and bind-9.9.8-p4
+
+diff -r e13d04281504 CHANGES
+--- a/CHANGES Thu Mar 03 13:53:44 2016 +0000
++++ b/CHANGES Fri Mar 04 12:27:21 2016 +0000
+@@ -1,3 +1,12 @@
++ --- 9.6-ESV-R11-P6 released ---
++
++4319. [security] Fix resolver assertion failure due to improper
++ DNAME handling when parsing fetch reply messages.
++ (CVE-2016-1286) [RT #41753]
++
++4318. [security] Malformed control messages can trigger assertions
++ in named and rndc. (CVE-2016-1285) [RT #41666]
++
+ --- 9.6-ESV-R11-P5 released ---
+
+ 4285. [security] Specific APL data could trigger a INSIST.
+diff -r e13d04281504 bin/named/control.c
+--- a/bin/named/control.c Thu Mar 03 13:53:44 2016 +0000
++++ b/bin/named/control.c Fri Mar 04 12:27:21 2016 +0000
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (C) 2004-2007, 2009, 2010, 2012 Internet Systems Consortium, Inc. ("ISC")
++ * Copyright (C) 2004-2007, 2009-2016 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001-2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+@@ -69,7 +69,7 @@
+ #endif
+
+ data = isccc_alist_lookup(message, "_data");
+- if (data == NULL) {
++ if (!isccc_alist_alistp(data)) {
+ /*
+ * No data section.
+ */
+diff -r e13d04281504 bin/named/controlconf.c
+--- a/bin/named/controlconf.c Thu Mar 03 13:53:44 2016 +0000
++++ b/bin/named/controlconf.c Fri Mar 04 12:27:21 2016 +0000
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (C) 2004-2008, 2011-2014 Internet Systems Consortium, Inc. ("ISC")
++ * Copyright (C) 2004-2008, 2011-2014, 2016 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001-2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+@@ -396,7 +396,7 @@
+ * Limit exposure to replay attacks.
+ */
+ _ctrl = isccc_alist_lookup(request, "_ctrl");
+- if (_ctrl == NULL) {
++ if (!isccc_alist_alistp(_ctrl)) {
+ log_invalid(&conn->ccmsg, ISC_R_FAILURE);
+ goto cleanup_request;
+ }
+diff -r e13d04281504 bin/rndc/rndc.c
+--- a/bin/rndc/rndc.c Thu Mar 03 13:53:44 2016 +0000
++++ b/bin/rndc/rndc.c Fri Mar 04 12:27:21 2016 +0000
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (C) 2004-2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC")
++ * Copyright (C) 2004-2016 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+@@ -220,8 +220,8 @@
+ DO("parse message", isccc_cc_fromwire(&source, &response, &secret));
+
+ data = isccc_alist_lookup(response, "_data");
+- if (data == NULL)
+- fatal("no data section in response");
++ if (!isccc_alist_alistp(data))
++ fatal("bad or missing data section in response");
+ result = isccc_cc_lookupstring(data, "err", &errormsg);
+ if (result == ISC_R_SUCCESS) {
+ failed = ISC_TRUE;
+@@ -283,8 +283,8 @@
+ DO("parse message", isccc_cc_fromwire(&source, &response, &secret));
+
+ _ctrl = isccc_alist_lookup(response, "_ctrl");
+- if (_ctrl == NULL)
+- fatal("_ctrl section missing");
++ if (!isccc_alist_alistp(_ctrl))
++ fatal("bad or missing ctrl section in response");
+ nonce = 0;
+ if (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS)
+ nonce = 0;
+diff -r e13d04281504 lib/dns/resolver.c
+--- a/lib/dns/resolver.c Thu Mar 03 13:53:44 2016 +0000
++++ b/lib/dns/resolver.c Fri Mar 04 12:27:21 2016 +0000
+@@ -5364,21 +5364,17 @@
+ }
+
+ static inline isc_result_t
+-dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, dns_name_t *oname,
+- dns_fixedname_t *fixeddname)
++dname_target(dns_rdataset_t *rdataset, dns_name_t *qname,
++ unsigned int nlabels, dns_fixedname_t *fixeddname)
+ {
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+- unsigned int nlabels;
+- int order;
+- dns_namereln_t namereln;
+ dns_rdata_dname_t dname;
+ dns_fixedname_t prefix;
+
+ /*
+ * Get the target name of the DNAME.
+ */
+-
+ result = dns_rdataset_first(rdataset);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+@@ -5387,14 +5383,6 @@
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+- /*
+- * Get the prefix of qname.
+- */
+- namereln = dns_name_fullcompare(qname, oname, &order, &nlabels);
+- if (namereln != dns_namereln_subdomain) {
+- dns_rdata_freestruct(&dname);
+- return (DNS_R_FORMERR);
+- }
+ dns_fixedname_init(&prefix);
+ dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL);
+ dns_fixedname_init(fixeddname);
+@@ -5789,13 +5777,13 @@
+ answer_response(fetchctx_t *fctx) {
+ isc_result_t result;
+ dns_message_t *message;
+- dns_name_t *name, *qname, tname, *ns_name;
++ dns_name_t *name, *dname = NULL, *qname, tname, *ns_name;
+ dns_rdataset_t *rdataset, *ns_rdataset;
+ isc_boolean_t done, external, chaining, aa, found, want_chaining;
+ isc_boolean_t have_answer, found_cname, found_type, wanted_chaining;
+ unsigned int aflag;
+ dns_rdatatype_t type;
+- dns_fixedname_t dname, fqname;
++ dns_fixedname_t fdname, fqname;
+
+ FCTXTRACE("answer_response");
+
+@@ -5821,10 +5809,15 @@
+ type = fctx->type;
+ result = dns_message_firstname(message, DNS_SECTION_ANSWER);
+ while (!done && result == ISC_R_SUCCESS) {
++ dns_namereln_t namereln;
++ int order;
++ unsigned int nlabels;
++
+ name = NULL;
+ dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
+ external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
+- if (dns_name_equal(name, qname)) {
++ namereln = dns_name_fullcompare(qname, name, &order, &nlabels);
++ if (namereln == dns_namereln_equal) {
+ wanted_chaining = ISC_FALSE;
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+@@ -5837,6 +5830,10 @@
+ * NSEC3 records are not allowed to
+ * appear in the answer section.
+ */
++ isc_log_write(dns_lctx,
++ DNS_LOGCATEGORY_RESOLVER,
++ DNS_LOGMODULE_RESOLVER,
++ ISC_LOG_NOTICE, "NSEC3 in answer");
+ return (DNS_R_FORMERR);
+ }
+ if (rdataset->type == type && !found_cname) {
+@@ -5878,8 +5875,18 @@
+ */
+ if (type == dns_rdatatype_rrsig ||
+ type == dns_rdatatype_key ||
+- type == dns_rdatatype_nsec)
++ type == dns_rdatatype_nsec) {
++ char buf[DNS_RDATATYPE_FORMATSIZE];
++ dns_rdatatype_format(fctx->type,
++ buf, sizeof(buf));
++ isc_log_write(dns_lctx,
++ DNS_LOGCATEGORY_RESOLVER,
++ DNS_LOGMODULE_RESOLVER,
++ ISC_LOG_NOTICE,
++ "CNAME response "
++ "for %s RR", buf);
+ return (DNS_R_FORMERR);
++ }
+ found = ISC_TRUE;
+ found_cname = ISC_TRUE;
+ want_chaining = ISC_TRUE;
+@@ -5921,10 +5928,11 @@
+ */
+ INSIST(!external);
+ if (aflag ==
+- DNS_RDATASETATTR_ANSWER)
++ DNS_RDATASETATTR_ANSWER) {
+ have_answer = ISC_TRUE;
+- name->attributes |=
+- DNS_NAMEATTR_ANSWER;
++ name->attributes |=
++ DNS_NAMEATTR_ANSWER;
++ }
+ rdataset->attributes |= aflag;
+ if (aa)
+ rdataset->trust =
+@@ -5979,6 +5987,8 @@
+ if (wanted_chaining)
+ chaining = ISC_TRUE;
+ } else {
++ dns_rdataset_t *dnameset = NULL;
++
+ /*
+ * Look for a DNAME (or its SIG). Anything else is
+ * ignored.
+@@ -5986,27 +5996,64 @@
+ wanted_chaining = ISC_FALSE;
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+- rdataset = ISC_LIST_NEXT(rdataset, link)) {
+- isc_boolean_t found_dname = ISC_FALSE;
+- found = ISC_FALSE;
++ rdataset = ISC_LIST_NEXT(rdataset, link))
++ {
++ /*
++ * Only pass DNAME or RRSIG(DNAME).
++ */
++ if (rdataset->type != dns_rdatatype_dname &&
++ (rdataset->type != dns_rdatatype_rrsig ||
++ rdataset->covers != dns_rdatatype_dname))
++ continue;
++
++ /*
++ * If we're not chaining, then the DNAME and
++ * its signature should not be external.
++ */
++ if (!chaining && external) {
++ char qbuf[DNS_NAME_FORMATSIZE];
++ char obuf[DNS_NAME_FORMATSIZE];
++
++ dns_name_format(name, qbuf,
++ sizeof(qbuf));
++ dns_name_format(&fctx->domain, obuf,
++ sizeof(obuf));
++ isc_log_write(dns_lctx,
++ DNS_LOGCATEGORY_RESOLVER,
++ DNS_LOGMODULE_RESOLVER,
++ ISC_LOG_NOTICE,
++ "external DNAME or "
++ "RRSIG covering DNAME "
++ "in answer: %s is "
++ "not in %s", qbuf, obuf);
++ return (DNS_R_FORMERR);
++ }
++
++ if (namereln != dns_namereln_subdomain) {
++ char qbuf[DNS_NAME_FORMATSIZE];
++ char obuf[DNS_NAME_FORMATSIZE];
++
++ dns_name_format(qname, qbuf,
++ sizeof(qbuf));
++ dns_name_format(name, obuf,
++ sizeof(obuf));
++ isc_log_write(dns_lctx,
++ DNS_LOGCATEGORY_RESOLVER,
++ DNS_LOGMODULE_RESOLVER,
++ ISC_LOG_NOTICE,
++ "unrelated DNAME "
++ "in answer: %s is "
++ "not in %s", qbuf, obuf);
++ return (DNS_R_FORMERR);
++ }
++
+ aflag = 0;
+ if (rdataset->type == dns_rdatatype_dname) {
+- /*
+- * We're looking for something else,
+- * but we found a DNAME.
+- *
+- * If we're not chaining, then the
+- * DNAME should not be external.
+- */
+- if (!chaining && external)
+- return (DNS_R_FORMERR);
+- found = ISC_TRUE;
+ want_chaining = ISC_TRUE;
+ POST(want_chaining);
+ aflag = DNS_RDATASETATTR_ANSWER;
+- result = dname_target(rdataset,
+- qname, name,
+- &dname);
++ result = dname_target(rdataset, qname,
++ nlabels, &fdname);
+ if (result == ISC_R_NOSPACE) {
+ /*
+ * We can't construct the
+@@ -6018,81 +6065,68 @@
+ } else if (result != ISC_R_SUCCESS)
+ return (result);
+ else
+- found_dname = ISC_TRUE;
+- } else if (rdataset->type == dns_rdatatype_rrsig
+- && rdataset->covers ==
+- dns_rdatatype_dname) {
++ dnameset = rdataset;
++
++ dname = dns_fixedname_name(&fdname);
++ } else {
+ /*
+ * We've found a signature that
+ * covers the DNAME.
+ */
+- found = ISC_TRUE;
+ aflag = DNS_RDATASETATTR_ANSWERSIG;
+ }
+
+- if (found) {
++ /*
++ * We've found an answer to our
++ * question.
++ */
++ name->attributes |= DNS_NAMEATTR_CACHE;
++ rdataset->attributes |= DNS_RDATASETATTR_CACHE;
++ rdataset->trust = dns_trust_answer;
++ if (!chaining) {
+ /*
+- * We've found an answer to our
+- * question.
++ * This data is "the" answer to
++ * our question only if we're
++ * not chaining.
+ */
+- name->attributes |=
+- DNS_NAMEATTR_CACHE;
+- rdataset->attributes |=
+- DNS_RDATASETATTR_CACHE;
+- rdataset->trust = dns_trust_answer;
+- if (!chaining) {
+- /*
+- * This data is "the" answer
+- * to our question only if
+- * we're not chaining.
+- */
+- INSIST(!external);
+- if (aflag ==
+- DNS_RDATASETATTR_ANSWER)
+- have_answer = ISC_TRUE;
++ INSIST(!external);
++ if (aflag == DNS_RDATASETATTR_ANSWER) {
++ have_answer = ISC_TRUE;
+ name->attributes |=
+ DNS_NAMEATTR_ANSWER;
+- rdataset->attributes |= aflag;
+- if (aa)
+- rdataset->trust =
+- dns_trust_authanswer;
+- } else if (external) {
+- rdataset->attributes |=
+- DNS_RDATASETATTR_EXTERNAL;
+ }
+-
+- /*
+- * DNAME chaining.
+- */
+- if (found_dname) {
+- /*
+- * Copy the dname into the
+- * qname fixed name.
+- *
+- * Although we check for
+- * failure of the copy
+- * operation, in practice it
+- * should never fail since
+- * we already know that the
+- * result fits in a fixedname.
+- */
+- dns_fixedname_init(&fqname);
+- result = dns_name_copy(
+- dns_fixedname_name(&dname),
+- dns_fixedname_name(&fqname),
+- NULL);
+- if (result != ISC_R_SUCCESS)
+- return (result);
+- wanted_chaining = ISC_TRUE;
+- name->attributes |=
+- DNS_NAMEATTR_CHAINING;
+- rdataset->attributes |=
+- DNS_RDATASETATTR_CHAINING;
+- qname = dns_fixedname_name(
+- &fqname);
+- }
++ rdataset->attributes |= aflag;
++ if (aa)
++ rdataset->trust =
++ dns_trust_authanswer;
++ } else if (external) {
++ rdataset->attributes |=
++ DNS_RDATASETATTR_EXTERNAL;
+ }
+ }
++
++ /*
++ * DNAME chaining.
++ */
++ if (dnameset != NULL) {
++ /*
++ * Copy the dname into the qname fixed name.
++ *
++ * Although we check for failure of the copy
++ * operation, in practice it should never fail
++ * since we already know that the result fits
++ * in a fixedname.
++ */
++ dns_fixedname_init(&fqname);
++ qname = dns_fixedname_name(&fqname);
++ result = dns_name_copy(dname, qname, NULL);
++ if (result != ISC_R_SUCCESS)
++ return (result);
++ wanted_chaining = ISC_TRUE;
++ name->attributes |= DNS_NAMEATTR_CHAINING;
++ dnameset->attributes |=
++ DNS_RDATASETATTR_CHAINING;
++ }
+ if (wanted_chaining)
+ chaining = ISC_TRUE;
+ }
+@@ -6106,8 +6140,14 @@
+ /*
+ * We should have found an answer.
+ */
+- if (!have_answer)
++ if (!have_answer) {
++ isc_log_write(dns_lctx,
++ DNS_LOGCATEGORY_RESOLVER,
++ DNS_LOGMODULE_RESOLVER,
++ ISC_LOG_NOTICE,
++ "reply has no answer");
+ return (DNS_R_FORMERR);
++ }
+
+ /*
+ * This response is now potentially cacheable.
+diff -r e13d04281504 lib/isccc/cc.c
+--- a/lib/isccc/cc.c Thu Mar 03 13:53:44 2016 +0000
++++ b/lib/isccc/cc.c Fri Mar 04 12:27:21 2016 +0000
+@@ -286,10 +286,10 @@
+ * Extract digest.
+ */
+ _auth = isccc_alist_lookup(alist, "_auth");
+- if (_auth == NULL)
++ if (!isccc_alist_alistp(_auth))
+ return (ISC_R_FAILURE);
+ hmd5 = isccc_alist_lookup(_auth, "hmd5");
+- if (hmd5 == NULL)
++ if (!isccc_sexpr_binaryp(hmd5))
+ return (ISC_R_FAILURE);
+ /*
+ * Compute digest.
+@@ -543,7 +543,7 @@
+ REQUIRE(ackp != NULL && *ackp == NULL);
+
+ _ctrl = isccc_alist_lookup(message, "_ctrl");
+- if (_ctrl == NULL ||
++ if (!isccc_alist_alistp(_ctrl) ||
+ isccc_cc_lookupuint32(_ctrl, "_ser", &serial) != ISC_R_SUCCESS ||
+ isccc_cc_lookupuint32(_ctrl, "_tim", &t) != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+@@ -588,7 +588,7 @@
+ isccc_sexpr_t *_ctrl;
+
+ _ctrl = isccc_alist_lookup(message, "_ctrl");
+- if (_ctrl == NULL)
++ if (!isccc_alist_alistp(_ctrl))
+ return (ISC_FALSE);
+ if (isccc_cc_lookupstring(_ctrl, "_ack", NULL) == ISC_R_SUCCESS)
+ return (ISC_TRUE);
+@@ -601,7 +601,7 @@
+ isccc_sexpr_t *_ctrl;
+
+ _ctrl = isccc_alist_lookup(message, "_ctrl");
+- if (_ctrl == NULL)
++ if (!isccc_alist_alistp(_ctrl))
+ return (ISC_FALSE);
+ if (isccc_cc_lookupstring(_ctrl, "_rpl", NULL) == ISC_R_SUCCESS)
+ return (ISC_TRUE);
+@@ -621,7 +621,7 @@
+
+ _ctrl = isccc_alist_lookup(message, "_ctrl");
+ _data = isccc_alist_lookup(message, "_data");
+- if (_ctrl == NULL || _data == NULL ||
++ if (!isccc_alist_alistp(_ctrl) || !isccc_alist_alistp(_data) ||
+ isccc_cc_lookupuint32(_ctrl, "_ser", &serial) != ISC_R_SUCCESS ||
+ isccc_cc_lookupstring(_data, "type", &type) != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+@@ -810,7 +810,7 @@
+ isccc_sexpr_t *_ctrl;
+
+ _ctrl = isccc_alist_lookup(message, "_ctrl");
+- if (_ctrl == NULL ||
++ if (!isccc_alist_alistp(_ctrl) ||
+ isccc_cc_lookupstring(_ctrl, "_ser", &_ser) != ISC_R_SUCCESS ||
+ isccc_cc_lookupstring(_ctrl, "_tim", &_tim) != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+diff -r e13d04281504 version
+--- a/version Thu Mar 03 13:53:44 2016 +0000
++++ b/version Fri Mar 04 12:27:21 2016 +0000
+@@ -10,4 +10,4 @@
+ PATCHVER=
+ RELEASETYPE=-ESV
+ RELEASEVER=-R11
+-EXTENSIONS=-P5
++EXTENSIONS=-P6