From fb713b23a2cb8acb40b37e14b87c58d9c0bf2a88 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Mon, 19 Oct 2015 16:59:08 +0100 Subject: [PATCH] Add module to get data from HTTP headers Issue: #285 Reported by: @msimerson --- rules/http_headers.lua | 116 +++++++++++++++++++++++++++++++++++++++++ rules/rspamd.lua | 1 + 2 files changed, 117 insertions(+) create mode 100644 rules/http_headers.lua diff --git a/rules/http_headers.lua b/rules/http_headers.lua new file mode 100644 index 000000000..9a7ff3b09 --- /dev/null +++ b/rules/http_headers.lua @@ -0,0 +1,116 @@ +--[[ +Copyright (c) 2015, Vsevolod Stakhov +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 logger = require "rspamd_logger" +local ucl = require "ucl" + +-- Disable DKIM checks if passed via HTTP headers +rspamd_config:add_condition("R_DKIM_ALLOW", function(task) + local hdr = task:get_request_header('DKIM') + + if hdr then + local parser = ucl.parser() + local res, err = parser:parse_string(tostring(hdr)) + if not res or type(res) ~= 'table' then + logger.infox(task, "cannot parse DKIM header: %1", err) + return true + end + + if res['result'] then + if res['result'] == 'pass' or res['result'] == 'allow' then + task:insert_result('R_DKIM_ALLOW', 1.0) + elseif res['result'] == 'fail' or res['result'] == 'reject' then + task:insert_result('R_DKIM_REJECT', 1.0) + elseif res['result'] == 'tempfail' or res['result'] == 'softfail' then + task:insert_result('R_DKIM_TEMPFAIL', 1.0) + end + + return false + end + end + + return true +end) + +-- Disable DKIM checks if passed via HTTP headers +rspamd_config:add_condition("R_SPF_ALLOW", function(task) + local hdr = task:get_request_header('SPF') + + if hdr then + local parser = ucl.parser() + local res, err = parser:parse_string(tostring(hdr)) + if not res or type(res) ~= 'table' then + logger.infox(task, "cannot parse SPF header: %1", err) + return true + end + + if res['result'] then + if res['result'] == 'pass' or res['result'] == 'allow' then + task:insert_result('R_SPF_ALLOW', 1.0) + elseif res['result'] == 'fail' or res['result'] == 'reject' then + task:insert_result('R_SPF_FAIL', 1.0) + elseif res['result'] == 'neutral' then + task:insert_result('R_SPF_NEUTRAL', 1.0) + elseif res['result'] == 'tempfail' or res['result'] == 'softfail' then + task:insert_result('R_SPF_TEMPFAIL', 1.0) + end + + return false + end + end + + return true +end) + +rspamd_config:add_condition("DMARC_POLICY_ALLOW", function(task) + local hdr = task:get_request_header('DMARC') + + if hdr then + local parser = ucl.parser() + local res, err = parser:parse_string(tostring(hdr)) + if not res or type(res) ~= 'table' then + logger.infox(task, "cannot parse DMARC header: %1", err) + return true + end + + if res['result'] then + if res['result'] == 'pass' or res['result'] == 'allow' then + task:insert_result('DMARC_POLICY_ALLOW', 1.0) + elseif res['result'] == 'fail' or res['result'] == 'reject' then + task:insert_result('DMARC_POLICY_REJECT', 1.0) + elseif res['result'] == 'quarantine' then + task:insert_result('DMARC_POLICY_QUARANTINE', 1.0) + elseif res['result'] == 'tempfail' or res['result'] == 'softfail' then + task:insert_result('DMARC_POLICY_SOFTFAIL', 1.0) + end + + return false + end + end + + return true +end) + diff --git a/rules/rspamd.lua b/rules/rspamd.lua index 75dd2b3d9..f670a3d02 100644 --- a/rules/rspamd.lua +++ b/rules/rspamd.lua @@ -40,6 +40,7 @@ dofile(local_rules .. '/regexp/fraud.lua') dofile(local_rules .. '/regexp/drugs.lua') dofile(local_rules .. '/html.lua') dofile(local_rules .. '/misc.lua') +dofile(local_rules .. '/http_headers.lua') local function file_exists(filename) local file = io.open(filename) -- 2.39.5