Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
pymilter
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Container registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
misc
pymilter
Commits
8df5cd02
Commit
8df5cd02
authored
20 years ago
by
Stuart Gathman
Browse files
Options
Downloads
Patches
Plain Diff
Limit CNAME chains independently of DNS lookup limit
parent
0cbfc0d2
No related branches found
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
milter.html
+9
-2
9 additions, 2 deletions
milter.html
milter.spec
+9
-4
9 additions, 4 deletions
milter.spec
spf.py
+44
-14
44 additions, 14 deletions
spf.py
with
62 additions
and
20 deletions
milter.html
+
9
−
2
View file @
8df5cd02
...
@@ -24,7 +24,7 @@ ALT="Viewable With Any Browser" BORDER="0"></A>
...
@@ -24,7 +24,7 @@ ALT="Viewable With Any Browser" BORDER="0"></A>
Stuart D. Gathman
</a><br>
Stuart D. Gathman
</a><br>
This web page is written by Stuart D. Gathman
<br>
and
<br>
sponsored by
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>
<a
href=
"http://www.bmsi.com"
>
Business Management Systems, Inc.
</a>
<br>
Last updated Ju
n 09
, 2005
</h4>
Last updated Ju
l 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>
|
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>
|
<a
href=
"/mailman/listinfo/pymilter"
>
Subscribe to mailing list
</a>
|
...
@@ -49,7 +49,14 @@ efficient and secure. I recommend upgrading.
...
@@ -49,7 +49,14 @@ efficient and secure. I recommend upgrading.
Python milter is being moved to
Python milter is being moved to
<a
href=
"http://sourceforge.net/projects/pymilter/"
>
pymilter Sourceforge
<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>
<p>
Release 0.8.0 is the first
<a
href=
"http://sourceforge.net/"
>
Sourceforge
</a>
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
release. It supports Python-2.4, and provides an option to accept mail
...
...
This diff is collapsed.
Click to expand it.
milter.spec
+
9
−
4
View file @
8df5cd02
%define name milter
%define name milter
%define version 0.8.2
%define version 0.8.2
%define release
2
.RH7
%define release
4
.RH7
# what version of RH are we building for?
# what version of RH are we building for?
%define redhat9 0
%define redhat9 0
%define redhat7 1
%define redhat7 1
...
@@ -31,7 +31,7 @@ Name: %{name}
...
@@ -31,7 +31,7 @@ Name: %{name}
Version: %{version}
Version: %{version}
Release: %{release}
Release: %{release}
Source: %{name}-%{version}.tar.gz
Source: %{name}-%{version}.tar.gz
#
Patch: %{name}-%{version}.patch
Patch: %{name}-%{version}.patch
Copyright: GPL
Copyright: GPL
Group: Development/Libraries
Group: Development/Libraries
BuildRoot: %{_tmppath}/%{name}-buildroot
BuildRoot: %{_tmppath}/%{name}-buildroot
...
@@ -52,7 +52,7 @@ modules provide for navigating and modifying MIME parts.
...
@@ -52,7 +52,7 @@ modules provide for navigating and modifying MIME parts.
%prep
%prep
%setup
%setup
#
%patch -p1
%patch -p1
%build
%build
env CFLAGS="$RPM_OPT_FLAGS" %{python} setup.py build
env CFLAGS="$RPM_OPT_FLAGS" %{python} setup.py build
...
@@ -166,6 +166,12 @@ rm -rf $RPM_BUILD_ROOT
...
@@ -166,6 +166,12 @@ rm -rf $RPM_BUILD_ROOT
/usr/share/sendmail-cf/hack/rhsbl.m4
/usr/share/sendmail-cf/hack/rhsbl.m4
%changelog
%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
* Fri Jul 15 2005 Stuart Gathman <stuart@bmsi.com> 0.8.2-1
- Strict processing limits per SPF RFC
- Strict processing limits per SPF RFC
- Fixed several parsing bugs under RFC
- Fixed several parsing bugs under RFC
...
@@ -174,7 +180,6 @@ rm -rf $RPM_BUILD_ROOT
...
@@ -174,7 +180,6 @@ rm -rf $RPM_BUILD_ROOT
- Extended SPF processing results beyond strict RFC limits
- Extended SPF processing results beyond strict RFC limits
- Support original SES for local bounce protection (requires pysrs-0.30.10)
- Support original SES for local bounce protection (requires pysrs-0.30.10)
- Callback exception processing option in milter module
- Callback exception processing option in milter module
- Handle corrupt ZIP attachments
* Thu Jun 16 2005 Stuart Gathman <stuart@bmsi.com> 0.8.1-1
* Thu Jun 16 2005 Stuart Gathman <stuart@bmsi.com> 0.8.1-1
- Fix zip in zip loop in mime.py
- Fix zip in zip loop in mime.py
- Fix HeaderParseError in bms.py header callback
- Fix HeaderParseError in bms.py header callback
...
...
This diff is collapsed.
Click to expand it.
spf.py
+
44
−
14
View file @
8df5cd02
...
@@ -47,8 +47,24 @@ For news, bugfixes, etc. visit the home page for this implementation at
...
@@ -47,8 +47,24 @@ 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.11 2005/07/20 03:30:04 customdesigned
# Revision 1.31 2005/07/22 02:11:50 customdesigned
# Check pydspam version for honeypot, include latest pyspf changes.
# 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
# Revision 1.26 2005/07/20 03:12:40 customdesigned
# When not in strict mode, don't give PermErr for bad mechanism until
# When not in strict mode, don't give PermErr for bad mechanism until
...
@@ -256,6 +272,16 @@ if not hasattr(DNS.Type,'SPF'):
...
@@ -256,6 +272,16 @@ if not hasattr(DNS.Type,'SPF'):
DNS
.
Type
.
typemap
[
99
]
=
'
SPF
'
DNS
.
Type
.
typemap
[
99
]
=
'
SPF
'
DNS
.
Lib
.
RRunpacker
.
getSPFdata
=
DNS
.
Lib
.
RRunpacker
.
getTXTdata
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
# 32-bit IPv4 address mask
MASK
=
0xFFFFFFFF
L
MASK
=
0xFFFFFFFF
L
...
@@ -308,6 +334,7 @@ DEFAULT_SPF = 'v=spf1 a/24 mx/24 ptr'
...
@@ -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_LOOKUP
=
10
#draft-schlitt-spf-classic-02 Para 10.1
MAX_MX
=
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_PTR
=
10
#draft-schlitt-spf-classic-02 Para 10.1
MAX_CNAME
=
10
# analogous interpretation to MAX_PTR
MAX_RECURSION
=
20
MAX_RECURSION
=
20
ALL_MECHANISMS
=
(
'
a
'
,
'
mx
'
,
'
ptr
'
,
'
exists
'
,
'
include
'
,
'
ip4
'
,
'
ip6
'
,
'
all
'
)
ALL_MECHANISMS
=
(
'
a
'
,
'
mx
'
,
'
ptr
'
,
'
exists
'
,
'
include
'
,
'
ip4
'
,
'
ip6
'
,
'
all
'
)
COMMON_MISTAKES
=
{
'
prt
'
:
'
ptr
'
,
'
ip
'
:
'
ip4
'
,
'
ipv4
'
:
'
ip4
'
,
'
ipv6
'
:
'
ip6
'
}
COMMON_MISTAKES
=
{
'
prt
'
:
'
ptr
'
,
'
ip
'
:
'
ip4
'
,
'
ipv4
'
:
'
ip4
'
,
'
ipv6
'
:
'
ip6
'
}
...
@@ -412,6 +439,9 @@ class query(object):
...
@@ -412,6 +439,9 @@ class query(object):
>>>
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
'
)
(
'
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
'
)
>>>
q
.
check
(
spf
=
'
v=spf1 ip4:192.0.0.0/8 ~all
'
)
(
'
pass
'
,
250
,
'
sender SPF verified
'
)
(
'
pass
'
,
250
,
'
sender SPF verified
'
)
...
@@ -453,8 +483,6 @@ class query(object):
...
@@ -453,8 +483,6 @@ class query(object):
self
.
perm_error
.
ext
=
rc
self
.
perm_error
.
ext
=
rc
raise
self
.
perm_error
raise
self
.
perm_error
return
rc
return
rc
except
DNS
.
DNSError
,
x
:
return
(
'
error
'
,
450
,
'
SPF DNS Error:
'
+
str
(
x
))
except
TempError
,
x
:
except
TempError
,
x
:
return
(
'
error
'
,
450
,
'
SPF Temporary Error:
'
+
str
(
x
))
return
(
'
error
'
,
450
,
'
SPF Temporary Error:
'
+
str
(
x
))
except
PermError
,
x
:
except
PermError
,
x
:
...
@@ -847,7 +875,7 @@ class query(object):
...
@@ -847,7 +875,7 @@ class query(object):
"""
Get a list of domain names for an IP address.
"""
"""
Get a list of domain names for an IP address.
"""
return
self
.
dns
(
reverse_dots
(
i
)
+
"
.in-addr.arpa
"
,
'
PTR
'
)
return
self
.
dns
(
reverse_dots
(
i
)
+
"
.in-addr.arpa
"
,
'
PTR
'
)
def
dns
(
self
,
name
,
qtype
):
def
dns
(
self
,
name
,
qtype
,
cnames
=
None
):
"""
DNS query.
"""
DNS query.
If the result is in cache, return that. Otherwise pull the
If the result is in cache, return that. Otherwise pull the
...
@@ -864,19 +892,21 @@ class query(object):
...
@@ -864,19 +892,21 @@ class query(object):
result
=
self
.
cache
.
get
(
(
name
,
qtype
)
)
result
=
self
.
cache
.
get
(
(
name
,
qtype
)
)
cname
=
None
cname
=
None
if
not
result
:
if
not
result
:
req
=
DNS
.
DnsRequest
(
name
,
qtype
=
qtype
)
for
k
,
v
in
DNSLookup
(
name
,
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
'
]
if
k
==
(
name
,
'
CNAME
'
):
if
k
==
(
name
,
'
CNAME
'
):
cname
=
v
cname
=
v
self
.
cache
.
setdefault
(
k
,
[]).
append
(
v
)
self
.
cache
.
setdefault
(
k
,
[]).
append
(
v
)
result
=
self
.
cache
.
get
(
(
name
,
qtype
),
[])
result
=
self
.
cache
.
get
(
(
name
,
qtype
),
[])
if
not
result
and
cname
:
if
not
result
and
cname
:
self
.
check_lookups
()
if
not
cnames
:
result
=
self
.
dns
(
cname
,
qtype
)
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
return
result
def
get_header
(
self
,
res
,
receiver
=
None
):
def
get_header
(
self
,
res
,
receiver
=
None
):
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment