From 07cf827b0b5d98f4f21ce354d9f0460eb7c1ff2a Mon Sep 17 00:00:00 2001 From: Artem Boldariev Date: Mon, 15 Nov 2021 17:42:15 +0200 Subject: [PATCH 1/8] Add isc_nm_socket_type() This commit adds an isc_nm_socket_type() function which can be used to obtain a handle's socket type. This change obsoletes isc_nm_is_tlsdns_handle() and isc_nm_is_http_handle(). However, it was decided to keep the latter as we eventually might end up supporting multiple HTTP versions. --- bin/dig/dighost.c | 2 +- lib/isc/include/isc/netmgr.h | 11 +++++++++-- lib/isc/include/isc/types.h | 20 ++++++++++++++++++++ lib/isc/netmgr/netmgr-int.h | 15 --------------- lib/isc/netmgr/netmgr.c | 16 ++++++++-------- lib/ns/query.c | 5 +++-- 6 files changed, 41 insertions(+), 28 deletions(-) diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 62fc949b39..38f8021ad7 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -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 " diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h index f662421a55..4b17006d28 100644 --- a/lib/isc/include/isc/netmgr.h +++ b/lib/isc/include/isc/netmgr.h @@ -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,15 @@ 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. + */ + void isc_nm_task_enqueue(isc_nm_t *mgr, isc_task_t *task, int threadid); /*%< diff --git a/lib/isc/include/isc/types.h b/lib/isc/include/isc/types.h index b68365cd93..eb39ed8204 100644 --- a/lib/isc/include/isc/types.h +++ b/lib/isc/include/isc/types.h @@ -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; diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index a281fbde76..649017e522 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -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. diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index e2d57f0ac1..97b9f5bb25 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -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,14 @@ 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); +} + #ifdef NETMGR_TRACE /* * Dump all active sockets in netmgr. We output to stderr diff --git a/lib/ns/query.c b/lib/ns/query.c index bf95b49f5a..71a65d4894 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -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 From f0e18f3927744571f9cc053c15eada7b9ae6fd61 Mon Sep 17 00:00:00 2001 From: Artem Boldariev Date: Tue, 16 Nov 2021 13:35:37 +0200 Subject: [PATCH 2/8] Add isc_nm_has_encryption() This commit adds an isc_nm_has_encryption() function intended to check if a given handle is backed by a connection which uses encryption. --- lib/isc/include/isc/netmgr.h | 9 +++++++++ lib/isc/netmgr/http.c | 16 ++++++++++++++++ lib/isc/netmgr/netmgr-int.h | 3 +++ lib/isc/netmgr/netmgr.c | 22 ++++++++++++++++++++++ 4 files changed, 50 insertions(+) diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h index 4b17006d28..94fed339a3 100644 --- a/lib/isc/include/isc/netmgr.h +++ b/lib/isc/include/isc/netmgr.h @@ -654,6 +654,15 @@ isc_nm_socket_type(const isc_nmhandle_t *handle); * \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); /*%< diff --git a/lib/isc/netmgr/http.c b/lib/isc/netmgr/http.c index 466ae5497a..539fef6fd3 100644 --- a/lib/isc/netmgr/http.c +++ b/lib/isc/netmgr/http.c @@ -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, diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index 649017e522..da892b8415 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -1695,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); diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index 97b9f5bb25..3404d19ba0 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -3500,6 +3500,28 @@ isc_nm_socket_type(const isc_nmhandle_t *handle) { 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 From af2d065c21e9bc9589492a658e102b14015adfc4 Mon Sep 17 00:00:00 2001 From: Artem Boldariev Date: Thu, 4 Nov 2021 16:52:49 +0200 Subject: [PATCH 3/8] Extend ACL syntax handling code with 'port' and 'transport' options This commit extends ACL syntax handling code with 'port' and 'transport' options. Currently, the extended syntax is available only for allow-transfer options. --- bin/named/named.conf.rst | 12 +++++++---- doc/man/named.conf.5in | 12 +++++++---- doc/misc/master.zoneopt | 2 +- doc/misc/master.zoneopt.rst | 2 +- doc/misc/mirror.zoneopt | 2 +- doc/misc/mirror.zoneopt.rst | 2 +- doc/misc/options | 12 +++++++---- doc/misc/options.active | 12 +++++++---- doc/misc/options.grammar.rst | 3 ++- doc/misc/slave.zoneopt | 2 +- doc/misc/slave.zoneopt.rst | 2 +- lib/bind9/check.c | 41 +++++++++++++++++++++++++++++++++++ lib/isccfg/aclconf.c | 18 +++++++++++++++- lib/isccfg/namedconf.c | 42 +++++++++++++++++++++++++++++++++++- 14 files changed, 139 insertions(+), 25 deletions(-) diff --git a/bin/named/named.conf.rst b/bin/named/named.conf.rst index 28a39c45e0..644c70430a 100644 --- a/bin/named/named.conf.rst +++ b/bin/named/named.conf.rst @@ -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 ] { ( diff --git a/doc/man/named.conf.5in b/doc/man/named.conf.5in index de092a77df..1e285a2d0e 100644 --- a/doc/man/named.conf.5in +++ b/doc/man/named.conf.5in @@ -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 ] { ( diff --git a/doc/misc/master.zoneopt b/doc/misc/master.zoneopt index e51eee9bcc..69134fd1f4 100644 --- a/doc/misc/master.zoneopt +++ b/doc/misc/master.zoneopt @@ -2,7 +2,7 @@ zone [ ] { type ( master | primary ); allow-query { ; ... }; allow-query-on { ; ... }; - allow-transfer { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; allow-update { ; ... }; also-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; alt-transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; diff --git a/doc/misc/master.zoneopt.rst b/doc/misc/master.zoneopt.rst index 985e2b404f..597a8dbdd9 100644 --- a/doc/misc/master.zoneopt.rst +++ b/doc/misc/master.zoneopt.rst @@ -4,7 +4,7 @@ type ( master | primary ); allow-query { ; ... }; allow-query-on { ; ... }; - allow-transfer { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; allow-update { ; ... }; also-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; alt-transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; diff --git a/doc/misc/mirror.zoneopt b/doc/misc/mirror.zoneopt index 50556fc9ec..a21182789d 100644 --- a/doc/misc/mirror.zoneopt +++ b/doc/misc/mirror.zoneopt @@ -3,7 +3,7 @@ zone [ ] { allow-notify { ; ... }; allow-query { ; ... }; allow-query-on { ; ... }; - allow-transfer { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; allow-update-forwarding { ; ... }; also-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; alt-transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; diff --git a/doc/misc/mirror.zoneopt.rst b/doc/misc/mirror.zoneopt.rst index d481248fb0..668207601c 100644 --- a/doc/misc/mirror.zoneopt.rst +++ b/doc/misc/mirror.zoneopt.rst @@ -5,7 +5,7 @@ allow-notify { ; ... }; allow-query { ; ... }; allow-query-on { ; ... }; - allow-transfer { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; allow-update-forwarding { ; ... }; also-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; alt-transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; diff --git a/doc/misc/options b/doc/misc/options index 86967657ae..b62967ef0c 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -90,7 +90,8 @@ options { allow-query-on { ; ... }; allow-recursion { ; ... }; allow-recursion-on { ; ... }; - allow-transfer { ; ... }; + allow-transfer [ port ] [ transport ] { + ; ... }; allow-update { ; ... }; allow-update-forwarding { ; ... }; also-notify [ port ] [ dscp ] { ( @@ -484,7 +485,8 @@ view [ ] { allow-query-on { ; ... }; allow-recursion { ; ... }; allow-recursion-on { ; ... }; - allow-transfer { ; ... }; + allow-transfer [ port ] [ transport ] { + ; ... }; allow-update { ; ... }; allow-update-forwarding { ; ... }; also-notify [ port ] [ dscp ] { ( @@ -770,7 +772,8 @@ view [ ] { allow-notify { ; ... }; allow-query { ; ... }; allow-query-on { ; ... }; - allow-transfer { ; ... }; + allow-transfer [ port ] [ transport ] { + ; ... }; allow-update { ; ... }; allow-update-forwarding { ; ... }; also-notify [ port ] [ dscp ] { ( @@ -886,7 +889,8 @@ zone [ ] { allow-notify { ; ... }; allow-query { ; ... }; allow-query-on { ; ... }; - allow-transfer { ; ... }; + allow-transfer [ port ] [ transport ] { + ; ... }; allow-update { ; ... }; allow-update-forwarding { ; ... }; also-notify [ port ] [ dscp ] { ( diff --git a/doc/misc/options.active b/doc/misc/options.active index bd4ceb26ae..a3e2fbe3f0 100644 --- a/doc/misc/options.active +++ b/doc/misc/options.active @@ -89,7 +89,8 @@ options { allow-query-on { ; ... }; allow-recursion { ; ... }; allow-recursion-on { ; ... }; - allow-transfer { ; ... }; + allow-transfer [ port ] [ transport ] { + ; ... }; allow-update { ; ... }; allow-update-forwarding { ; ... }; also-notify [ port ] [ dscp ] { ( @@ -481,7 +482,8 @@ view [ ] { allow-query-on { ; ... }; allow-recursion { ; ... }; allow-recursion-on { ; ... }; - allow-transfer { ; ... }; + allow-transfer [ port ] [ transport ] { + ; ... }; allow-update { ; ... }; allow-update-forwarding { ; ... }; also-notify [ port ] [ dscp ] { ( @@ -765,7 +767,8 @@ view [ ] { allow-notify { ; ... }; allow-query { ; ... }; allow-query-on { ; ... }; - allow-transfer { ; ... }; + allow-transfer [ port ] [ transport ] { + ; ... }; allow-update { ; ... }; allow-update-forwarding { ; ... }; also-notify [ port ] [ dscp ] { ( @@ -880,7 +883,8 @@ zone [ ] { allow-notify { ; ... }; allow-query { ; ... }; allow-query-on { ; ... }; - allow-transfer { ; ... }; + allow-transfer [ port ] [ transport ] { + ; ... }; allow-update { ; ... }; allow-update-forwarding { ; ... }; also-notify [ port ] [ dscp ] { ( diff --git a/doc/misc/options.grammar.rst b/doc/misc/options.grammar.rst index 2c440420f1..8e69a09686 100644 --- a/doc/misc/options.grammar.rst +++ b/doc/misc/options.grammar.rst @@ -9,7 +9,8 @@ allow-query-on { ; ... }; allow-recursion { ; ... }; allow-recursion-on { ; ... }; - allow-transfer { ; ... }; + allow-transfer [ port ] [ transport ] { + ; ... }; allow-update { ; ... }; allow-update-forwarding { ; ... }; also-notify [ port ] [ dscp ] { ( diff --git a/doc/misc/slave.zoneopt b/doc/misc/slave.zoneopt index be63c04e10..5fbbc065bc 100644 --- a/doc/misc/slave.zoneopt +++ b/doc/misc/slave.zoneopt @@ -3,7 +3,7 @@ zone [ ] { allow-notify { ; ... }; allow-query { ; ... }; allow-query-on { ; ... }; - allow-transfer { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; allow-update-forwarding { ; ... }; also-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; alt-transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; diff --git a/doc/misc/slave.zoneopt.rst b/doc/misc/slave.zoneopt.rst index 93996f47d8..3a603a044c 100644 --- a/doc/misc/slave.zoneopt.rst +++ b/doc/misc/slave.zoneopt.rst @@ -5,7 +5,7 @@ allow-notify { ; ... }; allow-query { ; ... }; allow-query-on { ; ... }; - allow-transfer { ; ... }; + allow-transfer [ port ] [ transport ] { ; ... }; allow-update-forwarding { ; ... }; also-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; alt-transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; diff --git a/lib/bind9/check.c b/lib/bind9/check.c index d127b6efa5..1130983732 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -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); } diff --git a/lib/isccfg/aclconf.c b/lib/isccfg/aclconf.c index f748199b74..9f2fea573b 100644 --- a/lib/isccfg/aclconf.c +++ b/lib/isccfg/aclconf.c @@ -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,9 @@ 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_proto = NULL; if (nest_level != 0) { new_nest_level = nest_level - 1; @@ -647,6 +650,19 @@ 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, "acl"); + 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_proto = cfg_tuple_get(obj_acl_tuple, "protocol"); + } + if (*target != NULL) { /* * If target already points to an ACL, then we're being diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 4ba4b0a17c..86d1bf16d9 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -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, From 0ee6f66cbddb69b599be4b191ec8c5531e9e9e2f Mon Sep 17 00:00:00 2001 From: Artem Boldariev Date: Fri, 12 Nov 2021 16:53:13 +0200 Subject: [PATCH 4/8] Integrate extended ACLs syntax featuring 'port' and 'transport' opts This commit completes the integration of the new, extended ACL syntax featuring 'port' and 'transport' options. The runtime presentation and ACL loading code are extended to allow the syntax to be used beyond the 'allow-transfer' option (e.g. in 'acl' definitions and other 'allow-*' options) and can be used to ultimately extend the ACL support with transport-only ACLs (e.g. 'transport-acl tls-acl port 853 transport tls'). But, due to fundamental nature of such a change, it has not been completed as a part of 9.17.X release series due to it being close to 9.18 stable release status. That means that we do not have enough time to fully test it. The complete integration is planned as a part of 9.19.X release series. The code was manually verified to work as expected by temporarily enabling the extended syntax for 'acl' statements and 'allow-query' options, including ACL merging, negated ACLs. --- lib/dns/acl.c | 122 ++++++++++++++++++++++++++++++++++++++ lib/dns/include/dns/acl.h | 52 ++++++++++++++++ lib/isccfg/aclconf.c | 62 ++++++++++++++++++- lib/ns/client.c | 9 ++- 4 files changed, 241 insertions(+), 4 deletions(-) diff --git a/lib/dns/acl.c b/lib/dns/acl.c index 33fcefef0a..a3cd6d4214 100644 --- a/lib/dns/acl.c +++ b/lib/dns/acl.c @@ -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); + } +} diff --git a/lib/dns/include/dns/acl.h b/lib/dns/include/dns/acl.h index e122340d1b..51678eee3d 100644 --- a/lib/dns/include/dns/acl.h +++ b/lib/dns/include/dns/acl.h @@ -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 diff --git a/lib/isccfg/aclconf.c b/lib/isccfg/aclconf.c index 9f2fea573b..e74fa3b918 100644 --- a/lib/isccfg/aclconf.c +++ b/lib/isccfg/aclconf.c @@ -640,7 +640,8 @@ cfg_acl_fromconfig2(const cfg_obj_t *acl_data, const cfg_obj_t *cctx, bool setpos; const cfg_obj_t *caml = NULL; const cfg_obj_t *obj_acl_tuple = NULL; - const cfg_obj_t *obj_port = NULL, *obj_proto = 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; @@ -655,12 +656,13 @@ cfg_acl_fromconfig2(const cfg_obj_t *acl_data, const cfg_obj_t *cctx, caml = acl_data; } else { INSIST(cfg_obj_istuple(acl_data)); - caml = cfg_tuple_get(acl_data, "acl"); + 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_proto = cfg_tuple_get(obj_acl_tuple, "protocol"); + obj_transport = cfg_tuple_get(obj_acl_tuple, "transport"); + is_tuple = true; } if (*target != NULL) { @@ -697,6 +699,54 @@ cfg_acl_fromconfig2(const cfg_obj_t *acl_data, 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)) { @@ -803,6 +853,12 @@ cfg_acl_fromconfig2(const cfg_obj_t *acl_data, 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. */ diff --git a/lib/ns/client.c b/lib/ns/client.c index 0825fc3e30..f598387729 100644 --- a/lib/ns/client.c +++ b/lib/ns/client.c @@ -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. */ } From 3cd2ffc01f95aae4d8b90f834cbba2c0171c23e7 Mon Sep 17 00:00:00 2001 From: Artem Boldariev Date: Mon, 22 Nov 2021 15:31:15 +0200 Subject: [PATCH 5/8] Extend the 'doth' system test to test extended allow-transfer option This commit extends the 'doth' system test to verify that the new extended 'allow-transfer' option syntax featuring 'port' and 'transport' parameters is supported and works as expected. That is, it restricts the primary server to allow zone transfers only via XoT. Additionally to that, it extends the 'checkonf' test with more configuration file examples featuring the new syntax. --- .../bad-dot-allow-transfer-bad-port.conf | 16 +++++++ .../bad-dot-allow-transfer-bad-proto-1.conf | 16 +++++++ .../bad-dot-allow-transfer-bad-proto-2.conf | 16 +++++++ .../bad-dot-allow-transfer-bad-proto-3.conf | 16 +++++++ .../bad-dot-allow-transfer-bad-proto-4.conf | 16 +++++++ .../good-dot-allow-transfer-encrypted.conf | 47 +++++++++++++++++++ bin/tests/system/doth/ns1/named.conf.in | 4 +- bin/tests/system/doth/tests.sh | 23 +++++++++ 8 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 bin/tests/system/checkconf/bad-dot-allow-transfer-bad-port.conf create mode 100644 bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-1.conf create mode 100644 bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-2.conf create mode 100644 bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-3.conf create mode 100644 bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-4.conf create mode 100644 bin/tests/system/checkconf/good-dot-allow-transfer-encrypted.conf diff --git a/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-port.conf b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-port.conf new file mode 100644 index 0000000000..4534126ddf --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-port.conf @@ -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; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-1.conf b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-1.conf new file mode 100644 index 0000000000..46bec68e48 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-1.conf @@ -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; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-2.conf b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-2.conf new file mode 100644 index 0000000000..b52929129b --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-2.conf @@ -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; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-3.conf b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-3.conf new file mode 100644 index 0000000000..e94c4b56a4 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-3.conf @@ -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; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-4.conf b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-4.conf new file mode 100644 index 0000000000..0bec62f113 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-4.conf @@ -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; }; +}; diff --git a/bin/tests/system/checkconf/good-dot-allow-transfer-encrypted.conf b/bin/tests/system/checkconf/good-dot-allow-transfer-encrypted.conf new file mode 100644 index 0000000000..96ec4cd857 --- /dev/null +++ b/bin/tests/system/checkconf/good-dot-allow-transfer-encrypted.conf @@ -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; }; +}; diff --git a/bin/tests/system/doth/ns1/named.conf.in b/bin/tests/system/doth/ns1/named.conf.in index a78e30c40f..0cb6b41ddd 100644 --- a/bin/tests/system/doth/ns1/named.conf.in +++ b/bin/tests/system/doth/ns1/named.conf.in @@ -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; }; }; diff --git a/bin/tests/system/doth/tests.sh b/bin/tests/system/doth/tests.sh index ee25102f2a..166f0410f1 100644 --- a/bin/tests/system/doth/tests.sh +++ b/bin/tests/system/doth/tests.sh @@ -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 From 792ff02045492d007dcb16aae6405e2b470739d4 Mon Sep 17 00:00:00 2001 From: Artem Boldariev Date: Tue, 23 Nov 2021 15:04:51 +0200 Subject: [PATCH 6/8] Mention that the allow-transfer option has been extended This commit updates both the reference manual and release notes with the information that 'allow-transfer' has been extended with additional "port" and "transport" options. --- doc/arm/reference.rst | 8 ++++++++ doc/notes/notes-current.rst | 8 +++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst index 0562bbe627..c69148989c 100644 --- a/doc/arm/reference.rst +++ b/doc/arm/reference.rst @@ -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 diff --git a/doc/notes/notes-current.rst b/doc/notes/notes-current.rst index 9fe3c2bfef..8932ffcca1 100644 --- a/doc/notes/notes-current.rst +++ b/doc/notes/notes-current.rst @@ -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 ~~~~~~~~~ From 758f748d5e3a6165309f5ea947992197da8b6d8d Mon Sep 17 00:00:00 2001 From: Artem Boldariev Date: Tue, 23 Nov 2021 17:11:44 +0200 Subject: [PATCH 7/8] Modify CHANGES [GL #2776] Mention in the CHANGES file that the allow-transfer options has been extended with 'port' and 'transport' options. --- CHANGES | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index ca80b0d14b..94801c811e 100644 --- a/CHANGES +++ b/CHANGES @@ -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] From 7f73e68730db0cecea6b73685db2cb4e5006ca29 Mon Sep 17 00:00:00 2001 From: Artem Boldariev Date: Mon, 29 Nov 2021 12:50:35 +0200 Subject: [PATCH 8/8] Add transport-acl system test This commit adds a new system-test: transport-acl system test. It is intended to test the new, extended syntax for ACLs, the one where port or transport protocol can be specified. Currently, it includes the tests only using allow-transfer statement, as this extended syntax is used only there, at least for now. --- bin/tests/system/Makefile.am | 1 + bin/tests/system/transport-acl/clean.sh | 22 +++ .../system/transport-acl/ns1/named.conf.in | 127 ++++++++++++++++++ .../system/transport-acl/self-signed-cert.pem | 28 ++++ .../system/transport-acl/self-signed-key.pem | 40 ++++++ bin/tests/system/transport-acl/setup.sh | 19 +++ bin/tests/system/transport-acl/tests.sh | 120 +++++++++++++++++ util/copyrights | 5 + 8 files changed, 362 insertions(+) create mode 100644 bin/tests/system/transport-acl/clean.sh create mode 100644 bin/tests/system/transport-acl/ns1/named.conf.in create mode 100644 bin/tests/system/transport-acl/self-signed-cert.pem create mode 100644 bin/tests/system/transport-acl/self-signed-key.pem create mode 100644 bin/tests/system/transport-acl/setup.sh create mode 100644 bin/tests/system/transport-acl/tests.sh diff --git a/bin/tests/system/Makefile.am b/bin/tests/system/Makefile.am index f47678ba59..5fe5b2d833 100644 --- a/bin/tests/system/Makefile.am +++ b/bin/tests/system/Makefile.am @@ -157,6 +157,7 @@ TESTS += \ synthfromdnssec \ tkey \ tools \ + transport-acl \ tsig \ tsiggss \ ttl \ diff --git a/bin/tests/system/transport-acl/clean.sh b/bin/tests/system/transport-acl/clean.sh new file mode 100644 index 0000000000..bd6739e94e --- /dev/null +++ b/bin/tests/system/transport-acl/clean.sh @@ -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.* diff --git a/bin/tests/system/transport-acl/ns1/named.conf.in b/bin/tests/system/transport-acl/ns1/named.conf.in new file mode 100644 index 0000000000..e46130f024 --- /dev/null +++ b/bin/tests/system/transport-acl/ns1/named.conf.in @@ -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; }; +}; diff --git a/bin/tests/system/transport-acl/self-signed-cert.pem b/bin/tests/system/transport-acl/self-signed-cert.pem new file mode 100644 index 0000000000..d56935317f --- /dev/null +++ b/bin/tests/system/transport-acl/self-signed-cert.pem @@ -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----- diff --git a/bin/tests/system/transport-acl/self-signed-key.pem b/bin/tests/system/transport-acl/self-signed-key.pem new file mode 100644 index 0000000000..5d9748bac7 --- /dev/null +++ b/bin/tests/system/transport-acl/self-signed-key.pem @@ -0,0 +1,40 @@ +-----BEGIN PRIVATE KEY----- +MIIG/AIBADANBgkqhkiG9w0BAQEFAASCBuYwggbiAgEAAoIBgQDPIc2EnnUBWo7I +ySlZ2dwXlizhlCyTtosUGf7zJwJOquWuiRUk+Q2FQBvOEvBis7MGYmzTbiiZ7rkD +t5gRNvj4qHPr8bXsMZc23ENhGioG8eSFXs8x7UFGMFlFHUr+1YijlXmiPY716qWF +G27S6IElZDwfv6FlNVruMv05F3OMBKgcUMfj+JDZ47LQj+6+RzJLwakIJqHea46i +xaIbSEGxIY0gWqCvrXdub1lL3xv4rHboisedrQuJNwgZwTiH74JDZiZOUYd0bn24 +sgUgrYAXB98KfVUgcqgu66BUKswZGZtGgproIDZl2zl1O5JRMlZgHoqi730EpIzb +A5pWk7BwrM4CAfUTwOH9OyletrhbHTrtCuPMlwZxGp2XiBasLk0vj1O0/kp1kBqC +Sw7wmuiDxEapPuY/eARE/OP8/eNli1aki5agKGtaxeevOptg4I9dEkVKRPfW5lYP +h2UcDv2W5C4LvrSC6qWKZyj+p/BQ6Y1tCZ5e+7sPUlHgL2xssOUCAwEAAQKCAYAy +VN9wy2RZKN0rUx5WNAc0QAy13+CZIDFZeBuokCESZpqbN7pImrA7YeGfyKBbC5mE +AqS5F7qL9SNGEPXFsRr8qUpJ2hk/xKke7pT84nO17k9+TRSB6EoFOThn//86Pz8N +qQO+dcDoZtVDq+/ZFiBTqrClclZQlo969C7uEZHFQ1hqUQLRlZP1LkxEO8VivUAu +gmeFkIWi23X0fZuvj3ZPCX0WkI8dQUSVND95nURZv+bBCQAKg4MbG6E/SOFovrzz +ohKK2zqSU+ncfWROYX/ulKMJKIhOKtxkprBnj2nSemTUEf5gDk9oDqsYClGmEcSL +XvNxq3WpVt4u7Fsr1QZ6fh/IYIQnKvI/H0wwYojtzkh3FGdb/K0dnKeoebUqlc9Q +4UwKGshhcbk2130t/zIdd5wnL5uj+xjh0cYSO5JqlcZwXC97SWDmEowCo8M/k8ie +c9cQeIOXUKvT3DvnEh1LAtfI8gW3g9GVHad4k25dQ4ZSiyXsKL2+mOWn+4WmQx0C +gcEA6UqykoDp2j6nfMA+5fEfNOplyXJMyTBxMoaFb+cO8P2qjjKOMyLJewXqW/3g +wWaPcl3dGVCPaqmQxf+fDEarSkDxkroN02YaQy3xdAAZvoUDc00VKq9BFe3TZEuP +7/sN3t3Ey7K5KVyKgh4cGPqSCCXrk3OPCyiRFxWa4wQAXuntT1iXkXGzXuoDPzCH +xWRiM+z3se6PdoPXMbJhuL04b4CIUmHSrGbqtO5bi6IDOksIhaKMFs4c7escSF+7 +jj0zAoHBAONLPcUT9uhzMIXe9BBdRYms65G3VjsTbS8MC/QiR6nl5/evQb0hDp0G +/tbLf9F9QVMA2onhK1mjafHFC4oVrwrLT+VZezKsQm3ICoqOFqxL+6dAu93A2dDA +99YCc6pCrmagaDpA5tz1UwBwA77pl2aMV2g7iIe2p+hmL6dx6Tp8jN+Mu0KXViyT +gPG9LITJQSu13EZgRukNnYu7+L2+NWfyGCbfCJ5/2qXmryjefoboR48sa8jZyUmQ +rf/VAG3phwKBwDE/lqD82+E5tsvMHbsXAtp93Q0AtxsFwe/DnCm6YloXgsjP/Vro +LhZtckMHPko1p3SiQgmVCyGeODTEOMQzqvda7GRoKIEHHeYurbkqSEUC+W5+yEgh +hSDm+uhCV1l26z+wG1pRGWuU4JyFVLMlOmzD7I5NJ9ZYMwDni7H+50EiKvnEHwMS +OKaByjutuAvAnEaP8N48GUcQn/4axSxlraNERAL4KaxBcazOYL8CbaIBswPbA63Q +xySmrGrO4t4tJwKBwGITmnDKv5Tn930cimXxSUsyAWgcGypcpJVTdmj+zbuDCAg5 +aH1qoTqixR38K4hCqwhc6u/p6GHCgLmhU+xelOxsdGo7pUxlRjjGw72ruB7anpk5 +9pamW5aXXZnL7wr9wPFpr+/LB5M6jHk43HTpqLnIPwMsBSrCZ0uBpHh1T7U7/zGL +MVZ3pOiRMWeeQHJ/wQ5SZ906N/7iMCQWlSuSwsq6jS9guABknP1PQC+7ag9edVpT +SaMeTpvewSYOTCQhSwKBwEmZP/Jh76G3bETPSPcIyPB0vgYmYiAftmvtwHzUL14V +dOfNbwXF6WiepSceLbw99LNpMwfRfKBGVDLRhKMqL7QR8ZKNew5AvfXVZ1yDNKu+ +/4hqFLUhsAARsfNofAzvKOtWmghVBzO9TauAyv3prFgjfvDkA+EZ2amDvXChkP/Q +7ck2aIUu9Sr4kPTUigIRlu6c18QQiLobXC7yKx6GhEpJsh9xGHHDJqkG16l+u1ju +bEd5UJArJoST5lff5y7MyQ== +-----END PRIVATE KEY----- diff --git a/bin/tests/system/transport-acl/setup.sh b/bin/tests/system/transport-acl/setup.sh new file mode 100644 index 0000000000..a54dba7732 --- /dev/null +++ b/bin/tests/system/transport-acl/setup.sh @@ -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 diff --git a/bin/tests/system/transport-acl/tests.sh b/bin/tests/system/transport-acl/tests.sh new file mode 100644 index 0000000000..339ad41c58 --- /dev/null +++ b/bin/tests/system/transport-acl/tests.sh @@ -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 diff --git a/util/copyrights b/util/copyrights index 1d43fbd260..1a78494769 100644 --- a/util/copyrights +++ b/util/copyrights @@ -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