From 21f74de38dc4bf1c8acc8f45404eebb84303ed40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Je=C5=BEek?= <lukas.jezek@nic.cz> Date: Tue, 14 Apr 2020 10:33:38 +0200 Subject: [PATCH] modules/policy: use origin and domain name as binary data --- modules/policy/README.rst | 2 +- modules/policy/policy.lua | 27 +++++++++++++++++++-------- modules/policy/policy.rpz.test.lua | 18 +++++++++++++----- modules/policy/policy.test.rpz | 9 ++++++--- tests/integration/deckard | 2 +- 5 files changed, 40 insertions(+), 18 deletions(-) diff --git a/modules/policy/README.rst b/modules/policy/README.rst index 031f0afe2..7d5f86903 100644 --- a/modules/policy/README.rst +++ b/modules/policy/README.rst @@ -152,7 +152,7 @@ Following actions stop the policy matching on the query, i.e. other rules are no .. code-block:: lua - -- this policy change IPv4 adress and TTL for `exmaple.com` + -- this policy changes IPv4 adress and TTL for `exmaple.com` policy.add(policy.suffix(policy.ANSWER({ [kres.type.A] = { ttl=300, rdata='\192\0\2\7' } }), { todname('example.com') })) More complex non-chain actions are described in their own chapters, namely: diff --git a/modules/policy/policy.lua b/modules/policy/policy.lua index 3448ce3dc..b9b90f5e8 100644 --- a/modules/policy/policy.lua +++ b/modules/policy/policy.lua @@ -378,7 +378,7 @@ end local function rpz_parse(action, path) local rules = {} local new_actions = {} - local origin = '.' + local origin = '\0' local action_map = { -- RPZ Policy Actions ['\0'] = action, @@ -416,22 +416,33 @@ local function rpz_parse(action, path) end if not ok then break end - local name = ffi.string(parser.r_owner, parser.r_owner_length) + local full_name = ffi.gc(ffi.C.knot_dname_copy(parser.r_owner, nil), ffi.C.free) local rdata = ffi.string(parser.r_data, parser.r_data_length) + ffi.C.knot_dname_to_lower(full_name) if (parser.r_type == kres.type.SOA) then - -- parser return \0 if SOA use @ as owner - origin = (name == '\0') and origin or name + origin = ffi.gc(ffi.C.knot_dname_copy(full_name, nil), ffi.C.free) goto continue end - name = (name == origin) and name or name:gsub('%'..origin, '') + local prefix_labels = ffi.C.knot_dname_in_bailiwick(full_name, origin) + local name + if prefix_labels > 0 then + local bytes = 0 + for _=1,prefix_labels do + bytes = bytes + 1 + full_name[bytes] + end + name = ffi.string(full_name, bytes) + name = name..'\0' + else + name = ffi.string(full_name, parser.r_owner_length) + end if parser.r_type == kres.type.CNAME then if action_map[rdata] then rules[name] = action_map[rdata] else - log('[poli] RPZ %s:%d: CNAME in RPZ is not supported', path, tonumber(parser.line_counter)) + log('[poli] RPZ %s:%d: CNAME with custom target in RPZ is not supported', path, tonumber(parser.line_counter)) end else -- Warn when NYI @@ -449,8 +460,8 @@ local function rpz_parse(action, path) ::continue:: end collectgarbage() - for k, v in pairs(new_actions) do - rules[k] = policy.ANSWER(v, true) + for qname, rrsets in pairs(new_actions) do + rules[qname] = policy.ANSWER(rrsets, true) end return rules end diff --git a/modules/policy/policy.rpz.test.lua b/modules/policy/policy.rpz.test.lua index 4f219ca20..846b642b0 100644 --- a/modules/policy/policy.rpz.test.lua +++ b/modules/policy/policy.rpz.test.lua @@ -45,18 +45,26 @@ end local function test_rpz() check_answer('"CNAME ." return NXDOMAIN', 'nxdomain.', kres.type.A, kres.rcode.NXDOMAIN) - check_answer('"CNAME *." return NXDOMAIN', + check_answer('"CNAME *." return NODATA', 'nodata.', kres.type.A, kres.rcode.NOERROR) + check_answer('"CNAME *. on wildcard" return NODATA', + 'nodata.nxdomain.', kres.type.A, kres.rcode.NOERROR) 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('"A 192.168.66.6" with suffixed zone name in owner return local A rrset', - 'rra-zonename-suffix.', kres.type.A, kres.rcode.NOERROR, '192.168.66.6') + check_answer('"A 192.168.5.5" return local A rrset', + 'rra.', kres.type.A, kres.rcode.NOERROR, '192.168.5.5') + check_answer('"A 192.168.6.6" with suffixed zone name in owner return local A rrset', + 'rra-zonename-suffix.', kres.type.A, kres.rcode.NOERROR, '192.168.6.6') + check_answer('"A 192.168.7.7" with suffixed zone name in owner return local A rrset', + 'testdomain.rra.', kres.type.A, kres.rcode.NOERROR, '192.168.7.7') check_answer('non existing AAAA on rra domain return NODATA', 'rra.', kres.type.AAAA, kres.rcode.NOERROR) + check_answer('"A 192.168.8.8" and domain with uppercase and lowercase letters', + 'case.sensitive.', kres.type.A, kres.rcode.NOERROR, '192.168.8.8') + check_answer('"A 192.168.8.8" and domain with uppercase and lowercase letters', + 'CASe.SENSItivE.', kres.type.A, kres.rcode.NOERROR, '192.168.8.8') end net.ipv4 = false diff --git a/modules/policy/policy.test.rpz b/modules/policy/policy.test.rpz index dd8fe3979..16c5c39a5 100644 --- a/modules/policy/policy.test.rpz +++ b/modules/policy/policy.test.rpz @@ -1,10 +1,13 @@ $TTL 30 testdomain. SOA nonexistent.testdomain. testdomain. 1 12h 15m 3w 2h - NS nonexistant.testdomain. + NS nonexistent.testdomain. nxdomain. CNAME . nodata. CNAME *. +*.nxdomain. CNAME *. rpzdrop. CNAME rpz-drop. rpzpassthru. CNAME rpz-passthru. -rra. A 192.168.55.5 -rra-zonename-suffix.testdomain. A 192.168.66.6 +rra. A 192.168.5.5 +rra-zonename-suffix.testdomain. A 192.168.6.6 +testdomain.rra.testdomain. A 192.168.7.7 +CaSe.SeNSiTiVe. A 192.168.8.8 diff --git a/tests/integration/deckard b/tests/integration/deckard index a90e8deac..84d16f4bf 160000 --- a/tests/integration/deckard +++ b/tests/integration/deckard @@ -1 +1 @@ -Subproject commit a90e8deacafc3a66b6109e62986fb2a72ea57c49 +Subproject commit 84d16f4bf169e1365e6e2bc68efd44592a7e37a1 -- GitLab