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 ...@@ -49,7 +49,8 @@ static int wildcard_has_visited(struct query_data *qdata, const zone_node_t *nod
} }
/*! \brief Mark given node as visited. */ /*! \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(qdata);
assert(node); assert(node);
...@@ -62,6 +63,7 @@ static int wildcard_visit(struct query_data *qdata, const zone_node_t *node, con ...@@ -62,6 +63,7 @@ static int wildcard_visit(struct query_data *qdata, const zone_node_t *node, con
knot_mm_t *mm = qdata->mm; knot_mm_t *mm = qdata->mm;
struct wildcard_hit *item = mm_alloc(mm, sizeof(struct wildcard_hit)); struct wildcard_hit *item = mm_alloc(mm, sizeof(struct wildcard_hit));
item->node = node; item->node = node;
item->prev = prev;
item->sname = sname; item->sname = sname;
add_tail(&qdata->wildcards, (node_t *)item); add_tail(&qdata->wildcards, (node_t *)item);
return KNOT_EOK; return KNOT_EOK;
...@@ -388,7 +390,7 @@ static int follow_cname(knot_pkt_t *pkt, uint16_t rrtype, struct query_data *qda ...@@ -388,7 +390,7 @@ static int follow_cname(knot_pkt_t *pkt, uint16_t rrtype, struct query_data *qda
} }
/* Put to wildcard node list. */ /* 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; return ERROR;
} }
} }
...@@ -448,14 +450,11 @@ static int name_not_found(knot_pkt_t *pkt, struct query_data *qdata) ...@@ -448,14 +450,11 @@ static int name_not_found(knot_pkt_t *pkt, struct query_data *qdata)
qdata->node = wildcard_node; qdata->node = wildcard_node;
assert(qdata->node != NULL); assert(qdata->node != NULL);
/* keep encloser */
qdata->previous = NULL;
/* Follow expanded wildcard. */ /* Follow expanded wildcard. */
int next_state = name_found(pkt, qdata); int next_state = name_found(pkt, qdata);
/* Put to wildcard node list. */ /* 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; next_state = ERROR;
} }
......
This diff is collapsed.
...@@ -13,14 +13,6 @@ ...@@ -13,14 +13,6 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. 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 #pragma once
...@@ -44,5 +36,3 @@ int nsec_append_rrsigs(knot_pkt_t *pkt, struct query_data *qdata, bool optional) ...@@ -44,5 +36,3 @@ int nsec_append_rrsigs(knot_pkt_t *pkt, struct query_data *qdata, bool optional)
/*! \brief Clear RRSIG list. */ /*! \brief Clear RRSIG list. */
void nsec_clear_rrsigs(struct query_data *qdata); void nsec_clear_rrsigs(struct query_data *qdata);
/*! @} */
...@@ -85,6 +85,7 @@ struct query_data { ...@@ -85,6 +85,7 @@ struct query_data {
struct wildcard_hit { struct wildcard_hit {
node_t n; node_t n;
const zone_node_t *node; /* Visited node. */ 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. */ 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) ...@@ -702,20 +702,6 @@ static int recreate_nsec3_tree(const zone_contents_t *z, zone_contents_t *out)
return KNOT_EOK; 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 // Public API
int zone_contents_add_rr(zone_contents_t *z, const knot_rrset_t *rr, 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 ...@@ -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, int zone_contents_find_dname(const zone_contents_t *zone,
const knot_dname_t *name, const knot_dname_t *name,
const zone_node_t **node, const zone_node_t **match,
const zone_node_t **closest_encloser, const zone_node_t **closest,
const zone_node_t **previous) const zone_node_t **previous)
{ {
if (zone == NULL || name == NULL || node == NULL if (!zone || !name || !match || !closest || !previous) {
|| closest_encloser == NULL || previous == NULL
|| zone->apex == NULL || zone->apex->owner == NULL) {
return KNOT_EINVAL; return KNOT_EINVAL;
} }
zone_node_t *found = NULL, *prev = NULL; if (!knot_dname_in(zone->apex->owner, name)) {
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) {
return KNOT_EOUTOFZONE; return KNOT_EOUTOFZONE;
} }
/* This function was quite out of date. The find_in_tree() function zone_node_t *node = NULL;
* may return NULL in the 'found' field, so we cannot search for the zone_node_t *prev = NULL;
* closest encloser from this node.
*/ 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) { return ZONE_NAME_FOUND;
*closest_encloser = *node;
} else { } else {
if (!knot_dname_is_sub(name, zone->apex->owner)) { // closest match
*node = NULL;
*closest_encloser = NULL;
return KNOT_EOUTOFZONE;
}
*closest_encloser = *previous; assert(!node && prev);
assert(*closest_encloser != NULL);
int matched_labels = knot_dname_matched_labels((*closest_encloser)->owner, name); node = prev;
while (matched_labels < knot_dname_labels((*closest_encloser)->owner, NULL)) { int matched_labels = knot_dname_matched_labels(node->owner, name);
*closest_encloser = (*closest_encloser)->parent; while (matched_labels < knot_dname_labels(node->owner, NULL)) {
assert(*closest_encloser); 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, return ZONE_NAME_NOT_FOUND;
const knot_dname_t *name) }
{
return get_previous(zone, name);
} }
const zone_node_t *zone_contents_find_nsec3_node(const zone_contents_t *zone, 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 ...@@ -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. * \brief Tries to find a node by owner in the zone contents.
* *
* \param[in] zone Zone to search for the name. * \param[in] contents Zone to search for the name.
* \param[in] name Domain name to search for. * \param[in] name Domain name to search for.
* \param[out] node The found node (if it was found, otherwise it may contain * \param[out] match Matching node or NULL.
* arbitrary node). * \param[out] closest Closest matching name in the zone.
* \param[out] closest_encloser Closest encloser of the given name in the zone. * May match \a match if found exactly.
* \param[out] previous Previous domain name in canonical order. * \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_FOUND if node with owner \a name was found.
* \retval ZONE_NAME_NOT_FOUND if it was not 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 ...@@ -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, int zone_contents_find_dname(const zone_contents_t *contents,
const knot_dname_t *name, const knot_dname_t *name,
const zone_node_t **node, const zone_node_t **match,
const zone_node_t **closest_encloser, const zone_node_t **closest,
const zone_node_t **previous); 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 * \brief Tries to find a node with the specified name among the NSEC3 nodes
* of the zone. * of the zone.
......
...@@ -118,47 +118,9 @@ int zone_tree_get_less_or_equal(zone_tree_t *tree, ...@@ -118,47 +118,9 @@ int zone_tree_get_less_or_equal(zone_tree_t *tree,
hattrie_iter_free(i); 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; 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, int zone_tree_remove(zone_tree_t *tree,
const knot_dname_t *owner, const knot_dname_t *owner,
zone_node_t **removed) zone_node_t **removed)
......
...@@ -51,6 +51,11 @@ resp = knot.dig("a.z.w.example", "AAAA", dnssec=True) ...@@ -51,6 +51,11 @@ resp = knot.dig("a.z.w.example", "AAAA", dnssec=True)
resp.check(rcode="NOERROR", flags="QR AA", eflags="DO") resp.check(rcode="NOERROR", flags="QR AA", eflags="DO")
resp.cmp(bind) 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 # Wildcard Expansion to apex
resp = knot.dig("a.to-apex.example", "SOA", dnssec=True) resp = knot.dig("a.to-apex.example", "SOA", dnssec=True)
resp.check(rcode="NOERROR", flags="QR AA", eflags="DO") 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