diff --git a/src/knot/dnssec/nsec-chain.c b/src/knot/dnssec/nsec-chain.c index cfaa609c77b03033c4914c774a274f3726f36577..38f112966adb7bef2545cf52e5c430dc4651ef61 100644 --- a/src/knot/dnssec/nsec-chain.c +++ b/src/knot/dnssec/nsec-chain.c @@ -401,6 +401,19 @@ int nsec_check_new_connects(zone_tree_t *tree, nsec_chain_iterate_data_t *data) return zone_tree_apply(tree, nsec_check_prev_next, data); } +static int check_subtree_optout(zone_node_t *node, void *ctx) +{ + bool *res = ctx; + if ((node->flags & NODE_FLAGS_NONAUTH) || !*res) { + return KNOT_EOK; + } + if (node_nsec3_get(node) != NULL && + node_rdataset(node_nsec3_get(node), KNOT_RRTYPE_NSEC3) != NULL) { + *res = false; + } + return KNOT_EOK; +} + static int check_nsec_bitmap(zone_node_t *node, void *ctx) { nsec_chain_iterate_data_t *data = ctx; @@ -419,6 +432,13 @@ static int check_nsec_bitmap(zone_node_t *node, void *ctx) } bool may_no_nsec = (data->nsec3_params != NULL && !(node->flags & NODE_FLAGS_SUBTREE_AUTH)); knot_rdataset_t *nsec = node_rdataset(nsec_node, data->nsec_type); + if (may_no_nsec && nsec == NULL) { + int ret = zone_tree_sub_apply(data->update->new_cont->nodes, node->owner, + true, check_subtree_optout, &may_no_nsec); + if (ret != KNOT_EOK) { + return ret; + } + } if ((nsec == NULL || nsec->count != 1) && !shall_no_nsec && !may_no_nsec) { data->update->validation_hint.node = (nsec_node == NULL ? node->owner : nsec_node->owner); data->update->validation_hint.rrtype = KNOT_RRTYPE_ANY; diff --git a/tests-extra/tests/dnssec/validate/data/optout.ent.zone b/tests-extra/tests/dnssec/validate/data/optout.ent.zone new file mode 100644 index 0000000000000000000000000000000000000000..b3e8b969c1a021dbcbd94ef8f912a22ef18ca4f1 --- /dev/null +++ b/tests-extra/tests/dnssec/validate/data/optout.ent.zone @@ -0,0 +1,80 @@ +; File written on Tue Aug 31 18:50:37 2021 +; dnssec_signzone version 9.16.8-Ubuntu +optout.ent. 3600 IN SOA a.optout.ent. a.optout.ent. ( + 1000000001 ; serial + 10800 ; refresh (3 hours) + 10 ; retry (10 seconds) + 1209600 ; expire (2 weeks) + 7200 ; minimum (2 hours) + ) + 3600 RRSIG SOA 13 2 3600 ( + 20601231235959 20210831155037 6971 optout.ent. + ipEvc00KUrW66efVnH32XGVnWblmQHWKyqf3 + 5EB6jMI6SVqmqfYaL0o9hahKOeib1OP14BPy + NN0aUmiNtEX+iw== ) + 3600 NS a.optout.ent. + 3600 RRSIG NS 13 2 3600 ( + 20601231235959 20210831155037 6971 optout.ent. + lnElW2h0idPtUIFmPVTi5D1biG9SuEwGd08R + ANEVC1JF0Cz7nBkqw7s1S3QNRVVFXw1eqi5w + aHoprR/YHbwr4g== ) + 3600 MX 10 a.optout.ent. + 3600 RRSIG MX 13 2 3600 ( + 20601231235959 20210831155037 6971 optout.ent. + k/kNDfVFcrP9/3/CWoI0VK938i0GoWXsxnOc + dzWjp1seFKVRJqsj3xRRqdlyV6Zikh9/Y01t + Vl4ihxxzs5jj5A== ) + 3600 DNSKEY 257 3 13 ( + JxNLxVlreytQBDK6mG44UQ1//gB5uW1pgEk3 + hC1mUHaa9qdXUOuoEx2tjyqmC7Rw/G+8IVpH + C7Zp6GC6xvdhJw== + ) ; KSK; alg = ECDSAP256SHA256 ; key id = 6971 + 3600 RRSIG DNSKEY 13 2 3600 ( + 20601231235959 20210831155037 6971 optout.ent. + n/Oz/yb6x24pAxgdrUfSu5AtJdVqRPnzsN39 + 2WbWsASaMPGvFqVuwalN69+qoKVVI72zxKKI + lfOs98fN5vFRWw== ) + 0 NSEC3PARAM 1 0 10 484E7FFF154B5357 + 0 RRSIG NSEC3PARAM 13 2 0 ( + 20601231235959 20210831155037 6971 optout.ent. + mfS0OsUnl8WTKJAcNzDYXxmMKjrVhwQLhSak + TgJxDxKpnuVIWYq6+8aX4xWLp/b5cN/b99Ws + Ji0zdZ+amZwMaA== ) +deleg.ent.optout.ent. 3600 IN NS out-of-bailiwick.example. +8DOAQD6MB2N59P3MCI8POSR8RMI2BSH2.optout.ent. 7200 IN NSEC3 1 0 10 484E7FFF154B5357 ( + 9SE9KJAM42S8ACFVJNU1QRVABUK9O20T + NS SOA MX RRSIG DNSKEY NSEC3PARAM ) + 7200 RRSIG NSEC3 13 3 7200 ( + 20601231235959 20210831155037 6971 optout.ent. + Ps7x9+9H56bkWb9rTOgzDat4ofnuLEHkA/TH + 5rT/XE3SShLLth6uDIQq8mQjwuTdK/kQjekm + 0ZNAAm9sqcYVZg== ) +a.optout.ent. 3600 IN A 1.2.3.4 + 3600 RRSIG A 13 3 3600 ( + 20601231235959 20210831155037 6971 optout.ent. + lVnzQ/IBtihiTWZZy62+9usJe6J475lU2Bbr + EctWkqotdGCks1XZT5g8R97YX6Ku2rpnsfKh + Ong6tdbBhKDMoA== ) +CEP7K90BHDB9DJ525KIG0325P07HAK7R.optout.ent. 7200 IN NSEC3 1 0 10 484E7FFF154B5357 ( + KU64EQGJN5I9HO9GRU9QMA4A333C6MJ3 + A RRSIG ) + 7200 RRSIG NSEC3 13 3 7200 ( + 20601231235959 20210831155037 6971 optout.ent. + NVXZDgzlq9Mp/bBAZ5uJYvgGOb8liEpIeGYn + hNF+ocC4Mg+IDauCreqPdwL3uX2fJTD7TO2t + JISmliby/QJmIQ== ) +9SE9KJAM42S8ACFVJNU1QRVABUK9O20T.optout.ent. 7200 IN NSEC3 1 0 10 484E7FFF154B5357 ( + CEP7K90BHDB9DJ525KIG0325P07HAK7R ) + 7200 RRSIG NSEC3 13 3 7200 ( + 20601231235959 20210831155037 6971 optout.ent. + /C1aqFdx57ObTiz4nQVDrDRbSFgVxCeJT3PR + KEp3MmspTC6MTikLvLAyETnrLuaIWggtx0x1 + f2kwjpZcbKnMZg== ) +KU64EQGJN5I9HO9GRU9QMA4A333C6MJ3.optout.ent. 7200 IN NSEC3 1 0 10 484E7FFF154B5357 ( + 8DOAQD6MB2N59P3MCI8POSR8RMI2BSH2 + NS ) + 7200 RRSIG NSEC3 13 3 7200 ( + 20601231235959 20210831155037 6971 optout.ent. + bpSSNo7+Bz6f3UMM/756LVSYKGIf6FlfBK5E + V98AbR8Mg29IXOt9Fq5vgegm2FVvlgtgppl2 + ewViHCEBZAuHSg== ) diff --git a/tests-extra/tests/dnssec/validate/data/optout.ent.zone.2 b/tests-extra/tests/dnssec/validate/data/optout.ent.zone.2 new file mode 100644 index 0000000000000000000000000000000000000000..0a201527487d76056a19fbf3137eb9fd2d748dbd --- /dev/null +++ b/tests-extra/tests/dnssec/validate/data/optout.ent.zone.2 @@ -0,0 +1,73 @@ +; File written on Tue Aug 31 18:50:37 2021 +; dnssec_signzone version 9.16.8-Ubuntu +optout.ent. 3600 IN SOA a.optout.ent. a.optout.ent. ( + 1000000003 ; serial + 10800 ; refresh (3 hours) + 10 ; retry (10 seconds) + 1209600 ; expire (2 weeks) + 7200 ; minimum (2 hours) + ) + 3600 RRSIG SOA 13 2 3600 ( + 20601231235959 20210831155037 6971 optout.ent. + cJM4ESx60urM2UquyD+2CnFqBmW/pffMbfUt + BPrjNByacG/Tgeoi5PhF/Piv6Ce5Hnni4GBj + IoyY5TnGXEceRQ== ) + 3600 NS a.optout.ent. + 3600 RRSIG NS 13 2 3600 ( + 20601231235959 20210831155037 6971 optout.ent. + lnElW2h0idPtUIFmPVTi5D1biG9SuEwGd08R + ANEVC1JF0Cz7nBkqw7s1S3QNRVVFXw1eqi5w + aHoprR/YHbwr4g== ) + 3600 MX 10 a.optout.ent. + 3600 RRSIG MX 13 2 3600 ( + 20601231235959 20210831155037 6971 optout.ent. + k/kNDfVFcrP9/3/CWoI0VK938i0GoWXsxnOc + dzWjp1seFKVRJqsj3xRRqdlyV6Zikh9/Y01t + Vl4ihxxzs5jj5A== ) + 3600 DNSKEY 257 3 13 ( + JxNLxVlreytQBDK6mG44UQ1//gB5uW1pgEk3 + hC1mUHaa9qdXUOuoEx2tjyqmC7Rw/G+8IVpH + C7Zp6GC6xvdhJw== + ) ; KSK; alg = ECDSAP256SHA256 ; key id = 6971 + 3600 RRSIG DNSKEY 13 2 3600 ( + 20601231235959 20210831155037 6971 optout.ent. + n/Oz/yb6x24pAxgdrUfSu5AtJdVqRPnzsN39 + 2WbWsASaMPGvFqVuwalN69+qoKVVI72zxKKI + lfOs98fN5vFRWw== ) + 0 NSEC3PARAM 1 0 10 484E7FFF154B5357 + 0 RRSIG NSEC3PARAM 13 2 0 ( + 20601231235959 20210831155037 6971 optout.ent. + mfS0OsUnl8WTKJAcNzDYXxmMKjrVhwQLhSak + TgJxDxKpnuVIWYq6+8aX4xWLp/b5cN/b99Ws + Ji0zdZ+amZwMaA== ) +deleg.ent.optout.ent. 3600 IN NS out-of-bailiwick.example. +a.optout.ent. 3600 IN A 1.2.3.4 + 3600 RRSIG A 13 3 3600 ( + 20601231235959 20210831155037 6971 optout.ent. + lVnzQ/IBtihiTWZZy62+9usJe6J475lU2Bbr + EctWkqotdGCks1XZT5g8R97YX6Ku2rpnsfKh + Ong6tdbBhKDMoA== ) +8DOAQD6MB2N59P3MCI8POSR8RMI2BSH2.optout.ent. 7200 IN NSEC3 1 1 10 484E7FFF154B5357 ( + CEP7K90BHDB9DJ525KIG0325P07HAK7R + NS SOA MX RRSIG DNSKEY NSEC3PARAM ) + 7200 RRSIG NSEC3 13 3 7200 ( + 20601231235959 20210831155037 6971 optout.ent. + siQxUHoSdNgxZ8FLpvR801dRP+fP2lDriEkq + 4+V2R9r+3SV48dOCfYySMXgxepoG8dlZhGSA + G4oCLO5OxETeRg== ) +CEP7K90BHDB9DJ525KIG0325P07HAK7R.optout.ent. 7200 IN NSEC3 1 0 10 484E7FFF154B5357 ( + KU64EQGJN5I9HO9GRU9QMA4A333C6MJ3 + A RRSIG ) + 7200 RRSIG NSEC3 13 3 7200 ( + 20601231235959 20210831155037 6971 optout.ent. + NVXZDgzlq9Mp/bBAZ5uJYvgGOb8liEpIeGYn + hNF+ocC4Mg+IDauCreqPdwL3uX2fJTD7TO2t + JISmliby/QJmIQ== ) +KU64EQGJN5I9HO9GRU9QMA4A333C6MJ3.optout.ent. 7200 IN NSEC3 1 0 10 484E7FFF154B5357 ( + 8DOAQD6MB2N59P3MCI8POSR8RMI2BSH2 + NS ) + 7200 RRSIG NSEC3 13 3 7200 ( + 20601231235959 20210831155037 6971 optout.ent. + bpSSNo7+Bz6f3UMM/756LVSYKGIf6FlfBK5E + V98AbR8Mg29IXOt9Fq5vgegm2FVvlgtgppl2 + ewViHCEBZAuHSg== ) diff --git a/tests-extra/tests/dnssec/validate/test.py b/tests-extra/tests/dnssec/validate/test.py index 0a1701279df64846cf4f230a14b837328a4bdb09..ecb383610885d99003e4382eedec3a2fb730750d 100644 --- a/tests-extra/tests/dnssec/validate/test.py +++ b/tests-extra/tests/dnssec/validate/test.py @@ -16,7 +16,8 @@ zones_nok = t.zone("missing.nsec.", storage=".") + t.zone("bitmap.nsec.", storag t.zone("chain.nsec.", storage=".") + t.zone("rrsig.a.", storage=".") + \ t.zone("rrsig.nsec.", storage=".") + t.zone("redundant.invalid.rrsig.", storage=".") zones_nok3 = t.zone("missing.nsec3", storage=".") + t.zone("bitmap.nsec3.", storage=".") + \ - t.zone("chain.nsec3.", storage=".") + t.zone("rrsig.nsec3", storage=".") + t.zone("chain.nsec3.", storage=".") + t.zone("rrsig.nsec3", storage=".") + \ + t.zone("optout.ent.", storage=".") zones_unsigned = t.zone("example.com.") zones = zones_ok + zones_ok3 + zones_nok + zones_nok3