]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib/resolve: fetching missing first DNSKEY
authorKarel Slany <karel.slany@nic.cz>
Thu, 9 Jul 2015 08:18:47 +0000 (10:18 +0200)
committerKarel Slany <karel.slany@nic.cz>
Thu, 9 Jul 2015 08:18:47 +0000 (10:18 +0200)
lib/layer/validate.c
lib/resolve.c
lib/zonecut.c
lib/zonecut.h

index a045d92252e8ee0e3078fb30cd30b66a8040969a..58bcfdc3b3cc317049746f4cd012dc1273362edb 100644 (file)
@@ -46,6 +46,39 @@ static int secure_query(knot_layer_t *ctx, knot_pkt_t *pkt)
                return ctx->state;
        }
 
+       if (query->zone_cut.key == NULL) {
+/*
+               query->flags |= QUERY_AWAIT_TRUST;
+
+               DEBUG_MSG("%s() A002 '%s'\n", __func__, knot_pkt_qname(pkt));
+
+               struct knot_rrset *opt_rr = knot_rrset_copy(req->answer->opt_rr, &pkt->mm);
+               if (opt_rr == NULL) {
+                       return KNOT_STATE_FAIL;
+               }
+               knot_pkt_clear(pkt);
+               int ret = knot_pkt_put_question(pkt, query->zone_cut.name, query->sclass, KNOT_RRTYPE_DNSKEY);
+               if (ret != KNOT_EOK) {
+                       knot_rrset_free(&opt_rr, &pkt->mm);
+                       return KNOT_STATE_FAIL;
+               }
+               knot_pkt_begin(pkt, KNOT_ADDITIONAL);
+               knot_pkt_put(pkt, KNOT_COMPR_HINT_NONE, opt_rr, KNOT_PF_FREE);
+
+               {
+               char name_str[KNOT_DNAME_MAXLEN], type_str[16];
+               knot_dname_to_str(name_str, knot_pkt_qname(pkt), sizeof(name_str));
+               knot_rrtype_to_string(knot_pkt_qtype(pkt), type_str, sizeof(type_str));
+               DEBUG_MSG("%s() A003 '%s %s'\n", __func__, name_str, type_str);
+               }
+
+               return KNOT_STATE_CONSUME;
+*/
+       }
+
+       DEBUG_MSG("%s() A004\n", __func__);
+
+#if 0
        /* Copy query EDNS options and request DNSKEY for current cut. */
        pkt->opt_rr = knot_rrset_copy(req->answer->opt_rr, &pkt->mm);
        query->flags |= QUERY_AWAIT_TRUST;
@@ -56,6 +89,8 @@ static int secure_query(knot_layer_t *ctx, knot_pkt_t *pkt)
        knot_pkt_put(pkt, KNOT_COMPR_HINT_NONE, pkt->opt_rr, KNOT_PF_FREE);
 
        return KNOT_STATE_CONSUME;
+#endif
+       return ctx->state;
 }
 
 static int validate(knot_layer_t *ctx, knot_pkt_t *pkt)
@@ -63,6 +98,8 @@ static int validate(knot_layer_t *ctx, knot_pkt_t *pkt)
 #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
+
+       return ctx->state;
 }
 
 /** Module implementation. */
index 512f43113826a8922682c245d99e6533e96578b9..2910428cbed637bd5df5d963a6b8d1b826e9eecf 100644 (file)
@@ -49,7 +49,7 @@ static int invalidate_ns(struct kr_rplan *rplan, struct kr_query *qry)
        }
 }
 
-static int ns_fetch_cut(struct kr_query *qry, struct kr_request *req)
+static int ns_fetch_cut(struct kr_query *qry, struct kr_request *req, bool secured)
 {
        struct kr_cache_txn txn;
        int ret = 0;
@@ -63,7 +63,7 @@ static int ns_fetch_cut(struct kr_query *qry, struct kr_request *req)
        if (kr_cache_txn_begin(&req->ctx->cache, &txn, NAMEDB_RDONLY) != 0) {
                ret = kr_zonecut_set_sbelt(req->ctx, &qry->zone_cut);
        } else {
-               ret = kr_zonecut_find_cached(req->ctx, &qry->zone_cut, qry->sname, &txn, qry->timestamp.tv_sec);
+               ret = kr_zonecut_find_cached(req->ctx, &qry->zone_cut, qry->sname, &txn, qry->timestamp.tv_sec, secured);
                kr_cache_txn_abort(&txn);
        }
        return ret;
@@ -424,6 +424,27 @@ 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)) {
@@ -447,10 +468,6 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t
         * 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);
-               if (ret != 0) {
-                       return KNOT_STATE_FAIL;
-               }
                qry->flags &= ~QUERY_AWAIT_CUT;
                /* Update minimized QNAME if zone cut changed */
                if (qry->zone_cut.name[0] != '\0' && !(qry->flags & QUERY_NO_MINIMIZE)) {
@@ -497,7 +514,8 @@ ns_election:
        struct sockaddr *addr = &qry->ns.addr.ip;
        inet_ntop(addr->sa_family, kr_nsrep_inaddr(qry->ns.addr), ns_str, sizeof(ns_str));
        knot_dname_to_str(zonecut_str, qry->zone_cut.name, sizeof(zonecut_str));
-       DEBUG_MSG("=> querying: '%s' score: %u zone cut: '%s' m12n: '%s'\n", ns_str, qry->ns.score, zonecut_str, qname_str);
+       knot_rrtype_to_string(knot_pkt_qtype(packet), type_str, sizeof(type_str));
+       DEBUG_MSG("=> querying: '%s' score: %u zone cut: '%s' m12n: '%s' type: '%s'\n", ns_str, qry->ns.score, zonecut_str, qname_str, type_str);
 #endif
 
        /* Prepare additional query */
index 7dfc5f6b7ecfce07c69457bbdec248e4c055bb62..4c7b070a73667acc118d0b7666ac20ba7cfed702 100644 (file)
@@ -321,8 +321,36 @@ static int fetch_ns(struct kr_context *ctx, struct kr_zonecut *cut, const knot_d
        return kr_ok();
 }
 
+/** Fetch DNSKEY for zone cut. */
+static int fetch_dnskey(struct kr_context *ctx, struct kr_zonecut *cut, const knot_dname_t *name, struct kr_cache_txn *txn, uint32_t timestamp)
+{
+       uint32_t drift = timestamp;
+       knot_rrset_t cached_rr;
+
+       knot_rrset_free(&cut->key, cut->pool);
+
+       knot_rrset_init(&cached_rr, (knot_dname_t *)name, KNOT_RRTYPE_DNSKEY, KNOT_CLASS_IN);
+       int ret = kr_cache_peek_rr(txn, &cached_rr, &drift);
+       if (ret != 0) {
+               return ret;
+       }
+
+       cut->key = knot_rrset_new(name, KNOT_RRTYPE_DNSKEY, KNOT_CLASS_IN, cut->pool);
+       if (cut->key == NULL) {
+               return kr_error(ENOMEM);
+       }
+
+       ret = kr_cache_materialize(cut->key, &cached_rr, timestamp, cut->pool);
+       if (ret != 0) {
+               knot_rrset_free(&cut->key, cut->pool);
+               return ret;
+       }
+
+       return kr_ok();
+}
+
 int kr_zonecut_find_cached(struct kr_context *ctx, struct kr_zonecut *cut, const knot_dname_t *name,
-                           struct kr_cache_txn *txn, uint32_t timestamp)
+                           struct kr_cache_txn *txn, uint32_t timestamp, bool secured)
 {
        if (!ctx || !cut || !name) {
                return kr_error(EINVAL);
@@ -330,7 +358,8 @@ int kr_zonecut_find_cached(struct kr_context *ctx, struct kr_zonecut *cut, const
 
        /* Start at QNAME parent. */
        while (txn) {
-               if (fetch_ns(ctx, cut, name, txn, timestamp) == 0) {
+               bool has_key = !secured || fetch_dnskey(ctx, cut, name, txn, timestamp) == 0;
+               if (has_key && fetch_ns(ctx, cut, name, txn, timestamp) == 0) {
                        update_cut_name(cut, name);
                        return kr_ok();
                }
index 72e564a2d3f9543295b60a02f310f800f98b0d58..1cd101655bc0d99f65a89afb213d0fa658267b5e 100644 (file)
@@ -115,7 +115,8 @@ int kr_zonecut_set_sbelt(struct kr_context *ctx, struct kr_zonecut *cut);
  * @param name      QNAME to start finding zone cut for
  * @param txn       cache transaction (read)
  * @param timestamp transaction timestamp
+ * @param secured   search nearest containing a DNSKEY
  * @return 0 or error code
  */
 int kr_zonecut_find_cached(struct kr_context *ctx, struct kr_zonecut *cut, const knot_dname_t *name,
-                           struct kr_cache_txn *txn, uint32_t timestamp);
+                           struct kr_cache_txn *txn, uint32_t timestamp, bool secured);