]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
avoid iterating from a too short zone cut
authorVladimír Čunát <vladimir.cunat@nic.cz>
Tue, 20 Feb 2018 14:50:48 +0000 (15:50 +0100)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Tue, 20 Feb 2018 15:52:50 +0000 (16:52 +0100)
Example: after foo.sk query the bar.sk query started iterating from
asking the root again for NS sk.  This bug was present on insecure zones,
and before version 2.0.0 only such that have a secure parent.
(These two parts of the bug correspond to the two changes in this commit.)

Fixes https://gitlab.labs.nic.cz/knot/knot-resolver/issues/246

NEWS
lib/layer/validate.c
lib/zonecut.c

diff --git a/NEWS b/NEWS
index 62cb62082c43ab83a5d95e7a746e2198c186c208..9cdb5f126caa20508a0bb68c52de604d463f7dd0 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,12 @@
+Knot Resolver 2.x.y (2018-02-zz)
+================================
+
+Bugfixes
+--------
+- when iterating, avoid unnecessary queries for NS in insecure parent.
+  This problem worsened in 2.0.0. (#246)
+
+
 Knot Resolver 2.1.0 (2018-02-16)
 ================================
 
index 2843d1dbc42d4f09d46aa8d9474648cd43238c14..a90afa3b12d9710fbdb4e80b428691f123e25c9f 100644 (file)
@@ -417,6 +417,22 @@ static int update_delegation(struct kr_request *req, struct kr_query *qry, knot_
                } else {
                        VERBOSE_MSG(qry, "<= DS doesn't exist, going insecure\n");
                        qry->flags.DNSSEC_NODS = true;
+                       /* Rank the corresponding nonauth NS as insecure. */
+                       for (int i = 0; i < req->auth_selected.len; ++i) {
+                               ranked_rr_array_entry_t *ns = req->auth_selected.at[i];
+                               if (ns->qry_uid != qry->uid || !ns->rr
+                                   || ns->rr->type != KNOT_RRTYPE_NS) {
+                                       continue;
+                               }
+                               /* Found the record.  Note: this is slightly fragile
+                                * in case there were more NS records in the packet.
+                                * As it is now, kr_nsec*_ref_to_unsigned consider
+                                * (only) the first NS record in the packet. */
+                               if (!kr_rank_test(ns->rank, KR_RANK_AUTH)) { /* sanity */
+                                       ns->rank = KR_RANK_INSECURE;
+                               }
+                               break;
+                       }
                }
                return ret;
        } else if (qry->flags.FORWARD && qry->parent) {
index d54a4d114d13bab32de5d8ea850084c9b62435aa..52ff6249120b10315d71384c88576f9ec37716f4 100644 (file)
@@ -308,14 +308,16 @@ static int fetch_ns(struct kr_context *ctx, struct kr_zonecut *cut,
        if (ret != 0) {
                return ret;
        }
-       int32_t new_ttl = kr_cache_ttl(&peek, qry, name, KNOT_RRTYPE_NS);
-       if (new_ttl < 0) {
-               return kr_error(ESTALE);
-       }
        /* Note: we accept *any* rank from the cache.  We assume that nothing
         * completely untrustworthy could get into the cache, e.g out-of-bailiwick
         * records that weren't validated.
         */
+       *rank = peek.rank;
+
+       int32_t new_ttl = kr_cache_ttl(&peek, qry, name, KNOT_RRTYPE_NS);
+       if (new_ttl < 0) {
+               return kr_error(ESTALE);
+       }
        /* Materialize the rdataset temporarily, for simplicity. */
        knot_rdataset_t ns_rds = { 0, NULL };
        ret = kr_cache_materialize(&ns_rds, &peek, new_ttl, cut->pool);