]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
policy.rpz: fix $ORIGIN-related handling
authorVladimír Čunát <vladimir.cunat@nic.cz>
Tue, 30 Jun 2020 12:37:12 +0000 (14:37 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Tue, 30 Jun 2020 14:19:36 +0000 (16:19 +0200)
- use parser-detected $ORIGIN instead of looking at SOA owner
- skip records outside $ORIGIN (and warn) instead of nesting them
- simplify a bit, and tweak warnings

modules/policy/policy.lua
modules/policy/policy.test.rpz

index 8a4e9407956e525882ffa8b378bd054fc971e953..1bb528d53e29196de52186a82f49303fcd4c6299 100644 (file)
@@ -378,7 +378,6 @@ end
 local function rpz_parse(action, path)
        local rules = {}
        local new_actions = {}
-       local origin = '\0'
        local action_map = {
                -- RPZ Policy Actions
                ['\0'] = action,
@@ -388,11 +387,11 @@ local function rpz_parse(action, path)
                ['\012rpz-tcp-only\0'] = policy.TC,
                -- Policy triggers @NYI@
        }
-       -- RR types to be skipped; boolean denoting whether to throw a warning.
+       -- RR types to be skipped; boolean denoting whether to throw a warning even for RPZ apex.
        local rrtype_bad = {
                [kres.type.DNAME]  = true,
-               [kres.type.NS]     = false, -- it's mandatory; could be improved to warn based on owner
-               [kres.type.SOA]    = false, -- it's mandatory; could be improved to warn based on owner
+               [kres.type.NS]     = false,
+               [kres.type.SOA]    = false,
                [kres.type.DNSKEY] = true,
                [kres.type.DS]     = true,
                [kres.type.RRSIG]  = true,
@@ -415,42 +414,34 @@ local function rpz_parse(action, path)
                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
-                       origin = ffi.gc(ffi.C.knot_dname_copy(full_name, nil), ffi.C.free)
+               local prefix_labels = ffi.C.knot_dname_in_bailiwick(full_name, parser.zone_origin)
+               if prefix_labels < 0 then
+                       log('[poli] RPZ %s:%d: RR owner "%s" outside the zone (ignored)',
+                               path, tonumber(parser.line_counter), kres.dname2str(full_name))
                        goto continue
                end
 
-               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
+               local bytes = ffi.C.knot_dname_size(full_name) - ffi.C.knot_dname_size(parser.zone_origin)
+               local name = ffi.string(full_name, bytes) .. '\0'
 
                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 with custom target in RPZ is not supported', path, tonumber(parser.line_counter))
+                               log('[poli] RPZ %s:%d: CNAME with custom target in RPZ is not supported yet (ignored)',
+                                       path, tonumber(parser.line_counter))
                        end
                else
-                       -- Warn when NYI
                        if #name then
                                local is_bad = rrtype_bad[parser.r_type]
-                               if is_bad == true 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 is_bad == true or (is_bad == false and prefix_labels ~= 0) then
+                                       log('[poli] RPZ %s:%d warning: RR type %s is not allowed in RPZ (ignored)',
+                                               path, tonumber(parser.line_counter), kres.tostring.type[parser.r_type])
                                elseif is_bad == nil then
                                        if new_actions[name] == nil then new_actions[name] = {} end
                                        new_actions[name][parser.r_type] = { ttl=parser.r_ttl, rdata=rdata }
                                else
-                                       assert(is_bad == false)
+                                       assert(is_bad == false and prefix_labels == 0)
                                end
                        end
                end
index 16c5c39a543e0a0064497851480fc787eb130795..8c07efc2e1fb182f5f9c8e6aab3509c2a46b9137 100644 (file)
@@ -1,13 +1,15 @@
+$ORIGIN testdomain.
 $TTL 30
 testdomain.            SOA nonexistent.testdomain. testdomain. 1 12h 15m 3w 2h
                        NS  nonexistent.testdomain.
 
-nxdomain.              CNAME   .
-nodata.                        CNAME   *.
-*.nxdomain.            CNAME   *.
-rpzdrop.               CNAME   rpz-drop.
-rpzpassthru.           CNAME   rpz-passthru.
-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
+nxdomain               CNAME   .
+nodata                 CNAME   *.
+*.nxdomain             CNAME   *.
+rpzdrop                        CNAME   rpz-drop.
+rpzpassthru            CNAME   rpz-passthru.
+rra                            A       192.168.5.5
+rra-zonename-suffix                    A       192.168.6.6
+testdomain.rra.testdomain.     A       192.168.7.7
+CaSe.SeNSiTiVe         A       192.168.8.8
+