コード例 #1
0
ファイル: auth.py プロジェクト: ldesiqueira/synapse-1
    def check_redaction(self, event, auth_events):
        """Check whether the event sender is allowed to redact the target event.

        Returns:
            True if the the sender is allowed to redact the target event if the
            target event was created by them.
            False if the sender is allowed to redact the target event with no
            further checks.

        Raises:
            AuthError if the event sender is definitely not allowed to redact
            the target event.
        """
        return event_auth.check_redaction(event, auth_events)
コード例 #2
0
ファイル: auth.py プロジェクト: matrix-org/synapse
    def check_redaction(self, room_version, event, auth_events):
        """Check whether the event sender is allowed to redact the target event.

        Returns:
            True if the the sender is allowed to redact the target event if the
                target event was created by them.
            False if the sender is allowed to redact the target event with no
                further checks.

        Raises:
            AuthError if the event sender is definitely not allowed to redact
                the target event.
        """
        return event_auth.check_redaction(room_version, event, auth_events)
コード例 #3
0
ファイル: message.py プロジェクト: mjvaldez/synapse
    async def persist_and_notify_client_event(self,
                                              requester,
                                              event,
                                              context,
                                              ratelimit=True,
                                              extra_users=[]) -> int:
        """Called when we have fully built the event, have already
        calculated the push actions for the event, and checked auth.

        This should only be run on the instance in charge of persisting events.
        """
        assert self._is_event_writer

        if ratelimit:
            # We check if this is a room admin redacting an event so that we
            # can apply different ratelimiting. We do this by simply checking
            # it's not a self-redaction (to avoid having to look up whether the
            # user is actually admin or not).
            is_admin_redaction = False
            if event.type == EventTypes.Redaction:
                original_event = await self.store.get_event(
                    event.redacts,
                    redact_behaviour=EventRedactBehaviour.AS_IS,
                    get_prev_content=False,
                    allow_rejected=False,
                    allow_none=True,
                )

                is_admin_redaction = (original_event and
                                      event.sender != original_event.sender)

            await self.base_handler.ratelimit(
                requester, is_admin_redaction=is_admin_redaction)

        await self.base_handler.maybe_kick_guest_users(event, context)

        if event.type == EventTypes.CanonicalAlias:
            # Validate a newly added alias or newly added alt_aliases.

            original_alias = None
            original_alt_aliases = set()

            original_event_id = event.unsigned.get("replaces_state")
            if original_event_id:
                original_event = await self.store.get_event(original_event_id)

                if original_event:
                    original_alias = original_event.content.get("alias", None)
                    original_alt_aliases = original_event.content.get(
                        "alt_aliases", [])

            # Check the alias is currently valid (if it has changed).
            room_alias_str = event.content.get("alias", None)
            directory_handler = self.hs.get_handlers().directory_handler
            if room_alias_str and room_alias_str != original_alias:
                await self._validate_canonical_alias(directory_handler,
                                                     room_alias_str,
                                                     event.room_id)

            # Check that alt_aliases is the proper form.
            alt_aliases = event.content.get("alt_aliases", [])
            if not isinstance(alt_aliases, (list, tuple)):
                raise SynapseError(400,
                                   "The alt_aliases property must be a list.",
                                   Codes.INVALID_PARAM)

            # If the old version of alt_aliases is of an unknown form,
            # completely replace it.
            if not isinstance(original_alt_aliases, (list, tuple)):
                original_alt_aliases = []

            # Check that each alias is currently valid.
            new_alt_aliases = set(alt_aliases) - set(original_alt_aliases)
            if new_alt_aliases:
                for alias_str in new_alt_aliases:
                    await self._validate_canonical_alias(
                        directory_handler, alias_str, event.room_id)

        federation_handler = self.hs.get_handlers().federation_handler

        if event.type == EventTypes.Member:
            if event.content["membership"] == Membership.INVITE:

                def is_inviter_member_event(e):
                    return e.type == EventTypes.Member and e.sender == event.sender

                current_state_ids = await context.get_current_state_ids()

                state_to_include_ids = [
                    e_id for k, e_id in current_state_ids.items()
                    if k[0] in self.room_invite_state_types or k == (
                        EventTypes.Member, event.sender)
                ]

                state_to_include = await self.store.get_events(
                    state_to_include_ids)

                event.unsigned["invite_room_state"] = [{
                    "type": e.type,
                    "state_key": e.state_key,
                    "content": e.content,
                    "sender": e.sender,
                } for e in state_to_include.values()]

                invitee = UserID.from_string(event.state_key)
                if not self.hs.is_mine(invitee):
                    # TODO: Can we add signature from remote server in a nicer
                    # way? If we have been invited by a remote server, we need
                    # to get them to sign the event.

                    returned_invite = await federation_handler.send_invite(
                        invitee.domain, event)
                    event.unsigned.pop("room_state", None)

                    # TODO: Make sure the signatures actually are correct.
                    event.signatures.update(returned_invite.signatures)

        if event.type == EventTypes.Redaction:
            original_event = await self.store.get_event(
                event.redacts,
                redact_behaviour=EventRedactBehaviour.AS_IS,
                get_prev_content=False,
                allow_rejected=False,
                allow_none=True,
            )

            # we can make some additional checks now if we have the original event.
            if original_event:
                if original_event.type == EventTypes.Create:
                    raise AuthError(
                        403, "Redacting create events is not permitted")

                if original_event.room_id != event.room_id:
                    raise SynapseError(
                        400, "Cannot redact event from a different room")

            prev_state_ids = await context.get_prev_state_ids()
            auth_events_ids = await self.auth.compute_auth_events(
                event, prev_state_ids, for_verification=True)
            auth_events = await self.store.get_events(auth_events_ids)
            auth_events = {(e.type, e.state_key): e
                           for e in auth_events.values()}

            room_version = await self.store.get_room_version_id(event.room_id)
            room_version_obj = KNOWN_ROOM_VERSIONS[room_version]

            if event_auth.check_redaction(room_version_obj,
                                          event,
                                          auth_events=auth_events):
                # this user doesn't have 'redact' rights, so we need to do some more
                # checks on the original event. Let's start by checking the original
                # event exists.
                if not original_event:
                    raise NotFoundError("Could not find event %s" %
                                        (event.redacts, ))

                if event.user_id != original_event.user_id:
                    raise AuthError(
                        403, "You don't have permission to redact events")

                # all the checks are done.
                event.internal_metadata.recheck_redaction = False

        if event.type == EventTypes.Create:
            prev_state_ids = await context.get_prev_state_ids()
            if prev_state_ids:
                raise AuthError(403,
                                "Changing the room create event is forbidden")

        event_stream_id, max_stream_id = await self.storage.persistence.persist_event(
            event, context=context)

        if self._ephemeral_events_enabled:
            # If there's an expiry timestamp on the event, schedule its expiry.
            self._message_handler.maybe_schedule_expiry(event)

        await self.pusher_pool.on_new_notifications(event_stream_id,
                                                    max_stream_id)

        def _notify():
            try:
                self.notifier.on_new_room_event(event,
                                                event_stream_id,
                                                max_stream_id,
                                                extra_users=extra_users)
            except Exception:
                logger.exception("Error notifying about new room event")

        run_in_background(_notify)

        if event.type == EventTypes.Message:
            # We don't want to block sending messages on any presence code. This
            # matters as sometimes presence code can take a while.
            run_in_background(self._bump_active_time, requester.user)

        return event_stream_id
コード例 #4
0
ファイル: message.py プロジェクト: syamgk/synapse
    def persist_and_notify_client_event(
        self, requester, event, context, ratelimit=True, extra_users=[]
    ):
        """Called when we have fully built the event, have already
        calculated the push actions for the event, and checked auth.

        This should only be run on master.
        """
        assert not self.config.worker_app

        if ratelimit:
            # We check if this is a room admin redacting an event so that we
            # can apply different ratelimiting. We do this by simply checking
            # it's not a self-redaction (to avoid having to look up whether the
            # user is actually admin or not).
            is_admin_redaction = False
            if event.type == EventTypes.Redaction:
                original_event = yield self.store.get_event(
                    event.redacts,
                    check_redacted=False,
                    get_prev_content=False,
                    allow_rejected=False,
                    allow_none=True,
                )

                is_admin_redaction = (
                    original_event and event.sender != original_event.sender
                )

            yield self.base_handler.ratelimit(
                requester, is_admin_redaction=is_admin_redaction
            )

        yield self.base_handler.maybe_kick_guest_users(event, context)

        if event.type == EventTypes.CanonicalAlias:
            # Check the alias is acually valid (at this time at least)
            room_alias_str = event.content.get("alias", None)
            if room_alias_str:
                room_alias = RoomAlias.from_string(room_alias_str)
                directory_handler = self.hs.get_handlers().directory_handler
                mapping = yield directory_handler.get_association(room_alias)

                if mapping["room_id"] != event.room_id:
                    raise SynapseError(
                        400,
                        "Room alias %s does not point to the room" % (room_alias_str,),
                    )

        federation_handler = self.hs.get_handlers().federation_handler

        if event.type == EventTypes.Member:
            if event.content["membership"] == Membership.INVITE:

                def is_inviter_member_event(e):
                    return e.type == EventTypes.Member and e.sender == event.sender

                current_state_ids = yield context.get_current_state_ids(self.store)

                state_to_include_ids = [
                    e_id
                    for k, e_id in iteritems(current_state_ids)
                    if k[0] in self.hs.config.room_invite_state_types
                    or k == (EventTypes.Member, event.sender)
                ]

                state_to_include = yield self.store.get_events(state_to_include_ids)

                event.unsigned["invite_room_state"] = [
                    {
                        "type": e.type,
                        "state_key": e.state_key,
                        "content": e.content,
                        "sender": e.sender,
                    }
                    for e in itervalues(state_to_include)
                ]

                invitee = UserID.from_string(event.state_key)
                if not self.hs.is_mine(invitee):
                    # TODO: Can we add signature from remote server in a nicer
                    # way? If we have been invited by a remote server, we need
                    # to get them to sign the event.

                    returned_invite = yield federation_handler.send_invite(
                        invitee.domain, event
                    )

                    event.unsigned.pop("room_state", None)

                    # TODO: Make sure the signatures actually are correct.
                    event.signatures.update(returned_invite.signatures)

        if event.type == EventTypes.Redaction:
            original_event = yield self.store.get_event(
                event.redacts,
                check_redacted=False,
                get_prev_content=False,
                allow_rejected=False,
                allow_none=True,
            )

            # we can make some additional checks now if we have the original event.
            if original_event:
                if original_event.type == EventTypes.Create:
                    raise AuthError(403, "Redacting create events is not permitted")

                if original_event.room_id != event.room_id:
                    raise SynapseError(400, "Cannot redact event from a different room")

            prev_state_ids = yield context.get_prev_state_ids(self.store)
            auth_events_ids = yield self.auth.compute_auth_events(
                event, prev_state_ids, for_verification=True
            )
            auth_events = yield self.store.get_events(auth_events_ids)
            auth_events = {(e.type, e.state_key): e for e in auth_events.values()}
            room_version = yield self.store.get_room_version(event.room_id)

            if event_auth.check_redaction(room_version, event, auth_events=auth_events):
                # this user doesn't have 'redact' rights, so we need to do some more
                # checks on the original event. Let's start by checking the original
                # event exists.
                if not original_event:
                    raise NotFoundError("Could not find event %s" % (event.redacts,))

                if event.user_id != original_event.user_id:
                    raise AuthError(403, "You don't have permission to redact events")

                # all the checks are done.
                event.internal_metadata.recheck_redaction = False

        if event.type == EventTypes.Create:
            prev_state_ids = yield context.get_prev_state_ids(self.store)
            if prev_state_ids:
                raise AuthError(403, "Changing the room create event is forbidden")

        event_stream_id, max_stream_id = yield self.storage.persistence.persist_event(
            event, context=context
        )

        yield self.pusher_pool.on_new_notifications(event_stream_id, max_stream_id)

        def _notify():
            try:
                self.notifier.on_new_room_event(
                    event, event_stream_id, max_stream_id, extra_users=extra_users
                )
            except Exception:
                logger.exception("Error notifying about new room event")

        run_in_background(_notify)

        if event.type == EventTypes.Message:
            # We don't want to block sending messages on any presence code. This
            # matters as sometimes presence code can take a while.
            run_in_background(self._bump_active_time, requester.user)