diff --git a/Mailman/Cgi/admindb.py b/Mailman/Cgi/admindb.py index d187332..defc58d 100644 --- a/Mailman/Cgi/admindb.py +++ b/Mailman/Cgi/admindb.py @@ -39,6 +39,7 @@ from Mailman.ListAdmin import readMessage from Mailman.Cgi import Auth from Mailman.htmlformat import * from Mailman.Logging.Syslog import syslog +from Mailman.CSRFcheck import csrf_check EMPTYSTRING = '' NL = '\n' @@ -51,6 +52,9 @@ i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE) EXCERPT_HEIGHT = 10 EXCERPT_WIDTH = 76 +AUTH_CONTEXTS = (mm_cfg.AuthListAdmin, mm_cfg.AuthSiteAdmin, + mm_cfg.AuthListModerator) + def helds_by_sender(mlist): @@ -100,6 +104,18 @@ def main(): # Make sure the user is authorized to see this page. cgidata = cgi.FieldStorage(keep_blank_values=1) + # CSRF check + safe_params = ['adminpw', 'admlogin', 'msgid', 'sender', 'details'] + params = cgidata.keys() + if set(params) - set(safe_params): + csrf_checked = csrf_check(mlist, cgidata.getvalue('csrf_token')) + else: + csrf_checked = True + # if password is present, void cookie to force password authentication. + if cgidata.getvalue('adminpw'): + os.environ['HTTP_COOKIE'] = '' + csrf_checked = True + if not mlist.WebAuthenticate((mm_cfg.AuthListAdmin, mm_cfg.AuthListModerator, mm_cfg.AuthSiteAdmin), @@ -177,7 +193,11 @@ def main(): elif not details: # This is a form submission doc.SetTitle(_('%(realname)s Administrative Database Results')) - process_form(mlist, doc, cgidata) + if csrf_checked: + process_form(mlist, doc, cgidata) + else: + doc.addError( + _('The form lifetime has expired. (request forgery check)')) # Now print the results and we're done. Short circuit for when there # are no pending requests, but be sure to save the results! admindburl = mlist.GetScriptURL('admindb', absolute=1) @@ -198,7 +218,7 @@ def main(): mlist.Save() return - form = Form(admindburl) + form = Form(admindburl, mlist=mlist, contexts=AUTH_CONTEXTS) # Add the instructions template if details == 'instructions': doc.AddItem(Header( diff --git a/Mailman/Cgi/edithtml.py b/Mailman/Cgi/edithtml.py index ee1ccd0..5c9416e 100644 --- a/Mailman/Cgi/edithtml.py +++ b/Mailman/Cgi/edithtml.py @@ -30,9 +30,12 @@ from Mailman import Errors from Mailman.Cgi import Auth from Mailman.Logging.Syslog import syslog from Mailman import i18n +from Mailman.CSRFcheck import csrf_check _ = i18n._ +AUTH_CONTEXTS = (mm_cfg.AuthListAdmin, mm_cfg.AuthSiteAdmin) + def main(): @@ -82,6 +85,18 @@ def main(): # Must be authenticated to get any farther cgidata = cgi.FieldStorage() + # CSRF check + safe_params = ['VARHELP', 'adminpw', 'admlogin'] + params = cgidata.keys() + if set(params) - set(safe_params): + csrf_checked = csrf_check(mlist, cgidata.getvalue('csrf_token')) + else: + csrf_checked = True + # if password is present, void cookie to force password authentication. + if cgidata.getvalue('adminpw'): + os.environ['HTTP_COOKIE'] = '' + csrf_checked = True + # Editing the html for a list is limited to the list admin and site admin. if not mlist.WebAuthenticate((mm_cfg.AuthListAdmin, mm_cfg.AuthSiteAdmin), @@ -126,7 +141,11 @@ def main(): try: if cgidata.keys(): - ChangeHTML(mlist, cgidata, template_name, doc) + if csrf_checked: + ChangeHTML(mlist, cgidata, template_name, doc) + else: + doc.addError( + _('The form lifetime has expired. (request forgery check)')) FormatHTML(mlist, doc, template_name, template_info) finally: doc.AddItem(mlist.GetMailmanFooter()) @@ -145,7 +164,8 @@ def FormatHTML(mlist, doc, template_name, template_info): doc.AddItem(FontSize("+1", link)) doc.AddItem('
') doc.AddItem('