Commit c04f4f38 authored by Daniel Salzman's avatar Daniel Salzman

Merge branch 'nsec-proofs-refactoring' into 'master'

NSEC proofs refactoring

Close #191, #471

See merge request !570
parents fe731eaa a7d2f8cf
......@@ -49,7 +49,8 @@ static int wildcard_has_visited(struct query_data *qdata, const zone_node_t *nod
}
/*! \brief Mark given node as visited. */
static int wildcard_visit(struct query_data *qdata, const zone_node_t *node, const knot_dname_t *sname)
static int wildcard_visit(struct query_data *qdata, const zone_node_t *node,
const zone_node_t *prev, const knot_dname_t *sname)
{
assert(qdata);
assert(node);
......@@ -62,6 +63,7 @@ static int wildcard_visit(struct query_data *qdata, const zone_node_t *node, con
knot_mm_t *mm = qdata->mm;
struct wildcard_hit *item = mm_alloc(mm, sizeof(struct wildcard_hit));
item->node = node;
item->prev = prev;
item->sname = sname;
add_tail(&qdata->wildcards, (node_t *)item);
return KNOT_EOK;
......@@ -388,7 +390,7 @@ static int follow_cname(knot_pkt_t *pkt, uint16_t rrtype, struct query_data *qda
}
/* Put to wildcard node list. */
if (wildcard_visit(qdata, cname_node, qdata->name) != KNOT_EOK) {
if (wildcard_visit(qdata, cname_node, qdata->previous, qdata->name) != KNOT_EOK) {
return ERROR;
}
}
......@@ -448,14 +450,11 @@ static int name_not_found(knot_pkt_t *pkt, struct query_data *qdata)
qdata->node = wildcard_node;
assert(qdata->node != NULL);
/* keep encloser */
qdata->previous = NULL;
/* Follow expanded wildcard. */
int next_state = name_found(pkt, qdata);
/* Put to wildcard node list. */
if (wildcard_visit(qdata, wildcard_node, qdata->name) != KNOT_EOK) {
if (wildcard_visit(qdata, wildcard_node, qdata->previous, qdata->name) != KNOT_EOK) {
next_state = ERROR;
}
......
This diff is collapsed.
......@@ -13,14 +13,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file
*
* \brief NSEC/NSEC3 proofs for various states.
*
* \addtogroup query_processing
* @{
*/
#pragma once
......@@ -44,5 +36,3 @@ int nsec_append_rrsigs(knot_pkt_t *pkt, struct query_data *qdata, bool optional)
/*! \brief Clear RRSIG list. */
void nsec_clear_rrsigs(struct query_data *qdata);
/*! @} */
......@@ -85,6 +85,7 @@ struct query_data {
struct wildcard_hit {
node_t n;
const zone_node_t *node; /* Visited node. */
const zone_node_t *prev; /* Previous node from the SNAME. */
const knot_dname_t *sname; /* Name leading to this node. */
};
......
......@@ -702,20 +702,6 @@ static int recreate_nsec3_tree(const zone_contents_t *z, zone_contents_t *out)
return KNOT_EOK;
}
static zone_node_t *get_previous(const zone_contents_t *zone,
const knot_dname_t *name)
{
if (zone == NULL || name == NULL) {
return NULL;
}
zone_node_t *found = NULL, *prev = NULL;
(void)find_in_tree(zone->nodes, name, &found, &prev);
assert(prev != NULL);
return prev;
}
// Public API
int zone_contents_add_rr(zone_contents_t *z, const knot_rrset_t *rr,
......@@ -779,59 +765,53 @@ zone_node_t *zone_contents_find_node_for_rr(zone_contents_t *contents, const kno
int zone_contents_find_dname(const zone_contents_t *zone,
const knot_dname_t *name,
const zone_node_t **node,
const zone_node_t **closest_encloser,
const zone_node_t **match,
const zone_node_t **closest,
const zone_node_t **previous)
{
if (zone == NULL || name == NULL || node == NULL
|| closest_encloser == NULL || previous == NULL
|| zone->apex == NULL || zone->apex->owner == NULL) {
if (!zone || !name || !match || !closest || !previous) {
return KNOT_EINVAL;
}
zone_node_t *found = NULL, *prev = NULL;
bool match = find_in_tree(zone->nodes, name, &found, &prev);
*node = found;
*previous = prev;
// there must be at least one node with domain name less or equal to
// the searched name if the name belongs to the zone (the root)
if (*node == NULL && *previous == NULL) {
if (!knot_dname_in(zone->apex->owner, name)) {
return KNOT_EOUTOFZONE;
}
/* This function was quite out of date. The find_in_tree() function
* may return NULL in the 'found' field, so we cannot search for the
* closest encloser from this node.
*/
zone_node_t *node = NULL;
zone_node_t *prev = NULL;
int found = zone_tree_get_less_or_equal(zone->nodes, name, &node, &prev);
if (found < 0) {
// error
return found;
} else if (found == 1) {
// exact match
assert(node && prev);
*match = node;
*closest = node;
*previous = prev;
if (match) {
*closest_encloser = *node;
return ZONE_NAME_FOUND;
} else {
if (!knot_dname_is_sub(name, zone->apex->owner)) {
*node = NULL;
*closest_encloser = NULL;
return KNOT_EOUTOFZONE;
}
// closest match
*closest_encloser = *previous;
assert(*closest_encloser != NULL);
assert(!node && prev);
int matched_labels = knot_dname_matched_labels((*closest_encloser)->owner, name);
while (matched_labels < knot_dname_labels((*closest_encloser)->owner, NULL)) {
*closest_encloser = (*closest_encloser)->parent;
assert(*closest_encloser);
node = prev;
int matched_labels = knot_dname_matched_labels(node->owner, name);
while (matched_labels < knot_dname_labels(node->owner, NULL)) {
node = node->parent;
assert(node);
}
}
return match ? ZONE_NAME_FOUND : ZONE_NAME_NOT_FOUND;
}
*match = NULL;
*closest = node;
*previous = prev;
const zone_node_t *zone_contents_find_previous(const zone_contents_t *zone,
const knot_dname_t *name)
{
return get_previous(zone, name);
return ZONE_NAME_NOT_FOUND;
}
}
const zone_node_t *zone_contents_find_nsec3_node(const zone_contents_t *zone,
......
......@@ -108,12 +108,16 @@ zone_node_t *zone_contents_find_node_for_rr(zone_contents_t *contents, const kno
/*!
* \brief Tries to find a node by owner in the zone contents.
*
* \param[in] zone Zone to search for the name.
* \param[in] name Domain name to search for.
* \param[out] node The found node (if it was found, otherwise it may contain
* arbitrary node).
* \param[out] closest_encloser Closest encloser of the given name in the zone.
* \param[out] previous Previous domain name in canonical order.
* \param[in] contents Zone to search for the name.
* \param[in] name Domain name to search for.
* \param[out] match Matching node or NULL.
* \param[out] closest Closest matching name in the zone.
* May match \a match if found exactly.
* \param[out] previous Previous domain name in canonical order.
* Always previous, won't match \a match.
*
* \note The encloser and previous mustn't be used directly for DNSSEC proofs.
* These nodes may be empty non-terminals or not authoritative.
*
* \retval ZONE_NAME_FOUND if node with owner \a name was found.
* \retval ZONE_NAME_NOT_FOUND if it was not found.
......@@ -122,21 +126,10 @@ zone_node_t *zone_contents_find_node_for_rr(zone_contents_t *contents, const kno
*/
int zone_contents_find_dname(const zone_contents_t *contents,
const knot_dname_t *name,
const zone_node_t **node,
const zone_node_t **closest_encloser,
const zone_node_t **match,
const zone_node_t **closest,
const zone_node_t **previous);
/*!
* \brief Finds previous name in canonical order to the given name in the zone.
*
* \param zone Zone to search for the name.
* \param name Domain name to find the previous domain name of.
*
* \return Previous node in canonical order, or NULL if some parameter is wrong.
*/
const zone_node_t *zone_contents_find_previous(const zone_contents_t *contents,
const knot_dname_t *name);
/*!
* \brief Tries to find a node with the specified name among the NSEC3 nodes
* of the zone.
......
......@@ -118,47 +118,9 @@ int zone_tree_get_less_or_equal(zone_tree_t *tree,
hattrie_iter_free(i);
}
/* Previous node for proof must be non-empty and authoritative. */
if (*previous &&
((*previous)->rrset_count == 0 || (*previous)->flags & NODE_FLAGS_NONAUTH)) {
*previous = (*previous)->prev;
}
return exact_match;
}
zone_node_t *zone_tree_get_next(zone_tree_t *tree,
const knot_dname_t *owner)
{
if (tree == NULL || owner == NULL) {
return NULL;
}
uint8_t lf[KNOT_DNAME_MAXLEN];
knot_dname_lf(lf, owner, NULL);
value_t *fval = NULL;
zone_node_t *n = NULL;
(void)hattrie_find_next(tree, (char*)lf + 1, *lf, &fval);
if (fval == NULL) {
/* Return first node. */
hattrie_iter_t *it = hattrie_iter_begin(tree, true);
if (it == NULL) {
return NULL;
}
fval = hattrie_iter_val(it);
hattrie_iter_free(it);
}
n = (zone_node_t *)*fval;
/* Next node must be non-empty and auth. */
if (n->rrset_count == 0 || n->flags & NODE_FLAGS_NONAUTH) {
return zone_tree_get_next(tree, n->owner);
} else {
return n;
}
}
int zone_tree_remove(zone_tree_t *tree,
const knot_dname_t *owner,
zone_node_t **removed)
......
......@@ -51,6 +51,11 @@ resp = knot.dig("a.z.w.example", "AAAA", dnssec=True)
resp.check(rcode="NOERROR", flags="QR AA", eflags="DO")
resp.cmp(bind)
# No wildcard match because empty non-terminal (y.w.example) exists.
resp = knot.dig("a.y.w.example", "AAAA", dnssec=True)
resp.check(rcode="NXDOMAIN", flags="QR AA", eflags="DO")
resp.cmp(bind)
# Wildcard Expansion to apex
resp = knot.dig("a.to-apex.example", "SOA", dnssec=True)
resp.check(rcode="NOERROR", flags="QR AA", eflags="DO")
......
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