]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
doh: make client and server address available to modules
authorPetr Špaček <petr.spacek@nic.cz>
Tue, 2 Apr 2019 17:12:46 +0000 (19:12 +0200)
committerPetr Špaček <petr.spacek@nic.cz>
Thu, 11 Apr 2019 07:12:48 +0000 (09:12 +0200)
This will allow modules like view etc. work in the same way with packets
received over HTTP.

daemon/lua/kres-gen.lua
daemon/lua/kres-gen.sh
modules/http/http_doh.lua
modules/http/http_doh.test.lua

index c369c6499eea6b51e3272f10467d558bb451d7c8..1b7571fbdaa78b1846010ae7f0b61dfd0fc0708c 100644 (file)
@@ -312,6 +312,7 @@ const char *kr_inaddr(const struct sockaddr *);
 int kr_inaddr_family(const struct sockaddr *);
 int kr_inaddr_len(const struct sockaddr *);
 int kr_inaddr_str(const struct sockaddr *, char *, size_t *);
+int kr_sockaddr_cmp(const struct sockaddr *, const struct sockaddr *);
 int kr_sockaddr_len(const struct sockaddr *);
 uint16_t kr_inaddr_port(const struct sockaddr *);
 int kr_straddr_family(const char *);
index 83d46c06959de7d0761218441e4ce520d8f39717..1365f1fe06007248f6eb828e330dd3152993c631 100755 (executable)
@@ -174,6 +174,7 @@ ${CDEFS} ${LIBKRES} functions <<-EOF
        kr_inaddr_family
        kr_inaddr_len
        kr_inaddr_str
+       kr_sockaddr_cmp
        kr_sockaddr_len
        kr_inaddr_port
        kr_straddr_family
index 8a061ee0ff1c0585c56307b3090bd7982d8e8187..4088ad07bed232bd7ee7e75cd1a1cf71e660c20d 100644 (file)
@@ -8,6 +8,13 @@ local function get_http_ttl(pkt)
        return ffi.C.packet_ttl(pkt, is_negative)
 end
 
+local function convert_sockaddr(family, ipaddr, port)
+       if not (family and ipaddr and port) then
+               panic('failed to obtain peer IP address')
+       end
+       return ffi.gc(ffi.C.kr_straddr_socket(ipaddr, port), ffi.C.free)
+end
+
 -- Trace execution of DNS queries
 local function serve_doh(h, stream)
        local input
@@ -81,8 +88,14 @@ local function serve_doh(h, stream)
        end
        print(pkt)
 
+       -- set source address so filters can work
+       local function init_cb(req)
+               req.qsource.addr = convert_sockaddr(stream:peername())
+               req.qsource.dst_addr = convert_sockaddr(stream:localname())
+       end
+
        -- resolve query
-       worker.resolve_pkt(pkt, finish_cb)
+       worker.resolve_pkt(pkt, finish_cb, init_cb)
        -- Wait for asynchronous query and free callbacks -- FIXME
        if not done then
                waiting = true
index 2b41edf547ac4917933257d937a18491252a0865..9dd3871569bb267fcc14730db6768af01e7924e4 100644 (file)
@@ -178,6 +178,47 @@ else
                check_err(req, '415', 'unsupported request content type finishes with 415')
        end
 
+       local function test_dstaddr()
+               local triggered = false
+               local exp_dstaddr = ffi.gc(ffi.C.kr_straddr_socket(host, port), ffi.C.free)
+               local function check_dstaddr(state, req)
+                       triggered = true
+                       print(exp_dstaddr)
+                       print(req.qsource.dst_addr)
+                       same(ffi.C.kr_sockaddr_cmp(req.qsource.dst_addr, exp_dstaddr), 0,
+                               'request has correct server address')
+                       return state
+               end
+               policy.add(policy.suffix(check_dstaddr, policy.todnames({'dstaddr.test'})))
+               local desc = 'valid POST query has server address available in request'
+               local req = req_templ:clone()
+               req.headers:upsert(':method', 'POST')
+               req:set_body(basexx.from_base64(  -- dstaddr.test. A
+                       'FnkBAAABAAAAAAAAB2RzdGFkZHIEdGVzdAAAAQAB'))
+               check_ok(req, desc)
+               ok(triggered, 'dstaddr policy was triggered')
+       end
+
+       local function test_srcaddr()
+               modules.load('view')
+               assert(view)
+               local policy_refuse = policy.suffix(policy.REFUSE, policy.todnames({'srcaddr.test.knot-resolver.cz'}))
+               -- these netmasks would not work if the request did not contain IP addresses
+               view:addr('0.0.0.0/0', policy_refuse)
+               view:addr('::/0', policy_refuse)
+
+               local desc = 'valid POST query has source address available in request'
+               local req = req_templ:clone()
+               req.headers:upsert(':method', 'POST')
+               req:set_body(basexx.from_base64(  -- srcaddr.test.knot-resolver.cz TXT
+                       'QNQBAAABAAAAAAAAB3NyY2FkZHIEdGVzdA1rbm90LXJlc29sdmVyAmN6AAAQAAE'))
+               headers, pkt = check_ok(req, desc)
+               same(pkt:rcode(), kres.rcode.REFUSED, desc .. ': view module caught it')
+
+               modules.unload('view')
+       end
+
+
 --     not implemented
 --     local function test_post_unsupp_accept()
 --             local req = assert(req_templ:clone())
@@ -197,7 +238,9 @@ else
                test_post_unsupp_type,
                test_doh_servfail,
                test_doh_nxdomain,
-               test_doh_noerror
+               test_doh_noerror,
+               test_dstaddr,
+               test_srcaddr
        }
 
        return tests