From: Marek VavruĊĦa Date: Sat, 19 Sep 2015 19:26:37 +0000 (+0200) Subject: lib: turn on DO=1 per query, fixed caching of DNSSEC data X-Git-Tag: v1.0.0-beta1~53^2~59 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2a9ed2ef15945dbbf718fb0bf3466d549e3bf908;p=thirdparty%2Fknot-resolver.git lib: turn on DO=1 per query, fixed caching of DNSSEC data subrequests may be insecure (e.g. out of bailiwick insecure NS), but the final answer may be secured the commit also fixes caching in this case --- diff --git a/lib/layer/pktcache.c b/lib/layer/pktcache.c index 1b1057c1d..c4a50d079 100644 --- a/lib/layer/pktcache.c +++ b/lib/layer/pktcache.c @@ -26,9 +26,9 @@ #define DEFAULT_MAXTTL (15 * 60) #define DEFAULT_NOTTL (5) /* Short-time "no data" retention to avoid bursts */ -static inline uint8_t get_tag(struct kr_request *req) +static inline uint8_t get_tag(struct kr_query *qry) { - return (req->options & QUERY_DNSSEC_WANT) ? KR_CACHE_SEC : KR_CACHE_PKT; + return (qry->flags & QUERY_DNSSEC_WANT) ? KR_CACHE_SEC : KR_CACHE_PKT; } static uint32_t limit_ttl(uint32_t ttl) @@ -115,7 +115,7 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt) } /* Fetch either answer to original or minimized query */ - uint8_t tag = get_tag(req); + uint8_t tag = get_tag(qry); int ret = loot_cache(&txn, pkt, tag, qry); kr_cache_txn_abort(&txn); if (ret == 0) { @@ -197,7 +197,7 @@ static int stash(knot_layer_t *ctx, knot_pkt_t *pkt) }; /* Stash answer in the cache */ - int ret = kr_cache_insert(&txn, get_tag(req), qname, qtype, &header, data); + int ret = kr_cache_insert(&txn, get_tag(qry), qname, qtype, &header, data); if (ret != 0) { kr_cache_txn_abort(&txn); } else { diff --git a/lib/layer/rrcache.c b/lib/layer/rrcache.c index 2a3e6a150..f72dbf3f3 100644 --- a/lib/layer/rrcache.c +++ b/lib/layer/rrcache.c @@ -125,7 +125,7 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt) * Only one step of the chain is resolved at a time. */ struct kr_cache *cache = &req->ctx->cache; - int ret = loot_cache(cache, pkt, qry, req->options & QUERY_DNSSEC_WANT); + int ret = loot_cache(cache, pkt, qry, (qry->flags & QUERY_DNSSEC_WANT)); if (ret == 0) { DEBUG_MSG("=> satisfied from cache\n"); qry->flags |= QUERY_CACHED|QUERY_NO_MINIMIZE; @@ -141,6 +141,7 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt) struct stash_baton { struct kr_request *req; + struct kr_query *qry; struct kr_cache_txn *txn; unsigned timestamp; uint32_t min_ttl; @@ -149,7 +150,7 @@ struct stash_baton static int commit_rrsig(struct stash_baton *baton, knot_rrset_t *rr) { /* If not doing secure resolution, ignore (unvalidated) RRSIGs. */ - if (!(baton->req->options & QUERY_DNSSEC_WANT)) { + if (!(baton->qry->flags & QUERY_DNSSEC_WANT)) { return kr_ok(); } /* Commit covering RRSIG to a separate cache namespace. */ @@ -197,12 +198,13 @@ static int commit_rr(const char *key, void *val, void *data) return kr_cache_insert_rr(baton->txn, rr, baton->timestamp); } -static int stash_commit(map_t *stash, unsigned timestamp, struct kr_cache_txn *txn, struct kr_request *req) +static int stash_commit(map_t *stash, struct kr_query *qry, struct kr_cache_txn *txn, struct kr_request *req) { struct stash_baton baton = { .req = req, + .qry = qry, .txn = txn, - .timestamp = timestamp, + .timestamp = qry->timestamp.tv_sec, .min_ttl = DEFAULT_MINTTL }; return map_walk(stash, &commit_rr, &baton); @@ -339,7 +341,7 @@ static int stash(knot_layer_t *ctx, knot_pkt_t *pkt) 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, qry->timestamp.tv_sec, &txn, req); + ret = stash_commit(&stash, qry, &txn, req); if (ret == 0) { kr_cache_txn_commit(&txn); } else { diff --git a/lib/resolve.c b/lib/resolve.c index 94084ce17..c77b40cec 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -154,10 +154,6 @@ static int edns_put(knot_pkt_t *pkt) static int edns_create(knot_pkt_t *pkt, knot_pkt_t *template, struct kr_request *req) { pkt->opt_rr = knot_rrset_copy(req->ctx->opt_rr, &pkt->mm); - /* Set DO bit if set (DNSSEC requested). */ - if (knot_pkt_has_dnssec(template) || (req->options & QUERY_DNSSEC_WANT)) { - knot_edns_set_do(pkt->opt_rr); - } return knot_pkt_reserve(pkt, knot_edns_wire_size(pkt->opt_rr)); } @@ -175,6 +171,10 @@ static int answer_prepare(knot_pkt_t *answer, knot_pkt_t *query, struct kr_reque if (ret != 0){ return ret; } + /* Set DO bit if set (DNSSEC requested). */ + if (knot_pkt_has_dnssec(query)) { + knot_edns_set_do(answer->opt_rr); + } } return kr_ok(); } @@ -197,10 +197,9 @@ static int answer_finalize(struct kr_request *request, int state) return kr_ok(); } -static int query_finalize(struct kr_request *request, knot_pkt_t *pkt) +static int query_finalize(struct kr_request *request, struct kr_query *qry, knot_pkt_t *pkt) { /* Randomize query case (if not in safemode) */ - struct kr_query *qry = kr_rplan_current(&request->rplan); qry->secret = (qry->flags & QUERY_SAFEMODE) ? 0 : kr_rand_uint(UINT32_MAX); knot_dname_t *qname_raw = (knot_dname_t *)knot_pkt_qname(pkt); randomized_qname_case(qname_raw, qry->secret); @@ -209,7 +208,10 @@ static int query_finalize(struct kr_request *request, knot_pkt_t *pkt) knot_pkt_begin(pkt, KNOT_ADDITIONAL); if (!(qry->flags & QUERY_SAFEMODE)) { ret = edns_create(pkt, request->answer, request); - if (ret == 0) { + if (ret == 0) { /* Enable DNSSEC for query. */ + if (qry->flags & QUERY_DNSSEC_WANT) { + knot_edns_set_do(pkt->opt_rr); + } ret = edns_put(pkt); } } @@ -229,9 +231,12 @@ int kr_resolve_begin(struct kr_request *request, struct kr_context *ctx, knot_pk return KNOT_STATE_CONSUME; } -int kr_resolve_query(struct kr_request *request, const knot_dname_t *qname, uint16_t qclass, uint16_t qtype) +static int resolve_query(struct kr_request *request, const knot_pkt_t *packet) { struct kr_rplan *rplan = &request->rplan; + const knot_dname_t *qname = knot_pkt_qname(packet); + uint16_t qclass = knot_pkt_qclass(packet); + uint16_t qtype = knot_pkt_qtype(packet); struct kr_query *qry = kr_rplan_push(rplan, NULL, qname, qclass, qtype); if (!qry) { return KNOT_STATE_FAIL; @@ -239,6 +244,9 @@ int kr_resolve_query(struct kr_request *request, const knot_dname_t *qname, uint /* Deferred zone cut lookup for this query. */ qry->flags |= QUERY_AWAIT_CUT; + if (knot_pkt_has_dnssec(packet)) { + qry->flags |= QUERY_DNSSEC_WANT; + } /* Initialize answer packet */ knot_pkt_t *answer = request->answer; @@ -266,11 +274,7 @@ int kr_resolve_consume(struct kr_request *request, knot_pkt_t *packet) if (answer_prepare(request->answer, packet, request) != 0) { return KNOT_STATE_FAIL; } - /* Start query resolution */ - const knot_dname_t *qname = knot_pkt_qname(packet); - uint16_t qclass = knot_pkt_qclass(packet); - uint16_t qtype = knot_pkt_qtype(packet); - return kr_resolve_query(request, qname, qclass, qtype); + return resolve_query(request, packet); } /* Different processing for network error */ @@ -336,6 +340,9 @@ static int zone_cut_subreq(struct kr_rplan *rplan, struct kr_query *parent, return kr_error(ENOMEM); } next->flags |= QUERY_NO_MINIMIZE; + if (parent->flags & QUERY_DNSSEC_WANT) { + next->flags |= QUERY_DNSSEC_WANT; + } return kr_ok(); } @@ -472,7 +479,7 @@ ns_election: } /* Prepare additional query */ - int ret = query_finalize(request, packet); + int ret = query_finalize(request, qry, packet); if (ret != 0) { return KNOT_STATE_FAIL; } diff --git a/lib/resolve.h b/lib/resolve.h index a6afb2ba6..c373819b7 100644 --- a/lib/resolve.h +++ b/lib/resolve.h @@ -42,8 +42,10 @@ * .alloc = (mm_alloc_t) mp_alloc * } * }; - * kr_resolve_begin(&req, ctx, answer); - * int state = kr_resolve_query(&req, qname, qclass, qtype); + * + * // Setup and provide input query + * int state = kr_resolve_begin(&req, ctx, final_answer); + * state = kr_resolve_consume(&req, query); * * // Generate answer * while (state == KNOT_STATE_PRODUCE) { @@ -126,16 +128,6 @@ struct kr_request { */ int kr_resolve_begin(struct kr_request *request, struct kr_context *ctx, knot_pkt_t *answer); -/** - * Push new query for resolution to the state. - * @param request request state (if already has a question, this will be resolved first) - * @param qname - * @param qclass - * @param qtype - * @return PRODUCE|FAIL - */ -int kr_resolve_query(struct kr_request *request, const knot_dname_t *qname, uint16_t qclass, uint16_t qtype); - /** * Consume input packet (may be either first query or answer to query originated from kr_resolve_produce()) * diff --git a/modules/stats/stats.c b/modules/stats/stats.c index 3b449a9ed..7941bb5f0 100644 --- a/modules/stats/stats.c +++ b/modules/stats/stats.c @@ -162,7 +162,7 @@ static int collect(knot_layer_t *ctx) /* Query parameters and transport mode */ if (knot_pkt_has_edns(param->answer)) { stat_const_add(data, metric_query_edns, 1); - if (param->options & QUERY_DNSSEC_WANT) { + if (knot_pkt_has_dnssec(param->answer)) { stat_const_add(data, metric_query_dnssec, 1); } }