mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-09 11:22:04 -04:00
rem: usr: Remove legacy special handling for SIG, NXT, and KEY records
BIND no longer applies legacy RFC 2535 handling to the obsolete ``SIG``, ``NXT`` and ``KEY`` record types; they are now served as plain zone data. Zones with both a ``CNAME`` and a ``KEY`` and or ``NXT`` at the same name — invalid under :rfc:`2181` — will now fail to load and must be corrected. Closes #6007 Merge branch '6007-remove-SIG-and-NXT-special-handling' into 'main' See merge request isc-projects/bind9!12056
This commit is contained in:
commit
ac342bf652
17 changed files with 107 additions and 174 deletions
|
|
@ -39,9 +39,13 @@ normalthenrrsig A 10.0.0.28
|
|||
rrsigonly A 10.0.0.29
|
||||
|
||||
cnameandkey CNAME @
|
||||
cnamenokey CNAME @
|
||||
dnameandkey DNAME @
|
||||
|
||||
; Legacy DNSSEC types (RFC 3755) carried as opaque zone data and signed.
|
||||
sigrr SIG A 6 2 86400 20260331170000 20260318160000 21831 . AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
nxtrr NXT next.secure.example. A
|
||||
keyrr KEY 0 3 13 zJxo/L9JqctLZuL8CqocSmgHUhmQCrQQmRHjwhzXfjDgPoPjRo1nofU7yXHeli8myiulQLZk3h1CTayP8dOvkQ==
|
||||
|
||||
mixedcase A 10.0.0.30
|
||||
mixedCASE TXT "mixed case"
|
||||
MIXEDcase AAAA 2002::
|
||||
|
|
|
|||
|
|
@ -115,11 +115,10 @@ zone=secure.example.
|
|||
infile=secure.example.db.in
|
||||
zonefile=secure.example.db
|
||||
|
||||
cnameandkey=$("$KEYGEN" -T KEY -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "cnameandkey.$zone")
|
||||
dnameandkey=$("$KEYGEN" -T KEY -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "dnameandkey.$zone")
|
||||
keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
|
||||
|
||||
cat "$infile" dsset-badalg.secure.example. "$cnameandkey.key" "$dnameandkey.key" "$keyname.key" >"$zonefile"
|
||||
cat "$infile" dsset-badalg.secure.example. "$dnameandkey.key" "$keyname.key" >"$zonefile"
|
||||
|
||||
"$SIGNER" -z -D -o "$zone" "$zonefile" >/dev/null
|
||||
cat "$zonefile" "$zonefile".signed >"$zonefile".tmp
|
||||
|
|
|
|||
|
|
@ -290,22 +290,6 @@ def test_chain_validation():
|
|||
isctest.check.adflag(res2)
|
||||
assert answer_has(res2, rdatatype.CNAME)
|
||||
|
||||
# check KEY lookup via CNAME
|
||||
msg = isctest.query.create("cnameandkey.secure.example", "KEY")
|
||||
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
||||
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
||||
isctest.check.same_answer(res1, res2)
|
||||
isctest.check.adflag(res2)
|
||||
assert not answer_has(res2, rdatatype.CNAME)
|
||||
|
||||
# check KEY lookup via CNAME (not present)
|
||||
msg = isctest.query.create("cnamenokey.secure.example", "KEY")
|
||||
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
||||
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
||||
isctest.check.same_answer(res1, res2)
|
||||
isctest.check.adflag(res2)
|
||||
assert not answer_has(res2, rdatatype.CNAME)
|
||||
|
||||
# check DNSKEY lookup via DNAME
|
||||
msg = isctest.query.create("a.dnameandkey.secure.example", "DNSKEY")
|
||||
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
||||
|
|
@ -1351,6 +1335,30 @@ def test_unknown_algorithms():
|
|||
isctest.check.noadflag(res2)
|
||||
|
||||
|
||||
def test_legacy_dnssec_types_are_signed():
|
||||
"""SIG (24), NXT (30) and KEY (25) records carry a covering RRSIG.
|
||||
|
||||
Per RFC 3755 SIG and NXT are obsolete and treated as opaque zone
|
||||
data; KEY remains valid for SIG(0)/TKEY use. All three are
|
||||
ordinary zone data and must be signed like any other RRset.
|
||||
"""
|
||||
for owner, rrtype in [
|
||||
("sigrr.secure.example", "SIG"),
|
||||
("nxtrr.secure.example", "NXT"),
|
||||
("keyrr.secure.example", "KEY"),
|
||||
]:
|
||||
expected = rdatatype.from_text(rrtype)
|
||||
msg = isctest.query.create(owner, rrtype, cd=True)
|
||||
res = isctest.query.tcp(msg, "10.53.0.3")
|
||||
isctest.check.noerror(res)
|
||||
assert any(
|
||||
rr.rdtype == expected for rr in res.answer
|
||||
), f"{rrtype} record missing in answer for {owner}: {res.answer}"
|
||||
assert any(
|
||||
rr.rdtype == rdatatype.RRSIG and rr.covers == expected for rr in res.answer
|
||||
), f"RRSIG({rrtype}) missing in answer for {owner}: {res.answer}"
|
||||
|
||||
|
||||
def test_rrsigs_for_glue():
|
||||
msg = isctest.query.create("ns3.secure.example", "A", cd=True)
|
||||
res = isctest.query.tcp(msg, "10.53.0.4")
|
||||
|
|
|
|||
|
|
@ -10,14 +10,13 @@
|
|||
# information regarding copyright ownership.
|
||||
|
||||
"""
|
||||
GL#5818 Finding 1 regression support — AsyncDnsServer primary.
|
||||
AsyncDnsServer primary serving "sigaxfr.nil.".
|
||||
|
||||
Serves a minimal zone "sigaxfr.nil." whose AXFR carries two SIG records
|
||||
at the same owner with different covered types (A and MX) and different
|
||||
TTLs (600 and 1200). A buggy secondary running dns_diff_load() with
|
||||
rdata_covers() that only recognises RRSIG will file both rdatas under
|
||||
typepair (SIG, 0) with the first tuple's TTL; a fixed secondary keeps
|
||||
them under (SIG, A) and (SIG, MX) with their distinct TTLs.
|
||||
The AXFR carries two SIG (type 24) rdatas at the same owner with
|
||||
different "covered type" body fields (A and MX) so the secondary can
|
||||
verify it stores both under a single opaque rdataset. Per RFC 3755
|
||||
SIG has no covered-type semantics on BIND any more; the two rdatas
|
||||
share the rdataset TTL.
|
||||
"""
|
||||
|
||||
from collections.abc import AsyncGenerator
|
||||
|
|
@ -75,7 +74,7 @@ class SigAxfrServer(DomainHandler):
|
|||
return
|
||||
|
||||
# AXFR: opening SOA, NS, NS's A, two SIG RRs at the same owner
|
||||
# with distinct covered types and TTLs, closing SOA.
|
||||
# with distinct "covered type" body fields, closing SOA.
|
||||
resp = qctx.response
|
||||
resp.answer.append(soa_rrset)
|
||||
|
||||
|
|
@ -89,17 +88,16 @@ class SigAxfrServer(DomainHandler):
|
|||
)
|
||||
resp.answer.append(a_rrset)
|
||||
|
||||
sig_a = _make_sig_rdata("A 6 2 600 20260331170000 20260318160000 21831 . 0000")
|
||||
sig_a_rrset = dns.rrset.RRset(HOST, dns.rdataclass.IN, dns.rdatatype.SIG)
|
||||
sig_a_rrset.add(sig_a, ttl=600)
|
||||
resp.answer.append(sig_a_rrset)
|
||||
|
||||
sig_mx = _make_sig_rdata(
|
||||
"MX 6 2 1200 20260331170000 20260318160000 21831 . 0000"
|
||||
sig_rrset = dns.rrset.RRset(HOST, dns.rdataclass.IN, dns.rdatatype.SIG)
|
||||
sig_rrset.add(
|
||||
_make_sig_rdata("A 6 2 600 20260331170000 20260318160000 21831 . 0000"),
|
||||
ttl=600,
|
||||
)
|
||||
sig_mx_rrset = dns.rrset.RRset(HOST, dns.rdataclass.IN, dns.rdatatype.SIG)
|
||||
sig_mx_rrset.add(sig_mx, ttl=1200)
|
||||
resp.answer.append(sig_mx_rrset)
|
||||
sig_rrset.add(
|
||||
_make_sig_rdata("MX 6 2 600 20260331170000 20260318160000 21831 . 0000"),
|
||||
ttl=600,
|
||||
)
|
||||
resp.answer.append(sig_rrset)
|
||||
|
||||
# Closing SOA terminates the AXFR.
|
||||
resp.answer.append(soa_rrset)
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@
|
|||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
"""
|
||||
Regression tests for GL#5818: legacy DNSSEC types on the dynamic-update path.
|
||||
"""Regression tests for GL#5818: legacy DNSSEC types on the dynamic-update path.
|
||||
|
||||
SIG (24) and NXT (30) are obsolete DNSSEC record types, superseded by RRSIG
|
||||
and NSEC in RFC 3755. Allowing a client to inject them via dynamic update
|
||||
|
|
@ -24,11 +23,9 @@ exposed two bugs in sequence:
|
|||
different TTL then tripped DNS_DBADD_EXACTTTL in qpzone and came back
|
||||
as SERVFAIL.
|
||||
|
||||
The adopted defence is to outright refuse SIG and NXT updates at the front
|
||||
door (ns/update.c), keeping KEY updates permitted for SIG(0) transaction
|
||||
signatures. These tests verify the refusal. The reachability of the
|
||||
diff.c:rdata_covers() bug via inbound zone transfer is covered separately
|
||||
by the AXFR-based regression test in this file.
|
||||
The adopted defence is to treat the legacy SIG and NXT records as normal RR
|
||||
records without any special processing.
|
||||
|
||||
"""
|
||||
|
||||
from re import compile as Re
|
||||
|
|
@ -92,18 +89,17 @@ def _make_nxt_rdata():
|
|||
|
||||
|
||||
def test_tcp_self_sig_record(ns6):
|
||||
"""SIG (type 24) updates must be refused at the front door.
|
||||
"""SIG (type 24) updates are accepted and stored as opaque rdata.
|
||||
|
||||
Prior to the fix in dns__db_findrdataset(), a SIG update here
|
||||
crashed named. Prior to the fix in diff.c rdata_covers(), the
|
||||
record was silently misfiled under typepair (SIG, 0). The
|
||||
adopted policy outright refuses SIG (obsolete; use RRSIG) so the
|
||||
buggy dynamic-update paths are no longer reachable. A PTR add
|
||||
first ensures the node exists, which is the original
|
||||
crash-reproducing precondition.
|
||||
Per RFC 3755 SIG is obsolete (superseded by RRSIG). BIND treats
|
||||
incoming SIG records as a generic unknown type with no covered-type
|
||||
semantics: dynamic updates carrying SIG are accepted and the record
|
||||
becomes queryable. A PTR add first ensures the node exists.
|
||||
"""
|
||||
owner = "1.0.53.10.in-addr.arpa."
|
||||
|
||||
ptr_update = dns.update.UpdateMessage("in-addr.arpa.")
|
||||
ptr_update.add("1.0.53.10.in-addr.arpa.", 600, "PTR", "localhost.")
|
||||
ptr_update.add(owner, 600, "PTR", "localhost.")
|
||||
response = isctest.query.tcp(
|
||||
ptr_update, ns6.ip, port=ns6.ports.dns, source="10.53.0.1"
|
||||
)
|
||||
|
|
@ -114,34 +110,27 @@ def test_tcp_self_sig_record(ns6):
|
|||
rds.update_ttl(600)
|
||||
rds.add(sig)
|
||||
sig_update = dns.update.UpdateMessage("in-addr.arpa.")
|
||||
sig_update.add("1.0.0.127.in-addr.arpa.", rds)
|
||||
sig_update.add(owner, rds)
|
||||
|
||||
with ns6.watch_log_from_here() as watcher:
|
||||
response = isctest.query.tcp(
|
||||
sig_update, ns6.ip, port=ns6.ports.dns, source="10.53.0.1"
|
||||
)
|
||||
assert response.rcode() == dns.rcode.REFUSED
|
||||
response = isctest.query.tcp(
|
||||
sig_update, ns6.ip, port=ns6.ports.dns, source="10.53.0.1"
|
||||
)
|
||||
assert response.rcode() == dns.rcode.NOERROR
|
||||
|
||||
watcher.wait_for_line(
|
||||
"updating zone 'in-addr.arpa/IN': update failed: SIG updates are not allowed (REFUSED)"
|
||||
)
|
||||
|
||||
# Confirm nothing of type SIG was stored.
|
||||
msg = isctest.query.create("1.0.53.10.in-addr.arpa.", "SIG")
|
||||
# Confirm the SIG record was stored.
|
||||
msg = isctest.query.create(owner, "SIG")
|
||||
res = isctest.query.tcp(msg, ns6.ip, port=ns6.ports.dns)
|
||||
stored = any(rrset.rdtype == dns.rdatatype.SIG for rrset in res.answer)
|
||||
assert not stored, "SIG record was stored despite REFUSED response"
|
||||
assert stored, "SIG record was not stored despite NOERROR response"
|
||||
|
||||
|
||||
def test_tcp_self_nxt_record(ns6):
|
||||
"""NXT (type 30) updates must be refused at the front door.
|
||||
"""NXT (type 30) updates are accepted and stored as opaque rdata.
|
||||
|
||||
NXT is the legacy DNSSEC denial-of-existence type, obsolete since
|
||||
RFC 3755 replaced it with NSEC. Accepting it via dynamic update
|
||||
would let an authorised updater inject records that the signing
|
||||
and cut-point logic has no provision for.
|
||||
RFC 3755 replaced it with NSEC. BIND treats it as a generic
|
||||
unknown rdata type.
|
||||
"""
|
||||
# A second owner under a source that also matches tcp-self.
|
||||
source = "10.53.0.2"
|
||||
owner = "2.0.53.10.in-addr.arpa."
|
||||
|
||||
|
|
@ -157,28 +146,23 @@ def test_tcp_self_nxt_record(ns6):
|
|||
nxt_update = dns.update.UpdateMessage("in-addr.arpa.")
|
||||
nxt_update.add(owner, rds)
|
||||
|
||||
with ns6.watch_log_from_here() as watcher:
|
||||
response = isctest.query.tcp(
|
||||
nxt_update, ns6.ip, port=ns6.ports.dns, source="10.53.0.1"
|
||||
)
|
||||
assert response.rcode() == dns.rcode.REFUSED
|
||||
response = isctest.query.tcp(nxt_update, ns6.ip, port=ns6.ports.dns, source=source)
|
||||
assert response.rcode() == dns.rcode.NOERROR
|
||||
|
||||
watcher.wait_for_line(
|
||||
"updating zone 'in-addr.arpa/IN': update failed: NXT updates are not allowed (REFUSED)"
|
||||
)
|
||||
# Confirm the NXT record was stored.
|
||||
msg = isctest.query.create(owner, "NXT")
|
||||
res = isctest.query.tcp(msg, ns6.ip, port=ns6.ports.dns)
|
||||
stored = any(rrset.rdtype == dns.rdatatype.NXT for rrset in res.answer)
|
||||
assert stored, "NXT record was not stored despite NOERROR response"
|
||||
|
||||
|
||||
def test_sig_covers_preserved_via_axfr(ns6):
|
||||
"""Regression test for GL#5818 Finding 1, reached via AXFR.
|
||||
def test_sig_axfr_stored_opaque(ns6):
|
||||
"""SIG records received via AXFR are stored as opaque rdata.
|
||||
|
||||
ans11 serves an AXFR for sigaxfr.nil. containing two SIG rdatas at
|
||||
the same owner with different covered types (A, MX) and different
|
||||
TTLs (600, 1200). ns6 pulls the zone via dns_diff_load(), which
|
||||
calls diff.c rdata_covers(); before the fix that helper returned 0
|
||||
for SIG, so both tuples were grouped and filed under typepair
|
||||
(SIG, 0) with the first TTL (600) — the MX-covering record's TTL
|
||||
(1200) was silently dropped. With the fix the records land in
|
||||
distinct typepairs and both TTLs survive.
|
||||
the same owner with different "covered type" body fields (A, MX).
|
||||
Per RFC 3755 SIG has no covered-type semantics; both rdatas land in
|
||||
a single opaque rdataset and both survive in the zone DB.
|
||||
|
||||
rndc dumpdb is used to inspect the secondary's stored state
|
||||
directly; the wire-level response can merge same-(owner,type,class)
|
||||
|
|
@ -211,12 +195,11 @@ def test_sig_covers_preserved_via_axfr(ns6):
|
|||
else:
|
||||
raise AssertionError(f"{dump_path} never contained {deadline_marker!r}")
|
||||
|
||||
# Collect every SIG line for the owner from the dump. Format is:
|
||||
# <owner>. <ttl> IN SIG <covered> <alg> <labels> ...
|
||||
# Collect every SIG line for the owner from the dump.
|
||||
sig_lines = []
|
||||
for line in text.splitlines():
|
||||
fields = line.split()
|
||||
if len(fields) < 6:
|
||||
if len(fields) < 4:
|
||||
continue
|
||||
if not fields[0].lower().startswith("host.sigaxfr.nil"):
|
||||
continue
|
||||
|
|
@ -226,14 +209,10 @@ def test_sig_covers_preserved_via_axfr(ns6):
|
|||
|
||||
assert (
|
||||
len(sig_lines) == 2
|
||||
), f"expected 2 SIG records at {owner}, got {len(sig_lines)}: {sig_lines}"
|
||||
), f"expected 2 SIG rdatas at {owner}, got {len(sig_lines)}: {sig_lines}"
|
||||
|
||||
ttl_by_covers = {fields[4]: int(fields[1]) for fields in sig_lines}
|
||||
assert ttl_by_covers == {"A": 600, "MX": 1200}, (
|
||||
f"SIG records lost their covers/TTL binding: {ttl_by_covers}. With "
|
||||
"the Finding 1 bug both records are filed under typepair (SIG, 0) "
|
||||
"and share the first-seen TTL (600)."
|
||||
)
|
||||
ttls = {int(fields[1]) for fields in sig_lines}
|
||||
assert ttls == {600}, f"SIG rdataset should share a single TTL, got {ttls}"
|
||||
|
||||
|
||||
def parse_named_conf_keys(conf_text):
|
||||
|
|
|
|||
|
|
@ -720,20 +720,19 @@ dns_rdatatype_isknown(dns_rdatatype_t type) {
|
|||
|
||||
/*%
|
||||
* Return true iff a query for the rdata type can have multiple
|
||||
* unrelated answers in a response: ANY, RRSIG, or SIG.
|
||||
* unrelated answers in a response: ANY, or RRSIG.
|
||||
*/
|
||||
static inline bool
|
||||
dns_rdatatype_ismulti(dns_rdatatype_t type) {
|
||||
return type == dns_rdatatype_any || type == dns_rdatatype_rrsig ||
|
||||
type == dns_rdatatype_sig;
|
||||
return type == dns_rdatatype_any || type == dns_rdatatype_rrsig;
|
||||
}
|
||||
|
||||
/*%
|
||||
* Return true iff the rdata type is a signature: either RRSIG or SIG.
|
||||
* Return true iff the rdata type is RRSIG.
|
||||
*/
|
||||
static inline bool
|
||||
dns_rdatatype_issig(dns_rdatatype_t type) {
|
||||
return type == dns_rdatatype_rrsig || type == dns_rdatatype_sig;
|
||||
return type == dns_rdatatype_rrsig;
|
||||
}
|
||||
|
||||
/*%
|
||||
|
|
|
|||
|
|
@ -494,7 +494,6 @@ loadctx_create(dns_masterformat_t format, isc_mem_t *mctx, unsigned int options,
|
|||
.ttl_known = ((options & DNS_MASTER_NOTTL) != 0),
|
||||
.default_ttl_known = ((options & DNS_MASTER_NOTTL) != 0),
|
||||
.warn_1035 = true,
|
||||
.warn_tcr = true,
|
||||
.warn_sigexpired = true,
|
||||
.options = options,
|
||||
.zclass = zclass,
|
||||
|
|
@ -1947,16 +1946,6 @@ load_text(dns_loadctx_t *lctx) {
|
|||
}
|
||||
}
|
||||
|
||||
if ((type == dns_rdatatype_sig || type == dns_rdatatype_nxt) &&
|
||||
lctx->warn_tcr && dns_master_isprimary(lctx))
|
||||
{
|
||||
(*callbacks->warn)(callbacks,
|
||||
"%s:%lu: old style DNSSEC "
|
||||
" zone detected",
|
||||
source, line);
|
||||
lctx->warn_tcr = false;
|
||||
}
|
||||
|
||||
if ((lctx->options & DNS_MASTER_AGETTL) != 0) {
|
||||
/*
|
||||
* Adjust the TTL for $DATE. If the RR has
|
||||
|
|
|
|||
|
|
@ -1285,12 +1285,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
|
|||
issigzero = true;
|
||||
}
|
||||
} else {
|
||||
if (msg->rdclass != dns_rdataclass_any &&
|
||||
msg->rdclass != rdclass)
|
||||
{
|
||||
/* XXX test coverage */
|
||||
DO_ERROR(DNS_R_FORMERR);
|
||||
}
|
||||
covers = dns_rdatatype_none;
|
||||
}
|
||||
} else {
|
||||
covers = dns_rdatatype_none;
|
||||
|
|
|
|||
|
|
@ -380,8 +380,7 @@ dns_nsec_noexistnodata(dns_rdatatype_t type, const dns_name_t *name,
|
|||
(*logit)(arg, ISC_LOG_DEBUG(3), "ignoring child nsec");
|
||||
return ISC_R_IGNORE;
|
||||
}
|
||||
if (type == dns_rdatatype_cname || type == dns_rdatatype_nxt ||
|
||||
type == dns_rdatatype_nsec || type == dns_rdatatype_key ||
|
||||
if (type == dns_rdatatype_cname || type == dns_rdatatype_nsec ||
|
||||
!dns_nsec_typepresent(&rdata, dns_rdatatype_cname))
|
||||
{
|
||||
*exists = true;
|
||||
|
|
|
|||
|
|
@ -1940,9 +1940,7 @@ dns_nsec3_noexistnodata(dns_rdatatype_t type, const dns_name_t *name,
|
|||
return ISC_R_IGNORE;
|
||||
}
|
||||
if (type == dns_rdatatype_cname ||
|
||||
type == dns_rdatatype_nxt ||
|
||||
type == dns_rdatatype_nsec ||
|
||||
type == dns_rdatatype_key ||
|
||||
!dns_nsec3_typepresent(&rdata, dns_rdatatype_cname))
|
||||
{
|
||||
*exists = true;
|
||||
|
|
|
|||
|
|
@ -1578,11 +1578,9 @@ qpcache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
|
|||
|
||||
/*
|
||||
* Certain DNSSEC types are not subject to CNAME matching
|
||||
* (RFC4035, section 2.5 and RFC3007).
|
||||
* (RFC4035, section 2.5).
|
||||
*/
|
||||
if (type == dns_rdatatype_key || type == dns_rdatatype_nsec ||
|
||||
type == dns_rdatatype_rrsig)
|
||||
{
|
||||
if (type == dns_rdatatype_nsec || type == dns_rdatatype_rrsig) {
|
||||
cname_ok = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1828,9 +1828,7 @@ cname_and_other(qpznode_t *node, uint32_t serial) {
|
|||
if (first_existing_header(top, serial) != NULL) {
|
||||
cname = true;
|
||||
}
|
||||
} else if (rdtype != dns_rdatatype_key &&
|
||||
rdtype != dns_rdatatype_sig &&
|
||||
rdtype != dns_rdatatype_nsec &&
|
||||
} else if (rdtype != dns_rdatatype_nsec &&
|
||||
rdtype != dns_rdatatype_rrsig)
|
||||
{
|
||||
if (first_existing_header(top, serial) != NULL) {
|
||||
|
|
@ -3639,12 +3637,12 @@ found:
|
|||
|
||||
/*
|
||||
* Certain DNSSEC types are not subject to CNAME matching
|
||||
* (RFC4035, section 2.5 and RFC3007).
|
||||
* (RFC4035, section 2.5).
|
||||
*
|
||||
* We don't check for RRSIG, because we don't store RRSIG records
|
||||
* directly.
|
||||
*/
|
||||
if (type == dns_rdatatype_key || type == dns_rdatatype_nsec) {
|
||||
if (type == dns_rdatatype_nsec) {
|
||||
cname_ok = false;
|
||||
}
|
||||
|
||||
|
|
@ -3685,15 +3683,9 @@ found:
|
|||
search.need_cleanup = true;
|
||||
maybe_zonecut = false;
|
||||
at_zonecut = true;
|
||||
/*
|
||||
* It is not clear if KEY should still be
|
||||
* allowed at the parent side of the zone
|
||||
* cut or not. It is needed for RFC3007
|
||||
* validated updates.
|
||||
*/
|
||||
|
||||
if ((search.options & DNS_DBFIND_GLUEOK) == 0 &&
|
||||
type != dns_rdatatype_nsec &&
|
||||
type != dns_rdatatype_key)
|
||||
type != dns_rdatatype_nsec)
|
||||
{
|
||||
/*
|
||||
* Glue is not OK, but any answer we
|
||||
|
|
@ -3901,18 +3893,10 @@ found:
|
|||
/*
|
||||
* If we're beneath a zone cut, we must indicate that the
|
||||
* result is glue, unless we're actually at the zone cut
|
||||
* and the type is NSEC or KEY.
|
||||
* and the type is NSEC.
|
||||
*/
|
||||
if (search.zonecut == node) {
|
||||
/*
|
||||
* It is not clear if KEY should still be
|
||||
* allowed at the parent side of the zone
|
||||
* cut or not. It is needed for RFC3007
|
||||
* validated updates.
|
||||
*/
|
||||
if (dns_rdatatype_isnsec(type) ||
|
||||
type == dns_rdatatype_key)
|
||||
{
|
||||
if (dns_rdatatype_isnsec(type)) {
|
||||
result = ISC_R_SUCCESS;
|
||||
} else if (type == dns_rdatatype_any) {
|
||||
result = DNS_R_ZONECUT;
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@
|
|||
|
||||
#include <dst/dst.h>
|
||||
|
||||
#define RRTYPE_KEY_ATTRIBUTES \
|
||||
(DNS_RDATATYPEATTR_ATCNAME | DNS_RDATATYPEATTR_ZONECUTAUTH)
|
||||
#define RRTYPE_KEY_ATTRIBUTES (0)
|
||||
|
||||
static isc_result_t
|
||||
generic_fromtext_key(ARGS_FROMTEXT) {
|
||||
|
|
|
|||
|
|
@ -936,7 +936,7 @@ typedef struct respctx {
|
|||
* fctx_query() when resending */
|
||||
|
||||
dns_rdatatype_t type; /* type being sought (set to
|
||||
* ANY if qtype was SIG or RRSIG) */
|
||||
* ANY if qtype was RRSIG) */
|
||||
bool aa; /* authoritative answer? */
|
||||
dns_trust_t trust; /* answer trust level */
|
||||
bool chaining; /* CNAME/DNAME processing? */
|
||||
|
|
@ -4571,10 +4571,8 @@ resume_qmin(void *arg) {
|
|||
*/
|
||||
if ((result == DNS_R_CNAME || result == DNS_R_DNAME) &&
|
||||
fctx->qmin_labels == dns_name_countlabels(fctx->name) &&
|
||||
fctx->type != dns_rdatatype_key &&
|
||||
fctx->type != dns_rdatatype_nsec &&
|
||||
fctx->type != dns_rdatatype_any &&
|
||||
fctx->type != dns_rdatatype_sig &&
|
||||
fctx->type != dns_rdatatype_rrsig)
|
||||
{
|
||||
pull_from_resp(resp, fctx);
|
||||
|
|
@ -5577,13 +5575,9 @@ evict_cname_other(fetchctx_t *fctx, dns_name_t *name) {
|
|||
dns_typepair_t typepair = DNS_TYPEPAIR_VALUE(rdataset.type,
|
||||
rdataset.covers);
|
||||
switch (typepair) {
|
||||
/* KEY, NSEC and NXT records are allowed */
|
||||
/* NSEC records are allowed */
|
||||
case DNS_TYPEPAIR(dns_rdatatype_nsec):
|
||||
case DNS_TYPEPAIR(dns_rdatatype_nxt):
|
||||
case DNS_TYPEPAIR(dns_rdatatype_key):
|
||||
case DNS_SIGTYPEPAIR(dns_rdatatype_nsec):
|
||||
case DNS_SIGTYPEPAIR(dns_rdatatype_nxt):
|
||||
case DNS_SIGTYPEPAIR(dns_rdatatype_key):
|
||||
/* Keep the CNAME and its signature */
|
||||
case DNS_TYPEPAIR(dns_rdatatype_cname):
|
||||
case DNS_SIGTYPEPAIR(dns_rdatatype_cname):
|
||||
|
|
@ -5663,9 +5657,7 @@ cache_rrset(fetchctx_t *fctx, isc_stdtime_t now, dns_name_t *name,
|
|||
* along with the covered RRset in 'delete_rrset()'.
|
||||
*/
|
||||
if (!dns_rdataset_matchestype(rdataset, dns_rdatatype_cname) &&
|
||||
!dns_rdataset_matchestype(rdataset, dns_rdatatype_key) &&
|
||||
!dns_rdataset_matchestype(rdataset, dns_rdatatype_nsec) &&
|
||||
!dns_rdataset_matchestype(rdataset, dns_rdatatype_nxt))
|
||||
!dns_rdataset_matchestype(rdataset, dns_rdatatype_nsec))
|
||||
{
|
||||
delete_rrset(fctx, name, dns_rdatatype_cname);
|
||||
}
|
||||
|
|
@ -8132,7 +8124,7 @@ rctx_answer_init(respctx_t *rctx) {
|
|||
}
|
||||
|
||||
/*
|
||||
* There can be multiple RRSIG and SIG records at a name so
|
||||
* There can be multiple RRSIG records at a name so
|
||||
* we treat these types as a subset of ANY.
|
||||
*/
|
||||
rctx->type = fctx->type;
|
||||
|
|
@ -8871,7 +8863,7 @@ rctx_answer_cname(respctx_t *rctx) {
|
|||
}
|
||||
|
||||
if (rctx->type == dns_rdatatype_rrsig ||
|
||||
rctx->type == dns_rdatatype_key || rctx->type == dns_rdatatype_nsec)
|
||||
rctx->type == dns_rdatatype_nsec)
|
||||
{
|
||||
char buf[DNS_RDATATYPE_FORMATSIZE];
|
||||
dns_rdatatype_format(rctx->type, buf, sizeof(buf));
|
||||
|
|
|
|||
|
|
@ -1687,12 +1687,6 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
|
|||
} else if (rdata.type == dns_rdatatype_nsec) {
|
||||
FAILC(DNS_R_REFUSED, "explicit NSEC updates are not "
|
||||
"allowed in secure zones");
|
||||
} else if (rdata.type == dns_rdatatype_sig) {
|
||||
FAILC(DNS_R_REFUSED, "SIG updates are not "
|
||||
"allowed");
|
||||
} else if (rdata.type == dns_rdatatype_nxt) {
|
||||
FAILC(DNS_R_REFUSED, "NXT updates are not "
|
||||
"allowed");
|
||||
} else if (rdata.type == dns_rdatatype_rrsig &&
|
||||
!dns_name_equal(name, zonename))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3365,7 +3365,6 @@ ISC_RUN_TEST_IMPL(atcname) {
|
|||
bool tf = dns_rdatatype_atcname((dns_rdatatype_t)i);
|
||||
switch (i) {
|
||||
case dns_rdatatype_nsec:
|
||||
case dns_rdatatype_key:
|
||||
case dns_rdatatype_rrsig:
|
||||
if (!tf) {
|
||||
print_message(UNR, i);
|
||||
|
|
@ -3416,7 +3415,6 @@ ISC_RUN_TEST_IMPL(iszonecutauth) {
|
|||
case dns_rdatatype_ns:
|
||||
case dns_rdatatype_ds:
|
||||
case dns_rdatatype_nsec:
|
||||
case dns_rdatatype_key:
|
||||
case dns_rdatatype_rrsig:
|
||||
if (!tf) {
|
||||
print_message(UNR, i);
|
||||
|
|
|
|||
Loading…
Reference in a new issue