summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2016-04-06 13:04:27 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2016-04-06 13:04:27 +0100
commitd06943dd720ad2925349136a30b67937014fdb6d (patch)
tree7843c4bd630f55478f2b2f92a79446e6aa3f8039 /src
parentb1050438ad5937175e699dc5c5826da3003f4e3d (diff)
parentc8c304d5617c1e10ff9bddf026b74f2d316e9c16 (diff)
downloadrspamd-d06943dd720ad2925349136a30b67937014fdb6d.tar.gz
rspamd-d06943dd720ad2925349136a30b67937014fdb6d.zip
Merge pull request #586 from smfreegard/dcc_module
New DCC module
Diffstat (limited to 'src')
-rw-r--r--src/plugins/lua/dcc.lua117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/plugins/lua/dcc.lua b/src/plugins/lua/dcc.lua
new file mode 100644
index 000000000..7e8c5b20d
--- /dev/null
+++ b/src/plugins/lua/dcc.lua
@@ -0,0 +1,117 @@
+--[[
+Copyright (c) 2016, Steve Freegard <steve.freegard@fsl.com>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+]]--
+
+-- Check messages for 'bulkiness' using DCC
+
+local symbol = "DCC_CHECK"
+local symbol_bulk = "DCC_BULK"
+local opts = rspamd_config:get_all_opt('dcc')
+local logger = require "rspamd_logger"
+local tcp = require "rspamd_tcp"
+
+local function check_dcc (task)
+ -- Connection
+ local client = '0.0.0.0'
+ local client_ip = task:get_from_ip():to_string()
+ if client_ip then
+ client = client_ip
+ end
+ local client_host = task:get_hostname()
+ if client_host and client_host ~= 'unknown' then
+ client = client .. "\r" .. client_host
+ end
+
+ -- HELO
+ local helo = task:get_helo() or ''
+
+ -- Envelope From
+ local ef = task:get_from(1)
+ local envfrom = 'test@example.com'
+ if ef and ef[1] then
+ envfrom = ef[1]['addr']
+ end
+
+ -- Envelope To
+ local envrcpt = 'test@example.com'
+ local rcpts = task:get_recipients(1);
+ if rcpts then
+ local r = table.concat(totable(map(function(rcpt) return rcpt['addr'] end, rcpts)), '\n')
+ if r then
+ envrcpt = r
+ end
+ end
+
+ -- Callback function to receive async result from DCC
+ local function cb(err, data)
+ if (err) then
+ logger.errx('DCC error: %1', err)
+ return 0
+ end
+ -- Parse the response
+ local _,_,result,disposition,header = tostring(data):find("(.-)\n(.-)\n(.-)\n")
+ logger.infox('DCC result=%1 disposition=%2 header="%3"', result, disposition, header)
+ local _,_,info = header:find("; (.-)$")
+ if (result == 'A') then
+ -- Accept
+ elseif (result == 'G') then
+ -- Greylist
+ elseif (result == 'R') then
+ -- Reject
+ task:insert_result('DCC_BULK', 1.0, info)
+ elseif (result == 'S') then
+ -- Accept for some recipients only
+ elseif (result == 'T') then
+ -- Temporary failure
+ logger.errx('DCC returned a temporary failure result')
+ else
+ -- Unknown result
+ logger.errx('DCC result error: %1', result);
+ end
+ return 0
+ end
+
+ -- Build the DCC query
+ -- https://www.dcc-servers.net/dcc/dcc-tree/dccifd.html#Protocol
+ local data = {
+ "header\n",
+ client .. "\n",
+ helo .. "\n",
+ envfrom .. "\n",
+ envrcpt .. "\n",
+ "\n",
+ task:get_content()
+ }
+
+ logger.infox('sending to dcc: client=%1 helo="%2" envfrom="%3" envrcpt="%4"',
+ client, helo, envfrom, envrcpt)
+
+ tcp.request({
+ task = task,
+ host = opts['host'],
+ port = opts['port'] or 1,
+ shutdown = true,
+ data = data,
+ callback = cb
+ })
+end
+
+-- Configuration
+if opts and opts['host'] then
+ local id = rspamd_config:register_symbol(symbol, 1.0, check_dcc)
+ rspamd_config:register_virtual_symbol(symbol_bulk, 1.0, id)
+else
+ logger.infox('DCC module not configured');
+end