summaryrefslogtreecommitdiff
path: root/lua/doh-get.lua
blob: d95b54266247c8617f8685e7201c70249b8dffd3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
--
-- Support for DoH GET dissection in Wireshark. Wireshark already supports
-- dissection of the application/dns-message POST request and response bodies,
-- but it does not yet support the GET request parameter. This Lua plugin
-- provides a workaround for that.
-- https://tools.ietf.org/html/rfc8484#section-4.1
--

local doh_get = Proto.new("doh-get", "DNS over HTTPS (GET)")
local media_type = DissectorTable.get("media_type")
local http_path = Field.new("http.request.uri")
local http2_path = Field.new("http2.headers.path")

-- Converts "base64url" to standard "base64" encoding.
local function from_base64url(b64url)
    local lastlen = string.len(b64url) % 4
    local b64 = string.gsub(string.gsub(b64url, "-", "+"), "_", "/")
    if lastlen == 3 then
        b64 = b64 .. "="
    elseif lastlen == 2 then
        b64 = b64 .. "=="
    end
    return b64
end

function doh_get.dissector(tvb, pinfo, tree)
    local path = http2_path() or http_path()
    if not path then
        return
    end

    local dns_b64, sep = string.match(path.value, "[%?&]dns=([A-Za-z0-9_=-]+)(.?)")
    if not dns_b64 then
        return
    end
    -- Check for forbidden values in query string.
    if sep ~= "" and sep ~= "&" then
        return
    end

    -- Convert base64url to standard base64 with +/ and padding
    dns_b64 = from_base64url(dns_b64)

    local dns_tvb = ByteArray.new(dns_b64, true):base64_decode():tvb("Base64-decoded DNS")

    -- Allow HTTP GET line to be replaced with the DNS one in the Info column.
    pinfo.columns.info:clear_fence()

    -- Call media_type table instead of dns directly, this ensures that the
    -- protocol is properly displayed as "DoH".
    media_type:try("application/dns-message", dns_tvb, pinfo, tree)
end

register_postdissector(doh_get)