rem: usr: Restrict views to the Internet (IN) class

Views could previously be declared in classes other than Internet (IN),
but that support was inconsistent — ``named-checkconf`` accepted configurations
that ``named`` then refused to load.  Views are now restricted to class IN, and
both tools reject any other class.  Configurations declaring a non-IN view
must drop the class to keep working.

Merge branch '5784-improve-class-handling' into 'main'

See merge request isc-projects/bind9!12163
This commit is contained in:
Ondřej Surý 2026-06-08 17:50:38 +02:00
commit edb03e2ee4
31 changed files with 56 additions and 182 deletions

View file

@ -5806,10 +5806,26 @@ get_viewinfo(const cfg_obj_t *vconfig, const char **namep,
classobj = cfg_tuple_get(vconfig, "class");
CHECK(named_config_getclass(classobj, dns_rdataclass_in,
&viewclass));
if (dns_rdataclass_ismeta(viewclass)) {
switch (viewclass) {
case dns_rdataclass_in:
break;
case dns_rdataclass_chaos:
/* allow the builtin _bind view */
if (strcmp(viewname, "_bind") != 0) {
isc_log_write(
NAMED_LOGCATEGORY_GENERAL,
NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
"view '%s': only builtin _bind view is "
"allowed in Chaos (CH) class",
viewname);
CLEANUP(ISC_R_FAILURE);
}
break;
default:
isc_log_write(NAMED_LOGCATEGORY_GENERAL,
NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
"view '%s': class must not be meta",
"view '%s': only Internet (IN) class is "
"allowed",
viewname);
CLEANUP(ISC_R_FAILURE);
}

View file

@ -1,12 +0,0 @@
$TTL 300 ; 5 minutes
@ CH SOA ns root (
2018010100 ; serial
1800 ; refresh (30 minutes)
1800 ; retry (30 minutes)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
NS ns
ns A ch-addr.example. 1001
test A ch-addr.example. 1002
A ch-addr.example. 1003

View file

@ -37,10 +37,3 @@ view main in {
log-report-channel yes;
};
};
view alt chaos {
zone example.chaos chaos {
type primary;
file "chaos.db";
};
};

View file

@ -177,15 +177,6 @@ grep 'a\.example\.com.*A.10\.53\.0\.1' dig.out.test$n >/dev/null && ret=1
[ $ret -eq 0 ] || echo_i "failed"
status=$((status + ret))
n=$((n + 1))
echo_i "check that CHAOS addresses are compared correctly ($n)"
ret=0
$DIG $DIGOPTS @10.53.0.1 +noall +answer ch test.example.chaos >dig.out.test$n || ret=1
lines=$(wc -l <dig.out.test$n)
[ ${lines:-0} -eq 2 ] || ret=1
[ $ret -eq 0 ] || echo_i "failed"
status=$((status + ret))
n=$((n + 1))
echo_i "check that a Report-Channel EDNS option is added to responses ($n)"
ret=0

View file

@ -1,3 +0,0 @@
@ 3600 SOA . . 1 86400 3600 86400 3600
@ 3600 CH NS invalid.
version CH TXT "2"

View file

@ -146,20 +146,6 @@ view "default" {
};
};
view "ch" ch {
# Non-IN class catalog zone
zone "catalog-bad5.example" ch {
type primary;
file "catalog-bad5.example.db";
allow-transfer { any; };
allow-update { any; };
also-notify { 10.53.0.2; };
notify explicit;
};
};
key tsig_key. {
secret "LSAnCU+Z";
algorithm @DEFAULT_HMAC@;

View file

@ -1,6 +0,0 @@
view override_bind chaos {
zone "version.bind" chaos {
type primary;
database "_builtin version";
};
};

View file

@ -0,0 +1,3 @@
view chaos ch {
match-clients { any; };
};

View file

@ -267,12 +267,6 @@ view "fifth" {
};
key-directory ".";
};
view "chaos" chaos {
zone "hostname.bind" chaos {
type primary;
database "_builtin hostname";
};
};
dyndb "name" "library.so" {
this;
\};

View file

@ -22,4 +22,3 @@ dnssec-view1 IN fifth primary
dnssec-view2 IN fifth primary
dnssec-view3 IN fifth primary
dnssec-view4 IN fifth primary
hostname.bind chaos chaos primary

View file

@ -345,16 +345,6 @@ if [ $ret -ne 0 ]; then
fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking that named-checkconf -z skips zone check with alternate databases ($n)"
ret=0
$CHECKCONF -z altdb.conf >checkconf.out$n 2>&1 || ret=1
if [ $ret -ne 0 ]; then
echo_i "failed"
ret=1
fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking that named-checkconf -z skips zone check with DLZ ($n)"
ret=0
@ -742,16 +732,5 @@ if [ $ret != 0 ]; then
fi
status=$((status + ret))
n=$((n + 1))
echo_i "check 'recursion yes;' is warned and disabled in a non-IN view ($n)"
ret=0
$CHECKCONF warn-chaos-recursion.conf >checkconf.out$n 2>&1 || ret=1
grep -F "recursion will be disabled" checkconf.out$n >/dev/null || ret=1
if [ $ret != 0 ]; then
echo_i "failed"
ret=1
fi
status=$((status + ret))
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1

View file

@ -1,12 +0,0 @@
options {
directory ".";
};
view chaos ch {
match-clients { any; };
recursion yes;
zone "." {
type hint;
file "chaos.hints";
};
};

View file

@ -1,4 +0,0 @@
. CH NS ns.root.
ns.root. CH A ns.root. 1
ns.root. CH AAAA \# 1 00

View file

@ -16,16 +16,3 @@ key rndc_key {
controls {
inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
view chaos ch {
match-clients { any; };
recursion yes;
zone "." {
type hint;
file "chaos.db";
};
zone "version.bind" {
type primary;
database "_builtin version";
};
};

View file

@ -1,6 +0,0 @@
$TTL 300
@ CH SOA ns.example. hostmaster.example. 1 3600 1200 604800 300
@ CH NS ns.example.
ns CH TXT "ns"
a CH A target.example. 1
target CH TXT "target"

View file

@ -30,13 +30,3 @@ view default {
};
};
};
view chaos ch {
match-clients { any; };
recursion no;
zone example {
type primary;
file "example.db";
allow-update { any; };
};
};

View file

@ -17,12 +17,3 @@ key rndc_key {
controls {
inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
view chaos ch {
match-clients { any; };
recursion yes;
dnssec-validation no;
forward only;
forwarders port @PORT@ { 10.53.0.2; };
deny-answer-addresses { 0.0.0.0/0; ::/0; };
};

View file

@ -14,6 +14,4 @@
# shellcheck source=conf.sh
. ../conf.sh
cp ns1/chaos.db.in ns1/chaos.db
cp ns2/example.db.in ns2/example.db
cp ns2/localhost.db.in ns2/localhost.db

View file

@ -18,6 +18,7 @@ import isctest
pytestmark = pytest.mark.extra_artifacts(
[
"*/*.db",
"*/*.jnl",
]
)
@ -31,7 +32,7 @@ def test_chaos_recursion():
def test_chaos_auth():
msg = isctest.query.create("a.example.", "A", qclass="CH")
res = isctest.query.udp(msg, "10.53.0.2")
isctest.check.noerror(res)
isctest.check.refused(res)
def test_chaos_forward():

View file

@ -21,6 +21,7 @@ import isctest
pytestmark = pytest.mark.extra_artifacts(
[
"*/*.db",
"*/*.jnl",
]
)

View file

@ -277,7 +277,7 @@ main(int argc, char *argv[]) {
RUNCHECK(dns_requestmgr_create(isc_g_mctx, dispatchmgr, dispatchv4,
NULL, &requestmgr));
dns_view_create(isc_g_mctx, NULL, 0, "_test", &view);
dns_view_create(isc_g_mctx, NULL, dns_rdataclass_in, "_test", &view);
isc_loopmgr_setup(sendqueries, NULL);
isc_loopmgr_teardown(teardown_view, view);

View file

@ -1,5 +0,0 @@
$TTL 3600
@ CHAOS SOA @ @ 1970010100 86400 600 86400 300
@ CHAOS NS @
version CHAOS TXT "CH 1.0"
hostname CHAOS TXT "unknown"

View file

@ -39,21 +39,6 @@ server fd92:7065:b8e:ffff::1000 {
transfer-source-v6 fd92:7065:b8e:ffff::1001;
};
/*
* Must be first view so that there is a CH cache with name
* "globalcache" before the recursive "default"/IN view is configured.
*/
view "class" chaos {
zone "chaostest" CHAOS {
type primary;
file "chaostest.db";
};
};
/*
* Must be second view so that so that we can check we don't attach to the
* "globalcache"/CH cache.
*/
view "default" {
zone "." {
type hint;

View file

@ -783,12 +783,10 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking REFUSED is returned when querying non existing domain in CH class ($n)"
echo_i "checking REFUSED is returned when querying name in CH class ($n)"
ret=0
dig_with_opts @10.53.0.1 hostname.chaostest txt ch >dig.ns1.out.1.${n} || ret=1
grep "status: NOERROR" dig.ns1.out.1.${n} >/dev/null || ret=1
dig_with_opts @10.53.0.1 id.hostname txt ch >dig.ns1.out.2.${n} || ret=1
grep "status: REFUSED" dig.ns1.out.2.${n} >/dev/null || ret=1
dig_with_opts @10.53.0.1 id.hostname txt ch >dig.ns1.out.${n} || ret=1
grep "status: REFUSED" dig.ns1.out.${n} >/dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))

View file

@ -44,15 +44,3 @@ view "in" {
file "broken5.db";
};
};
view "class10" class10 {
zone "." class10 {
type hint;
file "class10.hints";
};
zone "example." class10 {
type primary;
file "example-class10.db";
};
};

View file

@ -2046,7 +2046,7 @@ setup(void *arg ISC_ATTR_UNUSED) {
isc_g_mctx, dispatchmgr, have_ipv4 ? dispatchvx : NULL,
have_ipv6 ? dispatchvx : NULL, &requestmgr));
dns_view_create(isc_g_mctx, NULL, 0, "_mdig", &view);
dns_view_create(isc_g_mctx, NULL, dns_rdataclass_in, "_mdig", &view);
}
/*% Main processing routine for mdig */

View file

@ -6742,9 +6742,8 @@ with that view. When no view-specific value is given, the value in the
default values specified in the :any:`view` statement; these view-specific
defaults take precedence over those in the :namedconf:ref:`options` statement.
Views are class-specific. If no class is given, class IN is assumed.
Note that all non-IN views must contain a hint zone, since only the IN
class has compiled-in default hints.
Only class IN can be used for the views. If no class is given, class IN is
assumed.
If there are no :any:`view` statements in the config file, a default view
that matches any client is automatically created in class IN. Any

View file

@ -118,6 +118,19 @@ dns_view_create(isc_mem_t *mctx, dns_dispatchmgr_t *dispatchmgr,
REQUIRE(name != NULL);
REQUIRE(viewp != NULL && *viewp == NULL);
switch (rdclass) {
case dns_rdataclass_in:
break;
case dns_rdataclass_chaos:
if (strcmp(name, "_bind") == 0) {
/* allowed */
break;
}
FALLTHROUGH;
default:
UNREACHABLE();
}
result = isc_file_sanitize(NULL, name, "nta", buffer, sizeof(buffer));
RUNTIME_CHECK(result == ISC_R_SUCCESS);

View file

@ -6303,6 +6303,18 @@ isccfg_check_namedconf(const cfg_obj_t *config, unsigned int flags,
}
}
symtype = vclass + 1;
/*
* Only the Internet (IN) class is allowed for user-defined
* views. The builtin "_bind" view (Chaos) is generated
* internally and never appears in the configuration here.
*/
if (tresult == ISC_R_SUCCESS && vclass != dns_rdataclass_in) {
cfg_obj_log(view, ISC_LOG_ERROR,
"view '%s': only Internet (IN) class is "
"allowed",
key);
tresult = ISC_R_FAILURE;
}
if (tresult == ISC_R_SUCCESS && symtab != NULL) {
symvalue.as_cpointer = view;
tresult = isc_symtab_define(symtab, key, symtype,

View file

@ -2123,8 +2123,6 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
break;
case dns_rdataclass_chaos:
break;
case dns_rdataclass_hs:
break;
case dns_rdataclass_none:
if (client->message->opcode != dns_opcode_update) {
ns_client_dumpmessage(client,