From a9aba58ee84085cd9c439c41fc1fb0bc0937d131 Mon Sep 17 00:00:00 2001 From: Grigorii Demidov Date: Mon, 16 Jan 2017 16:22:06 +0100 Subject: [PATCH] layer/validate: additional check when validating CNAME chain --- daemon/lua/kres-gen.lua | 1 + lib/layer/validate.c | 26 ++++++++++++++++---------- lib/utils.c | 1 + lib/utils.h | 1 + 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/daemon/lua/kres-gen.lua b/daemon/lua/kres-gen.lua index d341c37e4..a77bcf400 100644 --- a/daemon/lua/kres-gen.lua +++ b/daemon/lua/kres-gen.lua @@ -65,6 +65,7 @@ typedef struct { struct ranked_rr_array_entry { uint32_t qry_uid; uint8_t rank; + uint8_t revalidation_cnt; _Bool cached; _Bool yielded; _Bool to_wire; diff --git a/lib/layer/validate.c b/lib/layer/validate.c index cfe352b3e..29a4c0395 100644 --- a/lib/layer/validate.c +++ b/lib/layer/validate.c @@ -37,6 +37,8 @@ #define VERBOSE_MSG(qry, fmt...) QRVERBOSE(qry, "vldr", fmt) +#define MAX_REVALIDATION_CNT 2 + /** * Search in section for given type. * @param sec Packet section. @@ -267,7 +269,8 @@ static void mark_insecure_parents(const struct kr_query *qry) while (parent && ((parent->flags & cut_flags) == 0)) { parent->flags &= ~QUERY_DNSSEC_WANT; parent->flags |= QUERY_DNSSEC_INSECURE; - if (parent->stype != KNOT_RRTYPE_DS) { + if (parent->stype != KNOT_RRTYPE_DS && + parent->stype != KNOT_RRTYPE_RRSIG) { break; } parent = parent->parent; @@ -406,13 +409,6 @@ static int rrsig_not_found(kr_layer_t *ctx, const knot_rrset_t *rr) struct kr_request *req = ctx->req; struct kr_query *qry = req->current_query; - if (knot_dname_is_equal(rr->owner, qry->zone_cut.name) || - ctx->state == KR_STATE_YIELD) { - /* Already yielded for revalidation. */ - VERBOSE_MSG(qry, "<= couldn't validate RRSIGs\n"); - qry->flags |= QUERY_DNSSEC_BOGUS; - return KR_STATE_FAIL; - } VERBOSE_MSG(qry, ">< no RRSIGs found\n"); struct kr_zonecut *cut = &qry->zone_cut; const knot_dname_t *cut_name_start = qry->zone_cut.name; @@ -455,7 +451,7 @@ static int check_validation_result(kr_layer_t *ctx, ranked_rr_array_t *arr) int ret = KR_STATE_DONE; struct kr_request *req = ctx->req; struct kr_query *qry = req->current_query; - const ranked_rr_array_entry_t *invalid_entry = NULL; + ranked_rr_array_entry_t *invalid_entry = NULL; for (size_t i = 0; i < arr->len; ++i) { ranked_rr_array_entry_t *entry = arr->at[i]; if (entry->yielded) { @@ -477,6 +473,13 @@ static int check_validation_result(kr_layer_t *ctx, ranked_rr_array_t *arr) return ret; } + if ((invalid_entry->rank != KR_VLDRANK_SECURE) && + (++(invalid_entry->revalidation_cnt) > MAX_REVALIDATION_CNT)) { + VERBOSE_MSG(qry, "<= continuous revalidation, fails\n"); + qry->flags |= QUERY_DNSSEC_BOGUS; + return KR_STATE_FAIL; + } + const knot_rrset_t *rr = invalid_entry->rr; if (invalid_entry->rank == KR_VLDRANK_MISMATCH) { const knot_dname_t *signer_name = knot_rrsig_signer_name(&rr->rrs, 0); @@ -657,7 +660,10 @@ static int validate(kr_layer_t *ctx, knot_pkt_t *pkt) VERBOSE_MSG(qry, "<= can't prove NODATA due to optout, going insecure\n"); qry->flags &= ~QUERY_DNSSEC_WANT; qry->flags |= QUERY_DNSSEC_INSECURE; - /* Could not return here, we must to update parent query */ + /* Could not return from here, + * we must continue and + * call update_parent_keys() to mark + * parent queries as insecured */ } else { VERBOSE_MSG(qry, "<= bad NODATA proof\n"); qry->flags |= QUERY_DNSSEC_BOGUS; diff --git a/lib/utils.c b/lib/utils.c index 2588ba159..4c196a067 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -457,6 +457,7 @@ int kr_ranked_rrarray_add(ranked_rr_array_t *array, const knot_rrset_t *rr, entry->qry_uid = qry_uid; entry->rr = copy; entry->rank = rank; + entry->revalidation_cnt = 0; entry->cached = false; entry->yielded = false; entry->to_wire = to_wire; diff --git a/lib/utils.h b/lib/utils.h index bdefbf7a2..a552e85f2 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -94,6 +94,7 @@ typedef array_t(knot_rrset_t *) rr_array_t; struct ranked_rr_array_entry { uint32_t qry_uid; uint8_t rank; + uint8_t revalidation_cnt; bool cached; bool yielded; bool to_wire; -- 2.47.3