From be555f381e6b72d76c72a91b78291217e6a77c0b Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 27 Jul 2010 19:09:41 +0400 Subject: [PATCH] * Fix lua representing of invalid ip (nil, not 255.255.255.255) * Fix R_TO_SEEMS_AUTO rule (by citrin) * Add multimap lua plugin --- conf/lua/regexp/headers.lua | 2 +- src/lua/lua_task.c | 6 +- src/plugins/lua/multimap.lua | 125 +++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 4 deletions(-) create mode 100644 src/plugins/lua/multimap.lua diff --git a/conf/lua/regexp/headers.lua b/conf/lua/regexp/headers.lua index 07f9a785c..d296b3653 100644 --- a/conf/lua/regexp/headers.lua +++ b/conf/lua/regexp/headers.lua @@ -44,7 +44,7 @@ reconf['MISSING_MID'] = '!header_exists(Message-Id)'; reconf['R_RCVD_SPAMBOTS'] = 'Received=/^from \\[\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\] by [-.\\w+]{5,255}; [SMTWF][a-z][a-z], [\\s\\d]?\\d [JFMAJSOND][a-z][a-z] \\d{4} \\d{2}:\\d{2}:\\d{2} [-+]\\d{4}$/mH' -- To header seems to be autogenerated -reconf['R_TO_SEEMS_AUTO'] = 'To=/\\"?(?[-.\\w]{1,64})\\"?\\s<\\k\\@/H' +reconf['R_TO_SEEMS_AUTO'] = 'To=/^\\"?(?[-.\\w]{1,64})\\"?\\s<\\k\\@/H' -- Charset is missing in message reconf['R_MISSING_CHARSET']= string.format('content_type_is_type(text) & !content_type_has_param(charset) & !%s', r_cte_7bit); diff --git a/src/lua/lua_task.c b/src/lua/lua_task.c index 71a36aba1..3630462f9 100644 --- a/src/lua/lua_task.c +++ b/src/lua/lua_task.c @@ -471,7 +471,7 @@ lua_task_get_from_ip (lua_State *L) struct worker_task *task = lua_check_task (L); if (task) { - if (task->from_addr.s_addr != 0) { + if (task->from_addr.s_addr != INADDR_NONE && task->from_addr.s_addr != INADDR_ANY) { lua_pushstring (L, inet_ntoa (task->from_addr)); return 1; } @@ -487,7 +487,7 @@ lua_task_get_from_ip_num (lua_State *L) struct worker_task *task = lua_check_task (L); if (task) { - if (task->from_addr.s_addr != 0) { + if (task->from_addr.s_addr != INADDR_NONE && task->from_addr.s_addr != INADDR_ANY) { lua_pushinteger (L, ntohl (task->from_addr.s_addr)); return 1; } @@ -503,7 +503,7 @@ lua_task_get_client_ip_num (lua_State *L) struct worker_task *task = lua_check_task (L); if (task) { - if (task->client_addr.s_addr != 0) { + if (task->client_addr.s_addr != INADDR_NONE && task->client_addr.s_addr != INADDR_ANY) { lua_pushinteger (L, ntohl (task->client_addr.s_addr)); return 1; } diff --git a/src/plugins/lua/multimap.lua b/src/plugins/lua/multimap.lua new file mode 100644 index 000000000..ebf419b12 --- /dev/null +++ b/src/plugins/lua/multimap.lua @@ -0,0 +1,125 @@ +-- Multimap is rspamd module designed to define and operate with different maps + +local rules = {} + +function split(str, delim, maxNb) + -- Eliminate bad cases... + if string.find(str, delim) == nil then + return { str } + end + if maxNb == nil or maxNb < 1 then + maxNb = 0 -- No limit + end + local result = {} + local pat = "(.-)" .. delim .. "()" + local nb = 0 + local lastPos + for part, pos in string.gfind(str, pat) do + nb = nb + 1 + result[nb] = part + lastPos = pos + if nb == maxNb then break end + end + -- Handle the last field + if nb ~= maxNb then + result[nb + 1] = string.sub(str, lastPos) + end + return result +end + +function check_multimap(task) + for _,rule in ipairs(rules) do + if rule['type'] == 'ip' then + local ip = task:get_from_ip_num() + if rule['ips']:get_key(ip) then + task:insert_result(rule['symbol'], 1) + end + elseif rule['type'] == 'header' then + local headers = task:get_message():get_header(rule['header']) + if headers then + for _,hv in ipairs(headers) do + if rule['pattern'] then + -- extract a part from header + local _,_,ext = string.find(hv, rule['pattern']) + if ext then + if rule['hash']:get_key(ext) then + task:insert_result(rule['symbol'], 1) + end + end + else + if rule['hash']:get_key(hv) then + task:insert_result(rule['symbol'], 1) + end + end + end + end + end + end +end + +function add_rule(params) + local newrule = { + type = 'ip', + header = nil, + pattern = nil, + file = nil, + symbol = nil + } + for _,param in ipairs(params) do + local _,_,name,value = string.find(param, '(%w+)%s*=%s*(.+)') + if not name or not value then + rspamd_logger:err('invalid rule: '..param) + return 0 + end + if name == 'type' then + if value == 'ip' then + newrule['type'] = 'ip' + elseif value == 'header' then + newrule['type'] = 'header' + else + rspamd_logger:err('invalid rule type: '.. value) + return 0 + end + elseif name == 'header' then + newrule['header'] = value + elseif name == 'pattern' then + newrule['pattern'] = value + elseif name == 'file' then + newrule['file'] = value + elseif name == 'symbol' then + newrule['symbol'] = value + else + rspamd_logger:err('invalid rule option: '.. name) + return 0 + end + + end + if not newrule['symbol'] or not newrule['file'] or not newrule['symbol'] then + rspamd_logger:err('incomplete rule') + return 0 + end + if newrule['type'] == 'ip' then + newrule['ips'] = rspamd_config:add_radix_map (newrule['file']) + else + newrule['hash'] = rspamd_config:add_hash_map (newrule['file']) + end + table.insert(rules, newrule) + return 1 +end + +local opts = rspamd_config:get_all_opt('multimap') +if opts then + for opt,value in pairs(opts) do + if opt == 'rule' then + local params = split(value, ',') + if not add_rule (params) then + rspamd_logger:err('cannot add rule: "'..value..'"') + end + end + end +end + +if table.maxn(rules) > 0 then + -- add fake symbol to check all maps inside a single callback + rspamd_config:register_symbol('MULTIMAP', 1.0, 'check_multimap') +end -- 2.39.5