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

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to