aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2015-09-14 22:12:04 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2015-09-14 22:12:04 +0100
commite9a993987839de1f012419c8f4c1211a5fa21477 (patch)
tree1cf77d9d32512e87934fbee1bd376c8cea61d55f /src
parent51e0796dcfb90c8431ee39b54448dcc8a591d535 (diff)
downloadrspamd-e9a993987839de1f012419c8f4c1211a5fa21477.tar.gz
rspamd-e9a993987839de1f012419c8f4c1211a5fa21477.zip
Add initial version of the whitelist plugin.
Diffstat (limited to 'src')
-rw-r--r--src/plugins/lua/whitelist.lua153
1 files changed, 153 insertions, 0 deletions
diff --git a/src/plugins/lua/whitelist.lua b/src/plugins/lua/whitelist.lua
new file mode 100644
index 000000000..f28e80018
--- /dev/null
+++ b/src/plugins/lua/whitelist.lua
@@ -0,0 +1,153 @@
+--[[
+Copyright (c) 2015, Vsevolod Stakhov <vsevolod@highsecure.ru>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+]]--
+
+local rspamd_logger = require "rspamd_logger"
+local ucl = require "ucl"
+require "fun" ()
+
+local options = {
+ dmarc_allow_symbol = 'DMARC_POLICY_ALLOW',
+ spf_allow_symbol = 'R_SPF_ALLOW',
+ dkim_allow_symbol = 'R_DKIM_ALLOW',
+
+ rules = {}
+}
+
+local function whitelist_cb(symbol, rule, task)
+ local from = task:get_from(1)
+ if from and from[1] and from[1]['domain'] then
+ local domain = from[1]['domain']
+ local found = false
+
+ if rule['map'] then
+ if rule['map']:get_key(domain) then
+ found = true
+ end
+ else
+ if rule['domains'][domain] then
+ found = true
+ end
+ end
+
+ if found then
+ if rule['valid_spf'] then
+ -- Check for spf symbol
+ if not task:get_symbol(options['spf_allow_symbol']) then
+ found = false
+ rspamd_logger.debugx(task, "domain %s has been found in whitelist %s" ..
+ "but it doesn't have valid SPF record", domain, symbol)
+ end
+ end
+ if rule['valid_dkim'] then
+ if not task:get_symbol(options['dkim_allow_symbol']) then
+ found = false
+ rspamd_logger.debugx(task, "domain %s has been found in whitelist %s" ..
+ "but it doesn't have valid DKIM", domain, symbol)
+ end
+ end
+ if rule['valid_dmarc'] then
+ if not task:get_symbol(options['dmarc_allow_symbol']) then
+ found = false
+ rspamd_logger.debugx(task, "domain %s has been found in whitelist %s" ..
+ "but it doesn't have valid DMARC", domain, symbol)
+ end
+ end
+ end
+
+ if found then
+ task:insert_result(symbol, 1.0, domain)
+ end
+ end
+
+end
+
+local function gen_whitelist_cb(symbol, rule)
+ return function(task)
+ whitelist_cb(symbol, rule, task)
+ end
+end
+
+local function process_whitelist_map(input)
+ local parser = ucl.parser()
+ local res,err = parser:parse_string(string)
+ if not res then
+ rspamd_logger.warnx(rspamd_config, 'cannot parse settings map: ' .. err)
+ else
+ local obj = parser:get_object()
+
+ options['rules'] = obj
+ end
+end
+
+local configure_whitelist_module = function()
+ local opts = rspamd_config:get_all_opt('whitelist')
+ if opts then
+ for k,v in pairs(opts) do
+ options[k] = v
+ end
+ end
+
+ if options['rules'] then
+ each(function(symbol, rule)
+ if rule['domains'] then
+ if type(rule['domains']) == 'string' then
+ rule['map'] = rspamd_config:add_hash_map(rule['domains'])
+ elseif type(rule['domains']) == 'table' then
+ -- Transform ['domain1', 'domain2' ...] to indexes:
+ -- {'domain1' = 1, 'domain2' = 1 ...]
+ rule['domains'] = tomap(zip(rule['domains'], ones()))
+ else
+ rspamd_logger.errx(rspamd_config, 'whitelist %s has bad "domains" value',
+ symbol)
+ return
+ end
+
+ local id = rspamd_config:register_symbol(symbol, -1.0,
+ gen_whitelist_cb(symbol, rule))
+
+ if rule['valid_spf'] then
+ rspamd_config:register_dependency(id, options['spf_allow_symbol'])
+ end
+ if rule['valid_dkim'] then
+ rspamd_config:register_dependency(id, options['dkim_allow_symbol'])
+ end
+ if rule['valid_dmarc'] then
+ rspamd_config:register_dependency(id, options['dmarc_allow_symbol'])
+ end
+
+ if rule['score'] then
+ if not rule['group'] then
+ rule['group'] = 'whitelist'
+ end
+ rule['name'] = symbol
+ rspamd_config:set_metric_symbol(rule)
+ end
+ end
+ end, options['rules'])
+ end
+end
+
+configure_whitelist_module() \ No newline at end of file