From 84d6c763cff06ad975b343bed281763273e5e0a6 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sat, 20 May 2017 13:42:21 +0100 Subject: [PATCH] [Rework] Move authentication results generation to a separate routine --- lualib/auth_results.lua | 151 ++++++++++++++++++++++++++++ src/plugins/lua/rmilter_headers.lua | 114 ++++----------------- 2 files changed, 172 insertions(+), 93 deletions(-) create mode 100644 lualib/auth_results.lua diff --git a/lualib/auth_results.lua b/lualib/auth_results.lua new file mode 100644 index 000000000..621141b5d --- /dev/null +++ b/lualib/auth_results.lua @@ -0,0 +1,151 @@ +--[[ +Copyright (c) 2016, Andrew Lewis +Copyright (c) 2017, Vsevolod Stakhov + +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 global = require "global_functions" + +local default_settings = { + spf_symbols = { + pass = 'R_SPF_ALLOW', + fail = 'R_SPF_FAIL', + softfail = 'R_SPF_SOFTFAIL', + neutral = 'R_SPF_NEUTRAL', + temperror = 'R_SPF_DNSFAIL', + none = 'R_SPF_NA', + permerror = 'R_SPF_PERMFAIL', + }, + dkim_symbols = { + pass = 'R_DKIM_ALLOW', + fail = 'R_DKIM_REJECT', + temperror = 'R_DKIM_TEMPFAIL', + none = 'R_DKIM_NA', + permerror = 'R_DKIM_PERMFAIL', + }, + dmarc_symbols = { + pass = 'DMARC_POLICY_ALLOW', + permerror = 'DMARC_BAD_POLICY', + temperror = 'DMARC_DNSFAIL', + none = 'DMARC_NA', + reject = 'DMARC_POLICY_REJECT', + softfail = 'DMARC_POLICY_SOFTFAIL', + quarantine = 'DMARC_POLICY_QUARANTINE', + }, +} + +local exports = {} + +local function gen_auth_results(task, settings) + local table = table + local pairs = pairs + local ipairs = ipairs + local auth_results, hdr_parts = {}, {} + + if not settings then + settings = default_settings + end + + local auth_types = { + dkim = settings.routines['authentication-results'].dkim_symbols, + dmarc = settings.routines['authentication-results'].dmarc_symbols, + spf = settings.routines['authentication-results'].spf_symbols, + } + + local common = { + symbols = {} + } + + for auth_type, symbols in pairs(auth_types) do + for key, sym in pairs(symbols) do + if not common.symbols.sym then + local s = task:get_symbol(sym) + if not s then + common.symbols[sym] = false + else + common.symbols[sym] = s + if not auth_results[auth_type] then + auth_results[auth_type] = {key} + else + table.insert(auth_results[auth_type], key) + end + + if auth_type ~= 'dkim' then + break + end + end + end + end + end + + for auth_type, keys in pairs(auth_results) do + for _, key in ipairs(keys) do + local hdr = '' + if auth_type == 'dmarc' and key ~= 'none' then + hdr = hdr .. 'dmarc=' + if key == 'reject' or key == 'quarantine' or key == 'softfail' then + hdr = hdr .. 'fail' + else + hdr = hdr .. key + end + if key == 'pass' then + hdr = hdr .. ' policy=' .. common.symbols[auth_types['dmarc'][key]][1]['options'][2] + hdr = hdr .. ' header.from=' .. common.symbols[auth_types['dmarc'][key]][1]['options'][1] + elseif key ~= 'none' then + local t = global.rspamd_str_split(common.symbols[auth_types['dmarc'][key]][1]['options'][1], ' : ') + local dom = t[1] + local rsn = t[2] + if rsn then + hdr = hdr .. ' reason="' .. rsn .. '"' + end + hdr = hdr .. ' header.from=' .. dom + if key == 'softfail' then + hdr = hdr .. ' policy=none' + else + hdr = hdr .. ' policy=' .. key + end + end + table.insert(hdr_parts, hdr) + elseif auth_type == 'dkim' and key ~= 'none' then + if common.symbols[auth_types['dkim'][key]][1] then + for _, v in ipairs(common.symbols[auth_types['dkim'][key]][1]['options']) do + hdr = hdr .. auth_type .. '=' .. key .. ' header.d=' .. v + table.insert(hdr_parts, hdr) + end + end + elseif auth_type == 'spf' and key ~= 'none' then + hdr = hdr .. auth_type .. '=' .. key + local smtp_from = task:get_from('smtp') + if smtp_from['addr'] ~= '' and smtp_from['addr'] ~= nil then + hdr = hdr .. ' smtp.mailfrom=' .. smtp_from['addr'] + else + local helo = task:get_helo() + if helo then + hdr = hdr .. ' smtp.helo=' .. task:get_helo() + end + end + table.insert(hdr_parts, hdr) + end + end + end + if #hdr_parts > 0 then + return table.concat(hdr_parts, '; ') + end + + return nil +end + +exports.gen_auth_results = gen_auth_results + +return exports \ No newline at end of file diff --git a/src/plugins/lua/rmilter_headers.lua b/src/plugins/lua/rmilter_headers.lua index 3221aa496..ca5571636 100644 --- a/src/plugins/lua/rmilter_headers.lua +++ b/src/plugins/lua/rmilter_headers.lua @@ -150,17 +150,17 @@ local function rmilter_headers(task) local virii = {} for _, sym in ipairs(settings.routines['x-virus'].symbols) do if not (common.symbols[sym] == false) then - local s = task:get_symbol(sym) - if not s then - common.symbols[sym] = false - else - common.symbols[sym] = s - if (((s or E)[1] or E).options or E)[1] then - table.insert(virii, s[1].options[1]) - else - table.insert(virii, 'unknown') - end - end + local s = task:get_symbol(sym) + if not s then + common.symbols[sym] = false + else + common.symbols[sym] = s + if (((s or E)[1] or E).options or E)[1] then + table.insert(virii, s[1].options[1]) + else + table.insert(virii, 'unknown') + end + end end end if #virii > 0 then @@ -192,90 +192,18 @@ local function rmilter_headers(task) end routines['authentication-results'] = function() - local auth_results, hdr_parts = {}, {} - if not common.symbols then - common.symbols = {} - end - local auth_types = { - dkim = settings.routines['authentication-results'].dkim_symbols, - dmarc = settings.routines['authentication-results'].dmarc_symbols, - spf = settings.routines['authentication-results'].spf_symbols, - } - for auth_type, symbols in pairs(auth_types) do - for key, sym in pairs(symbols) do - if not (common.symbols[sym] == false) then - local s = task:get_symbol(sym) - if not s then - common.symbols[sym] = false - else - common.symbols[sym] = s - if not auth_results[auth_type] then - auth_results[auth_type] = {key} - else - table.insert(auth_results[auth_type], key) - end - if auth_type ~= 'dkim' then - break - end - end - end - end - end + local ar = require "auth_results" + if settings.routines['authentication-results'].remove then - remove[settings.routines['authentication-results'].header] = settings.routines['authentication-results'].remove + remove[settings.routines['authentication-results'].header] = + settings.routines['authentication-results'].remove end - for auth_type, keys in pairs(auth_results) do - for _, key in ipairs(keys) do - local hdr = '' - if auth_type == 'dmarc' and key ~= 'none' then - hdr = hdr .. 'dmarc=' - if key == 'reject' or key == 'quarantine' or key == 'softfail' then - hdr = hdr .. 'fail' - else - hdr = hdr .. key - end - if key == 'pass' then - hdr = hdr .. ' policy=' .. common.symbols[auth_types['dmarc'][key]][1]['options'][2] - hdr = hdr .. ' header.from=' .. common.symbols[auth_types['dmarc'][key]][1]['options'][1] - elseif key ~= 'none' then - local t = rspamd_str_split(common.symbols[auth_types['dmarc'][key]][1]['options'][1], ' : ') - local dom = t[1] - local rsn = t[2] - if rsn then - hdr = hdr .. ' reason="' .. rsn .. '"' - end - hdr = hdr .. ' header.from=' .. dom - if key == 'softfail' then - hdr = hdr .. ' policy=none' - else - hdr = hdr .. ' policy=' .. key - end - end - table.insert(hdr_parts, hdr) - elseif auth_type == 'dkim' and key ~= 'none' then - if common.symbols[auth_types['dkim'][key]][1] then - for _, v in ipairs(common.symbols[auth_types['dkim'][key]][1]['options']) do - hdr = hdr .. auth_type .. '=' .. key .. ' header.d=' .. v - table.insert(hdr_parts, hdr) - end - end - elseif auth_type == 'spf' and key ~= 'none' then - hdr = hdr .. auth_type .. '=' .. key - local smtp_from = task:get_from('smtp') - if smtp_from['addr'] ~= '' and smtp_from['addr'] ~= nil then - hdr = hdr .. ' smtp.mailfrom=' .. smtp_from['addr'] - else - local helo = task:get_helo() - if helo then - hdr = hdr .. ' smtp.helo=' .. task:get_helo() - end - end - table.insert(hdr_parts, hdr) - end - end - end - if #hdr_parts > 0 then - add[settings.routines['authentication-results'].header] = table.concat(hdr_parts, '; ') + + local res = ar.gen_auth_results(task, + settings.routines['authentication-results']) + + if res then + add[settings.routines['authentication-results'].header] = res end end -- 2.39.5