Esempio n. 1
0
 def verify_json_for_server(self, server_name, json_object):
     logger.debug("Verifying for %s", server_name)
     key_ids = signature_ids(json_object, server_name)
     if not key_ids:
         raise SynapseError(
             400,
             "Not signed with a supported algorithm",
             Codes.UNAUTHORIZED,
         )
     try:
         verify_key = yield self.get_server_verify_key(server_name, key_ids)
     except IOError:
         raise SynapseError(
             502,
             "Error downloading keys for %s" % (server_name, ),
             Codes.UNAUTHORIZED,
         )
     except:
         raise SynapseError(
             401,
             "No key for %s with id %s" % (server_name, key_ids),
             Codes.UNAUTHORIZED,
         )
     try:
         verify_signed_json(json_object, server_name, verify_key)
     except:
         raise SynapseError(
             401,
             "Invalid signature for server %s with key %s:%s" %
             (server_name, verify_key.alg, verify_key.version),
             Codes.UNAUTHORIZED,
         )
Esempio n. 2
0
 def verify_json_for_server(self, server_name, json_object):
     logger.debug("Verifying for %s", server_name)
     key_ids = signature_ids(json_object, server_name)
     if not key_ids:
         raise SynapseError(
             400,
             "Not signed with a supported algorithm",
             Codes.UNAUTHORIZED,
         )
     try:
         verify_key = yield self.get_server_verify_key(server_name, key_ids)
     except IOError:
         raise SynapseError(
             502,
             "Error downloading keys for %s" % (server_name,),
             Codes.UNAUTHORIZED,
         )
     except:
         raise SynapseError(
             401,
             "No key for %s with id %s" % (server_name, key_ids),
             Codes.UNAUTHORIZED,
         )
     try:
         verify_signed_json(json_object, server_name, verify_key)
     except:
         raise SynapseError(
             401,
             "Invalid signature for server %s with key %s:%s" % (
                 server_name, verify_key.alg, verify_key.version
             ),
             Codes.UNAUTHORIZED,
         )
Esempio n. 3
0
    def verify_json_objects_for_server(self, server_and_json):
        """Bulk verfies signatures of json objects, bulk fetching keys as
        necessary.

        Args:
            server_and_json (list): List of pairs of (server_name, json_object)

        Returns:
            list of deferreds indicating success or failure to verify each
            json object's signature for the given server_name.
        """
        group_id_to_json = {}
        group_id_to_group = {}
        group_ids = []

        next_group_id = 0
        deferreds = {}

        for server_name, json_object in server_and_json:
            logger.debug("Verifying for %s", server_name)
            group_id = next_group_id
            next_group_id += 1
            group_ids.append(group_id)

            key_ids = signature_ids(json_object, server_name)
            if not key_ids:
                deferreds[group_id] = defer.fail(SynapseError(
                    400,
                    "Not signed with a supported algorithm",
                    Codes.UNAUTHORIZED,
                ))
            else:
                deferreds[group_id] = defer.Deferred()

            group = KeyGroup(server_name, group_id, key_ids)

            group_id_to_group[group_id] = group
            group_id_to_json[group_id] = json_object

        @defer.inlineCallbacks
        def handle_key_deferred(group, deferred):
            server_name = group.server_name
            try:
                _, _, key_id, verify_key = yield deferred
            except IOError as e:
                logger.warn(
                    "Got IOError when downloading keys for %s: %s %s",
                    server_name, type(e).__name__, str(e.message),
                )
                raise SynapseError(
                    502,
                    "Error downloading keys for %s" % (server_name,),
                    Codes.UNAUTHORIZED,
                )
            except Exception as e:
                logger.exception(
                    "Got Exception when downloading keys for %s: %s %s",
                    server_name, type(e).__name__, str(e.message),
                )
                raise SynapseError(
                    401,
                    "No key for %s with id %s" % (server_name, key_ids),
                    Codes.UNAUTHORIZED,
                )

            json_object = group_id_to_json[group.group_id]

            try:
                verify_signed_json(json_object, server_name, verify_key)
            except:
                raise SynapseError(
                    401,
                    "Invalid signature for server %s with key %s:%s" % (
                        server_name, verify_key.alg, verify_key.version
                    ),
                    Codes.UNAUTHORIZED,
                )

        server_to_deferred = {
            server_name: defer.Deferred()
            for server_name, _ in server_and_json
        }

        # We want to wait for any previous lookups to complete before
        # proceeding.
        wait_on_deferred = self.wait_for_previous_lookups(
            [server_name for server_name, _ in server_and_json],
            server_to_deferred,
        )

        # Actually start fetching keys.
        wait_on_deferred.addBoth(
            lambda _: self.get_server_verify_keys(group_id_to_group, deferreds)
        )

        # When we've finished fetching all the keys for a given server_name,
        # resolve the deferred passed to `wait_for_previous_lookups` so that
        # any lookups waiting will proceed.
        server_to_gids = {}

        def remove_deferreds(res, server_name, group_id):
            server_to_gids[server_name].discard(group_id)
            if not server_to_gids[server_name]:
                server_to_deferred.pop(server_name).callback(None)
            return res

        for g_id, deferred in deferreds.items():
            server_name = group_id_to_group[g_id].server_name
            server_to_gids.setdefault(server_name, set()).add(g_id)
            deferred.addBoth(remove_deferreds, server_name, g_id)

        # Pass those keys to handle_key_deferred so that the json object
        # signatures can be verified
        return [
            handle_key_deferred(
                group_id_to_group[g_id],
                deferreds[g_id],
            )
            for g_id in group_ids
        ]
Esempio n. 4
0
    def verify_json_objects_for_server(self, server_and_json):
        """Bulk verfies signatures of json objects, bulk fetching keys as
        necessary.

        Args:
            server_and_json (list): List of pairs of (server_name, json_object)

        Returns:
            list of deferreds indicating success or failure to verify each
            json object's signature for the given server_name.
        """
        group_id_to_json = {}
        group_id_to_group = {}
        group_ids = []

        next_group_id = 0
        deferreds = {}

        for server_name, json_object in server_and_json:
            logger.debug("Verifying for %s", server_name)
            group_id = next_group_id
            next_group_id += 1
            group_ids.append(group_id)

            key_ids = signature_ids(json_object, server_name)
            if not key_ids:
                deferreds[group_id] = defer.fail(
                    SynapseError(
                        400,
                        "Not signed with a supported algorithm",
                        Codes.UNAUTHORIZED,
                    ))
            else:
                deferreds[group_id] = defer.Deferred()

            group = KeyGroup(server_name, group_id, key_ids)

            group_id_to_group[group_id] = group
            group_id_to_json[group_id] = json_object

        @defer.inlineCallbacks
        def handle_key_deferred(group, deferred):
            server_name = group.server_name
            try:
                _, _, key_id, verify_key = yield deferred
            except IOError as e:
                logger.warn(
                    "Got IOError when downloading keys for %s: %s %s",
                    server_name,
                    type(e).__name__,
                    str(e.message),
                )
                raise SynapseError(
                    502,
                    "Error downloading keys for %s" % (server_name, ),
                    Codes.UNAUTHORIZED,
                )
            except Exception as e:
                logger.exception(
                    "Got Exception when downloading keys for %s: %s %s",
                    server_name,
                    type(e).__name__,
                    str(e.message),
                )
                raise SynapseError(
                    401,
                    "No key for %s with id %s" % (server_name, key_ids),
                    Codes.UNAUTHORIZED,
                )

            json_object = group_id_to_json[group.group_id]

            try:
                verify_signed_json(json_object, server_name, verify_key)
            except:
                raise SynapseError(
                    401,
                    "Invalid signature for server %s with key %s:%s" %
                    (server_name, verify_key.alg, verify_key.version),
                    Codes.UNAUTHORIZED,
                )

        server_to_deferred = {
            server_name: defer.Deferred()
            for server_name, _ in server_and_json
        }

        # We want to wait for any previous lookups to complete before
        # proceeding.
        wait_on_deferred = self.wait_for_previous_lookups(
            [server_name for server_name, _ in server_and_json],
            server_to_deferred,
        )

        # Actually start fetching keys.
        wait_on_deferred.addBoth(lambda _: self.get_server_verify_keys(
            group_id_to_group, deferreds))

        # When we've finished fetching all the keys for a given server_name,
        # resolve the deferred passed to `wait_for_previous_lookups` so that
        # any lookups waiting will proceed.
        server_to_gids = {}

        def remove_deferreds(res, server_name, group_id):
            server_to_gids[server_name].discard(group_id)
            if not server_to_gids[server_name]:
                d = server_to_deferred.pop(server_name, None)
                if d:
                    d.callback(None)
            return res

        for g_id, deferred in deferreds.items():
            server_name = group_id_to_group[g_id].server_name
            server_to_gids.setdefault(server_name, set()).add(g_id)
            deferred.addBoth(remove_deferreds, server_name, g_id)

        # Pass those keys to handle_key_deferred so that the json object
        # signatures can be verified
        return [
            handle_key_deferred(
                group_id_to_group[g_id],
                deferreds[g_id],
            ) for g_id in group_ids
        ]