aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2016-01-28 14:51:08 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2016-01-28 14:51:08 +0000
commit6d0833e5ab01b0bde51b4219eb027d2ba75c1a01 (patch)
treee3a84b6e48ac073d20a91b516024cb8a157e6ad2 /src
parent436ccb77ecdea5a70bb2d4627965551b6c3858b0 (diff)
downloadrspamd-6d0833e5ab01b0bde51b4219eb027d2ba75c1a01.tar.gz
rspamd-6d0833e5ab01b0bde51b4219eb027d2ba75c1a01.zip
Improve and fix multimap plugin
- Restore 'header' maps - Add filters for headers - Add 'email:addr', 'email:user', 'email:domain' and 'email:name' filters - Add generic regexp filters
Diffstat (limited to 'src')
-rw-r--r--src/plugins/lua/multimap.lua99
1 files changed, 79 insertions, 20 deletions
diff --git a/src/plugins/lua/multimap.lua b/src/plugins/lua/multimap.lua
index d821902ea..5a8bbeea9 100644
--- a/src/plugins/lua/multimap.lua
+++ b/src/plugins/lua/multimap.lua
@@ -29,6 +29,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
local rules = {}
local rspamd_logger = require "rspamd_logger"
local cdb = require "rspamd_cdb"
+local util = require "rspamd_util"
+local regexp = require "rspamd_regexp"
local _ = require "fun"
--local dumper = require 'pl.pretty'.dump
@@ -37,9 +39,63 @@ local function ip_to_rbl(ip, rbl)
end
local function check_multimap(task)
+ -- Applies specific filter for input
+ local function apply_filter(filter, input, rule)
+ if filter == 'email:addr' or filter == 'email' then
+ local addr = util.parse_mail_address(input)
+ if addr and addr[1] then
+ return addr[1]['addr']
+ end
+ elseif filter == 'email:user' then
+ local addr = util.parse_mail_address(input)
+ if addr and addr[1] then
+ return addr[1]['user']
+ end
+ elseif filter == 'email:domain' then
+ local addr = util.parse_mail_address(input)
+ if addr and addr[1] then
+ return addr[1]['domain']
+ end
+ elseif filter == 'email:name' then
+ local addr = util.parse_mail_address(input)
+ if addr and addr[1] then
+ return addr[1]['name']
+ end
+ else
+ -- regexp case
+ if not rule['regexp'] then
+ local type,pat = string.match(filter, '(regexp:)(.+)')
+ if type and pat then
+ rule['regexp'] = regexp.create(pat)
+ end
+ end
+
+ if not rule['regexp'] then
+ rspamd_logger.errx(task, 'bad search filter: %s', filter)
+ else
+ local results = rule['regexp']:search(input)
+ if results then
+ return results[1]
+ end
+ end
+ end
+
+ return input
+ end
+
+
-- Match a single value for against a single rule
local function match_rule(r, value)
local ret = false
+
+ if r['filter'] then
+ value = apply_filter(r['filter'], value, r)
+ end
+
+ if not value then
+ return false
+ end
+
if r['cdb'] then
local srch = value
if r['type'] == 'ip' then
@@ -56,7 +112,7 @@ local function check_multimap(task)
if ret then
task:insert_result(r['symbol'], 1)
end
-
+
return ret
end
@@ -65,13 +121,13 @@ local function check_multimap(task)
local ret = false
if ls then
if fields then
- _.each(function(e)
+ _.each(function(e)
local match = e[fields[1]]
if match then
if fields[2] then
match = fields[2](match)
end
- ret = match_rule(r, match)
+ ret = match_rule(r, match)
end
end, ls)
else
@@ -81,10 +137,10 @@ local function check_multimap(task)
return ret
end
-
+
local function match_addr(r, addr)
local ret = match_list(r, addr, {'addr'})
-
+
if not ret then
-- Try domain
ret = match_list(r, addr, {'domain', function(d) return '@' .. d end})
@@ -93,9 +149,10 @@ local function check_multimap(task)
-- Try user
ret = match_list(r, addr, {'user', function(d) return d .. '@' end})
end
-
+
return ret
end
+
-- IP rules
local ip = task:get_from_ip()
if ip:is_valid() then
@@ -106,13 +163,13 @@ local function check_multimap(task)
-- Header rules
_.each(function(r)
local hv = task:get_header_full(r['header'])
- match_list(r, hv, 'decoded')
+ match_list(r, hv, {'decoded'})
end,
_.filter(function(r) return r['type'] == 'header' end, rules))
-- Rcpt rules
- local rcpts = task:get_recipients()
- if rcpts then
+ if task:has_recipients() then
+ local rcpts = task:get_recipients()
_.each(function(r)
match_addr(r, rcpts)
end,
@@ -120,12 +177,14 @@ local function check_multimap(task)
end
-- From rules
- local from = task:get_from()
- if from then
- _.each(function(r)
- match_addr(r, from)
- end,
- _.filter(function(r) return r['type'] == 'from' end, rules))
+ if task:has_from() then
+ local from = task:get_from()
+ if from then
+ _.each(function(r)
+ match_addr(r, from)
+ end,
+ _.filter(function(r) return r['type'] == 'from' end, rules))
+ end
end
-- RBL rules
@@ -136,7 +195,7 @@ local function check_multimap(task)
task:insert_result(r['symbol'], 1, r['map'])
end
end
-
+
task:get_resolver():resolve_a({task = task,
name = ip_to_rbl(ip, r['map']),
callback = cb,
@@ -148,13 +207,13 @@ end
local function add_multimap_rule(key, newrule)
if not newrule['map'] then
- rspamd_logger.errx(rspamd_config, 'incomplete rule')
+ rspamd_logger.errx(rspamd_config, 'incomplete rule, missing map')
return nil
end
if not newrule['symbol'] and key then
newrule['symbol'] = key
elseif not newrule['symbol'] then
- rspamd_logger.errx(rspamd_config, 'incomplete rule')
+ rspamd_logger.errx(rspamd_config, 'incomplete rule, missing symbol')
return nil
end
-- Check cdb flag
@@ -186,7 +245,7 @@ local function add_multimap_rule(key, newrule)
newrule['map'])
end
elseif newrule['type'] == 'dnsbl' then
- return newrule
+ return newrule
end
end
return nil
@@ -209,7 +268,7 @@ if opts and type(opts) == 'table' then
end
-- add fake symbol to check all maps inside a single callback
if type(rspamd_config.get_api_version) ~= 'nil' then
- local id = rspamd_config:register_callback_symbol_priority(1.0, -1,
+ local id = rspamd_config:register_callback_symbol_priority(1.0, -1,
check_multimap)
for i,rule in ipairs(rules) do
rspamd_config:register_virtual_symbol(rule['symbol'], 1.0, id)