mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-28 03:20:23 -04:00
Add dnssec_py/tests_sibling_ds: reject DS for sibling zones in referrals
Add a system test that verifies the resolver rejects DS records whose owner name does not match the delegation (NS) name in a referral response. A custom authoritative server (ans4) serves the parent zone sibling-ds. from zone file with delegations for child and sibling subzones. Its DomainHandler injects a DS record for sibling.sibling-ds into referrals for child.sibling-ds. The resolver must detect the mismatch, log "DS doesn't match referral (NS)", and return SERVFAIL. Assisted-by: Claude:claude-opus-4-8
This commit is contained in:
parent
95a268f119
commit
a2b9dcff54
3 changed files with 137 additions and 0 deletions
65
bin/tests/system/dnssec_py/ans4/ans.py
Normal file
65
bin/tests/system/dnssec_py/ans4/ans.py
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# 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.
|
||||
|
||||
"""
|
||||
Custom authoritative server for the sibling-ds test.
|
||||
|
||||
When returning a referral for child.sibling-ds, this server injects a DS
|
||||
record for sibling.sibling-ds into the authority section. The resolver
|
||||
should reject this because the DS owner name does not match the
|
||||
delegation (NS) name.
|
||||
"""
|
||||
|
||||
from collections.abc import AsyncGenerator
|
||||
|
||||
import dns.rdatatype
|
||||
import dns.rrset
|
||||
|
||||
from isctest.asyncserver import (
|
||||
AsyncDnsServer,
|
||||
DnsResponseSend,
|
||||
DomainHandler,
|
||||
QueryContext,
|
||||
ResponseAction,
|
||||
)
|
||||
|
||||
|
||||
class SiblingDsInjectionHandler(DomainHandler):
|
||||
"""Inject a DS record for sibling.sibling-ds into child.sibling-ds referrals."""
|
||||
|
||||
domains = ["child.sibling-ds."]
|
||||
|
||||
async def get_responses(
|
||||
self, qctx: QueryContext
|
||||
) -> AsyncGenerator[ResponseAction, None]:
|
||||
# The default zone-data response already has the NS delegation for
|
||||
# child.sibling-ds. and glue. Add a DS record for the *sibling* zone
|
||||
# (wrong name for this referral).
|
||||
sibling_ds = dns.rrset.from_text(
|
||||
"sibling.sibling-ds.",
|
||||
300,
|
||||
qctx.qclass,
|
||||
dns.rdatatype.DS,
|
||||
"12345 8 2 "
|
||||
"49FD46E6C4B45C55D4AC69CBD3CD34AC1AFE51DE7B2B585ABCDEABCDEABCDEAB",
|
||||
)
|
||||
qctx.response.authority.append(sibling_ds)
|
||||
yield DnsResponseSend(qctx.response)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
server = AsyncDnsServer()
|
||||
server.install_response_handler(SiblingDsInjectionHandler())
|
||||
server.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -13,6 +13,8 @@ import pytest
|
|||
|
||||
DNSSEC_PY_MARK = pytest.mark.extra_artifacts(
|
||||
[
|
||||
"ans*/*.db",
|
||||
"ans*/*.run",
|
||||
"ns*/dsset-*",
|
||||
"ns*/trusted.conf",
|
||||
"ns*/zones/*.db",
|
||||
|
|
|
|||
70
bin/tests/system/dnssec_py/tests_sibling_ds.py
Normal file
70
bin/tests/system/dnssec_py/tests_sibling_ds.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# 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.
|
||||
|
||||
"""
|
||||
Test that the resolver rejects DS records for sibling zones in referrals.
|
||||
|
||||
A custom authoritative server (ans4) returns a referral for
|
||||
child.sibling-ds that includes a DS record for sibling.sibling-ds. The
|
||||
resolver must detect that the DS owner does not match the delegation NS
|
||||
name and treat the response as a form error.
|
||||
"""
|
||||
|
||||
from re import compile as Re
|
||||
|
||||
from dnssec_py.common import DNSSEC_PY_MARK
|
||||
from isctest.template import NS2, Nameserver, zones
|
||||
from isctest.zone import Zone, configure_root
|
||||
|
||||
import isctest
|
||||
|
||||
pytestmark = DNSSEC_PY_MARK
|
||||
|
||||
ANS4 = Nameserver("ans4")
|
||||
|
||||
|
||||
def bootstrap():
|
||||
# Child zone on ns2 — the test queries a.child.sibling-ds which
|
||||
# resolves to the default template A record (10.0.0.1).
|
||||
child = Zone("child.sibling-ds", NS2)
|
||||
child.configure()
|
||||
|
||||
# Sibling zone on ns2 — exists so the sibling DS in the referral
|
||||
# refers to a real delegation.
|
||||
sibling = Zone("sibling.sibling-ds", NS2)
|
||||
sibling.configure()
|
||||
|
||||
# Parent zone rendered into ans4/ (subdir=None puts the .db file
|
||||
# directly in the ans4 directory where AsyncDnsServer loads it).
|
||||
parent = Zone("sibling-ds", ANS4, subdir=None)
|
||||
parent.delegations = [child, sibling]
|
||||
parent.configure()
|
||||
|
||||
# Root zone delegates sibling-ds. to ans4.
|
||||
root = configure_root([parent])
|
||||
|
||||
return {
|
||||
"trust_anchors": root.trust_anchors(),
|
||||
"zones": zones([root, child, sibling]),
|
||||
}
|
||||
|
||||
|
||||
def test_sibling_ds_rejected(ns9):
|
||||
"""Resolver must reject a referral that contains DS for a sibling zone."""
|
||||
log_ds_mismatch = Re(r"DS doesn't match the delegation owner name")
|
||||
|
||||
msg = isctest.query.create("a.child.sibling-ds.", "A")
|
||||
|
||||
with ns9.watch_log_from_here() as watcher:
|
||||
res = isctest.query.tcp(msg, ns9.ip)
|
||||
watcher.wait_for_line(log_ds_mismatch)
|
||||
|
||||
isctest.check.servfail(res)
|
||||
Loading…
Reference in a new issue