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
|
/* Cached SPF interface.
Copyright (C) 2007, 2008 Sergey Poznyakoff
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#require safedb
#pragma regex push +extended +icase
set spf_database "%__statedir__/spf.db"
set spf_negative_ttl interval("1 day")
number spf_cached 0
const None 0
const Neutral 1
const Pass 2
const Fail 3
const SoftFail 4
const TempError 5
const PermError 6
func spf_status_string(number code) returns string
do
switch %code
do
case None: return "None"
case Neutral: return "Neutral"
case Pass: return "Pass"
case Fail: return "Fail"
case SoftFail: return "SoftFail"
case TempError: return "TempError"
case PermError: return "PermError"
done
return "UNKNOWN (" %code ")"
done
func __spf_get_cache(string ip, string domain, string sender)
returns number
do
string record safedbget(%spf_database, "%ip-%domain-%sender")
number timestamp
number ttl
number result
if %record = ""
set result -1
elif %record matches '([^ ]+) ([^ ]+) <(.*)> <(.*)>'
set timestamp \1
if time() >= %timestamp
echo "$i: CLEARING record %record"
set result -1
else
set result \2
set spf_mechanism \3
set spf_explanation \4
fi
else
echo "$i: ERROR: Malformed DB line: %record"
set result -1
fi
return %result
done
func __spf_put_cache(number result, string ip, string domain, string sender)
do
safedbput(%spf_database, "%ip-%domain-%sender",
(time() + %spf_ttl)
" %result <%spf_mechanism> <%spf_explanation>")
done
func __spf_log(number result, string ip, string domain, string sender)
do
string logmsg "SPF check_host(%ip, %domain, %sender) = "
spf_status_string(%result)
if %spf_cached
set logmsg %logmsg " [CACHED]"
fi
if %spf_mechanism != ""
set logmsg %logmsg "; matching mechanism \"%spf_mechanism\""
fi
if %spf_explanation != ""
set logmsg %logmsg "; %spf_explanation"
fi
echo "$i: %logmsg"
done
func check_host(string ip, string domain, string sender, string helo)
returns number
do
number result __spf_get_cache(%ip, %domain, %sender)
if %result == -1
set result spf_check_host(%ip, %domain, %sender, %helo, %ehlo_domain)
set spf_cached 0
if %result = None
set spf_ttl %spf_negative_ttl
fi
__spf_put_cache(%result, %ip, %domain, %sender)
else
set spf_cached 1
fi
__spf_log(%result, %ip, %domain, %sender)
return %result
done
#pragma regex pop
|