From: Ondřej Surý Date: Tue, 7 Apr 2026 14:40:36 +0000 (+0200) Subject: Add system test for SIG record handling in update-policy tcp-self X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ecddeab6962fe7aab70ccaff56fab8f496316a9b;p=thirdparty%2Fbind9.git Add system test for SIG record handling in update-policy tcp-self Verify that a SIG record sent via TCP dynamic update is accepted by the tcp-self update-policy and correctly stored in the zone. --- diff --git a/bin/tests/system/nsupdate/tests_tcp_self_sig.py b/bin/tests/system/nsupdate/tests_tcp_self_sig.py new file mode 100644 index 00000000000..3378097e30f --- /dev/null +++ b/bin/tests/system/nsupdate/tests_tcp_self_sig.py @@ -0,0 +1,88 @@ +# 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. + +""" +Regression test for GL#5818: update-policy tcp-self must handle SIG records. + +The dns_db_findrdataset() REQUIRE check only accepted dns_rdatatype_rrsig +for the covers parameter, causing named to abort when processing a SIG +record (type 24) via dynamic update with tcp-self policy. +""" + +import dns.rcode +import dns.rdata +import dns.rdataclass +import dns.rdataset +import dns.rdatatype +import dns.update + +import isctest + + +def _make_sig_rdata(text): + """Create a SIG rdata from text. + + dnspython has no native text parser for the legacy SIG type (24), + but the wire format is identical to RRSIG (46). Parse as RRSIG, + then re-wrap as SIG via the wire representation. + """ + rrsig = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.RRSIG, text) + wire = rrsig.to_digestable() + return dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.SIG, wire, 0, len(wire)) + + +def test_tcp_self_sig_record(ns6): + """Verify that update-policy tcp-self accepts a SIG record via TCP. + + The node must already exist (have at least one RR) so that + dns_db_findrdataset() is called during the update — that is the + function whose REQUIRE was too strict. We therefore add a PTR + record first. + """ + # First, create the node by adding a PTR record (allowed by tcp-self). + ptr_update = dns.update.UpdateMessage("in-addr.arpa.") + ptr_update.add("1.0.0.127.in-addr.arpa.", 600, "PTR", "localhost.") + response = isctest.query.tcp( + ptr_update, ns6.ip, port=ns6.ports.dns, source="127.0.0.1" + ) + assert response.rcode() == dns.rcode.NOERROR + + # Now add a SIG record at the same node — this triggers the + # dns_db_findrdataset() call with type=SIG and covers=A. + sig = _make_sig_rdata("A 6 0 86400 20260331170000 20260318160000 21831 . 0000") + rds = dns.rdataset.Rdataset(dns.rdataclass.IN, dns.rdatatype.SIG) + 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) + + with ns6.watch_log_from_here() as watcher: + response = isctest.query.tcp( + sig_update, ns6.ip, port=ns6.ports.dns, source="127.0.0.1" + ) + assert response.rcode() == dns.rcode.NOERROR + + watcher.wait_for_sequence( + [ + "update-policy: using: signer= name=1.0.0.127.in-addr.arpa" + " addr=127.0.0.1 tcp=1 type=SIG target=", + "update-policy: trying: grant * tcp-self . PTR(1) ANY(2) A", + "update-policy: tcp-self=1.0.0.127.IN-ADDR.ARPA", + "update-policy: matched: grant * tcp-self . PTR(1) ANY(2) A", + ] + ) + + # Verify the SIG record was actually stored + msg = isctest.query.create("1.0.0.127.in-addr.arpa.", "SIG") + res = isctest.query.tcp(msg, ns6.ip, port=ns6.ports.dns) + found = any(rrset.rdtype == dns.rdatatype.SIG for rrset in res.answer) + assert found, "SIG record not found in answer section"