diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2016-04-06 13:04:27 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2016-04-06 13:04:27 +0100 |
commit | d06943dd720ad2925349136a30b67937014fdb6d (patch) | |
tree | 7843c4bd630f55478f2b2f92a79446e6aa3f8039 /src | |
parent | b1050438ad5937175e699dc5c5826da3003f4e3d (diff) | |
parent | c8c304d5617c1e10ff9bddf026b74f2d316e9c16 (diff) | |
download | rspamd-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.lua | 117 |
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 |