From cbd8f55b34515ce7a066e2cc677c8e642b1bd0f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Vavru=C5=A1a?= <marek.vavrusa@nic.cz>
Date: Sat, 19 Sep 2015 21:22:12 +0200
Subject: [PATCH] lib: per-query islands of trust, prep for NTA
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

each subrequest can now enter and leave islands of trust
independently. this fixes a case when a zone is in an
island of trust, but one of its NS isn’t (different zone for example)
---
 lib/dnssec/ta.c | 15 +++++++++++++++
 lib/dnssec/ta.h |  2 ++
 lib/resolve.c   | 33 +++++++++++++++++++++------------
 lib/zonecut.c   |  8 --------
 4 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/lib/dnssec/ta.c b/lib/dnssec/ta.c
index fe3c0d5c0..f9fd2bd96 100644
--- a/lib/dnssec/ta.c
+++ b/lib/dnssec/ta.c
@@ -26,6 +26,7 @@
 #include <libknot/rdataset.h>
 #include <libknot/rrset.h>
 #include <libknot/rrtype/rdname.h>
+#include <libknot/packet/wire.h>
 
 #include "lib/defines.h"
 #include "lib/dnssec/ta.h"
@@ -644,6 +645,20 @@ int kr_ta_contains(struct trust_anchors *tas, const knot_dname_t *name)
 	return ta_find(&tas->locked, name) != NULL;
 }
 
+int kr_ta_covers(struct trust_anchors *tas, const knot_dname_t *name)
+{
+	while(name) {
+		if (kr_ta_contains(tas, name)) {
+			return true;
+		}
+		if (name[0] == '\0') {
+			return false;
+		}
+		name = knot_wire_next_label(name, NULL);
+	}
+	return false;	
+}
+
 int kr_ta_get(knot_rrset_t **ta, struct trust_anchors *tas, const knot_dname_t *name, mm_ctx_t *pool)
 {
 	if (!ta || !tas || !name) {
diff --git a/lib/dnssec/ta.h b/lib/dnssec/ta.h
index 7d57d932c..390004437 100644
--- a/lib/dnssec/ta.h
+++ b/lib/dnssec/ta.h
@@ -50,6 +50,8 @@ int kr_ta_add(struct trust_anchors *tas, const char *ta_str);
 
 int kr_ta_contains(struct trust_anchors *tas, const knot_dname_t *name);
 
+int kr_ta_covers(struct trust_anchors *tas, const knot_dname_t *name);
+
 int kr_ta_get(knot_rrset_t **ta, struct trust_anchors *tas, const knot_dname_t *name, mm_ctx_t *pool);
 
 int kr_ta_rdlock(struct trust_anchors *tas);
diff --git a/lib/resolve.c b/lib/resolve.c
index ae623568d..94084ce17 100644
--- a/lib/resolve.c
+++ b/lib/resolve.c
@@ -344,17 +344,14 @@ static int zone_cut_check(struct kr_request *request, struct kr_query *qry, knot
 {
 	struct kr_rplan *rplan = &request->rplan;
 
-	/* Always try with DNSSEC if it finds an island of trust. */
-	if (!(request->options & QUERY_DNSSEC_WANT) &&
-	    kr_ta_contains(&global_trust_anchors, qry->zone_cut.name)) {
-		request->options |= QUERY_DNSSEC_WANT;
-		DEBUG_MSG(">< entered island of trust\n");
-	}
 	/* The query wasn't resolved from cache,
 	 * now it's the time to look up closest zone cut from cache. */
-	bool want_secured = (request->options & QUERY_DNSSEC_WANT);
 	if (qry->flags & QUERY_AWAIT_CUT) {
-		int ret = ns_fetch_cut(qry, request, want_secured);
+		/* Want DNSSEC if it's posible to secure this name (e.g. is covered by any TA) */
+		if (kr_ta_covers(&global_trust_anchors, qry->zone_cut.name)) {
+			qry->flags |= QUERY_DNSSEC_WANT;
+		}
+		int ret = ns_fetch_cut(qry, request, (qry->flags & QUERY_DNSSEC_WANT));
 		if (ret != 0) {
 			return KNOT_STATE_FAIL;
 		}
@@ -366,10 +363,22 @@ static int zone_cut_check(struct kr_request *request, struct kr_query *qry, knot
 		}
 		qry->flags &= ~QUERY_AWAIT_CUT;
 	}
-
-	/* Missing delegation signature, fetch it first. */
-	if ((qry->flags & QUERY_AWAIT_DS) && (qry->zone_cut.missing_name)) {
-		int ret = zone_cut_subreq(rplan, qry, qry->zone_cut.missing_name, KNOT_RRTYPE_DS);
+	/* Enable DNSSEC if enters a new island of trust. */
+	bool want_secured = (qry->flags & QUERY_DNSSEC_WANT);
+	if (!want_secured && kr_ta_contains(&global_trust_anchors, qry->zone_cut.name)) {
+		qry->flags |= QUERY_DNSSEC_WANT;
+		want_secured = true;
+		WITH_DEBUG {
+		char qname_str[KNOT_DNAME_MAXLEN];
+		knot_dname_to_str(qname_str, qry->zone_cut.name, sizeof(qname_str));
+		DEBUG_MSG(">< TA: using '%s'\n", qname_str);
+		}
+	}
+	/* @todo Disable DNSSEC if it encounters NTA */
+	if (want_secured && !qry->zone_cut.trust_anchor) {
+		kr_ta_get(&qry->zone_cut.trust_anchor, &global_trust_anchors,
+		          qry->zone_cut.name, qry->zone_cut.pool);
+	}
 		if (ret != 0) {
 			return KNOT_STATE_FAIL;
 		}
diff --git a/lib/zonecut.c b/lib/zonecut.c
index c0bb394a9..3a3baa41f 100644
--- a/lib/zonecut.c
+++ b/lib/zonecut.c
@@ -24,7 +24,6 @@
 #include "lib/rplan.h"
 #include "lib/defines.h"
 #include "lib/layer.h"
-#include "lib/dnssec/ta.h" // kr_ta_parse()
 #include "lib/generic/pack.h"
 
 /* Root hint descriptor. */
@@ -291,13 +290,6 @@ int kr_zonecut_set_sbelt(struct kr_context *ctx, struct kr_zonecut *cut)
 
 	/* Set trust anchor. */
 	knot_rrset_free(&cut->trust_anchor, cut->pool);
-	/* The root trust anchor can be changed via the validator layer
-	 * (interactive) interface.
-	 */
-	int ret = kr_ta_get(&cut->trust_anchor, &global_trust_anchors, ROOT_NAME, cut->pool);
-	if (ret != 0) {
-		return ret;
-	}
 	return kr_ok();
 }
 
-- 
GitLab