From 021046601d44f392adad58b41e778205ef166d00 Mon Sep 17 00:00:00 2001
From: Karel Slany <karel.slany@nic.cz>
Date: Thu, 24 Sep 2015 18:25:16 +0200
Subject: [PATCH] lib/validate: Added function that validates any NSEC no data
 response.

---
 lib/dnssec/nsec.c    | 45 ++++++++++++++++++++++++++++++++++++++++++++
 lib/dnssec/nsec.h    | 11 +++++++++++
 lib/layer/validate.c |  8 +-------
 3 files changed, 57 insertions(+), 7 deletions(-)

diff --git a/lib/dnssec/nsec.c b/lib/dnssec/nsec.c
index c5a974477..1f8248270 100644
--- a/lib/dnssec/nsec.c
+++ b/lib/dnssec/nsec.c
@@ -400,6 +400,51 @@ int kr_nsec_empty_nonterminal_response_check(const knot_pkt_t *pkt, knot_section
 	return kr_error(ENOENT);
 }
 
+int kr_nsec_no_data(const knot_pkt_t *pkt, knot_section_t section_id,
+                    const knot_dname_t *sname, uint16_t stype)
+{
+	const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id);
+	if (!sec || !sname) {
+		return kr_error(EINVAL);
+	}
+
+	int ret;
+	int flags = 0;
+	for (unsigned i = 0; i < sec->count; ++i) {
+		const knot_rrset_t *rrset = knot_pkt_rr(sec, i);
+		if (rrset->type != KNOT_RRTYPE_NSEC) {
+			continue;
+		}
+
+		/* No data. */
+		if (knot_dname_is_equal(rrset->owner, sname)) {
+			ret = no_data_response_check_rrtype(&flags, rrset, stype);
+			if (ret != 0) {
+				return ret;
+			}
+		}
+		if (flags & FLG_NOEXIST_RRTYPE) {
+			return kr_ok();
+		}
+
+		/* Empty non-terminal. */
+		if (nsec_empty_nonterminal(rrset, sname) == 0) {
+			return kr_ok();
+		}
+
+		/* Wild card no data. */
+		ret = wildcard_no_data_response_check(&flags, rrset, sname, stype);
+		if (ret != 0) {
+			return ret;
+		}
+		if ((flags & FLG_NOEXIST_RRSET) && (flags & FLG_NOEXIST_CLOSER)) {
+			return kr_ok();
+		}
+	}
+
+	return kr_error(ENOENT);
+}
+
 int kr_nsec_existence_denial(const knot_pkt_t *pkt, knot_section_t section_id,
                              const knot_dname_t *sname, uint16_t stype, mm_ctx_t *pool)
 {
diff --git a/lib/dnssec/nsec.h b/lib/dnssec/nsec.h
index 1f9d258c1..bb4cb210b 100644
--- a/lib/dnssec/nsec.h
+++ b/lib/dnssec/nsec.h
@@ -85,6 +85,17 @@ int kr_nsec_wildcard_answer_response_check(const knot_pkt_t *pkt, knot_section_t
 int kr_nsec_empty_nonterminal_response_check(const knot_pkt_t *pkt, knot_section_t section_id,
                                              const knot_dname_t *sname);
 
+/**
+ * Authenticated denial of existence according to RFC4035 3.1.3.1 and 3.1.3.4.
+ * @param pkt        Packet structure to be processed.
+ * @param section_id Packet section to be processed.
+ * @param sname      Name to be checked.
+ * @param stype      Type to be checked.
+ * @return           0 or error code.
+ */
+int kr_nsec_no_data(const knot_pkt_t *pkt, knot_section_t section_id,
+                    const knot_dname_t *sname, uint16_t stype);
+
 /**
  * Authenticated denial of existence according to RFC4035 5.4.
  * @note No RRSIGs are validated.
diff --git a/lib/layer/validate.c b/lib/layer/validate.c
index fa9d10fbd..63d44701e 100644
--- a/lib/layer/validate.c
+++ b/lib/layer/validate.c
@@ -392,13 +392,7 @@ static int validate(knot_layer_t *ctx, knot_pkt_t *pkt)
 			 * ? merge the functionality together to share code/resources
 			 */
 			if (!has_nsec3) {
-				ret = kr_nsec_no_data_response_check(pkt, KNOT_AUTHORITY, knot_pkt_qname(pkt), knot_pkt_qtype(pkt));
-				if (ret != 0) {
-					ret = kr_nsec_wildcard_no_data_response_check(pkt, KNOT_AUTHORITY, knot_pkt_qname(pkt), knot_pkt_qtype(pkt));
-				}
-				if (ret != 0) {
-					ret = kr_nsec_empty_nonterminal_response_check(pkt, KNOT_AUTHORITY, knot_pkt_qname(pkt));
-				}
+				ret = kr_nsec_no_data(pkt, KNOT_AUTHORITY, knot_pkt_qname(pkt), knot_pkt_qtype(pkt));
 			} else {
 				ret = kr_nsec3_no_data(pkt, KNOT_AUTHORITY, knot_pkt_qname(pkt), knot_pkt_qtype(pkt));
 			}
-- 
GitLab