From: Petr Špaček Date: Mon, 1 Apr 2019 17:05:57 +0000 (+0200) Subject: doh: GET support, breaks on large payloads X-Git-Tag: v4.0.0~10^2~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=042d052b44f677ff029cbddc002a9a72a8e17da7;p=thirdparty%2Fknot-resolver.git doh: GET support, breaks on large payloads This seems to be a limitation in cqueues but we have to confirm this. --- diff --git a/modules/http/http_doh.lua b/modules/http/http_doh.lua index ae1367dc5..9b0f6a35c 100644 --- a/modules/http/http_doh.lua +++ b/modules/http/http_doh.lua @@ -1,3 +1,4 @@ +local basexx = require('basexx') local ffi = require('ffi') local condition = require('cqueues.condition') @@ -35,10 +36,32 @@ end -- Trace execution of DNS queries local function serve_doh(h, stream) + local input local method = h:get(':method') - if method ~= 'POST' then - return 405, 'only HTTP post is supported' + if method == 'POST' then + input = stream:get_body_chars(65536, 10) -- FIXME: timeout + elseif method == 'GET' then + local input_b64 = string.match(h:get(':path'), '^/doh%?dns=([a-zA-Z0-9_-]+)$') + if not input_b64 then + return 400, 'base64url query not found' + end + if #input_b64 > 87380 then -- base64url encode 65535 + return 414, 'query parameter in URI too long' + end + input = basexx.from_url64(input_b64) + if not input then + return 400, 'invalid base64url' + end + else + return 405, 'only HTTP POST and GET are supported' end + + if #input < 12 then + return 400, 'input too short' + elseif #input > 65535 then + return 413, 'input too long' + end + local content_type = h:get('content-type') or 'application/dns-message' if content_type ~= 'application/dns-message' then return 415, 'only Content-Type: application/dns-message is supported' @@ -49,12 +72,6 @@ local function serve_doh(h, stream) -- return 406, 'only Accept: application/dns-message is supported' -- end - local input = stream:get_body_chars(65536, 10) -- FIXME: timeout - if #input < 12 then - return 400, 'bad request: input too short' - elseif #input > 65535 then - return 413, 'bad request: input too long' - end -- Output buffer local output = '' @@ -65,7 +82,7 @@ local function serve_doh(h, stream) local cond = condition.new() local waiting, done = false, false local finish_cb = function (answer, req) - print(tostring(answer)) + print(tostring(answer)) -- FIXME print('TTL: ', get_http_ttl(answer)) diff --git a/modules/http/http_doh.test.lua b/modules/http/http_doh.test.lua index f3691246d..148e66014 100644 --- a/modules/http/http_doh.test.lua +++ b/modules/http/http_doh.test.lua @@ -1,3 +1,4 @@ +local basexx = require('basexx') local ffi = require('ffi') function parse_pkt(input) @@ -49,10 +50,13 @@ else end local function check_err(req, exp_status, desc) - local headers = req:go(5) -- randomly chosen timeout + local headers, errmsg, errno = req:go(5) -- TODO: randomly chosen timeout + if errno then + nok(errmsg, desc .. ': ' .. errmsg) + return + end local got_status = headers:get(':status') same(got_status, exp_status, desc) - print(got_status) -- TODO end -- test whether http interface responds and binds @@ -85,6 +89,13 @@ 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('s', 65536))) + 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') @@ -115,6 +126,7 @@ else -- test_doh_post, test_post_short_input, test_post_long_input, + test_get_long_input, test_post_unparseable_input, test_post_unsupp_type }