catalog: enforce single label for PTR defining member

This commit is contained in:
Libor Peltan 2021-03-25 13:48:36 +01:00
parent 4401ec71a5
commit 9b1bcb9487
4 changed files with 26 additions and 29 deletions

View 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.

View 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;
}

View 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.

View 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")