diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2015-11-23 13:48:11 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2015-11-23 13:48:11 +0000 |
commit | 3e3b6e8185b8e19794e7dbd2515f60e2bbc81983 (patch) | |
tree | 3a78a1cca5577ddbff5fb3cfc6174feeb5257369 /src/plugins/lua | |
parent | 88a9da36c51e0e53afffab9eecf94c65066d99e5 (diff) | |
download | rspamd-3e3b6e8185b8e19794e7dbd2515f60e2bbc81983.tar.gz rspamd-3e3b6e8185b8e19794e7dbd2515f60e2bbc81983.zip |
Rework SA plugin for some problematic cases
Diffstat (limited to 'src/plugins/lua')
-rw-r--r-- | src/plugins/lua/spamassassin.lua | 109 |
1 files changed, 88 insertions, 21 deletions
diff --git a/src/plugins/lua/spamassassin.lua b/src/plugins/lua/spamassassin.lua index fb1998d98..7f5376019 100644 --- a/src/plugins/lua/spamassassin.lua +++ b/src/plugins/lua/spamassassin.lua @@ -42,7 +42,9 @@ local known_plugins = { 'Mail::SpamAssassin::Plugin::FreeMail', 'Mail::SpamAssassin::Plugin::HeaderEval', 'Mail::SpamAssassin::Plugin::ReplaceTags', - 'Mail::SpamAssassin::Plugin::RelayEval' + 'Mail::SpamAssassin::Plugin::RelayEval', + 'Mail::SpamAssassin::Plugin::MIMEEval', + 'Mail::SpamAssassin::Plugin::BodyEval' } -- Internal variables @@ -61,8 +63,9 @@ local replace = { rules = {}, } local internal_regexp = { - date_shift = rspamd_regexp.create_cached("^\\(\\s*'((?:-?\\d+)|(?:undef))'\\s*,\\s*'((?:-?\\d+)|(?:undef))'\\s*\\)$") + date_shift = rspamd_regexp.create("^\\(\\s*'((?:-?\\d+)|(?:undef))'\\s*,\\s*'((?:-?\\d+)|(?:undef))'\\s*\\)$") } +local func_cache = {} local section = rspamd_config:get_all_opt("spamassassin") -- Minimum score to treat symbols as meta @@ -85,6 +88,10 @@ local function split(str, delim) return result end +local function trim(s) + return s:match "^%s*(.-)%s*$" +end + local function handle_header_def(hline, cur_rule) --Now check for modifiers inside header's name local hdrs = split(hline, '[^|]+') @@ -304,7 +311,6 @@ local function maybe_parse_sa_function(line) local arg local elts = split(line, '[^:]+') arg = elts[2] - local func_cache = {} rspamd_logger.debugx(rspamd_config, 'trying to parse SA function %1 with args %2', elts[1], elts[2]) @@ -388,6 +394,9 @@ local function process_sa_conf(f) cur_rule['symbol'] = nsym end -- We have previous rule valid + if not cur_rule['symbol'] then + rspamd_logger.errx(rspamd_config, 'bad rule definition: %1', cur_rule) + end rules[cur_rule['symbol']] = cur_rule cur_rule = {} valid_rule = false @@ -411,16 +420,24 @@ local function process_sa_conf(f) end local skip_to_endif = false + local if_nested = 0 for l in f:lines() do (function () - if string.len(l) == 0 or - _.nth(1, _.drop_while(function(c) return c == ' ' end, _.iter(l))) == '#' then + l = trim(l) + + if string.len(l) == 0 or string.sub(l, 1, 1) == '#' then return end if skip_to_endif then if string.match(l, '^endif') then - skip_to_endif = false + if_nested = if_nested - 1 + + if if_nested == 0 then + skip_to_endif = false + end + elseif string.match(l, '^if') then + if_nested = if_nested + 1 end return else @@ -432,7 +449,21 @@ local function process_sa_conf(f) return false end, known_plugins) then skip_to_endif = true + if_nested = 1 end + elseif string.match(l, '^if !plugin%(') then + local pname = string.match(l, '^if !plugin%(([A-Za-z:]+)%)') + if _.any(function(pl) + if pl == pname then return true end + return false + end, known_plugins) then + skip_to_endif = true + if_nested = 1 + end + elseif string.match(l, '^if') then + -- Unknown if + skip_to_endif = true + if_nested = 1 end end @@ -497,33 +528,69 @@ local function process_sa_conf(f) rspamd_logger.infox(rspamd_config, 'unknown function %1', args) end end - elseif words[1] == "body" and slash then + elseif words[1] == "body" then -- body SYMBOL /regexp/ if valid_rule then insert_cur_rule() end - cur_rule['type'] = 'part' + cur_rule['symbol'] = words[2] - cur_rule['re_expr'] = words_to_re(words, 2) - cur_rule['re'] = rspamd_regexp.create_cached(cur_rule['re_expr']) - cur_rule['raw'] = true - if cur_rule['re'] and cur_rule['symbol'] then - valid_rule = true - cur_rule['re']:set_limit(match_limit) + if words[3] and (string.sub(words[3], 1, 1) == '/' + or string.sub(words[3], 1, 1) == 'm') then + cur_rule['type'] = 'part' + cur_rule['re_expr'] = words_to_re(words, 2) + cur_rule['re'] = rspamd_regexp.create_cached(cur_rule['re_expr']) + cur_rule['raw'] = true + if cur_rule['re'] then + valid_rule = true + cur_rule['re']:set_limit(match_limit) + end + else + -- might be function + local args = words_to_re(words, 2) + local func = maybe_parse_sa_function(args) + + if func then + cur_rule['type'] = 'function' + cur_rule['symbol'] = words[2] + cur_rule['function'] = func + valid_rule = true + else + rspamd_logger.infox(rspamd_config, 'unknown function %1', args) + end end - elseif words[1] == "rawbody" or words[1] == "full" and slash then + elseif words[1] == "rawbody" or words[1] == "full" then -- body SYMBOL /regexp/ if valid_rule then insert_cur_rule() end - cur_rule['type'] = 'message' + cur_rule['symbol'] = words[2] - cur_rule['re_expr'] = words_to_re(words, 2) - cur_rule['re'] = rspamd_regexp.create_cached(cur_rule['re_expr']) - if cur_rule['re'] and cur_rule['symbol'] then - valid_rule = true - cur_rule['re']:set_limit(match_limit) + + if words[3] and (string.sub(words[3], 1, 1) == '/' + or string.sub(words[3], 1, 1) == 'm') then + cur_rule['type'] = 'message' + cur_rule['re_expr'] = words_to_re(words, 2) + cur_rule['re'] = rspamd_regexp.create_cached(cur_rule['re_expr']) + cur_rule['raw'] = true + if cur_rule['re'] then + valid_rule = true + cur_rule['re']:set_limit(match_limit) + end + else + -- might be function + local args = words_to_re(words, 2) + local func = maybe_parse_sa_function(args) + + if func then + cur_rule['type'] = 'function' + cur_rule['symbol'] = words[2] + cur_rule['function'] = func + valid_rule = true + else + rspamd_logger.infox(rspamd_config, 'unknown function %1', args) + end end elseif words[1] == "uri" then -- uri SYMBOL /regexp/ |