From 7dae38f7fc5ec634461e4ea7122e3667e5c98203 Mon Sep 17 00:00:00 2001 From: Karel Slany Date: Thu, 21 Jul 2016 12:13:19 +0200 Subject: [PATCH] Served cookie queries are handled inside cookie module. --- daemon/lua/kres.lua | 1 + lib/layer/iterate.c | 9 ++++ lib/resolve.c | 79 --------------------------------- lib/rplan.c | 17 ++++--- lib/rplan.h | 1 + modules/cookies/cookiemonster.c | 17 +++++-- tests/test_rplan.c | 3 +- 7 files changed, 34 insertions(+), 93 deletions(-) diff --git a/daemon/lua/kres.lua b/daemon/lua/kres.lua index 563ee8777..ebf8754a4 100644 --- a/daemon/lua/kres.lua +++ b/daemon/lua/kres.lua @@ -203,6 +203,7 @@ struct kr_zonecut { }; struct kr_query { struct kr_query *parent; + uint16_t qdcount; knot_dname_t *sname; uint16_t type; uint16_t class; diff --git a/lib/layer/iterate.c b/lib/layer/iterate.c index f963596d0..f668638a4 100644 --- a/lib/layer/iterate.c +++ b/lib/layer/iterate.c @@ -511,6 +511,15 @@ static int begin(knot_layer_t *ctx, void *module_param) if (ctx->state & (KNOT_STATE_DONE|KNOT_STATE_FAIL)) { return ctx->state; } + /* + * Fail if no query section. DNS cookies must be handled before + * this layer. + */ + const struct kr_request *req = ctx->data; + const struct kr_query *qry = req->current_query; + if (qry->qdcount == 0) { + return KNOT_STATE_FAIL; + } return reset(ctx); } diff --git a/lib/resolve.c b/lib/resolve.c index 9d5a1da40..d974452f8 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -389,62 +389,6 @@ int kr_resolve_begin(struct kr_request *request, struct kr_context *ctx, knot_pk return KNOT_STATE_CONSUME; } -#if defined(ENABLE_COOKIES) -/** - * @brief Put cookie into answer packet. - * @param clnt_sockaddr client socket address - * @param srvr_sett settings structure of the server cookie algorithm - * @param cookies obtained cookies - * @param answer answer packet - * @return state - */ -static int cookie_answer(const void *clnt_sockaddr, - const struct kr_cookie_settings *srvr_sett, - struct knot_dns_cookies *cookies, knot_pkt_t *answer) -{ - assert(srvr_sett && cookies && answer); - - /* Initialise answer. */ - knot_wire_set_qr(answer->wire); - knot_wire_clear_aa(answer->wire); - knot_wire_set_ra(answer->wire); - knot_wire_set_rcode(answer->wire, KNOT_RCODE_NOERROR); - - struct knot_sc_private srvr_data = { - .clnt_sockaddr = clnt_sockaddr, - .secret_data = srvr_sett->current.secr->data, - .secret_len = srvr_sett->current.secr->size - }; - - struct timeval tv; - gettimeofday(&tv, NULL); - - struct kr_nonce_input nonce = { - .rand = kr_rand_uint(UINT32_MAX), - .time = tv.tv_sec - }; - - /* Add fres cookie into the answer. */ - int ret = kr_answer_write_cookie(&srvr_data, - cookies->cc, cookies->cc_len, &nonce, - kr_sc_algs[srvr_sett->current.alg_id], answer); - if (ret != kr_ok()) { - return KNOT_STATE_FAIL; - } - - /* Check server cookie only with current settings. */ - ret = knot_sc_check(KR_NONCE_LEN, cookies, &srvr_data, - kr_sc_algs[srvr_sett->current.alg_id]); - if (ret != KNOT_EOK) { - /* RFC7873 5.4 */ - kr_pkt_set_ext_rcode(answer, KNOT_RCODE_BADCOOKIE); - return KNOT_STATE_FAIL | KNOT_STATE_DONE; - } - - return KNOT_STATE_DONE; -} -#endif /* defined(ENABLE_COOKIES) */ - static int resolve_query(struct kr_request *request, const knot_pkt_t *packet) { struct kr_rplan *rplan = &request->rplan; @@ -453,30 +397,7 @@ static int resolve_query(struct kr_request *request, const knot_pkt_t *packet) uint16_t qtype = knot_pkt_qtype(packet); struct kr_query *qry = kr_rplan_push(rplan, NULL, qname, qclass, qtype); if (!qry) { -#if defined(ENABLE_COOKIES) - /* RFC7873 5.4 specifies a query for server cookie. Such query - * has QDCOUNT == 0 and contains a cookie option. - * - * The layers don't expect to handle queries with QDCOUNT != 1 - * so such queries are handled directly here. */ - struct knot_dns_cookies cookies = { 0, }; - uint8_t *cookie_opt = kr_no_question_cookie_query(packet); - if (cookie_opt && request->ctx->cookie_ctx.clnt.enabled) { - if (kr_ok() != kr_parse_cookie_opt(cookie_opt, - &cookies)) { - /* RFC7873 5.2.2 malformed cookie. */ - knot_wire_set_rcode(request->answer->wire, - KNOT_RCODE_FORMERR); - return KNOT_STATE_FAIL; - } - } - - return cookie_answer(request->qsource.addr, - &request->ctx->cookie_ctx.srvr, - &cookies, request->answer); -#else /* !defined(ENABLE_COOKIES) */ return KNOT_STATE_FAIL; -#endif /* defined(ENABLE_COOKIES) */ } /* Deferred zone cut lookup for this query. */ diff --git a/lib/rplan.c b/lib/rplan.c index f5d050e80..0479b47ed 100644 --- a/lib/rplan.c +++ b/lib/rplan.c @@ -42,20 +42,19 @@ const knot_lookup_t *kr_query_flag_names(void) static struct kr_query *query_create(knot_mm_t *pool, const knot_dname_t *name) { - if (name == NULL) { - return NULL; - } - struct kr_query *qry = mm_alloc(pool, sizeof(struct kr_query)); if (qry == NULL) { return NULL; } memset(qry, 0, sizeof(struct kr_query)); - qry->sname = knot_dname_copy(name, pool); - if (qry->sname == NULL) { - mm_free(pool, qry); - return NULL; + if (name != NULL) { + qry->sname = knot_dname_copy(name, pool); + if (qry->sname == NULL) { + mm_free(pool, qry); + return NULL; + } + qry->qdcount = 1; } knot_dname_to_lower(qry->sname); @@ -112,7 +111,7 @@ bool kr_rplan_empty(struct kr_rplan *rplan) struct kr_query *kr_rplan_push(struct kr_rplan *rplan, struct kr_query *parent, const knot_dname_t *name, uint16_t cls, uint16_t type) { - if (rplan == NULL || name == NULL) { + if (rplan == NULL) { return NULL; } diff --git a/lib/rplan.h b/lib/rplan.h index aa6fa5fe3..944261ce8 100644 --- a/lib/rplan.h +++ b/lib/rplan.h @@ -65,6 +65,7 @@ const knot_lookup_t *kr_query_flag_names(void); */ struct kr_query { struct kr_query *parent; + uint16_t qdcount; /* Can be 0 when querying server cookie. */ knot_dname_t *sname; uint16_t stype; uint16_t sclass; diff --git a/modules/cookies/cookiemonster.c b/modules/cookies/cookiemonster.c index 6a60f5d6b..e2739224a 100644 --- a/modules/cookies/cookiemonster.c +++ b/modules/cookies/cookiemonster.c @@ -397,9 +397,14 @@ int check_request(knot_layer_t *ctx, void *module_param) .time = req->current_query->timestamp.tv_sec }; + const struct kr_query *qry = req->current_query; + if (!cookies.sc) { - /* Request has no server cookie. TODO -- Silently discard? */ - if (!ignore_badcookie) { + /* Request has no server cookie. */ + if (qry->qdcount == 0) { + /* RFC7873 5.4 */ + return_state = KNOT_STATE_DONE; + } else if (!ignore_badcookie) { /* TODO -- Silently discard? */ /* Generate BADCOOKIE response. */ DEBUG_MSG(NULL, "%s\n", "request is missing server cookie"); @@ -431,8 +436,12 @@ int check_request(knot_layer_t *ctx, void *module_param) kr_sc_algs[srvr_sett->recent.alg_id]); } if (ret != KNOT_EOK) { - /* TODO -- Silently discard? */ - if (!ignore_badcookie) { + /* Invalid server cookie. */ + if (qry->qdcount == 0) { + /* RFC7873 5.4 */ + kr_pkt_set_ext_rcode(req->answer, KNOT_RCODE_BADCOOKIE); + return_state = KNOT_STATE_DONE | KNOT_STATE_FAIL; + } else if (!ignore_badcookie) { /* TODO -- Silently discard? */ /* Generate BADCOOKIE response. */ DEBUG_MSG(NULL, "%s\n", "request has invalid server cookie"); diff --git a/tests/test_rplan.c b/tests/test_rplan.c index 0374fe1b9..f628b2954 100644 --- a/tests/test_rplan.c +++ b/tests/test_rplan.c @@ -32,7 +32,8 @@ static void test_rplan_params(void **state) struct kr_rplan rplan; assert_int_equal(kr_rplan_init(&rplan, NULL, NULL), KNOT_EOK); - assert_null((void *)kr_rplan_push(&rplan, NULL, NULL, 0, 0)); + // TODO: add test for empty dname +// assert_null((void *)kr_rplan_push(&rplan, NULL, NULL, 0, 0)); assert_int_equal(kr_rplan_pop(&rplan, NULL), KNOT_EINVAL); assert_true(kr_rplan_empty(&rplan) == true); kr_rplan_deinit(&rplan); -- 2.47.3