@@ -92,8 +92,11 @@ local function dmarc_callback(task) | |||
local lookup_domain = string.sub(to_resolve, 8) | |||
if not results then | |||
if lookup_domain ~= dmarc_domain then | |||
task:get_resolver():resolve_txt(task:get_session(), | |||
task:get_mempool(), '_dmarc.' .. dmarc_domain, dmarc_dns_cb) | |||
local resolve_name = '_dmarc.' .. dmarc_domain | |||
task:get_resolver():resolve_txt({ | |||
task=task, | |||
name = resolve_name, | |||
callback = dmarc_dns_cb}) | |||
return | |||
end | |||
@@ -191,8 +194,12 @@ local function dmarc_callback(task) | |||
if not found_policy then | |||
if lookup_domain ~= dmarc_domain then | |||
task:get_resolver():resolve_txt(task:get_session(), | |||
task:get_mempool(), '_dmarc.' .. dmarc_domain, dmarc_dns_cb) | |||
local resolve_name = '_dmarc.' .. dmarc_domain | |||
task:get_resolver():resolve_txt({ | |||
task=task, | |||
name = resolve_name, | |||
callback = dmarc_dns_cb}) | |||
return | |||
else | |||
return | |||
@@ -266,8 +273,11 @@ local function dmarc_callback(task) | |||
end | |||
-- Do initial request | |||
task:get_resolver():resolve_txt(task:get_session(), task:get_mempool(), | |||
'_dmarc.' .. from[1]['domain'], dmarc_dns_cb) | |||
local resolve_name = '_dmarc.' .. from[1]['domain'] | |||
task:get_resolver():resolve_txt({ | |||
task=task, | |||
name = resolve_name, | |||
callback = dmarc_dns_cb}) | |||
end | |||
local opts = rspamd_config:get_all_opt('dmarc') |
@@ -34,84 +34,86 @@ local logger = require "rspamd_logger" | |||
-- Check rule for a single email | |||
local function check_email_rule(task, rule, addr) | |||
local function emails_dns_cb(resolver, to_resolve, results, err) | |||
task:inc_dns_req() | |||
if results then | |||
logger.infox('<%1> email: [%2] resolved for symbol: %3', | |||
task:get_message_id(), to_resolve, rule['symbol']) | |||
task:insert_result(rule['symbol'], 1) | |||
end | |||
end | |||
if rule['dnsbl'] then | |||
local to_resolve = '' | |||
if rule['domain_only'] then | |||
to_resolve = string.format('%s.%s', addr:get_host(), rule['dnsbl']) | |||
else | |||
to_resolve = string.format('%s.%s.%s', addr:get_user(), addr:get_host(), rule['dnsbl']) | |||
end | |||
task:get_resolver():resolve_a(task:get_session(), task:get_mempool(), | |||
to_resolve, emails_dns_cb) | |||
elseif rule['map'] then | |||
if rule['domain_only'] then | |||
local key = addr:get_host() | |||
if rule['map']:get_key(key) then | |||
task:insert_result(rule['symbol'], 1) | |||
logger.infox('<%1> email: \'%2\' is found in list: %3', | |||
task:get_message_id(), key, rule['symbol']) | |||
end | |||
else | |||
local key = string.format('%s@%s', addr:get_user(), addr:get_host()) | |||
if rule['map']:get_key(key) then | |||
task:insert_result(rule['symbol'], 1) | |||
logger.infox('<%1> email: \'%2\' is found in list: %3', | |||
task:get_message_id(), key, rule['symbol']) | |||
end | |||
end | |||
end | |||
local function emails_dns_cb(resolver, to_resolve, results, err) | |||
if results then | |||
logger.infox('<%1> email: [%2] resolved for symbol: %3', | |||
task:get_message_id(), to_resolve, rule['symbol']) | |||
task:insert_result(rule['symbol'], 1) | |||
end | |||
end | |||
if rule['dnsbl'] then | |||
local to_resolve = '' | |||
if rule['domain_only'] then | |||
to_resolve = string.format('%s.%s', addr:get_host(), rule['dnsbl']) | |||
else | |||
to_resolve = string.format('%s.%s.%s', addr:get_user(), addr:get_host(), rule['dnsbl']) | |||
end | |||
task:get_resolver():resolve_a({ | |||
task=task, | |||
name = to_resolve, | |||
callback = emails_dns_cb}) | |||
elseif rule['map'] then | |||
if rule['domain_only'] then | |||
local key = addr:get_host() | |||
if rule['map']:get_key(key) then | |||
task:insert_result(rule['symbol'], 1) | |||
logger.infox('<%1> email: \'%2\' is found in list: %3', | |||
task:get_message_id(), key, rule['symbol']) | |||
end | |||
else | |||
local key = string.format('%s@%s', addr:get_user(), addr:get_host()) | |||
if rule['map']:get_key(key) then | |||
task:insert_result(rule['symbol'], 1) | |||
logger.infox('<%1> email: \'%2\' is found in list: %3', | |||
task:get_message_id(), key, rule['symbol']) | |||
end | |||
end | |||
end | |||
end | |||
-- Check email | |||
local function check_emails(task) | |||
local emails = task:get_emails() | |||
local checked = {} | |||
if emails then | |||
for _,addr in ipairs(emails) do | |||
local to_check = string.format('%s@%s', addr:get_user(), addr:get_host()) | |||
if not checked['to_check'] then | |||
for _,rule in ipairs(rules) do | |||
check_email_rule(task, rule, addr) | |||
end | |||
checked[to_check] = true | |||
end | |||
end | |||
end | |||
local emails = task:get_emails() | |||
local checked = {} | |||
if emails then | |||
for _,addr in ipairs(emails) do | |||
local to_check = string.format('%s@%s', addr:get_user(), addr:get_host()) | |||
if not checked['to_check'] then | |||
for _,rule in ipairs(rules) do | |||
check_email_rule(task, rule, addr) | |||
end | |||
checked[to_check] = true | |||
end | |||
end | |||
end | |||
end | |||
local opts = rspamd_config:get_all_opt('emails', 'rule') | |||
if opts and type(opts) == 'table' then | |||
for k,v in pairs(opts) do | |||
if k == 'rule' and type(v) == 'table' then | |||
local rule = v | |||
if not rule['symbol'] then | |||
rule['symbol'] = k | |||
end | |||
if rule['map'] then | |||
rule['name'] = rule['map'] | |||
rule['map'] = rspamd_config:add_hash_map (rule['name']) | |||
end | |||
if not rule['symbol'] or (not rule['map'] and not rule['dnsbl']) then | |||
logger.err('incomplete rule') | |||
else | |||
table.insert(rules, rule) | |||
end | |||
end | |||
end | |||
for k,v in pairs(opts) do | |||
if k == 'rule' and type(v) == 'table' then | |||
local rule = v | |||
if not rule['symbol'] then | |||
rule['symbol'] = k | |||
end | |||
if rule['map'] then | |||
rule['name'] = rule['map'] | |||
rule['map'] = rspamd_config:add_hash_map (rule['name']) | |||
end | |||
if not rule['symbol'] or (not rule['map'] and not rule['dnsbl']) then | |||
logger.err('incomplete rule') | |||
else | |||
table.insert(rules, rule) | |||
end | |||
end | |||
end | |||
end | |||
if table.maxn(rules) > 0 then | |||
-- add fake symbol to check all maps inside a single callback | |||
local id = rspamd_config:register_callback_symbol(1.0, check_emails) | |||
for _,rule in ipairs(rules) do | |||
rspamd_config:register_virtual_symbol(rule['symbol'], 1.0, id) | |||
end | |||
-- add fake symbol to check all maps inside a single callback | |||
local id = rspamd_config:register_callback_symbol(1.0, check_emails) | |||
for _,rule in ipairs(rules) do | |||
rspamd_config:register_virtual_symbol(rule['symbol'], 1.0, id) | |||
end | |||
end |
@@ -37,17 +37,6 @@ local function ip_to_rbl(ip, rbl) | |||
end | |||
local function check_multimap(task) | |||
-- Generate dns callback closure | |||
local function dns_cb_generator(r) | |||
local cb = function (resolver, to_resolve, results, err, rbl) | |||
task:inc_dns_req() | |||
if results then | |||
task:insert_result(r['symbol'], 1, r['map']) | |||
end | |||
end | |||
return cb | |||
end | |||
-- Match a single value for against a single rule | |||
local function match_rule(r, value) | |||
local ret = false | |||
@@ -142,9 +131,17 @@ local function check_multimap(task) | |||
-- RBL rules | |||
if ip:is_valid() then | |||
_.each(function(r) | |||
task:get_resolver():resolve_a(task:get_session(), task:get_mempool(), | |||
ip_to_rbl(ip, r['map']), dns_cb_generator(r)) | |||
end, | |||
local cb = function (resolver, to_resolve, results, err, rbl) | |||
if results then | |||
task:insert_result(r['symbol'], 1, r['map']) | |||
end | |||
end | |||
task:get_resolver():resolve_a({task = task, | |||
name = ip_to_rbl(ip, r['map']), | |||
callback = cb, | |||
}) | |||
end, | |||
_.filter(function(r) return r['type'] == 'dnsbl' end, rules)) | |||
end | |||
end |
@@ -79,8 +79,10 @@ local function check_quantity_received (task) | |||
if r['real_ip'] and r['real_ip']:is_valid() then | |||
-- Try to resolve it again | |||
task:get_resolver():resolve_ptr(task:get_session(), task:get_mempool(), | |||
r['real_ip']:to_string(), recv_dns_cb) | |||
task:get_resolver():resolve_ptr({task = task, | |||
name = r['real_ip']:to_string(), | |||
callback = recv_dns_cb | |||
}) | |||
else | |||
task:insert_result(symbol_strict, 1) | |||
end |
@@ -168,25 +168,27 @@ local function rbl_cb (task) | |||
return | |||
end | |||
end | |||
task:get_resolver():resolve_a(task:get_session(), task:get_mempool(), | |||
havegot['helo'] .. '.' .. rbl['rbl'], rbl_dns_cb, k) | |||
task:get_resolver():resolve_a({task = task, | |||
name = havegot['helo'] .. '.' .. rbl['rbl'], | |||
callback = rbl_dns_cb, | |||
option = k}) | |||
end)() | |||
end | |||
if rbl['dkim'] then | |||
(function() | |||
if notgot['dkim'] then | |||
return | |||
end | |||
if not havegot['dkim'] then | |||
(function() | |||
if notgot['dkim'] then | |||
return | |||
end | |||
if not havegot['dkim'] then | |||
local das = task:get_symbol(symbols['dkim_allow_symbol']) | |||
if das and das[1] and das[1]['options'] and das[1]['options'][0] then | |||
havegot['dkim'] = das[1]['options'] | |||
else | |||
notgot['dkim'] = true | |||
return | |||
end | |||
end | |||
else | |||
notgot['dkim'] = true | |||
return | |||
end | |||
end | |||
for _, d in pairs(havegot['dkim']) do | |||
if rbl['dkim_domainonly'] then | |||
local url_from = rspamd_url.create(task:get_mempool(), d) | |||
@@ -196,10 +198,13 @@ local function rbl_cb (task) | |||
return | |||
end | |||
end | |||
task:get_resolver():resolve_a(task:get_session(), task:get_mempool(), | |||
d .. '.' .. rbl['rbl'], rbl_dns_cb, k) | |||
task:get_resolver():resolve_a({task = task, | |||
name = d .. '.' .. rbl['rbl'], | |||
callback = rbl_dns_cb, | |||
option = k}) | |||
end | |||
end)() | |||
end)() | |||
end | |||
if rbl['emails'] then | |||
@@ -235,13 +240,17 @@ local function rbl_cb (task) | |||
end | |||
if rbl['emails'] == 'domain_only' then | |||
for domain, _ in pairs(havegot['emails']) do | |||
task:get_resolver():resolve_a(task:get_session(), task:get_mempool(), | |||
domain .. '.' .. rbl['rbl'], rbl_dns_cb, k) | |||
task:get_resolver():resolve_a({task = task, | |||
name = domain .. '.' .. rbl['rbl'], | |||
callback = rbl_dns_cb, | |||
option = k}) | |||
end | |||
else | |||
for _, email in pairs(havegot['emails']) do | |||
task:get_resolver():resolve_a(task:get_session(), task:get_mempool(), | |||
email .. '.' .. rbl['rbl'], rbl_dns_cb, k) | |||
task:get_resolver():resolve_a({task = task, | |||
name = email .. '.' .. rbl['rbl'], | |||
callback = rbl_dns_cb, | |||
option = k}) | |||
end | |||
end | |||
end)() | |||
@@ -259,8 +268,10 @@ local function rbl_cb (task) | |||
return | |||
end | |||
end | |||
task:get_resolver():resolve_a(task:get_session(), task:get_mempool(), | |||
havegot['rdns'] .. '.' .. rbl['rbl'], rbl_dns_cb, k) | |||
task:get_resolver():resolve_a({task = task, | |||
name = havegot['rdns'] .. '.' .. rbl['rbl'], | |||
callback = rbl_dns_cb, | |||
option = k}) | |||
end)() | |||
end | |||
@@ -278,8 +289,10 @@ local function rbl_cb (task) | |||
end | |||
if (havegot['from']:get_version() == 6 and rbl['ipv6']) or | |||
(havegot['from']:get_version() == 4 and rbl['ipv4']) then | |||
task:get_resolver():resolve_a(task:get_session(), task:get_mempool(), | |||
ip_to_rbl(havegot['from'], rbl['rbl']), rbl_dns_cb, k) | |||
task:get_resolver():resolve_a({task = task, | |||
name = ip_to_rbl(havegot['from'], rbl['rbl']), | |||
callback = rbl_dns_cb, | |||
option = k}) | |||
end | |||
end)() | |||
end | |||
@@ -303,8 +316,10 @@ local function rbl_cb (task) | |||
((rbl['exclude_private_ips'] and not is_private_ip(rh['real_ip'])) 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 | |||
task:get_resolver():resolve_a(task:get_session(), task:get_mempool(), | |||
ip_to_rbl(rh['real_ip'], rbl['rbl']), rbl_dns_cb, k) | |||
task:get_resolver():resolve_a({task = task, | |||
name = ip_to_rbl(rh['real_ip'], rbl['rbl']), | |||
callback = rbl_dns_cb, | |||
option = k}) | |||
end | |||
end | |||
end |