Commit b7697175 authored by Libor Peltan's avatar Libor Peltan Committed by Daniel Salzman
Browse files

bugfix: fix answering with opt-outed NSEC3 on empty-non-terminal

parent 09efb9c1
Pipeline #87594 passed with stages
in 6 minutes and 58 seconds
/* Copyright (C) 2020 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
......@@ -42,7 +42,7 @@ static bool wildcard_expanded(const zone_node_t *node, const knot_dname_t *qname
*/
static bool ds_optout(const zone_node_t *node)
{
return node_nsec3_get(node) == NULL && node->flags & NODE_FLAGS_DELEG;
return node_nsec3_get(node) == NULL && !(node->flags & NODE_FLAGS_SUBTREE_AUTH);
}
/*!
......
......@@ -23,19 +23,47 @@
#include "knot/zone/adds_tree.h"
#include "knot/zone/measure.h"
static bool node_non_dnssec_exists(const zone_node_t *node)
{
assert(node);
for (uint16_t i = 0; i < node->rrset_count; ++i) {
switch (node->rrs[i].type) {
case KNOT_RRTYPE_NSEC:
case KNOT_RRTYPE_NSEC3:
case KNOT_RRTYPE_RRSIG:
continue;
default:
return true;
}
}
return false;
}
int adjust_cb_flags(zone_node_t *node, adjust_ctx_t *ctx)
{
zone_node_t *parent = node_parent(node);
uint16_t flags_orig = node->flags;
bool set_subt_auth = false;
assert(!(node->flags & NODE_FLAGS_DELETED));
node->flags &= ~(NODE_FLAGS_DELEG | NODE_FLAGS_NONAUTH);
node->flags &= ~(NODE_FLAGS_DELEG | NODE_FLAGS_NONAUTH | NODE_FLAGS_SUBTREE_AUTH);
if (parent && (parent->flags & NODE_FLAGS_DELEG || parent->flags & NODE_FLAGS_NONAUTH)) {
node->flags |= NODE_FLAGS_NONAUTH;
} else if (node_rrtype_exists(node, KNOT_RRTYPE_NS) && node != ctx->zone->apex) {
node->flags |= NODE_FLAGS_DELEG;
if (node_rrtype_exists(node, KNOT_RRTYPE_DS)) {
set_subt_auth = true;
}
} else if (node_non_dnssec_exists(node)) {
set_subt_auth = true;
}
if (set_subt_auth) {
node_set_flag_hierarch(node, NODE_FLAGS_SUBTREE_AUTH);
}
if (node->flags != flags_orig && ctx->changed_nodes != NULL) {
......
/* 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
......@@ -100,6 +100,8 @@ enum node_flags {
NODE_FLAGS_SECOND = 1 << 9, // this value shall be fixed
/*! \brief The node shall be deleted. It's just not because it's a bi-node and the counterpart still exists. */
NODE_FLAGS_DELETED = 1 << 10,
/*! \brief The node or some node in subtree has some authoritative data in it (possibly also DS at deleg). */
NODE_FLAGS_SUBTREE_AUTH = 1 << 11,
};
typedef void (*node_addrem_cb)(zone_node_t *, void *);
......@@ -296,6 +298,16 @@ inline static const zone_node_t *glue_node(const glue_t *glue, const zone_node_t
return binode_node_as((zone_node_t *)glue->node, another_zone_node);
}
/*!
* \brief Add a flag to this node and all (grand-)parents until the flag is present.
*/
inline static void node_set_flag_hierarch(zone_node_t *node, uint16_t fl)
{
for (zone_node_t *i = node; i != NULL && (i->flags & fl) != fl; i = node_parent(i)) {
i->flags |= fl;
}
}
/*!
* \brief Checks whether node contains any RRSIG for given type.
*
......
......@@ -23,6 +23,9 @@ sub NS sub
sub A 192.0.0.1
ns.sub A 192.0.2.4
; Opt-outable delegation below empty-non-terminal
deleg.ent NS sub
; CNAME to A record
cname CNAME dns1
......
......@@ -69,6 +69,11 @@ def query_test(knot, bind, dnssec):
resp.check(rcode="NOERROR", flags="QR AA", noflags="TC AD RA")
resp.cmp(bind, additional=True)
# Positive (NODATA, at delegation, DS type, below empty-non-terminal)
resp = knot.dig("deleg.ent.flags", "DS", udp=True, dnssec=dnssec)
resp.check(rcode="NOERROR", flags="QR AA", noflags="TC AD RA")
resp.cmp(bind, additional=True)
# Positive (REFERRAL, below delegation, DS type)
resp = knot.dig("net.ds-sub.flags", "DS", udp=True, dnssec=dnssec)
resp.check(rcode="NOERROR", flags="QR", noflags="AA TC AD RA")
......@@ -324,6 +329,15 @@ query_test(knot, bind, False)
knot.dnssec(zone[0]).enable = True
knot.dnssec(zone[0]).nsec3 = False
knot.dnssec(zone[0]).nsec3_opt_out = False
knot.gen_confile()
knot.reload()
serial = bind.zone_wait(zone, serial)
query_test(knot, bind, True)
knot.dnssec(zone[0]).nsec3 = True
knot.dnssec(zone[0]).nsec3_opt_out = False
knot.gen_confile()
knot.reload()
......@@ -331,6 +345,7 @@ serial = bind.zone_wait(zone, serial)
query_test(knot, bind, True)
knot.dnssec(zone[0]).nsec3 = True
knot.dnssec(zone[0]).nsec3_opt_out = True
knot.gen_confile()
knot.reload()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment