diff options
-rw-r--r-- | Mailman/Cgi/admin.py | 7 | ||||
-rw-r--r-- | Mailman/Cgi/admindb.py | 7 | ||||
-rw-r--r-- | Mailman/Cgi/edithtml.py | 7 | ||||
-rw-r--r-- | Mailman/Cgi/options.py | 11 | ||||
-rwxr-xr-x | Mailman/Cgi/private.py | 7 | ||||
-rw-r--r-- | Mailman/Cgi/roster.py | 7 | ||||
-rwxr-xr-x | Mailman/MailList.py | 2 | ||||
-rw-r--r-- | Mailman/Utils.py | 7 | ||||
-rw-r--r-- | NEWS | 18 | ||||
-rw-r--r-- | templates/en/adminsubscribeack.txt | 2 | ||||
-rw-r--r-- | templates/en/adminunsubscribeack.txt | 1 |
11 files changed, 70 insertions, 6 deletions
diff --git a/Mailman/Cgi/admin.py b/Mailman/Cgi/admin.py index eeefc056..174cf34f 100644 --- a/Mailman/Cgi/admin.py +++ b/Mailman/Cgi/admin.py @@ -119,6 +119,13 @@ def main(): if cgidata.has_key('adminpw'): # This is a re-authorization attempt msg = Bold(FontSize('+1', _('Authorization failed.'))).Format() + remote = os.environ.get('HTTP_FORWARDED_FOR', + os.environ.get('HTTP_X_FORWARDED_FOR', + os.environ.get('REMOTE_ADDR', + 'unidentified origin'))) + syslog('security', + 'Authorization failed (admin): list=%s: remote=%s', + listname, remote) else: msg = '' Auth.loginpage(mlist, 'admin', msg=msg) diff --git a/Mailman/Cgi/admindb.py b/Mailman/Cgi/admindb.py index cc863306..010d8aae 100644 --- a/Mailman/Cgi/admindb.py +++ b/Mailman/Cgi/admindb.py @@ -159,6 +159,13 @@ def main(): if cgidata.has_key('adminpw'): # This is a re-authorization attempt msg = Bold(FontSize('+1', _('Authorization failed.'))).Format() + remote = os.environ.get('HTTP_FORWARDED_FOR', + os.environ.get('HTTP_X_FORWARDED_FOR', + os.environ.get('REMOTE_ADDR', + 'unidentified origin'))) + syslog('security', + 'Authorization failed (admindb): list=%s: remote=%s', + listname, remote) else: msg = '' Auth.loginpage(mlist, 'admindb', msg=msg) diff --git a/Mailman/Cgi/edithtml.py b/Mailman/Cgi/edithtml.py index d3d04a31..8bf1652a 100644 --- a/Mailman/Cgi/edithtml.py +++ b/Mailman/Cgi/edithtml.py @@ -126,6 +126,13 @@ def main(): if cgidata.has_key('admlogin'): # This is a re-authorization attempt msg = Bold(FontSize('+1', _('Authorization failed.'))).Format() + remote = os.environ.get('HTTP_FORWARDED_FOR', + os.environ.get('HTTP_X_FORWARDED_FOR', + os.environ.get('REMOTE_ADDR', + 'unidentified origin'))) + syslog('security', + 'Authorization failed (edithtml): list=%s: remote=%s', + listname, remote) else: msg = '' Auth.loginpage(mlist, 'admin', msg=msg) diff --git a/Mailman/Cgi/options.py b/Mailman/Cgi/options.py index 6608df4f..4f128baf 100644 --- a/Mailman/Cgi/options.py +++ b/Mailman/Cgi/options.py @@ -288,13 +288,16 @@ def main(): # message. if cgidata.has_key('password'): doc.addError(_('Authentication failed.')) + remote = os.environ.get('HTTP_FORWARDED_FOR', + os.environ.get('HTTP_X_FORWARDED_FOR', + os.environ.get('REMOTE_ADDR', + 'unidentified origin'))) + syslog('security', + 'Authorization failed (private): user=%s: list=%s: remote=%s', + user, listname, remote) # So as not to allow membership leakage, prompt for the email # address and the password here. if mlist.private_roster <> 0: - remote = os.environ.get('HTTP_FORWARDED_FOR', - os.environ.get('HTTP_X_FORWARDED_FOR', - os.environ.get('REMOTE_ADDR', - 'unidentified origin'))) syslog('mischief', 'Login failure with private rosters: %s from %s', user, remote) diff --git a/Mailman/Cgi/private.py b/Mailman/Cgi/private.py index 80369e84..131c5de8 100755 --- a/Mailman/Cgi/private.py +++ b/Mailman/Cgi/private.py @@ -142,6 +142,13 @@ def main(): if cgidata.has_key('submit'): # This is a re-authorization attempt message = Bold(FontSize('+1', _('Authorization failed.'))).Format() + remote = os.environ.get('HTTP_FORWARDED_FOR', + os.environ.get('HTTP_X_FORWARDED_FOR', + os.environ.get('REMOTE_ADDR', + 'unidentified origin'))) + syslog('security', + 'Authorization failed (private): user=%s: list=%s: remote=%s', + username, listname, remote) # give an HTTP 401 for authentication failure print 'Status: 401 Unauthorized' # Are we processing a password reminder from the login screen? diff --git a/Mailman/Cgi/roster.py b/Mailman/Cgi/roster.py index 739d4fff..02286c09 100644 --- a/Mailman/Cgi/roster.py +++ b/Mailman/Cgi/roster.py @@ -118,6 +118,13 @@ def main(): error_page_doc(doc, _('%(realname)s roster authentication failed.')) doc.AddItem(mlist.GetMailmanFooter()) print doc.Format() + remote = os.environ.get('HTTP_FORWARDED_FOR', + os.environ.get('HTTP_X_FORWARDED_FOR', + os.environ.get('REMOTE_ADDR', + 'unidentified origin'))) + syslog('security', + 'Authorization failed (roster): list=%s: remote=%s', + listname, remote) return # The document and its language diff --git a/Mailman/MailList.py b/Mailman/MailList.py index b2bb22a5..cc1be3b5 100755 --- a/Mailman/MailList.py +++ b/Mailman/MailList.py @@ -1075,6 +1075,7 @@ class MailList(HTMLFormatter, Deliverer, ListAdmin, "adminsubscribeack.txt", {"listname" : realname, "member" : formataddr((name, email)), + "whence" : "" if whence is None else "(" + whence + ")" }, mlist=self) msg = Message.OwnerNotification(self, subject, text) msg.send(self) @@ -1111,6 +1112,7 @@ class MailList(HTMLFormatter, Deliverer, ListAdmin, 'adminunsubscribeack.txt', {'member' : name, 'listname': self.real_name, + "whence" : "" if whence is None else "(" + whence + ")" }, mlist=self) msg = Message.OwnerNotification(self, subject, text) msg.send(self) diff --git a/Mailman/Utils.py b/Mailman/Utils.py index a8c8fd82..d504ecce 100644 --- a/Mailman/Utils.py +++ b/Mailman/Utils.py @@ -111,7 +111,12 @@ def list_exists(listname): # But first ensure the list name doesn't contain a path traversal # attack. if len(re.sub(mm_cfg.ACCEPTABLE_LISTNAME_CHARACTERS, '', listname)) > 0: - syslog('mischief', 'Hostile listname: %s', listname) + remote = os.environ.get('HTTP_FORWARDED_FOR', + os.environ.get('HTTP_X_FORWARDED_FOR', + os.environ.get('REMOTE_ADDR', + 'unidentified origin'))) + syslog('mischief', + 'Hostile listname: listname=%s: remote=%s', listname, remote) return False basepath = Site.get_listpath(listname) for ext in ('.pck', '.pck.last', '.db', '.db.last'): @@ -30,6 +30,24 @@ Here is a history of user visible changes to Mailman. py2-ipaddress module is installed. The module can be installed via pip if not included in your Python. + - Thanks to Jim Popovitch, Mailman has a new 'security' log and logs + authentication failures to the various web CGI functions. The logged + data include the remote IP and can be used to automate blocking of IPs + with something like fail2ban. Since Mailman 2.1.14, these have returned + an http 401 status and the information should be logged by the web + server, but this new log makes that more convenient. Also, the + 'mischief' log entries for 'hostile listname' noe include the remote IP + if available. + + - Thanks to Jim Popovitch, admin notices of (un)subscribes now may give + the source of the action. This consists of a %(whence)s replacement + that can be added to the admin(un)subscribeack.txt templates. This + has been done for the 'en' templates, but not for most others. + + - Thanks to Jim Popovitch, there is a new + BLOCK_SPAMHAUS_LISTED_DBL_SUBSCRIBE setting to enable blocking web + subscribes for addresses in domains listed in the Spamhaus DBL. + i18n - The Japanese translation has been updated by Yasuhito FUTATSUKI. diff --git a/templates/en/adminsubscribeack.txt b/templates/en/adminsubscribeack.txt index 388a3a24..2c83f5c8 100644 --- a/templates/en/adminsubscribeack.txt +++ b/templates/en/adminsubscribeack.txt @@ -1,3 +1,3 @@ %(member)s has been successfully subscribed to %(listname)s. - +%(whence)s diff --git a/templates/en/adminunsubscribeack.txt b/templates/en/adminunsubscribeack.txt index 2ebcfeb7..bbfcd430 100644 --- a/templates/en/adminunsubscribeack.txt +++ b/templates/en/adminunsubscribeack.txt @@ -1,2 +1,3 @@ %(member)s has been removed from %(listname)s. +%(whence)s |