]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Error if EDNS Keepalive received over UDP.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 31 Jul 2018 07:16:25 +0000 (07:16 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 31 Jul 2018 07:16:25 +0000 (07:16 +0000)
  implement and add test.

git-svn-id: file:///svn/unbound/trunk@4803 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/worker.c
testdata/edns_keepalive.rpl [new file with mode: 0644]

index 8568ac3cf77627444150c1c1208a087dbce4a408..7aa6ebe4271c3fd96c5502a1ed65094aac1d8221 100644 (file)
@@ -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 (file)
index 0000000..a59f10c
--- /dev/null
@@ -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