From: Wouter Wijngaards Date: Tue, 31 Jul 2018 07:16:25 +0000 (+0000) Subject: - Error if EDNS Keepalive received over UDP. X-Git-Tag: release-1.8.0rc1~79 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6da37e5ecdbaee3252155d84b5cb58472c21a3e8;p=thirdparty%2Funbound.git - Error if EDNS Keepalive received over UDP. implement and add test. git-svn-id: file:///svn/unbound/trunk@4803 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/daemon/worker.c b/daemon/worker.c index 8568ac3cf..7aa6ebe42 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -1246,29 +1246,52 @@ worker_handle_request(struct comm_point* c, void* arg, int error, server_stats_insrcode(&worker->stats, c->buffer); goto send_reply; } - if(edns.edns_present && edns.edns_version != 0) { - edns.ext_rcode = (uint8_t)(EDNS_RCODE_BADVERS>>4); - edns.edns_version = EDNS_ADVERTISED_VERSION; - edns.udp_size = EDNS_ADVERTISED_SIZE; - edns.bits &= EDNS_DO; - edns.opt_list = NULL; - verbose(VERB_ALGO, "query with bad edns version."); - log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); - error_encode(c->buffer, EDNS_RCODE_BADVERS&0xf, &qinfo, - *(uint16_t*)(void *)sldns_buffer_begin(c->buffer), - sldns_buffer_read_u16_at(c->buffer, 2), NULL); - if(sldns_buffer_capacity(c->buffer) >= - sldns_buffer_limit(c->buffer)+calc_edns_field_size(&edns)) - attach_edns_record(c->buffer, &edns); - regional_free_all(worker->scratchpad); - goto send_reply; - } - if(edns.edns_present && edns.udp_size < NORMAL_UDP_SIZE && - worker->daemon->cfg->harden_short_bufsize) { - verbose(VERB_QUERY, "worker request: EDNS bufsize %d ignored", - (int)edns.udp_size); - log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); - edns.udp_size = NORMAL_UDP_SIZE; + if(edns.edns_present) { + struct edns_option* edns_opt; + if(edns.edns_version != 0) { + edns.ext_rcode = (uint8_t)(EDNS_RCODE_BADVERS>>4); + edns.edns_version = EDNS_ADVERTISED_VERSION; + edns.udp_size = EDNS_ADVERTISED_SIZE; + edns.bits &= EDNS_DO; + edns.opt_list = NULL; + verbose(VERB_ALGO, "query with bad edns version."); + log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); + error_encode(c->buffer, EDNS_RCODE_BADVERS&0xf, &qinfo, + *(uint16_t*)(void *)sldns_buffer_begin(c->buffer), + sldns_buffer_read_u16_at(c->buffer, 2), NULL); + if(sldns_buffer_capacity(c->buffer) >= + sldns_buffer_limit(c->buffer)+calc_edns_field_size(&edns)) + attach_edns_record(c->buffer, &edns); + regional_free_all(worker->scratchpad); + goto send_reply; + } + if(edns.udp_size < NORMAL_UDP_SIZE && + worker->daemon->cfg->harden_short_bufsize) { + verbose(VERB_QUERY, "worker request: EDNS bufsize %d ignored", + (int)edns.udp_size); + log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); + edns.udp_size = NORMAL_UDP_SIZE; + } + edns_opt = edns_opt_list_find(edns.opt_list, LDNS_EDNS_KEEPALIVE); + if(edns_opt && c->type != comm_udp) { + if(edns_opt->opt_len > 0) { + edns.ext_rcode = 0; + edns.edns_version = EDNS_ADVERTISED_VERSION; + edns.udp_size = EDNS_ADVERTISED_SIZE; + edns.bits &= EDNS_DO; + edns.opt_list = NULL; + verbose(VERB_ALGO, "query with bad edns keepalive."); + log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); + error_encode(c->buffer, LDNS_RCODE_FORMERR, &qinfo, + *(uint16_t*)(void *)sldns_buffer_begin(c->buffer), + sldns_buffer_read_u16_at(c->buffer, 2), NULL); + if(sldns_buffer_capacity(c->buffer) >= + sldns_buffer_limit(c->buffer)+calc_edns_field_size(&edns)) + attach_edns_record(c->buffer, &edns); + regional_free_all(worker->scratchpad); + goto send_reply; + } + } } if(edns.udp_size > worker->daemon->cfg->max_udp_size && c->type == comm_udp) { diff --git a/testdata/edns_keepalive.rpl b/testdata/edns_keepalive.rpl new file mode 100644 index 000000000..a59f10ce1 --- /dev/null +++ b/testdata/edns_keepalive.rpl @@ -0,0 +1,85 @@ +server: + verbosity: 3 +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN TCP Keepalive + +RANGE_BEGIN 0 100 + + ADDRESS 193.0.14.129 + + ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR NOERROR + SECTION QUESTION + . IN NS + SECTION ANSWER + . IN NS K.ROOT-SERVERS.NET. + SECTION ADDITIONAL + K.ROOT-SERVERS.NET. IN A 193.0.14.129 + ENTRY_END + +RANGE_END + +;; ---------------------------------------- + +STEP 1 QUERY + + ENTRY_BEGIN + MATCH TCP ednsdata + REPLY RD + SECTION QUESTION + www.example.com. IN A + SECTION ADDITIONAL + HEX_EDNSDATA_BEGIN + 00 0b ; Opcode 11 + 00 02 ; Length 2 + 00 ff ; Timeout + HEX_EDNSDATA_END + ENTRY_END + +STEP 10 CHECK_ANSWER + + ENTRY_BEGIN + MATCH TCP ednsdata + REPLY RD FORMERR + SECTION QUESTION + www.example.com. IN A + SECTION ADDITIONAL + HEX_EDNSDATA_BEGIN + ; Empty + HEX_EDNSDATA_END + ENTRY_END + +STEP 20 QUERY + + ENTRY_BEGIN + MATCH TCP ednsdata + REPLY RD + SECTION QUESTION + . IN NS + SECTION ADDITIONAL + HEX_EDNSDATA_BEGIN + 00 0b ; Opcode 11 + 00 00 ; Length 0 + HEX_EDNSDATA_END + ENTRY_END + +STEP 30 CHECK_ANSWER + + ENTRY_BEGIN + MATCH TCP ednsdata + REPLY QR RD RA NOERROR + SECTION QUESTION + . IN NS + SECTION ANSWER + . IN NS K.ROOT-SERVERS.NET. + SECTION ADDITIONAL + K.ROOT-SERVERS.NET. IN A 193.0.14.129 + ENTRY_END + +SCENARIO_END