-- 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')
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
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
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')
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')
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)
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())
-- 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