]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib/cache;lib/dnssec;lib/layer: some issues were fixed
authorGrigorii Demidov <grigorii.demidov@nic.cz>
Wed, 24 Feb 2016 10:19:05 +0000 (11:19 +0100)
committerGrigorii Demidov <grigorii.demidov@nic.cz>
Wed, 24 Feb 2016 10:19:05 +0000 (11:19 +0100)
lib/cache.c
lib/dnssec/nsec3.c
lib/dnssec/nsec3.h
lib/layer/validate.c

index 6d0d25aaa48cfb6847574e51ccb66d65fe5c51d0..45de6e0794fe3fbbe5c22ba657c4926f040dde39 100644 (file)
 /** @internal Removes all records from cache. */
 static int cache_purge(struct kr_cache_txn *txn)
 {
-       int ret;
-       if (!txn_is_valid(txn)) {
-               return kr_error(EINVAL);
+       int ret = kr_error(EINVAL);
+       if (txn_is_valid(txn)) {
+               txn->owner->stats.delete += 1;
+               ret = txn_api(txn)->clear(&txn->t);
        }
-
-       txn->owner->stats.delete += 1;
-       ret = txn_api(txn)->clear(&txn->t);
        return ret;
 }
 
 /** @internal  Check cache internal data version. Clear if it doesn't match.
  * returns :   EEXIST - cache data version matched.
- *              0 - cache recreated, txn has to be committed.
- *             otherwise - cache recreation fails.
+ *             0 - cache recreated, txn has to be committed.
+ *             Otherwise - cache recreation fails.
  */
 static int assert_right_version_txn(struct kr_cache_txn *txn)
 {
@@ -67,7 +65,7 @@ static int assert_right_version_txn(struct kr_cache_txn *txn)
                ret = kr_error(EEXIST);
        } else {
                /*
-                * Version doesn't not match.
+                * Version doesn't match.
                 * Recreate cache and write version key.
                 */
                ret = txn_api(txn)->count(&txn->t);
index a46716246abd434807a131b5316f6bbe69d52e96..71a8949f9c39050e156e99ba01a37c180972c3e0 100644 (file)
@@ -222,62 +222,44 @@ static int covers_name(int *flags, const knot_rrset_t *nsec3, const knot_dname_t
        uint8_t *next_hash = NULL;
        knot_nsec3_next_hashed(&nsec3->rrs, 0, &next_hash, &next_size);
 
-       if ((owner_hash.size != next_size) || (name_hash.size != next_size)) {
-               /*
-                * All hash lengths must be same.
-                * NSEC3 rr span doesn't cover name which has to be checked.
-                * Exit with no-error return code,
-                * FLG_NAME_COVERED will not be set.
-                */
-               goto fail;
-       }
-
-       const uint8_t *ownrd = owner_hash.data;
-       const uint8_t *nextd = next_hash;
-       if (memcmp(ownrd, nextd, next_size) < 0) {
-               /*
-                * 0 (...) owner ... next (...) MAX
-                *                ^
-                *                name
-                * ==>
-                * (owner < name) && (name < next)
-                */
-               if ((memcmp(ownrd, name_hash.data, next_size) >= 0) ||
-                   (memcmp(name_hash.data, nextd, next_size) >= 0)) {
+       if ((owner_hash.size == next_size) && (name_hash.size == next_size)) {
+               /* All hash lengths must be same. */
+               const uint8_t *ownrd = owner_hash.data;
+               const uint8_t *nextd = next_hash;
+               int covered = 0;
+               int greater_then_owner = (memcmp(ownrd, name_hash.data, next_size) < 0);
+               int less_then_next = (memcmp(name_hash.data, nextd, next_size) < 0);
+               if (memcmp(ownrd, nextd, next_size) < 0) {
                        /*
-                        * NSEC3 rr span doesn't cover name has to be checked.
-                        * Exit with no-error return code,
-                        * FLG_NAME_COVERED will not be set.
+                        * 0 (...) owner ... next (...) MAX
+                        *                ^
+                        *                name
+                        * ==>
+                        * (owner < name) && (name < next)
                         */
-                       goto fail;
-               }
-       } else {
-               /*
-                * owner ... MAX, 0 ... next
-                *        ^     ^    ^
-                *        name  name name
-                * =>
-                * (owner < name) || (name < next)
-                */
-               if ((memcmp(ownrd, name_hash.data, next_size) >= 0) &&
-                   (memcmp(name_hash.data, nextd, next_size) >= 0)) {
+                       covered = ((greater_then_owner) && (less_then_next));
+               } else {
                        /*
-                        * NSEC3 rr span doesn't cover name has to be checked.
-                        * Exit with no-error return code,
-                        * FLG_NAME_COVERED will not be set.
+                        * owner ... MAX, 0 ... next
+                        *        ^     ^    ^
+                        *        name  name name
+                        * =>
+                        * (owner < name) || (name < next)
                         */
-                       goto fail;
+                       covered = ((greater_then_owner) || (less_then_next));
                }
-       }
 
-       *flags |= FLG_NAME_COVERED;
+               if (covered) {
+                       *flags |= FLG_NAME_COVERED;
 
-       uint8_t nsec3_flags = knot_nsec3_flags(&nsec3->rrs, 0);
-       if (nsec3_flags & ~OPT_OUT_BIT) {
-               /* RFC5155 3.1.2 */
-               ret = kr_error(EINVAL);
-       } else {
-               ret = kr_ok();
+                       uint8_t nsec3_flags = knot_nsec3_flags(&nsec3->rrs, 0);
+                       if (nsec3_flags & ~OPT_OUT_BIT) {
+                               /* RFC5155 3.1.2 */
+                               ret = kr_error(EINVAL);
+                       } else {
+                               ret = kr_ok();
+                       }
+               }
        }
 
 fail:
@@ -344,19 +326,12 @@ static int matches_name(int *flags, const knot_rrset_t *nsec3, const knot_dname_
                goto fail;
        }
 
-       if ((owner_hash.size != name_hash.size) ||
-           (memcmp(owner_hash.data, name_hash.data, owner_hash.size) != 0)) {
-               /*
-                * NSEC3 owner does not match name has to be checked.
-                * Exit with no-error return code,
-                * FLG_NAME_MATCHED will not be set.
-                */
-               goto fail;
+       if ((owner_hash.size == name_hash.size) &&
+           (memcmp(owner_hash.data, name_hash.data, owner_hash.size) == 0)) {
+               *flags |= FLG_NAME_MATCHED;
+               ret = kr_ok();
        }
 
-       *flags |= FLG_NAME_MATCHED;
-       ret = kr_ok();
-
 fail:
        if (params.salt.data) {
                dnssec_nsec3_params_free(&params);
@@ -639,7 +614,10 @@ static int matches_closest_encloser_wildcard(const knot_pkt_t *pkt, knot_section
                /* TODO -- The loop resembles no_data_response_no_ds() exept
                 * the following condition.
                 */
-               if ((flags & FLG_NAME_MATCHED) && (flags & FLG_TYPE_BIT_MISSING)) {
+               if ((flags & FLG_NAME_MATCHED) &&
+                   (flags & FLG_TYPE_BIT_MISSING) &&
+                   (flags & FLG_CNAME_BIT_MISSING)) {
+                       /* rfc5155 8.7 */
                        return kr_ok();
                }
        }
@@ -680,45 +658,16 @@ int kr_nsec3_wildcard_answer_response_check(const knot_pkt_t *pkt, knot_section_
 }
 
 
-int kr_nsec3_no_data_ds(const knot_pkt_t *pkt, knot_section_t section_id,
-                     const knot_dname_t *sname)
-{
-       /* DS record may be also matched by an existing NSEC3 RR. */
-       int ret = no_data_response_no_ds(pkt, section_id, sname, KNOT_RRTYPE_DS);
-       if (ret == 0) {
-               /* Satisfies RFC5155 8.6, first paragraph. */
-               return ret;
-       }
-
-       /* Find closest provable encloser. */
-       const knot_dname_t *encloser_name = NULL;
-       const knot_rrset_t *covering_next_nsec3 = NULL;
-       ret = closest_encloser_proof(pkt, section_id, sname, &encloser_name,
-                                     NULL, &covering_next_nsec3);
-       if (ret != 0) {
-               return ret;
-       }
-
-       assert(encloser_name && covering_next_nsec3);
-       if (!has_optout(covering_next_nsec3)) {
-               /* Don't satisfies RFC5155 8.6, second paragraph. */
-               ret = kr_error(DNSSEC_NOT_FOUND);
-       }
-
-       return ret;
-}
-
-
-int kr_nsec3_no_data_no_ds(const knot_pkt_t *pkt, knot_section_t section_id,
+int kr_nsec3_no_data(const knot_pkt_t *pkt, knot_section_t section_id,
                      const knot_dname_t *sname, uint16_t stype)
 {
+       /* DS record may be also matched by an existing NSEC3 RR. */
        int ret = no_data_response_no_ds(pkt, section_id, sname, stype);
        if (ret == 0) {
-               /* Satisfies RFC5155 8.5, first paragraph. */
+               /* Satisfies RFC5155 8.5 and 8.6, both first paragraph. */
                return ret;
        }
 
-       /* Check RFC5155 8.7.   */
        /* Find closest provable encloser. */
        const knot_dname_t *encloser_name = NULL;
        const knot_rrset_t *covering_next_nsec3 = NULL;
@@ -736,15 +685,16 @@ int kr_nsec3_no_data_no_ds(const knot_pkt_t *pkt, knot_section_t section_id,
                return ret;
        }
 
-       if (has_optout(covering_next_nsec3)) {
+       if (!has_optout(covering_next_nsec3)) {
+               /* Bogus */
+               ret = kr_error(ENOENT);
+       } else {
                /* 
-                * Satisfies RFC5155 ERRATA 3441 8.5 
-                * (No Data Responses, QTYPE is not DS)
-                * - empty nonterminal derived from unsecure delegation.
-                * Moreover, ENT may be wilcard.
-                * Hence it covers "wilcard nodata response" case.
-                * It is not an error, but
-                * denial of existance can not be proven.
+                * Satisfies RFC5155 8.6 (QTYPE == DS), 2nd paragraph.
+                * Also satisfies ERRATA 3441 8.5 (QTYPE != DS), 3rd paragraph.
+                * - (wildcard) empty nonterminal
+                * derived from unsecure delegation.
+                * Denial of existance can not be proven.
                 * Set error code to proceed unsecure.
                 */
                ret = kr_error(DNSSEC_NOT_FOUND);
index 73cc35561a84204bf31bfe8711872a7442809a1e..97f36d2a3fe47c2bf33c9cb0903ad8d65c7db735 100644 (file)
@@ -47,18 +47,9 @@ int kr_nsec3_wildcard_answer_response_check(const knot_pkt_t *pkt, knot_section_
  * @param section_id Packet section to be processed.
  * @param sname      Queried domain name.
  * @param stype      Queried type.
- * @return           0 or error code.
- * @retval           DNSSEC_NOT_FOUND denial of existence can't be proven due to opt-out.
+ * @return           0 or error code:
+ *                  DNSSEC_NOT_FOUND - denial of existence can't be proven
+ *                  due to opt-out, otherwise - bogus.
  */
-int kr_nsec3_no_data_no_ds(const knot_pkt_t *pkt, knot_section_t section_id,
+int kr_nsec3_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 RFC5155 8.6
- * @note No RRSIGs are validated.
- * @param pkt        Packet structure to be processed.
- * @param section_id Packet section to be processed.
- * @param sname      Queried domain name.
- * @return           0 or error code.
- */
-int kr_nsec3_no_data_ds(const knot_pkt_t *pkt, knot_section_t section_id,
-                     const knot_dname_t *sname);
index fb8e0ff3f423a48e45776e68910ae5ab000596f1..40ab2950cd33d8848eb97bdb6b99a7e3f6fe5c60 100644 (file)
@@ -295,7 +295,11 @@ static int update_delegation(struct kr_request *req, struct kr_query *qry, knot_
                if (!has_nsec3) {
                        ret = kr_nsec_existence_denial(answer, KNOT_AUTHORITY, proved_name, KNOT_RRTYPE_DS);
                } else {
-                       ret = kr_nsec3_no_data_ds(answer, KNOT_AUTHORITY, proved_name);
+                       ret = kr_nsec3_no_data(answer, KNOT_AUTHORITY, proved_name, KNOT_RRTYPE_DS);
+                       if (ret == kr_error(DNSSEC_NOT_FOUND)) {
+                               /* Not bogus, but going insecure */
+                               ret = 0;
+                       }
                }
                if (ret != 0) {
                        DEBUG_MSG(qry, "<= bogus proof of DS non-existence\n");
@@ -422,7 +426,7 @@ static int validate(knot_layer_t *ctx, knot_pkt_t *pkt)
                        if (!has_nsec3) {
                                ret = kr_nsec_existence_denial(pkt, KNOT_AUTHORITY, knot_pkt_qname(pkt), knot_pkt_qtype(pkt));
                        } else {
-                               ret = kr_nsec3_no_data_no_ds(pkt, KNOT_AUTHORITY, knot_pkt_qname(pkt), knot_pkt_qtype(pkt));
+                               ret = kr_nsec3_no_data(pkt, KNOT_AUTHORITY, knot_pkt_qname(pkt), knot_pkt_qtype(pkt));
                        }
                        if (ret != 0) {
                                if (has_nsec3 && (ret == kr_error(DNSSEC_NOT_FOUND))) {