~mailman-coders/mailman/2.1

« back to all changes in this revision

Viewing changes to Mailman/CSRFcheck.py

  • Committer: Mark Sapiro
  • Date: 2021-11-22 04:31:11 UTC
  • Revision ID: mark@msapiro.net-20211122043111-v9n55ud4tk337ks6
Avoid NotAMemberError in CSRF check from user options page.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
""" Cross-Site Request Forgery checker """
19
19
 
20
20
import time
 
21
import urllib
21
22
import marshal
22
23
import binascii
23
24
 
24
25
from Mailman import mm_cfg
25
 
from Mailman.Utils import sha_new
 
26
from Mailman.Logging.Syslog import syslog
 
27
from Mailman.Utils import UnobscureEmail, sha_new
26
28
 
27
29
keydict = {
28
30
    'user':      mm_cfg.AuthUser,
37
39
def csrf_token(mlist, contexts, user=None):
38
40
    """ create token by mailman cookie generation algorithm """
39
41
 
 
42
    if user:
 
43
        # Unmunge a munged email address.
 
44
        user = UnobscureEmail(urllib.unquote(user))
 
45
        
40
46
    for context in contexts:
41
47
        key, secret = mlist.AuthContextInfo(context, user)
42
 
        if key:
 
48
        if key and secret:
43
49
            break
44
50
    else:
45
51
        return None     # not authenticated
49
55
    token = binascii.hexlify(marshal.dumps((issued, keymac)))
50
56
    return token
51
57
 
52
 
def csrf_check(mlist, token):
 
58
def csrf_check(mlist, token, options_user=None):
53
59
    """ check token by mailman cookie validation algorithm """
54
 
 
55
60
    try:
56
61
        issued, keymac = marshal.loads(binascii.unhexlify(token))
57
62
        key, received_mac = keymac.split(':', 1)
62
67
            key, user = key.split('+', 1)
63
68
        else:
64
69
            user = None
 
70
        if user:
 
71
            # This is for CVE-2021-42097.  The token is a user token because
 
72
            # of the fix for CVE-2021-42096 but it must match the user for
 
73
            # whom the options page is requested.
 
74
            raw_user = UnobscureEmail(urllib.unquote(user))
 
75
            if options_user and options_user != raw_user:
 
76
                syslog('mischief',
 
77
                       'Form for user %s submitted with CSRF token '
 
78
                       'issued for %s.',
 
79
                       options_user, raw_user)
 
80
                return False
65
81
        context = keydict.get(key)
66
82
        key, secret = mlist.AuthContextInfo(context, user)
67
83
        assert key