Limit CNAME chains independently of DNS lookup limit
This commit is contained in:
+9
-2
@@ -24,7 +24,7 @@ ALT="Viewable With Any Browser" BORDER="0"></A>
|
||||
Stuart D. Gathman</a><br>
|
||||
This web page is written by Stuart D. Gathman<br>and<br>sponsored by
|
||||
<a href="http://www.bmsi.com">Business Management Systems, Inc.</a> <br>
|
||||
Last updated Jun 09, 2005</h4>
|
||||
Last updated Jul 20, 2005</h4>
|
||||
|
||||
See the <a href="faq.html">FAQ</a> | <a href="http://sourceforge.net/project/showfiles.php?group_id=139894">Download now</a> |
|
||||
<a href="/mailman/listinfo/pymilter">Subscribe to mailing list</a> |
|
||||
@@ -49,7 +49,14 @@ efficient and secure. I recommend upgrading.
|
||||
|
||||
Python milter is being moved to
|
||||
<a href="http://sourceforge.net/projects/pymilter/">pymilter Sourceforge
|
||||
project</a> for development.
|
||||
project</a> for development and release downloads.
|
||||
<p>
|
||||
Release 0.8.2 has changes to SPF to bring it in line with the newly
|
||||
official RFC. It adds SES support (the original SES without body hash)
|
||||
for pysrs-0.30.10, and honeypot support for pydspam-1.1.9. There is
|
||||
a new method in the base milter module. milter.set_exception_policy(i)
|
||||
lets you choose a policy of CONTINUE, REJECT, or TEMPFAIL (default) for
|
||||
untrapped exceptions encountered in a milter callback.
|
||||
<p>
|
||||
Release 0.8.0 is the first <a href="http://sourceforge.net/">Sourceforge</a>
|
||||
release. It supports Python-2.4, and provides an option to accept mail
|
||||
|
||||
+9
-4
@@ -1,6 +1,6 @@
|
||||
%define name milter
|
||||
%define version 0.8.2
|
||||
%define release 2.RH7
|
||||
%define release 4.RH7
|
||||
# what version of RH are we building for?
|
||||
%define redhat9 0
|
||||
%define redhat7 1
|
||||
@@ -31,7 +31,7 @@ Name: %{name}
|
||||
Version: %{version}
|
||||
Release: %{release}
|
||||
Source: %{name}-%{version}.tar.gz
|
||||
#Patch: %{name}-%{version}.patch
|
||||
Patch: %{name}-%{version}.patch
|
||||
Copyright: GPL
|
||||
Group: Development/Libraries
|
||||
BuildRoot: %{_tmppath}/%{name}-buildroot
|
||||
@@ -52,7 +52,7 @@ modules provide for navigating and modifying MIME parts.
|
||||
|
||||
%prep
|
||||
%setup
|
||||
#%patch -p1
|
||||
%patch -p1
|
||||
|
||||
%build
|
||||
env CFLAGS="$RPM_OPT_FLAGS" %{python} setup.py build
|
||||
@@ -166,6 +166,12 @@ rm -rf $RPM_BUILD_ROOT
|
||||
/usr/share/sendmail-cf/hack/rhsbl.m4
|
||||
|
||||
%changelog
|
||||
* Fri Jul 15 2005 Stuart Gathman <stuart@bmsi.com> 0.8.2-4
|
||||
- Limit each CNAME chain independently like PTR and MX
|
||||
* Fri Jul 15 2005 Stuart Gathman <stuart@bmsi.com> 0.8.2-3
|
||||
- Limit CNAME lookups (regression)
|
||||
* Fri Jul 15 2005 Stuart Gathman <stuart@bmsi.com> 0.8.2-2
|
||||
- Handle corrupt ZIP attachments
|
||||
* Fri Jul 15 2005 Stuart Gathman <stuart@bmsi.com> 0.8.2-1
|
||||
- Strict processing limits per SPF RFC
|
||||
- Fixed several parsing bugs under RFC
|
||||
@@ -174,7 +180,6 @@ rm -rf $RPM_BUILD_ROOT
|
||||
- Extended SPF processing results beyond strict RFC limits
|
||||
- Support original SES for local bounce protection (requires pysrs-0.30.10)
|
||||
- Callback exception processing option in milter module
|
||||
- Handle corrupt ZIP attachments
|
||||
* Thu Jun 16 2005 Stuart Gathman <stuart@bmsi.com> 0.8.1-1
|
||||
- Fix zip in zip loop in mime.py
|
||||
- Fix HeaderParseError in bms.py header callback
|
||||
|
||||
@@ -47,8 +47,24 @@ For news, bugfixes, etc. visit the home page for this implementation at
|
||||
# Terrence is not responding to email.
|
||||
#
|
||||
# $Log$
|
||||
# Revision 1.11 2005/07/20 03:30:04 customdesigned
|
||||
# Check pydspam version for honeypot, include latest pyspf changes.
|
||||
# Revision 1.31 2005/07/22 02:11:50 customdesigned
|
||||
# Use dictionary to check for CNAME loops. Check limit independently for
|
||||
# each top level name, just like for PTR.
|
||||
#
|
||||
# Revision 1.30 2005/07/21 20:07:31 customdesigned
|
||||
# Translate DNS error in DNSLookup. This completely isolates DNS
|
||||
# dependencies to the DNSLookup method.
|
||||
#
|
||||
# Revision 1.29 2005/07/21 17:49:39 customdesigned
|
||||
# My best guess at what RFC intended for limiting CNAME loops.
|
||||
#
|
||||
# Revision 1.28 2005/07/21 17:37:08 customdesigned
|
||||
# Break out external DNSLookup method so that test suite can
|
||||
# duplicate CNAME loop bug. Test zone data dictionary now
|
||||
# mirrors structure of real DNS.
|
||||
#
|
||||
# Revision 1.27 2005/07/21 15:26:06 customdesigned
|
||||
# First cut at updating docs. Test suite is obsolete.
|
||||
#
|
||||
# Revision 1.26 2005/07/20 03:12:40 customdesigned
|
||||
# When not in strict mode, don't give PermErr for bad mechanism until
|
||||
@@ -256,6 +272,16 @@ if not hasattr(DNS.Type,'SPF'):
|
||||
DNS.Type.typemap[99] = 'SPF'
|
||||
DNS.Lib.RRunpacker.getSPFdata = DNS.Lib.RRunpacker.getTXTdata
|
||||
|
||||
def DNSLookup(name,qtype):
|
||||
try:
|
||||
req = DNS.DnsRequest(name, qtype=qtype)
|
||||
resp = req.req()
|
||||
#resp.show()
|
||||
# key k: ('wayforward.net', 'A'), value v
|
||||
return [((a['name'], a['typename']), a['data']) for a in resp.answers]
|
||||
except DNS.DNSError,x:
|
||||
raise TempError,'DNS ' + str(x)
|
||||
|
||||
# 32-bit IPv4 address mask
|
||||
MASK = 0xFFFFFFFFL
|
||||
|
||||
@@ -308,6 +334,7 @@ DEFAULT_SPF = 'v=spf1 a/24 mx/24 ptr'
|
||||
MAX_LOOKUP = 10 #draft-schlitt-spf-classic-02 Para 10.1
|
||||
MAX_MX = 10 #draft-schlitt-spf-classic-02 Para 10.1
|
||||
MAX_PTR = 10 #draft-schlitt-spf-classic-02 Para 10.1
|
||||
MAX_CNAME = 10 # analogous interpretation to MAX_PTR
|
||||
MAX_RECURSION = 20
|
||||
ALL_MECHANISMS = ('a', 'mx', 'ptr', 'exists', 'include', 'ip4', 'ip6', 'all')
|
||||
COMMON_MISTAKES = { 'prt': 'ptr', 'ip': 'ip4', 'ipv4': 'ip4', 'ipv6': 'ip6' }
|
||||
@@ -412,6 +439,9 @@ class query(object):
|
||||
>>> q.check(spf='v=spf1 ip4:192.0.0.0/8 ?all moo')
|
||||
('unknown', 550, 'SPF Permanent Error: Unknown mechanism found: moo')
|
||||
|
||||
>>> q.check(spf='v=spf1 =a ?all moo')
|
||||
('unknown', 550, 'SPF Permanent Error: Unknown qualifier, IETF draft para 4.6.1, found in: =a')
|
||||
|
||||
>>> q.check(spf='v=spf1 ip4:192.0.0.0/8 ~all')
|
||||
('pass', 250, 'sender SPF verified')
|
||||
|
||||
@@ -453,8 +483,6 @@ class query(object):
|
||||
self.perm_error.ext = rc
|
||||
raise self.perm_error
|
||||
return rc
|
||||
except DNS.DNSError,x:
|
||||
return ('error', 450, 'SPF DNS Error: ' + str(x))
|
||||
except TempError,x:
|
||||
return ('error', 450, 'SPF Temporary Error: ' + str(x))
|
||||
except PermError,x:
|
||||
@@ -847,7 +875,7 @@ class query(object):
|
||||
"""Get a list of domain names for an IP address."""
|
||||
return self.dns(reverse_dots(i) + ".in-addr.arpa", 'PTR')
|
||||
|
||||
def dns(self, name, qtype):
|
||||
def dns(self, name, qtype, cnames=None):
|
||||
"""DNS query.
|
||||
|
||||
If the result is in cache, return that. Otherwise pull the
|
||||
@@ -864,19 +892,21 @@ class query(object):
|
||||
result = self.cache.get( (name, qtype) )
|
||||
cname = None
|
||||
if not result:
|
||||
req = DNS.DnsRequest(name, qtype=qtype)
|
||||
resp = req.req()
|
||||
#resp.show()
|
||||
for a in resp.answers:
|
||||
# key k: ('wayforward.net', 'A'), value v
|
||||
k, v = (a['name'], a['typename']), a['data']
|
||||
for k,v in DNSLookup(name,qtype):
|
||||
if k == (name, 'CNAME'):
|
||||
cname = v
|
||||
self.cache.setdefault(k, []).append(v)
|
||||
result = self.cache.get( (name, qtype), [])
|
||||
if not result and cname:
|
||||
self.check_lookups()
|
||||
result = self.dns(cname, qtype)
|
||||
if not cnames:
|
||||
cnames = {}
|
||||
elif len(cnames) >= MAX_CNAME:
|
||||
raise PermError(
|
||||
'Length of CNAME chain exceeds %d' % MAX_CNAME)
|
||||
cnames[name] = cname
|
||||
if cname in cnames:
|
||||
raise PermError,'CNAME loop'
|
||||
result = self.dns(cname, qtype, cnames=cnames)
|
||||
return result
|
||||
|
||||
def get_header(self,res,receiver=None):
|
||||
|
||||
Reference in New Issue
Block a user