diff --git a/src/knot/events/handlers/ds_push.c b/src/knot/events/handlers/ds_push.c index 6bcaa92ef4733a268f74113eea439a06a2f4d838..f8559af7e230deb4cff2684e0f278f3ed84da479 100644 --- a/src/knot/events/handlers/ds_push.c +++ b/src/knot/events/handlers/ds_push.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,6 +25,7 @@ struct ds_push_data { const knot_dname_t *zone; + const knot_dname_t *parent_query; knot_dname_t *parent_soa; knot_rrset_t del_old_ds; knot_rrset_t new_ds; @@ -49,9 +50,10 @@ static int ds_push_begin(knot_layer_t *layer, void *params) static int parent_soa_produce(struct ds_push_data *data, knot_pkt_t *pkt) { - const knot_dname_t *query_name = knot_wire_next_label(data->zone, NULL); + assert(data->parent_query[0] != '\0'); + data->parent_query = knot_wire_next_label(data->parent_query, NULL); - int ret = knot_pkt_put_question(pkt, query_name, KNOT_CLASS_IN, KNOT_RRTYPE_SOA); + int ret = knot_pkt_put_question(pkt, data->parent_query, KNOT_CLASS_IN, KNOT_RRTYPE_SOA); if (ret != KNOT_EOK) { return KNOT_STATE_FAIL; } @@ -123,18 +125,20 @@ static int ds_push_consume(knot_layer_t *layer, knot_pkt_t *pkt) } const knot_rrset_t *parent_soa = sect_soa(pkt, KNOT_ANSWER); - if (parent_soa == NULL) { - parent_soa = sect_soa(pkt, KNOT_AUTHORITY); + if (parent_soa != NULL) { + // parent SOA obtained, continue with DS push + data->parent_soa = knot_dname_copy(parent_soa->owner, NULL); + return KNOT_STATE_RESET; } - if (parent_soa == NULL) { + + if (data->parent_query[0] == '\0') { + // query for parent SOA systematicly fails DS_PUSH_LOG(LOG_WARNING, data->zone, data->remote, - "malformed message"); + "unable to query parent SOA"); return KNOT_STATE_FAIL; } - data->parent_soa = knot_dname_copy(parent_soa->owner, NULL); - - return KNOT_STATE_RESET; + return KNOT_STATE_RESET; // cut off one more label and re-query } static int ds_push_reset(knot_layer_t *layer) @@ -170,6 +174,7 @@ static int send_ds_push(conf_t *conf, zone_t *zone, struct ds_push_data data = { .zone = zone->name, + .parent_query = zone->name, .new_ds = zone_cds, .remote = (struct sockaddr *)&parent->addr, }; diff --git a/tests-extra/tests/dnssec/ds_push/data/com.zone b/tests-extra/tests/dnssec/ds_push/data/com.zone index 34859ad30ceedf225a754e4ac78f928ccb8ad156..d340e010a8c9134a6fa6c94640233f185df8ee2a 100644 --- a/tests-extra/tests/dnssec/ds_push/data/com.zone +++ b/tests-extra/tests/dnssec/ds_push/data/com.zone @@ -4,3 +4,4 @@ $TTL 1200 @ SOA ns admin 20110100 7 7 16 600 ns AAAA ::0 +example.com. CNAME intentionally.disruptive.cname. diff --git a/tests-extra/tests/dnssec/ds_push/data/example.com.zone b/tests-extra/tests/dnssec/ds_push/data/example.com.zone deleted file mode 100644 index ecd27e06e967ddb34a7420fd99137c0eec1dbdb2..0000000000000000000000000000000000000000 --- a/tests-extra/tests/dnssec/ds_push/data/example.com.zone +++ /dev/null @@ -1,9 +0,0 @@ -example.com. 3 SOA dns1.example.com. hostmaster.example.com. 2010111227 21600 3600 604800 3 -example.com. 0 NS dns1.example.com. -example.com. 2 MX 10 mail.example.com. -dns1.example.com. 4 A 192.0.2.1 -dns1.example.com. 3 AAAA 2001:db8::1 -foo.example.com. 5 A 192.0.2.4 -mail.example.com. 3 A 192.0.2.3 -mail.example.com. 1 AAAA 2001:db8::3 - diff --git a/tests-extra/tests/dnssec/ds_push/data/sub.example.com.zone b/tests-extra/tests/dnssec/ds_push/data/sub.example.com.zone new file mode 100644 index 0000000000000000000000000000000000000000..28f75708dbb88f5dc2e08ba2ee5bd1382ad8e123 --- /dev/null +++ b/tests-extra/tests/dnssec/ds_push/data/sub.example.com.zone @@ -0,0 +1,9 @@ +sub.example.com. 3 SOA dns1 hostmaster 2010111227 21600 3600 604800 3 +sub.example.com. 0 NS dns1 +sub.example.com. 2 MX 10 mail +dns1 4 A 192.0.2.1 +dns1 3 AAAA 2001:db8::1 +foo 5 A 192.0.2.4 +mail 3 A 192.0.2.3 +mail 1 AAAA 2001:db8::3 + diff --git a/tests-extra/tests/dnssec/ds_push/test.py b/tests-extra/tests/dnssec/ds_push/test.py index 9c3b2837ec28689410ad4f38880c65d2bb3d96ff..f09c686ef86a17ac914784e851141959a9e630d4 100644 --- a/tests-extra/tests/dnssec/ds_push/test.py +++ b/tests-extra/tests/dnssec/ds_push/test.py @@ -15,6 +15,8 @@ from dnstest.utils import * from dnstest.keys import Keymgr from dnstest.test import Test +ZONE = "sub.example.com." + def pregenerate_key(server, zone, alg): class a_class_with_name: def __init__(self, name): @@ -25,16 +27,16 @@ def pregenerate_key(server, zone, alg): # check zone if keys are present and used for signing def check_zone(server, zone, dnskeys, dnskey_rrsigs, cdnskeys, soa_rrsigs, msg): - qdnskeys = server.dig("example.com", "DNSKEY", bufsize=4096) + qdnskeys = server.dig(ZONE, "DNSKEY", bufsize=4096) found_dnskeys = qdnskeys.count("DNSKEY") - qdnskeyrrsig = server.dig("example.com", "DNSKEY", dnssec=True, bufsize=4096) + qdnskeyrrsig = server.dig(ZONE, "DNSKEY", dnssec=True, bufsize=4096) found_rrsigs = qdnskeyrrsig.count("RRSIG") - qcdnskey = server.dig("example.com", "CDNSKEY", bufsize=4096) + qcdnskey = server.dig(ZONE, "CDNSKEY", bufsize=4096) found_cdnskeys = qcdnskey.count("CDNSKEY") - qsoa = server.dig("example.com", "SOA", dnssec=True, bufsize=4096) + qsoa = server.dig(ZONE, "SOA", dnssec=True, bufsize=4096) found_soa_rrsigs = qsoa.count("RRSIG") check_log("DNSKEYs: %d (expected %d)" % (found_dnskeys, dnskeys)); @@ -66,7 +68,7 @@ def check_zone(server, zone, dnskeys, dnskey_rrsigs, cdnskeys, soa_rrsigs, msg): def wait_for_rrsig_count(t, server, rrtype, rrsig_count, timeout): rtime = 0.0 while True: - qdnskeyrrsig = server.dig("example.com", rrtype, dnssec=True, bufsize=4096) + qdnskeyrrsig = server.dig(ZONE, rrtype, dnssec=True, bufsize=4096) found_rrsigs = qdnskeyrrsig.count("RRSIG") if found_rrsigs == rrsig_count: break @@ -78,7 +80,7 @@ def wait_for_rrsig_count(t, server, rrtype, rrsig_count, timeout): def wait_for_dnskey_count(t, server, dnskey_count, timeout): rtime = 0.0 while True: - qdnskeyrrsig = server.dig("example.com", "DNSKEY", dnssec=True, bufsize=4096) + qdnskeyrrsig = server.dig(ZONE, "DNSKEY", dnssec=True, bufsize=4096) found_dnskeys = qdnskeyrrsig.count("DNSKEY") if found_dnskeys == dnskey_count: break @@ -107,7 +109,7 @@ t.link(parent_zone, parent, ddns=True) parent.dnssec(parent_zone).enable = True child = t.server("knot") -child_zone = t.zone("example.com.", storage=".") +child_zone = t.zone(ZONE, storage=".") t.link(child_zone, child) child.zonefile_sync = 24 * 60 * 60 @@ -125,9 +127,6 @@ child.dnssec(child_zone).ds_push = parent child.dnssec(child_zone).ksk_shared = True child.dnssec(child_zone).cds_publish = "always" -# parameters -ZONE = "example.com." - #t.start() t.generate_conf() parent.start() @@ -140,7 +139,7 @@ t.sleep(5) pregenerate_key(child, child_zone, "ECDSAP256SHA256") watch_ksk_rollover(t, child, child_zone, 2, 2, 3, "KSK rollover") -resp = parent.dig("example.com.", "DS") +resp = parent.dig(ZONE, "DS") resp.check_count(1, rtype="DS") t.end()