]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
modules/policy: Add RPZ test
authorLukáš Ježek <lukas.jezek@nic.cz>
Thu, 2 Apr 2020 12:38:13 +0000 (14:38 +0200)
committerPetr Špaček <petr.spacek@nic.cz>
Tue, 14 Apr 2020 14:55:57 +0000 (16:55 +0200)
modules/policy/meson.build
modules/policy/policy.lua
modules/policy/policy.rpz.test.lua [new file with mode: 0644]
modules/policy/policy.test.rpz [new file with mode: 0644]

index 2e16c4d1484b27b879f347cd76d1b98ff4d7d764..8a4991349f0221cb7be58326c7b223532ac2d904 100644 (file)
@@ -8,6 +8,7 @@ lua_mod_src += [
 config_tests += [
   ['policy', files('policy.test.lua')],
   ['policy.slice', files('policy.slice.test.lua')],
+  ['policy.rpz', files('policy.rpz.test.lua')],
 ]
 
 integr_tests += [
index a75d5fdf149569cb85aa4cf622e012392ac6aa23..53a0ce7b8f24062634134744d77ab0767dde3f68 100644 (file)
@@ -416,19 +416,24 @@ local function rpz_parse(action, path)
                if not ok then break end
 
                local name = ffi.string(parser.r_owner, parser.r_owner_length)
-               local name_action = ffi.string(parser.r_data, parser.r_data_length)
-               rules[name] = action_map[name_action]
-               -- Warn when NYI
-               if #name > 1 and not action_map[name_action] then
+               local rdata = ffi.string(parser.r_data, parser.r_data_length)
 
-                       if parser.r_type == kres.type.CNAME then
-                               log('[poli] RPZ %s:%d: CNAME in RPZ is not supported', path, tonumber(parser.line_counter))
-                       elseif unsupp_rrs(parser.r_type) then
-                               log('[poli] RPZ %s:%d: RR type %s is not allowed in RPZ', path, tonumber(parser.line_counter),
-                                   kres.tostring.type[parser.r_type])
+               if parser.r_type == kres.type.CNAME then
+                       if action_map[rdata] then
+                               rules[name] = action_map[rdata]
                        else
-                               if new_actions[name] == nil then new_actions[name] = {} end
-                               new_actions[name][parser.r_type] = { ttl=parser.r_ttl, rdata=name_action }
+                               log('[poli] RPZ %s:%d: CNAME in RPZ is not supported', path, tonumber(parser.line_counter))
+                       end
+               else
+                       -- Warn when NYI
+                       if #name then
+                               if unsupp_rrs(parser.r_type) then
+                                       log('[poli] RPZ %s:%d: RR type %s is not allowed in RPZ', path, tonumber(parser.line_counter),
+                                           kres.tostring.type[parser.r_type])
+                               else
+                                       if new_actions[name] == nil then new_actions[name] = {} end
+                                       new_actions[name][parser.r_type] = { ttl=parser.r_ttl, rdata=rdata }
+                               end
                        end
                end
        end
diff --git a/modules/policy/policy.rpz.test.lua b/modules/policy/policy.rpz.test.lua
new file mode 100644 (file)
index 0000000..b63d850
--- /dev/null
@@ -0,0 +1,69 @@
+
+local function prepare_cache()
+       cache.open(100*MB)
+       cache.clear()
+
+       local ffi = require('ffi')
+       local c = kres.context().cache
+
+       local passthru_addr = '\127\0\0\9'
+       rr_passthru = kres.rrset(todname('rpzpassthru.'), kres.type.A, kres.class.IN, 3600999999)
+       assert(rr_passthru:add_rdata(passthru_addr, #passthru_addr))
+       assert(c:insert(rr_passthru, nil, ffi.C.KR_RANK_SECURE + ffi.C.KR_RANK_AUTH))
+
+       c:commit()
+end
+
+local function rrset_to_texts(rr)
+       local rr_text = {}
+       for w in rr:txt_dump():gmatch("%S+") do table.insert(rr_text, w) end
+       return rr_text
+end
+
+local function check_answer(desc, qname, qtype, expected_rcode, expected_rdata)
+       qtype_str = kres.tostring.type[qtype]
+       callback = function(pkt)
+               same(pkt:rcode(), expected_rcode,
+                       desc .. ': expecting answer for query ' .. qname .. ' ' .. qtype_str
+                       .. ' with rcode ' .. kres.tostring.rcode[expected_rcode])
+
+               if expected_rdata then
+                       rr_text = rrset_to_texts(pkt:rrsets(kres.section.ANSWER)[1])
+                       ok(rr_text[4] == expected_rdata,
+                               desc ..': checking rdata of answer for ' .. qname .. ' ' .. qtype_str)
+               else
+                       -- check empty section
+                       ok(pkt:rrsets(kres.section.ANSWER)[1] == nil,
+                               desc ..': checking empty answer section for ' .. qname .. ' ' .. qtype_str)
+               end
+
+       end
+
+       resolve(qname, qtype, kres.class.IN, {}, callback)
+end
+
+local function test_rpz()
+       check_answer('"CNAME ." return NXDOMAIN',
+               'nxdomain.', kres.type.A, kres.rcode.NXDOMAIN)
+       check_answer('"CNAME *." return NXDOMAIN',
+               'nodata.', kres.type.A, kres.rcode.NXDOMAIN)
+       check_answer('"CNAME rpz-drop." be dropped',
+               'rpzdrop.', kres.type.A, kres.rcode.SERVFAIL)
+       check_answer('"CNAME rpz-passthru" return A rrset',
+               'rpzpassthru.', kres.type.A, kres.rcode.NOERROR, '127.0.0.9')
+       check_answer('"A 192.168.55.5" return local A rrset',
+               'rra.', kres.type.A, kres.rcode.NOERROR, '192.168.55.5')
+       check_answer('non existing AAAA on rra domain return NODATA',
+               'rra.', kres.type.AAAA, kres.rcode.NOERROR)
+end
+
+net.ipv4 = false
+net.ipv6 = false
+
+prepare_cache()
+
+policy.add(policy.rpz(policy.DENY, 'policy.test.rpz'))
+
+return {
+       test_rpz,
+}
diff --git a/modules/policy/policy.test.rpz b/modules/policy/policy.test.rpz
new file mode 100644 (file)
index 0000000..9ebaa17
--- /dev/null
@@ -0,0 +1,9 @@
+$TTL 30
+@        SOA nonexistent.nodomain.none. dummy.nodomain.none. 1 12h 15m 3w 2h
+         NS  nonexistant.nodomain.none.
+
+nxdomain.      CNAME   .
+nodata.                CNAME   *.
+rpzdrop.       CNAME   rpz-drop.
+rpzpassthru.   CNAME   rpz-passthru.
+rra.           A       192.168.55.5