]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Do not allow zone transfers in dig over TLS without ALPN
authorArtem Boldariev <artem@boldariev.com>
Thu, 2 Sep 2021 12:39:50 +0000 (15:39 +0300)
committerArtem Boldariev <artem@boldariev.com>
Tue, 5 Oct 2021 08:23:47 +0000 (11:23 +0300)
This commit makes dig fail with error in case a zone transfer is
attempted over a connections where ALPN was not negotiated. All other
request types will work fine.

bin/dig/dighost.c
bin/tests/system/doth/tests.sh

index c40a1992f77e7ea502edb07912d8f7feb05a38cb..2397ac7c81e2a7fdcf7003a0e429a87697f826b5 100644 (file)
@@ -3121,6 +3121,7 @@ launch_next_query(dig_query_t *query) {
        int local_timeout = timeout * 1000;
        dig_lookup_t *l = NULL;
        isc_region_t r;
+       bool xfr;
 
        REQUIRE(DIG_VALID_QUERY(query));
        INSIST(!free_now);
@@ -3149,6 +3150,25 @@ launch_next_query(dig_query_t *query) {
        isc_nmhandle_settimeout(query->handle, local_timeout);
 
        query_attach(query, &readquery);
+
+       xfr = query->lookup->rdtype == dns_rdatatype_ixfr ||
+             query->lookup->rdtype == dns_rdatatype_axfr;
+       if (xfr && isc_nm_is_tlsdns_handle(query->handle) &&
+           !isc_nm_xfr_allowed(query->handle))
+       {
+               dighost_error("zone transfers over the "
+                             "established TLS connection are not allowed");
+               dighost_error("as the "
+                             "connection does not meet the requirements "
+                             "enforced by the RFC 9103");
+               isc_refcount_decrement0(&recvcount);
+               isc_nmhandle_detach(&query->readhandle);
+               cancel_lookup(l);
+               lookup_detach(&l);
+               clear_current_lookup();
+               return;
+       }
+
        isc_nm_read(query->handle, recv_done, readquery);
 
        if (!query->first_soa_rcvd) {
index 39ed8571f52489d6242fff6a824af6d8c6c6cb33..00ef08c7715e061dc43999d92e490b38c99071c7 100644 (file)
 # shellcheck disable=SC1091
 . ../conf.sh
 
+common_dig_options="+noadd +nosea +nostat +noquest +nocmd"
+msg_xfrs_not_allowed=";; zone transfers over the established TLS connection are not allowed"
+
 dig_with_tls_opts() {
-       "$DIG" +tls +noadd +nosea +nostat +noquest +nocmd -p "${TLSPORT}" "$@"
+       # shellcheck disable=SC2086
+       "$DIG" +tls $common_dig_options -p "${TLSPORT}" "$@"
 }
 
 dig_with_https_opts() {
-       "$DIG" +https +noadd +nosea +nostat +noquest +nocmd -p "${HTTPSPORT}" "$@"
+       # shellcheck disable=SC2086
+       "$DIG" +https $common_dig_options -p "${HTTPSPORT}" "$@"
 }
 
 dig_with_http_opts() {
-       "$DIG" +http-plain +noadd +nosea +nostat +noquest +nocmd -p "${HTTPPORT}" "$@"
+       # shellcheck disable=SC2086
+       "$DIG" +http-plain $common_dig_options -p "${HTTPPORT}" "$@"
 }
 
 wait_for_tls_xfer() (
@@ -95,6 +101,21 @@ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
 if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status + ret))
 
+# In this test we are trying to establish a DoT connection over the
+# DoH port. That is intentional, as dig should fail right after
+# handshake has happened and before sending any queries, as XFRs, per
+# the RFC, could happen only over a connection where "dot" ALPN token
+# was negotiated.  over DoH it cannot happen, as only "h2" token could
+# be selected for a DoH connection.
+n=$((n + 1))
+echo_i "checking DoT XFR with wrong ALPN token (h2, failure expected) ($n)"
+ret=0
+# shellcheck disable=SC2086
+"$DIG" +tls $common_dig_options -p "${HTTPSPORT}" +comm @10.53.0.1 . AXFR > dig.out.test$n
+grep "$msg_xfrs_not_allowed" dig.out.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
 n=$((n + 1))
 echo_i "checking DoH query (POST) ($n)"
 ret=0