Skip to content
Snippets Groups Projects
Commit a9ffc3ae authored by Stuart Gathman's avatar Stuart Gathman
Browse files

a:1.2.3.4 -> ip4:1.2.3.4 'lax' heuristic.

parent eda8680b
No related branches found
No related tags found
No related merge requests found
...@@ -47,6 +47,10 @@ For news, bugfixes, etc. visit the home page for this implementation at ...@@ -47,6 +47,10 @@ For news, bugfixes, etc. visit the home page for this implementation at
# Terrence is not responding to email. # Terrence is not responding to email.
# #
# $Log$ # $Log$
# Revision 1.20 2006/03/21 18:48:51 customdesigned
# Import note_error from pyspf. Handle timeout on type99 lookup
# specially (sender actually has no SPF record and a braindead DNS server).
#
# Revision 1.19 2006/02/24 02:12:54 customdesigned # Revision 1.19 2006/02/24 02:12:54 customdesigned
# Properly report hard PermError (lax mode fails also) by always setting # Properly report hard PermError (lax mode fails also) by always setting
# perm_error attribute with PermError exception. Improve reporting of # perm_error attribute with PermError exception. Improve reporting of
...@@ -325,6 +329,9 @@ RE_ARGS = re.compile(r'([0-9]*)(r?)([^0-9a-zA-Z]*)') ...@@ -325,6 +329,9 @@ RE_ARGS = re.compile(r'([0-9]*)(r?)([^0-9a-zA-Z]*)')
RE_CIDR = re.compile(r'/([1-9]|1[0-9]*|2[0-9]*|3[0-2]*)$') RE_CIDR = re.compile(r'/([1-9]|1[0-9]*|2[0-9]*|3[0-2]*)$')
RE_IP4 = re.compile(r'\.'.join(
[r'(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])']*4)+'$')
# Local parts and senders have their delimiters replaced with '.' during # Local parts and senders have their delimiters replaced with '.' during
# macro expansion # macro expansion
# #
...@@ -476,10 +483,14 @@ class query(object): ...@@ -476,10 +483,14 @@ class query(object):
>>> q.strict = False >>> q.strict = False
>>> q.check(spf='v=spf1 ip4:192.0.0.0/8 -all moo') >>> q.check(spf='v=spf1 ip4:192.0.0.0/8 -all moo')
('unknown', 550, 'SPF Permanent Error: Unknown mechanism found: moo')
>>> q.perm_error.ext
('pass', 250, 'sender SPF verified') ('pass', 250, 'sender SPF verified')
>>> q.check(spf='v=spf1 ip4:192.1.0.0/16 moo -all') >>> q.check(spf='v=spf1 ip4:192.1.0.0/16 moo -all')
('unknown', 550, 'SPF Permanent Error: Unknown mechanism found: moo') ('unknown', 550, 'SPF Permanent Error: Unknown mechanism found: moo')
>>> str(q.perm_error.ext)
'None'
>>> q.check(spf='v=spf1 ip4:192.1.0.0/16 ~all') >>> q.check(spf='v=spf1 ip4:192.1.0.0/16 ~all')
('softfail', 250, 'domain in transition') ('softfail', 250, 'domain in transition')
...@@ -589,17 +600,33 @@ class query(object): ...@@ -589,17 +600,33 @@ class query(object):
self.note_error('Unknown mechanism found',mech) self.note_error('Unknown mechanism found',mech)
m = COMMON_MISTAKES[m] m = COMMON_MISTAKES[m]
if m == 'a' and RE_IP4.match(arg):
x = self.note_error(
'Use the ip4 mechanism for ip4 addresses',mech)
m = 'ip4'
if m in ('a', 'mx', 'ptr', 'exists', 'include'): if m in ('a', 'mx', 'ptr', 'exists', 'include'):
arg = self.expand(arg) arg = self.expand(arg)
if not (0 < arg.find('.') < len(arg) - 1): # FQDN must contain at least one '.'
pos = arg.rfind('.')
if not (0 < pos < len(arg) - 1):
raise PermError('Invalid domain found (use FQDN)', raise PermError('Invalid domain found (use FQDN)',
m+':'+arg) arg)
#Test for all numeric TLD as recommended by RFC 3696
#Note this TLD test may pass non-existant TLDs. 3696
#recommends using DNS lookups to test beyond this
#initial test.
if arg[pos+1:].isdigit():
raise PermError('Top Level Domain may not be all numbers',
arg)
if m == 'include': if m == 'include':
if arg == self.d: if arg == self.d:
if mech != 'include': if mech != 'include':
raise PermError('include has trivial recursion',mech) raise PermError('include has trivial recursion',mech)
raise PermError('include mechanism missing domain',mech) raise PermError('include mechanism missing domain',mech)
return mech,m,arg,cidrlength,result return mech,m,arg,cidrlength,result
if m == 'ip4' and not RE_IP4.match(arg):
raise PermError('Invalid IP4 address',mech)
if m in ALL_MECHANISMS: if m in ALL_MECHANISMS:
return mech,m,arg,cidrlength,result return mech,m,arg,cidrlength,result
if m[1:] in ALL_MECHANISMS: if m[1:] in ALL_MECHANISMS:
...@@ -673,15 +700,10 @@ class query(object): ...@@ -673,15 +700,10 @@ class query(object):
if res == 'pass': if res == 'pass':
break break
if res == 'none': if res == 'none':
try: self.note_error(
if self.strict or not self.perm_error:
raise PermError(
'No valid SPF record for included domain: %s'%arg, 'No valid SPF record for included domain: %s'%arg,
mech) mech)
except PermError,x: res = 'neutral'
if self.strict:
raise x
self.perm_error = x
continue continue
elif m == 'all': elif m == 'all':
break break
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment