diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2019-06-25 18:37:09 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2019-06-25 18:37:09 +0100 |
commit | a2748a06d9e4c50ac31e2c2669ef2cd8b882b662 (patch) | |
tree | 438c39de68c9322b343d50d1d7deff53a7d38142 /src | |
parent | 327f40670c931e39a8643af9539fde9625925cec (diff) | |
download | rspamd-a2748a06d9e4c50ac31e2c2669ef2cd8b882b662.tar.gz rspamd-a2748a06d9e4c50ac31e2c2669ef2cd8b882b662.zip |
[Project] Settings: Add expression aliases
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/lua/settings.lua | 85 |
1 files changed, 58 insertions, 27 deletions
diff --git a/src/plugins/lua/settings.lua b/src/plugins/lua/settings.lua index f269a4018..4b129db0f 100644 --- a/src/plugins/lua/settings.lua +++ b/src/plugins/lua/settings.lua @@ -261,7 +261,7 @@ local function check_settings(task) if not input then return false end if elt.check(input) then - matched[#matched] = atom + matched[#matched + 1] = atom return 1.0 end else @@ -302,8 +302,8 @@ local function check_settings(task) for _,s in ipairs(settings[pri]) do local matched = {} - lua_util.debugm(N, task, "check for settings element %s; %s", - s.name, s.rule.expression) + lua_util.debugm(N, task, "check for settings element %s", + s.name) local result = check_specific_setting(s.rule, matched) -- Can use xor here but more complicated for reading if result then @@ -702,6 +702,41 @@ local function process_settings_table(tbl, allow_ids, mempool) } end + local aliases = {} + -- This function is used to convert compound condition with + -- generic type and specific part (e.g. `header`, `Content-Transfer-Encoding`) + -- to a set of usable check elements: + -- `generic:specific` - most common part + -- `generic:<order>` - e.g. `header:1` for the first header + -- `generic:safe` - replace unsafe stuff with safe + lowercase + -- also aliases entry is set to avoid implicit expression + local function process_compound_condition(cond, generic, specific) + local full_key = generic .. ':' .. specific + checks[full_key] = cond + + -- Try numeric key + for i=1,1000 do + local num_key = generic .. ':' .. tostring(i) + if not checks[num_key] then + checks[num_key] = cond + aliases[num_key] = true + break + end + end + + local safe_key = generic .. ':' .. + specific:gsub('[:%-+&|><]', '_') + :gsub('%(', '[') + :gsub('%)', ']') + :lower() + + if not checks[safe_key] then + checks[safe_key] = cond + aliases[safe_key] = true + end + + return safe_key + end -- Headers are tricky: -- We create an closure with extraction function depending on header name -- We also inserts it into `checks` table as an atom in form header:<hname> @@ -714,30 +749,30 @@ local function process_settings_table(tbl, allow_ids, mempool) if type(v) == 'string' then local re = rspamd_regexp.create(v) if re then - checks[table_element .. ':'..k] = { + local cond = { check = function(values) return fun.any(function(c) return re:match(c) end, values) end, extract = extractor_func(k), } - + local skey = process_compound_condition(cond, table_element, + k) lua_util.debugm(N, rspamd_config, 'added %s condition to "%s": %s =~ %s', - table_element, name, k, v) + skey, name, k, v) end elseif type(v) == 'boolean' then - checks[table_element .. ':'..k] = { + local cond = { check = function(values) - return fun.any(function(c) - if c and v then return true end - if not c or not v then return true end - return false - end, values) + if #values == 0 then return (not v) end + return v end, extract = extractor_func(k), } - lua_util.debugm(N, rspamd_config, 'added %s condition to "%s": %s =~ %s', - table_element, name, k, v) + local skey = process_compound_condition(cond, table_element, + k) + lua_util.debugm(N, rspamd_config, 'added %s condition to "%s": %s == %s', + skey, name, k, v) else rspamd_logger.errx(rspamd_config, 'invalid %s %s = %s', table_element, k, v) end @@ -756,25 +791,18 @@ local function process_settings_table(tbl, allow_ids, mempool) return function(task) local rh = task:get_header_full(hname) if rh then - return fun.map(function(h) return h.decoded end, rh) + return fun.totable(fun.map(function(h) return h.decoded end, rh)) end return {} end end) if elt['selector'] then - local sel = selectors_cache[name] - if not sel then - sel = lua_selectors.create_selector_closure(rspamd_config, elt.selector, - elt.delimiter or "") - - if sel then - selectors_cache[name] = sel - end - end + local sel = lua_selectors.create_selector_closure(rspamd_config, elt.selector, + elt.delimiter or "") if sel then - checks['selector:' .. name] = { + local cond = { check = function(values) return fun.any(function(c) return c @@ -782,8 +810,9 @@ local function process_settings_table(tbl, allow_ids, mempool) end, extract = sel, } + local skey = process_compound_condition(cond, 'selector', elt.selector) lua_util.debugm(N, rspamd_config, 'added selector condition to "%s": %s', - name, sel) + name, skey) end end @@ -808,8 +837,10 @@ local function process_settings_table(tbl, allow_ids, mempool) local s = ' && ' -- By De Morgan laws if inverse then s = ' || ' end + -- Exclude aliases and join all checks by key local expr_str = table.concat(fun.totable(fun.map(function(k, _) - return k end, checks)), s) + return k end, + fun.filter(function(k, _) return not aliases[k] end, checks))), s) if inverse then expr_str = string.format('!(%s)', expr_str) |