Commit bb795a44 authored by Jan Včelák's avatar Jan Včelák 🚀

NSEC: zone adjusting: remove connecting of regular nodes and NSEC3 nodes

- connections are generated when NSEC3 nodes are created
- explicitly request node connecting when the zone is loaded or after incoming transfer
parent d311c8f2
......@@ -31,6 +31,7 @@
#include "libknot/common.h"
#include "knot/zone/semantic-check.h"
#include "libknot/zone/zone-contents.h"
#include "libknot/zone/zone-nsec.h"
#include "knot/other/debug.h"
#include "knot/zone/zone-load.h"
#include "zscanner/file_loader.h"
......@@ -696,12 +697,32 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
return NULL;
}
int ret;
knot_node_t *first_nsec3_node = NULL;
knot_node_t *last_nsec3_node = NULL;
rrset_list_delete(&c->node_rrsigs);
knot_zone_contents_adjust(c->current_zone, &first_nsec3_node,
&last_nsec3_node, 0);
ret = knot_zone_contents_adjust(c->current_zone, &first_nsec3_node,
&last_nsec3_node, 0);
if (ret != KNOT_EOK) {
log_zone_error("Failed to finalize zone contents: %s\n",
knot_strerror(ret));
rrset_list_delete(&c->node_rrsigs);
knot_zone_t *zone_to_free = c->current_zone->zone;
knot_zone_deep_free(&zone_to_free);
return NULL;
}
ret = knot_zone_connect_nsec_nodes(c->current_zone);
if (ret != KNOT_EOK) {
log_zone_error("Failed to connect regular and NSEC3 nodes: %s\n",
knot_strerror(ret));
rrset_list_delete(&c->node_rrsigs);
knot_zone_t *zone_to_free = c->current_zone->zone;
knot_zone_deep_free(&zone_to_free);
return NULL;
}
if (loader->semantic_checks) {
int check_level = 1;
const knot_rrset_t *soa_rr =
......
......@@ -37,6 +37,7 @@
#include "updates/changesets.h"
#include "updates/ddns.h"
#include "tsig-op.h"
#include "zone/zone-nsec.h"
/*----------------------------------------------------------------------------*/
......@@ -4079,9 +4080,11 @@ int knot_ns_process_axfrin(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
dbg_ns_verb("ns_process_axfrin: adjusting zone.\n");
int rc = knot_zone_contents_adjust(zone, NULL, NULL, 0);
if (rc != KNOT_EOK) {
if (rc != KNOT_EOK)
return rc;
rc = knot_zone_connect_nsec_nodes(zone);
if (rc != KNOT_EOK)
return rc;
}
// save the zone contents to the xfr->data
xfr->new_contents = zone;
......
......@@ -28,6 +28,7 @@
#include "packet/packet.h"
#include "dname.h"
#include "zone/zone.h"
#include "zone/zone-nsec.h"
#include "packet/query.h"
#include "common.h"
#include "updates/changesets.h"
......@@ -3154,6 +3155,13 @@ int xfrin_finalize_updated_zone(knot_zone_contents_t *contents_copy,
knot_strerror(ret));
return ret;
}
ret = knot_zone_connect_nsec_nodes(contents_copy);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to connect regular and NSEC3 nodes: %s\n",
knot_strerror(ret));
return ret;
}
assert(knot_zone_contents_apex(contents_copy) != NULL);
return KNOT_EOK;
......
......@@ -402,26 +402,6 @@ static int knot_zone_contents_adjust_node(knot_node_t *node,
knot_node_set_wildcard_child(knot_node_get_parent(node), node);
}
// NSEC3 node (only if NSEC3 tree is not empty)
/*! \todo We need only exact matches, what if node has no nsec3 node? */
/* This is faster, as it doesn't need ordered access. */
knot_node_t *nsec3 = NULL;
knot_dname_t *nsec3_name = NULL;
ret = knot_zone_contents_nsec3_name(zone, knot_node_owner(node),
&nsec3_name);
if (ret == KNOT_EOK) {
assert(nsec3_name);
knot_zone_tree_get(zone->nsec3_nodes, nsec3_name, &nsec3);
knot_node_set_nsec3_node(node, nsec3);
} else if (ret == KNOT_ENSEC3PAR) {
knot_node_set_nsec3_node(node, NULL);
} else {
/* Something could be in DNAME. */
knot_dname_free(&nsec3_name);
return ret;
}
knot_dname_free(&nsec3_name);
dbg_zone_detail("Set flags to the node: \n");
dbg_zone_detail("Delegation point: %s\n",
knot_node_is_deleg_point(node) ? "yes" : "no");
......@@ -592,9 +572,9 @@ static void knot_zone_contents_adjust_nsec3_node_in_tree_ptr(
/*----------------------------------------------------------------------------*/
int knot_zone_contents_nsec3_name(const knot_zone_contents_t *zone,
const knot_dname_t *name,
knot_dname_t **nsec3_name)
static int knot_zone_contents_nsec3_name(const knot_zone_contents_t *zone,
const knot_dname_t *name,
knot_dname_t **nsec3_name)
{
assert(nsec3_name != NULL);
......@@ -603,24 +583,12 @@ int knot_zone_contents_nsec3_name(const knot_zone_contents_t *zone,
const knot_nsec3_params_t *nsec3_params =
knot_zone_contents_nsec3params(zone);
if (nsec3_params == NULL) {
dbg_zone_exec(
char *n = knot_dname_to_str(zone->apex->owner);
dbg_zone("No NSEC3PARAM for zone %s.\n", n);
free(n);
);
if (nsec3_params == NULL)
return KNOT_ENSEC3PAR;
}
uint8_t *hashed_name = NULL;
size_t hash_size = 0;
dbg_zone_exec_verb(
char *n = knot_dname_to_str(name);
dbg_zone_verb("Hashing name %s.\n", n);
free(n);
);
int res = knot_nsec3_hash(nsec3_params, name->name, name->size,
&hashed_name, &hash_size);
......@@ -641,7 +609,6 @@ dbg_zone_exec_verb(
if (size == 0) {
char *n = knot_dname_to_str(name);
dbg_zone("Error while encoding hashed name %s to base32.\n", n);
free(n);
free(name_b32);
return KNOT_ECRYPTO;
......@@ -650,31 +617,20 @@ dbg_zone_exec_verb(
assert(name_b32 != NULL);
free(hashed_name);
dbg_zone_exec_verb(
/* name_b32 is not 0-terminated. */
char b32_string[hash_size + 1];
memset(b32_string, 0, hash_size + 1);
memcpy(b32_string, name_b32, hash_size);
dbg_zone_verb("Base32-encoded hash: %s\n", b32_string);
);
/* Will be returned to caller, make sure it is released after use. */
*nsec3_name = knot_dname_new_from_str((char *)name_b32, size, NULL);
free(name_b32);
if (*nsec3_name == NULL) {
dbg_zone("Error while creating domain name for hashed name.\n");
if (*nsec3_name == NULL)
return KNOT_ERROR;
}
knot_dname_to_lower(*nsec3_name);
assert(zone->apex->owner != NULL);
knot_dname_t *ret = knot_dname_cat(*nsec3_name, zone->apex->owner);
if (ret == NULL) {
dbg_zone("Error while creating NSEC3 domain name for "
"hashed name.\n");
knot_dname_release(*nsec3_name);
return KNOT_ERROR;
}
......
......@@ -501,26 +501,6 @@ const knot_dname_t *knot_zone_contents_find_dname_in_rdata(
const knot_zone_contents_t *zone,
const knot_dname_t *dname);
/*!
* \brief Creates a NSEC3 hashed name for the given domain name.
*
* \note The zone's NSEC3PARAM record must be parsed prior to calling this
* function (see knot_zone_load_nsec3param()).
*
* \param zone Zone from which to take the NSEC3 parameters.
* \param name Domain name to hash.
* \param nsec3_name Hashed name.
*
* \retval KNOT_EOK
* \retval KNOT_ENSEC3PAR
* \retval KNOT_ECRYPTO
* \retval KNOT_ERROR if an error occured while creating a new domain name
* from the hash or concatenating it with the zone name.
*/
int knot_zone_contents_nsec3_name(const knot_zone_contents_t *zone,
const knot_dname_t *name,
knot_dname_t **nsec3_name);
void knot_zone_contents_insert_dname_into_table(knot_dname_t **in_dname,
hattrie_t *lookup_tree);
......
......@@ -653,3 +653,58 @@ int knot_zone_create_nsec_chain(knot_zone_t *zone)
return knot_zone_contents_adjust(zone->contents, NULL, NULL, 0);
}
/*!
* \brief Connect regular and NSEC3 nodes in the zone.
*/
int knot_zone_connect_nsec_nodes(knot_zone_contents_t *zone)
{
// TODO: little cleanup will be useful (zone->zone, ...)
if (!zone)
return KNOT_EINVAL;
if (!is_nsec3_enabled(zone->zone))
return KNOT_EOK;
char *apex;
size_t apex_size;
if (!get_zone_apex_str(zone->zone, &apex, &apex_size))
return KNOT_ENOMEM;
bool sorted = false;
hattrie_iter_t *it = hattrie_iter_begin(zone->nodes, sorted);
if (!it) {
free(apex);
return KNOT_ENOMEM;
}
int result = KNOT_EOK;
while (!hattrie_iter_finished(it)) {
knot_node_t *node = (knot_node_t *)*hattrie_iter_val(it);
knot_dname_t *nsec3_name;
nsec3_name = create_nsec3_owner(node->owner, &zone->nsec3_params, apex, apex_size);
if (!nsec3_name) {
result = KNOT_ENOMEM;
break;
}
knot_node_t *nsec3_node = NULL;
result = knot_zone_tree_get(zone->nsec3_nodes, nsec3_name, &nsec3_node);
if (result != KNOT_EOK)
break;
if (nsec3_node != NULL)
node->nsec3_node = nsec3_node;
knot_dname_release(nsec3_name);
hattrie_iter_next(it);
}
free(apex);
hattrie_iter_free(it);
return result;
}
......@@ -27,4 +27,17 @@
*/
int knot_zone_create_nsec_chain(knot_zone_t *zone);
/*!
* \brief Connect regular and NSEC3 nodes in the zone.
*
* \note No need to call this function after 'knot_zone_create_nsec_chain'.
* \note Exits succesfully if NSEC3 is not enabled.
* \note Skips nodes with missing related NSEC3 nodes.
*
* \param zone Zone for which the operation is performed.
*
* \return Error code, KNOT_EOK if successful.
*/
int knot_zone_connect_nsec_nodes(knot_zone_contents_t *zone);
#endif // _KNOT_ZONE_NSEC_H_
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