]> source.dussan.org Git - rspamd.git/commitdiff
[Project] Restore custom keywords in ratelimit and fix issues
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 13 Jul 2018 16:23:23 +0000 (17:23 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 13 Jul 2018 16:24:42 +0000 (17:24 +0100)
src/plugins/lua/ratelimit.lua

index f81ac4f6e2255e7e18f2e3fb6d48c469923f17b9..73f05a1cf5feb293dcbe9d4b99784fbca263c95a 100644 (file)
@@ -267,7 +267,7 @@ local function parse_limit(name, data)
 
   -- Filter valid
   return fun.totable(fun.filter(function(val)
-    return type(val.bucket) == 'number' and type(val.rate) == 'number'
+    return type(val.burst) == 'number' and type(val.rate) == 'number'
   end, buckets))
 end
 
@@ -337,7 +337,7 @@ local keywords = {
 }
 
 local function gen_rate_key(task, rtype, bucket)
-  local key_t = {tostring(lua_util.round(100000.0 / bucket[1]))}
+  local key_t = {tostring(lua_util.round(100000.0 / bucket.burst))}
   local key_keywords = lua_util.str_split(rtype, '_')
   local have_user = false
 
@@ -442,6 +442,18 @@ local function ratelimit_cb(task)
     nprefixes = nprefixes + limit_to_prefixes(task, k, v, prefixes)
   end
 
+  for k, hdl in pairs(settings.custom_keywords or E) do
+    local ret, redis_key, bucket = pcall(hdl(task))
+
+    if ret then
+      prefixes[redis_key] = make_prefix(redis_key, k, bucket)
+      nprefixes = nprefixes + 1
+    else
+      rspamd_logger.errx(task, 'cannot call handler for %s: %s',
+          k, redis_key)
+    end
+  end
+
   local function gen_check_cb(prefix, bucket, lim_name)
     return function(err, data)
       if err then
@@ -484,7 +496,7 @@ local function ratelimit_cb(task)
 
     for pr,value in pairs(prefixes) do
       local bucket = value.bucket
-      local rate = (bucket[1]) / 1000.0 -- Leak rate in messages/ms
+      local rate = (bucket.rate) / 1000.0 -- Leak rate in messages/ms
       rspamd_logger.debugm(N, task, "check limit %s:%s -> %s (%s/%s)",
           value.name, pr, value.hash, bucket.burst, bucket.rate)
       lua_redis.exec_redis_script(bucket_check_id,
@@ -500,17 +512,14 @@ local function ratelimit_update_cb(task)
   local prefixes = task:cache_get('ratelimit_prefixes')
 
   if prefixes then
-    local action = task:get_metric_action()
-    local is_spam = true
-
-    if action == 'soft reject' then
+    if task:has_pre_result() then
       -- Already rate limited/greylisted, do nothing
-      rspamd_logger.debugm(N, task, 'already soft rejected, do not update')
+      rspamd_logger.debugm(N, task, 'pre-action has been set, do not update')
       return
-    elseif action == 'no action' then
-      is_spam = false
     end
 
+    local is_spam = not (task:get_metric_action() == 'no action')
+
     -- Update each bucket
     for k, v in pairs(prefixes) do
       local bucket = v.bucket
@@ -605,7 +614,22 @@ if opts then
   end
 
   if opts['custom_keywords'] then
-    settings.custom_keywords = dofile(opts['custom_keywords'])
+    local ret, res_or_err = pcall(dofile(opts['custom_keywords']))
+
+    if ret then
+      opts['custom_keywords'] = {}
+      if type(res_or_err) == 'table' then
+        for k,hdl in pairs(res_or_err) do
+          opts['custom_keywords'][k] = hdl
+        end
+      elseif type(res_or_err) == 'function' then
+        opts['custom_keywords']['custom'] = res_or_err
+      end
+    else
+      rspamd_logger.errx(rspamd_config, 'cannot execute %s: %s',
+          opts['custom_keywords'], res_or_err)
+      opts['custom_keywords'] = {}
+    end
   end
 
   if opts['message_func'] then