From 3846cc78b474d8ecce51b4a276ddd5be9ec14606 Mon Sep 17 00:00:00 2001 From: Grigorii Demidov <grigorii.demidov@nic.cz> Date: Wed, 10 Aug 2016 10:24:27 +0200 Subject: [PATCH] lib/resolve: empty final answer when SERVFAIL --- lib/resolve.c | 51 +++++++++++++++++++++++++++++++++++---------------- lib/utils.c | 16 ++++++++++++++++ lib/utils.h | 4 ++++ 3 files changed, 55 insertions(+), 16 deletions(-) diff --git a/lib/resolve.c b/lib/resolve.c index 56ee37b58..55ca92ce6 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -337,43 +337,62 @@ static void write_extra_records(rr_array_t *arr, knot_pkt_t *answer) } } +static int answer_fail(knot_pkt_t *answer) +{ + int ret = kr_pkt_clear_payload(answer); + knot_wire_clear_ad(answer->wire); + knot_wire_clear_aa(answer->wire); + knot_wire_set_rcode(answer->wire, KNOT_RCODE_SERVFAIL); + if (ret == 0 && answer->opt_rr) { + /* OPT in SERVFAIL response is still useful for cookies/additional info. */ + knot_pkt_begin(answer, KNOT_ADDITIONAL); + ret = edns_put(answer); + } + return ret; +} + static int answer_finalize(struct kr_request *request, int state) { - /* Write authority records. */ + struct kr_rplan *rplan = &request->rplan; knot_pkt_t *answer = request->answer; - if (answer->current < KNOT_AUTHORITY) + + /* Always set SERVFAIL for bogus answers. */ + if (state == KNOT_STATE_FAIL && rplan->pending.len > 0) { + struct kr_query *last = array_tail(rplan->pending); + if ((last->flags & QUERY_DNSSEC_WANT) && (last->flags & QUERY_DNSSEC_BOGUS)) { + return answer_fail(answer); + } + } + + /* Write authority records. */ + if (answer->current < KNOT_AUTHORITY) { knot_pkt_begin(answer, KNOT_AUTHORITY); + } write_extra_records(&request->authority, answer); /* Write additional records. */ knot_pkt_begin(answer, KNOT_ADDITIONAL); write_extra_records(&request->additional, answer); /* Write EDNS information */ + int ret = 0; if (answer->opt_rr) { - int ret = edns_put(answer); - if (ret != 0) { - return ret; - } - } - struct kr_rplan *rplan = &request->rplan; - /* Always set SERVFAIL for bogus answers. */ - if (state == KNOT_STATE_FAIL && rplan->pending.len > 0) { - struct kr_query *last = array_tail(rplan->pending); - if ((last->flags & QUERY_DNSSEC_WANT) && (last->flags & QUERY_DNSSEC_BOGUS)) { - knot_wire_set_rcode(answer->wire,KNOT_RCODE_SERVFAIL); - } + knot_pkt_begin(answer, KNOT_ADDITIONAL); + ret = edns_put(answer); } + /* Set AD=1 if succeeded and requested secured answer. */ const bool has_ad = knot_wire_get_ad(answer->wire); knot_wire_clear_ad(answer->wire); if (state == KNOT_STATE_DONE && rplan->resolved.len > 0) { struct kr_query *last = array_tail(rplan->resolved); /* Do not set AD for RRSIG query, as we can't validate it. */ - const bool secure = (last->flags & QUERY_DNSSEC_WANT) && !(last->flags & QUERY_DNSSEC_INSECURE); + const bool secure = (last->flags & QUERY_DNSSEC_WANT) && + !(last->flags & QUERY_DNSSEC_INSECURE); if (has_ad && secure && knot_pkt_qtype(answer) != KNOT_RRTYPE_RRSIG) { knot_wire_set_ad(answer->wire); } } - return kr_ok(); + + return ret; } static int query_finalize(struct kr_request *request, struct kr_query *qry, knot_pkt_t *pkt) diff --git a/lib/utils.c b/lib/utils.c index 216b5f1d4..d8cc96c8a 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -208,6 +208,22 @@ int kr_pkt_recycle(knot_pkt_t *pkt) return knot_pkt_parse_question(pkt); } +int kr_pkt_clear_payload(knot_pkt_t *pkt) +{ + pkt->rrset_count = 0; + pkt->size = KNOT_WIRE_HEADER_SIZE + pkt->qname_size + + 2 * sizeof(uint16_t); /* QTYPE + QCLASS */ + pkt->parsed = KNOT_WIRE_HEADER_SIZE; + pkt->current = KNOT_ANSWER; + knot_wire_set_ancount(pkt->wire, 0); + knot_wire_set_nscount(pkt->wire, 0); + knot_wire_set_arcount(pkt->wire, 0); + memset(&pkt->sections[KNOT_ANSWER], 0, sizeof(knot_pktsection_t) * + (KNOT_PKT_SECTIONS - (KNOT_ANSWER + 1))); + knot_pkt_begin(pkt, KNOT_ANSWER); + return knot_pkt_parse_question(pkt); +} + int kr_pkt_put(knot_pkt_t *pkt, const knot_dname_t *name, uint32_t ttl, uint16_t rclass, uint16_t rtype, const uint8_t *rdata, uint16_t rdlen) { diff --git a/lib/utils.h b/lib/utils.h index dfcc55f6f..b7ef1f251 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -103,6 +103,10 @@ int kr_memreserve(void *baton, char **mem, size_t elm_size, size_t want, size_t KR_EXPORT int kr_pkt_recycle(knot_pkt_t *pkt); +/** @internal Clear packet payload. */ +KR_EXPORT +int kr_pkt_clear_payload(knot_pkt_t *pkt); + /** Construct and put record to packet. */ KR_EXPORT int kr_pkt_put(knot_pkt_t *pkt, const knot_dname_t *name, uint32_t ttl, -- GitLab