"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.

    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