Projet

Général

Profil

0001-Make-get_user_from_api_query_string-report-detailed-.patch

Benjamin Dauvergne, 18 septembre 2014 11:55

Télécharger (3,5 ko)

Voir les différences:

Subject: [PATCH] Make get_user_from_api_query_string() report detailed errors
 when signature checking fails

 wcs/api.py |   35 ++++++++++++++++++++++-------------
 1 file changed, 22 insertions(+), 13 deletions(-)
wcs/api.py
20 20
import datetime
21 21

  
22 22
from quixote import get_request, get_publisher
23
from qommon.errors import AccessForbiddenError
23 24

  
24 25
def get_user_from_api_query_string():
25 26
    query_string = get_request().get_query()
26 27
    if not query_string:
27 28
        return None
29
    signature = get_request().form.get('signature')
30
    if not isinstance(signature, basestring):
31
        return None
28 32
    # verify signature
29 33
    orig = get_request().form.get('orig')
30 34
    if not isinstance(orig, basestring):
31
        return None
35
        raise AccessForbiddenError('missing/multiple orig field')
32 36
    key = get_publisher().get_site_option(orig, 'api-secrets')
33 37
    if not key:
34
        return None
35
    signature = get_request().form.get('signature')
36
    if not isinstance(signature, basestring):
37
        return None
38
        raise AccessForbiddenError('invalid orig')
38 39
    algo = get_request().form.get('algo')
39 40
    if not isinstance(algo, basestring):
40
        return None
41
        raise AccessForbiddenError('missing/multiple algo field')
41 42
    try:
42 43
        algo = getattr(hashlib, algo)
43 44
    except AttributeError:
44
        algo = hashlib.sha256
45
        raise AccessForbiddenError('invalid algo')
45 46
    if signature != base64.standard_b64encode(hmac.new(key,
46 47
                            query_string[:query_string.find('&signature=')],
47 48
                            algo).digest()):
48
        return None
49
        raise AccessForbiddenError('invalid signature')
49 50
    timestamp = get_request().form.get('timestamp')
50 51
    if not isinstance(timestamp, basestring):
51
        return None
52
        raise AccessForbiddenError('missing/multiple timestamp field')
52 53
    delta = (datetime.datetime.utcnow().replace(tzinfo=None) -
53 54
             datetime.datetime.strptime(timestamp,
54 55
                     '%Y-%m-%dT%H:%M:%SZ'))
55
    if abs(delta) > datetime.timedelta(seconds=30):
56
        return None
56
    MAX_DELTA = 30
57
    if abs(delta) > datetime.timedelta(seconds=MAX_DELTAT):
58
        raise AccessForbiddenError('timestamp delta is more '
59
                'than %s seconds: %s seconds' % (MAX_DELTA, delta))
57 60

  
58 61
    user = None
59 62
    if get_request().form.get('email'):
60 63
        email = get_request().form.get('email')
61 64
        if not isinstance(email, basestring):
62
            return None
65
            raise AccessForbiddenError('multiple email field')
63 66
        users = list(get_publisher().user_class.get_users_with_email(email))
64 67
        if users:
65 68
            user = users[0]
69
        else:
70
            raise AccessForbiddenError('unknown email')
66 71
    elif get_request().form.get('NameID'):
67 72
        ni = get_request().form.get('NameID')
68 73
        if not isinstance(ni, basestring):
69
            return None
74
            raise AccessForbiddenError('multiple NameID field')
70 75
        users = list(get_publisher().user_class.get_users_with_name_identifier(ni))
71 76
        if users:
72 77
            user = users[0]
78
        else:
79
            raise AccessForbiddenError('unknown NameID')
80
    else:
81
        raise AccessForbiddenError('missing email or NameID fields')
73 82

  
74 83
    return user
75
-