diff options
-rw-r--r-- | src/lua/lua_task.c | 22 | ||||
-rw-r--r-- | src/plugins/lua/gpt.lua | 29 | ||||
-rw-r--r-- | src/plugins/lua/metric_exporter.lua | 2 | ||||
-rw-r--r-- | test/functional/cases/500_ratelimit.conf | 44 | ||||
-rw-r--r-- | test/functional/configs/ratelimit.conf | 20 |
5 files changed, 102 insertions, 15 deletions
diff --git a/src/lua/lua_task.c b/src/lua/lua_task.c index dc41d4ab7..61aac63f2 100644 --- a/src/lua/lua_task.c +++ b/src/lua/lua_task.c @@ -2642,7 +2642,7 @@ struct rspamd_url_query_to_inject_cbd { static gboolean inject_url_query_callback(struct rspamd_url *url, gsize start_offset, - gsize end_offset, gpointer ud) + gsize end_offset, gpointer ud) { struct rspamd_url_query_to_inject_cbd *cbd = (struct rspamd_url_query_to_inject_cbd *) ud; @@ -2661,7 +2661,7 @@ inject_url_query_callback(struct rspamd_url *url, gsize start_offset, static void inject_url_query(struct rspamd_task *task, struct rspamd_url *url, - GPtrArray *part_urls) + GPtrArray *part_urls) { if (url->querylen > 0) { struct rspamd_url_query_to_inject_cbd cbd; @@ -2692,11 +2692,11 @@ lua_task_inject_url(lua_State *L) if (lua_isuserdata(L, 3)) { /* We also have a mime part there */ mpart = *((struct rspamd_mime_part **) - rspamd_lua_check_udata_maybe(L, 3, rspamd_mimepart_classname)); + rspamd_lua_check_udata_maybe(L, 3, rspamd_mimepart_classname)); } if (task && task->message && url && url->url) { if (rspamd_url_set_add_or_increase(MESSAGE_FIELD(task, urls), url->url, false)) { - if(mpart && mpart->urls) { + if (mpart && mpart->urls) { inject_url_query(task, url->url, mpart->urls); } } @@ -4682,7 +4682,7 @@ lua_push_symbol_result(lua_State *L, struct rspamd_symbol_option *opt; struct rspamd_symbols_group *sym_group; unsigned int i; - int j = 1, table_fields_cnt = 4; + int j = 1, table_fields_cnt = 5; if (!metric_res) { metric_res = task->result; @@ -4710,10 +4710,22 @@ lua_push_symbol_result(lua_State *L, lua_pushstring(L, symbol); lua_settable(L, -3); } + lua_pushstring(L, "score"); lua_pushnumber(L, s->score); lua_settable(L, -3); + /* Dynamic weight of the symbol */ + if (s->sym->score != 0) { + lua_pushstring(L, "weight"); + lua_pushnumber(L, s->score / s->sym->score); + } + else { + lua_pushstring(L, "weight"); + lua_pushnumber(L, 0.0); + } + lua_settable(L, -3); + if (s->sym && s->sym->gr) { lua_pushstring(L, "group"); lua_pushstring(L, s->sym->gr->name); diff --git a/src/plugins/lua/gpt.lua b/src/plugins/lua/gpt.lua index ddd2f0186..6adbce3bf 100644 --- a/src/plugins/lua/gpt.lua +++ b/src/plugins/lua/gpt.lua @@ -59,13 +59,13 @@ local fun = require "fun" -- Exclude checks if one of those is found local default_symbols_to_except = { - 'BAYES_SPAM', -- We already know that it is a spam, so we can safely skip it, but no same logic for HAM! - 'WHITELIST_SPF', - 'WHITELIST_DKIM', - 'WHITELIST_DMARC', - 'FUZZY_DENIED', - 'REPLY', - 'BOUNCE', + BAYES_SPAM = 0.9, -- We already know that it is a spam, so we can safely skip it, but no same logic for HAM! + WHITELIST_SPF = -1, + WHITELIST_DKIM = -1, + WHITELIST_DMARC = -1, + FUZZY_DENIED = -1, + REPLY = -1, + BOUNCE = -1, } local settings = { @@ -105,9 +105,20 @@ local function default_condition(task) end end -- We also exclude some symbols - for _, s in ipairs(settings.symbols_to_except) do + for s, required_weight in pairs(settings.symbols_to_except) do if task:has_symbol(s) then - return false, 'skip as "' .. s .. '" is found' + if required_weight > 0 then + -- Also check score + local sym = task:get_symbol(s) + -- Must exist as we checked it before with `has_symbol` + if math.abs(sym.weight) >= required_weight then + return false, 'skip as "' .. s .. '" is found (weight: ' .. sym.weight .. ')' + end + lua_util.debugm(N, task, 'symbol %s has weight %s, but required %s', s, + sym.weight, required_weight) + else + return false, 'skip as "' .. s .. '" is found' + end end end diff --git a/src/plugins/lua/metric_exporter.lua b/src/plugins/lua/metric_exporter.lua index 75885516c..3de87c157 100644 --- a/src/plugins/lua/metric_exporter.lua +++ b/src/plugins/lua/metric_exporter.lua @@ -117,7 +117,7 @@ local function graphite_push(kwargs) elseif #split == 2 then mvalue = kwargs['stats'][split[1]][split[2]] end - table.insert(metrics_str, string.format('%s %s %s', mname, mvalue, stamp)) + table.insert(metrics_str, string.format('%s %s %s', mname, mvalue or 'null', stamp)) end metrics_str = table.concat(metrics_str, '\n') diff --git a/test/functional/cases/500_ratelimit.conf b/test/functional/cases/500_ratelimit.conf new file mode 100644 index 000000000..425df34be --- /dev/null +++ b/test/functional/cases/500_ratelimit.conf @@ -0,0 +1,44 @@ +*** Settings *** +Suite Setup Rspamd Setup +Suite Teardown Rspamd Teardown +Library ${RSPAMD_TESTDIR}/lib/rspamd.py +Resource ${RSPAMD_TESTDIR}/lib/rspamd.robot +Variables ${RSPAMD_TESTDIR}/lib/vars.py + +*** Variables *** +${CONFIG} ${RSPAMD_TESTDIR}/configs/ratelimit.conf +${MESSAGE} ${RSPAMD_TESTDIR}/messages/ham.eml +${RSPAMD_SCOPE} Suite +${SETTINGS_REPLIES} {symbols_enabled = [RATELIMIT_CHECK, RATELIMIT_UPDATE]} + +*** Keywords *** +Recipient Test + [Arguments] ${from} ${rcpt} ${howmany} + FOR ${index} IN RANGE ${howmany} + Scan File ${HAM_MESSAGE} + ... From=${from} + ... IP=1.1.1.1 + ... Settings=${SETTINGS_RATELIMIT} + ... Rcpt=${rcpt} + Expect Action no action + END + Scan File ${HAM_MESSAGE} + ... From=${from} + ... IP=1.1.1.1 + ... Settings=${SETTINGS_RATELIMIT} + ... Rcpt=${rcpt} + Expect Action soft reject + Sleep 1s + Scan File ${HAM_MESSAGE} + ... From=${from} + ... IP=1.1.1.1 + ... Settings=${SETTINGS_RATELIMIT} + ... Rcpt=${rcpt} + Expect Action no action + +*** Test Cases *** +CHECK BASIC + Recipient Test ${EMPTY} foobar@example.net 4 + +CHECK SELECTOR + Recipient Test foo@example.net special@example.net 2 diff --git a/test/functional/configs/ratelimit.conf b/test/functional/configs/ratelimit.conf new file mode 100644 index 000000000..ab0c44b42 --- /dev/null +++ b/test/functional/configs/ratelimit.conf @@ -0,0 +1,20 @@ +.include(duplicate=append,priority=0) "{= env.TESTDIR =}/configs/plugins.conf" + +lua = "{= env.LUA_SCRIPT =}"; +redis { + servers = "{= env.REDIS_ADDR =}:{= env.REDIS_PORT =}"; +} + +ratelimit { + bounce_to_ip { + bucket { + burst = 4; + rate = "1 / 1s"; + } + } + to_selector { + selector = "to:in{special@example.net}"; + burst = 2; + rate = "1 / 1s"; + } +} |