mirror of
https://gitlab.nic.cz/knot/knot-dns.git
synced 2026-05-28 04:02:31 -04:00
157 lines
5.6 KiB
Python
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()
|