knot-dns/tests-extra/tests/basic/deleg/test.py
Libor Peltan 5de6f107c1 DELEG: conf knob to enforce/override DELEG-awareness...
...manually, e.g. even for unsigned zones
2026-05-06 12:14:06 +02:00

157 lines
5.6 KiB
Python

#!/usr/bin/env python3
'''Various tests of DELEG-aware and unaware auth server answering.'''
from dnstest.test import Test
from dnstest.utils import *
import random
import shutil
DELEGATIONS = [ "ns.d.xdp.cz.", "ns-ds.d.xdp.cz.", "deleg.d.xdp.cz.", "deleg-ds.d.xdp.cz.",
"deleg-ns.d.xdp.cz.", "deleg-ns-ds.d.xdp.cz." ]
CHILDS_DNSSEC = random.choice([False, True])
def check_normal(resp, presence, rrtype, dnssec=True): # check positive answer or NODATA
resp.check(rcode="NOERROR")
resp.check_count(0, "NS", section="authority")
resp.check_count(0, "TYPE61440", section="authority")
if presence:
resp.check_count(1, rrtype, section="answer")
else:
resp.check_count(1, "SOA", section="authority")
resp.check_count(1 if dnssec else 0, "NSEC", section="authority")
if (resp.resp.ednsflags & (1<<13)) != ((1<<13) if debit else 0): # resp.check(noeflags=...) requires DEflag support in dnspython
set_err("%sDE flag in response" % ("no " if debit else ""))
def check_delegation(resp, D, debit):
resp.check(rcode="NOERROR")
resp.check_count(0, "A", section="answer")
resp.check_count(0, "TYPE61440", section="answer")
if debit and ("deleg" in D):
resp.check_count(1, "TYPE61440", section="authority")
else:
resp.check_count(1, "NS", section="authority")
if debit:
resp.check_count(1, "NSEC", section="authority")
if "ds" in D:
resp.check_count(1, "DS", section="authority")
else:
resp.check_count(1, "NSEC", section="authority")
if (resp.resp.ednsflags & (1<<13)) != ((1<<13) if debit else 0): # resp.check(noeflags=...) requires DEflag support in dnspython
set_err("%sDE flag in response" % ("no " if debit else ""))
def check_nxdomain(resp, nsec_count, dnssec=True):
resp.check(rcode="NXDOMAIN")
resp.check_count(0, "A", section="answer")
resp.check_count(0, "TYPE61440", section="answer")
resp.check_count(0, "TYPE61440", section="authority")
resp.check_count(1, "SOA", section="authority")
resp.check_count(nsec_count if dnssec else 0, "NSEC", section="authority")
resp.check_count(0, "NS", section="authority")
def check_adt(server, zone_name, expected):
resp = server.dig(zone_name, "DNSKEY")
adt_found = False
for dnskey_rr in resp.resp.answer[0].to_rdataset():
adt_found = adt_found or (dnskey_rr.flags & 2 != 0)
compare(adt_found, expected, "ADT bit%s set" % ("" if expected else " not"))
t = Test()
knot = t.server("knot")
parent = t.zone("d.xdp.cz.", storage=".")
childs = []
shutil.copy(os.path.join(t.data_dir, "child-generic.zone"), os.path.join(knot.dir, "child-generic.zone"))
for childz in DELEGATIONS:
zf = os.path.join(knot.dir, "%szone" % childz)
shutil.copy(os.path.join(t.data_dir, "child-generic.zone"), zf)
childs += t.zone(childz, file_name=zf)
t.link(parent, knot)
knot.dnssec(parent).enable = True
t.start()
parent_serial = knot.zone_wait(parent)
check_adt(knot, parent[0].name, False)
isset(knot.log_search("no DNSKEY with ADT bit"), "warning of missing ADT")
knot.dnssec(parent).deleg_adt = True
knot.gen_confile()
knot.reload()
t.sleep(2)
check_adt(knot, parent[0].name, False)
knot.ctl("zone-key-rollover %s zsk" % parent[0].name)
parent_serial = knot.zone_wait(parent, parent_serial)
check_adt(knot, parent[0].name, True)
for childs_running in [ False, True ]:
if childs_running and DELEGATIONS[0] not in knot.zones:
t.link(childs, knot)
if CHILDS_DNSSEC:
knot.dnssec(childs).enable = True
knot.dnssec(childs).deleg_adt = True
else:
knot.conf_zone(childs).deleg_aware = True
knot.gen_confile()
knot.reload()
serials = knot.zones_wait(childs)
for debit in [ False, True ]:
for D in DELEGATIONS:
understood = (debit or ("ns" in D)) # the client understands that there IS a delegation
resp = knot.dig("dns1." + D, "A", dnssec=True, de=debit)
if childs_running: # direct answer from child zone
check_normal(resp, True, "A", CHILDS_DNSSEC)
elif understood:
check_delegation(resp, D, debit)
else:
check_nxdomain(resp, 1)
resp = knot.dig("dns2." + D, "A", dnssec=True, de=debit)
if childs_running:
check_nxdomain(resp, 2, CHILDS_DNSSEC)
elif understood:
check_delegation(resp, D, debit)
else:
check_nxdomain(resp, 1)
resp = knot.dig(D, "DS", dnssec=True, de=debit)
check_normal(resp, "ds" in D, "DS")
resp = knot.dig(D, "TYPE61440", dnssec=True, de=debit)
if debit:
check_normal(resp, "deleg" in D, "TYPE61440")
elif childs_running:
check_normal(resp, False, "TYPE61440", CHILDS_DNSSEC)
elif "ns" in D: # understood
check_delegation(resp, D, debit)
else:
check_normal(resp, True, "TYPE61440")
resp = knot.dig(D, "NS", dnssec=True, de=debit)
if childs_running:
check_normal(resp, True, "NS", CHILDS_DNSSEC)
elif understood:
check_delegation(resp, D, debit)
else:
check_normal(resp, False, "NS")
resp = knot.dig(D, "A", dnssec=True, de=debit)
if childs_running:
check_normal(resp, False, "A", CHILDS_DNSSEC)
elif understood:
check_delegation(resp, D, debit)
else:
check_normal(resp, False, "A")
knot.ctl("zone-flush", wait=True)
t.end()