diff --git a/bin/tests/system/nsupdate/tests_sh_nsupdate.py b/bin/tests/system/nsupdate/tests_sh_nsupdate.py index bd41ac64c5..51e22c9985 100644 --- a/bin/tests/system/nsupdate/tests_sh_nsupdate.py +++ b/bin/tests/system/nsupdate/tests_sh_nsupdate.py @@ -58,6 +58,7 @@ pytestmark = pytest.mark.extra_artifacts( "ns5/local.db", "ns6/2.0.0.2.ip6.addr.db", "ns6/in-addr.db", + "ns6/sigaxfr.bk", "ns7/_default.tsigkeys", "ns7/example.com.db", "ns7/in-addr.db", diff --git a/bin/tests/system/nsupdate/tests_tcp_self_sig.py b/bin/tests/system/nsupdate/tests_update_sig.py similarity index 84% rename from bin/tests/system/nsupdate/tests_tcp_self_sig.py rename to bin/tests/system/nsupdate/tests_update_sig.py index 6e83aded29..42f60a2b56 100644 --- a/bin/tests/system/nsupdate/tests_tcp_self_sig.py +++ b/bin/tests/system/nsupdate/tests_update_sig.py @@ -39,9 +39,29 @@ import dns.rdataclass import dns.rdataset import dns.rdatatype import dns.update +import pytest import isctest +pytestmark = pytest.mark.extra_artifacts( + [ + "ans*/ans.run", + "ns*/*.bk", + "ns*/*.conf", + "ns*/*.db", + "ns*/*.db.jnl", + "ns*/*.db.signed", + "ns*/*.jnl", + "ns*/*.key", + "ns*/K*.key", + "ns*/K*.private", + "ns*/K*.state", + "ns*/dsset-*.", + "ns6/sigaxfr.bk", + "verylarge", + ] +) + def _make_sig_rdata(text): """Create a SIG rdata from text. @@ -79,9 +99,9 @@ def test_tcp_self_sig_record(ns6): crash-reproducing precondition. """ ptr_update = dns.update.UpdateMessage("in-addr.arpa.") - ptr_update.add("1.0.0.127.in-addr.arpa.", 600, "PTR", "localhost.") + ptr_update.add("1.0.53.10.in-addr.arpa.", 600, "PTR", "localhost.") response = isctest.query.tcp( - ptr_update, ns6.ip, port=ns6.ports.dns, source="127.0.0.1" + ptr_update, ns6.ip, port=ns6.ports.dns, source="10.53.0.1" ) assert response.rcode() == dns.rcode.NOERROR @@ -92,18 +112,58 @@ def test_tcp_self_sig_record(ns6): sig_update = dns.update.UpdateMessage("in-addr.arpa.") sig_update.add("1.0.0.127.in-addr.arpa.", rds) - response = isctest.query.tcp( - sig_update, ns6.ip, port=ns6.ports.dns, source="127.0.0.1" - ) - assert response.rcode() == dns.rcode.REFUSED + 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 + + 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.0.127.in-addr.arpa.", "SIG") + msg = isctest.query.create("1.0.53.10.in-addr.arpa.", "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" +def test_tcp_self_nxt_record(ns6): + """NXT (type 30) updates must be refused at the front door. + + 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. + """ + # A second owner under a source that also matches tcp-self. + source = "10.53.0.2" + owner = "2.0.53.10.in-addr.arpa." + + ptr_update = dns.update.UpdateMessage("in-addr.arpa.") + ptr_update.add(owner, 600, "PTR", "localhost.") + response = isctest.query.tcp(ptr_update, ns6.ip, port=ns6.ports.dns, source=source) + assert response.rcode() == dns.rcode.NOERROR + + nxt = _make_nxt_rdata() + rds = dns.rdataset.Rdataset(dns.rdataclass.IN, dns.rdatatype.NXT) + rds.update_ttl(600) + rds.add(nxt) + 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 + + watcher.wait_for_line( + "updating zone 'in-addr.arpa/IN': update failed: NXT updates are not allowed (REFUSED)" + ) + + def test_sig_covers_preserved_via_axfr(ns6): """Regression test for GL#5818 Finding 1, reached via AXFR. @@ -170,31 +230,3 @@ def test_sig_covers_preserved_via_axfr(ns6): "the Finding 1 bug both records are filed under typepair (SIG, 0) " "and share the first-seen TTL (600)." ) - - -def test_tcp_self_nxt_record(ns6): - """NXT (type 30) updates must be refused at the front door. - - 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. - """ - # A second owner under a source that also matches tcp-self. - source = "127.0.0.2" - owner = "2.0.0.127.in-addr.arpa." - - ptr_update = dns.update.UpdateMessage("in-addr.arpa.") - ptr_update.add(owner, 600, "PTR", "localhost.") - response = isctest.query.tcp(ptr_update, ns6.ip, port=ns6.ports.dns, source=source) - assert response.rcode() == dns.rcode.NOERROR - - nxt = _make_nxt_rdata() - rds = dns.rdataset.Rdataset(dns.rdataclass.IN, dns.rdatatype.NXT) - rds.update_ttl(600) - rds.add(nxt) - nxt_update = dns.update.UpdateMessage("in-addr.arpa.") - nxt_update.add(owner, rds) - - response = isctest.query.tcp(nxt_update, ns6.ip, port=ns6.ports.dns, source=source) - assert response.rcode() == dns.rcode.REFUSED