diff options
author | Vsevolod Stakhov <vsevolod@rspamd.com> | 2025-03-06 20:00:31 +0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-06 20:00:31 +0600 |
commit | d645fdc2008e61baa2b0d8d7f930a3faebce1d69 (patch) | |
tree | 91c4f411eadd0b39ae34a9e1cbec8a9b4445e76a | |
parent | 22b1d712b36654514db359dbebe1d096d828fb05 (diff) | |
parent | 69b753d4af7db0c76ada3c32328c508b14fbd347 (diff) | |
download | rspamd-d645fdc2008e61baa2b0d8d7f930a3faebce1d69.tar.gz rspamd-d645fdc2008e61baa2b0d8d7f930a3faebce1d69.zip |
Merge pull request #5372 from amulet1/map_improvements
Better support for maps and IP-related fixes/improvements in settings
-rw-r--r-- | lualib/lua_maps.lua | 13 | ||||
-rw-r--r-- | src/plugins/lua/settings.lua | 150 |
2 files changed, 80 insertions, 83 deletions
diff --git a/lualib/lua_maps.lua b/lualib/lua_maps.lua index 2699ea214..6dad3b6ad 100644 --- a/lualib/lua_maps.lua +++ b/lualib/lua_maps.lua @@ -526,15 +526,12 @@ local function rspamd_maybe_check_map(key, what) return rspamd_maybe_check_map(key, elt) end, what) end - if type(rspamd_maps) == "table" then - local mn - if starts(key, "map:") then - mn = string.sub(key, 5) - elseif starts(key, "map://") then - mn = string.sub(key, 7) + if type(rspamd_maps) == "table" and starts(key, "map:") then + local mn = string.sub(key, 5) + if starts(mn, "//") then + mn = string.sub(mn, 3) end - - if mn and rspamd_maps[mn] then + if rspamd_maps[mn] then return rspamd_maps[mn]:get_key(what) end end diff --git a/src/plugins/lua/settings.lua b/src/plugins/lua/settings.lua index 69d31d301..0f8e00723 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 @@ -464,44 +460,52 @@ local function gen_settings_external_cb(name) end -- Process IP address: converted to a table {ip, mask} -local function process_ip_condition(ip) - local out = {} - +local function process_ip_condition(ip, out) if type(ip) == "table" then for _, v in ipairs(ip) do - table.insert(out, process_ip_condition(v)) + process_ip_condition(v, out) end - elseif type(ip) == "string" then - local slash = string.find(ip, '/') + return + end - if not slash then - -- Just a plain IP address - local res = rspamd_ip.from_string(ip) + if type(ip) == "string" then + if string.sub(ip, 1, 4) == "map:" then + -- It is a map, don't apply any extra logic + table.insert(out, ip) + return + 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)) + 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:is_valid() then + table.insert(out, { res:to_string(), mask_num }) + return + end + end - if res:is_valid() then - out[1] = res:to_string() - out[2] = mask - else - rspamd_logger.errx(rspamd_config, "bad IP address: " .. ip) - return nil + rspamd_logger.errx(rspamd_config, "bad IP mask: %s/%s", ip, mask) + return end + + -- Just a plain IP address + table.insert(out, res:to_string()) + return end - else - return nil end - return out + rspamd_logger.errx(rspamd_config, "bad IP address: " .. ip) end -- Process email like condition, converted to a table with fields: @@ -613,6 +617,12 @@ end -- Used to create a checking closure: if value matches expected somehow, return true local function gen_check_closure(expected, check_func) + if not check_func then + check_func = function(a, b) + return a == b + end + end + return function(value) if not value then return false @@ -623,13 +633,6 @@ local function gen_check_closure(expected, check_func) end if value then - - if not check_func then - check_func = function(a, b) - return a == b - end - end - local ret if type(expected) == 'table' then ret = fun.any(function(d) @@ -659,22 +662,21 @@ local function process_settings_table(tbl, allow_ids, mempool, is_static) local checks = {} if elt.ip then - local ips_table = process_ip_condition(elt['ip']) + local ips_table = {} + process_ip_condition(elt.ip, ips_table) - if ips_table then - lua_util.debugm(N, rspamd_config, 'added ip condition to "%s": %s', - name, ips_table) - checks.ip = { - check = gen_check_closure(convert_to_table(elt.ip, ips_table), check_ip_setting), - extract = function(task) - local ip = task:get_from_ip() - if ip and ip:is_valid() then - return ip - end - return nil - end, - } - end + lua_util.debugm(N, rspamd_config, 'added ip condition to "%s": %s', + name, ips_table) + checks.ip = { + check = gen_check_closure(ips_table, check_ip_setting), + extract = function(task) + local ip = task:get_from_ip() + if ip and ip:is_valid() then + return ip + end + return nil + end, + } end if elt.ip_map then local ips_map = lua_maps.map_add_from_ucl(elt.ip_map, 'radix', @@ -697,23 +699,21 @@ local function process_settings_table(tbl, allow_ids, mempool, is_static) end if elt.client_ip then - local client_ips_table = process_ip_condition(elt.client_ip) - - if client_ips_table then - lua_util.debugm(N, rspamd_config, 'added client_ip condition to "%s": %s', - name, client_ips_table) - checks.client_ip = { - check = gen_check_closure(convert_to_table(elt.client_ip, client_ips_table), - check_ip_setting), - extract = function(task) - local ip = task:get_client_ip() - if ip:is_valid() then - return ip - end - return nil - end, - } - end + local client_ips_table = {} + process_ip_condition(elt.client_ip, client_ips_table) + + lua_util.debugm(N, rspamd_config, 'added client_ip condition to "%s": %s', + name, client_ips_table) + checks.client_ip = { + check = gen_check_closure(client_ips_table, check_ip_setting), + extract = function(task) + local ip = task:get_client_ip() + if ip:is_valid() then + return ip + end + return nil + end, + } end if elt.client_ip_map then local ips_map = lua_maps.map_add_from_ucl(elt.ip_map, 'radix', |