From 5a3bb649bc20aa8621330b1616184dae64788f2e Mon Sep 17 00:00:00 2001
From: Lubos Slovak <lubos.slovak@nic.cz>
Date: Tue, 8 Oct 2013 16:12:27 +0200
Subject: [PATCH] Moved node to NSEC3 connecting to node adjusting.

Saves one iteration over the zone + properly sets NSEC3 references
when disabling NSEC3.

refs #4
---
 src/libknot/dnssec/zone-nsec.c   | 126 ++++++++-----------------------
 src/libknot/dnssec/zone-nsec.h   |  31 ++++----
 src/libknot/zone/zone-contents.c | 126 ++++++++++++-------------------
 3 files changed, 94 insertions(+), 189 deletions(-)

diff --git a/src/libknot/dnssec/zone-nsec.c b/src/libknot/dnssec/zone-nsec.c
index c8fea7066..577f6f638 100644
--- a/src/libknot/dnssec/zone-nsec.c
+++ b/src/libknot/dnssec/zone-nsec.c
@@ -434,43 +434,6 @@ static knot_dname_t *nsec3_hash_to_dname(const uint8_t *hash, size_t hash_size,
 	return dname;
 }
 
-/*!
- * \brief Create NSEC3 owner name from regular owner name.
- *
- * \param owner      Node owner name.
- * \param params     Params for NSEC3 hashing function.
- * \param apex       Apex size.
- * \param apex_size  Size of the zone apex.
- *
- * \return NSEC3 owner name, NULL in case of error.
- */
-static knot_dname_t *create_nsec3_owner(const knot_dname_t *owner,
-                                        const knot_nsec3_params_t *params,
-                                        const char *apex, size_t apex_size)
-{
-	assert(owner);
-	assert(params);
-	assert(apex);
-
-	uint8_t *hash = NULL;
-	size_t hash_size = 0;
-	int name_size = knot_dname_size(owner);
-
-	if (name_size < 0) {
-		return NULL;
-	}
-
-	if (knot_nsec3_hash(params, owner, name_size, &hash, &hash_size)
-	    != KNOT_EOK) {
-		return NULL;
-	}
-
-	knot_dname_t *result = nsec3_hash_to_dname(hash, hash_size, apex, apex_size);
-	free(hash);
-
-	return result;
-}
-
 /* - NSEC3 nodes construction ---------------------------------------------- */
 
 /*!
@@ -862,6 +825,36 @@ static bool get_zone_soa_min_ttl(const knot_zone_contents_t *zone,
 
 /* - public API ------------------------------------------------------------ */
 
+/*!
+ * \brief Create NSEC3 owner name from regular owner name.
+ */
+knot_dname_t *create_nsec3_owner(const knot_dname_t *owner,
+                                 const knot_nsec3_params_t *params,
+                                 const char *apex, size_t apex_size)
+{
+	if (owner == NULL || params == NULL || apex == NULL) {
+		return NULL;
+	}
+
+	uint8_t *hash = NULL;
+	size_t hash_size = 0;
+	int name_size = knot_dname_size(owner);
+
+	if (name_size < 0) {
+		return NULL;
+	}
+
+	if (knot_nsec3_hash(params, owner, name_size, &hash, &hash_size)
+	    != KNOT_EOK) {
+		return NULL;
+	}
+
+	knot_dname_t *result = nsec3_hash_to_dname(hash, hash_size, apex, apex_size);
+	free(hash);
+
+	return result;
+}
+
 /*!
  * \brief Create NSEC or NSEC3 chain in the zone.
  */
@@ -894,62 +887,3 @@ int knot_zone_create_nsec_chain(const knot_zone_contents_t *zone,
 	// Sign newly created records right away
 	return knot_zone_sign_nsecs_in_changeset(zone_keys, policy, changeset);
 }
-
-/*!
- * \brief Connect regular and NSEC3 nodes in the zone.
- */
-int knot_zone_connect_nsec_nodes(knot_zone_contents_t *zone)
-{
-	if (!zone) {
-		return KNOT_EINVAL;
-	}
-
-	if (!is_nsec3_enabled(zone)) {
-		return KNOT_EOK;
-	}
-
-	char *apex;
-	size_t apex_size;
-	if (!get_zone_apex_str(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;
-		}
-
-		node->nsec3_node = nsec3_node;
-
-		knot_dname_free(&nsec3_name);
-		hattrie_iter_next(it);
-	}
-
-	free(apex);
-	hattrie_iter_free(it);
-
-	return result;
-}
diff --git a/src/libknot/dnssec/zone-nsec.h b/src/libknot/dnssec/zone-nsec.h
index 491f45f6e..0cea6944d 100644
--- a/src/libknot/dnssec/zone-nsec.h
+++ b/src/libknot/dnssec/zone-nsec.h
@@ -44,6 +44,20 @@
  */
 bool is_nsec3_enabled(const knot_zone_contents_t *zone);
 
+/*!
+ * \brief Create NSEC3 owner name from regular owner name.
+ *
+ * \param owner      Node owner name.
+ * \param params     Params for NSEC3 hashing function.
+ * \param apex       Apex name.
+ * \param apex_size  Size of the zone apex name.
+ *
+ * \return NSEC3 owner name, NULL in case of error.
+ */
+knot_dname_t *create_nsec3_owner(const knot_dname_t *owner,
+                                 const knot_nsec3_params_t *params,
+                                 const char *apex, size_t apex_size);
+
 /*!
  * \brief Create NSEC or NSEC3 chain in the zone.
  *
@@ -57,23 +71,6 @@ int knot_zone_create_nsec_chain(const knot_zone_contents_t *zone,
                                 const knot_zone_keys_t *zone_keys,
                                 const knot_dnssec_policy_t *policy);
 
-/*!
- * \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.
- *
- * \todo IMPORTANT: this is called always when zone adjusting is. IMHO it can
- *       be moved back into zone adjusting as before commit bb795a4. This only
- *       leads to confusion and duplication of code.
- */
-int knot_zone_connect_nsec_nodes(knot_zone_contents_t *zone);
-
 #endif // _KNOT_DNSSEC_ZONE_NSEC_H_
 
 /*! @} */
diff --git a/src/libknot/zone/zone-contents.c b/src/libknot/zone/zone-contents.c
index dc33e4d09..97ebbd508 100644
--- a/src/libknot/zone/zone-contents.c
+++ b/src/libknot/zone/zone-contents.c
@@ -128,6 +128,37 @@ static void knot_zone_contents_destroy_node_rrsets_from_tree(
 	knot_node_free(tnode);
 }
 
+/*----------------------------------------------------------------------------*/
+
+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);
+	*nsec3_name = NULL;
+
+	const knot_nsec3_params_t *nsec3_params =
+		knot_zone_contents_nsec3params(zone);
+
+	if (nsec3_params == NULL) {
+		return KNOT_ENSEC3PAR;
+	}
+
+	const knot_dname_t *apex_name = knot_node_owner(
+	                        knot_zone_contents_apex(zone));
+	assert(apex_name);
+
+	*nsec3_name = create_nsec3_owner(name, nsec3_params,
+	                                 (const char *)apex_name,
+	                                 knot_dname_size(apex_name));
+	if (nsec3_name == NULL) {
+		return KNOT_ERROR;
+	}
+
+	return KNOT_EOK;
+}
+
+
 /*----------------------------------------------------------------------------*/
 
 /*!
@@ -192,6 +223,24 @@ static void knot_zone_contents_adjust_normal_node(knot_node_t **tnode,
 	if (!knot_node_is_non_auth(node) && knot_node_rrset_count(node) > 0) {
 		args->previous_node = node;
 	}
+
+	// Connect to NSEC3 node (only if NSEC3 tree is not empty)
+	knot_node_t *nsec3 = NULL;
+	knot_dname_t *nsec3_name = NULL;
+	int ret = knot_zone_contents_nsec3_name(args->zone,
+	                                        knot_node_owner(node),
+	                                        &nsec3_name);
+	if (ret == KNOT_EOK) {
+		assert(nsec3_name);
+		knot_zone_tree_get(args->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 {
+		args->err = ret;
+	}
+
+	knot_dname_free(&nsec3_name);
 }
 
 /*----------------------------------------------------------------------------*/
@@ -225,79 +274,6 @@ static void knot_zone_contents_adjust_nsec3_node(knot_node_t **tnode,
 	knot_node_set_previous(node, args->previous_node);
 	args->previous_node = node;
 }
-
-/*----------------------------------------------------------------------------*/
-
-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);
-
-	*nsec3_name = NULL;
-
-	const knot_nsec3_params_t *nsec3_params =
-		knot_zone_contents_nsec3params(zone);
-
-	if (nsec3_params == NULL) {
-		return KNOT_ENSEC3PAR;
-	}
-
-	uint8_t *hashed_name = NULL;
-	size_t hash_size = 0;
-
-	int res = knot_nsec3_hash(nsec3_params, name, knot_dname_size(name),
-	                          &hashed_name, &hash_size);
-
-	if (res != 0) {
-		char *n = knot_dname_to_str(name);
-		dbg_zone("Error while hashing name %s.\n", n);
-		free(n);
-		return KNOT_ECRYPTO;
-	}
-
-	dbg_zone("Hash: ");
-	dbg_zone_hex((char *)hashed_name, hash_size);
-	dbg_zone("\n");
-
-	uint8_t *name_b32 = NULL;
-	size_t size = base32hex_encode_alloc(hashed_name, hash_size,
-					     &name_b32);
-
-	if (size == 0) {
-		char *n = knot_dname_to_str(name);
-		free(n);
-		free(name_b32);
-		return KNOT_ECRYPTO;
-	}
-
-	assert(name_b32 != NULL);
-	free(hashed_name);
-
-	/* Will be returned to caller, make sure it is released after use. */
-	*nsec3_name = knot_dname_from_str((char *)name_b32, size);
-
-	free(name_b32);
-
-	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) {
-		free(*nsec3_name);
-		return KNOT_ERROR;
-	}
-
-	*nsec3_name = ret;
-
-	return KNOT_EOK;
-}
-
 /*----------------------------------------------------------------------------*/
 /*!
  * \brief Tries to find the given domain name in the zone tree.
@@ -1355,9 +1331,7 @@ int knot_zone_contents_adjust(knot_zone_contents_t *zone,
 
 	assert(zone->apex == adjust_arg.first_node);
 
-	// connect NSEC3 nodes
-
-	return knot_zone_connect_nsec_nodes(zone);
+	return KNOT_EOK;
 }
 
 /*----------------------------------------------------------------------------*/
-- 
GitLab