From 709655fd55ea787f3aafdb10d991c0a0f9c52890 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 14 Aug 2018 17:19:58 +0100 Subject: [PATCH] [Feature] Allow to get dkim signing data directly from HTTP headers --- lualib/lua_dkim_tools.lua | 50 ++++++++++++++++++++++++++++++++ src/plugins/lua/arc.lua | 24 +++++++++------ src/plugins/lua/dkim_signing.lua | 30 +++++++++++-------- 3 files changed, 83 insertions(+), 21 deletions(-) diff --git a/lualib/lua_dkim_tools.lua b/lualib/lua_dkim_tools.lua index 832e8a3ea..5ea3f68bf 100644 --- a/lualib/lua_dkim_tools.lua +++ b/lualib/lua_dkim_tools.lua @@ -21,8 +21,58 @@ local E = {} local lua_util = require "lua_util" local rspamd_util = require "rspamd_util" +local function parse_dkim_http_headers(N, task, settings) + local logger = require "rspamd_logger" + -- Configure headers + local headers = { + sign_header = settings.http_sign_header or "PerformDkimSign", + sign_on_reject_header = settings.http_sign_on_reject_header_header or 'SignOnAuthFailed', + domain_header = settings.http_domain_header or 'DkimDomain', + selector_header = settings.http_selector_header or 'DkimSelector', + key_header = settings.http_key_header or 'DkimPrivateKey' + } + + if task:get_request_header(headers.sign_header) then + local domain = task:get_request_header(headers.domain_header) + local selector = task:get_request_header(headers.selector_header) + local key = task:get_request_header(headers.key_header) + + if not (domain and selector and key) then + + logger.errx(task, 'missing required headers to sign email') + return false,{} + end + + -- Now check if we need to check the existing auth + local hdr = task:get_request_header(headers.sign_on_reject_header) + if not hdr then + -- Check for DKIM_REJECT + if task:has_symbol('R_DKIM_REJECT') then + local sym = task:get_symbol('R_DKIM_REJECT') + logger.infox(task, 'skip signing for %s:%s: R_DKIM_REJECT found: %s', + domain, selector, sym.options) + return false,{} + end + end + + return true,{ + rawkey = key, + domain = domain, + selector = selector + } + end + + lua_util.debugm(N, task, 'no sign header %s', headers.sign_header) + return false,{} +end + local function prepare_dkim_signing(N, task, settings) local is_local, is_sign_networks + + if settings.use_http_headers then + return parse_dkim_http_headers(N, task, settings) + end + local auser = task:get_user() local ip = task:get_from_ip() diff --git a/src/plugins/lua/arc.lua b/src/plugins/lua/arc.lua index ef6a11e71..30ae0cd19 100644 --- a/src/plugins/lua/arc.lua +++ b/src/plugins/lua/arc.lua @@ -549,16 +549,22 @@ local function arc_signing_cb(task) try_redis_key(p.selector) end else - if (p.key and p.selector) then - p.key = lua_util.template(p.key, {domain = p.domain, selector = p.selector}) - local exists,err = rspamd_util.file_exists(p.key) - if not exists then - if err and err == 'No such file or directory' then - lua_util.debugm(N, task, 'cannot read key from %s: %s', p.key, err) - else - rspamd_logger.warnx(N, task, 'cannot read key from %s: %s', p.key, err) + if ((p.key or p.rawkey) and p.selector) then + if p.key then + p.key = lua_util.template(p.key, { + domain = p.domain, + selector = p.selector + }) + + local exists,err = rspamd_util.file_exists(p.key) + if not exists then + if err and err == 'No such file or directory' then + lua_util.debugm(N, task, 'cannot read key from %s: %s', p.key, err) + else + rspamd_logger.warnx(N, task, 'cannot read key from %s: %s', p.key, err) + end + return false end - return false end local dret, hdr = dkim_sign(task, p) diff --git a/src/plugins/lua/dkim_signing.lua b/src/plugins/lua/dkim_signing.lua index 343fb8a84..99e1fca68 100644 --- a/src/plugins/lua/dkim_signing.lua +++ b/src/plugins/lua/dkim_signing.lua @@ -152,20 +152,26 @@ local function dkim_signing_cb(task) try_redis_key(p.selector) end else - if (p.key and p.selector) then - p.key = lua_util.template(p.key, { domain = p.domain, selector = p.selector}) - local exists,err = rspamd_util.file_exists(p.key) - if not exists then - if err and err == 'No such file or directory' then - lua_util.debugm(N, task, 'cannot read key from "%s": %s', p.key, err) - else - rspamd_logger.warnx(N, task, 'cannot read key from "%s": %s', p.key, err) + if ((p.key or p.rawkey) and p.selector) then + if p.key then + -- templates + p.key = lua_util.template(p.key, { + domain = p.domain, + selector = p.selector + }) + local exists,err = rspamd_util.file_exists(p.key) + if not exists then + if err and err == 'No such file or directory' then + lua_util.debugm(N, task, 'cannot read key from "%s": %s', p.key, err) + else + rspamd_logger.warnx(N, task, 'cannot read key from "%s": %s', p.key, err) + end + return false end - return false - end - lua_util.debugm(N, task, 'key found at "%s", use selector "%s" for domain "%s"', - p.key, p.selector, p.domain) + lua_util.debugm(N, task, 'key found at "%s", use selector "%s" for domain "%s"', + p.key, p.selector, p.domain) + end do_sign() else -- 2.39.5