]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib: made tests pass again, cleanup
authorMarek Vavruša <marek.vavrusa@nic.cz>
Thu, 9 Jul 2015 20:19:15 +0000 (22:19 +0200)
committerMarek Vavruša <marek.vavrusa@nic.cz>
Thu, 9 Jul 2015 20:19:15 +0000 (22:19 +0200)
lib/layer/rrsigcache.c [deleted file]
lib/layer/validate.c
lib/resolve.c
lib/rplan.h
tests/test_zonecut.c

diff --git a/lib/layer/rrsigcache.c b/lib/layer/rrsigcache.c
deleted file mode 100644 (file)
index 915d4a2..0000000
+++ /dev/null
@@ -1,393 +0,0 @@
-/*  Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <libknot/descriptor.h>
-#include <libknot/errcode.h>
-#include <libknot/rrset.h>
-#include <libknot/internal/mempool.h>
-#include <libknot/rrtype/rdname.h>
-#include <libknot/rrtype/rrsig.h>
-
-#include "lib/layer/iterate.h"
-#include "lib/cache.h"
-#include "lib/module.h"
-
-#define DEBUG_MSG(fmt...) QRDEBUG(kr_rplan_current(rplan), "rrsc",  fmt)
-#define DEBUG_MSG_NOPLAN(fmt...) QRDEBUG(NULL, "rrsc",  fmt)
-//#define DEBUG_MSG(fmt...)
-//#define DEBUG_MSG_NOPLAN(fmt...)
-
-static int begin(knot_layer_t *ctx, void *module_param)
-{
-       ctx->data = module_param;
-       return ctx->state;
-}
-
-/** @internal Baton for stash_commit */
-struct stash_baton
-{
-       struct kr_cache_txn *txn;
-       unsigned timestamp;
-};
-
-static int commit_rrsig(const char *key, void *val, void *data)
-{
-       knot_rrset_t *rrsig = val;
-       struct stash_baton *baton = data;
-       if (knot_rrset_ttl(rrsig) < 1) {
-               return kr_ok(); /* Ignore cache busters. */
-       }
-       /* Check if already cached */
-       /** @todo This should check if less trusted data is in the cache,
-                 for that the cache would need to trace data trust level.
-          */
-       unsigned drift = baton->timestamp;
-       knot_rrset_t query_rrsig;
-
-       knot_rrset_init(&query_rrsig, rrsig->owner, rrsig->type, rrsig->rclass);
-       if (kr_cache_peek_rrsig(baton->txn, &query_rrsig, &drift) == 0) {
-               return kr_ok();
-       }
-       return kr_cache_insert_rrsig(baton->txn, rrsig, rrsig->type, baton->timestamp);
-}
-
-static int stash_commit(map_t *stash, unsigned timestamp, struct kr_cache_txn *txn)
-{
-       struct stash_baton baton = {
-               .txn = txn,
-               .timestamp = timestamp
-       };
-       return map_walk(stash, &commit_rrsig, &baton);
-       return kr_ok();
-}
-
-static int validate_rrsig(const knot_rrset_t *rrsig, size_t pos, const knot_rrset_t *rr,
-                      struct kr_cache_txn *txn, struct kr_request *req)
-{
-       struct kr_rplan *rplan = &req->rplan;
-       struct kr_query *qry = kr_rplan_current(rplan);
-       uint32_t timestamp = qry->timestamp.tv_sec;
-
-       const knot_dname_t *signer = knot_rrsig_signer_name(&rrsig->rrs, pos);
-
-       knot_rrset_t dnskey_rr;
-       knot_rrset_init(&dnskey_rr, (knot_dname_t *)signer, KNOT_RRTYPE_DNSKEY, rr->rclass);
-       int ret = kr_cache_peek_rr(txn, &dnskey_rr, &timestamp);
-       if (ret != 0) {
-               return KNOT_DNSSEC_ENOKEY;
-       }
-
-       return kr_ok();
-}
-
-static int merge_in_rrsigs(knot_rrset_t *cache_rr, const knot_rrset_t *rrsigset, const knot_rrset_t *rr,
-                           struct kr_cache_txn *txn, struct kr_request *req)
-{
-       struct kr_rplan *rplan = &req->rplan;
-       struct kr_query *query = kr_rplan_current(&req->rplan);
-       int ret = KNOT_EOK;
-
-       /* Find rrset corresponding to RRSIG. */
-       for (unsigned i = 0; i < rrsigset->rrs.rr_count; ++i) {
-               if ((knot_rrsig_type_covered(&rrsigset->rrs, i) == rr->type) &&
-                   knot_dname_is_equal(cache_rr->owner, rrsigset->owner)) {
-                       ret = validate_rrsig(rrsigset, i, rr, txn, req);
-                       switch (ret) {
-                       case KNOT_DNSSEC_ENOKEY:
-#ifndef NDEBUG
-                               {
-                                       char name_str[KNOT_DNAME_MAXLEN], type_str[16];
-                                       knot_dname_to_str(name_str, knot_rrsig_signer_name(&rrsigset->rrs, i), sizeof(name_str));
-                                       knot_rrtype_to_string(rr->type, type_str, sizeof(type_str));
-                                       DEBUG_MSG_NOPLAN("%s() Missing DNSKEY for '%s %s'.\n", __func__, type_str, name_str);
-                               }
-#endif
-                               DEBUG_MSG("<= missing DNSKEY\n");
-                               const knot_dname_t *signer = knot_rrsig_signer_name(&rrsigset->rrs, i);
-                               struct kr_query *next = kr_rplan_push(rplan, query->parent,
-                                                                     signer, query->sclass, KNOT_RRTYPE_DNSKEY);
-                               if (!next) {
-                                       return KNOT_STATE_FAIL;
-                               }
-                               rem_node(&query->node); /* *MUST* keep current query at tail */
-                               insert_node(&query->node, &next->node);
-                               next->flags |= QUERY_AWAIT_CUT;
-                               return ret;
-                               break;
-                       case 0:
-                               break;
-                       default:
-                               return ret;
-                               break;
-                       }
-
-                       const knot_rdata_t *rdata = knot_rdataset_at(&rrsigset->rrs, i);
-                       ret = knot_rdataset_add(&cache_rr->rrs, rdata, rplan->pool);
-                       if (KNOT_EOK != ret) {
-                               return ret;
-                       }
-               }
-       }
-
-       return ret;
-}
-
-static int scan_for_rrsigs(knot_rrset_t *cache_rrsig, const knot_pktsection_t *section,
-                           const knot_rrset_t *rr, struct kr_request *req)
-{
-       struct kr_rplan *rplan = &req->rplan;
-       struct kr_cache *cache = &req->ctx->cache;
-
-       struct kr_cache_txn txn;
-       int ret = kr_cache_txn_begin(cache, &txn, 0);
-       if (0 != ret) {
-               return ret;
-       }
-
-       knot_rrset_init(cache_rrsig, rr->owner, rr->type, rr->rclass);
-       for (uint16_t i = 0; i < section->count; ++i) {
-               const knot_rrset_t *rrset = knot_pkt_rr(section, i);
-               if (KNOT_RRTYPE_RRSIG != rrset->type) {
-                       continue;
-               }
-               /* Currently only merge. Signature check is missing. */
-               int ret = merge_in_rrsigs(cache_rrsig, rrset, rr, &txn, req);
-               if (KNOT_EOK != ret) {
-                       knot_rrset_clear(cache_rrsig, rplan->pool);
-                       kr_cache_txn_abort(&txn);
-                       return ret;
-               }
-       }
-
-       kr_cache_txn_abort(&txn);
-       return kr_ok();
-}
-
-static int stash_add_rrsig(map_t *stash, const knot_pktsection_t *section,
-                           const knot_rrset_t *rr, struct kr_request *req)
-{
-       if (rr->type == KNOT_RRTYPE_RRSIG) {
-               return kr_ok();
-       }
-
-       struct kr_rplan *rplan = &req->rplan;
-
-       /* Stash key = {[1-255] owner, [1-5] type covered, [1] \x00 } */
-       char key[8 + KNOT_DNAME_MAXLEN];
-       int ret = knot_dname_to_wire((uint8_t *)key, rr->owner, KNOT_DNAME_MAXLEN);
-       if (ret <= 0) {
-               return ret;
-       }
-       knot_dname_to_lower((uint8_t *)key);
-       ret = snprintf(key + ret - 1, sizeof(key) - KNOT_DNAME_MAXLEN, "%hu", rr->type);
-       if (ret <= 0 || ret >= KNOT_DNAME_MAXLEN) {
-               return kr_error(EILSEQ);
-       }
-
-       /* Check if already exists */
-       knot_rrset_t *stashed = map_get(stash, key);
-       if (stashed) {
-               return kr_ok();
-       }
-
-       /* Construct RRSIG RRSet containing related data. */
-       knot_rrset_t cache_rrsig;
-       ret = scan_for_rrsigs(&cache_rrsig, section, rr, req);
-       if (ret != 0) {
-               return ret;
-       }
-
-       if (cache_rrsig.rrs.rr_count) {
-               stashed = knot_rrset_copy(&cache_rrsig, rplan->pool);
-               if (!stashed) {
-                       return kr_error(ENOMEM);
-               }
-       }
-       knot_rrset_clear(&cache_rrsig, rplan->pool);
-       if (stashed) {
-               return map_set(stash, key, stashed);
-       }
-       return kr_ok();
-}
-
-static void stash_glue(map_t *stash, knot_pkt_t *pkt, const knot_dname_t *ns_name, mm_ctx_t *pool)
-{
-       const knot_pktsection_t *additional = knot_pkt_section(pkt, KNOT_ADDITIONAL);
-       for (unsigned i = 0; i < additional->count; ++i) {
-               const knot_rrset_t *rr = knot_pkt_rr(additional, i);
-               if ((rr->type != KNOT_RRTYPE_A && rr->type != KNOT_RRTYPE_AAAA) ||
-                   !knot_dname_is_equal(rr->owner, ns_name)) {
-                       continue;
-               }
-//             stash_add_rrsig(stash, additional, rr, pool);
-       }
-}
-
-static int stash_authority(map_t *stash, knot_pkt_t *pkt, struct kr_request *req)
-{
-       struct kr_rplan *rplan = &req->rplan;
-       struct kr_query *qry = kr_rplan_current(rplan);
-       const knot_pktsection_t *authority = knot_pkt_section(pkt, KNOT_AUTHORITY);
-       for (unsigned i = 0; i < authority->count; ++i) {
-               const knot_rrset_t *rr = knot_pkt_rr(authority, i);
-               /* Cache in-bailiwick data only */
-               if (!knot_dname_in(qry->zone_cut.name, rr->owner)) {
-                       continue;
-               }
-               /* Look up glue records for NS */
-               if (rr->type == KNOT_RRTYPE_NS) {
-                       stash_glue(stash, pkt, knot_ns_name(&rr->rrs, 0), rplan->pool);
-               }
-               /* Ignore RRSIGs directly. */
-               if (rr->type == KNOT_RRTYPE_RRSIG) {
-                       continue;
-               }
-               /* Stash record */
-               int ret = stash_add_rrsig(stash, authority, rr, req);
-               if (ret == KNOT_DNSSEC_ENOKEY) {
-                       return ret;
-               }
-       }
-       return kr_ok();
-}
-
-static int stash_answer(map_t *stash, knot_pkt_t *pkt, struct kr_request *req)
-{
-       struct kr_rplan *rplan = &req->rplan;
-       struct kr_query *qry = kr_rplan_current(rplan);
-       const knot_dname_t *cname = qry->sname;
-       const knot_pktsection_t *answer = knot_pkt_section(pkt, KNOT_ANSWER);
-       for (unsigned i = 0; i < answer->count; ++i) {
-               /* Stash direct answers (equal to current QNAME/CNAME) */
-               const knot_rrset_t *rr = knot_pkt_rr(answer, i);
-               if (!knot_dname_is_equal(rr->owner, cname)) {
-                       continue;
-               }
-               /* Ignore RRSIGs directly. */
-               if (rr->type == KNOT_RRTYPE_RRSIG) {
-                       continue;
-               }
-               int ret = stash_add_rrsig(stash, answer, rr, req);
-               if (ret == KNOT_DNSSEC_ENOKEY) {
-                       return ret;
-               }
-               /* Follow CNAME chain */
-               if (rr->type == KNOT_RRTYPE_CNAME) {
-                       cname = knot_cname_name(&rr->rrs);
-               } else {
-                       cname = qry->sname;
-               }
-       }
-       return kr_ok();
-}
-
-static int scan_rrsigs(map_t *stash, knot_pkt_t *pkt, struct kr_request *req)
-{
-       int ret = stash_authority(stash, pkt, req);
-       if (ret == 0 && knot_wire_get_aa(pkt->wire)) {
-               ret = stash_answer(stash, pkt, req);
-       }
-       return ret;
-}
-
-static int stash(knot_layer_t *ctx, knot_pkt_t *pkt)
-{
-       /* Do nothing when no DNSSEC required. */
-       bool dobit = knot_pkt_has_dnssec(pkt);
-       if (!dobit) {
-               return ctx->state;
-       }
-
-       struct kr_request *req = ctx->data;
-       struct kr_rplan *rplan = &req->rplan;
-
-#ifndef NDEBUG
-       {
-               struct kr_query *qry = NULL;
-               WALK_LIST(qry, rplan->resolved) {
-                       char qname_str[KNOT_DNAME_MAXLEN], qtype_str[16];
-                       knot_dname_to_str(qname_str, qry->sname, sizeof(qname_str));
-                       knot_rrtype_to_string(qry->stype, qtype_str, sizeof(qtype_str));
-
-                       DEBUG_MSG("%s() resolved '%s %s' at %u\n", __func__, qtype_str, qname_str, qry->timestamp.tv_sec);
-               }
-       }
-#endif
-
-       struct kr_query *qry = kr_rplan_current(rplan);
-       if (!qry || ctx->state & KNOT_STATE_FAIL) {
-               return ctx->state;
-       }
-
-       /* Cache only positive answers. */
-       if (qry->flags & QUERY_CACHED || knot_wire_get_rcode(pkt->wire) != KNOT_RCODE_NOERROR) {
-               return ctx->state;
-       }
-       /* Stash RRSIG data from the AUTHORITY and ANSWER. */
-       map_t stash_rrsig = map_make();
-       stash_rrsig.malloc = (map_alloc_f) mm_alloc;
-       stash_rrsig.free = (map_free_f) mm_free;
-       stash_rrsig.baton = rplan->pool;
-       int ret = scan_rrsigs(&stash_rrsig, pkt, req);
-       /* Cache stashed records */
-       if (ret == 0) {
-               /* Open write transaction */
-               struct kr_cache *cache = &req->ctx->cache;
-               struct kr_cache_txn txn;
-               if (kr_cache_txn_begin(cache, &txn, 0) == 0) {
-                       ret = stash_commit(&stash_rrsig, qry->timestamp.tv_sec, &txn);
-                       if (ret == 0) {
-                               kr_cache_txn_commit(&txn);
-                       } else {
-                               kr_cache_txn_abort(&txn);
-                       }
-               }
-               /* Clear if full */
-               if (ret == KNOT_ESPACE) {
-                       /*
-                        * Commit empty transaction to make freed pages reclaimable
-                        * (This increases the txnid)
-                        */
-                       if (kr_cache_txn_begin(cache, &txn, 0) == 0) {
-                               kr_cache_txn_commit(&txn);
-                       }
-                       /* Now drop the database */
-                       if (kr_cache_txn_begin(cache, &txn, 0) == 0) {
-                               ret = kr_cache_clear(&txn);
-                               if (ret == 0) {
-                                       kr_cache_txn_commit(&txn);
-                               } else {
-                                       kr_cache_txn_abort(&txn);
-                               }
-                       }
-               }
-       }
-
-       return ctx->state;
-}
-
-/** Module implementation. */
-const knot_layer_api_t *rrsigcache_layer(struct kr_module *module)
-{
-       static const knot_layer_api_t _layer = {
-               .begin = &begin,
-               .consume = &stash
-       };
-
-       return &_layer;
-}
-
-KR_MODULE_EXPORT(rrsigcache)
index 58bcfdc3b3cc317049746f4cd012dc1273362edb..87c61c402f4864c720e59d4b3e56069b2cc6803e 100644 (file)
 #include "lib/nsrep.h"
 #include "lib/module.h"
 
-#define DEBUG_MSG(fmt...) QRDEBUG(kr_rplan_current(&req->rplan), "validate", fmt)
+#define DEBUG_MSG(fmt...) QRDEBUG(kr_rplan_current(&req->rplan), "vldr", fmt)
 
 /* Set resolution context and parameters. */
 static int begin(knot_layer_t *ctx, void *module_param)
 {
-#warning TODO: set root trust anchor
        ctx->data = module_param;
        return KNOT_STATE_PRODUCE;
 }
@@ -95,10 +94,17 @@ static int secure_query(knot_layer_t *ctx, knot_pkt_t *pkt)
 
 static int validate(knot_layer_t *ctx, knot_pkt_t *pkt)
 {
+       struct kr_request *req = ctx->data;
+       struct kr_query *query = kr_rplan_current(&req->rplan);
+       if (ctx->state & KNOT_STATE_FAIL) {
+               return ctx->state;
+       }
 #warning TODO: check if we have DNSKEY in qry->zone_cut and validate RRSIGS/proof, return FAIL if failed
 #warning TODO: we must also validate incoming DNSKEY records against the current zone cut TA
 #warning FLOW: first answer that comes here must have the DNSKEY that we can validate using TA
-
+       DEBUG_MSG("checking query, dnskey: %d, secured: %d\n",
+                 knot_pkt_qtype(pkt) == KNOT_RRTYPE_DNSKEY,
+                 knot_pkt_has_dnssec(pkt));
        return ctx->state;
 }
 
@@ -108,7 +114,6 @@ const knot_layer_api_t *validate_layer(struct kr_module *module)
        static const knot_layer_api_t _layer = {
                .begin = &begin,
                .consume = &validate,
-               .produce = &secure_query
        };
        return &_layer;
 }
index 2910428cbed637bd5df5d963a6b8d1b826e9eecf..6a4409cbdf28a98a60b5313e18b8bdde5326b57c 100644 (file)
@@ -424,27 +424,6 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t
        DEBUG_MSG("query '%s %s'\n", type_str, name_str);
 #endif
 
-       /* The query wasn't resolved from cache,
-        * now it's the time to look up closest zone cut from cache.
-        */
-       if (qry->flags & QUERY_AWAIT_CUT) {
-               int ret = ns_fetch_cut(qry, request, true);
-               if (ret != 0) {
-                       return KNOT_STATE_FAIL;
-               }
-
-               if (!qry->zone_cut.key) {
-                       /* Try to fetch missing DNSKEY. */
-                       /* TODO -- Fetch all missing DNSKEYS and DS records. */
-                       /* TODO -- Fetch DS at parent side of a zone cut. Fetch NS at the child side of the zone cut. */
-                       /* TODO -- Handle holes (sequences with missing delegation). */
-                       struct kr_query *next = kr_rplan_push(rplan, qry, qry->zone_cut.name, KNOT_CLASS_IN, KNOT_RRTYPE_DNSKEY);
-                       if (!next) {
-                               return kr_error(ENOMEM);
-                       }
-               }
-       }
-
        /* Resolve current query and produce dependent or finish */
        int state = knot_overlay_produce(&request->overlay, packet);
        if (state != KNOT_STATE_FAIL && knot_wire_get_qr(packet->wire)) {
@@ -469,15 +448,28 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t
         */
        if (qry->flags & QUERY_AWAIT_CUT) {
                qry->flags &= ~QUERY_AWAIT_CUT;
+               bool want_secured = knot_pkt_has_dnssec(request->answer);
+               int ret = ns_fetch_cut(qry, request, want_secured);
+               if (ret != 0) {
+                       return KNOT_STATE_FAIL;
+               }
+               /* Try to fetch missing DNSKEY. */
+               if (want_secured && !qry->zone_cut.key && qry->stype != KNOT_RRTYPE_DNSKEY) {
+                       /* TODO -- Fetch all missing DNSKEYS and DS records. */
+                       /* TODO -- Fetch DS at parent side of a zone cut. Fetch NS at the child side of the zone cut. */
+                       /* TODO -- Handle holes (sequences with missing delegation). */
+                       struct kr_query *next = kr_rplan_push(rplan, qry, qry->zone_cut.name, KNOT_CLASS_IN, KNOT_RRTYPE_DNSKEY);
+                       if (!next) {
+                               return kr_error(ENOMEM);
+                       }
+                       return KNOT_STATE_PRODUCE;
+               }
                /* Update minimized QNAME if zone cut changed */
                if (qry->zone_cut.name[0] != '\0' && !(qry->flags & QUERY_NO_MINIMIZE)) {
                        if (kr_make_query(qry, packet) != 0) {
                                return KNOT_STATE_FAIL;
                        }
                }
-       } else if (qry->flags & QUERY_AWAIT_TRUST) {
-#warning TODO: request DNSKEY in the same way as in the ns_fetch_cut()
-#warning FLOW: this will put current query on hold and resolve DNSKEY first, so we can validate
        }
 
 ns_election:
index d64f0b58f67a0b1946e5123c3529d5ad9ed022ce..546b35577835ff719ad48cb09d4f54731291074e 100644 (file)
@@ -34,7 +34,6 @@
        X(AWAIT_IPV4 , 1 << 4) /**< Query is waiting for A address. */ \
        X(AWAIT_IPV6 , 1 << 5) /**< Query is waiting for AAAA address. */ \
        X(AWAIT_CUT  , 1 << 6) /**< Query is waiting for zone cut lookup */ \
-       X(AWAIT_TRUST, 1 << 7) /**< Query is waiting for trust anchor and key */ \
        X(SAFEMODE   , 1 << 8) /**< Don't use fancy stuff (EDNS...) */ \
        X(CACHED     , 1 << 9) /**< Query response is cached. */
 
index 772de3e99d8f07ddef1c188d706c5e311783a474..939ccc83a9e65a9466126adf78036f09cc0d83d6 100644 (file)
@@ -32,7 +32,7 @@ static void test_zonecut_params(void **state)
        assert_null((void *)kr_zonecut_find(NULL, NULL));
        assert_null((void *)kr_zonecut_find(&cut, NULL));
        assert_int_not_equal(kr_zonecut_set_sbelt(NULL, NULL), 0);
-       assert_int_not_equal(kr_zonecut_find_cached(NULL, NULL, NULL, NULL, 0), 0);
+       assert_int_not_equal(kr_zonecut_find_cached(NULL, NULL, NULL, NULL, 0, 0), 0);
 }
 
 #define TEST_IP(cut, ip, expect) { \