]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
catalog: enforce single label for PTR defining member
authorLibor Peltan <libor.peltan@nic.cz>
Thu, 25 Mar 2021 12:48:36 +0000 (13:48 +0100)
committerLibor Peltan <libor.peltan@nic.cz>
Thu, 25 Mar 2021 12:48:36 +0000 (13:48 +0100)
doc/configuration.rst
src/knot/catalog/interpret.c
tests-extra/tests/catalog/basic/data/catalog1.zone
tests-extra/tests/catalog/basic/test.py

index 48ea8ce256e609c4641b026ef5b14683a4144f23..b8454b03abe2a4e7562d613f3c655b6e146b5a16 100644 (file)
@@ -602,8 +602,8 @@ multiple catalog zones.
    existing zones configured on the server as it would effectively "shadow"
    part of your DNS subtree.
 
-Upon catalog zone (re)load or change, all the PTR records in the zone
-sub-tree *zones* (e.g. ``unique-id1.zones.catalog. 0 IN PTR member.com.``)
+Upon catalog zone (re)load or change, all the PTR records in the format
+``unique-id.zones.catalog. 0 IN PTR member.com.`` (but not ``too.deep.zones.catalog.``!)
 are processed and member zones created, with zone names taken from the
 PTR records' RData, and zone settings taken from the configuration
 template specified by :ref:`zone_catalog-template`.
@@ -612,11 +612,10 @@ The owner names of the PTR records shall follow this scheme:
 
 .. code-block:: console
 
-    <any-junk>.<unique-id>.zones.<catalog-zone>.
+    <unique-id>.zones.<catalog-zone>.
 
 where the mentioned group of labels shall match:
 
-- *<any-junk>* — (optional) Any additional labels with no particular meaning.
 - *<unique-id>* — Single label that is recommended to be unique among member zones.
 - ``zones`` — Required label.
 - *<catalog-zone>* — Name of the catalog zone.
index fa45bbe2145e737cdf6469cb6fd5ac2c7dee5598..f5c3b371e01b4f9b5f74d1845ca42780a2515394 100644 (file)
@@ -22,6 +22,7 @@
 typedef struct {
        catalog_update_t *u;
        const knot_dname_t *apex;
+       int apex_labels;
        bool remove;
        catalog_t *check;
 } cat_upd_ctx_t;
@@ -52,6 +53,13 @@ static bool check_zone_version(const zone_contents_t *zone)
 static int cat_update_add_node(zone_node_t *node, void *data)
 {
        cat_upd_ctx_t *ctx = data;
+       int labels_diff = knot_dname_labels(node->owner, NULL) - ctx->apex_labels
+                         - 1 /* "zones" label */ - 1 /* unique-N label */;
+       assert(labels_diff >= 0);
+       if (labels_diff > 0) {
+               return KNOT_EOK;
+       }
+
        const knot_rdataset_t *ptr = node_rdataset(node, KNOT_RRTYPE_PTR);
        if (ptr == NULL || ptr->count == 0) {
                return KNOT_EOK;
@@ -84,9 +92,9 @@ int catalog_update_from_zone(catalog_update_t *u, struct zone_contents *zone,
                return KNOT_EOK;
        }
 
-       cat_upd_ctx_t ctx = { u, zone->apex->owner, remove, check };
+       cat_upd_ctx_t ctx = { u, zone->apex->owner, knot_dname_labels(zone->apex->owner, NULL), remove, check };
        pthread_mutex_lock(&u->mutex);
-       int ret = zone_tree_sub_apply(zone->nodes, sub, false, cat_update_add_node, &ctx);
+       int ret = zone_tree_sub_apply(zone->nodes, sub, true, cat_update_add_node, &ctx);
        pthread_mutex_unlock(&u->mutex);
        return ret;
 }
index 4883a05bbd266cbe9ab5c0f337c6db16c3833602..b3f6480e98e770f545bab5fe3b24908023b850db 100644 (file)
@@ -5,5 +5,7 @@ $TTL 0
   NS ns
 ns AAAA ::0
 version TXT "2"
-foo.bar.zones PTR cataloged1.
+foo.zones PTR cataloged1.
 not.zones.in PTR not-cataloged1.
+too.deep.zones PTR not-cataloged2.
+zones PTR not-cataloged3.
index 6528aa563b5ae094564a9e6581dad8d99da2e590..b4b1920a1bf31fcb870c755ed1c88aed183e93d9 100644 (file)
@@ -53,6 +53,10 @@ resp.check_count(2, "DNSKEY")
 resp.check_count(1, "RRSIG")
 resp = master.dig("not-cataloged1.", "SOA")
 resp.check(rcode="REFUSED")
+resp = master.dig("not-cataloged2.", "SOA")
+resp.check(rcode="REFUSED")
+resp = master.dig("not-cataloged3.", "SOA")
+resp.check(rcode="REFUSED")
 
 # Udating a cataloged zone
 subprocess.run(["sed", "-i", "s/10001/10002/;$s/$/\\nxyz A 1.2.3.4/", master.dir + "/master/cataloged1.zone"])
@@ -66,7 +70,7 @@ check_keys(slave, "cataloged1", 2)
 
 # Check adding cataloged zone.
 up = master.update(zone[1])
-up.add("junk.bar.zones.catalog1.", 0, "PTR", "cataloged2.")
+up.add("bar.zones.catalog1.", 0, "PTR", "cataloged2.")
 up.send("NOERROR")
 t.sleep(6)
 resp = master.dig("cataloged2.", "NS")
@@ -88,8 +92,8 @@ resp0 = slave.dig("cataloged2.", "DNSKEY")
 resp0.check_count(2, "DNSKEY")
 dnskey0 = resp0.resp.answer[0].to_rdataset()[0]
 up = master.update(zone[1])
-up.delete("junk.bar.zones.catalog1.", "PTR", "cataloged2.")
-up.add("junk.bar.zones.catalog1.", 0, "PTR", "cataloged2.")
+up.delete("bar.zones.catalog1.", "PTR", "cataloged2.")
+up.add("bar.zones.catalog1.", 0, "PTR", "cataloged2.")
 up.send("NOERROR")
 t.sleep(4)
 resp1 = slave.dig("cataloged2.", "DNSKEY")
@@ -107,8 +111,8 @@ else:
 
 # Check remove-adding the zone: shall effectively purge it
 up = master.update(zone[1])
-up.delete("junk.bar.zones.catalog1.", "PTR", "cataloged2.")
-up.add("junk.bar2.zones.catalog1.", 0, "PTR", "cataloged2.")
+up.delete("bar.zones.catalog1.", "PTR", "cataloged2.")
+up.add("bar2.zones.catalog1.", 0, "PTR", "cataloged2.")
 up.send("NOERROR")
 t.sleep(4)
 shutil.copy(t.data_dir + "/cataloged2.zone", master.dir + "/master") # because the purge deletes even zonefile
@@ -122,22 +126,6 @@ if resp2.count("DNSKEY") > 0:
             set_err("ZONE NOT PURGED")
 dnskey2 = resp2.resp.answer[0].to_rdataset()[0]
 
-# Check remove-adding while keeping the 'uniq' label
-up = master.update(zone[1])
-up.delete("junk.bar2.zones.catalog1.", "PTR", "cataloged2.")
-up.add("jang.bar2.zones.catalog1.", 0, "PTR", "cataloged2.")
-up.send("NOERROR")
-t.sleep(4)
-resp3 = slave.dig("cataloged2.", "DNSKEY")
-resp3.check_count(2, "DNSKEY")
-match = 0
-if resp3.count("DNSKEY") > 0:
-    for dnskey3 in resp3.resp.answer[0].to_rdataset():
-        if dnskey3.to_text() == dnskey2.to_text():
-             match = match + 1
-if match < 1:
-    set_err("ZONE PURGED2")
-
 # Check persistence after server restart
 slave.stop()
 slave.start()
@@ -171,7 +159,7 @@ check_keys(slave, "cataloged2", 2)
 master.ctl("zone-backup +journal +backupdir %s/backup %s" % (master.dir, zone[1].name))
 # Check removing cataloged zone
 up = master.update(zone[1])
-up.delete("foo.bar.zones.catalog1.", "PTR")
+up.delete("foo.zones.catalog1.", "PTR")
 up.send("NOERROR")
 t.sleep(6)
 resp = master.dig("cataloged1.", "SOA")