From: Ralf Jung Date: Sun, 3 Jan 2021 12:58:30 +0000 (+0100) Subject: update mailman patch X-Git-Url: https://git.ralfj.de/ansible.git/commitdiff_plain/ae3368ea92cc4894b83a452c77a2ec02ad61ee81?ds=inline update mailman patch --- diff --git a/roles/email/files/mailman-patched/Cgi/listinfo.py b/roles/email/files/mailman-patched/Cgi/listinfo.py index b46bab1..0e38d03 100644 --- a/roles/email/files/mailman-patched/Cgi/listinfo.py +++ b/roles/email/files/mailman-patched/Cgi/listinfo.py @@ -1,4 +1,4 @@ -# Copyright (C) 1998-2016 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2018 by the Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -38,8 +38,7 @@ _ = i18n._ i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE) - - + def main(): parts = Utils.GetPathPieces() if not parts: @@ -61,7 +60,7 @@ def main(): # See if the user want to see this page in other language cgidata = cgi.FieldStorage() try: - language = cgidata.getvalue('language') + language = cgidata.getfirst('language') except TypeError: # Someone crafted a POST with a bad Content-Type:. doc = Document() @@ -79,8 +78,7 @@ def main(): list_listinfo(mlist, language) - - + def listinfo_overview(msg=''): # Present the general listinfo overview hostname = Utils.get_domain() @@ -117,7 +115,7 @@ def listinfo_overview(msg=''): else: advertised.append((mlist.GetScriptURL('listinfo'), mlist.real_name, - Utils.websafe(mlist.description))) + Utils.websafe(mlist.GetDescription()))) if msg: greeting = FontAttr(msg, color="ff5060", size="+1") else: @@ -175,8 +173,7 @@ def listinfo_overview(msg=''): print doc.Format() - - + def list_listinfo(mlist, lang): # Generate list specific listinfo doc = HeadlessDocument() @@ -227,10 +224,10 @@ def list_listinfo(mlist, lang): # fill form replacements[''] += ( '\n' - % (now, captcha_idx, Utils.sha_new(mm_cfg.SUBSCRIBE_FORM_SECRET + - now + - captcha_idx + - mlist.internal_name() + + % (now, captcha_idx, Utils.sha_new(mm_cfg.SUBSCRIBE_FORM_SECRET + ":" + + now + ":" + + captcha_idx + ":" + + mlist.internal_name() + ":" + remote ).hexdigest() ) @@ -253,13 +250,25 @@ def list_listinfo(mlist, lang): replacements[''] = displang replacements[''] = mlist.FormatFormStart('listinfo') replacements[''] = mlist.FormatBox('fullname', size=30) + # If reCAPTCHA is enabled, display its user interface + if mm_cfg.RECAPTCHA_SITE_KEY: + noscript = _('This form requires JavaScript.') + replacements[''] = ( + """  + + +
+ """ + % (noscript, lang, mm_cfg.RECAPTCHA_SITE_KEY)) + else: + replacements[''] = '' # Do the expansion. doc.AddItem(mlist.ParseTags('listinfo.html', replacements, lang)) print doc.Format() - - + if __name__ == "__main__": main() diff --git a/roles/email/files/mailman-patched/Cgi/subscribe.py b/roles/email/files/mailman-patched/Cgi/subscribe.py index 153286d..ea4ef94 100644 --- a/roles/email/files/mailman-patched/Cgi/subscribe.py +++ b/roles/email/files/mailman-patched/Cgi/subscribe.py @@ -1,4 +1,4 @@ -# Copyright (C) 1998-2016 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2018 by the Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -22,6 +22,9 @@ import os import cgi import time import signal +import urllib +import urllib2 +import json from Mailman import mm_cfg from Mailman import Utils @@ -36,14 +39,14 @@ from Mailman.Logging.Syslog import syslog SLASH = '/' ERRORSEP = '\n\n

' +COMMASPACE = ', ' # Set up i18n _ = i18n._ i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE) - - + def main(): doc = Document() doc.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE) @@ -73,7 +76,7 @@ def main(): # for the results. If not, use the list's preferred language. cgidata = cgi.FieldStorage() try: - language = cgidata.getvalue('language', '') + language = cgidata.getfirst('language', '') except TypeError: # Someone crafted a POST with a bad Content-Type:. doc.AddItem(Header(2, _("Error"))) @@ -114,19 +117,18 @@ def main(): mlist.Unlock() - - + def process_form(mlist, doc, cgidata, lang): listowner = mlist.GetOwnerEmail() realname = mlist.real_name results = [] # The email address being subscribed, required - email = cgidata.getvalue('email', '').strip() + email = cgidata.getfirst('email', '').strip() if not email: results.append(_('You must supply a valid email address.')) - fullname = cgidata.getvalue('fullname', '') + fullname = cgidata.getfirst('fullname', '') # Canonicalize the full name fullname = Utils.canonstr(fullname, lang) # Who was doing the subscribing? @@ -134,6 +136,26 @@ def process_form(mlist, doc, cgidata, lang): os.environ.get('HTTP_X_FORWARDED_FOR', os.environ.get('REMOTE_ADDR', 'unidentified origin'))) + + # Check reCAPTCHA submission, if enabled + if mm_cfg.RECAPTCHA_SECRET_KEY: + request = urllib2.Request( + url = 'https://www.google.com/recaptcha/api/siteverify', + data = urllib.urlencode({ + 'secret': mm_cfg.RECAPTCHA_SECRET_KEY, + 'response': cgidata.getvalue('g-recaptcha-response', ''), + 'remoteip': remote})) + try: + httpresp = urllib2.urlopen(request) + captcha_response = json.load(httpresp) + httpresp.close() + if not captcha_response['success']: + e_codes = COMMASPACE.join(captcha_response['error-codes']) + results.append(_('reCAPTCHA validation failed: %(e_codes)s')) + except urllib2.URLError, e: + e_reason = e.reason + results.append(_('reCAPTCHA could not be validated: %(e_reason)s')) + # Are we checking the hidden data? if mm_cfg.SUBSCRIBE_FORM_SECRET: now = int(time.time()) @@ -147,15 +169,15 @@ def process_form(mlist, doc, cgidata, lang): # for our hash so it doesn't matter. remote1 = remote.rsplit(':', 1)[0] try: - ftime, fcaptcha_idx, fhash = cgidata.getvalue('sub_form_token', '').split(':') + ftime, fcaptcha_idx, fhash = cgidata.getfirst('sub_form_token', '').split(':') then = int(ftime) except ValueError: ftime = fcaptcha_idx = fhash = '' then = 0 - token = Utils.sha_new(mm_cfg.SUBSCRIBE_FORM_SECRET + - ftime + - fcaptcha_idx + - mlist.internal_name() + + token = Utils.sha_new(mm_cfg.SUBSCRIBE_FORM_SECRET + ":" + + ftime + ":" + + fcaptcha_idx + ":" + + mlist.internal_name() + ":" + remote1).hexdigest() if ftime and now - then > mm_cfg.FORM_LIFETIME: results.append(_('The form is too old. Please GET it again.')) @@ -169,17 +191,17 @@ def process_form(mlist, doc, cgidata, lang): results.append( _('There was no hidden token in your submission or it was corrupted.')) results.append(_('You must GET the form before submitting it.')) - # Check captcha - captcha_answer = cgidata.getvalue('captcha_answer', '') - if not Captcha.verify(fcaptcha_idx, captcha_answer, mm_cfg.CAPTCHAS): - results.append(_('This was not the right answer to the CAPTCHA question.')) + # Check captcha + captcha_answer = cgidata.getvalue('captcha_answer', '') + if not Captcha.verify(fcaptcha_idx, captcha_answer, mm_cfg.CAPTCHAS): + results.append(_('This was not the right answer to the CAPTCHA question.')) # Was an attempt made to subscribe the list to itself? if email == mlist.GetListEmail(): syslog('mischief', 'Attempt to self subscribe %s: %s', email, remote) results.append(_('You may not subscribe a list to itself!')) # If the user did not supply a password, generate one for him - password = cgidata.getvalue('pw', '').strip() - confirmed = cgidata.getvalue('pw-conf', '').strip() + password = cgidata.getfirst('pw', '').strip() + confirmed = cgidata.getfirst('pw-conf', '').strip() if not password and not confirmed: password = Utils.MakeRandomPassword() @@ -189,11 +211,11 @@ def process_form(mlist, doc, cgidata, lang): results.append(_('Your passwords did not match.')) # Get the digest option for the subscription. - digestflag = cgidata.getvalue('digest') + digestflag = cgidata.getfirst('digest') if digestflag: try: digest = int(digestflag) - except ValueError: + except (TypeError, ValueError): digest = 0 else: digest = mlist.digest_is_default @@ -318,8 +340,7 @@ You have been successfully subscribed to the %(realname)s mailing list.""") print_results(mlist, results, doc, lang) - - + def print_results(mlist, results, doc, lang): # The bulk of the document will come from the options.html template, which # includes its own html armor (head tags, etc.). Suppress the head that diff --git a/roles/email/tasks/mailman.yml b/roles/email/tasks/mailman.yml index 0988edb..cba4519 100644 --- a/roles/email/tasks/mailman.yml +++ b/roles/email/tasks/mailman.yml @@ -21,8 +21,8 @@ - name: check if all the files have the right checksums to be patched shell: 'echo "{{item}}" | sha256sum -c' loop: - - "26b4cbb7c5bde8badf741e31975235e74abb932037d77d862cf00b412726c2c2 /usr/lib/mailman/Mailman/Cgi/listinfo.py" - - "cbef3d8cb6b65e4c9b2462f8627966d55dd52caa2e626c87241c4f8d47477dc7 /usr/lib/mailman/Mailman/Cgi/subscribe.py" + - "621368ef38d991be46e4537b1d5444276579cd60cc721a749d500dd0b98efe27 /usr/lib/mailman/Mailman/Cgi/listinfo.py" + - "c6e46afe1c016d6853c8397916a6f6fd88c6cea71ae890ef3680617f1f8f7c9a /usr/lib/mailman/Mailman/Cgi/subscribe.py" changed_when: False when: mailman_patched.rc != 0 - name: install patched python files