Use signed Message-ID in delayed reject to blacklist senders

This commit is contained in:
Stuart Gathman
2006-03-07 20:50:54 +00:00
parent 994bcce7dc
commit d69b805690
4 changed files with 63 additions and 8 deletions
+1
View File
@@ -1,5 +1,6 @@
Here is a history of user visible changes to Python milter.
0.8.6
0.8.5 Simple trusted_forwarder implementation.
Fix access_file neutral policy
Move Received-SPF header to beginning of headers
+3
View File
@@ -1,3 +1,6 @@
Allow unsigned DSNs from selected domains (that don't accept signed MFROM,
e.g. verizon.net).
Added Message-ID header to DSN with SRS signed sender. When seen on incoming
rfc ignorant failure message, blacklist sender.
+46 -8
View File
@@ -1,6 +1,11 @@
#!/usr/bin/env python
# A simple milter that has grown quite a bit.
# $Log$
# Revision 1.56 2006/02/24 02:12:54 customdesigned
# Properly report hard PermError (lax mode fails also) by always setting
# perm_error attribute with PermError exception. Improve reporting of
# invalid domain PermError.
#
# Revision 1.55 2006/02/17 05:04:29 customdesigned
# Use SRS sign domain list.
# Accept but do not use for training whitelisted senders without SPF pass.
@@ -184,7 +189,6 @@ import mime
import email.Errors
import Milter
import tempfile
import traceback
import ConfigParser
import time
import socket
@@ -800,6 +804,7 @@ class bmsMilter(Milter.Milter):
self.blacklist = False
self.reject_spam = True
self.data_allowed = True
self.delayed_failure = None
self.trust_received = self.trusted_relay
self.trust_spf = self.trusted_relay
self.redirect_list = []
@@ -1082,7 +1087,9 @@ class bmsMilter(Milter.Milter):
self.log("REJECT: ses spoofed:",oldaddr)
self.setreply('550','5.7.1','Invalid SES signature')
return Milter.REJECT
if srs_reject_spoofed: # FIXME: srs_reject_immed?
# reject for certain recipients are delayed until after DATA
if srs_reject_spoofed \
and not user.lower() in ('postmaster','abuse'):
return self.forged_bounce()
self.data_allowed = not srs_reject_spoofed
@@ -1125,6 +1132,13 @@ class bmsMilter(Milter.Milter):
self.setreply('550','5.7.1','That subject is not allowed')
return Milter.REJECT
# even if we wanted the Taiwanese spam, we can't read Chinese
if block_chinese:
if val.startswith('=?big5') or val.startswith('=?ISO-2022-JP'):
self.log('REJECT: %s: %s' % (name,val))
self.setreply('550','5.7.1',"We don't understand chinese")
return Milter.REJECT
# check for spam that claims to be legal
lval = val.lower().strip()
for adv in ("adv:","adv.","adv ","[adv]","(adv)","advt:","advert:"):
@@ -1152,6 +1166,15 @@ class bmsMilter(Milter.Milter):
self.setreply('550','5.7.1','I find unedited forwards annoying')
return Milter.REJECT
# check for delayed bounce of CBV
if self.is_bounce and srs:
for w in ("delivery failure", "failure notice",
"returned mail", "undeliverable"):
if lval.startswith(w):
self.delayed_failure = val.strip()
# if confirmed by finding our signed Message-ID,
# original sender (encoded in Message-ID) is blacklisted
# check for invalid message id
if lname == 'message-id' and len(val) < 4:
self.log('REJECT: %s: %s' % (name,val))
@@ -1192,12 +1215,6 @@ class bmsMilter(Milter.Milter):
# decode near ascii text to unobfuscate
val = parse_header(hval)
if not self.internal_connection and not (self.blacklist or self.whitelist):
# even if we wanted the Taiwanese spam, we can't read Chinese
if block_chinese and lname == 'subject':
if val.startswith('=?big5') or val.startswith('=?ISO-2022-JP'):
self.log('REJECT: %s: %s' % (name,val))
self.setreply('550','5.7.1',"We don't understand chinese")
return Milter.REJECT
rc = self.check_header(name,val)
if rc != Milter.CONTINUE: return rc
elif self.whitelist_sender and lname == 'subject':
@@ -1490,6 +1507,27 @@ class bmsMilter(Milter.Milter):
return Milter.ACCEPT # no message collected - so no eom processing
try:
# check for delayed bounce
if self.delayed_failure:
self.fp.seek(0)
for ln in self.fp:
if ln.lower().startswith('message-id:'):
name,val = ln.split(None,1)
if val.startswith('<SRS'):
try:
sender = srs.reverse(val[1:-1])
cbv_cache[sender] = 500,self.delayed_failure,time.time()
try:
# save message for debugging
fname = tempfile.mktemp(".dsn")
os.rename(self.tempname,fname)
except:
fname = self.tempname
self.tempname = None
self.log('BLACKLIST:',sender,fname)
return Milter.DISCARD
except: continue
# analyze external mail for spam
spam_checked = self.check_spam() # tag or quarantine for spam
if not self.fp:
+13
View File
@@ -174,6 +174,19 @@ rm -rf $RPM_BUILD_ROOT
/usr/share/sendmail-cf/hack/rhsbl.m4
%changelog
* Thu Feb 23 2006 Stuart Gathman <stuart@bmsi.com> 0.8.6-1
- Delay reject of unsigned RCPT for postmaster and abuse only
- Fix dsn reporting of hard permerror
- Resolve FIXME for wrap_close in miltermodule.c
- Add Message-ID to DSNs
- Use signed Message-ID in delayed reject to blacklist senders
- Auto-train via blacklist and auto-whitelist
- Don't check userlist for signed MFROM
- Accept but skip DSPAM and training for whitelisted senders without SPF PASS
- Report GC stats
- Support CIDR matching for IP lists
- Support pysrs sign feature
- Support localpart specific SPF policy in access file
* Thu Dec 29 2005 Stuart Gathman <stuart@bmsi.com> 0.8.5-1
- Simple trusted_forwarder implementation.
- Fix access_file neutral policy