]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
fix positive NSEC3 wildcards not always being answered
authorVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 7 May 2018 14:38:57 +0000 (16:38 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 7 May 2018 14:38:57 +0000 (16:38 +0200)
lib/cache/api.c
lib/cache/nsec3.c

index 03953a397910ab756bc5b37b3f156339b052b9c4..09c07ebdf66ff5ab8b74306a225dfd37b9b5d4d3 100644 (file)
@@ -595,6 +595,7 @@ static int peek_encloser(
 
        /**** 2. Find a closest (provable) encloser (of sname). */
        int clencl_labels = -1;
+       bool clencl_is_tentative = false;
        if (!ans->nsec_p) { /* NSEC */
                int ret = nsec1_encloser(k, ans, sname_labels, &clencl_labels,
                                         &cover_low_kwz, &cover_hi_kwz, qry, cache);
@@ -602,7 +603,9 @@ static int peek_encloser(
        } else {
                int ret = nsec3_encloser(k, ans, sname_labels, &clencl_labels,
                                         &cover_low_kwz, &cover_hi_kwz, qry, cache);
-               if (ret) return ret;
+               clencl_is_tentative = ret == ABS(ENOENT) && clencl_labels >= 0;
+               /* ^^ Last chance: *positive* wildcard record under this clencl. */
+               if (ret && !clencl_is_tentative) return ret;
        }
 
        /* We should have either a match or a cover at this point. */
@@ -610,37 +613,36 @@ static int peek_encloser(
                assert(false);
                return kr_error(EINVAL);
        }
-       const bool sname_covered = ans->rcode == PKT_NXDOMAIN;
+       const bool ncloser_covered = ans->rcode == PKT_NXDOMAIN;
 
        /** Name of the closest (provable) encloser. */
        const knot_dname_t *clencl_name = qry->sname;
        for (int l = sname_labels; l > clencl_labels; --l)
                clencl_name = knot_wire_next_label(clencl_name, NULL);
 
-       /**** 3. source of synthesis checks, in case sname was covered.
+       /**** 3. source of synthesis checks, in case the next closer name was covered.
         **** 3a. We want to query for NSEC* of source of synthesis (SS) or its
         * predecessor, providing us with a proof of its existence or non-existence. */
-       if (sname_covered && !ans->nsec_p) {
+       if (ncloser_covered && !ans->nsec_p) {
                int ret = nsec1_src_synth(k, ans, clencl_name,
                                          cover_low_kwz, cover_hi_kwz, qry, cache);
                if (ret == AR_SOA) return 0;
                assert(ret <= 0);
                if (ret) return ret;
 
-       } else if (sname_covered && ans->nsec_p) {
-               //XXX NSEC3
+       } else if (ncloser_covered && ans->nsec_p && !clencl_is_tentative) {
                int ret = nsec3_src_synth(k, ans, clencl_name,
                                          cover_low_kwz, cover_hi_kwz, qry, cache);
                if (ret == AR_SOA) return 0;
                assert(ret <= 0);
                if (ret) return ret;
 
-       } /* else (!sname_covered) so no wildcard checks needed,
+       } /* else (!ncloser_covered) so no wildcard checks needed,
           * as we proved that sname exists. */
 
-       /**** 3b. find wildcarded answer, if sname was covered
+       /**** 3b. find wildcarded answer, if next closer name was covered
         * and we don't have a full proof yet.  (common for NSEC*) */
-       if (!sname_covered)
+       if (!ncloser_covered)
                return kr_ok(); /* decrease indentation */
        /* Construct key for exact qry->stype + source of synthesis. */
        int ret = kr_dname_lf(k->buf, clencl_name, true);
@@ -1168,7 +1170,7 @@ static int try_wild(struct key *k, struct answer *ans, const knot_dname_t *clenc
        /* Add the RR into the answer. */
        const void *eh_bound = val.data + val.len;
        ret = entry2answer(ans, AR_ANSWER, eh, eh_bound, qry->sname, type, new_ttl);
-       VERBOSE_MSG(qry, "=> NSEC wildcard: answer expanded, ret = %d, new TTL %d\n",
+       VERBOSE_MSG(qry, "=> wildcard: answer expanded, ret = %d, new TTL %d\n",
                        ret, (int)new_ttl);
        if (ret) return kr_error(ret);
        ans->rcode = PKT_NOERROR;
index e891d5cf1e565eeaa1825ccc4e1d35df3f39f02e..a5691e7302b6488c9c6379fb4e7f0fd6cdae67ce 100644 (file)
@@ -421,7 +421,14 @@ int nsec3_encloser(struct key *k, struct answer *ans,
                return kr_ok();
        }
 
-       /* ran out of options */
+       /* We've ran out of options. */
+       if (last_nxproven_labels > 0) {
+               /* We didn't manage to prove existence of the closest encloser,
+                * meaning the only chance left is a *positive* wildcard record. */
+               *clencl_labels = last_nxproven_labels - 1;
+               ans->rcode = PKT_NXDOMAIN;
+               /* FIXME: review */
+       }
        return ESKIP;
 }
 
@@ -496,15 +503,8 @@ int nsec3_src_synth(struct key *k, struct answer *ans, const knot_dname_t *clenc
        }
 
 
-       /* Find the NSEC3 in cache (or exit). */
-
-       /* Handle the two cases: covered and matched. */
-
        /* FIXME XXX */
        VERBOSE_MSG(qry, "=> NSEC3 wildcard: failed!\n");
        return kr_ok();
-
-       //assert(false);
-       return -ENOSYS;
 }