]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
policy.rpz: fix origin detection in files without $ORIGIN
authorVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 18 Oct 2021 11:31:58 +0000 (13:31 +0200)
committerTomas Krizek <tomas.krizek@nic.cz>
Wed, 20 Oct 2021 15:01:21 +0000 (17:01 +0200)
NEWS
modules/policy/policy.lua

diff --git a/NEWS b/NEWS
index 891675e4e949b728fbe8131ce197cb86855b6399..e6bc4a35ec57cc67c931f436a889df44c130ec3f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,11 @@
+Knot Resolver 5.4.3 (2021-mm-dd)
+================================
+
+Bugfixes
+--------
+- policy.rpz: improve logs, fix origin detection in files without $ORIGIN
+
+
 Knot Resolver 5.4.2 (2021-10-13)
 ================================
 
index 41320adf85ad177f5cc96d984b351d7446b91263..dd68102add50a8e3ddabab48fffc8ce8a31de3e7 100644 (file)
@@ -404,13 +404,18 @@ local function rpz_parse(action, path)
        local rrtype_bad = {
                [kres.type.DNAME]  = true,
                [kres.type.NS]     = false,
-               [kres.type.SOA]    = false,
                [kres.type.DNSKEY] = true,
                [kres.type.DS]     = true,
                [kres.type.RRSIG]  = true,
                [kres.type.NSEC]   = true,
                [kres.type.NSEC3]  = true,
        }
+
+       -- We generally don't know what zone should be in the file; we try to detect it.
+       -- Fortunately, it's typical that SOA is the first record, even required for AXFR.
+       local origin_soa = nil
+       local warned_soa, warned_bailiwick
+
        local parser = require('zonefile').new()
        local ok, errstr = parser:open(path)
        if not ok then
@@ -427,14 +432,19 @@ 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)
 
-               local prefix_labels = ffi.C.knot_dname_in_bailiwick(full_name, parser.zone_origin)
+               local origin = origin_soa or parser.zone_origin
+               local prefix_labels = ffi.C.knot_dname_in_bailiwick(full_name, origin)
                if prefix_labels < 0 then
-                       log_info(ffi.C.LOG_GRP_POLICY, 'RPZ %s:%d: RR owner "%s" outside the zone (ignored)',
-                               path, tonumber(parser.line_counter), kres.dname2str(full_name))
+                       if not warned_bailiwick then
+                               warned_bailiwick = true
+                               log_warn(ffi.C.LOG_GRP_POLICY,
+                                       'RPZ %s:%d: RR owner "%s" outside the zone (ignored; reported once per file)',
+                                       path, tonumber(parser.line_counter), kres.dname2str(full_name))
+                       end
                        goto continue
                end
 
-               local bytes = ffi.C.knot_dname_size(full_name) - ffi.C.knot_dname_size(parser.zone_origin)
+               local bytes = ffi.C.knot_dname_size(full_name) - ffi.C.knot_dname_size(origin)
                local name = ffi.string(full_name, bytes) .. '\0'
 
                if parser.r_type == kres.type.CNAME then
@@ -447,6 +457,21 @@ local function rpz_parse(action, path)
                else
                        if #name then
                                local is_bad = rrtype_bad[parser.r_type]
+
+                               if parser.r_type == kres.type.SOA then
+                                       if origin_soa == nil then
+                                               origin_soa = ffi.gc(ffi.C.knot_dname_copy(parser.r_owner, nil), ffi.C.free)
+                                               goto continue -- we don't want to modify `new_actions`
+                                       else
+                                               is_bad = true -- maybe provide more info, but it seems rare
+                                       end
+                               elseif origin_soa == nil and not warned_soa then
+                                       warned_soa = true
+                                       log_warn(ffi.C.LOG_GRP_POLICY,
+                                               'RPZ %s:%d warning: SOA missing as the first record',
+                                               path, tonumber(parser.line_counter))
+                               end
+
                                if is_bad == true or (is_bad == false and prefix_labels ~= 0) then
                                        log_warn(ffi.C.LOG_GRP_POLICY, 'RPZ %s:%d warning: RR type %s is not allowed in RPZ (ignored)',
                                                path, tonumber(parser.line_counter), kres.tostring.type[parser.r_type])