@@ -0,0 +1,175 @@ | |||
--[[ | |||
Copyright (c) 2016, Andrew Lewis <nerf@judo.za.org> | |||
Copyright (c) 2017, 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 exports = {} | |||
local rspamd_logger = require "rspamd_logger" | |||
local rspamd_util = require "rspamd_util" | |||
local function prepare_dkim_signing(N, task, settings) | |||
local is_local, is_sign_networks | |||
local auser = task:get_user() | |||
local ip = task:get_from_ip() | |||
if ip and ip:is_local() then | |||
is_local = true | |||
end | |||
if settings.auth_only and not auser then | |||
if (settings.sign_networks and settings.sign_networks:get_key(ip)) then | |||
is_sign_networks = true | |||
rspamd_logger.debugm(N, task, 'mail is from address in sign_networks') | |||
elseif settings.sign_local and is_local then | |||
rspamd_logger.debugm(N, task, 'mail is from local address') | |||
else | |||
rspamd_logger.debugm(N, task, 'ignoring unauthenticated mail') | |||
return false,{} | |||
end | |||
end | |||
local efrom = task:get_from('smtp') | |||
if not settings.allow_envfrom_empty and | |||
#(((efrom or E)[1] or E).addr or '') == 0 then | |||
rspamd_logger.debugm(N, task, 'empty envelope from not allowed') | |||
return false,{} | |||
end | |||
local hfrom = task:get_from('mime') | |||
if not settings.allow_hdrfrom_multiple and (hfrom or E)[2] then | |||
rspamd_logger.debugm(N, task, 'multiple header from not allowed') | |||
return false,{} | |||
end | |||
local dkim_domain | |||
local hdom = ((hfrom or E)[1] or E).domain | |||
local edom = ((efrom or E)[1] or E).domain | |||
local udom = string.match(auser or '', '.*@(.*)') | |||
local function get_dkim_domain(type) | |||
if settings[type] == 'header' then | |||
return hdom | |||
elseif settings[type] == 'envelope' then | |||
return edom | |||
elseif settings[type] == 'auth' then | |||
return udom | |||
end | |||
end | |||
if hdom then | |||
hdom = hdom:lower() | |||
end | |||
if edom then | |||
edom = edom:lower() | |||
end | |||
if udom then | |||
udom = udom:lower() | |||
end | |||
if settings.use_domain_sign_networks and is_sign_networks then | |||
dkim_domain = get_dkim_domain('use_domain_sign_networks') | |||
elseif settings.use_domain_local and is_local then | |||
dkim_domain = get_dkim_domain('use_domain_local') | |||
else | |||
dkim_domain = get_dkim_domain('use_domain') | |||
end | |||
if not dkim_domain then | |||
rspamd_logger.debugm(N, task, 'could not extract dkim domain') | |||
return false,{} | |||
else | |||
rspamd_logger.debugm(N, task, 'use domain(%s) for sugnature: %s', | |||
settings.use_domain, dkim_domain) | |||
end | |||
if settings.use_esld then | |||
dkim_domain = rspamd_util.get_tld(dkim_domain) | |||
if settings.use_domain == 'envelope' and hdom then | |||
hdom = rspamd_util.get_tld(hdom) | |||
elseif settings.use_domain == 'header' and edom then | |||
edom = rspamd_util.get_tld(edom) | |||
end | |||
end | |||
if edom and hdom and not settings.allow_hdrfrom_mismatch and hdom ~= edom then | |||
if settings.allow_hdrfrom_mismatch_local and is_local then | |||
rspamd_logger.debugm(N, task, 'domain mismatch allowed for local IP: %1 != %2', hdom, edom) | |||
elseif settings.allow_hdrfrom_mismatch_sign_networks and is_sign_networks then | |||
rspamd_logger.debugm(N, task, 'domain mismatch allowed for sign_networks: %1 != %2', hdom, edom) | |||
else | |||
rspamd_logger.debugm(N, task, 'domain mismatch not allowed: %1 != %2', hdom, edom) | |||
return false,{} | |||
end | |||
end | |||
if auser and not settings.allow_username_mismatch then | |||
if not udom then | |||
rspamd_logger.debugm(N, task, 'couldnt find domain in username') | |||
return false,{} | |||
end | |||
if settings.use_esld then | |||
udom = rspamd_util.get_tld(udom) | |||
end | |||
if udom ~= dkim_domain then | |||
rspamd_logger.debugm(N, task, 'user domain mismatch') | |||
return false,{} | |||
end | |||
end | |||
local p = {} | |||
if settings.domain[dkim_domain] then | |||
p.selector = settings.domain[dkim_domain].selector | |||
p.key = settings.domain[dkim_domain].path | |||
end | |||
if not (p.key and p.selector) and not | |||
(settings.try_fallback or settings.use_redis or settings.selector_map or settings.path_map) then | |||
rspamd_logger.debugm(N, task, 'dkim unconfigured and fallback disabled') | |||
return false,{} | |||
end | |||
if not p.key then | |||
if not settings.use_redis then | |||
p.key = settings.path | |||
end | |||
end | |||
if not p.selector then | |||
p.selector = settings.selector | |||
end | |||
p.domain = dkim_domain | |||
if settings.selector_map then | |||
local data = settings.selector_map:get_key(dkim_domain) | |||
if data then | |||
p.selector = data | |||
end | |||
end | |||
if settings.path_map then | |||
local data = settings.path_map:get_key(dkim_domain) | |||
if data then | |||
p.key = data | |||
end | |||
end | |||
return true,p | |||
end | |||
exports.prepare_dkim_signing = prepare_dkim_signing | |||
return exports |
@@ -16,6 +16,7 @@ limitations under the License. | |||
local rspamd_logger = require "rspamd_logger" | |||
local lua_util = require "lua_util" | |||
local dkim_sign_tools = require "dkim_sign_tools" | |||
local rspamd_util = require "rspamd_util" | |||
local rspamd_rsa_privkey = require "rspamd_rsa_privkey" | |||
local rspamd_rsa = require "rspamd_rsa" | |||
@@ -418,150 +419,11 @@ end | |||
local function arc_signing_cb(task) | |||
local arc_sigs = task:cache_get('arc-sigs') | |||
local arc_seals = task:cache_get('arc-seals') | |||
local is_local, is_sign_networks | |||
local auser = task:get_user() | |||
local ip = task:get_from_ip() | |||
if ip and ip:is_local() then | |||
is_local = true | |||
end | |||
if settings.auth_only and not auser then | |||
if (settings.sign_networks and settings.sign_networks:get_key(ip)) then | |||
is_sign_networks = true | |||
rspamd_logger.debugm(N, task, 'mail is from address in sign_networks') | |||
elseif settings.sign_local and is_local then | |||
rspamd_logger.debugm(N, task, 'mail is from local address') | |||
else | |||
rspamd_logger.debugm(N, task, 'ignoring unauthenticated mail') | |||
return | |||
end | |||
end | |||
local efrom = task:get_from('smtp') | |||
if not settings.allow_envfrom_empty and | |||
#(((efrom or E)[1] or E).addr or '') == 0 then | |||
rspamd_logger.debugm(N, task, 'empty envelope from not allowed') | |||
return false | |||
end | |||
local hfrom = task:get_from('mime') | |||
if not settings.allow_hdrfrom_multiple and (hfrom or E)[2] then | |||
rspamd_logger.debugm(N, task, 'multiple header from not allowed') | |||
return false | |||
end | |||
local dkim_domain | |||
local hdom = ((hfrom or E)[1] or E).domain | |||
local edom = ((efrom or E)[1] or E).domain | |||
local udom = string.match(auser or '', '.*@(.*)') | |||
local function get_dkim_domain(type) | |||
if settings[type] == 'header' then | |||
return hdom | |||
elseif settings[type] == 'envelope' then | |||
return edom | |||
elseif settings[type] == 'auth' then | |||
return udom | |||
end | |||
end | |||
if hdom then | |||
hdom = hdom:lower() | |||
end | |||
if edom then | |||
edom = edom:lower() | |||
end | |||
if udom then | |||
udom = udom:lower() | |||
end | |||
if settings.use_domain_sign_networks and is_sign_networks then | |||
dkim_domain = get_dkim_domain('use_domain_sign_networks') | |||
elseif settings.use_domain_local and is_local then | |||
dkim_domain = get_dkim_domain('use_domain_local') | |||
else | |||
dkim_domain = get_dkim_domain('use_domain') | |||
end | |||
if not dkim_domain then | |||
rspamd_logger.debugm(N, task, 'could not extract dkim domain') | |||
return false | |||
else | |||
rspamd_logger.debugm(N, task, 'use domain(%s) for sugnature: %s', | |||
settings.use_domain, dkim_domain) | |||
end | |||
if settings.use_esld then | |||
dkim_domain = rspamd_util.get_tld(dkim_domain) | |||
if settings.use_domain == 'envelope' and hdom then | |||
hdom = rspamd_util.get_tld(hdom) | |||
elseif settings.use_domain == 'header' and edom then | |||
edom = rspamd_util.get_tld(edom) | |||
end | |||
end | |||
if edom and hdom and not settings.allow_hdrfrom_mismatch and hdom ~= edom then | |||
if settings.allow_hdrfrom_mismatch_local and is_local then | |||
rspamd_logger.debugm(N, task, 'domain mismatch allowed for local IP: %1 != %2', hdom, edom) | |||
elseif settings.allow_hdrfrom_mismatch_sign_networks and is_sign_networks then | |||
rspamd_logger.debugm(N, task, 'domain mismatch allowed for sign_networks: %1 != %2', hdom, edom) | |||
else | |||
rspamd_logger.debugm(N, task, 'domain mismatch not allowed: %1 != %2', hdom, edom) | |||
return false | |||
end | |||
end | |||
if auser and not settings.allow_username_mismatch then | |||
if not udom then | |||
rspamd_logger.debugm(N, task, 'couldnt find domain in username') | |||
return false | |||
end | |||
if settings.use_esld then | |||
udom = rspamd_util.get_tld(udom) | |||
end | |||
if udom ~= dkim_domain then | |||
rspamd_logger.debugm(N, task, 'user domain mismatch') | |||
return false | |||
end | |||
end | |||
local p = {} | |||
if settings.domain[dkim_domain] then | |||
p.selector = settings.domain[dkim_domain].selector | |||
p.key = settings.domain[dkim_domain].path | |||
end | |||
if not (p.key and p.selector) and not | |||
(settings.try_fallback or settings.use_redis or settings.selector_map or settings.path_map) then | |||
rspamd_logger.debugm(N, task, 'dkim unconfigured and fallback disabled') | |||
return false | |||
end | |||
local ret,p = dkim_sign_tools.prepare_dkim_signing(N, task, settings) | |||
if not p.key then | |||
if not settings.use_redis then | |||
p.key = settings.path | |||
end | |||
end | |||
if not p.selector then | |||
p.selector = settings.selector | |||
end | |||
p.domain = dkim_domain | |||
if settings.selector_map then | |||
local data = settings.selector_map:get_key(dkim_domain) | |||
if data then | |||
p.selector = data | |||
end | |||
end | |||
if settings.path_map then | |||
local data = settings.path_map:get_key(dkim_domain) | |||
if data then | |||
p.key = data | |||
end | |||
if not ret then | |||
return | |||
end | |||
p.arc_cv = 'none' |
@@ -16,7 +16,7 @@ limitations under the License. | |||
]]-- | |||
local rspamd_logger = require "rspamd_logger" | |||
local rspamd_util = require "rspamd_util" | |||
local dkim_sign_tools = require "dkim_sign_tools" | |||
if confighelp then | |||
return | |||
@@ -60,129 +60,10 @@ local function simple_template(tmpl, keys) | |||
end | |||
local function dkim_signing_cb(task) | |||
local is_local, is_sign_networks | |||
local auser = task:get_user() | |||
local ip = task:get_from_ip() | |||
if ip and ip:is_local() then | |||
is_local = true | |||
end | |||
if settings.auth_only and not auser then | |||
if (settings.sign_networks and settings.sign_networks:get_key(ip)) then | |||
is_sign_networks = true | |||
rspamd_logger.debugm(N, task, 'mail is from address in sign_networks') | |||
elseif settings.sign_local and is_local then | |||
rspamd_logger.debugm(N, task, 'mail is from local address') | |||
else | |||
rspamd_logger.debugm(N, task, 'ignoring unauthenticated mail') | |||
return | |||
end | |||
end | |||
local efrom = task:get_from('smtp') | |||
if not settings.allow_envfrom_empty and | |||
#(((efrom or E)[1] or E).addr or '') == 0 then | |||
rspamd_logger.debugm(N, task, 'empty envelope from not allowed') | |||
return false | |||
end | |||
local hfrom = task:get_from('mime') | |||
if not settings.allow_hdrfrom_multiple and (hfrom or E)[2] then | |||
rspamd_logger.debugm(N, task, 'multiple header from not allowed') | |||
return false | |||
end | |||
local dkim_domain | |||
local hdom = ((hfrom or E)[1] or E).domain | |||
local edom = ((efrom or E)[1] or E).domain | |||
if hdom then | |||
hdom = hdom:lower() | |||
end | |||
if edom then | |||
edom = edom:lower() | |||
end | |||
if settings.use_domain_sign_networks and is_sign_networks then | |||
if settings.use_domain_sign_networks == 'header' then | |||
dkim_domain = hdom | |||
else | |||
dkim_domain = edom | |||
end | |||
elseif settings.use_domain_local and is_local then | |||
if settings.use_domain_local == 'header' then | |||
dkim_domain = hdom | |||
else | |||
dkim_domain = edom | |||
end | |||
else | |||
if settings.use_domain == 'header' then | |||
dkim_domain = hdom | |||
else | |||
dkim_domain = edom | |||
end | |||
end | |||
if not dkim_domain then | |||
rspamd_logger.debugm(N, task, 'could not extract dkim domain') | |||
return false | |||
end | |||
if settings.use_esld then | |||
dkim_domain = rspamd_util.get_tld(dkim_domain) | |||
if settings.use_domain == 'envelope' and hdom then | |||
hdom = rspamd_util.get_tld(hdom) | |||
elseif settings.use_domain == 'header' and edom then | |||
edom = rspamd_util.get_tld(edom) | |||
end | |||
end | |||
if edom and hdom and not settings.allow_hdrfrom_mismatch and hdom ~= edom then | |||
if settings.allow_hdrfrom_mismatch_local and is_local then | |||
rspamd_logger.debugm(N, task, 'domain mismatch allowed for local IP: %1 != %2', hdom, edom) | |||
elseif settings.allow_hdrfrom_mismatch_sign_networks and is_sign_networks then | |||
rspamd_logger.debugm(N, task, 'domain mismatch allowed for sign_networks: %1 != %2', hdom, edom) | |||
else | |||
rspamd_logger.debugm(N, task, 'domain mismatch not allowed: %1 != %2', hdom, edom) | |||
return false | |||
end | |||
end | |||
if auser and not settings.allow_username_mismatch then | |||
local udom = string.match(auser, '.*@(.*)') | |||
if not udom then | |||
rspamd_logger.debugm(N, task, 'couldnt find domain in username') | |||
return false | |||
end | |||
if settings.use_esld then | |||
udom = rspamd_util.get_tld(udom) | |||
end | |||
if udom ~= dkim_domain then | |||
rspamd_logger.debugm(N, task, 'user domain mismatch') | |||
return false | |||
end | |||
end | |||
local p = {} | |||
if settings.domain[dkim_domain] then | |||
p.selector = settings.domain[dkim_domain].selector | |||
p.key = settings.domain[dkim_domain].path | |||
end | |||
if not (p.key and p.selector) and not | |||
(settings.try_fallback or settings.use_redis or settings.selector_map or settings.path_map) then | |||
rspamd_logger.debugm(N, task, 'dkim unconfigured and fallback disabled') | |||
return false | |||
end | |||
if not p.key then | |||
if not settings.use_redis then | |||
p.key = settings.path | |||
end | |||
end | |||
if not p.selector then | |||
p.selector = settings.selector | |||
end | |||
p.domain = dkim_domain | |||
local ret,p = dkim_sign_tools.prepare_dkim_signing(N, task, settings) | |||
if settings.selector_map then | |||
local data = settings.selector_map:get_key(dkim_domain) | |||
if data then | |||
p.selector = data | |||
end | |||
end | |||
if settings.path_map then | |||
local data = settings.path_map:get_key(dkim_domain) | |||
if data then | |||
p.key = data | |||
end | |||
if not ret then | |||
return | |||
end | |||
if settings.use_redis then |