Example #1
0
    def test_to_utf8(self):
        res = webapp2._to_utf8('ábcdéf'.decode('utf-8')
                               if six.PY2 else 'ábcdéf')
        self.assertIsInstance(res, six.binary_type, True)

        res = webapp2._to_utf8('abcdef')
        self.assertIsInstance(res, six.binary_type, True)
Example #2
0
    def generate_token_string(self, action=None):
        """Generate a hash of the given token contents that can be verified.

        :param action:
            A string representing the action that the generated hash is valid
            for. This string is usually a URL.
        :returns:
            A string containing the hash contents of the given `action` and the
            contents of the `XSRFToken`. Can be verified with
            `verify_token_string`. The string is base64 encoded so it is safe
            to use in HTML forms without escaping.
        """
        digest_maker = self._digest_maker()
        digest_maker.update(self.user_id)
        digest_maker.update(self._DELIMITER)
        if action:
            digest_maker.update(webapp2._to_utf8(action))
            digest_maker.update(self._DELIMITER)

        digest_maker.update(self.current_time)
        return base64.urlsafe_b64encode(
            self._DELIMITER.join([
                webapp2._to_utf8(digest_maker.hexdigest()),
                self.current_time
            ])
        )
Example #3
0
    def test_to_utf8(self):
        res = webapp2._to_utf8(
            "ábcdéf".decode("utf-8") if six.PY2 else "ábcdéf")
        self.assertIsInstance(res, bytes, True)

        res = webapp2._to_utf8("abcdef")
        self.assertIsInstance(res, bytes, True)
Example #4
0
    def test_to_utf8(self):
        res = webapp2._to_utf8(
            'ábcdéf'.decode('utf-8') if six.PY2 else 'ábcdéf')
        self.assertIsInstance(res, six.binary_type, True)

        res = webapp2._to_utf8('abcdef')
        self.assertIsInstance(res, six.binary_type, True)
Example #5
0
    def serialize(self, name, value):
        """Serializes a signed cookie value.

        :param name:
            Cookie name.
        :param value:
            Cookie value to be serialized.
        :returns:
            A serialized value ready to be stored in a cookie.
        """
        name = webapp2._to_utf8(name)
        timestamp = webapp2._to_utf8(str(self._get_timestamp()))
        value = self._encode(value)
        signature = self._get_signature(name, value, timestamp)
        return b'|'.join([value, timestamp, signature])
Example #6
0
    def test_extra_request_methods(self):
        allowed_methods_backup = app.allowed_methods
        webdav_methods = ('VERSION-CONTROL', 'UNLOCK', 'PROPFIND')

        for method in webdav_methods:
            # It is still not possible to use WebDav methods...
            req = webapp2.Request.blank('/webdav')
            req.method = method
            rsp = req.get_response(app)
            self.assertEqual(rsp.status_int, 501)

        # Let's extend ALLOWED_METHODS with some WebDav methods.
        app.allowed_methods = tuple(app.allowed_methods) + webdav_methods

        # self.assertEqual(
        # sorted(webapp2.get_valid_methods(WebDavHandler)),
        # sorted(list(webdav_methods)))

        # Now we can use WebDav methods...
        for method in webdav_methods:
            req = webapp2.Request.blank('/webdav')
            req.method = method
            rsp = req.get_response(app)
            self.assertEqual(rsp.status_int, 200)
            self.assertEqual(rsp.body, webapp2._to_utf8('Method: %s' % method))

        # Restore initial values.
        app.allowed_methods = allowed_methods_backup
        self.assertEqual(len(app.allowed_methods), 7)
Example #7
0
    def __init__(self, secret_key):
        """Initiliazes the serializer/deserializer.

        :param secret_key:
            A random string to be used as the HMAC secret for the cookie
            signature.
        """
        self.secret_key = webapp2._to_utf8(secret_key)
Example #8
0
    def deserialize(self, name, value, max_age=None):
        """Deserializes a signed cookie value.

        :param name:
            Cookie name.
        :param value:
            A cookie value to be deserialized.
        :param max_age:
            Maximum age in seconds for a valid cookie. If the cookie is older
            than this, returns None.
        :returns:
            The deserialized secure cookie, or None if it is not valid.
        """
        if not value:
            return None

        name = webapp2._to_utf8(name)
        value = webapp2._to_utf8(value)

        # Unquote for old WebOb.
        value = http_cookies._unquote(value)

        parts = value.split(b'|')
        if len(parts) != 3:
            return None

        signature = self._get_signature(name, parts[0], parts[1])

        if not security.compare_hashes(parts[2], signature):
            logging.warning('Invalid cookie signature %r', value)
            return None

        if max_age is not None:
            if int(parts[1]) < self._get_timestamp() - max_age:
                logging.warning('Expired cookie %r', value)
                return None

        try:
            return self._decode(parts[0])
        except Exception:
            logging.warning('Cookie value failed to be decoded: %r', parts[0])
            return None
Example #9
0
    def __init__(self, user_id, secret, current_time=None):
        """Initializes the XSRFToken object.

        :param user_id:
            A string representing the user that the token will be valid for.
        :param secret:
            A string containing a secret key that will be used to seed the
            hash used by the :class:`XSRFToken`.
        :param current_time:
            An int representing the number of seconds since the epoch. Will be
            used by `verify_token_string` to check for token expiry. If `None`
            then the current time will be used.
        """
        self.user_id = webapp2._to_utf8(user_id)
        self.secret = webapp2._to_utf8(secret)
        if current_time is None:
            self.current_time = int(time.time())
        else:
            self.current_time = int(current_time)

        self.current_time = webapp2._to_utf8(str(self.current_time))
Example #10
0
    def __init__(self, user_id, secret, current_time=None):
        """Initializes the XSRFToken object.

        :param user_id:
            A string representing the user that the token will be valid for.
        :param secret:
            A string containing a secret key that will be used to seed the
            hash used by the :class:`XSRFToken`.
        :param current_time:
            An int representing the number of seconds since the epoch. Will be
            used by `verify_token_string` to check for token expiry. If `None`
            then the current time will be used.
        """
        self.user_id = webapp2._to_utf8(user_id)
        self.secret = webapp2._to_utf8(secret)
        if current_time is None:
            self.current_time = int(time.time())
        else:
            self.current_time = int(current_time)

        self.current_time = webapp2._to_utf8(str(self.current_time))
Example #11
0
def hash_password(password, method, salt=None, pepper=None):
    """Hashes a password.

    Supports plaintext without salt, unsalted and salted passwords. In case
    salted passwords are used hmac is used.

    :param password:
        The password to be hashed.
    :param method:
        A method from ``hashlib``, e.g., `sha1` or `md5`, or `plain`.
    :param salt:
        A random salt string.
    :param pepper:
        A secret constant stored in the application code.
    :returns:
        A hashed password.

    This function was ported and adapted from `Werkzeug`_.
    """
    if method == 'plain':
        return password

    password = webapp2._to_utf8(password)

    method = getattr(hashlib, method, None)
    if not method:
        return None

    if salt:
        h = hmac.new(webapp2._to_utf8(salt), password, method)
    else:
        h = method(password)

    if pepper:
        h = hmac.new(
            webapp2._to_utf8(pepper), webapp2._to_utf8(h.hexdigest()), method)

    return h.hexdigest()
Example #12
0
def hash_password(password, method, salt=None, pepper=None):
    """Hashes a password.

    Supports plaintext without salt, unsalted and salted passwords. In case
    salted passwords are used hmac is used.

    :param password:
        The password to be hashed.
    :param method:
        A method from ``hashlib``, e.g., `sha1` or `md5`, or `plain`.
    :param salt:
        A random salt string.
    :param pepper:
        A secret constant stored in the application code.
    :returns:
        A hashed password.

    This function was ported and adapted from `Werkzeug`_.
    """
    password = webapp2._to_utf8(password)
    if method == 'plain':
        return password

    method = getattr(hashlib, method, None)
    if not method:
        return None

    if salt:
        h = hmac.new(webapp2._to_utf8(salt), password, method)
    else:
        h = method(password)

    if pepper:
        h = hmac.new(webapp2._to_utf8(pepper), h.hexdigest(), method)

    return h.hexdigest()
    def test_write(self):
        var_1 = NoStringOrUnicodeConversion()
        var_2 = StringConversion()
        var_3 = UnicodeConversion()

        rsp = webapp2.Response()
        rsp.write(var_1)
        rsp.write(var_2)
        rsp.write(var_3)
        self.assertEqual(rsp.body, webapp2._to_utf8('%rfoobar' % var_1))

        rsp = webapp2.Response()
        rsp.write(var_1)
        rsp.write(var_3)
        rsp.write(var_2)
        self.assertEqual(rsp.body, webapp2._to_utf8('%rbarfoo' % var_1))

        rsp = webapp2.Response()
        rsp.write(var_2)
        rsp.write(var_1)
        rsp.write(var_3)
        self.assertEqual(rsp.body, webapp2._to_utf8('foo%rbar' % var_1))

        rsp = webapp2.Response()
        rsp.write(var_2)
        rsp.write(var_3)
        rsp.write(var_1)
        self.assertEqual(rsp.body, webapp2._to_utf8('foobar%r' % var_1))

        rsp = webapp2.Response()
        rsp.write(var_3)
        rsp.write(var_1)
        rsp.write(var_2)
        self.assertEqual(rsp.body, webapp2._to_utf8('bar%rfoo' % var_1))

        rsp = webapp2.Response()
        rsp.write(var_3)
        rsp.write(var_2)
        rsp.write(var_1)
        self.assertEqual(rsp.body, webapp2._to_utf8('barfoo%r' % var_1))
Example #14
0
    def test_write(self):
        var_1 = NoStringOrUnicodeConversion()
        var_2 = StringConversion()
        var_3 = UnicodeConversion()

        rsp = webapp2.Response()
        rsp.write(var_1)
        rsp.write(var_2)
        rsp.write(var_3)
        self.assertEqual(rsp.body, webapp2._to_utf8('%rfoobar' % var_1))

        rsp = webapp2.Response()
        rsp.write(var_1)
        rsp.write(var_3)
        rsp.write(var_2)
        self.assertEqual(rsp.body, webapp2._to_utf8('%rbarfoo' % var_1))

        rsp = webapp2.Response()
        rsp.write(var_2)
        rsp.write(var_1)
        rsp.write(var_3)
        self.assertEqual(rsp.body, webapp2._to_utf8('foo%rbar' % var_1))

        rsp = webapp2.Response()
        rsp.write(var_2)
        rsp.write(var_3)
        rsp.write(var_1)
        self.assertEqual(rsp.body, webapp2._to_utf8('foobar%r' % var_1))

        rsp = webapp2.Response()
        rsp.write(var_3)
        rsp.write(var_1)
        rsp.write(var_2)
        self.assertEqual(rsp.body, webapp2._to_utf8('bar%rfoo' % var_1))

        rsp = webapp2.Response()
        rsp.write(var_3)
        rsp.write(var_2)
        rsp.write(var_1)
        self.assertEqual(rsp.body, webapp2._to_utf8('barfoo%r' % var_1))
Example #15
0
    def verify_token_string(self,
                            token_string,
                            action=None,
                            timeout=None,
                            current_time=None):
        """Generate a hash of the given token contents that can be verified.

        :param token_string:
            A string containing the hashed token (generated by
            `generate_token_string`).
        :param action:
            A string containing the action that is being verified.
        :param timeout:
            An int or float representing the number of seconds that the token
            is valid for. If None then tokens are valid forever.
        :current_time:
            An int representing the number of seconds since the epoch. Will be
            used by to check for token expiry if `timeout` is set. If `None`
            then the current time will be used.
        :raises:
            XSRFTokenMalformed if the given token_string cannot be parsed.
            XSRFTokenExpiredException if the given token string is expired.
            XSRFTokenInvalid if the given token string does not match the
            contents of the `XSRFToken`.
        """
        import binascii

        try:
            decoded_token_string = base64.urlsafe_b64decode(
                webapp2._to_utf8(token_string))
        except (TypeError, binascii.Error):
            raise XSRFTokenMalformed()

        split_token = decoded_token_string.split(self._DELIMITER)
        if len(split_token) != 2:
            raise XSRFTokenMalformed()

        try:
            token_time = int(split_token[1])
        except ValueError:
            raise XSRFTokenMalformed()

        if timeout is not None:
            if current_time is None:
                current_time = time.time()
            # If an attacker modifies the plain text time then
            # it will not match the hashed time so this check is sufficient.
            if (token_time + timeout) < current_time:
                raise XSRFTokenExpiredException()

        expected_token = XSRFToken(self.user_id, self.secret, token_time)
        expected_token_string = expected_token.generate_token_string(action)

        if len(expected_token_string) != len(token_string):
            raise XSRFTokenInvalid()

        # Compare the two strings in constant time to prevent timing attacks.
        different = 0
        for a, b in zip(
                webapp2._to_basestring(token_string),
                webapp2._to_basestring(expected_token_string)):
            different |= ord(a) ^ ord(b)
        if different:
            raise XSRFTokenInvalid()
Example #16
0
 def _get_signature(self, *parts):
     """Generates an HMAC signature."""
     signature = hmac.new(self.secret_key, digestmod=hashlib.sha1)
     signature.update(b'|'.join(parts))
     return webapp2._to_utf8(signature.hexdigest())
Example #17
0
    def test_to_utf8(self):
        res = webapp2._to_utf8('ábcdéf'.decode('utf-8'))
        self.assertEqual(isinstance(res, str), True)

        res = webapp2._to_utf8('abcdef')
        self.assertEqual(isinstance(res, str), True)
    def test_to_utf8(self):
        res = webapp2._to_utf8('ábcdéf'.decode('utf-8'))
        self.assertEqual(isinstance(res, str), True)

        res = webapp2._to_utf8('abcdef')
        self.assertEqual(isinstance(res, str), True)
Example #19
0
    def verify_token_string(self,
                            token_string,
                            action=None,
                            timeout=None,
                            current_time=None):
        """Generate a hash of the given token contents that can be verified.

        :param token_string:
            A string containing the hashed token (generated by
            `generate_token_string`).
        :param action:
            A string containing the action that is being verified.
        :param timeout:
            An int or float representing the number of seconds that the token
            is valid for. If None then tokens are valid forever.
        :current_time:
            An int representing the number of seconds since the epoch. Will be
            used by to check for token expiry if `timeout` is set. If `None`
            then the current time will be used.
        :raises:
            XSRFTokenMalformed if the given token_string cannot be parsed.
            XSRFTokenExpiredException if the given token string is expired.
            XSRFTokenInvalid if the given token string does not match the
            contents of the `XSRFToken`.
        """
        import binascii

        try:
            decoded_token_string = base64.urlsafe_b64decode(
                webapp2._to_utf8(token_string))
        except (TypeError, binascii.Error):
            raise XSRFTokenMalformed()

        split_token = decoded_token_string.split(self._DELIMITER)
        if len(split_token) != 2:
            raise XSRFTokenMalformed()

        try:
            token_time = int(split_token[1])
        except ValueError:
            raise XSRFTokenMalformed()

        if timeout is not None:
            if current_time is None:
                current_time = time.time()
            # If an attacker modifies the plain text time then
            # it will not match the hashed time so this check is sufficient.
            if (token_time + timeout) < current_time:
                raise XSRFTokenExpiredException()

        expected_token = XSRFToken(self.user_id, self.secret, token_time)
        expected_token_string = expected_token.generate_token_string(action)

        if len(expected_token_string) != len(token_string):
            raise XSRFTokenInvalid()

        # Compare the two strings in constant time to prevent timing attacks.
        different = 0
        for a, b in zip(webapp2._to_basestring(token_string),
                        webapp2._to_basestring(expected_token_string)):
            different |= ord(a) ^ ord(b)
        if different:
            raise XSRFTokenInvalid()