Bladeren bron

[Project] Rbl: Move config code outside of the plugin

tags/2.7
Vsevolod Stakhov 3 jaren geleden
bovenliggende
commit
3541f5d1fc
2 gewijzigde bestanden met toevoegingen van 190 en 99 verwijderingen
  1. 175
    0
      lualib/plugins/rbl.lua
  2. 15
    99
      src/plugins/lua/rbl.lua

+ 175
- 0
lualib/plugins/rbl.lua Bestand weergeven

--[[
Copyright (c) 2020, Vsevolod Stakhov <vsevolod@highsecure.ru>

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.
]]--

local ts = require("tableshape").types
local lua_maps = require "lua_maps"
local lua_util = require "lua_util"

-- Common RBL plugin definitions

local check_types = {
from = {
connfilter = true,
},
received = {},
helo = {
connfilter = true,
},
urls = {},
content_urls = {},
emails = {},
replyto = {},
dkim = {},
rdns = {
connfilter = true,
},
selector = {
require_argument = true,
},
}

local default_options = {
['default_enabled'] = true,
['default_ipv4'] = true,
['default_ipv6'] = true,
['default_unknown'] = false,
['default_dkim_domainonly'] = true,
['default_emails_domainonly'] = false,
['default_exclude_private_ips'] = true,
['default_exclude_users'] = false,
['default_exclude_local'] = true,
['default_no_ip'] = false,
['default_dkim_match_from'] = false,
}

local return_codes_schema = ts.map_of(
ts.string / string.upper, -- Symbol name
(
ts.array_of(ts.string) +
(ts.string / function(s)
return { s }
end) -- List of IP patterns
)
)
local return_bits_schema = ts.map_of(
ts.string / string.upper, -- Symbol name
(
ts.array_of(ts.number + ts.string / tonumber) +
(ts.string / function(s)
return { tonumber(s) }
end) +
(ts.number / function(s)
return { s }
end)
)
)

local rule_schema_tbl = {
content_urls = ts.boolean:is_optional(),
disable_monitoring = ts.boolean:is_optional(),
disabled = ts.boolean:is_optional(),
dkim = ts.boolean:is_optional(),
dkim_domainonly = ts.boolean:is_optional(),
dkim_match_from = ts.boolean:is_optional(),
emails = ts.boolean:is_optional(),
emails_delimiter = ts.string:is_optional(),
emails_domainonly = ts.boolean:is_optional(),
enabled = ts.boolean:is_optional(),
exclude_local = ts.boolean:is_optional(),
exclude_private_ips = ts.boolean:is_optional(),
exclude_users = ts.boolean:is_optional(),
from = ts.boolean:is_optional(),
hash = ts.one_of{"sha1", "sha256", "sha384", "sha512", "md5", "blake2"}:is_optional(),
hash_format = ts.one_of{"hex", "base32", "base64"}:is_optional(),
hash_len = (ts.integer + ts.string / tonumber):is_optional(),
helo = ts.boolean:is_optional(),
ignore_default = ts.boolean:is_optional(), -- alias
ignore_defaults = ts.boolean:is_optional(),
ignore_whitelist = ts.boolean:is_optional(),
ignore_whitelists = ts.boolean:is_optional(), -- alias
images = ts.boolean:is_optional(),
ipv4 = ts.boolean:is_optional(),
ipv6 = ts.boolean:is_optional(),
is_whitelist = ts.boolean:is_optional(),
local_exclude_ip_map = ts.string:is_optional(),
monitored_address = ts.string:is_optional(),
no_ip = ts.boolean:is_optional(),
process_script = ts.string:is_optional(),
rbl = ts.string,
rdns = ts.boolean:is_optional(),
received = ts.boolean:is_optional(),
replyto = ts.boolean:is_optional(),
requests_limit = (ts.integer + ts.string / tonumber):is_optional(),
resolve_ip = ts.boolean:is_optional(),
return_bits = return_bits_schema:is_optional(),
return_codes = return_codes_schema:is_optional(),
returnbits = return_bits_schema:is_optional(),
returncodes = return_codes_schema:is_optional(),
selector = ts.one_of{ts.string, ts.table}:is_optional(),
symbol = ts.string:is_optional(),
symbols_prefixes = ts.map_of(ts.string, ts.string):is_optional(),
unknown = ts.boolean:is_optional(),
url_compose_map = lua_maps.map_schema:is_optional(),
urls = ts.boolean:is_optional(),
whitelist = lua_maps.map_schema:is_optional(),
whitelist_exception = (
ts.array_of(ts.string) + (ts.string / function(s) return {s} end)
):is_optional(),
checks = ts.array_of(ts.one_of(lua_util.keys(check_types))):is_optional(),
}

local function convert_checks(rule)
local rspamd_logger = require "rspamd_logger"
if rule.checks then
local all_connfilter = true
for _,check in ipairs(rule.checks) do
local check_type = check_types[check]
if check_type.require_argument then
if not rule[check] then
rspamd_logger.errx(rspamd_config, 'rbl rule %s has check %s which requires an argument',
rule.symbol, check)
return nil
else
rule[check] = check_type
end
end
if not check_type.connfilter then
all_connfilter = false
end
if not check_type then
rspamd_logger.errx(rspamd_config, 'rbl rule %s has invalid check type: %s',
rule.symbol, check)
return nil
end
end
rule.connfilter = all_connfilter
end

return rule
end


-- Add default boolean flags to the schema
for def_k,_ in pairs(default_options) do
rule_schema_tbl[def_k:sub(#('default_') + 1)] = ts.boolean:is_optional()
end

return {
check_types = check_types,
rule_schema = ts.shape(rule_schema_tbl),
default_options = default_options,
convert_checks = convert_checks,
}

+ 15
- 99
src/plugins/lua/rbl.lua Bestand weergeven

--[[ --[[
Copyright (c) 2011-2015, Vsevolod Stakhov <vsevolod@highsecure.ru>
Copyright (c) 2011-2020, Vsevolod Stakhov <vsevolod@highsecure.ru>
Copyright (c) 2013-2015, Andrew Lewis <nerf@judo.za.org> Copyright (c) 2013-2015, Andrew Lewis <nerf@judo.za.org>


Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
local rspamd_util = require 'rspamd_util' local rspamd_util = require 'rspamd_util'
local fun = require 'fun' local fun = require 'fun'
local lua_util = require 'lua_util' local lua_util = require 'lua_util'
local ts = require("tableshape").types
local selectors = require "lua_selectors" local selectors = require "lua_selectors"
local bit = require 'bit' local bit = require 'bit'
local lua_maps = require "lua_maps" local lua_maps = require "lua_maps"
local rbl_common = require "plugins/rbl"


-- This plugin implements various types of RBL checks -- This plugin implements various types of RBL checks
-- Documentation can be found here: -- Documentation can be found here:
local E = {} local E = {}
local N = 'rbl' local N = 'rbl'


-- Checks that could be performed by rbl module
local local_exclusions local local_exclusions
local white_symbols = {} local white_symbols = {}
local black_symbols = {} local black_symbols = {}


-- Plugin defaults should not be changed - override these in config -- Plugin defaults should not be changed - override these in config
-- New defaults should not alter behaviour -- New defaults should not alter behaviour
local default_options = {
['default_enabled'] = true,
['default_ipv4'] = true,
['default_ipv6'] = true,
['default_unknown'] = false,
['default_dkim_domainonly'] = true,
['default_emails_domainonly'] = false,
['default_exclude_private_ips'] = true,
['default_exclude_users'] = false,
['default_exclude_local'] = true,
['default_no_ip'] = false,
['default_dkim_match_from'] = false,
}


opts = lua_util.override_defaults(default_options, opts)

opts = lua_util.override_defaults(rbl_common.default_options, opts)


if(opts['local_exclude_ip_map'] ~= nil) then if(opts['local_exclude_ip_map'] ~= nil) then
local_exclusions = lua_maps.map_add(N, 'local_exclude_ip_map', 'radix', local_exclusions = lua_maps.map_add(N, 'local_exclude_ip_map', 'radix',
'RBL exclusions map') 'RBL exclusions map')
end end


local return_codes_schema = ts.map_of(
ts.string / string.upper, -- Symbol name
(
ts.array_of(ts.string) +
(ts.string / function(s)
return { s }
end) -- List of IP patterns
)
)
local return_bits_schema = ts.map_of(
ts.string / string.upper, -- Symbol name
(
ts.array_of(ts.number + ts.string / tonumber) +
(ts.string / function(s)
return { tonumber(s) }
end) +
(ts.number / function(s)
return { s }
end)
)
)

local rule_schema_tbl = {
content_urls = ts.boolean:is_optional(),
disable_monitoring = ts.boolean:is_optional(),
disabled = ts.boolean:is_optional(),
dkim = ts.boolean:is_optional(),
dkim_domainonly = ts.boolean:is_optional(),
dkim_match_from = ts.boolean:is_optional(),
emails = ts.boolean:is_optional(),
emails_delimiter = ts.string:is_optional(),
emails_domainonly = ts.boolean:is_optional(),
enabled = ts.boolean:is_optional(),
exclude_local = ts.boolean:is_optional(),
exclude_private_ips = ts.boolean:is_optional(),
exclude_users = ts.boolean:is_optional(),
from = ts.boolean:is_optional(),
hash = ts.one_of{"sha1", "sha256", "sha384", "sha512", "md5", "blake2"}:is_optional(),
hash_format = ts.one_of{"hex", "base32", "base64"}:is_optional(),
hash_len = (ts.integer + ts.string / tonumber):is_optional(),
helo = ts.boolean:is_optional(),
ignore_default = ts.boolean:is_optional(), -- alias
ignore_defaults = ts.boolean:is_optional(),
ignore_whitelist = ts.boolean:is_optional(),
ignore_whitelists = ts.boolean:is_optional(), -- alias
images = ts.boolean:is_optional(),
ipv4 = ts.boolean:is_optional(),
ipv6 = ts.boolean:is_optional(),
is_whitelist = ts.boolean:is_optional(),
local_exclude_ip_map = ts.string:is_optional(),
monitored_address = ts.string:is_optional(),
no_ip = ts.boolean:is_optional(),
process_script = ts.string:is_optional(),
rbl = ts.string,
rdns = ts.boolean:is_optional(),
received = ts.boolean:is_optional(),
replyto = ts.boolean:is_optional(),
requests_limit = (ts.integer + ts.string / tonumber):is_optional(),
resolve_ip = ts.boolean:is_optional(),
return_bits = return_bits_schema:is_optional(),
return_codes = return_codes_schema:is_optional(),
returnbits = return_bits_schema:is_optional(),
returncodes = return_codes_schema:is_optional(),
selector = ts.one_of{ts.string, ts.table}:is_optional(),
symbol = ts.string:is_optional(),
symbols_prefixes = ts.map_of(ts.string, ts.string):is_optional(),
unknown = ts.boolean:is_optional(),
url_compose_map = lua_maps.map_schema:is_optional(),
urls = ts.boolean:is_optional(),
whitelist = lua_maps.map_schema:is_optional(),
whitelist_exception = (
ts.array_of(ts.string) + (ts.string / function(s) return {s} end)
):is_optional(),
}
for def_k,_ in pairs(default_options) do
rule_schema_tbl[def_k:sub(#('default_') + 1)] = ts.boolean:is_optional()
end

local rule_schema = ts.shape(rule_schema_tbl)

for key,rbl in pairs(opts.rbls or opts.rules) do for key,rbl in pairs(opts.rbls or opts.rules) do
if type(rbl) ~= 'table' or rbl.disabled == true or rbl.enabled == false then if type(rbl) ~= 'table' or rbl.disabled == true or rbl.enabled == false then
rspamd_logger.infox(rspamd_config, 'disable rbl "%s"', key) rspamd_logger.infox(rspamd_config, 'disable rbl "%s"', key)
end end
-- Propagate default options from opts to rule -- Propagate default options from opts to rule
if not rbl.ignore_defaults then if not rbl.ignore_defaults then
for default_opt_key,_ in pairs(default_options) do
for default_opt_key,_ in pairs(rbl_common.default_options) do
local rbl_opt = default_opt_key:sub(#('default_') + 1) local rbl_opt = default_opt_key:sub(#('default_') + 1)
if rbl[rbl_opt] == nil then if rbl[rbl_opt] == nil then
rbl[rbl_opt] = opts[default_opt_key] rbl[rbl_opt] = opts[default_opt_key]
rbl.requests_limit = rspamd_config:get_dns_max_requests() rbl.requests_limit = rspamd_config:get_dns_max_requests()
end end


local res,err = rule_schema:transform(rbl)
local res,err = rbl_common.rule_schema:transform(rbl)
if not res then if not res then
rspamd_logger.errx(rspamd_config, 'invalid config for %s: %s, RBL is DISABLED', rspamd_logger.errx(rspamd_config, 'invalid config for %s: %s, RBL is DISABLED',
key, err) key, err)
else else
res = rbl_common.convert_checks(res)
-- Aliases -- Aliases
if res.return_codes then res.returncodes = res.return_codes end if res.return_codes then res.returncodes = res.return_codes end
if res.return_bits then res.returnbits = res.return_bits end if res.return_bits then res.returnbits = res.return_bits end
add_rbl(key, res, opts)

if not res then
rspamd_logger.errx(rspamd_config, 'invalid config for %s: %s, RBL is DISABLED',
key, err)
else
add_rbl(key, res, opts)
end
end end
end -- rbl.enabled end -- rbl.enabled
end end

Laden…
Annuleren
Opslaan