summary refs log tree commit diff
path: root/synapse
diff options
context:
space:
mode:
authorRichard van der Hoff <richard@matrix.org>2019-01-10 12:58:33 +0000
committerRichard van der Hoff <richard@matrix.org>2019-01-10 12:58:33 +0000
commitaa70d2412570d6d810fe8c0a625a41584c99b7d2 (patch)
treef3c8f54409fe6ecd3a6cb25a9f1a8aeeaf84596f /synapse
parentClarify that py2 packages will continue to exist (diff)
parentFix macaroon_secret_key fallback logic (diff)
downloadsynapse-aa70d2412570d6d810fe8c0a625a41584c99b7d2.tar.xz
Merge branch 'rav/macaroon_key_fix' into rav/macaroon_key_fix_0.34
Diffstat (limited to 'synapse')
-rw-r--r--synapse/api/auth.py65
-rw-r--r--synapse/config/key.py10
2 files changed, 32 insertions, 43 deletions
diff --git a/synapse/api/auth.py b/synapse/api/auth.py
index 5309899703..4811300c16 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.
diff --git a/synapse/config/key.py b/synapse/config/key.py
index 279c47bb48..c26b7529f2 100644
--- a/synapse/config/key.py
+++ b/synapse/config/key.py
@@ -57,8 +57,8 @@ class KeyConfig(Config):
             # Unfortunately, there are people out there that don't have this
             # set. Lets just be "nice" and derive one from their secret key.
             logger.warn("Config is missing missing macaroon_secret_key")
-            seed = self.signing_key[0].seed
-            self.macaroon_secret_key = hashlib.sha256(seed)
+            seed = bytes(self.signing_key[0])
+            self.macaroon_secret_key = hashlib.sha256(seed).digest()
 
         self.expire_access_token = config.get("expire_access_token", False)
 
@@ -71,14 +71,14 @@ class KeyConfig(Config):
         base_key_name = os.path.join(config_dir_path, server_name)
 
         if is_generating_file:
-            macaroon_secret_key = random_string_with_symbols(50)
+            macaroon_secret_key = '"%s"' % random_string_with_symbols(50)
             form_secret = '"%s"' % random_string_with_symbols(50)
         else:
-            macaroon_secret_key = None
+            macaroon_secret_key = 'null'
             form_secret = 'null'
 
         return """\
-        macaroon_secret_key: "%(macaroon_secret_key)s"
+        macaroon_secret_key: %(macaroon_secret_key)s
 
         # Used to enable access token expiration.
         expire_access_token: False