From 655a1116e05bbbb641a7f88bbfad8d806f02438a Mon Sep 17 00:00:00 2001 From: Andrew Lewis Date: Tue, 12 Dec 2017 16:20:56 +0200 Subject: [PATCH] [Feature] RBL: received: filtering by position & flags - Also filter artificial header always --- src/plugins/lua/rbl.lua | 92 +++++++++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 13 deletions(-) diff --git a/src/plugins/lua/rbl.lua b/src/plugins/lua/rbl.lua index 59d1de2d54..82c1fb9755 100644 --- a/src/plugins/lua/rbl.lua +++ b/src/plugins/lua/rbl.lua @@ -87,6 +87,72 @@ local function ip_to_rbl(ip, rbl) return table.concat(ip:inversed_str_octets(), '.') .. '.' .. rbl end +local function gen_check_rcvd_conditions(rbl, received_total) + local min_pos = tonumber(rbl['received_min_pos']) + local max_pos = tonumber(rbl['received_max_pos']) + local match_flags = rbl['received_flags'] + local nmatch_flags = rbl['received_nflags'] + local function basic_received_check(rh) + if ((rh['real_ip']:get_version() == 6 and rbl['ipv6']) or + (rh['real_ip']:get_version() == 4 and rbl['ipv4'])) and + ((rbl['exclude_private_ips'] and not rh['real_ip']:is_local()) or + not rbl['exclude_private_ips']) and ((rbl['exclude_local_ips'] and + not is_excluded_ip(rh['real_ip'])) or not rbl['exclude_local_ips']) then + return true + else + return false + end + end + if not (max_pos or min_pos or match_flags or nmatch_flags) then + return basic_received_check + end + return function(rh, pos) + if not basic_received_check() then return false end + local got_flags = rh['flags'] + if min_pos then + if min_pos < 0 then + if min_pos == -1 then + if (pos ~= received_total) then + return false + end + else + if pos <= (received_total - (min_pos*-1)) then + return false + end + end + elseif pos < min_pos then + return false + end + end + if max_pos then + if max_pos < -1 then + if (received_total - (max_pos*-1)) >= pos then + return false + end + elseif max_pos > 0 then + if pos > max_pos then + return false + end + end + end + if match_flags then + for _, flag in ipairs(match_flags) do + if not got_flags[flag] then + return false + end + end + end + if nmatch_flags then + for _, flag in ipairs(nmatch_flags) do + if got_flags[flag] then + return false + end + end + end + return true + end +end + local function rbl_cb (task) local function gen_rbl_callback(rule) return function (_, to_resolve, results, err) @@ -380,21 +446,21 @@ local function rbl_cb (task) return false end, enabled_rbls)) + havegot['received'] = fun.filter(function(h) + return not h['flags']['artificial'] + end, havegot['received']):totable() + + local received_total = #havegot['received'] -- Received lists fun.each(function(_, rbl) - for _,rh in ipairs(havegot['received']) do - if rh['real_ip'] and rh['real_ip']:is_valid() then - if ((rh['real_ip']:get_version() == 6 and rbl['ipv6']) or - (rh['real_ip']:get_version() == 4 and rbl['ipv4'])) and - ((rbl['exclude_private_ips'] and not rh['real_ip']:is_local()) or - not rbl['exclude_private_ips']) and ((rbl['exclude_local_ips'] and - not is_excluded_ip(rh['real_ip'])) or not rbl['exclude_local_ips']) then - -- Disable forced for received resolving, as we have no control on - -- those headers count - local to_resolve = ip_to_rbl(rh['real_ip'], rbl['rbl']) - local rule = gen_rbl_rule(to_resolve, rbl) - rule.forced = false - end + local check_conditions = gen_check_rcvd_conditions(rbl, received_total) + for pos,rh in ipairs(havegot['received']) do + if check_conditions(rh, pos) then + local to_resolve = ip_to_rbl(rh['real_ip'], rbl['rbl']) + local rule = gen_rbl_rule(to_resolve, rbl) + -- Disable forced for received resolving, as we have no control on + -- those headers count + rule.forced = false end end end, -- 2.47.3