mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-10 21:20:00 -04:00
chg: usr: Lowercase the NSEC next owner name when signing
When building the NSEC rdata, lowercase the next owner name before storing it in the Next Domain Name Field. Note that this is not required according to RFC 6840, but since there is inconsistency in the documents over time, having uppercase next owner names in the NSEC records may cause validation failures if validators are not following RFC 6840. Closes #5702 Merge branch '5702-lowercase-nsec-next-owner-name' into 'main' See merge request isc-projects/bind9!11442
This commit is contained in:
commit
dd8651ff36
6 changed files with 91 additions and 7 deletions
|
|
@ -952,6 +952,8 @@ def _check_signatures(
|
|||
zrrsig = False
|
||||
krrsig = not zrrsig
|
||||
|
||||
signer = fqdn.lower()
|
||||
|
||||
for key in keys:
|
||||
if key.external:
|
||||
continue
|
||||
|
|
@ -963,7 +965,7 @@ def _check_signatures(
|
|||
alg = key.get_dnsalg()
|
||||
rtype = dns.rdatatype.to_text(covers)
|
||||
|
||||
expect = rf"IN RRSIG {rtype} {alg} (\d) (\d+) (\d+) (\d+) {key.tag} {fqdn}"
|
||||
expect = rf"IN RRSIG {rtype} {alg} (\d) (\d+) (\d+) (\d+) {key.tag} {signer}"
|
||||
|
||||
if zrrsig and zsigning:
|
||||
has_rrsig = False
|
||||
|
|
@ -1572,17 +1574,18 @@ def keydir_to_keylist(
|
|||
"""
|
||||
if zone is None:
|
||||
zone = ""
|
||||
zname = zone.lower()
|
||||
|
||||
all_keys = []
|
||||
if keydir is None:
|
||||
regex = rf"(K{zone}\.\+.*\+.*)\.key"
|
||||
for filename in glob.glob(f"K{zone}.+*+*.key"):
|
||||
regex = rf"(K{zname}\.\+.*\+.*)\.key"
|
||||
for filename in glob.glob(f"K{zname}.+*+*.key"):
|
||||
match = re.match(regex, filename)
|
||||
if match is not None:
|
||||
all_keys.append(Key(match.group(1)))
|
||||
else:
|
||||
regex = rf"{keydir}/(K{zone}\.\+.*\+.*)\.key"
|
||||
for filename in glob.glob(f"{keydir}/K{zone}.+*+*.key"):
|
||||
regex = rf"{keydir}/(K{zname}\.\+.*\+.*)\.key"
|
||||
for filename in glob.glob(f"{keydir}/K{zname}.+*+*.key"):
|
||||
match = re.match(regex, filename)
|
||||
if match is not None:
|
||||
all_keys.append(Key(match.group(1), keydir))
|
||||
|
|
|
|||
|
|
@ -20,6 +20,13 @@ zone "default.kasp" {
|
|||
dnssec-policy "default";
|
||||
};
|
||||
|
||||
/* The UPPER case: a zone with uppercase characters. */
|
||||
zone "UPPER.KASP" {
|
||||
type primary;
|
||||
file "upper.kasp.db";
|
||||
dnssec-policy "default";
|
||||
};
|
||||
|
||||
/* A zone with special characters. */
|
||||
zone {% raw %}"i-am.\":\;?&[]\@!\$*+,|=\.\(\)special.kasp."{% endraw %} {
|
||||
type primary;
|
||||
|
|
|
|||
|
|
@ -56,12 +56,16 @@ for zn in default dnssec-keygen some-keys legacy-keys pregenerated \
|
|||
done
|
||||
|
||||
#
|
||||
# Setup special zone
|
||||
# Setup special zones
|
||||
#
|
||||
zone="i-am.\":\;?&[]\@!\$*+,|=\.\(\)special.kasp."
|
||||
echo_i "setting up zone: $zone"
|
||||
cp template.db.in "i-am.special.kasp.db"
|
||||
|
||||
zone="UPPER.KASP."
|
||||
echo_i "setting up zone: $zone"
|
||||
cp upper.kasp.db.in "upper.kasp.db"
|
||||
|
||||
#
|
||||
# Set up RSASHA1 based zones
|
||||
#
|
||||
|
|
|
|||
27
bin/tests/system/kasp/ns3/upper.kasp.db.in
Normal file
27
bin/tests/system/kasp/ns3/upper.kasp.db.in
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
; 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.
|
||||
|
||||
$TTL 300
|
||||
UPPER.KASP. IN SOA MNAME1. . (
|
||||
1 ; serial
|
||||
20 ; refresh (20 seconds)
|
||||
20 ; retry (20 seconds)
|
||||
1814400 ; expire (3 weeks)
|
||||
3600 ; minimum (1 hour)
|
||||
)
|
||||
|
||||
NS ns3
|
||||
ns3 A 10.53.0.3
|
||||
|
||||
a A 10.0.0.1
|
||||
b A 10.0.0.2
|
||||
c A 10.0.0.3
|
||||
|
||||
|
|
@ -936,6 +936,42 @@ def test_kasp_default(ns3):
|
|||
check_all(ns3, zone, policy, keys, [])
|
||||
|
||||
|
||||
def test_kasp_uppercase(ns3):
|
||||
# check the zone with uppercase characters is loaded and signed.
|
||||
isctest.log.info("check a zone with upper case characters is signed")
|
||||
zone = "UPPER.KASP"
|
||||
policy = "default"
|
||||
|
||||
isctest.kasp.wait_keymgr_done(ns3, zone)
|
||||
|
||||
# Key properties.
|
||||
# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait.
|
||||
keyprops = [
|
||||
"csk 0 13 256 goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden",
|
||||
]
|
||||
expected = isctest.kasp.policy_to_properties(ttl=3600, keys=keyprops)
|
||||
keys = isctest.kasp.keydir_to_keylist(zone, "ns3")
|
||||
isctest.kasp.check_dnssec_verify(ns3, zone)
|
||||
isctest.kasp.check_keys(zone, keys, expected)
|
||||
set_keytimes_default_policy(expected[0])
|
||||
isctest.kasp.check_keytimes(keys, expected)
|
||||
check_all(ns3, zone, policy, keys, [])
|
||||
|
||||
fqdn = f"{zone}."
|
||||
query = isctest.query.create(fqdn, dns.rdatatype.NSEC)
|
||||
response = isctest.query.tcp(query, ns3.ip)
|
||||
assert response.rcode() == dns.rcode.NOERROR
|
||||
|
||||
nsec = response.get_rrset(
|
||||
response.answer,
|
||||
dns.name.from_text(fqdn),
|
||||
dns.rdataclass.IN,
|
||||
dns.rdatatype.NSEC,
|
||||
)
|
||||
nextname = nsec[0].next
|
||||
assert str(nextname) == "a.upper.kasp."
|
||||
|
||||
|
||||
def test_kasp_dynamic(ns3):
|
||||
# Standard dynamic zone.
|
||||
isctest.log.info("check dynamic zone is updated and signed after update")
|
||||
|
|
|
|||
|
|
@ -100,11 +100,18 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node,
|
|||
unsigned char *nsec_bits, *bm;
|
||||
unsigned int max_type;
|
||||
dns_rdatasetiter_t *rdsiter;
|
||||
dns_fixedname_t fnextname;
|
||||
dns_name_t *nextname;
|
||||
|
||||
REQUIRE(target != NULL);
|
||||
|
||||
/*
|
||||
* Downcase next owner name.
|
||||
*/
|
||||
nextname = dns_fixedname_initname(&fnextname);
|
||||
RUNTIME_CHECK(dns_name_downcase(target, nextname) == ISC_R_SUCCESS);
|
||||
memset(buffer, 0, DNS_NSEC_BUFFERSIZE);
|
||||
dns_name_toregion(target, &r);
|
||||
dns_name_toregion(nextname, &r);
|
||||
memmove(buffer, r.base, r.length);
|
||||
r.base = buffer;
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in a new issue