aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/lua/replies.lua
diff options
context:
space:
mode:
authorAndrew Lewis <nerf@judo.za.org>2016-05-08 16:37:12 +0200
committerAndrew Lewis <nerf@judo.za.org>2016-05-08 16:44:50 +0200
commit0a4bbf32ba9e5c36b3a01f6b4b885a969c21007f (patch)
treeaaffcfc2032182297cae018ef4a6fede64606ac2 /src/plugins/lua/replies.lua
parent7e3619944c79e1b78039f4451713125003cfaca7 (diff)
downloadrspamd-0a4bbf32ba9e5c36b3a01f6b4b885a969c21007f.tar.gz
rspamd-0a4bbf32ba9e5c36b3a01f6b4b885a969c21007f.zip
[Feature] Add replies plugin
Diffstat (limited to 'src/plugins/lua/replies.lua')
-rw-r--r--src/plugins/lua/replies.lua120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/plugins/lua/replies.lua b/src/plugins/lua/replies.lua
new file mode 100644
index 000000000..dca2b0866
--- /dev/null
+++ b/src/plugins/lua/replies.lua
@@ -0,0 +1,120 @@
+--[[
+Copyright (c) 2016, Vsevolod Stakhov <vsevolod@highsecure.ru>
+Copyright (c) 2016, Andrew Lewis <nerf@judo.za.org>
+
+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.
+]]--
+
+-- A plugin that implements replies check using redis
+
+-- Default port for redis upstreams
+local default_port = 6379
+local upstreams
+local whitelisted_ip
+local settings = {
+ action = nil,
+ expire = 86400, -- 1 day by default
+ key_prefix = 'rr',
+ message = 'Message is reply to one we originated',
+ symbol = 'REPLY',
+}
+
+local rspamd_logger = require 'rspamd_logger'
+local rspamd_redis = require 'rspamd_redis'
+local upstream_list = require 'rspamd_upstream_list'
+local hash = require 'rspamd_cryptobox_hash'
+
+local function make_key(goop)
+ local h = hash.create()
+ h:update(goop)
+ local key = h:base32()
+ key = settings['key_prefix'] .. key
+ return key
+end
+
+local function replies_check(task)
+ local function redis_get_cb(task, err, data)
+ if err ~= nil then
+ rspamd_logger.errx('redis_get_cb received error: %1', err)
+ return
+ end
+ if data == '1' then
+ -- Hash was found
+ task:insert_result(settings['symbol'], 0.0)
+ if settings['action'] ~= nil then
+ task:set_pre_result(settings['action'], settings['message'])
+ end
+ end
+ end
+ -- If in-reply-to header not present return
+ local irt = task:get_header_raw('in-reply-to')
+ if irt == nil then
+ return
+ end
+ -- Create hash of in-reply-to and query redis
+ local key = make_key(irt)
+ local upstream = upstreams:get_upstream_by_hash(key)
+ local addr = upstream:get_addr()
+ if not rspamd_redis.make_request({task = task, host = addr, callback = redis_get_cb,
+ cmd = 'GET', args = {key}}) then
+ rspamd_logger.errx("redis request wasn't scheduled")
+ end
+end
+
+local function replies_set(task)
+ local function redis_set_cb(task, err, data)
+ if err ~=nil then
+ rspamd_logger.errx('redis_set_cb received error: %1', err)
+ end
+ end
+ -- If sender is unauthenticated return
+ if task:get_user() == nil then
+ return
+ end
+ -- If no message-id present return
+ local msg_id = task:get_header_raw('message-id')
+ if msg_id == nil then
+ return
+ end
+ -- Create hash of message-id and store to redis
+ local key = make_key(msg_id)
+ local upstream = upstreams:get_upstream_by_hash(key)
+ local addr = upstream:get_addr()
+ if not addr then
+ rspamd_logger.errx("couldn't get address for upstream")
+ return
+ end
+ if not rspamd_redis.make_request({task = task, host = addr, callback = redis_set_cb,
+ cmd = 'SET', args = {key, 1, "ex", settings['expire']}}) then
+ rspamd_logger.errx("redis request wasn't scheduled")
+ end
+end
+
+local opts = rspamd_config:get_all_opt('replies')
+if opts then
+ if not opts['servers'] then
+ rspamd_logger.infox(rspamd_config, 'no servers are specified, disabling module')
+ else
+ upstreams = upstream_list.create(rspamd_config, opts['servers'], default_port)
+ if not upstreams then
+ rspamd_logger.infox(rspamd_config, 'no servers are specified, disabling module')
+ else
+ rspamd_config:register_pre_filter(replies_check)
+ rspamd_config:register_post_filter(replies_set, 10)
+ end
+ end
+
+ for k,v in pairs(opts) do
+ settings[k] = v
+ end
+end