mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
[9.20] [CVE-2026-5946] sec: usr: Disable recursion, UPDATE, and NOTIFY for non-IN views
Recursion, dynamic updates (UPDATE), and zone change notifications (NOTIFY) are now disabled for views with a class other than IN (such as CHAOS or HESIOD); authoritative service for non-IN zones (e.g. version.bind in class CHAOS) continues to work as before. Servers configured with recursion yes in a non-IN view will log a warning at startup, and named-checkconf flags the same condition. UPDATE and NOTIFY messages that specify the meta-classes ANY or NONE in the question section are now rejected with FORMERR. This addresses a set of closely related security issues collectively identified as CVE-2026-5946. ISC would like to thank Mcsky23 for bringing these issues to our attention. Backport of https://gitlab.isc.org/isc-private/bind9/-/merge_requests/936 Merge branch 'each-security-disable-chaos-recursion-security-bind-9.20' into 'security-bind-9.20' See merge request isc-private/bind9!1009
This commit is contained in:
commit
4c1547e4b5
26 changed files with 537 additions and 94 deletions
|
|
@ -1917,10 +1917,12 @@ dlzconfigure_callback(dns_view_t *view, dns_dlzdb_t *dlzdb, dns_zone_t *zone) {
|
|||
dns_rdataclass_t zclass = view->rdclass;
|
||||
isc_result_t result;
|
||||
|
||||
dns_zone_setclass(zone, zclass);
|
||||
result = dns_zonemgr_managezone(named_g_server->zonemgr, zone);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
dns_zone_setstats(zone, named_g_server->zonestats);
|
||||
|
||||
return named_zone_configure_writeable_dlz(dlzdb, zone, zclass, origin);
|
||||
|
|
@ -4428,7 +4430,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
obj = NULL;
|
||||
result = named_config_get(maps, "recursion", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
view->recursion = cfg_obj_asboolean(obj);
|
||||
view->recursion = (view->rdclass == dns_rdataclass_in &&
|
||||
cfg_obj_asboolean(obj));
|
||||
|
||||
if (named_g_maxcachesize != 0) {
|
||||
/*
|
||||
|
|
@ -5144,35 +5147,15 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
}
|
||||
|
||||
/*
|
||||
* We have default hints for class IN if we need them.
|
||||
* We have default root hints for class IN if we need them.
|
||||
* Each view gets its own rootdb so a priming response only
|
||||
* writes into that view's copy. Other classes don't support
|
||||
* recursion and don't need hints.
|
||||
*/
|
||||
if (view->rdclass == dns_rdataclass_in && view->hints == NULL) {
|
||||
dns_view_sethints(view, named_g_server->in_roothints);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we still have no hints, this is a non-IN view with no
|
||||
* "hints zone" configured. Issue a warning, except if this
|
||||
* is a root server. Root servers never need to consult
|
||||
* their hints, so it's no point requiring users to configure
|
||||
* them.
|
||||
*/
|
||||
if (view->hints == NULL) {
|
||||
dns_zone_t *rootzone = NULL;
|
||||
(void)dns_view_findzone(view, dns_rootname, DNS_ZTFIND_EXACT,
|
||||
&rootzone);
|
||||
if (rootzone != NULL) {
|
||||
dns_zone_detach(&rootzone);
|
||||
need_hints = false;
|
||||
}
|
||||
if (need_hints) {
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
|
||||
"no root hints for view '%s'",
|
||||
view->name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure the view's transports (DoT/DoH)
|
||||
*/
|
||||
|
|
@ -5408,14 +5391,13 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
"allow-proxy-on", NULL, actx, named_g_mctx,
|
||||
&view->proxyonacl));
|
||||
|
||||
if (strcmp(view->name, "_bind") != 0 &&
|
||||
view->rdclass != dns_rdataclass_chaos)
|
||||
{
|
||||
/* named.conf only */
|
||||
if (view->rdclass != dns_rdataclass_in) {
|
||||
dns_acl_none(named_g_mctx, &view->recursionacl);
|
||||
dns_acl_none(named_g_mctx, &view->recursiononacl);
|
||||
} else {
|
||||
CHECK(configure_view_acl(vconfig, config, NULL,
|
||||
"allow-recursion", NULL, actx,
|
||||
named_g_mctx, &view->recursionacl));
|
||||
/* named.conf only */
|
||||
CHECK(configure_view_acl(vconfig, config, NULL,
|
||||
"allow-recursion-on", NULL, actx,
|
||||
named_g_mctx, &view->recursiononacl));
|
||||
|
|
|
|||
|
|
@ -703,7 +703,7 @@ $DIG -p ${PORT} @10.53.1.2 d.normal.example a >dig.out.ns3.4.$n || ret=1
|
|||
grep 'recursion requested but not available' dig.out.ns3.4.$n >/dev/null || ret=1
|
||||
grep 'status: REFUSED' dig.out.ns3.4.$n >/dev/null || ret=1
|
||||
grep 'EDE: 18 (Prohibited)' dig.out.ns3.4.$n >/dev/null || ret=1
|
||||
nextpart ns3/named.run | grep 'allow-recursion-on did not match' >/dev/null || ret=1
|
||||
nextpart ns3/named.run | grep 'allow-query-cache-on did not match' >/dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
|
|
|
|||
|
|
@ -545,6 +545,7 @@ $CHECKCONF -l good.conf \
|
|||
| grep -v "is not implemented" \
|
||||
| grep -v "is not recommended" \
|
||||
| grep -v "no longer exists" \
|
||||
| grep -v "recursion will be disabled" \
|
||||
| grep -v "is obsolete" >checkconf.out$n || ret=1
|
||||
diff good.zonelist checkconf.out$n >diff.out$n || ret=1
|
||||
if [ $ret -ne 0 ]; then
|
||||
|
|
@ -805,5 +806,16 @@ 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
|
||||
|
|
|
|||
12
bin/tests/system/checkconf/warn-chaos-recursion.conf
Normal file
12
bin/tests/system/checkconf/warn-chaos-recursion.conf
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
options {
|
||||
directory ".";
|
||||
};
|
||||
|
||||
view chaos ch {
|
||||
match-clients { any; };
|
||||
recursion yes;
|
||||
zone "." {
|
||||
type hint;
|
||||
file "chaos.hints";
|
||||
};
|
||||
};
|
||||
4
bin/tests/system/class/ns1/chaos.db.in
Normal file
4
bin/tests/system/class/ns1/chaos.db.in
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
. CH NS ns.root.
|
||||
ns.root. CH A ns.root. 1
|
||||
ns.root. CH AAAA \# 1 00
|
||||
|
||||
31
bin/tests/system/class/ns1/named.conf.j2
Normal file
31
bin/tests/system/class/ns1/named.conf.j2
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
options {
|
||||
query-source address 10.53.0.1;
|
||||
notify-source 10.53.0.1;
|
||||
transfer-source 10.53.0.1;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.1; };
|
||||
listen-on-v6 { none; };
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
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";
|
||||
};
|
||||
};
|
||||
6
bin/tests/system/class/ns2/example.db.in
Normal file
6
bin/tests/system/class/ns2/example.db.in
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
$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"
|
||||
11
bin/tests/system/class/ns2/localhost.db.in
Normal file
11
bin/tests/system/class/ns2/localhost.db.in
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
$ORIGIN 1.0.0.127.in-addr.arpa.
|
||||
$TTL 300
|
||||
@ IN SOA ns hostmaster 1 3600 900 604800 300
|
||||
@ IN NS ns
|
||||
ns IN A 127.0.0.1
|
||||
|
||||
@ IN KX 10 target.example.
|
||||
@ IN PX 10 map822.example. mapx400.example.
|
||||
@ IN NSAP 0x47000580ffff0000000001e133ffffff00016200
|
||||
@ IN NSAP-PTR target.example.
|
||||
@ in EID \# 01 aa
|
||||
42
bin/tests/system/class/ns2/named.conf.j2
Normal file
42
bin/tests/system/class/ns2/named.conf.j2
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
options {
|
||||
directory ".";
|
||||
query-source address 10.53.0.2;
|
||||
notify-source 10.53.0.2;
|
||||
transfer-source 10.53.0.2;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.2; };
|
||||
listen-on-v6 { none; };
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
view default {
|
||||
match-clients { any; };
|
||||
recursion no;
|
||||
dnssec-validation no;
|
||||
zone "1.0.0.127.in-addr.arpa." {
|
||||
type primary;
|
||||
file "localhost.db";
|
||||
update-policy {
|
||||
grant * tcp-self . ANY;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
view chaos ch {
|
||||
match-clients { any; };
|
||||
recursion no;
|
||||
zone example {
|
||||
type primary;
|
||||
file "example.db";
|
||||
allow-update { any; };
|
||||
};
|
||||
};
|
||||
28
bin/tests/system/class/ns3/named.conf.j2
Normal file
28
bin/tests/system/class/ns3/named.conf.j2
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
options {
|
||||
directory ".";
|
||||
query-source address 10.53.0.3;
|
||||
notify-source 10.53.0.3;
|
||||
transfer-source 10.53.0.3;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.3; };
|
||||
listen-on-v6 { none; };
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm @DEFAULT_HMAC@;
|
||||
};
|
||||
|
||||
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; };
|
||||
};
|
||||
19
bin/tests/system/class/setup.sh
Normal file
19
bin/tests/system/class/setup.sh
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# 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 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
|
||||
54
bin/tests/system/class/tests_class_chaos.py
Normal file
54
bin/tests/system/class/tests_class_chaos.py
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
import dns.opcode
|
||||
import pytest
|
||||
|
||||
import isctest
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
[
|
||||
"*/*.db",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_chaos_recursion():
|
||||
msg = isctest.query.create("foo.example.", "TXT", qclass="CH")
|
||||
res = isctest.query.udp(msg, "10.53.0.1")
|
||||
isctest.check.refused(res)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
def test_chaos_forward():
|
||||
msg = isctest.query.create("a.example.", "A", qclass="CH")
|
||||
res = isctest.query.udp(msg, "10.53.0.3")
|
||||
isctest.check.refused(res)
|
||||
|
||||
|
||||
def test_chaos_notify():
|
||||
msg = isctest.query.create("example.", "SOA", qclass="CH", rd=False, dnssec=False)
|
||||
msg.set_opcode(dns.opcode.NOTIFY)
|
||||
msg.flags = dns.opcode.to_flags(dns.opcode.NOTIFY)
|
||||
res = isctest.query.udp(msg, "10.53.0.2")
|
||||
isctest.check.notimp(res)
|
||||
|
||||
|
||||
def test_query_class_none():
|
||||
msg = isctest.query.create("example.", "A", qclass="NONE")
|
||||
res = isctest.query.udp(msg, "10.53.0.2")
|
||||
isctest.check.formerr(res)
|
||||
137
bin/tests/system/class/tests_class_update.py
Normal file
137
bin/tests/system/class/tests_class_update.py
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# 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.
|
||||
|
||||
import socket
|
||||
import struct
|
||||
|
||||
from dns import message, rdataclass, rdatatype, update
|
||||
|
||||
import pytest
|
||||
|
||||
import isctest
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
[
|
||||
"*/*.db",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def encode_name(name: str) -> bytes:
|
||||
out = b""
|
||||
for label in name.rstrip(".").split("."):
|
||||
out += bytes([len(label)]) + label.encode("ascii")
|
||||
return out + b"\x00"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"rdtype,rdclass,ttl,rdata",
|
||||
[
|
||||
(rdatatype.SRV, rdataclass.NONE, 0, b"\x00\x00\x00\x00\x00\x00\x01"),
|
||||
(rdatatype.SRV, rdataclass.NONE, 0, b"\x00"),
|
||||
(rdatatype.KX, rdataclass.NONE, 0, b""),
|
||||
(rdatatype.PX, rdataclass.NONE, 0, b""),
|
||||
(rdatatype.NSAP, rdataclass.NONE, 0, b""),
|
||||
(rdatatype.NSAP_PTR, rdataclass.NONE, 0, b""),
|
||||
(31, rdataclass.NONE, 0, b""), # dnspython doesn't define type EID
|
||||
],
|
||||
)
|
||||
def test_class_invalid(rdtype, rdclass, ttl, rdata, named_port):
|
||||
# these update messages are badly formatted, so we construct
|
||||
# them manually instead of using dnspython.
|
||||
|
||||
# opcode=UPDATE, 1 RRset in ZONE, 1 RRset in UPDATE
|
||||
header = struct.pack("!HHHHHH", 0, 0x2800, 1, 0, 1, 0)
|
||||
|
||||
# ZONE section: QNAME=<zone>, QTYPE=SOA, QCLASS=ANY
|
||||
zone_q = encode_name("1.0.0.127.in-addr.arpa") + struct.pack("!HH", 6, 255)
|
||||
|
||||
# UPDATE section RR:
|
||||
update_rr = (
|
||||
encode_name("1.0.0.127.in-addr.arpa")
|
||||
+ struct.pack("!HHIH", rdtype, rdclass, ttl, len(rdata))
|
||||
+ rdata
|
||||
)
|
||||
|
||||
m = header + zone_q + update_rr
|
||||
packet = struct.pack("!H", len(m)) + m
|
||||
|
||||
with socket.create_connection(
|
||||
("10.53.0.2", named_port), source_address=("127.0.0.1", 0), timeout=2.0
|
||||
) as s:
|
||||
s.sendall(packet)
|
||||
try:
|
||||
rwire = s.recv(4096)
|
||||
res = message.from_wire(rwire)
|
||||
isctest.check.formerr(res)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
pass
|
||||
|
||||
# check the server is answering
|
||||
msg = isctest.query.create("1.0.0.127.in-addr.arpa", "SRV")
|
||||
res = isctest.query.udp(msg, "10.53.0.2")
|
||||
isctest.check.noerror(res)
|
||||
isctest.check.rr_count_eq(res.answer, 0)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"rdtype,rdata",
|
||||
[
|
||||
(rdatatype.SVCB, "\\# 02 0000"),
|
||||
(rdatatype.WKS, "\\# 02 4142"),
|
||||
(rdatatype.WKS, "\\# 02 4344"),
|
||||
],
|
||||
)
|
||||
def test_class_chaosupdate(rdtype, rdata):
|
||||
up = update.UpdateMessage("example.", rdclass=rdataclass.CHAOS)
|
||||
up.add("foo.example.", 300, rdtype, rdata)
|
||||
res = isctest.query.tcp(up, "10.53.0.2")
|
||||
isctest.check.notimp(res)
|
||||
|
||||
|
||||
def test_class_undefined(ns2):
|
||||
up = update.UpdateMessage(".", rdclass=257)
|
||||
up.present(".", 0)
|
||||
up.answer[0].rdclass = rdataclass.NONE
|
||||
with ns2.watch_log_from_here() as watcher:
|
||||
res = isctest.query.tcp(up, "10.53.0.2")
|
||||
isctest.check.notimp(res)
|
||||
watcher.wait_for_line("invalid message class: CLASS257")
|
||||
|
||||
|
||||
def test_class_zero(ns2):
|
||||
up = update.UpdateMessage(".", rdclass=0)
|
||||
up.present(".", 0)
|
||||
up.answer[0].rdclass = rdataclass.NONE
|
||||
with ns2.watch_log_from_here() as watcher:
|
||||
res = isctest.query.tcp(up, "10.53.0.2")
|
||||
isctest.check.formerr(res)
|
||||
watcher.wait_for_line("message class could not be determined")
|
||||
|
||||
|
||||
def test_class_any(ns2):
|
||||
up = update.UpdateMessage(".", rdclass=rdataclass.ANY)
|
||||
up.present(".", 0)
|
||||
up.answer[0].rdclass = rdataclass.NONE
|
||||
with ns2.watch_log_from_here() as watcher:
|
||||
res = isctest.query.tcp(up, "10.53.0.2")
|
||||
isctest.check.formerr(res)
|
||||
watcher.wait_for_line("message parsing failed: FORMERR")
|
||||
|
||||
|
||||
def test_class_none(ns2):
|
||||
up = update.UpdateMessage(".", rdclass=rdataclass.NONE)
|
||||
up.present(".", 0)
|
||||
up.answer[0].rdclass = rdataclass.NONE
|
||||
with ns2.watch_log_from_here() as watcher:
|
||||
res = isctest.query.tcp(up, "10.53.0.2")
|
||||
isctest.check.formerr(res)
|
||||
watcher.wait_for_line("message parsing failed: FORMERR")
|
||||
|
|
@ -46,6 +46,10 @@ def servfail(message: dns.message.Message) -> None:
|
|||
rcode(message, dns.rcode.SERVFAIL)
|
||||
|
||||
|
||||
def formerr(message: dns.message.Message) -> None:
|
||||
rcode(message, dns.rcode.FORMERR)
|
||||
|
||||
|
||||
def adflag(message: dns.message.Message) -> None:
|
||||
assert (message.flags & dns.flags.AD) != 0, str(message)
|
||||
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ def create(
|
|||
qtype,
|
||||
qclass=dns.rdataclass.IN,
|
||||
dnssec: bool = True,
|
||||
rd: bool = True,
|
||||
cd: bool = False,
|
||||
ad: bool = True,
|
||||
) -> dns.message.Message:
|
||||
|
|
@ -143,7 +144,9 @@ def create(
|
|||
msg = dns.message.make_query(
|
||||
qname, qtype, qclass, use_edns=True, want_dnssec=dnssec
|
||||
)
|
||||
msg.flags = dns.flags.RD
|
||||
msg.flags = 0
|
||||
if rd:
|
||||
msg.flags = dns.flags.RD
|
||||
if ad:
|
||||
msg.flags |= dns.flags.AD
|
||||
if cd:
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ update.nil IN SOA ns1.example.nil. hostmaster.example.nil. (
|
|||
3600 ; minimum (1 hour)
|
||||
)
|
||||
update.nil. NS ns1.update.nil.
|
||||
update.nil. KX 0 .
|
||||
ns1.update.nil. A 10.53.0.2
|
||||
ns2.update.nil. AAAA ::1
|
||||
EOF
|
||||
|
|
|
|||
|
|
@ -340,8 +340,10 @@ grep "status: NOERROR" dig.out.ns1.$n >/dev/null || ret=1
|
|||
n=$((n + 1))
|
||||
ret=0
|
||||
echo_i "check that TYPE=0 update is handled ($n)"
|
||||
nextpart ns1/named.run >/dev/null
|
||||
echo "a0e4280000010000000100000000060001c00c000000fe000000000000" \
|
||||
| $PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp >/dev/null || ret=1
|
||||
| $PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp -b >/dev/null || ret=1
|
||||
wait_for_log 2 "message parsing failed: FORMERR" ns1/named.run || ret=1
|
||||
$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 >dig.out.ns1.$n || ret=1
|
||||
grep "status: NOERROR" dig.out.ns1.$n >/dev/null || ret=1
|
||||
[ $ret = 0 ] || {
|
||||
|
|
@ -352,20 +354,10 @@ grep "status: NOERROR" dig.out.ns1.$n >/dev/null || ret=1
|
|||
n=$((n + 1))
|
||||
ret=0
|
||||
echo_i "check that TYPE=0 additional data is handled ($n)"
|
||||
nextpart ns1/named.run >/dev/null
|
||||
echo "a0e4280000010000000000010000060001c00c000000fe000000000000" \
|
||||
| $PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp >/dev/null || ret=1
|
||||
$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 >dig.out.ns1.$n || ret=1
|
||||
grep "status: NOERROR" dig.out.ns1.$n >/dev/null || ret=1
|
||||
[ $ret = 0 ] || {
|
||||
echo_i "failed"
|
||||
status=1
|
||||
}
|
||||
|
||||
n=$((n + 1))
|
||||
ret=0
|
||||
echo_i "check that update to undefined class is handled ($n)"
|
||||
echo "a0e4280000010001000000000000060101c00c000000fe000000000000" \
|
||||
| $PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp >/dev/null || ret=1
|
||||
| $PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp -b >/dev/null || ret=1
|
||||
wait_for_log 2 "message parsing failed: FORMERR" ns1/named.run || ret=1
|
||||
$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 >dig.out.ns1.$n || ret=1
|
||||
grep "status: NOERROR" dig.out.ns1.$n >/dev/null || ret=1
|
||||
[ $ret = 0 ] || {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
# -p <port>: specify port
|
||||
# -t <protocol>: specify UDP or TCP
|
||||
# -r <num>: send packet <num> times
|
||||
# -b: blocking io
|
||||
# -d: dump response packets
|
||||
#
|
||||
# If not specified, address defaults to 127.0.0.1, port to 53, protocol
|
||||
|
|
@ -51,6 +52,8 @@ use strict;
|
|||
use Getopt::Std;
|
||||
use IO::File;
|
||||
use IO::Socket;
|
||||
use Net::DNS;
|
||||
use Net::DNS::Packet;
|
||||
|
||||
sub usage {
|
||||
print ("Usage: packet.pl [-a address] [-d] [-p port] [-t (tcp|udp)] [-r <repeats>] [file]\n");
|
||||
|
|
@ -61,8 +64,6 @@ my $sock;
|
|||
my $proto;
|
||||
|
||||
sub dumppacket {
|
||||
use Net::DNS;
|
||||
use Net::DNS::Packet;
|
||||
|
||||
my $rin;
|
||||
my $rout;
|
||||
|
|
@ -96,7 +97,7 @@ sub dumppacket {
|
|||
}
|
||||
|
||||
my %options={};
|
||||
getopts("a:dp:t:r:", \%options);
|
||||
getopts("a:bdp:t:r:", \%options);
|
||||
|
||||
my $addr = "127.0.0.1";
|
||||
$addr = $options{a} if defined $options{a};
|
||||
|
|
@ -111,6 +112,8 @@ usage if ($proto !~ /^(udp|tcp)$/);
|
|||
my $repeats = 1;
|
||||
$repeats = $options{r} if defined $options{r};
|
||||
|
||||
my $blocking = defined $options{b} ? 1 : 0;
|
||||
|
||||
my $file = "STDIN";
|
||||
if (@ARGV >= 1) {
|
||||
my $filename = shift @ARGV;
|
||||
|
|
@ -132,8 +135,22 @@ my $len = length $data;
|
|||
my $output = unpack("H*", $data);
|
||||
print ("sending $repeats time(s): $output\n");
|
||||
|
||||
|
||||
if (defined $options{d}) {
|
||||
my $request;
|
||||
if ($Net::DNS::VERSION > 0.68) {
|
||||
$request = new Net::DNS::Packet(\$data, 0);
|
||||
$@ and die $@;
|
||||
} else {
|
||||
my $err;
|
||||
($request, $err) = new Net::DNS::Packet(\$data, 0);
|
||||
$err and die $err;
|
||||
}
|
||||
$request->print;
|
||||
}
|
||||
|
||||
$sock = IO::Socket::INET->new(PeerAddr => $addr, PeerPort => $port,
|
||||
Blocking => 0,
|
||||
Blocking => $blocking,
|
||||
Proto => $proto,) or die "$!";
|
||||
|
||||
STDOUT->autoflush(1);
|
||||
|
|
|
|||
|
|
@ -782,10 +782,12 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
|
|||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking NXDOMAIN is returned when querying non existing domain in CH class ($n)"
|
||||
echo_i "checking REFUSED is returned when querying non existing domain in CH class ($n)"
|
||||
ret=0
|
||||
dig_with_opts @10.53.0.1 id.hostname txt ch >dig.ns1.out.${n} || ret=1
|
||||
grep "status: NXDOMAIN" dig.ns1.out.${n} >/dev/null || ret=1
|
||||
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
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@ dig_cmd() {
|
|||
"$DIG" $DIGOPTS "$@" | grep -v '^;'
|
||||
}
|
||||
|
||||
dig_full() {
|
||||
# shellcheck disable=SC2086
|
||||
"$DIG" $DIGOPTS "$@"
|
||||
}
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "querying for various representations of an IN A record ($n)"
|
||||
for i in 1 2 3 4 5 6 7 8 9 10 11 12; do
|
||||
|
|
@ -81,8 +86,8 @@ n=$((n + 1))
|
|||
echo_i "querying for various representations of a CLASS10 TYPE1 record ($n)"
|
||||
for i in 1 2; do
|
||||
ret=0
|
||||
dig_cmd +short @10.53.0.1 a$i.example a class10 >dig.out.$i.test$n
|
||||
echo '\# 4 0A000001' | diff - dig.out.$i.test$n || ret=1
|
||||
dig_full @10.53.0.1 a$i.example a class10 >dig.out.$i.test$n
|
||||
grep -q "NOTIMP" dig.out.$i.test$n || ret=1
|
||||
if [ $ret != 0 ]; then
|
||||
echo_i "#$i failed"
|
||||
fi
|
||||
|
|
@ -93,8 +98,8 @@ n=$((n + 1))
|
|||
echo_i "querying for various representations of a CLASS10 TXT record ($n)"
|
||||
for i in 1 2 3 4; do
|
||||
ret=0
|
||||
dig_cmd +short @10.53.0.1 txt$i.example txt class10 >dig.out.$i.test$n
|
||||
echo '"hello"' | diff - dig.out.$i.test$n || ret=1
|
||||
dig_full @10.53.0.1 txt$i.example txt class10 >dig.out.$i.test$n
|
||||
grep -q "NOTIMP" dig.out.$i.test$n || ret=1
|
||||
if [ $ret != 0 ]; then
|
||||
echo_i "#$i failed"
|
||||
fi
|
||||
|
|
@ -105,8 +110,8 @@ n=$((n + 1))
|
|||
echo_i "querying for various representations of a CLASS10 TYPE123 record ($n)"
|
||||
for i in 1 2; do
|
||||
ret=0
|
||||
dig_cmd +short @10.53.0.1 unk$i.example type123 class10 >dig.out.$i.test$n
|
||||
echo '\# 1 00' | diff - dig.out.$i.test$n || ret=1
|
||||
dig_full @10.53.0.1 unk$i.example type123 class10 >dig.out.$i.test$n
|
||||
grep -q "NOTIMP" dig.out.$i.test$n || ret=1
|
||||
if [ $ret != 0 ]; then
|
||||
echo_i "#$i failed"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -567,6 +567,9 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
|
|||
|
||||
rdtype = rdataset->type;
|
||||
|
||||
REQUIRE(rdataset->rdclass == dns_rdataclass_in);
|
||||
REQUIRE(rdtype == dns_rdatatype_a || rdtype == dns_rdatatype_aaaa);
|
||||
|
||||
switch (rdataset->trust) {
|
||||
case dns_trust_glue:
|
||||
case dns_trust_additional:
|
||||
|
|
@ -579,8 +582,6 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
|
|||
rdataset->ttl = ttlclamp(rdataset->ttl);
|
||||
}
|
||||
|
||||
REQUIRE(rdtype == dns_rdatatype_a || rdtype == dns_rdatatype_aaaa);
|
||||
|
||||
for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
|
||||
result = dns_rdataset_next(rdataset))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1073,6 +1073,17 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
|
|||
rdtype = isc_buffer_getuint16(source);
|
||||
rdclass = isc_buffer_getuint16(source);
|
||||
|
||||
/*
|
||||
* Notify and update messages need to specify the data class.
|
||||
*/
|
||||
if ((msg->opcode == dns_opcode_update ||
|
||||
msg->opcode == dns_opcode_notify) &&
|
||||
(rdclass == dns_rdataclass_none ||
|
||||
rdclass == dns_rdataclass_any))
|
||||
{
|
||||
DO_ERROR(DNS_R_FORMERR);
|
||||
}
|
||||
|
||||
/*
|
||||
* If this class is different than the one we already read,
|
||||
* this is an error.
|
||||
|
|
|
|||
|
|
@ -6967,6 +6967,13 @@ is_answeraddress_allowed(dns_view_t *view, dns_name_t *name,
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* deny-answer-address doesn't apply to non-IN classes.
|
||||
*/
|
||||
if (rdataset->rdclass != dns_rdataclass_in) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, search the filter list for a match for each
|
||||
* address record. If a match is found, the address should be
|
||||
|
|
|
|||
|
|
@ -3041,13 +3041,17 @@ check_mirror_zone_notify(const cfg_obj_t *zoptions, const char *znamestr,
|
|||
*/
|
||||
static bool
|
||||
check_recursion(const cfg_obj_t *config, const cfg_obj_t *voptions,
|
||||
const cfg_obj_t *goptions, isc_log_t *logctx,
|
||||
cfg_aclconfctx_t *actx, isc_mem_t *mctx) {
|
||||
dns_rdataclass_t vclass, const cfg_obj_t *goptions,
|
||||
isc_log_t *logctx, cfg_aclconfctx_t *actx, isc_mem_t *mctx) {
|
||||
dns_acl_t *acl = NULL;
|
||||
const cfg_obj_t *obj;
|
||||
isc_result_t result;
|
||||
bool retval = true;
|
||||
|
||||
if (vclass != dns_rdataclass_in) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the "recursion" option first.
|
||||
*/
|
||||
|
|
@ -3905,7 +3909,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
|||
* contradicts the purpose of the former.
|
||||
*/
|
||||
if (ztype == CFG_ZONE_MIRROR &&
|
||||
!check_recursion(config, voptions, goptions, logctx, actx, mctx))
|
||||
!check_recursion(config, voptions, zclass, goptions, logctx, actx,
|
||||
mctx))
|
||||
{
|
||||
cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
|
||||
"zone '%s': mirror zones cannot be used if "
|
||||
|
|
@ -5719,6 +5724,17 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
|
|||
|
||||
cfg_aclconfctx_create(mctx, &actx);
|
||||
|
||||
if (vclass != dns_rdataclass_in) {
|
||||
if (check_recursion(config, voptions, dns_rdataclass_in,
|
||||
options, logctx, actx, mctx))
|
||||
{
|
||||
cfg_obj_log(opts, logctx, ISC_LOG_WARNING,
|
||||
"recursion will be disabled for "
|
||||
"non-IN view '%s'",
|
||||
viewname);
|
||||
}
|
||||
}
|
||||
|
||||
if (voptions != NULL) {
|
||||
(void)cfg_map_get(voptions, "zone", &zones);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include <dns/dispatch.h>
|
||||
#include <dns/dnstap.h>
|
||||
#include <dns/edns.h>
|
||||
#include <dns/enumclass.h>
|
||||
#include <dns/message.h>
|
||||
#include <dns/peer.h>
|
||||
#include <dns/rcode.h>
|
||||
|
|
@ -2041,7 +2042,9 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
}
|
||||
}
|
||||
|
||||
if (client->message->rdclass == 0) {
|
||||
char classbuf[DNS_RDATACLASS_FORMATSIZE];
|
||||
switch (client->message->rdclass) {
|
||||
case dns_rdataclass_reserved0:
|
||||
if ((client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0 &&
|
||||
client->message->opcode == dns_opcode_query &&
|
||||
client->message->counts[DNS_SECTION_QUESTION] == 0U)
|
||||
|
|
@ -2060,12 +2063,46 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
return;
|
||||
}
|
||||
|
||||
ns_client_dumpmessage(client,
|
||||
"message class could not be determined");
|
||||
ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
|
||||
return;
|
||||
case dns_rdataclass_in:
|
||||
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,
|
||||
"message class NONE can be only "
|
||||
"used in DNS updates");
|
||||
ns_client_error(client, DNS_R_FORMERR);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case dns_rdataclass_any:
|
||||
/*
|
||||
* Required for TKEY negotiation.
|
||||
*/
|
||||
if (client->message->tkey == 0) {
|
||||
ns_client_dumpmessage(client,
|
||||
"message class ANY can be only "
|
||||
"used for TKEY negotiation");
|
||||
ns_client_error(client, DNS_R_FORMERR);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dns_rdataclass_format(client->message->rdclass, classbuf,
|
||||
sizeof(classbuf));
|
||||
ns_client_dumpmessage(client, NULL);
|
||||
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
|
||||
"message class could not be determined");
|
||||
ns_client_dumpmessage(client, "message class could not be "
|
||||
"determined");
|
||||
ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
|
||||
"invalid message class: %s", classbuf);
|
||||
|
||||
ns_client_error(client, DNS_R_NOTIMP);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2149,9 +2186,6 @@ ns_client_request_continue(void *arg) {
|
|||
"SIG(0) checks quota reached");
|
||||
|
||||
if (can_log_sigchecks_quota()) {
|
||||
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_INFO,
|
||||
"SIG(0) checks quota reached");
|
||||
ns_client_dumpmessage(
|
||||
client, "SIG(0) checks quota reached");
|
||||
}
|
||||
|
|
@ -2161,12 +2195,11 @@ ns_client_request_continue(void *arg) {
|
|||
dns_rdataclass_format(client->message->rdclass,
|
||||
classname, sizeof(classname));
|
||||
|
||||
ns_client_dumpmessage(client, NULL);
|
||||
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
|
||||
"no matching view in class '%s'",
|
||||
classname);
|
||||
ns_client_dumpmessage(client,
|
||||
"no matching view in class");
|
||||
}
|
||||
|
||||
dns_ede_add(&client->edectx, DNS_EDE_PROHIBITED, NULL);
|
||||
|
|
@ -2413,6 +2446,10 @@ ns_client_request_continue(void *arg) {
|
|||
break;
|
||||
case dns_opcode_update:
|
||||
CTRACE("update");
|
||||
if (client->view->rdclass != dns_rdataclass_in) {
|
||||
ns_client_error(client, DNS_R_NOTIMP);
|
||||
break;
|
||||
}
|
||||
#ifdef HAVE_DNSTAP
|
||||
dns_dt_send(client->view, DNS_DTTYPE_UQ, &client->peeraddr,
|
||||
&client->destsockaddr, transport_type, NULL,
|
||||
|
|
@ -2423,6 +2460,10 @@ ns_client_request_continue(void *arg) {
|
|||
break;
|
||||
case dns_opcode_notify:
|
||||
CTRACE("notify");
|
||||
if (client->view->rdclass != dns_rdataclass_in) {
|
||||
ns_client_error(client, DNS_R_NOTIMP);
|
||||
break;
|
||||
}
|
||||
ns_client_settimeout(client, 60);
|
||||
ns_notify_start(client, client->handle);
|
||||
break;
|
||||
|
|
@ -2796,7 +2837,7 @@ ns_client_dumpmessage(ns_client_t *client, const char *reason) {
|
|||
int len = 1024;
|
||||
isc_result_t result;
|
||||
|
||||
if (!isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(1))) {
|
||||
if (!isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(1)) || reason == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -997,7 +997,9 @@ ssu_checkrr(void *data, rr_t *rr) {
|
|||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
target = &ptr.ptr;
|
||||
}
|
||||
if (rr->rdata.type == dns_rdatatype_srv) {
|
||||
if (rr->rdata.rdclass == dns_rdataclass_in &&
|
||||
rr->rdata.type == dns_rdatatype_srv)
|
||||
{
|
||||
result = dns_rdata_tostruct(&rr->rdata, &srv, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
target = &srv.target;
|
||||
|
|
@ -1352,7 +1354,10 @@ replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
if (db_rr->type == dns_rdatatype_wks) {
|
||||
|
||||
if (db_rr->rdclass == dns_rdataclass_in &&
|
||||
db_rr->type == dns_rdatatype_wks)
|
||||
{
|
||||
/*
|
||||
* Compare the address and protocol fields only. These
|
||||
* form the first five bytes of the RR data. Do a
|
||||
|
|
@ -1495,8 +1500,7 @@ cleanup:
|
|||
* 'rdata', and 'ttl', respectively.
|
||||
*/
|
||||
static void
|
||||
get_current_rr(dns_message_t *msg, dns_section_t section,
|
||||
dns_rdataclass_t zoneclass, dns_name_t **name,
|
||||
get_current_rr(dns_message_t *msg, dns_section_t section, dns_name_t **name,
|
||||
dns_rdata_t *rdata, dns_rdatatype_t *covers, dns_ttl_t *ttl,
|
||||
dns_rdataclass_t *update_class) {
|
||||
dns_rdataset_t *rdataset;
|
||||
|
|
@ -1512,7 +1516,7 @@ get_current_rr(dns_message_t *msg, dns_section_t section,
|
|||
dns_rdataset_current(rdataset, rdata);
|
||||
INSIST(dns_rdataset_next(rdataset) == ISC_R_NOMORE);
|
||||
*update_class = rdata->rdclass;
|
||||
rdata->rdclass = zoneclass;
|
||||
rdata->rdclass = dns_rdataclass_in;
|
||||
}
|
||||
|
||||
/*%
|
||||
|
|
@ -1612,7 +1616,6 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
|
|||
dns_message_t *request = client->message;
|
||||
isc_mem_t *mctx = client->manager->mctx;
|
||||
dns_aclenv_t *env = client->manager->aclenv;
|
||||
dns_rdataclass_t zoneclass;
|
||||
dns_rdatatype_t covers;
|
||||
dns_name_t *zonename = NULL;
|
||||
unsigned int *maxbytype = NULL;
|
||||
|
|
@ -1624,11 +1627,13 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
|
|||
|
||||
CHECK(dns_zone_getdb(zone, &db));
|
||||
zonename = dns_db_origin(db);
|
||||
zoneclass = dns_db_class(db);
|
||||
dns_zone_getssutable(zone, &ssutable);
|
||||
options = dns_zone_getoptions(zone);
|
||||
dns_db_currentversion(db, &ver);
|
||||
|
||||
/* Updates are only supported for class IN. */
|
||||
INSIST(dns_zone_getclass(zone) == dns_rdataclass_in);
|
||||
|
||||
/*
|
||||
* Update message processing can leak record existence information
|
||||
* so check that we are allowed to query this zone. Additionally,
|
||||
|
|
@ -1678,13 +1683,13 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
|
|||
|
||||
INSIST(ssutable == NULL || update < maxbytypelen);
|
||||
|
||||
get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, &name,
|
||||
&rdata, &covers, &ttl, &update_class);
|
||||
get_current_rr(request, DNS_SECTION_UPDATE, &name, &rdata,
|
||||
&covers, &ttl, &update_class);
|
||||
|
||||
if (!dns_name_issubdomain(name, zonename)) {
|
||||
FAILC(DNS_R_NOTZONE, "update RR is outside zone");
|
||||
}
|
||||
if (update_class == zoneclass) {
|
||||
if (update_class == dns_rdataclass_in) {
|
||||
/*
|
||||
* Check for meta-RRs. The RFC2136 pseudocode says
|
||||
* check for ANY|AXFR|MAILA|MAILB, but the text adds
|
||||
|
|
@ -1698,6 +1703,7 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
|
|||
CHECK(DNS_R_REFUSED);
|
||||
}
|
||||
if ((options & DNS_ZONEOPT_CHECKSVCB) != 0 &&
|
||||
rdata.rdclass == dns_rdataclass_in &&
|
||||
rdata.type == dns_rdatatype_svcb)
|
||||
{
|
||||
result = dns_rdata_checksvcb(name, &rdata);
|
||||
|
|
@ -1785,7 +1791,6 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
|
|||
}
|
||||
|
||||
if (update_class == dns_rdataclass_any &&
|
||||
zoneclass == dns_rdataclass_in &&
|
||||
(rdata.type == dns_rdatatype_ptr ||
|
||||
rdata.type == dns_rdatatype_srv))
|
||||
{
|
||||
|
|
@ -2717,7 +2722,6 @@ update_action(void *arg) {
|
|||
isc_mem_t *mctx = client->manager->mctx;
|
||||
dns_rdatatype_t covers;
|
||||
dns_message_t *request = client->message;
|
||||
dns_rdataclass_t zoneclass;
|
||||
dns_name_t *zonename = NULL;
|
||||
dns_fixedname_t tmpnamefixed;
|
||||
dns_name_t *tmpname = NULL;
|
||||
|
|
@ -2734,9 +2738,10 @@ update_action(void *arg) {
|
|||
|
||||
CHECK(dns_zone_getdb(zone, &db));
|
||||
zonename = dns_db_origin(db);
|
||||
zoneclass = dns_db_class(db);
|
||||
options = dns_zone_getoptions(zone);
|
||||
|
||||
INSIST(dns_zone_getclass(zone) == dns_rdataclass_in);
|
||||
|
||||
is_inline = (!dns_zone_israw(zone) && dns_zone_issecure(zone));
|
||||
is_maintain = ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0);
|
||||
is_signing = is_inline || (!is_inline && is_maintain);
|
||||
|
|
@ -2761,8 +2766,8 @@ update_action(void *arg) {
|
|||
dns_rdataclass_t update_class;
|
||||
bool flag;
|
||||
|
||||
get_current_rr(request, DNS_SECTION_PREREQUISITE, zoneclass,
|
||||
&name, &rdata, &covers, &ttl, &update_class);
|
||||
get_current_rr(request, DNS_SECTION_PREREQUISITE, &name, &rdata,
|
||||
&covers, &ttl, &update_class);
|
||||
|
||||
if (ttl != 0) {
|
||||
PREREQFAILC(DNS_R_FORMERR,
|
||||
|
|
@ -2825,7 +2830,7 @@ update_action(void *arg) {
|
|||
"prerequisite not satisfied");
|
||||
}
|
||||
}
|
||||
} else if (update_class == zoneclass) {
|
||||
} else if (update_class == dns_rdataclass_in) {
|
||||
/* "temp<rr.name, rr.type> += rr;" */
|
||||
result = temp_append(&temp, name, &rdata);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
@ -2887,10 +2892,10 @@ update_action(void *arg) {
|
|||
|
||||
INSIST(ssutable == NULL || update < maxbytypelen);
|
||||
|
||||
get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, &name,
|
||||
&rdata, &covers, &ttl, &update_class);
|
||||
get_current_rr(request, DNS_SECTION_UPDATE, &name, &rdata,
|
||||
&covers, &ttl, &update_class);
|
||||
|
||||
if (update_class == zoneclass) {
|
||||
if (update_class == dns_rdataclass_in) {
|
||||
/*
|
||||
* RFC1123 doesn't allow MF and MD in master files.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue