summary refs log tree commit diff
path: root/synapse/api/auth.py
diff options
context:
space:
mode:
authorRichard van der Hoff <richard@matrix.org>2019-01-11 10:21:18 +0000
committerRichard van der Hoff <richard@matrix.org>2019-01-11 10:21:18 +0000
commit892f6c98ec58933a7f45fed895f40f5bc6a78b9c (patch)
tree6fe0cb6f181d0cc1c5e432039b42dd6a36359333 /synapse/api/auth.py
parentMerge branch 'develop' of github.com:matrix-org/synapse into matrix-org-hotfixes (diff)
parentchangelog (diff)
downloadsynapse-892f6c98ec58933a7f45fed895f40f5bc6a78b9c.tar.xz
Merge tag 'v0.34.1.1' into matrix-org-hotfixes
Synapse 0.34.1.1 (2019-01-11)
=============================

This release fixes CVE-2019-5885 and is recommended for all users of Synapse 0.34.1.

This release is compatible with Python 2.7 and 3.5+. Python 3.7 is fully supported.

Bugfixes
--------

- Fix spontaneous logout on upgrade
  ([\#4374](https://github.com/matrix-org/synapse/issues/4374))
Diffstat (limited to 'synapse/api/auth.py')
-rw-r--r--synapse/api/auth.py65
1 files changed, 27 insertions, 38 deletions
diff --git a/synapse/api/auth.py b/synapse/api/auth.py

index b8a9af7158..ba1019b9b2 100644 --- a/synapse/api/auth.py +++ b/synapse/api/auth.py
@@ -300,20 +300,28 @@ class Auth(object): Raises: AuthError if no user by that token exists or the token is invalid. """ - try: - user_id, guest = self._parse_and_validate_macaroon(token, rights) - except _InvalidMacaroonException: - # doesn't look like a macaroon: treat it as an opaque token which - # must be in the database. - # TODO: it would be nice to get rid of this, but apparently some - # people use access tokens which aren't macaroons + + if rights == "access": + # first look in the database r = yield self._look_up_user_by_access_token(token) - defer.returnValue(r) + if r: + defer.returnValue(r) + # otherwise it needs to be a valid macaroon try: + user_id, guest = self._parse_and_validate_macaroon(token, rights) user = UserID.from_string(user_id) - if guest: + if rights == "access": + if not guest: + # non-guest access tokens must be in the database + logger.warning("Unrecognised access token - not in store.") + raise AuthError( + self.TOKEN_NOT_FOUND_HTTP_STATUS, + "Unrecognised access token.", + errcode=Codes.UNKNOWN_TOKEN, + ) + # Guest access tokens are not stored in the database (there can # only be one access token per guest, anyway). # @@ -354,31 +362,15 @@ class Auth(object): "device_id": None, } else: - # This codepath exists for several reasons: - # * so that we can actually return a token ID, which is used - # in some parts of the schema (where we probably ought to - # use device IDs instead) - # * the only way we currently have to invalidate an - # access_token is by removing it from the database, so we - # have to check here that it is still in the db - # * some attributes (notably device_id) aren't stored in the - # macaroon. They probably should be. - # TODO: build the dictionary from the macaroon once the - # above are fixed - ret = yield self._look_up_user_by_access_token(token) - if ret["user"] != user: - logger.error( - "Macaroon user (%s) != DB user (%s)", - user, - ret["user"] - ) - raise AuthError( - self.TOKEN_NOT_FOUND_HTTP_STATUS, - "User mismatch in macaroon", - errcode=Codes.UNKNOWN_TOKEN - ) + raise RuntimeError("Unknown rights setting %s", rights) defer.returnValue(ret) - except (pymacaroons.exceptions.MacaroonException, TypeError, ValueError): + except ( + _InvalidMacaroonException, + pymacaroons.exceptions.MacaroonException, + TypeError, + ValueError, + ) as e: + logger.warning("Invalid macaroon in auth: %s %s", type(e), e) raise AuthError( self.TOKEN_NOT_FOUND_HTTP_STATUS, "Invalid macaroon passed.", errcode=Codes.UNKNOWN_TOKEN @@ -508,11 +500,8 @@ class Auth(object): def _look_up_user_by_access_token(self, token): ret = yield self.store.get_user_by_access_token(token) if not ret: - logger.warn("Unrecognised access token - not in store.") - raise AuthError( - self.TOKEN_NOT_FOUND_HTTP_STATUS, "Unrecognised access token.", - errcode=Codes.UNKNOWN_TOKEN - ) + defer.returnValue(None) + # we use ret.get() below because *lots* of unit tests stub out # get_user_by_access_token in a way where it only returns a couple of # the fields.