aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/lua/rbl.lua
blob: cef48f8b6304af058537780bebd7c0ef8a625ca2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
local rbls = {}

local function ip_to_rbl(ip, rbl)
	return table.concat(ip:inversed_str_octets(), ".") .. '.' .. rbl
end

local function rbl_cb (task)
	local function rbl_dns_cb(resolver, to_resolve, results, err, key)
		if results then
			local thisrbl = nil
			for k,r in pairs(rbls) do
				if k == key then
					thisrbl = r
					break
				end
			end
			if thisrbl ~= nil then
				if thisrbl['returncodes'] == nil then
					if thisrbl['symbol'] ~= nil then
						task:insert_result(thisrbl['symbol'], 1)
					end
				else
					for _,result in pairs(results) do 
						local ipstr = result:to_string()
						local foundrc = false
						for s,i in pairs(thisrbl['returncodes']) do
							if type(i) == 'string' then
								if string.find(ipstr, "^" .. v .. "$") then
									foundrc = true
									task:insert_result(s, 1)
									break
								end
							elseif type(i) == 'table' then
								for _,v in pairs(i) do
									if string.find(ipstr, "^" .. v .. "$") then
										foundrc = true
										task:insert_result(s, 1)
										break
									end
								end
							end
						end
						if not foundrc then
							if thisrbl['unknown'] and thisrbl['symbol'] then
								task:insert_result(thisrbl['symbol'], 1)
							else
								rspamd_logger.err('RBL ' .. thisrbl['rbl'] .. ' returned unknown result ' .. ipstr)
							end
						end
					end
				end
			end
		end
		task:inc_dns_req()
	end

	local helo = task:get_helo()
	if helo and string.sub(helo,1,1) ~= '[' then
		for k,rbl in pairs(rbls) do
			if rbl['helo'] then
				task:get_resolver():resolve_a(task:get_session(), task:get_mempool(), helo .. '.' .. rbl['rbl'], rbl_dns_cb, k)
			end
		end
	end
	local sender_dns = task:get_hostname()
	if sender_dns ~= nil and sender_dns ~= 'unknown' then
		for k,rbl in pairs(rbls) do
			if rbl['rdns'] then
				task:get_resolver():resolve_a(task:get_session(), task:get_mempool(), sender_dns .. '.' .. rbl['rbl'], rbl_dns_cb, k)
			end
		end
	end
	local rip = task:get_from_ip()
	if rip and (rip:to_string() ~= '0.0.0.0') then
		for k,rbl in pairs(rbls) do
			if (rip:get_version() == 6 and rbl['ipv6'] and rbl['from']) or 
				(rip:get_version() == 4 and rbl['ipv4'] and rbl['from']) then
			task:get_resolver():resolve_a(task:get_session(), task:get_mempool(), 
				ip_to_rbl(rip, rbl['rbl']), rbl_dns_cb, k)
			end
		end
	end
	local recvh = task:get_received_headers()
	for _,rh in ipairs(recvh) do
		if rh['real_ip'] and rh['real_ip']:to_string() ~= '0.0.0.0' then
			for k,rbl in pairs(rbls) do
				if (rh['real_ip']:get_version() == 6 and rbl['ipv6'] and rbl['received']) or
					(rh['real_ip']:get_version() == 4 and rbl['ipv4'] and rbl['received']) then
				task:get_resolver():resolve_a(task:get_session(), task:get_mempool(), 
					ip_to_rbl(rh['real_ip'], rbl['rbl']), rbl_dns_cb, k)
				end
			end
    	end
	end
end

-- Registration
if type(rspamd_config.get_api_version) ~= 'nil' then
	if rspamd_config:get_api_version() >= 1 then
		rspamd_config:register_module_option('rbl', 'rbls', 'map')
		rspamd_config:register_module_option('rbl', 'default_ipv4', 'string')
		rspamd_config:register_module_option('rbl', 'default_ipv6', 'string')
		rspamd_config:register_module_option('rbl', 'default_received', 'string')
		rspamd_config:register_module_option('rbl', 'default_from', 'string')
		rspamd_config:register_module_option('rbl', 'default_rdns', 'string')
		rspamd_config:register_module_option('rbl', 'default_helo', 'string')
		rspamd_config:register_module_option('rbl', 'default_unknown', 'string')
	end
end

-- Configuration
local opts = rspamd_config:get_all_opt('rbl')
if not opts or type(opts) ~= 'table' then
	return
end
if(opts['default_ipv4'] == nil) then
	opts['default_ipv4'] = true
end
if(opts['default_ipv6'] == nil) then
	opts['default_ipv6'] = false
end
if(opts['default_received'] == nil) then
	opts['default_received'] = true 
end
if(opts['default_from'] == nil) then
	opts['default_from'] = false
end
if(opts['default_unknown'] == nil) then
	opts['default_unknown'] = false
end
if(opts['default_rdns'] == nil) then
        opts['default_rdns'] = false
end
if(opts['default_helo'] == nil) then
        opts['default_helo'] = false
end
for key,rbl in pairs(opts['rbls']) do
	local o = { "ipv4", "ipv6", "from", "received", "unknown", "rdns", "helo" }
	for i=1,table.maxn(o) do
		if(rbl[o[i]] == nil) then
			rbl[o[i]] = opts['default_' .. o[i]]
		end
	end
	if type(rbl['returncodes']) == 'table' then
		for s,_ in pairs(rbl['returncodes']) do
			if type(rspamd_config.get_api_version) ~= 'nil' then
				rspamd_config:register_virtual_symbol(s, 1)
			end
		end
	end
	if not rbl['symbol'] and type(rbl['returncodes']) ~= 'nil' and not rbl['unknown'] then
		rbl['symbol'] = key
	end
	if type(rspamd_config.get_api_version) ~= 'nil' and rbl['symbol'] then
		rspamd_config:register_virtual_symbol(rbl['symbol'], 1)
	end
	rbls[key] = rbl
end
rspamd_config:register_callback_symbol_priority('RBL', 1.0, 0, rbl_cb)