From: Dmitry Petrov Date: Tue, 4 Mar 2025 18:12:21 +0000 (-0500) Subject: Rework IP processing/checking in settings X-Git-Tag: 3.11.1~5^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6a4f0caad741aa7125255e40dc86cdc2cc33f145;p=thirdparty%2Frspamd.git Rework IP processing/checking in settings * Avoid misleading "cannot parse ip" logging by checking for "map:" prefix early * Do not use tables for maps or IPs without mask * Normalize IPs by applying mask during processing * Add error logging for wrong IP mask * Simplify check_ip_settings() based on changes in process_ip_condition() --- diff --git a/src/plugins/lua/settings.lua b/src/plugins/lua/settings.lua index 69d31d3017..2c9d5b2f98 100644 --- a/src/plugins/lua/settings.lua +++ b/src/plugins/lua/settings.lua @@ -248,17 +248,13 @@ local function check_string_setting(expected, str) end local function check_ip_setting(expected, ip) - if not expected[2] then - if lua_maps.rspamd_maybe_check_map(expected[1], ip:to_string()) then + if type(expected) == "string" then + if lua_maps.rspamd_maybe_check_map(expected, ip:to_string()) then return true end else - if expected[2] ~= 0 then - local nip = ip:apply_mask(expected[2]) - if nip and nip:to_string() == expected[1] then - return true - end - elseif ip:to_string() == expected[1] then + local nip = ip:apply_mask(expected[2]) + if nip and nip:to_string() == expected[1] then return true end end @@ -465,43 +461,48 @@ end -- Process IP address: converted to a table {ip, mask} local function process_ip_condition(ip) - local out = {} - if type(ip) == "table" then + local out = {} for _, v in ipairs(ip) do + -- should we check/abort on nil here? table.insert(out, process_ip_condition(v)) end - elseif type(ip) == "string" then - local slash = string.find(ip, '/') - - if not slash then - -- Just a plain IP address - local res = rspamd_ip.from_string(ip) + return out + end - if res:is_valid() then - out[1] = res:to_string() - out[2] = 0 - else - -- It can still be a map - out[1] = ip - end - else - local res = rspamd_ip.from_string(string.sub(ip, 1, slash - 1)) - local mask = tonumber(string.sub(ip, slash + 1)) + if type(ip) == "string" then + if string.sub(ip, 1, 4) == "map:" then + -- It is a map, don't apply any extra logic + return ip + end - if res:is_valid() then - out[1] = res:to_string() - out[2] = mask - else - rspamd_logger.errx(rspamd_config, "bad IP address: " .. ip) + local mask + local slash = string.find(ip, '/') + if slash then + mask = string.sub(ip, slash + 1) + ip = string.sub(ip, 1, slash - 1) + end + + local res = rspamd_ip.from_string(ip) + if res:is_valid() then + if mask then + local mask_num = tonumber(mask) + if mask_num then + -- normalize IP + res = res:apply_mask(mask_num) + if res then + return { res:to_string(), mask_num } + end + end + rspamd_logger.errx(rspamd_config, "bad IP mask: " .. mask) return nil end + return ip end - else - return nil end - return out + rspamd_logger.errx(rspamd_config, "bad IP address: " .. ip) + return nil end -- Process email like condition, converted to a table with fields: