"Fossies" - the Fresh Open Source Software Archive

Member "mailman-2.1.39/Mailman/CSRFcheck.py" (13 Dec 2021, 3867 Bytes) of package /linux/misc/mailman-2.1.39.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "CSRFcheck.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.1.38_vs_2.1.39.

    1 # Copyright (C) 2011-2018 by the Free Software Foundation, Inc.
    2 #
    3 # This program is free software; you can redistribute it and/or
    4 # modify it under the terms of the GNU General Public License
    5 # as published by the Free Software Foundation; either version 2
    6 # of the License, or (at your option) any later version.
    7 #
    8 # This program is distributed in the hope that it will be useful,
    9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
   10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11 # GNU General Public License for more details.
   12 #
   13 # You should have received a copy of the GNU General Public License
   14 # along with this program; if not, write to the Free Software
   15 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
   16 # USA.
   17 
   18 """ Cross-Site Request Forgery checker """
   19 
   20 import time
   21 import urllib
   22 import marshal
   23 import binascii
   24 
   25 from Mailman import mm_cfg
   26 from Mailman.Logging.Syslog import syslog
   27 from Mailman.Utils import UnobscureEmail, sha_new
   28 
   29 keydict = {
   30     'user':      mm_cfg.AuthUser,
   31     'poster':    mm_cfg.AuthListPoster,
   32     'moderator': mm_cfg.AuthListModerator,
   33     'admin':     mm_cfg.AuthListAdmin,
   34     'site':      mm_cfg.AuthSiteAdmin,
   35 }
   36 
   37 
   38 
   39 def csrf_token(mlist, contexts, user=None):
   40     """ create token by mailman cookie generation algorithm """
   41 
   42     if user:
   43         # Unmunge a munged email address.
   44         user = UnobscureEmail(urllib.unquote(user))
   45         
   46     for context in contexts:
   47         key, secret = mlist.AuthContextInfo(context, user)
   48         if key and secret:
   49             break
   50     else:
   51         return None     # not authenticated
   52     issued = int(time.time())
   53     mac = sha_new(secret + `issued`).hexdigest()
   54     keymac = '%s:%s' % (key, mac)
   55     token = binascii.hexlify(marshal.dumps((issued, keymac)))
   56     return token
   57 
   58 def csrf_check(mlist, token, cgi_user=None):
   59     """ check token by mailman cookie validation algorithm """
   60     try:
   61         issued, keymac = marshal.loads(binascii.unhexlify(token))
   62         key, received_mac = keymac.split(':', 1)
   63         if not key.startswith(mlist.internal_name() + '+'):
   64             return False
   65         key = key[len(mlist.internal_name()) + 1:]
   66         if '+' in key:
   67             key, user = key.split('+', 1)
   68         else:
   69             user = None
   70         # Don't allow unprivileged tokens for admin or admindb.
   71         if cgi_user == 'admin':
   72             if key not in ('admin', 'site'):
   73                 syslog('mischief',
   74                        'admin form submitted with CSRF token issued for %s.',
   75                        key + '+' + user if user else key)
   76                 return False
   77         elif cgi_user == 'admindb':
   78             if key not in ('moderator', 'admin', 'site'):
   79                 syslog('mischief',
   80                        'admindb form submitted with CSRF token issued for %s.',
   81                        key + '+' + user if user else key)
   82                 return False
   83         if user:
   84             # This is for CVE-2021-42097.  The token is a user token because
   85             # of the fix for CVE-2021-42096 but it must match the user for
   86             # whom the options page is requested.
   87             raw_user = UnobscureEmail(urllib.unquote(user))
   88             if cgi_user and cgi_user.lower() != raw_user.lower():
   89                 syslog('mischief',
   90                        'Form for user %s submitted with CSRF token '
   91                        'issued for %s.',
   92                        cgi_user, raw_user)
   93                 return False
   94         context = keydict.get(key)
   95         key, secret = mlist.AuthContextInfo(context, user)
   96         assert key
   97         mac = sha_new(secret + `issued`).hexdigest()
   98         if (mac == received_mac 
   99             and 0 < time.time() - issued < mm_cfg.FORM_LIFETIME):
  100             return True
  101         return False
  102     except (AssertionError, ValueError, TypeError):
  103         return False