]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[v9_10_5_patch] address TSIG bypass/forgery vulnerabilities
authorEvan Hunt <each@isc.org>
Tue, 27 Jun 2017 19:26:58 +0000 (12:26 -0700)
committerEvan Hunt <each@isc.org>
Tue, 27 Jun 2017 19:26:58 +0000 (12:26 -0700)
4643. [security] An error in TSIG handling could permit unauthorized
zone transfers or zone updates. (CVE-2017-3142)
(CVE-2017-3143) [RT #45383]

(cherry picked from commit 581c1526ab0f74a177980da9ff0514f795ed8669)
(cherry picked from commit a03f4b1ea4f1a4a70963fbeb606841c217f9e5f3)
(cherry picked from commit 8d00c66095b91be20d5ca5b85666ec940f724e6d)

CHANGES
README
doc/arm/notes.xml
lib/dns/api
lib/dns/dnssec.c
lib/dns/message.c
lib/dns/tsig.c
version

diff --git a/CHANGES b/CHANGES
index b2af1bdb5d1228235ad43d76cafc7bcbcb6f37b4..74a2b6b64fa525c4b021c1f58be3dbfd1e9a9c51 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+       --- 9.11.1-P2 released ---
+
+4643.  [security]      An error in TSIG handling could permit unauthorized
+                       zone transfers or zone updates. (CVE-2017-3142)
+                       (CVE-2017-3143) [RT #45383]
+
 4633.  [maint]         Updated AAAA (2001:500:200::b) for B.ROOT-SERVERS.NET.
 
        --- 9.10.5-P1 released ---
diff --git a/README b/README
index e74caf130d0f40664237551236ff3fc28b67f8c9..411950807ed2afff692f2b53b46d13efef4189d3 100644 (file)
--- a/README
+++ b/README
@@ -51,6 +51,11 @@ BIND 9
        For up-to-date release notes and errata, see
        http://www.isc.org/software/bind9/releasenotes
 
+BIND 9.10.5-P2
+
+        This version contains a fix for the security flaws
+        disclosed in CVE-2017-3142 and CVE-2017-3143.
+
 BIND 9.10.5-P1
 
         This version contains a fix for the security flaws
index c9b304edd843ffc0bb480a989e8107a358aeb017..8770c7f55fb844cb7e7be245741b4bfb576b0a13 100644 (file)
       BIND 9.10.5-P1 addresses the security issues described in
       CVE-2017-3140 and CVE-2017-3141.
     </para>
+    <para>
+      BIND 9.11.1-P2 addresses the security issues described in
+      CVE-2017-3142 and CVE-2017-3143. It also includes an update
+      to the address of the B root server.
+    </para>
   </section>
 
 
 
   <section xml:id="relnotes_security"><info><title>Security Fixes</title></info>
     <itemizedlist>
+      <listitem>
+       <para>
+         An error in TSIG handling could permit unauthorized zone
+         transfers or zone updates. These flaws are disclosed in
+         CVE-2017-3142 and CVE-2017-3143. [RT #45383]
+       </para>
+      </listitem>
       <listitem>
        <para>
          The BIND installer on Windows used an unquoted service path,
index 08e8a6e003e56a63ac82d146aabfd6632bce8652..98ab1a8324cab282114e26a4f1a710abb8ddae49 100644 (file)
@@ -7,5 +7,5 @@
 # 9.10: 140-149, 170-179
 # 9.11: 160-169
 LIBINTERFACE = 170
-LIBREVISION = 2
+LIBREVISION = 3
 LIBAGE = 0
index dae1cd7c669cf46b4381bd4beb4decba95a4a791..cf6b206af481269f7cb0ed9fe665f0142b11d112 100644 (file)
@@ -980,6 +980,8 @@ dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg,
        mctx = msg->mctx;
 
        msg->verify_attempted = 1;
+       msg->verified_sig = 0;
+       msg->sig0status = dns_tsigerror_badsig;
 
        if (is_response(msg)) {
                if (msg->query.base == NULL)
@@ -1075,6 +1077,7 @@ dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg,
        }
 
        msg->verified_sig = 1;
+       msg->sig0status = dns_rcode_noerror;
 
        dst_context_destroy(&ctx);
        dns_rdata_freestruct(&sig);
index 63c43b153c162e52d08c6c046224937968d10979..90f669d69a326851f9b57c4697236366640e68c9 100644 (file)
@@ -3058,12 +3058,19 @@ dns_message_signer(dns_message_t *msg, dns_name_t *signer) {
 
                result = dns_rdata_tostruct(&rdata, &tsig, NULL);
                INSIST(result == ISC_R_SUCCESS);
-               if (msg->tsigstatus != dns_rcode_noerror)
+               if (msg->verified_sig &&
+                   msg->tsigstatus == dns_rcode_noerror &&
+                   tsig.error == dns_rcode_noerror)
+               {
+                       result = ISC_R_SUCCESS;
+               } else if ((!msg->verified_sig) ||
+                          (msg->tsigstatus != dns_rcode_noerror))
+               {
                        result = DNS_R_TSIGVERIFYFAILURE;
-               else if (tsig.error != dns_rcode_noerror)
+               } else {
+                       INSIST(tsig.error != dns_rcode_noerror);
                        result = DNS_R_TSIGERRORSET;
-               else
-                       result = ISC_R_SUCCESS;
+               }
                dns_rdata_freestruct(&tsig);
 
                if (msg->tsigkey == NULL) {
index bbbfc11213284c3f25d14943b3e7f06efac73f70..49967540fdb29329c530173daecde8b3eee78fd9 100644 (file)
@@ -979,9 +979,10 @@ dns_tsig_sign(dns_message_t *msg) {
                        return (ret);
 
                /*
-                * If this is a response, digest the query signature.
+                * If this is a response and the query's signature
+                * validated, digest the query signature.
                 */
-               if (response) {
+               if (response && (tsig.error == dns_rcode_noerror)) {
                        dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
 
                        ret = dns_rdataset_first(msg->querytsig);
@@ -1218,6 +1219,8 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
        REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey));
 
        msg->verify_attempted = 1;
+       msg->verified_sig = 0;
+       msg->tsigstatus = dns_tsigerror_badsig;
 
        if (msg->tcp_continuation) {
                if (tsigkey == NULL || msg->querytsig == NULL)
@@ -1341,27 +1344,31 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
 #endif
            alg == DST_ALG_HMACSHA1 ||
            alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
-           alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) {
+           alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512)
+       {
                isc_uint16_t digestbits = dst_key_getbits(key);
                if (tsig.siglen > siglen) {
                        tsig_log(msg->tsigkey, 2, "signature length too big");
                        return (DNS_R_FORMERR);
                }
                if (tsig.siglen > 0 &&
-                   (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) {
+                   (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2)))
+               {
                        tsig_log(msg->tsigkey, 2,
                                 "signature length below minimum");
                        return (DNS_R_FORMERR);
                }
                if (tsig.siglen > 0 && digestbits != 0 &&
-                   tsig.siglen < ((digestbits + 1) / 8)) {
+                   tsig.siglen < ((digestbits + 1) / 8))
+               {
                        msg->tsigstatus = dns_tsigerror_badtrunc;
                        tsig_log(msg->tsigkey, 2,
                                 "truncated signature length too small");
                        return (DNS_R_TSIGVERIFYFAILURE);
                }
                if (tsig.siglen > 0 && digestbits == 0 &&
-                   tsig.siglen < siglen) {
+                   tsig.siglen < siglen)
+               {
                        msg->tsigstatus = dns_tsigerror_badtrunc;
                        tsig_log(msg->tsigkey, 2, "signature length too small");
                        return (DNS_R_TSIGVERIFYFAILURE);
@@ -1380,7 +1387,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
                if (ret != ISC_R_SUCCESS)
                        return (ret);
 
-               if (response) {
+               if (response && (tsig.error == dns_rcode_noerror)) {
                        isc_buffer_init(&databuf, data, sizeof(data));
                        isc_buffer_putuint16(&databuf, querytsig.siglen);
                        isc_buffer_usedregion(&databuf, &r);
@@ -1485,10 +1492,9 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
                        tsig_log(msg->tsigkey, 2,
                                 "signature failed to verify(1)");
                        goto cleanup_context;
-               } else if (ret != ISC_R_SUCCESS)
+               } else if (ret != ISC_R_SUCCESS) {
                        goto cleanup_context;
-
-               dst_context_destroy(&ctx);
+               }
        } else if (tsig.error != dns_tsigerror_badsig &&
                   tsig.error != dns_tsigerror_badkey) {
                msg->tsigstatus = dns_tsigerror_badsig;
@@ -1496,18 +1502,18 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
                return (DNS_R_TSIGVERIFYFAILURE);
        }
 
-       msg->tsigstatus = dns_rcode_noerror;
-
        if (tsig.error != dns_rcode_noerror) {
+               msg->tsigstatus = tsig.error;
                if (tsig.error == dns_tsigerror_badtime)
-                       return (DNS_R_CLOCKSKEW);
+                       ret = DNS_R_CLOCKSKEW;
                else
-                       return (DNS_R_TSIGERRORSET);
+                       ret = DNS_R_TSIGERRORSET;
+               goto cleanup_context;
        }
 
+       msg->tsigstatus = dns_rcode_noerror;
        msg->verified_sig = 1;
-
-       return (ISC_R_SUCCESS);
+       ret = ISC_R_SUCCESS;
 
 cleanup_context:
        if (ctx != NULL)
@@ -1539,6 +1545,9 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
        REQUIRE(msg->tcp_continuation == 1);
        REQUIRE(msg->querytsig != NULL);
 
+       msg->verified_sig = 0;
+       msg->tsigstatus = dns_tsigerror_badsig;
+
        if (!is_response(msg))
                return (DNS_R_EXPECTEDRESPONSE);
 
@@ -1577,7 +1586,8 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
                 * Do the key name and algorithm match that of the query?
                 */
                if (!dns_name_equal(keyname, &tsigkey->name) ||
-                   !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) {
+                   !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))
+               {
                        msg->tsigstatus = dns_tsigerror_badkey;
                        ret = DNS_R_TSIGVERIFYFAILURE;
                        tsig_log(msg->tsigkey, 2,
@@ -1596,7 +1606,8 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
                        ret = DNS_R_CLOCKSKEW;
                        goto cleanup_querystruct;
                } else if (now + msg->timeadjust <
-                          tsig.timesigned - tsig.fudge) {
+                          tsig.timesigned - tsig.fudge)
+               {
                        msg->tsigstatus = dns_tsigerror_badtime;
                        tsig_log(msg->tsigkey, 2,
                                 "signature is in the future");
@@ -1702,10 +1713,12 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
                sig_r.length = tsig.siglen;
                if (tsig.siglen == 0) {
                        if (tsig.error != dns_rcode_noerror) {
-                               if (tsig.error == dns_tsigerror_badtime)
+                               msg->tsigstatus = tsig.error;
+                               if (tsig.error == dns_tsigerror_badtime) {
                                        ret = DNS_R_CLOCKSKEW;
-                               else
+                               } else {
                                        ret = DNS_R_TSIGERRORSET;
+                               }
                        } else {
                                tsig_log(msg->tsigkey, 2,
                                         "signature is empty");
@@ -1721,24 +1734,32 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
                                 "signature failed to verify(2)");
                        ret = DNS_R_TSIGVERIFYFAILURE;
                        goto cleanup_context;
-               }
-               else if (ret != ISC_R_SUCCESS)
+               } else if (ret != ISC_R_SUCCESS) {
                        goto cleanup_context;
+               }
 
-               dst_context_destroy(&msg->tsigctx);
+               if (tsig.error != dns_rcode_noerror) {
+                       msg->tsigstatus = tsig.error;
+                       if (tsig.error == dns_tsigerror_badtime)
+                               ret = DNS_R_CLOCKSKEW;
+                       else
+                               ret = DNS_R_TSIGERRORSET;
+                       goto cleanup_context;
+               }
        }
 
        msg->tsigstatus = dns_rcode_noerror;
-       return (ISC_R_SUCCESS);
+       msg->verified_sig = 1;
+       ret = ISC_R_SUCCESS;
 
  cleanup_context:
-       dst_context_destroy(&msg->tsigctx);
+       if (msg->tsigctx != NULL)
+               dst_context_destroy(&msg->tsigctx);
 
  cleanup_querystruct:
        dns_rdata_freestruct(&querytsig);
 
        return (ret);
-
 }
 
 isc_result_t
diff --git a/version b/version
index 5de176749aa5a08189989cd6fe00ca9ecb6b6454..bf7b828be0f21b1eca86424b89af89b242e0cd3c 100644 (file)
--- a/version
+++ b/version
@@ -7,5 +7,5 @@ MAJORVER=9
 MINORVER=10
 PATCHVER=5
 RELEASETYPE=-P
-RELEASEVER=1
+RELEASEVER=2
 EXTENSIONS=