Merge lp:~jimpop/mailman/security-logging into lp:mailman/2.1

Proposed by Jim Popovitch
Status: Merged
Merged at revision: 1768
Proposed branch: lp:~jimpop/mailman/security-logging
Merge into: lp:mailman/2.1
Diff against target: 121 lines (+37/-5)
7 files modified
Mailman/Cgi/admin.py (+5/-0)
Mailman/Cgi/admindb.py (+5/-0)
Mailman/Cgi/edithtml.py (+5/-0)
Mailman/Cgi/options.py (+6/-4)
Mailman/Cgi/private.py (+6/-0)
Mailman/Cgi/roster.py (+5/-0)
Mailman/Utils.py (+5/-1)
To merge this branch: bzr merge lp:~jimpop/mailman/security-logging
Reviewer Review Type Date Requested Status
Mark Sapiro Approve
Jim Popovitch (community) Needs Resubmitting
Review via email: mp+347728@code.launchpad.net

Commit message

Logging improvement for security related events (failed logins, etc.)

To post a comment you must log in.
Revision history for this message
Jim Popovitch (jimpop) wrote :

Here's a patch that logs security related events (failed logins, etc).

Revision history for this message
Mark Sapiro (msapiro) wrote :

There are a couple of issues.

First, there is currently a log entry in mischief for an options page login failure, but only with private rosters. If we are going to be logging auth failures in a new security log, the options failure should be logged there too and unconditionally.

Second, the Changes to the owner notifications to add

text = "%s\nReason: %s" % (text, whence)

to the owner notifications for subscribe and unsubscribe are problematic. whence is not a 'Reason' and there is no i18n for 'Reason'

It would be better to just add whence as an additional replacement in the templates.

Finally, I don't see the need for this in the owner notices at all. This info is already in the subscribe log which I think is a better place for it.

review: Needs Fixing
lp:~jimpop/mailman/security-logging updated
1768. By Jim Popovitch

Changes based on feedback from Mark.

Revision history for this message
Jim Popovitch (jimpop) wrote :

Thanks Mark,

The auth failure is now always logged to security in options.py, and the mischief log entry remains as was (logging only if private roster).

The only reason I put the whence in the owner notification emails is so that it is crystal clear to all the admins and moderators why a subscriber was added or removed, i.e. "bin/remove_member", "email confirmation", "web confirmation". It keeps a large mod team informed, as well as saving mods from having to ask "why was this person removed?". etc. I like the idea of integrating it in the templates, so I've removed it from this merge and I'll do a new merge request for that piece (and you can decide on that at that time).

review: Needs Resubmitting
Revision history for this message
Mark Sapiro (msapiro) wrote :

I added a NEWS item and fixed a few small issues.

Thanks for the contribution.

review: Approve
Revision history for this message
Mark Sapiro (msapiro) wrote :

On 6/10/18 4:02 PM, Jim Popovitch wrote:
>
> The only reason I put the whence in the owner notification emails is so that it is crystal clear to all the admins and moderators why a subscriber was added or removed, i.e. "bin/remove_member", "email confirmation", "web confirmation". It keeps a large mod team informed, as well as saving mods from having to ask "why was this person removed?". etc. I like the idea of integrating it in the templates, so I've removed it from this merge and I'll do a new merge request for that piece (and you can decide on that at that time).

I was confused. I forgot that whence was those things in these cases. I
was focused on its being an IP address. No that I realize what it is, I
think it's fine to add it to the notice, but making it a replacement for
the templates is the way to go.

--
Mark Sapiro <email address hidden> The highway is for gamblers,
San Francisco Bay Area, California better use your sense - B. Dylan

Revision history for this message
Jim Popovitch (jimpop) wrote :

I've gone ahead and created the new branch for the whence templates. The chief problem for me at this point is making sure that the placement of $(whence) is grammatically correct in each template.

https://code.launchpad.net/~jimpop/mailman/owner-notification-whence

Revision history for this message
Mark Sapiro (msapiro) wrote :

On 6/11/18 5:23 PM, Jim Popovitch wrote:
> I've gone ahead and created the new branch for the whence templates. The chief problem for me at this point is making sure that the placement of $(whence) is grammatically correct in each template.
>
> https://code.launchpad.net/~jimpop/mailman/owner-notification-whence

I understand the issue, and I wouldn't worry about it.

I'd say only do the 'en' templates and I'll post to mailman-i18n that
templates need to be updated to take advantage of this. There's no
problem if the template doesn't have %(whence)s in it.

My concerns are:

the 'en' adminsubscribeack.txt template adds a %(method)s replacement
and that doesn't seem to be provided.

There is no 'en' (or other) adminunsubscribeack.txt template.

--
Mark Sapiro <email address hidden> The highway is for gamblers,
San Francisco Bay Area, California better use your sense - B. Dylan

Revision history for this message
Jim Popovitch (jimpop) wrote :

Thanks for pointing that out. I've re-pushed a complete new branch
with just the changes for the 2 "en" templates and MailList.py.

I left the branch as "Development" status (as opposed to Mature) for
now, and sent you a merge request.

Thanks!!

-Jim P.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Mailman/Cgi/admin.py'
--- Mailman/Cgi/admin.py 2017-06-21 16:59:41 +0000
+++ Mailman/Cgi/admin.py 2018-06-10 23:02:31 +0000
@@ -119,6 +119,11 @@
119 if cgidata.has_key('adminpw'):119 if cgidata.has_key('adminpw'):
120 # This is a re-authorization attempt120 # This is a re-authorization attempt
121 msg = Bold(FontSize('+1', _('Authorization failed.'))).Format()121 msg = Bold(FontSize('+1', _('Authorization failed.'))).Format()
122 remote = os.environ.get('HTTP_FORWARDED_FOR',
123 os.environ.get('HTTP_X_FORWARDED_FOR',
124 os.environ.get('REMOTE_ADDR',
125 'unidentified origin')))
126 syslog('security', 'Authorization failed (admin): list=%s: remote=%s', listname, remote)
122 else:127 else:
123 msg = ''128 msg = ''
124 Auth.loginpage(mlist, 'admin', msg=msg)129 Auth.loginpage(mlist, 'admin', msg=msg)
125130
=== modified file 'Mailman/Cgi/admindb.py'
--- Mailman/Cgi/admindb.py 2017-06-24 21:34:48 +0000
+++ Mailman/Cgi/admindb.py 2018-06-10 23:02:31 +0000
@@ -159,6 +159,11 @@
159 if cgidata.has_key('adminpw'):159 if cgidata.has_key('adminpw'):
160 # This is a re-authorization attempt160 # This is a re-authorization attempt
161 msg = Bold(FontSize('+1', _('Authorization failed.'))).Format()161 msg = Bold(FontSize('+1', _('Authorization failed.'))).Format()
162 remote = os.environ.get('HTTP_FORWARDED_FOR',
163 os.environ.get('HTTP_X_FORWARDED_FOR',
164 os.environ.get('REMOTE_ADDR',
165 'unidentified origin')))
166 syslog('security', 'Authorization failed (admindb): list=%s: domain=%s', listname, remote)
162 else:167 else:
163 msg = ''168 msg = ''
164 Auth.loginpage(mlist, 'admindb', msg=msg)169 Auth.loginpage(mlist, 'admindb', msg=msg)
165170
=== modified file 'Mailman/Cgi/edithtml.py'
--- Mailman/Cgi/edithtml.py 2017-06-06 05:47:05 +0000
+++ Mailman/Cgi/edithtml.py 2018-06-10 23:02:31 +0000
@@ -126,6 +126,11 @@
126 if cgidata.has_key('admlogin'):126 if cgidata.has_key('admlogin'):
127 # This is a re-authorization attempt127 # This is a re-authorization attempt
128 msg = Bold(FontSize('+1', _('Authorization failed.'))).Format()128 msg = Bold(FontSize('+1', _('Authorization failed.'))).Format()
129 remote = os.environ.get('HTTP_FORWARDED_FOR',
130 os.environ.get('HTTP_X_FORWARDED_FOR',
131 os.environ.get('REMOTE_ADDR',
132 'unidentified origin')))
133 syslog('security', 'Authorization failed (edithtml): list=%s: remote=%s', listname, remote)
129 else:134 else:
130 msg = ''135 msg = ''
131 Auth.loginpage(mlist, 'admin', msg=msg)136 Auth.loginpage(mlist, 'admin', msg=msg)
132137
=== modified file 'Mailman/Cgi/options.py'
--- Mailman/Cgi/options.py 2018-02-04 16:41:19 +0000
+++ Mailman/Cgi/options.py 2018-06-10 23:02:31 +0000
@@ -288,13 +288,15 @@
288 # message.288 # message.
289 if cgidata.has_key('password'):289 if cgidata.has_key('password'):
290 doc.addError(_('Authentication failed.'))290 doc.addError(_('Authentication failed.'))
291 remote = os.environ.get('HTTP_FORWARDED_FOR',
292 os.environ.get('HTTP_X_FORWARDED_FOR',
293 os.environ.get('REMOTE_ADDR',
294 'unidentified origin')))
295 syslog('security', 'Authorization failed (private): user=%s
296 list=%s remote=%s', user, listname, remote)
291 # So as not to allow membership leakage, prompt for the email297 # So as not to allow membership leakage, prompt for the email
292 # address and the password here.298 # address and the password here.
293 if mlist.private_roster <> 0:299 if mlist.private_roster <> 0:
294 remote = os.environ.get('HTTP_FORWARDED_FOR',
295 os.environ.get('HTTP_X_FORWARDED_FOR',
296 os.environ.get('REMOTE_ADDR',
297 'unidentified origin')))
298 syslog('mischief',300 syslog('mischief',
299 'Login failure with private rosters: %s from %s',301 'Login failure with private rosters: %s from %s',
300 user, remote)302 user, remote)
301303
=== modified file 'Mailman/Cgi/private.py'
--- Mailman/Cgi/private.py 2017-06-06 05:47:05 +0000
+++ Mailman/Cgi/private.py 2018-06-10 23:02:31 +0000
@@ -142,6 +142,12 @@
142 if cgidata.has_key('submit'):142 if cgidata.has_key('submit'):
143 # This is a re-authorization attempt143 # This is a re-authorization attempt
144 message = Bold(FontSize('+1', _('Authorization failed.'))).Format()144 message = Bold(FontSize('+1', _('Authorization failed.'))).Format()
145 remote = os.environ.get('HTTP_FORWARDED_FOR',
146 os.environ.get('HTTP_X_FORWARDED_FOR',
147 os.environ.get('REMOTE_ADDR',
148 'unidentified origin')))
149 syslog('security', 'Authorization failed (private): user=%s list=%s
150 remote=%s', username, listname, remote)
145 # give an HTTP 401 for authentication failure151 # give an HTTP 401 for authentication failure
146 print 'Status: 401 Unauthorized'152 print 'Status: 401 Unauthorized'
147 # Are we processing a password reminder from the login screen?153 # Are we processing a password reminder from the login screen?
148154
=== modified file 'Mailman/Cgi/roster.py'
--- Mailman/Cgi/roster.py 2017-06-06 03:48:34 +0000
+++ Mailman/Cgi/roster.py 2018-06-10 23:02:31 +0000
@@ -118,6 +118,11 @@
118 error_page_doc(doc, _('%(realname)s roster authentication failed.'))118 error_page_doc(doc, _('%(realname)s roster authentication failed.'))
119 doc.AddItem(mlist.GetMailmanFooter())119 doc.AddItem(mlist.GetMailmanFooter())
120 print doc.Format()120 print doc.Format()
121 remote = os.environ.get('HTTP_FORWARDED_FOR',
122 os.environ.get('HTTP_X_FORWARDED_FOR',
123 os.environ.get('REMOTE_ADDR',
124 'unidentified origin')))
125 syslog('security', 'Authorization failed (roster): list=%s: remote=%s', listname, remote)
121 return126 return
122127
123 # The document and its language128 # The document and its language
124129
=== modified file 'Mailman/Utils.py'
--- Mailman/Utils.py 2018-06-05 19:14:08 +0000
+++ Mailman/Utils.py 2018-06-10 23:02:31 +0000
@@ -111,7 +111,11 @@
111 # But first ensure the list name doesn't contain a path traversal111 # But first ensure the list name doesn't contain a path traversal
112 # attack.112 # attack.
113 if len(re.sub(mm_cfg.ACCEPTABLE_LISTNAME_CHARACTERS, '', listname)) > 0:113 if len(re.sub(mm_cfg.ACCEPTABLE_LISTNAME_CHARACTERS, '', listname)) > 0:
114 syslog('mischief', 'Hostile listname: %s', listname)114 remote = os.environ.get('HTTP_FORWARDED_FOR',
115 os.environ.get('HTTP_X_FORWARDED_FOR',
116 os.environ.get('REMOTE_ADDR',
117 'unidentified origin')))
118 syslog('mischief', 'Hostile listname: listname=%s remote=%s', listname, remote)
115 return False119 return False
116 basepath = Site.get_listpath(listname)120 basepath = Site.get_listpath(listname)
117 for ext in ('.pck', '.pck.last', '.db', '.db.last'):121 for ext in ('.pck', '.pck.last', '.db', '.db.last'):