--- Begin Message ---
Package: mailman
Severity: wishlist
Tags: patch
Please apply the attached patch which prevents extra subscription spam.
By this I mean that on lists where admin approval is required for
subscription, an annoying user could attempt to subscribe the same email
address over and over again, spamming the list admin or the person they
attempt to subscribe (depending on the list config).
I've posted this patch to the upstream tracker too:
http://sf.net/tracker/?func=detail&aid=1527537&group_id=103&atid=300103
--
bye,
pabs
http://wiki.debian.org/PaulWise
Paul Wise <[email protected]> http://pabs.zip.to
Prevent (and log) subscription spam
diff -urNad mailman-2.1.8~/Mailman/ListAdmin.py mailman-2.1.8/Mailman/ListAdmin.py
--- mailman-2.1.8~/Mailman/ListAdmin.py 2006-07-24 03:24:02.000000000 +0800
+++ mailman-2.1.8/Mailman/ListAdmin.py 2006-07-24 03:24:03.000000000 +0800
@@ -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
diff -urNad mailman-2.1.8~/Mailman/MailList.py mailman-2.1.8/Mailman/MailList.py
--- mailman-2.1.8~/Mailman/MailList.py 2006-07-24 03:24:02.000000000 +0800
+++ mailman-2.1.8/Mailman/MailList.py 2006-07-24 03:24:03.000000000 +0800
@@ -966,6 +966,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 some random email address
+ 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 = ''
@@ -1003,7 +1007,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')
@@ -1091,7 +1097,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')
diff -urNad mailman-2.1.8~/Mailman/Pending.py mailman-2.1.8/Mailman/Pending.py
--- mailman-2.1.8~/Mailman/Pending.py 2005-08-27 09:40:15.000000000 +0800
+++ mailman-2.1.8/Mailman/Pending.py 2006-07-24 03:24:26.000000000 +0800
@@ -63,6 +63,16 @@
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] in (SUBSCRIPTION, UNSUBSCRIPTION) and data[1].address == 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
--- End Message ---