Hi all, Finally got around to fixing the tracebacks with the subscription spam problem. I recommend we now apply this patch in the Debian mailman package. I'll also send the fixed version upstream.
-- bye, pabs http://wiki.debian.org/PaulWise
Patch: imc-37-stop-subscription-spam.patch
Author: Paul Wise <[EMAIL PROTECTED]>
Description: Prevent (and log) subscription spam
Index: Mailman/ListAdmin.py
===================================================================
--- Mailman/ListAdmin.py.orig 2007-06-13 17:29:38.000000000 +0100
+++ Mailman/ListAdmin.py 2007-06-13 17:29:38.000000000 +0100
@@ -376,6 +376,10 @@
def HoldSubscription(self, addr, fullname, password, digest, lang):
# Assure that the database is open for writing
self.__opendb()
+ # Check for attempts at spamming the admin
+ for k, (type, data) in self.__db.items():
+ if type == SUBSCRIPTION and data[1] == addr:
+ return 1
# Get the next unique id
id = self.__nextid()
# Save the information to the request database. for held subscription
@@ -412,6 +416,7 @@
msg = Message.UserNotification(owneraddr, owneraddr, subject, text,
self.preferred_language)
msg.send(self, **{'tomoderators': 1})
+ return 0
def __handlesubscription(self, record, value, comment):
stime, addr, fullname, password, digest, lang = record
@@ -440,6 +445,10 @@
def HoldUnsubscription(self, addr):
# Assure the database is open for writing
self.__opendb()
+ # Check for attempts at spamming the admin
+ for k, (type, data) in self.__db.items():
+ if type == UNSUBSCRIPTION and data[1] == addr:
+ return 1
# Get the next unique id
id = self.__nextid()
# All we need to do is save the unsubscribing address
@@ -464,6 +473,7 @@
msg = Message.UserNotification(owneraddr, owneraddr, subject, text,
self.preferred_language)
msg.send(self, **{'tomoderators': 1})
+ return 0
def __handleunsubscription(self, record, value, comment):
addr = record
Index: Mailman/MailList.py
===================================================================
--- Mailman/MailList.py.orig 2007-06-13 17:29:38.000000000 +0100
+++ Mailman/MailList.py 2007-06-13 17:29:38.000000000 +0100
@@ -946,6 +946,10 @@
# User confirmation required. BAW: this should probably just
# accept a userdesc instance.
cookie = self.pend_new(Pending.SUBSCRIPTION, userdesc)
+ if cookie == '':
+ # Someone tried to spam the poor list admin
+ syslog('mischief', 'Duplicate subscription attempt on list %s for %s by %s', self.internal_name(), email, remote)
+ raise Errors.MMSubscribeNeedsConfirmation
# Send the user the confirmation mailback
if remote is None:
by = remote = ''
@@ -983,7 +987,9 @@
# Subscription approval is required. Add this entry to the admin
# requests database. BAW: this should probably take a userdesc
# just like above.
- self.HoldSubscription(email, name, password, digest, lang)
+ if self.HoldSubscription(email, name, password, digest, lang):
+ # Someone tried to spam the poor list admin
+ syslog('mischief', 'Duplicate subscription attempt on list %s for %s by %s', self.internal_name(), email, remote)
raise Errors.MMNeedApproval, _(
'subscriptions to %(realname)s require moderator approval')
@@ -1071,7 +1077,9 @@
if self.unsubscribe_policy == 0:
self.ApprovedDeleteMember(name, whence, admin_notif, userack)
else:
- self.HoldUnsubscription(email)
+ if self.HoldUnsubscription(email):
+ # Someone tried to spam the poor list admin
+ syslog('mischief', 'Duplicate subscription attempt on list %s for %s by %s', self.internal_name(), email, whence)
raise Errors.MMNeedApproval, _(
'unsubscriptions require moderator approval')
Index: Mailman/Pending.py
===================================================================
--- Mailman/Pending.py.orig 2007-06-13 17:29:18.000000000 +0100
+++ Mailman/Pending.py 2007-06-13 17:31:42.000000000 +0100
@@ -63,6 +63,18 @@
assert self.Locked()
# Load the database
db = self.__load()
+ evictions = db['evictions']
+ now = time.time()
+ for cookie, data in db.items():
+ if cookie in ('evictions', 'version'):
+ continue
+ timestamp = evictions[cookie]
+ if now > timestamp:
+ continue
+ if data[0] == SUBSCRIPTION and data[1].address == content[0].address:
+ return ''
+ if data[0] == UNSUBSCRIPTION and data[1] == content[0].address:
+ return ''
# Calculate a unique cookie. Algorithm vetted by the Timbot. time()
# has high resolution on Linux, clock() on Windows. random gives us
# about 45 bits in Python 2.2, 53 bits on Python 2.3. The time and
signature.asc
Description: This is a digitally signed message part

