]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
dcc cleanup
authorFrancois Lesueur <flesueur@alwaysdata.com>
Wed, 3 Sep 2025 14:50:05 +0000 (16:50 +0200)
committerFrancois Lesueur <flesueur@alwaysdata.com>
Wed, 3 Sep 2025 14:50:05 +0000 (16:50 +0200)
lualib/lua_scanners/dcc.lua
src/plugins/lua/dcc.lua
src/plugins/lua/external_services.lua

index 32936226e28114bf62bebd077cac51a437c017b6..ef725d9e2b2d298fc91dd754d988b2d4b23fef62 100644 (file)
@@ -41,10 +41,8 @@ local function dcc_config(opts)
     message = '${SCANNER}: bulk message found: "${VIRUS}"',
     detection_category = "hash",
     default_score = 1,
-    action = false,
     client = '0.0.0.0',
     symbol_fail = 'DCC_FAIL',
-    symbol = 'DCC_REJECT',
     symbol_bulk = 'DCC_BULK',
     body_max = 999999,
     fuz1_max = 999999,
@@ -127,7 +125,7 @@ local function dcc_check(task, content, digest, rule)
     -- Build the DCC query
     -- https://www.dcc-servers.net/dcc/dcc-tree/dccifd.html#Protocol
     local request_data = {
-      "header\n",
+      "header grey-off no-reject\n",
       client .. "\n",
       helo .. "\n",
       envfrom .. "\n",
@@ -160,9 +158,6 @@ local function dcc_check(task, content, digest, rule)
             shutdown = true,
             data = request_data,
             callback = dcc_callback,
-            body_max = 999999,
-            fuz1_max = 999999,
-            fuz2_max = 999999,
           })
         else
           rspamd_logger.errx(task, '%s: failed to scan, maximum retransmits ' ..
@@ -180,79 +175,82 @@ local function dcc_check(task, content, digest, rule)
         local _, _, result, disposition, header = tostring(data):find("(.-)\n(.-)\n(.-)$")
         lua_util.debugm(rule.name, task, 'DCC result=%1 disposition=%2 header="%3"',
             result, disposition, header)
+        -- rspamd_logger.warnx(task, '%s: result: %s, header: %s', rule.log_prefix, result, header);
 
         if header then
           -- Unfold header
           header = header:gsub('\r?\n%s*', ' ')
           local _, _, info = header:find("; (.-)$")
           if (result == 'R') then
-            -- Reject
-            common.yield_result(task, rule, info, rule.default_score)
-            common.save_cache(task, digest, rule, info, rule.default_score)
+            -- Reject, should not happen so do nothing
+            if rule.log_clean then
+              rspamd_logger.infox(task, '%s: clean, returned result R - info: %s', rule.log_prefix, info)
+            else
+              lua_util.debugm(rule.name, task, '%s: returned result R - info: %s', rule.log_prefix, info)
+            end
           elseif (result == 'T') then
             -- Temporary failure
             rspamd_logger.warnx(task, 'DCC returned a temporary failure result: %s', result)
             dcc_requery()
           elseif result == 'A' then
-
+            -- Accept decision, get results
             local opts = {}
             local score = 0.0
-            info = info:lower()
-            local rep = info:match('rep=(%d+)')
-
-            -- Adjust reputation if available
-            if rep then
-              rep = (tonumber(rep) or 100.0) / 100.0
-
-              if rep > 1.0 then
-                rep = 1.0
-              elseif rep < 0.0 then
-                rep = 0.0
-              end
-            else
-              rep = 1.0
-            end
-
-            local function check_threshold(what, num, lim)
-              local rnum
-              if num == 'many' then
-                rnum = lim
+            if info then
+              info = info:lower()
+              local rep = info:match('rep=(%d+)')
+
+              -- Adjust reputation if available
+              if rep then
+                rep = (tonumber(rep) or 100.0) / 100.0
+
+                if rep > 1.0 then
+                  rep = 1.0
+                elseif rep < 0.0 then
+                  rep = 0.0
+                end
               else
-                rnum = tonumber(num) or lim
+                rep = 1.0
               end
 
-              if rnum and rnum >= lim then
-                opts[#opts + 1] = string.format('%s=%s', what, num)
-                score = score + (rep / 3.0)
+              local function check_threshold(what, num, lim)
+                local rnum
+                if num == 'many' then
+                  rnum = lim
+                else
+                  rnum = tonumber(num) or lim
+                end
+
+                if rnum and rnum >= lim then
+                  opts[#opts + 1] = string.format('%s=%s', what, num)
+                  score = score + (rule.default_score * rep / 3.0)
+                end
               end
-            end
 
-            info = info:lower()
-            local body = info:match('body=([^=%s]+)')
+              local body = info:match('body=([^=%s]+)')
 
-            if body then
-              check_threshold('body', body, rule.body_max)
-            end
+              if body then
+                check_threshold('body', body, rule.body_max)
+              end
 
-            local fuz1 = info:match('fuz1=([^=%s]+)')
+              local fuz1 = info:match('fuz1=([^=%s]+)')
 
-            if fuz1 then
-              check_threshold('fuz1', fuz1, rule.fuz1_max)
-            end
+              if fuz1 then
+                check_threshold('fuz1', fuz1, rule.fuz1_max)
+              end
 
-            local fuz2 = info:match('fuz2=([^=%s]+)')
+              local fuz2 = info:match('fuz2=([^=%s]+)')
 
-            if fuz2 then
-              check_threshold('fuz2', fuz2, rule.fuz2_max)
+              if fuz2 then
+                check_threshold('fuz2', fuz2, rule.fuz2_max)
+              end
             end
 
             if #opts > 0 and score > 0 then
               task:insert_result(rule.symbol_bulk,
                   score,
                   opts)
-              common.save_cache(task, digest, rule, opts, score)
             else
-              common.save_cache(task, digest, rule, 'OK')
               if rule.log_clean then
                 rspamd_logger.infox(task, '%s: clean, returned result A - info: %s',
                     rule.log_prefix, info)
@@ -262,16 +260,14 @@ local function dcc_check(task, content, digest, rule)
               end
             end
           elseif result == 'G' then
-            -- do nothing
-            common.save_cache(task, digest, rule, 'OK')
+            -- Greylist, should not happen so do nothing
             if rule.log_clean then
               rspamd_logger.infox(task, '%s: clean, returned result G - info: %s', rule.log_prefix, info)
             else
               lua_util.debugm(rule.name, task, '%s: returned result G - info: %s', rule.log_prefix, info)
             end
           elseif result == 'S' then
-            -- do nothing
-            common.save_cache(task, digest, rule, 'OK')
+            -- Accept only for some recipients, should not happen so do nothing
             if rule.log_clean then
               rspamd_logger.infox(task, '%s: clean, returned result S - info: %s', rule.log_prefix, info)
             else
@@ -295,18 +291,10 @@ local function dcc_check(task, content, digest, rule)
       upstream = upstream,
       data = request_data,
       callback = dcc_callback,
-      body_max = 999999,
-      fuz1_max = 999999,
-      fuz2_max = 999999,
     })
   end
 
-  if common.condition_check_and_continue(task, content, rule, digest, dcc_check_uncached) then
-    return
-  else
-    dcc_check_uncached()
-  end
-
+  dcc_check_uncached()
 end
 
 return {
index 850832057e85eb333a9fd07930ab6f8c6f6fa700..0f03f4322c836a0c15abe10b3857c4d20efbb3f2 100644 (file)
@@ -19,7 +19,7 @@ limitations under the License.
 
 local N = 'dcc'
 local symbol_bulk = "DCC_BULK"
-local symbol = "DCC_REJECT"
+local symbol_fail = "DCC_FAIL"
 local opts = rspamd_config:get_all_opt(N)
 local lua_util = require "lua_util"
 local rspamd_logger = require "rspamd_logger"
@@ -77,11 +77,6 @@ if rule then
     callback = check_dcc,
     type = 'callback',
   })
-  rspamd_config:register_symbol {
-    type = 'virtual',
-    parent = id,
-    name = opts.symbol
-  }
   rspamd_config:register_symbol {
     type = 'virtual',
     parent = id,
@@ -90,7 +85,7 @@ if rule then
   rspamd_config:register_symbol {
     type = 'virtual',
     parent = id,
-    name = 'DCC_FAIL'
+    name = opts.symbol_fail
   }
   rspamd_config:set_metric_symbol({
     group = N,
@@ -99,19 +94,12 @@ if rule then
     one_shot = true,
     name = opts.symbol_bulk,
   })
-  rspamd_config:set_metric_symbol({
-    group = N,
-    score = 2.0,
-    description = 'Rejected by DCC',
-    one_shot = true,
-    name = opts.symbol,
-  })
   rspamd_config:set_metric_symbol({
     group = N,
     score = 0.0,
     description = 'DCC failure',
     one_shot = true,
-    name = 'DCC_FAIL',
+    name = opts.symbol_fail,
   })
 else
   lua_util.disable_module(N, "config")
index 307218d94a4540bdf57cca188e5cf75c2cffe86c..489b0af7d62bb909a08fc88a340664c3f0429da8 100644 (file)
@@ -27,7 +27,7 @@ local N = "external_services"
 
 if confighelp then
   rspamd_config:add_example(nil, 'external_services',
-      "Check messages using external services (e.g. OEM AS engines, DCC, Pyzor etc)",
+      "Check messages using external services (e.g. OEM AS engines, Pyzor etc)",
       [[
   external_services {
     # multiple scanners could be checked, for each we create a configuration block with an arbitrary name
@@ -90,22 +90,6 @@ if confighelp then
       # `whitelist` points to a map of IP addresses. Mail from these addresses is not scanned.
       whitelist = "/etc/rspamd/antivirus.wl";
     }
-    dcc {
-      # If set force this action if any virus is found (default unset: no action is forced)
-      # action = "reject";
-      # If set, then rejection message is set to this value (mention single quotes)
-      # If `max_size` is set, messages > n bytes in size are not scanned
-      max_size = 20000000;
-      #servers = "127.0.0.1:10045;
-      # if `patterns` is specified virus name will be matched against provided regexes and the related
-      # symbol will be yielded if a match is found. If no match is found, default symbol is yielded.
-      patterns {
-        # symbol_name = "pattern";
-        JUST_EICAR = "^Eicar-Test-Signature$";
-      }
-      # `whitelist` points to a map of IP addresses. Mail from these addresses is not scanned.
-      whitelist = "/etc/rspamd/antivirus.wl";
-    }
   }
   ]])
   return