]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
modules/http: tests for DoH
authorIvana Krumlová <ivana.krumlova@nic.cz>
Mon, 24 Jun 2019 11:32:41 +0000 (13:32 +0200)
committerPetr Špaček <petr.spacek@nic.cz>
Tue, 25 Jun 2019 11:01:54 +0000 (11:01 +0000)
modules/http/http_doh.test.lua

index 00238b8d7bb745e050cf8bc97e2c68eb5ac05c85..480df3a1b0d6d4f16db03e0544f40770a48c7538 100644 (file)
@@ -111,7 +111,7 @@ else
 
 
        -- test a valid DNS query using POST
-       local function test_doh_servfail()
+       local function test_post_servfail()
                local desc = 'valid POST query which ends with SERVFAIL'
                local req = req_templ:clone()
                req.headers:upsert(':method', 'POST')
@@ -126,12 +126,12 @@ else
                same(pkt:rcode(), kres.rcode.SERVFAIL, desc .. ': rcode matches')
        end
 
-       local function test_doh_noerror()
+       local function test_post_noerror()
                local desc = 'valid POST query which ends with NOERROR'
                local req = req_templ:clone()
-               req.headers:upsert(':method', 'GET')
-               req.headers:upsert(':path', '/doh?dns='  -- noerror.test. A
-                       .. 'vMEBAAABAAAAAAAAB25vZXJyb3IEdGVzdAAAAQAB')
+               req.headers:upsert(':method', 'POST')
+               req:set_body(basexx.from_base64(  -- noerror.test. A
+                       'vMEBAAABAAAAAAAAB25vZXJyb3IEdGVzdAAAAQAB'))
                local headers, pkt = check_ok(req, desc)
                if not (headers and pkt) then
                        return
@@ -144,11 +144,11 @@ else
                same(pkt:arcount(), 0, desc .. ': ADDITIONAL is empty')
        end
 
-       local function test_doh_nxdomain()
+       local function test_post_nxdomain()
                local desc = 'valid POST query which ends with NXDOMAIN'
                local req = req_templ:clone()
                req.headers:upsert(':method', 'POST')
-               req:set_body(basexx.from_base64(  -- servfail.test. A
+               req:set_body(basexx.from_base64(  -- nxdomain.test. A
                        'viABAAABAAAAAAAACG54ZG9tYWluBHRlc3QAAAEAAQ=='))
                local headers, pkt = check_ok(req, desc)
                if not (headers and pkt) then
@@ -159,13 +159,21 @@ else
                same(pkt:nscount(), 1, desc .. ': AUTHORITY is present')
        end
 
-
-       local function test_unsupp_method()
-               local req = assert(req_templ:clone())
-               req.headers:upsert(':method', 'PUT')
-               check_err(req, '405', 'unsupported method finishes with 405')
+       -- RFC 8484 section 6 explicitly allows huge answers over HTTP
+       local function test_huge_answer()
+               policy.add(policy.suffix(gen_huge_answer, policy.todnames({'huge.test'})))
+               local desc = 'POST query for a huge answer'
+               local req = req_templ:clone()
+               req.headers:upsert(':method', 'POST')
+               req:set_body(basexx.from_base64(  -- huge.test. URI, no EDNS
+                       'HHwBAAABAAAAAAAABGh1Z2UEdGVzdAABAAAB'))
+               local _, pkt = check_ok(req, desc)
+               same(pkt:rcode(), kres.rcode.NOERROR, desc .. ': rcode NOERROR')
+               same(pkt:tc(), false, desc .. ': no TC bit')
+               same(pkt:ancount(), 2, desc .. ': ANSWER contains both RRs')
        end
 
+       -- test an invalid DNS query using POST
        local function test_post_short_input()
                local req = assert(req_templ:clone())
                req.headers:upsert(':method', 'POST')
@@ -180,13 +188,6 @@ else
                check_err(req, '413', 'too long POST finishes with 413')
        end
 
-       local function test_get_long_input()
-               local req = assert(req_templ:clone())
-               req.headers:upsert(':method', 'GET')
-               req.headers:upsert(':path', '/doh?dns=' .. basexx.to_url64(string.rep('\0', 1030)))
-               check_err(req, '414', 'too long GET finishes with 414')
-       end
-
        local function test_post_unparseable_input()
                local req = assert(req_templ:clone())
                req.headers:upsert(':method', 'POST')
@@ -202,6 +203,124 @@ else
                check_err(req, '415', 'unsupported request content type finishes with 415')
        end
 
+       -- test a valid DNS query using GET
+       local function test_get_servfail()
+               local desc = 'valid GET query which ends with SERVFAIL'
+               local req = req_templ:clone()
+               req.headers:upsert(':method', 'GET')
+               req.headers:upsert(':path', '/doh?dns='  -- servfail.test. A
+                       .. 'FZUBAAABAAAAAAAACHNlcnZmYWlsBHRlc3QAAAEAAQ')
+               local headers, pkt = check_ok(req, desc)
+               if not (headers and pkt) then
+                       return
+               end
+               -- uncacheable
+               same(headers:get('cache-control'), 'max-age=0', desc .. ': TTL 0')
+               same(pkt:rcode(), kres.rcode.SERVFAIL, desc .. ': rcode matches')
+       end
+
+       local function test_get_noerror()
+               local desc = 'valid GET query which ends with NOERROR'
+               local req = req_templ:clone()
+               req.headers:upsert(':method', 'GET')
+               req.headers:upsert(':path', '/doh?dns='  -- noerror.test. A
+                       .. 'vMEBAAABAAAAAAAAB25vZXJyb3IEdGVzdAAAAQAB')
+               local headers, pkt = check_ok(req, desc)
+               if not (headers and pkt) then
+                       return
+               end
+               -- HTTP TTL is minimum from all RRs in the answer
+               same(headers:get('cache-control'), 'max-age=300', desc .. ': TTL 900')
+               same(pkt:rcode(), kres.rcode.NOERROR, desc .. ': rcode matches')
+               same(pkt:ancount(), 3, desc .. ': ANSWER is present')
+               same(pkt:nscount(), 1, desc .. ': AUTHORITY is present')
+               same(pkt:arcount(), 0, desc .. ': ADDITIONAL is empty')
+       end
+
+       local function test_get_nxdomain()
+               local desc = 'valid GET query which ends with NXDOMAIN'
+               local req = req_templ:clone()
+               req.headers:upsert(':method', 'GET')
+               req.headers:upsert(':path', '/doh?dns='  -- nxdomain.test. A
+                       .. 'viABAAABAAAAAAAACG54ZG9tYWluBHRlc3QAAAEAAQ')
+               local headers, pkt = check_ok(req, desc)
+               if not (headers and pkt) then
+                       return
+               end
+               same(headers:get('cache-control'), 'max-age=10800', desc .. ': TTL 10800')
+               same(pkt:rcode(), kres.rcode.NXDOMAIN, desc .. ': rcode matches')
+               same(pkt:nscount(), 1, desc .. ': AUTHORITY is present')
+       end
+
+        local function test_get_other_params_before_dns()
+                local desc = 'GET query with other parameters before dns is valid'
+                local req = req_templ:clone()
+                req.headers:upsert(':method', 'GET')
+                req.headers:upsert(':path',
+               '/doh?other=something&another=something&dns=vMEBAAABAAAAAAAAB25vZXJyb3IEdGVzdAAAAQAB')
+                check_ok(req, desc)
+        end
+
+        local function test_get_other_params_after_dns()
+                local desc = 'GET query with other parameters after dns is valid'
+                local req = req_templ:clone()
+                req.headers:upsert(':method', 'GET')
+                req.headers:upsert(':path',
+               '/doh?dns=vMEBAAABAAAAAAAAB25vZXJyb3IEdGVzdAAAAQAB&other=something&another=something')
+                check_ok(req, desc)
+        end
+
+        local function test_get_other_params()
+                local desc = 'GET query with other parameters than dns on both sides is valid'
+                local req = req_templ:clone()
+                req.headers:upsert(':method', 'GET')
+                req.headers:upsert(':path',
+               '/doh?other=something&dns=vMEBAAABAAAAAAAAB25vZXJyb3IEdGVzdAAAAQAB&another=something')
+                check_ok(req, desc)
+        end
+
+       -- test an invalid DNS query using GET
+               local function test_get_long_input()
+               local req = assert(req_templ:clone())
+               req.headers:upsert(':method', 'GET')
+               req.headers:upsert(':path', '/doh?dns=' .. basexx.to_url64(string.rep('\0', 1030)))
+               check_err(req, '414', 'too long GET finishes with 414')
+       end
+
+       local function test_get_no_dns_param()
+               local req = assert(req_templ:clone())
+               req.headers:upsert(':method', 'GET')
+               req.headers:upsert(':path', '/doh?notdns=' .. basexx.to_url64(string.rep('\0', 1024)))
+               check_err(req, '400', 'GET without dns paramter finishes with 400')
+       end
+
+       local function test_get_unparseable()
+                local req = assert(req_templ:clone())
+                req.headers:upsert(':method', 'GET')
+                req.headers:upsert(':path', '/doh??dns=' .. basexx.to_url64(string.rep('\0', 1024)))
+                check_err(req, '400', 'unparseable GET finishes with 400')
+        end
+
+       local function test_get_invalid_b64()
+                local req = assert(req_templ:clone())
+                req.headers:upsert(':method', 'GET')
+                req.headers:upsert(':path', '/doh?dns=thisisnotb64')
+                check_err(req, '400', 'GET with invalid base64 finishes with 400')
+        end
+
+       local function test_get_invalid_chars()
+                local req = assert(req_templ:clone())
+                req.headers:upsert(':method', 'GET')
+                req.headers:upsert(':path', '/doh?dns=' .. basexx.to_url64(string.rep('\0', 200)) .. '@#$%?!')
+                check_err(req, '400', 'GET with invalid characters in b64 finishes with 400')
+        end
+
+       local function test_unsupp_method()
+               local req = assert(req_templ:clone())
+               req.headers:upsert(':method', 'PUT')
+               check_err(req, '405', 'unsupported method finishes with 405')
+       end
+
        local function test_dstaddr()
                local triggered = false
                local exp_dstaddr = ffi.gc(ffi.C.kr_straddr_socket(host, port, nil), ffi.C.free)
@@ -240,56 +359,6 @@ else
                modules.unload('view')
        end
 
-       -- RFC 8484 section 6 explicitly allows huge answers over HTTP
-       local function test_huge_answer()
-               policy.add(policy.suffix(gen_huge_answer, policy.todnames({'huge.test'})))
-               local desc = 'POST query for a huge answer'
-               local req = req_templ:clone()
-               req.headers:upsert(':method', 'POST')
-               req:set_body(basexx.from_base64(  -- huge.test. URI, no EDNS
-                       'HHwBAAABAAAAAAAABGh1Z2UEdGVzdAABAAAB'))
-               local _, pkt = check_ok(req, desc)
-               same(pkt:rcode(), kres.rcode.NOERROR, desc .. ': rcode NOERROR')
-               same(pkt:tc(), false, desc .. ': no TC bit')
-               same(pkt:ancount(), 2, desc .. ': ANSWER contains both RRs')
-       end
-
-       local function test_get_no_dns_param()
-               local req = assert(req_templ:clone())
-               req.headers:upsert(':method', 'GET')
-               req.headers:upsert(':path', '/doh?notdns=' .. basexx.to_url64(string.rep('\0', 1024)))
-               check_err(req, '400', 'GET without dns paramter finishes with 400')
-       end
-
-       local function test_unparseble_get()
-                local req = assert(req_templ:clone())
-                req.headers:upsert(':method', 'GET')
-                req.headers:upsert(':path', '/doh??dns=' .. basexx.to_url64(string.rep('\0', 1024)))
-                check_err(req, '400', 'unparseble GET finishes with 400')
-        end
-
-        local function test_get_other_params()
-                local desc = 'valid GET query with other parameters than dns finishes with 200'
-                local req = req_templ:clone()
-                req.headers:upsert(':method', 'GET')
-                req.headers:upsert(':path', '/doh?other=something&dns=vMEBAAABAAAAAAAAB25vZXJyb3IEdGVzdAAAAQAB&another=something')
-                local headers, pkt = check_ok(req, desc)
-        end
-
-       local function test_get_invalid_b64()
-                local req = assert(req_templ:clone())
-                req.headers:upsert(':method', 'GET')
-                req.headers:upsert(':path', '/doh?dns=thisisnotb64')
-                check_err(req, '400', 'GET with invalid base64 finishes with 400')
-        end
-
-       local function test_get_invalid_chars()
-                local req = assert(req_templ:clone())
-                req.headers:upsert(':method', 'GET')
-                req.headers:upsert(':path', '/doh?dns=' .. basexx.to_url64(string.rep('\0', 200)) .. '@#$%?!')
-                check_err(req, '400', 'GET with invalid characters in b64 finishes with 400')
-        end
-
 --     not implemented
 --     local function test_post_unsupp_accept()
 --             local req = assert(req_templ:clone())
@@ -302,23 +371,28 @@ else
        -- plan tests
        local tests = {
                start_server,
-               test_unsupp_method,
+               test_post_servfail,
+               test_post_noerror,
+               test_post_nxdomain,
+               test_huge_answer,
                test_post_short_input,
                test_post_long_input,
-               test_get_long_input,
                test_post_unparseable_input,
                test_post_unsupp_type,
-               test_doh_servfail,
-               test_doh_nxdomain,
-               test_doh_noerror,
-               test_dstaddr,
-               test_srcaddr,
-               test_huge_answer,
-               test_get_no_dns_param,
-               test_unparseble_get,
+               test_get_servfail,
+               test_get_noerror,
+               test_get_nxdomain,
+               test_get_other_params_before_dns,
+               test_get_other_params_after_dns,
                test_get_other_params,
+               test_get_long_input,
+               test_get_no_dns_param,
+               test_get_unparseable,
                test_get_invalid_b64,
-               test_get_invalid_chars
+               test_get_invalid_chars,
+               test_unsupp_method,
+               test_dstaddr,
+               test_srcaddr
        }
 
        return tests