]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
dnssec/DELEG: conf knob in policy triggers ADT
authorLibor Peltan <libor.peltan@nic.cz>
Fri, 6 Feb 2026 14:36:52 +0000 (15:36 +0100)
committerLibor Peltan <libor.peltan@nic.cz>
Wed, 6 May 2026 10:14:06 +0000 (12:14 +0200)
doc/reference.rst
src/knot/conf/schema.c
src/knot/conf/schema.h
src/knot/dnssec/context.c
src/knot/dnssec/policy.c
tests-extra/tests/basic/deleg/test.py

index 0df9a42756e102c9a6e54e70e17842a451842096..2ceb218db60c21fdc091aad8a1a31e7773c86a0e 100644 (file)
@@ -2109,6 +2109,7 @@ DNSSEC policy configuration.
      keytag-modulo: INT/INT
      ksk-lifetime: TIME
      zsk-lifetime: TIME
+     deleg-adt: BOOL
      delete-delay: TIME
      propagation-delay: TIME
      rrsig-lifetime: TIME
@@ -2318,6 +2319,16 @@ A period (in seconds) between ZSK activation and the next rollover initiation.
 
 *Default:* ``30d`` (30 days)
 
+.. _policy_deleg-adt:
+
+deleg-adt
+---------
+
+All newly generated keys will have ADT bit set, signaling possible presence
+of DELEG RRs in the zone.
+
+*Default:* ``off``
+
 .. _policy_delete-delay:
 
 delete-delay
index bf599c558d4f2dfbf2424178c49531ceefbc25fd..ec02228732720d04c6de1223871b740d9ab93e14 100644 (file)
@@ -433,6 +433,7 @@ static const yp_item_t desc_policy[] = {
                                           CONF_IO_FRLD_ZONES },
        { C_ZSK_LIFETIME,        YP_TINT,  YP_VINT = { 0, UINT32_MAX, DAYS(30), YP_STIME },
                                           CONF_IO_FRLD_ZONES },
+       { C_DELEG_ADT,           YP_TBOOL, YP_VNONE },
        { C_DELETE_DELAY,        YP_TINT,  YP_VINT = { 0, UINT32_MAX, 0, YP_STIME } },
        { C_PROPAG_DELAY,        YP_TINT,  YP_VINT = { 0, INT32_MAX, HOURS(1), YP_STIME },
                                           CONF_IO_FRLD_ZONES },
index 385142970b16e678c12993e960dd6626991233c3..2b07ec55020a440254f407faf12946944dd412be 100644 (file)
@@ -46,6 +46,7 @@
 #define C_DBUS_INIT_DELAY      "\x0F""dbus-init-delay"
 #define C_DDNS_MASTER          "\x0B""ddns-master"
 #define C_DEFAULT_TTL          "\x0B""default-ttl"
+#define C_DELEG_ADT             "\x09""deleg-adt"
 #define C_DENY                 "\x04""deny"
 #define C_DNSKEY_MGMT          "\x11""dnskey-management"
 #define C_DNSKEY_SYNC          "\x0B""dnskey-sync"
index 27e311095c420ab0e82ea32e03570d9ab2f9bd56..24f82d474c957385490ef5ad26aec3b1b37b5e3e 100644 (file)
@@ -63,6 +63,9 @@ static void policy_load(knot_kasp_policy_t *policy, conf_t *conf, conf_val_t *id
        val = conf_id_get(conf, C_POLICY, C_KSK_LIFETIME, id);
        policy->ksk_lifetime = conf_int(&val);
 
+       val = conf_id_get(conf, C_POLICY, C_DELEG_ADT, id);
+       policy->deleg_aware = conf_bool(&val);
+
        val = conf_id_get(conf, C_POLICY, C_DELETE_DELAY, id);
        policy->delete_delay = conf_int(&val);
 
index 724df5bed771d71064dd6488f56cda21824d0d1f..11b72a23bf2581900906ac7b4a1aeaf50361f0c2 100644 (file)
@@ -20,8 +20,6 @@ void update_policy_from_zone(knot_kasp_policy_t *policy,
        assert(policy);
        assert(zone);
 
-       policy->deleg_aware = (zone->nodes->flags & ZONE_TREE_CONTAINS_DELEG);
-
        if (policy->dnskey_ttl == UINT32_MAX) {
                policy->dnskey_ttl = zone_soa_ttl(zone);
        }
index c080964236bc2e45f1e10e9032a883081baf19e7..470647a0a54b6b0f675cfa21f19564498abd06ac 100644 (file)
@@ -47,6 +47,13 @@ def check_nxdomain(resp, nsec_count):
     resp.check_count(nsec_count, "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")
@@ -62,13 +69,27 @@ t.link(parent, knot)
 knot.dnssec(parent).enable = True
 
 t.start()
-knot.zone_wait(parent)
+parent_serial = knot.zone_wait(parent)
+
+check_adt(knot, parent[0].name, False)
+isset(knot.log_search("missing ADT"), "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)
         knot.dnssec(childs).enable = True
+        knot.dnssec(childs).deleg_adt = True
         knot.gen_confile()
         knot.reload()
         serials = knot.zones_wait(childs)
@@ -124,11 +145,4 @@ for childs_running in [ False, True ]:
 
 knot.ctl("zone-flush", wait=True)
 
-resp = knot.dig(parent[0].name, "DNSKEY")
-if resp.resp.answer[0].to_rdataset()[0].flags & 2 != 2:
-    set_err("No ADT flag")
-resp = knot.dig(childs[0].name, "DNSKEY")
-if resp.resp.answer[0].to_rdataset()[0].flags & 2 != 0:
-    set_err("Extra ADT flag")
-
 t.end()