Merge branch '2776-allow-transfer-encrypted' into 'main'

Resolve #2776: Extend 'allow-transfer' with 'port' and 'transport' parameters

Closes #2776

See merge request isc-projects/bind9!5587
This commit is contained in:
Artem Boldariev 2021-11-30 10:44:11 +00:00
commit 3443938b99
43 changed files with 1002 additions and 57 deletions

View file

@ -1,3 +1,8 @@
5767. [func] Extend allow-transfer option with 'port' and
'transport' options to restrict zone transfers to
a specific port and DNS transport protocol.
[GL #2776]
5766. [func] Unused 'tls' clause options 'ca-file' and 'hostname'
were disabled. [GL !5600]

View file

@ -3149,7 +3149,7 @@ launch_next_query(dig_query_t *query) {
xfr = query->lookup->rdtype == dns_rdatatype_ixfr ||
query->lookup->rdtype == dns_rdatatype_axfr;
if (xfr && isc_nm_is_tlsdns_handle(query->handle) &&
if (xfr && isc_nm_socket_type(query->handle) == isc_nm_tlsdnssocket &&
!isc_nm_xfr_allowed(query->handle))
{
dighost_error("zone transfers over the "

View file

@ -166,7 +166,8 @@ OPTIONS
allow-query-on { address_match_element; ... };
allow-recursion { address_match_element; ... };
allow-recursion-on { address_match_element; ... };
allow-transfer { address_match_element; ... };
allow-transfer [ port integer ] [ transport string ] {
address_match_element; ... };
allow-update { address_match_element; ... };
allow-update-forwarding { address_match_element; ... };
also-notify [ port integer ] [ dscp integer ] { (
@ -605,7 +606,8 @@ VIEW
allow-query-on { address_match_element; ... };
allow-recursion { address_match_element; ... };
allow-recursion-on { address_match_element; ... };
allow-transfer { address_match_element; ... };
allow-transfer [ port integer ] [ transport string ] {
address_match_element; ... };
allow-update { address_match_element; ... };
allow-update-forwarding { address_match_element; ... };
also-notify [ port integer ] [ dscp integer ] { (
@ -889,7 +891,8 @@ VIEW
allow-notify { address_match_element; ... };
allow-query { address_match_element; ... };
allow-query-on { address_match_element; ... };
allow-transfer { address_match_element; ... };
allow-transfer [ port integer ] [ transport string ] {
address_match_element; ... };
allow-update { address_match_element; ... };
allow-update-forwarding { address_match_element; ... };
also-notify [ port integer ] [ dscp integer ] { (
@ -1009,7 +1012,8 @@ ZONE
allow-notify { address_match_element; ... };
allow-query { address_match_element; ... };
allow-query-on { address_match_element; ... };
allow-transfer { address_match_element; ... };
allow-transfer [ port integer ] [ transport string ] {
address_match_element; ... };
allow-update { address_match_element; ... };
allow-update-forwarding { address_match_element; ... };
also-notify [ port integer ] [ dscp integer ] { (

View file

@ -157,6 +157,7 @@ TESTS += \
synthfromdnssec \
tkey \
tools \
transport-acl \
tsig \
tsiggss \
ttl \

View file

@ -0,0 +1,16 @@
/*
* Copyright (C) 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/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
zone "example1" {
type primary;
file "example1.db";
allow-transfer port 99999 { any; };
};

View file

@ -0,0 +1,16 @@
/*
* Copyright (C) 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/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
zone "example1" {
type primary;
file "example1.db";
allow-transfer port 44344 transport blah { any; };
};

View file

@ -0,0 +1,16 @@
/*
* Copyright (C) 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/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
zone "example1" {
type primary;
file "example1.db";
allow-transfer port 44344 transport udp { any; };
};

View file

@ -0,0 +1,16 @@
/*
* Copyright (C) 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/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
zone "example1" {
type primary;
file "example1.db";
allow-transfer port 44344 transport http { any; };
};

View file

@ -0,0 +1,16 @@
/*
* Copyright (C) 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/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
zone "example1" {
type primary;
file "example1.db";
allow-transfer port 44344 transport http-plain { any; };
};

View file

@ -0,0 +1,47 @@
/*
* Copyright (C) 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/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
zone "example1" {
type primary;
file "example1.db";
allow-transfer port 44344 transport tls { any; };
};
zone "example2" {
type primary;
file "example2.db";
allow-transfer port 44344 transport tcp { any; };
};
zone "example3" {
type primary;
file "example3.db";
allow-transfer transport tls { any; };
};
zone "example4" {
type primary;
file "example4.db";
allow-transfer transport tcp { any; };
};
zone "example5" {
type primary;
file "example5.db";
allow-transfer port 53 { any; };
};
zone "example6" {
type primary;
file "example6.db";
allow-transfer { any; };
};

View file

@ -44,11 +44,11 @@ options {
zone "." {
type primary;
file "root.db";
allow-transfer { any; };
allow-transfer port @TLSPORT@ transport tls { any; };
};
zone "example" {
type primary;
file "example.db";
allow-transfer { any; };
allow-transfer port @TLSPORT@ transport tls { any; };
};

View file

@ -30,6 +30,11 @@ dig_with_http_opts() {
"$DIG" +http-plain $common_dig_options -p "${HTTPPORT}" "$@"
}
dig_with_opts() {
# shellcheck disable=SC2086
"$DIG" $common_dig_options -p "${PORT}" "$@"
}
wait_for_tls_xfer() (
dig_with_tls_opts -b 10.53.0.3 @10.53.0.2 example. AXFR > "dig.out.ns2.test$n" || return 1
grep "^;" "dig.out.ns2.test$n" > /dev/null && return 1
@ -101,6 +106,24 @@ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
# zone transfers are allowed only via TLS
n=$((n+1))
echo_i "testing zone transfer over Do53 server functionality (using dig, failure expected) ($n)"
ret=0
dig_with_opts example. -b 10.53.0.3 @10.53.0.1 axfr > dig.out.ns1.test$n || ret=1
grep "; Transfer failed." dig.out.ns1.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
# querying zones is still allowed via UDP/TCP
n=$((n + 1))
echo_i "checking Do53 query ($n)"
ret=0
dig_with_opts @10.53.0.1 example SOA > dig.out.test$n
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

View file

@ -0,0 +1,22 @@
#!/bin/sh
#
# Copyright (C) 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
#
# Clean up after zone transfer tests.
#
rm -f ./*/named.conf
rm -f ./*/named.memstats
rm -f ./*/named.run
rm -f ./*/named.run.prev
rm -f ./dig.out.*
rm -f ./*/example.db
rm -rf ./headers.*

View file

@ -0,0 +1,127 @@
/*
* Copyright (C) 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/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
include "../../common/rndc.key";
controls {
inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
tls self-signed {
cert-file "../self-signed-cert.pem";
key-file "../self-signed-key.pem";
};
options {
pid-file "named.pid";
##
# generic test
listen-on port @PORT@ { 10.53.0.1; };
listen-on port @TLSPORT@ tls self-signed { 10.53.0.1; };
# test #1
listen-on port @EXTRAPORT1@ { 10.53.0.1; };
listen-on port @EXTRAPORT1@ tls self-signed { 10.53.0.2; };
listen-on port @EXTRAPORT2@ { 10.53.0.1; };
listen-on port @EXTRAPORT2@ tls self-signed { 10.53.0.2; };
# test #2
listen-on port @EXTRAPORT1@ { 10.53.0.3; };
listen-on port @EXTRAPORT2@ { 10.53.0.3; };
listen-on port @EXTRAPORT1@ tls self-signed { 10.53.0.4; };
listen-on port @EXTRAPORT2@ tls self-signed { 10.53.0.4; };
# test #3
listen-on port @EXTRAPORT3@ tls self-signed { 10.53.0.3; };
listen-on port @EXTRAPORT4@ tls self-signed { 10.53.0.3; };
listen-on port @EXTRAPORT3@ { 10.53.0.4; };
listen-on port @EXTRAPORT4@ { 10.53.0.4; };
# test #4
listen-on port @EXTRAPORT1@ { 10.53.0.5; };
listen-on port @EXTRAPORT2@ { 10.53.0.5; };
listen-on port @EXTRAPORT1@ tls self-signed { 10.53.0.6; };
# test #5
listen-on port @EXTRAPORT3@ tls self-signed { 10.53.0.1; };
listen-on port @EXTRAPORT4@ tls self-signed { 10.53.0.1; };
listen-on port @EXTRAPORT3@ { 10.53.0.2; };
# test #6
listen-on port @EXTRAPORT5@ { 10.53.0.1; };
# test #7
listen-on port @EXTRAPORT6@ tls self-signed { 10.53.0.1; };
# test #7
listen-on port @EXTRAPORT7@ tls self-signed { 10.53.0.1; };
# test #8
listen-on port @EXTRAPORT8@ { 10.53.0.1; };
##
listen-on-v6 { none; };
recursion no;
notify explicit;
statistics-file "named.stats";
dnssec-validation yes;
tcp-initial-timeout 1200;
};
zone "example0" {
type primary;
file "example.db";
allow-transfer port @TLSPORT@ transport tls { any; };
};
zone "example1" {
type primary;
file "example.db";
allow-transfer port @EXTRAPORT1@ { any; };
};
zone "example2" {
type primary;
file "example.db";
allow-transfer transport tcp { any; };
};
zone "example3" {
type primary;
file "example.db";
allow-transfer transport tls { any; };
};
zone "example4" {
type primary;
file "example.db";
allow-transfer port @EXTRAPORT1@ transport tcp { any; };
};
zone "example5" {
type primary;
file "example.db";
allow-transfer port @EXTRAPORT3@ transport tls { any; };
};
zone "example6" {
type primary;
file "example.db";
allow-transfer port @EXTRAPORT5@ transport tcp { 10.53.0.7; 10.53.0.8; 10.53.0.9; };
};
zone "example7" {
type primary;
file "example.db";
allow-transfer port @EXTRAPORT6@ transport tls { 10.53.0.7; 10.53.0.8; 10.53.0.9; };
};
zone "example8" {
type primary;
file "example.db";
allow-transfer port @EXTRAPORT7@ transport tls { 10.53.0.1; 10.53.0.2; 10.53.0.3; };
};
zone "example9" {
type primary;
file "example.db";
allow-transfer port @EXTRAPORT8@ transport tcp { 10.53.0.7; !10.53.0.8; 10.53.0.9; };
};

View file

@ -0,0 +1,28 @@
-----BEGIN CERTIFICATE-----
MIIEwTCCAymgAwIBAgIUJm/nnhqH3omkx9PqEyewJhYg/sQwDQYJKoZIhvcNAQEL
BQAwbzELMAkGA1UEBhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4G
A1UEBwwHS2hhcmtpdjEMMAoGA1UECgwDSVNDMQ8wDQYDVQQLDAZTVy1FbmcxFTAT
BgNVBAMMDHRlc3QuaXNjLm9yZzAgFw0yMTExMjkxMTQ0MDRaGA8yMTIxMTEzMDEx
NDQwNFowbzELMAkGA1UEBhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQ
MA4GA1UEBwwHS2hhcmtpdjEMMAoGA1UECgwDSVNDMQ8wDQYDVQQLDAZTVy1Fbmcx
FTATBgNVBAMMDHRlc3QuaXNjLm9yZzCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCC
AYoCggGBAM8hzYSedQFajsjJKVnZ3BeWLOGULJO2ixQZ/vMnAk6q5a6JFST5DYVA
G84S8GKzswZibNNuKJnuuQO3mBE2+Pioc+vxtewxlzbcQ2EaKgbx5IVezzHtQUYw
WUUdSv7ViKOVeaI9jvXqpYUbbtLogSVkPB+/oWU1Wu4y/TkXc4wEqBxQx+P4kNnj
stCP7r5HMkvBqQgmod5rjqLFohtIQbEhjSBaoK+td25vWUvfG/isduiKx52tC4k3
CBnBOIfvgkNmJk5Rh3RufbiyBSCtgBcH3wp9VSByqC7roFQqzBkZm0aCmuggNmXb
OXU7klEyVmAeiqLvfQSkjNsDmlaTsHCszgIB9RPA4f07KV62uFsdOu0K48yXBnEa
nZeIFqwuTS+PU7T+SnWQGoJLDvCa6IPERqk+5j94BET84/z942WLVqSLlqAoa1rF
5686m2Dgj10SRUpE99bmVg+HZRwO/ZbkLgu+tILqpYpnKP6n8FDpjW0Jnl77uw9S
UeAvbGyw5QIDAQABo1MwUTAdBgNVHQ4EFgQUJV5YRDD9iF+uz9AFx5fA86CtlVQw
HwYDVR0jBBgwFoAUJV5YRDD9iF+uz9AFx5fA86CtlVQwDwYDVR0TAQH/BAUwAwEB
/zANBgkqhkiG9w0BAQsFAAOCAYEAi8sOMYGFs6n1C23vXorx5Zbbym5QkUVgYbxe
9VaBy0Y/PgvXaxtz8zytbtFhyU5izXNZ7k8A4vnJ/TGxoIj503ArBMZj+CiwIBVI
yMzheDp+MY4F19OIy/TsQglYeOEhK/PA9uj5GZYE1Ar6Qck4wl2vk3iaTMsaniyV
zPqCiso2YDLISSvF3nvLcTQ8nX6JyYR/3J0t5biLcissPvubgzguoULRn2VwWw/7
MaRXXPMTBTyCAylJrSgfBKvYmJcnHHocTAZkGElDaYHfALlR+5K9wi/QYwz3kFpN
mS55yjSBlPPxH0rZw8fOdCLNbyzPjP+aXXoTUJa5/X7RNGKQTcuohektsuU1quxo
lugrRYjhiytqBUek3qtBJfmX28LnfZHyKpDpHO6wykQS7FTWb69c6tvAzlwFbH7o
onyhZz1Z2iXw4u7N4nTlj1VqHVMiEr2KUfxtOm5HQ7tZFSaWIA0HfIRB7WD3Escz
DY3Bbu9bS711Yywp+NpvOqBSvMon
-----END CERTIFICATE-----

View file

@ -0,0 +1,40 @@
-----BEGIN PRIVATE KEY-----
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
bEd5UJArJoST5lff5y7MyQ==
-----END PRIVATE KEY-----

View file

@ -0,0 +1,19 @@
#!/bin/sh
#
# Copyright (C) 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
# shellcheck disable=SC1091
. ../conf.sh
$SHELL clean.sh
$SHELL "${TOP_SRCDIR}"/bin/tests/system/genzone.sh 2 > ns1/example.db
copy_setports ns1/named.conf.in ns1/named.conf

View file

@ -0,0 +1,120 @@
#!/bin/sh
#
# Copyright (C) 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
# shellcheck disable=SC1091
. ../conf.sh
dig_out_basename="dig.out.test"
testing="testing allow-transfer transport ACL functionality"
dig_with_opts() {
# shellcheck disable=SC2086
"$DIG" +noadd +nosea +nostat +noquest +nocmd "$@"
}
status=0
n=0
run_dig_test () {
test_message="$1"
shift
n=$((n+1))
echo_i "$test_message ($n)"
ret=0
dig_with_opts "$@" > "$dig_out_basename$n" || ret=1
}
run_dig_expect_axfr_success () {
run_dig_test "$@"
grep "; Transfer failed" "$dig_out_basename$n" > /dev/null && ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status+ret))
}
run_dig_expect_axfr_failure () {
run_dig_test "$@"
grep "; Transfer failed" "$dig_out_basename$n" > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
}
# generic tests
run_dig_expect_axfr_success "$testing for XoT" -p "${TLSPORT}" +tls -b 10.53.0.10 @10.53.0.1 axfr example0
run_dig_expect_axfr_failure "$testing XFR via TCP (failure expected)" -p "${PORT}" +tcp -b 10.53.0.10 @10.53.0.1 axfr example0
# 1. Test allow-transfer port X, transfer works with TCP and TLS on port X but not port Y.
run_dig_expect_axfr_success "$testing for XFR via TCP" -p "${EXTRAPORT1}" +tcp -b 10.53.0.10 @10.53.0.1 axfr example1
run_dig_expect_axfr_success "$testing for XoT" -p "${EXTRAPORT1}" +tls -b 10.53.0.10 @10.53.0.2 axfr example1
run_dig_expect_axfr_failure "$testing for XFR via TCP (failure expected)" -p "${EXTRAPORT2}" +tcp -b 10.53.0.10 @10.53.0.1 axfr example1
run_dig_expect_axfr_failure "$testing for XoT (failure expected)" -p "${EXTRAPORT2}" +tls -b 10.53.0.10 @10.53.0.2 axfr example1
# 2. Test allow-transfer transport tcp, transfer works with TCP on any port but not TLS.
run_dig_expect_axfr_success "$testing for XFR via TCP" -p "${EXTRAPORT1}" +tcp -b 10.53.0.10 @10.53.0.3 axfr example2
run_dig_expect_axfr_success "$testing for XFR via TCP" -p "${EXTRAPORT2}" +tcp -b 10.53.0.10 @10.53.0.3 axfr example2
run_dig_expect_axfr_failure "$testing for XoT (failure expected)" -p "${EXTRAPORT1}" +tls -b 10.53.0.10 @10.53.0.4 axfr example2
run_dig_expect_axfr_failure "$testing for XoT (failure expected)" -p "${EXTRAPORT2}" +tls -b 10.53.0.10 @10.53.0.4 axfr example2
# 3. Test allow-transfer transport tls, transfer works with TLS on any port but not TCP.
run_dig_expect_axfr_success "$testing for XoT" -p "${EXTRAPORT3}" +tls -b 10.53.0.10 @10.53.0.3 axfr example3
run_dig_expect_axfr_success "$testing for XoT" -p "${EXTRAPORT4}" +tls -b 10.53.0.10 @10.53.0.3 axfr example3
run_dig_expect_axfr_failure "$testing for XFR via TCP (failure expected)" -p "${EXTRAPORT3}" +tcp -b 10.53.0.10 @10.53.0.4 axfr example3
run_dig_expect_axfr_failure "$testing for XFR via TCP (failure expected)" -p "${EXTRAPORT4}" +tcp -b 10.53.0.10 @10.53.0.4 axfr example3
# 4. Test allow-transfer port X transport tcp, transfer works with TCP on port X but not port Y and not with TLS on port X.
run_dig_expect_axfr_success "$testing for XFR via TCP" -p "${EXTRAPORT1}" +tcp -b 10.53.0.10 @10.53.0.5 axfr example4
run_dig_expect_axfr_failure "$testing for XFR via TCP (failure expected)" -p "${EXTRAPORT2}" +tcp -b 10.53.0.10 @10.53.0.5 axfr example4
run_dig_expect_axfr_failure "$testing for XoT (failure expected)" -p "${EXTRAPORT1}" +tls -b 10.53.0.10 @10.53.0.6 axfr example4
# 5. Test allow-transfer port X transport tls, transfer works with TLS on port X but not port Y and not with TCP on port X.
run_dig_expect_axfr_success "$testing for XoT" -p "${EXTRAPORT3}" +tls -b 10.53.0.10 @10.53.0.1 axfr example5
run_dig_expect_axfr_failure "$testing for XoT (failure expected)" -p "${EXTRAPORT4}" +tls -b 10.53.0.10 @10.53.0.1 axfr example5
run_dig_expect_axfr_failure "$testing for XFR via TCP (failure expected)" -p "${EXTRAPORT3}" +tcp -b 10.53.0.10 @10.53.0.2 axfr example5
# 6. Test with multiple allow-transfer available, first ACL is a match.
run_dig_expect_axfr_success "$testing for XFR via TCP" -p "${EXTRAPORT5}" +tcp -b 10.53.0.7 @10.53.0.1 axfr example6
run_dig_expect_axfr_failure "$testing for XFR via TCP (failure expected)" -p "${EXTRAPORT5}" +tcp -b 10.53.0.6 @10.53.0.1 axfr example6
# 7. Test with multiple allow-transfer available, last ACL is a match.
run_dig_expect_axfr_success "$testing for XoT" -p "${EXTRAPORT6}" +tls -b 10.53.0.9 @10.53.0.1 axfr example7
run_dig_expect_axfr_failure "$testing for XoT (failure expected)" -p "${EXTRAPORT6}" +tls -b 10.53.0.6 @10.53.0.1 axfr example7
# 8. Test with multiple allow-transfer available, no ACL is a match.
run_dig_expect_axfr_failure "$testing for XoT (failure expected)" -p "${EXTRAPORT7}" +tls -b 10.53.0.7 @10.53.0.1 axfr example8
# 9. Test with multiple allow-transfer available, negated ACL is used.
run_dig_expect_axfr_success "$testing for XFR via TCP" -p "${EXTRAPORT8}" +tcp -b 10.53.0.7 @10.53.0.1 axfr example9
run_dig_expect_axfr_failure "$testing for XoT (failure expected)" -p "${EXTRAPORT8}" +tcp -b 10.53.0.8 @10.53.0.1 axfr example9
run_dig_expect_axfr_success "$testing for XFR via TCP" -p "${EXTRAPORT8}" +tcp -b 10.53.0.9 @10.53.0.1 axfr example9
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1

View file

@ -2416,6 +2416,14 @@ for details on how to specify IP address lists.
statement set in ``options`` or ``view``. If not specified, the
default is to allow transfers to all hosts.
The transport level limitations can also be specified. In
particular, zone transfers can be restricted to a specific port and
DNS transport protocol by using the options ``port`` and
``transport``. Zone transfers are currently only possible via the
TCP and TLS transports; either option can be specified.
For example: ``allow-transfer port 853 transport tls { any; };``
``blackhole``
This specifies a list of addresses which the server does not accept queries
from or use to resolve a query. Queries from these addresses are not

View file

@ -233,7 +233,8 @@ options {
allow\-query\-on { address_match_element; ... };
allow\-recursion { address_match_element; ... };
allow\-recursion\-on { address_match_element; ... };
allow\-transfer { address_match_element; ... };
allow\-transfer [ port integer ] [ transport string ] {
address_match_element; ... };
allow\-update { address_match_element; ... };
allow\-update\-forwarding { address_match_element; ... };
also\-notify [ port integer ] [ dscp integer ] { (
@ -708,7 +709,8 @@ view string [ class ] {
allow\-query\-on { address_match_element; ... };
allow\-recursion { address_match_element; ... };
allow\-recursion\-on { address_match_element; ... };
allow\-transfer { address_match_element; ... };
allow\-transfer [ port integer ] [ transport string ] {
address_match_element; ... };
allow\-update { address_match_element; ... };
allow\-update\-forwarding { address_match_element; ... };
also\-notify [ port integer ] [ dscp integer ] { (
@ -992,7 +994,8 @@ view string [ class ] {
allow\-notify { address_match_element; ... };
allow\-query { address_match_element; ... };
allow\-query\-on { address_match_element; ... };
allow\-transfer { address_match_element; ... };
allow\-transfer [ port integer ] [ transport string ] {
address_match_element; ... };
allow\-update { address_match_element; ... };
allow\-update\-forwarding { address_match_element; ... };
also\-notify [ port integer ] [ dscp integer ] { (
@ -1116,7 +1119,8 @@ zone string [ class ] {
allow\-notify { address_match_element; ... };
allow\-query { address_match_element; ... };
allow\-query\-on { address_match_element; ... };
allow\-transfer { address_match_element; ... };
allow\-transfer [ port integer ] [ transport string ] {
address_match_element; ... };
allow\-update { address_match_element; ... };
allow\-update\-forwarding { address_match_element; ... };
also\-notify [ port integer ] [ dscp integer ] { (

View file

@ -2,7 +2,7 @@ zone <string> [ <class> ] {
type ( master | primary );
allow-query { <address_match_element>; ... };
allow-query-on { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
allow-update { <address_match_element>; ... };
also-notify [ port <integer> ] [ dscp <integer> ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [ dscp <integer> ];

View file

@ -4,7 +4,7 @@
type ( master | primary );
allow-query { <address_match_element>; ... };
allow-query-on { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
allow-update { <address_match_element>; ... };
also-notify [ port <integer> ] [ dscp <integer> ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [ dscp <integer> ];

View file

@ -3,7 +3,7 @@ zone <string> [ <class> ] {
allow-notify { <address_match_element>; ... };
allow-query { <address_match_element>; ... };
allow-query-on { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
allow-update-forwarding { <address_match_element>; ... };
also-notify [ port <integer> ] [ dscp <integer> ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [ dscp <integer> ];

View file

@ -5,7 +5,7 @@
allow-notify { <address_match_element>; ... };
allow-query { <address_match_element>; ... };
allow-query-on { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
allow-update-forwarding { <address_match_element>; ... };
also-notify [ port <integer> ] [ dscp <integer> ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [ dscp <integer> ];

View file

@ -90,7 +90,8 @@ options {
allow-query-on { <address_match_element>; ... };
allow-recursion { <address_match_element>; ... };
allow-recursion-on { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-transfer [ port <integer> ] [ transport <string> ] {
<address_match_element>; ... };
allow-update { <address_match_element>; ... };
allow-update-forwarding { <address_match_element>; ... };
also-notify [ port <integer> ] [ dscp <integer> ] { (
@ -484,7 +485,8 @@ view <string> [ <class> ] {
allow-query-on { <address_match_element>; ... };
allow-recursion { <address_match_element>; ... };
allow-recursion-on { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-transfer [ port <integer> ] [ transport <string> ] {
<address_match_element>; ... };
allow-update { <address_match_element>; ... };
allow-update-forwarding { <address_match_element>; ... };
also-notify [ port <integer> ] [ dscp <integer> ] { (
@ -770,7 +772,8 @@ view <string> [ <class> ] {
allow-notify { <address_match_element>; ... };
allow-query { <address_match_element>; ... };
allow-query-on { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-transfer [ port <integer> ] [ transport <string> ] {
<address_match_element>; ... };
allow-update { <address_match_element>; ... };
allow-update-forwarding { <address_match_element>; ... };
also-notify [ port <integer> ] [ dscp <integer> ] { (
@ -886,7 +889,8 @@ zone <string> [ <class> ] {
allow-notify { <address_match_element>; ... };
allow-query { <address_match_element>; ... };
allow-query-on { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-transfer [ port <integer> ] [ transport <string> ] {
<address_match_element>; ... };
allow-update { <address_match_element>; ... };
allow-update-forwarding { <address_match_element>; ... };
also-notify [ port <integer> ] [ dscp <integer> ] { (

View file

@ -89,7 +89,8 @@ options {
allow-query-on { <address_match_element>; ... };
allow-recursion { <address_match_element>; ... };
allow-recursion-on { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-transfer [ port <integer> ] [ transport <string> ] {
<address_match_element>; ... };
allow-update { <address_match_element>; ... };
allow-update-forwarding { <address_match_element>; ... };
also-notify [ port <integer> ] [ dscp <integer> ] { (
@ -481,7 +482,8 @@ view <string> [ <class> ] {
allow-query-on { <address_match_element>; ... };
allow-recursion { <address_match_element>; ... };
allow-recursion-on { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-transfer [ port <integer> ] [ transport <string> ] {
<address_match_element>; ... };
allow-update { <address_match_element>; ... };
allow-update-forwarding { <address_match_element>; ... };
also-notify [ port <integer> ] [ dscp <integer> ] { (
@ -765,7 +767,8 @@ view <string> [ <class> ] {
allow-notify { <address_match_element>; ... };
allow-query { <address_match_element>; ... };
allow-query-on { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-transfer [ port <integer> ] [ transport <string> ] {
<address_match_element>; ... };
allow-update { <address_match_element>; ... };
allow-update-forwarding { <address_match_element>; ... };
also-notify [ port <integer> ] [ dscp <integer> ] { (
@ -880,7 +883,8 @@ zone <string> [ <class> ] {
allow-notify { <address_match_element>; ... };
allow-query { <address_match_element>; ... };
allow-query-on { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-transfer [ port <integer> ] [ transport <string> ] {
<address_match_element>; ... };
allow-update { <address_match_element>; ... };
allow-update-forwarding { <address_match_element>; ... };
also-notify [ port <integer> ] [ dscp <integer> ] { (

View file

@ -9,7 +9,8 @@
allow-query-on { <address_match_element>; ... };
allow-recursion { <address_match_element>; ... };
allow-recursion-on { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-transfer [ port <integer> ] [ transport <string> ] {
<address_match_element>; ... };
allow-update { <address_match_element>; ... };
allow-update-forwarding { <address_match_element>; ... };
also-notify [ port <integer> ] [ dscp <integer> ] { (

View file

@ -3,7 +3,7 @@ zone <string> [ <class> ] {
allow-notify { <address_match_element>; ... };
allow-query { <address_match_element>; ... };
allow-query-on { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
allow-update-forwarding { <address_match_element>; ... };
also-notify [ port <integer> ] [ dscp <integer> ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [ dscp <integer> ];

View file

@ -5,7 +5,7 @@
allow-notify { <address_match_element>; ... };
allow-query { <address_match_element>; ... };
allow-query-on { <address_match_element>; ... };
allow-transfer { <address_match_element>; ... };
allow-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
allow-update-forwarding { <address_match_element>; ... };
also-notify [ port <integer> ] [ dscp <integer> ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [ dscp <integer> ];

View file

@ -35,7 +35,13 @@ Removed Features
Feature Changes
~~~~~~~~~~~~~~~
- None.
- The ``allow-transfers`` option was extended to accept additional
``port`` and ``transport`` parameters, to further restrict zone
transfers to a particular port and DNS transport protocol. Either of
these options can be specified.
For example: ``allow-transfer port 853 transport tls { any; };``
:gl:`#2776`
Bug Fixes
~~~~~~~~~

View file

@ -475,6 +475,47 @@ checkacl(const char *aclname, cfg_aclconfctx_t *actx, const cfg_obj_t *zconfig,
if (acl != NULL) {
dns_acl_detach(&acl);
}
if (strcasecmp(aclname, "allow-transfer") == 0 &&
cfg_obj_istuple(aclobj)) {
const cfg_obj_t *obj_port = cfg_tuple_get(
cfg_tuple_get(aclobj, "port-transport"), "port");
const cfg_obj_t *obj_proto = cfg_tuple_get(
cfg_tuple_get(aclobj, "port-transport"), "transport");
if (cfg_obj_isuint32(obj_port) &&
cfg_obj_asuint32(obj_port) >= UINT16_MAX) {
cfg_obj_log(obj_port, logctx, ISC_LOG_ERROR,
"port value '%u' is out of range",
cfg_obj_asuint32(obj_port));
if (result == ISC_R_SUCCESS) {
result = ISC_R_RANGE;
}
}
if (cfg_obj_isstring(obj_proto)) {
const char *allowed[] = { "tcp", "tls" };
const char *transport = cfg_obj_asstring(obj_proto);
bool found = false;
for (size_t i = 0; i < ARRAY_SIZE(allowed); i++) {
if (strcasecmp(transport, allowed[i]) == 0) {
found = true;
}
}
if (!found) {
cfg_obj_log(obj_proto, logctx, ISC_LOG_ERROR,
"'%s' is not a valid transport "
"protocol for "
"zone "
"transfers. Please specify either "
"'tcp' or 'tls'",
transport);
result = ISC_R_FAILURE;
}
}
}
return (result);
}

View file

@ -71,6 +71,9 @@ dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
acl->elements = isc_mem_get(mctx, n * sizeof(dns_aclelement_t));
acl->alloc = n;
memset(acl->elements, 0, n * sizeof(dns_aclelement_t));
ISC_LIST_INIT(acl->ports_and_transports);
acl->port_proto_entries = 0;
*target = acl;
return (ISC_R_SUCCESS);
}
@ -241,6 +244,54 @@ dns_acl_match(const isc_netaddr_t *reqaddr, const dns_name_t *reqsigner,
return (ISC_R_SUCCESS);
}
isc_result_t
dns_acl_match_port_transport(const isc_netaddr_t *reqaddr,
const in_port_t local_port,
const isc_nmsocket_type_t transport,
const bool encrypted, const dns_name_t *reqsigner,
const dns_acl_t *acl, const dns_aclenv_t *env,
int *match, const dns_aclelement_t **matchelt) {
isc_result_t result = ISC_R_SUCCESS;
dns_acl_port_transports_t *next;
REQUIRE(reqaddr != NULL);
REQUIRE(DNS_ACL_VALID(acl));
if (!ISC_LIST_EMPTY(acl->ports_and_transports)) {
result = ISC_R_FAILURE;
for (next = ISC_LIST_HEAD(acl->ports_and_transports);
next != NULL; next = ISC_LIST_NEXT(next, link))
{
bool match_port = true;
bool match_transport = true;
if (next->port != 0) {
/* Port is specified. */
match_port = (local_port == next->port);
}
if (next->transports != 0) {
/* Transport protocol is specified. */
match_transport =
((transport & next->transports) ==
transport &&
next->encrypted == encrypted);
}
if (match_port && match_transport) {
result = next->negative ? ISC_R_FAILURE
: ISC_R_SUCCESS;
break;
}
}
}
if (result != ISC_R_SUCCESS) {
return (result);
}
return (dns_acl_match(reqaddr, reqsigner, acl, env, match, matchelt));
}
/*
* Merge the contents of one ACL into another. Call dns_iptable_merge()
* for the IP tables, then concatenate the element arrays.
@ -347,6 +398,11 @@ dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, bool pos) {
dns_acl_node_count(dest) = nodes;
}
/*
* Merge ports and transports
*/
dns_acl_merge_ports_transports(dest, source, pos);
return (ISC_R_SUCCESS);
}
@ -449,6 +505,7 @@ dns_acl_attach(dns_acl_t *source, dns_acl_t **target) {
static void
destroy(dns_acl_t *dacl) {
unsigned int i;
dns_acl_port_transports_t *port_proto;
INSIST(!ISC_LINK_LINKED(dacl, nextincache));
@ -470,6 +527,17 @@ destroy(dns_acl_t *dacl) {
if (dacl->iptable != NULL) {
dns_iptable_detach(&dacl->iptable);
}
port_proto = ISC_LIST_HEAD(dacl->ports_and_transports);
while (port_proto != NULL) {
dns_acl_port_transports_t *next = NULL;
next = ISC_LIST_NEXT(port_proto, link);
ISC_LIST_DEQUEUE(dacl->ports_and_transports, port_proto, link);
isc_mem_put(dacl->mctx, port_proto, sizeof(*port_proto));
port_proto = next;
}
isc_refcount_destroy(&dacl->refcount);
dacl->magic = 0;
isc_mem_putanddetach(&dacl->mctx, dacl, sizeof(*dacl));
@ -707,3 +775,57 @@ dns_aclenv_detach(dns_aclenv_t **aclenvp) {
dns__aclenv_destroy(aclenv);
}
}
void
dns_acl_add_port_transports(dns_acl_t *acl, const in_port_t port,
const uint32_t transports, const bool encrypted,
const bool negative) {
dns_acl_port_transports_t *port_proto;
REQUIRE(DNS_ACL_VALID(acl));
REQUIRE(port != 0 || transports != 0);
port_proto = isc_mem_get(acl->mctx, sizeof(*port_proto));
*port_proto = (dns_acl_port_transports_t){ .port = port,
.transports = transports,
.encrypted = encrypted,
.negative = negative };
ISC_LINK_INIT(port_proto, link);
ISC_LIST_APPEND(acl->ports_and_transports, port_proto, link);
acl->port_proto_entries++;
}
void
dns_acl_merge_ports_transports(dns_acl_t *dest, dns_acl_t *source, bool pos) {
dns_acl_port_transports_t *next;
REQUIRE(DNS_ACL_VALID(dest));
REQUIRE(DNS_ACL_VALID(source));
const bool negative = !pos;
/*
* Merge ports and transports
*/
for (next = ISC_LIST_HEAD(source->ports_and_transports); next != NULL;
next = ISC_LIST_NEXT(next, link))
{
const bool next_positive = !next->negative;
bool add_negative;
/*
* Reverse sense of positives if this is a negative acl. The
* logic is used (and, thus, enforced) by dns_acl_merge(),
* from which dns_acl_merge_ports_transports() is called.
*/
if (negative && next_positive) {
add_negative = true;
} else {
add_negative = next->negative;
}
dns_acl_add_port_transports(dest, next->port, next->transports,
next->encrypted, add_negative);
}
}

View file

@ -52,6 +52,14 @@ typedef enum {
dns_aclelementtype_any
} dns_aclelementtype_t;
typedef struct dns_acl_port_transports {
in_port_t port;
uint32_t transports;
bool encrypted; /* for protocols with optional encryption (e.g. HTTP) */
bool negative;
ISC_LINK(struct dns_acl_port_transports) link;
} dns_acl_port_transports_t;
typedef struct dns_aclipprefix dns_aclipprefix_t;
struct dns_aclipprefix {
@ -83,6 +91,8 @@ struct dns_acl {
unsigned int length; /*%< Elements initialized */
char *name; /*%< Temporary use only */
ISC_LINK(dns_acl_t) nextincache; /*%< Ditto */
ISC_LIST(dns_acl_port_transports_t) ports_and_transports;
size_t port_proto_entries;
};
struct dns_aclenv {
@ -270,4 +280,46 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr, const dns_name_t *reqsigner,
* returned through 'matchelt' is not necessarily 'e' itself.
*/
isc_result_t
dns_acl_match_port_transport(const isc_netaddr_t *reqaddr,
const in_port_t local_port,
const isc_nmsocket_type_t transport,
const bool encrypted, const dns_name_t *reqsigner,
const dns_acl_t *acl, const dns_aclenv_t *env,
int *match, const dns_aclelement_t **matchelt);
/*%<
* Like dns_acl_match, but able to match the server port and
* transport, as well as encryption status.
*
* Requires:
*\li 'reqaddr' is not 'NULL';
*\li 'acl' is a valid ACL object.
*/
void
dns_acl_add_port_transports(dns_acl_t *acl, const in_port_t port,
const uint32_t transports, const bool encrypted,
const bool negative);
/*%<
* Adds a "port-transports" entry to the specified ACL. Transports
* are specified as a bit-set 'transports' consisting of entries
* defined in the isc_nmsocket_type enumeration.
*
* Requires:
*\li 'acl' is a valid ACL object;
*\li either 'port' or 'transports' is not equal to 0.
*/
void
dns_acl_merge_ports_transports(dns_acl_t *dest, dns_acl_t *source, bool pos);
/*%<
* Merges "port-transports" entries from the 'dest' ACL into
* the 'source' ACL. The 'pos' parameter works in a way similar to
* 'dns_acl_merge()'.
*
* Requires:
*\li 'dest' is a valid ACL object;
*\li 'source' is a valid ACL object.
*/
ISC_LANG_ENDDECLS

View file

@ -500,8 +500,6 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
* 'cb'.
*/
bool
isc_nm_is_tlsdns_handle(isc_nmhandle_t *handle);
/*%<
* Returns 'true' iff 'handle' is associated with a socket of type
* 'isc_nm_tlsdnssocket'.
@ -647,6 +645,24 @@ isc_nm_set_maxage(isc_nmhandle_t *handle, const uint32_t ttl);
* connection.
*/
isc_nmsocket_type
isc_nm_socket_type(const isc_nmhandle_t *handle);
/*%<
* Returns the handle's underlying socket type.
*
* Requires:
* \li 'handle' is a valid netmgr handle object.
*/
bool
isc_nm_has_encryption(const isc_nmhandle_t *handle);
/*%<
* Returns 'true' iff the handle's underlying transport does encryption.
*
* Requires:
* \li 'handle' is a valid netmgr handle object.
*/
void
isc_nm_task_enqueue(isc_nm_t *mgr, isc_task_t *task, int threadid);
/*%<

View file

@ -122,3 +122,23 @@ typedef enum {
isc_statsformat_xml,
isc_statsformat_json
} isc_statsformat_t;
typedef enum isc_nmsocket_type {
isc_nm_nonesocket = 0,
isc_nm_udpsocket = 1 << 1,
isc_nm_tcpsocket = 1 << 2,
isc_nm_tcpdnssocket = 1 << 3,
isc_nm_tlssocket = 1 << 4,
isc_nm_tlsdnssocket = 1 << 5,
isc_nm_httpsocket = 1 << 6,
isc_nm_maxsocket,
isc_nm_udplistener, /* Aggregate of nm_udpsocks */
isc_nm_tcplistener,
isc_nm_tlslistener,
isc_nm_tcpdnslistener,
isc_nm_tlsdnslistener,
isc_nm_httplistener
} isc_nmsocket_type;
typedef isc_nmsocket_type isc_nmsocket_type_t;

View file

@ -2863,6 +2863,22 @@ isc__nm_http_set_maxage(isc_nmhandle_t *handle, const uint32_t ttl) {
sock->h2.min_ttl = ttl;
}
bool
isc__nm_http_has_encryption(const isc_nmhandle_t *handle) {
isc_nm_http_session_t *session;
isc_nmsocket_t *sock;
REQUIRE(VALID_NMHANDLE(handle));
REQUIRE(VALID_NMSOCK(handle->sock));
sock = handle->sock;
session = sock->h2.session;
INSIST(VALID_HTTP2_SESSION(session));
return (isc_nm_socket_type(session->handle) == isc_nm_tlssocket);
}
static const bool base64url_validation_table[256] = {
false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false,

View file

@ -709,21 +709,6 @@ struct isc_nm {
#endif
};
typedef enum isc_nmsocket_type {
isc_nm_udpsocket,
isc_nm_udplistener, /* Aggregate of nm_udpsocks */
isc_nm_tcpsocket,
isc_nm_tcplistener,
isc_nm_tcpdnslistener,
isc_nm_tcpdnssocket,
isc_nm_tlslistener,
isc_nm_tlssocket,
isc_nm_tlsdnslistener,
isc_nm_tlsdnssocket,
isc_nm_httplistener,
isc_nm_httpsocket
} isc_nmsocket_type;
/*%
* A universal structure for either a single socket or a group of
* dup'd/SO_REUSE_PORT-using sockets listening on the same interface.
@ -1710,6 +1695,9 @@ isc__nm_http_bad_request(isc_nmhandle_t *handle);
* socket
*/
bool
isc__nm_http_has_encryption(const isc_nmhandle_t *handle);
void
isc__nm_http_set_maxage(isc_nmhandle_t *handle, const uint32_t ttl);

View file

@ -3448,14 +3448,6 @@ isc_nm_xfr_allowed(isc_nmhandle_t *handle) {
return (false);
}
bool
isc_nm_is_tlsdns_handle(isc_nmhandle_t *handle) {
REQUIRE(VALID_NMHANDLE(handle));
REQUIRE(VALID_NMSOCK(handle->sock));
return (handle->sock->type == isc_nm_tlsdnssocket);
}
bool
isc_nm_is_http_handle(isc_nmhandle_t *handle) {
REQUIRE(VALID_NMHANDLE(handle));
@ -3500,6 +3492,36 @@ isc_nm_set_maxage(isc_nmhandle_t *handle, const uint32_t ttl) {
}
}
isc_nmsocket_type
isc_nm_socket_type(const isc_nmhandle_t *handle) {
REQUIRE(VALID_NMHANDLE(handle));
REQUIRE(VALID_NMSOCK(handle->sock));
return (handle->sock->type);
}
bool
isc_nm_has_encryption(const isc_nmhandle_t *handle) {
REQUIRE(VALID_NMHANDLE(handle));
REQUIRE(VALID_NMSOCK(handle->sock));
switch (handle->sock->type) {
case isc_nm_tlsdnssocket:
#if HAVE_LIBNGHTTP2
case isc_nm_tlssocket:
#endif /* HAVE_LIBNGHTTP2 */
return (true);
#if HAVE_LIBNGHTTP2
case isc_nm_httpsocket:
return (isc__nm_http_has_encryption(handle));
#endif /* HAVE_LIBNGHTTP2 */
default:
return (false);
};
return (false);
}
#ifdef NETMGR_TRACE
/*
* Dump all active sockets in netmgr. We output to stderr

View file

@ -627,7 +627,7 @@ cfg_acl_fromconfig(const cfg_obj_t *caml, const cfg_obj_t *cctx,
}
isc_result_t
cfg_acl_fromconfig2(const cfg_obj_t *caml, const cfg_obj_t *cctx,
cfg_acl_fromconfig2(const cfg_obj_t *acl_data, const cfg_obj_t *cctx,
isc_log_t *lctx, cfg_aclconfctx_t *ctx, isc_mem_t *mctx,
unsigned int nest_level, uint16_t family,
dns_acl_t **target) {
@ -638,6 +638,10 @@ cfg_acl_fromconfig2(const cfg_obj_t *caml, const cfg_obj_t *cctx,
dns_iptable_t *iptab;
int new_nest_level = 0;
bool setpos;
const cfg_obj_t *caml = NULL;
const cfg_obj_t *obj_acl_tuple = NULL;
const cfg_obj_t *obj_port = NULL, *obj_transport = NULL;
bool is_tuple = false;
if (nest_level != 0) {
new_nest_level = nest_level - 1;
@ -647,6 +651,20 @@ cfg_acl_fromconfig2(const cfg_obj_t *caml, const cfg_obj_t *cctx,
REQUIRE(target != NULL);
REQUIRE(*target == NULL || DNS_ACL_VALID(*target));
REQUIRE(acl_data != NULL);
if (cfg_obj_islist(acl_data)) {
caml = acl_data;
} else {
INSIST(cfg_obj_istuple(acl_data));
caml = cfg_tuple_get(acl_data, "aml");
INSIST(caml != NULL);
obj_acl_tuple = cfg_tuple_get(acl_data, "port-transport");
INSIST(obj_acl_tuple != NULL);
obj_port = cfg_tuple_get(obj_acl_tuple, "port");
obj_transport = cfg_tuple_get(obj_acl_tuple, "transport");
is_tuple = true;
}
if (*target != NULL) {
/*
* If target already points to an ACL, then we're being
@ -681,6 +699,54 @@ cfg_acl_fromconfig2(const cfg_obj_t *caml, const cfg_obj_t *cctx,
}
}
if (is_tuple) {
uint16_t port = 0;
uint32_t transports = 0;
bool encrypted = false;
if (obj_port != NULL && cfg_obj_isuint32(obj_port)) {
port = (uint16_t)cfg_obj_asuint32(obj_port);
}
if (obj_transport != NULL && cfg_obj_isstring(obj_transport)) {
if (strcasecmp(cfg_obj_asstring(obj_transport),
"udp") == 0) {
transports = isc_nm_udpsocket;
encrypted = false;
} else if (strcasecmp(cfg_obj_asstring(obj_transport),
"tcp") == 0) {
transports = isc_nm_tcpdnssocket;
encrypted = false;
} else if (strcasecmp(cfg_obj_asstring(obj_transport),
"udp-tcp") == 0) {
/* Good ol' DNS over port 53 */
transports = isc_nm_tcpdnssocket |
isc_nm_udpsocket;
encrypted = false;
} else if (strcasecmp(cfg_obj_asstring(obj_transport),
"tls") == 0) {
transports = isc_nm_tlsdnssocket;
encrypted = true;
} else if (strcasecmp(cfg_obj_asstring(obj_transport),
"http") == 0) {
transports = isc_nm_httpsocket;
encrypted = true;
} else if (strcasecmp(cfg_obj_asstring(obj_transport),
"http-plain") == 0) {
transports = isc_nm_httpsocket;
encrypted = false;
} else {
result = ISC_R_FAILURE;
goto cleanup;
}
}
if (port != 0 || transports != 0) {
dns_acl_add_port_transports(dacl, port, transports,
encrypted, false);
}
}
de = dacl->elements;
for (elt = cfg_list_first(caml); elt != NULL; elt = cfg_list_next(elt))
{
@ -787,6 +853,12 @@ cfg_acl_fromconfig2(const cfg_obj_t *caml, const cfg_obj_t *cctx,
if (de->nestedacl != NULL) {
dns_acl_detach(&de->nestedacl);
}
/*
* Merge the port-transports entries from the
* nested ACL into its parent.
*/
dns_acl_merge_ports_transports(dacl, inneracl,
!neg);
dns_acl_attach(inneracl, &de->nestedacl);
dns_acl_detach(&inneracl);
/* Fall through. */

View file

@ -185,6 +185,39 @@ static cfg_type_t cfg_type_listenon = { "listenon", cfg_parse_tuple,
/*% acl */
/*
* Encrypted transfer related definitions
*/
static cfg_tuplefielddef_t cfg_transport_acl_tuple_fields[] = {
{ "port", &cfg_type_optional_port, 0 },
{ "transport", &cfg_type_astring, 0 },
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_transport_acl_tuple = {
"transport-acl tuple", cfg_parse_kv_tuple,
cfg_print_kv_tuple, cfg_doc_kv_tuple,
&cfg_rep_tuple, cfg_transport_acl_tuple_fields
};
static cfg_tuplefielddef_t cfg_transport_acl_fields[] = {
{ "port-transport", &cfg_transport_acl_tuple, 0 },
{ "aml", &cfg_type_bracketed_aml, 0 },
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_transport_acl = {
"transport-acl", cfg_parse_tuple, cfg_print_tuple,
cfg_doc_tuple, &cfg_rep_tuple, cfg_transport_acl_fields
};
/*
* NOTE: To enable syntax which allows specifying port and protocol,
* replace 'cfg_type_bracketed_aml' with
* 'cfg_type_transport_acl'.
*
* Example: acl port 853 protocol tls { ... };
*/
static cfg_tuplefielddef_t acl_fields[] = { { "name", &cfg_type_astring, 0 },
{ "value", &cfg_type_bracketed_aml,
0 },
@ -2174,6 +2207,13 @@ static cfg_clausedef_t dnssecpolicy_clauses[] = {
* Note: CFG_ZONE_* options indicate in which zone types this clause is
* legal.
*/
/*
* NOTE: To enable syntax which allows specifying port and protocol
* within 'allow-*' clauses, replace 'cfg_type_bracketed_aml' with
* 'cfg_type_transport_acl'.
*
* Example: allow-transfer port 853 protocol tls { ... };
*/
static cfg_clausedef_t zone_clauses[] = {
{ "allow-notify", &cfg_type_bracketed_aml,
CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
@ -2183,7 +2223,7 @@ static cfg_clausedef_t zone_clauses[] = {
{ "allow-query-on", &cfg_type_bracketed_aml,
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
CFG_ZONE_STUB | CFG_ZONE_REDIRECT | CFG_ZONE_STATICSTUB },
{ "allow-transfer", &cfg_type_bracketed_aml,
{ "allow-transfer", &cfg_type_transport_acl,
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
{ "allow-update", &cfg_type_bracketed_aml, CFG_ZONE_PRIMARY },
{ "allow-update-forwarding", &cfg_type_bracketed_aml,

View file

@ -2553,6 +2553,7 @@ ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
dns_aclenv_t *env = client->manager->aclenv;
isc_netaddr_t tmpnetaddr;
int match;
isc_sockaddr_t local;
if (acl == NULL) {
if (default_allow) {
@ -2567,7 +2568,13 @@ ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
netaddr = &tmpnetaddr;
}
result = dns_acl_match(netaddr, client->signer, acl, env, &match, NULL);
local = isc_nmhandle_localaddr(client->handle);
result = dns_acl_match_port_transport(
netaddr, isc_sockaddr_getport(&local),
isc_nm_socket_type(client->handle),
isc_nm_has_encryption(client->handle), client->signer, acl, env,
&match, NULL);
if (result != ISC_R_SUCCESS) {
goto deny; /* Internal error, already logged. */
}

View file

@ -12064,8 +12064,9 @@ ns_query_start(ns_client_t *client, isc_nmhandle_t *handle) {
query_error(client, DNS_R_NOTIMP, __LINE__);
return;
}
if (isc_nm_is_tlsdns_handle(handle) &&
!isc_nm_xfr_allowed(handle)) {
if (isc_nm_socket_type(handle) == isc_nm_tlsdnssocket &&
!isc_nm_xfr_allowed(handle))
{
/*
* Currently this code is here for DoT, which
* has more complex requirements for zone

View file

@ -823,6 +823,11 @@
./bin/tests/system/tools/clean.sh SH 2017,2018,2019,2020,2021
./bin/tests/system/tools/setup.sh SH 2019,2020,2021
./bin/tests/system/tools/tests.sh SH 2017,2018,2019,2020,2021
./bin/tests/system/transport-acl/clean.sh SH 2021
./bin/tests/system/transport-acl/self-signed-cert.pem X 2021
./bin/tests/system/transport-acl/self-signed-key.pem X 2021
./bin/tests/system/transport-acl/setup.sh SH 2021
./bin/tests/system/transport-acl/tests.sh SH 2021
./bin/tests/system/tsig/ans2/ans.pl PERL 2020,2021
./bin/tests/system/tsig/badlocation X 2020,2021
./bin/tests/system/tsig/badtime X 2020,2021