diff --git a/src/knot/modules/cookies/cookies.c b/src/knot/modules/cookies/cookies.c index fbc9c9eb22ffbf404beca9b8bfe8f2f6c6975ff1..c85528d6fe2e2f0704ff6039d23f546c0871b263 100644 --- a/src/knot/modules/cookies/cookies.c +++ b/src/knot/modules/cookies/cookies.c @@ -149,11 +149,6 @@ static knotd_state_t cookies_process(knotd_state_t state, knot_pkt_t *pkt, cookies_ctx_t *ctx = knotd_mod_ctx(mod); - // DNS cookies are ignored in the case of the TCP connection. - if (!(qdata->params->flags & KNOTD_QUERY_FLAG_LIMIT_SIZE)) { - return state; - } - // Check if the cookie option is present. uint8_t *cookie_opt = knot_pkt_edns_option(qdata->query, KNOT_EDNS_OPTION_COOKIE); @@ -192,7 +187,18 @@ static knotd_state_t cookies_process(knotd_state_t state, knot_pkt_t *pkt, // Compare server cookie. ret = knot_edns_cookie_server_check(&sc, &cc, ¶ms); if (ret != KNOT_EOK) { - if (ATOMIC_GET(ctx->badcookie_ctr) > BADCOOKIE_CTR_INIT) { + // TCP server should take the authentication provided by the use + // of TCP into account and SHOULD process the request and provide + // a normal response. + if (!(qdata->params->flags & KNOTD_QUERY_FLAG_LIMIT_SIZE)) { + if (knot_edns_cookie_server_generate(&sc, &cc, ¶ms) != KNOT_EOK || + put_cookie(qdata, pkt, &cc, &sc) != KNOT_EOK) + { + return KNOTD_STATE_FAIL; + } + + return state; + } else if (ATOMIC_GET(ctx->badcookie_ctr) > BADCOOKIE_CTR_INIT) { // Silently drop the response. update_ctr(ctx); knotd_mod_stats_incr(mod, qdata->params->thread_id, 1, 0, 1); @@ -202,13 +208,9 @@ static knotd_state_t cookies_process(knotd_state_t state, knot_pkt_t *pkt, update_ctr(ctx); } - ret = knot_edns_cookie_server_generate(&sc, &cc, ¶ms); - if (ret != KNOT_EOK) { - return KNOTD_STATE_FAIL; - } - - ret = put_cookie(qdata, pkt, &cc, &sc); - if (ret != KNOT_EOK) { + if (knot_edns_cookie_server_generate(&sc, &cc, ¶ms) != KNOT_EOK || + put_cookie(qdata, pkt, &cc, &sc) != KNOT_EOK) + { return KNOTD_STATE_FAIL; } diff --git a/tests-extra/tests/modules/cookies/test.py b/tests-extra/tests/modules/cookies/test.py index fa23b6c40120fabc56647c3225cebfcd50125ee8..3be0096879e796a71042c78156c05ffd5163f0e7 100644 --- a/tests-extra/tests/modules/cookies/test.py +++ b/tests-extra/tests/modules/cookies/test.py @@ -40,6 +40,16 @@ def check_rcode(server, query, rcode, msg): compare(response.rcode(), rcode, msg) return response +def check_rcode_tcp(server, query, rcode, msg): + try: + response = dns.query.tcp(query, server.addr, port=server.port, timeout=1) + except dns.exception.Timeout: + response = None + if response is None: + return None + compare(response.rcode(), rcode, msg) + return response + t = Test(stress=False) ModCookies.check() @@ -61,6 +71,11 @@ check_rcode(knot, query, rcodeNoerror, "NO EDNS") query = dns.message.make_query("dns1.example.com", "A", use_edns=True) check_rcode(knot, query, rcodeNoerror, "NO COOKIE OPT") +# Try a query without a server cookie over TCP +cookieOpt = dns.edns.option_from_wire(cookieOpcode, clientCookie, 0, clientCookieLen) +query = dns.message.make_query("dns1.example.com", "A", use_edns=True, options=[cookieOpt]) +response = check_rcode_tcp(knot, query, rcodeNoerror, "ONLY CLIENT COOKIE [TCP]") + # Try a query without a server cookie cookieOpt = dns.edns.option_from_wire(cookieOpcode, clientCookie, 0, clientCookieLen) query = dns.message.make_query("dns1.example.com", "A", use_edns=True, options=[cookieOpt])