Ignore redactions of m.room.create events (#5701)

pull/5712/head
Richard van der Hoff 2019-07-17 19:08:02 +01:00 committed by GitHub
parent 1def298119
commit 9c70a02a9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 57 additions and 24 deletions

1
changelog.d/5701.bugfix Normal file
View File

@ -0,0 +1 @@
Ignore redactions of m.room.create events.

View File

@ -606,21 +606,6 @@ class Auth(object):
defer.returnValue(auth_ids) defer.returnValue(auth_ids)
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)
@defer.inlineCallbacks @defer.inlineCallbacks
def check_can_change_room_list(self, room_id, user): def check_can_change_room_list(self, room_id, user):
"""Check if the user is allowed to edit the room's entry in the """Check if the user is allowed to edit the room's entry in the

View File

@ -23,6 +23,7 @@ from canonicaljson import encode_canonical_json, json
from twisted.internet import defer from twisted.internet import defer
from twisted.internet.defer import succeed from twisted.internet.defer import succeed
from synapse import event_auth
from synapse.api.constants import EventTypes, Membership, RelationTypes from synapse.api.constants import EventTypes, Membership, RelationTypes
from synapse.api.errors import ( from synapse.api.errors import (
AuthError, AuthError,
@ -784,6 +785,20 @@ class EventCreationHandler(object):
event.signatures.update(returned_invite.signatures) event.signatures.update(returned_invite.signatures)
if event.type == EventTypes.Redaction: 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,
check_room_id=event.room_id,
)
# 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")
prev_state_ids = yield context.get_prev_state_ids(self.store) prev_state_ids = yield context.get_prev_state_ids(self.store)
auth_events_ids = yield self.auth.compute_auth_events( auth_events_ids = yield self.auth.compute_auth_events(
event, prev_state_ids, for_verification=True event, prev_state_ids, for_verification=True
@ -791,18 +806,18 @@ class EventCreationHandler(object):
auth_events = yield self.store.get_events(auth_events_ids) auth_events = yield self.store.get_events(auth_events_ids)
auth_events = {(e.type, e.state_key): e for e in auth_events.values()} 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) room_version = yield self.store.get_room_version(event.room_id)
if self.auth.check_redaction(room_version, event, auth_events=auth_events):
original_event = yield self.store.get_event( if event_auth.check_redaction(room_version, event, auth_events=auth_events):
event.redacts, # this user doesn't have 'redact' rights, so we need to do some more
check_redacted=False, # checks on the original event. Let's start by checking the original
get_prev_content=False, # event exists.
allow_rejected=False, if not original_event:
allow_none=False, raise NotFoundError("Could not find event %s" % (event.redacts,))
)
if event.user_id != original_event.user_id: if event.user_id != original_event.user_id:
raise AuthError(403, "You don't have permission to redact events") raise AuthError(403, "You don't have permission to redact events")
# We've already checked. # all the checks are done.
event.internal_metadata.recheck_redaction = False event.internal_metadata.recheck_redaction = False
if event.type == EventTypes.Create: if event.type == EventTypes.Create:

View File

@ -259,6 +259,14 @@ class EventsWorkerStore(SQLBaseStore):
continue continue
original_event = original_event_entry.event original_event = original_event_entry.event
if original_event.type == EventTypes.Create:
# we never serve redactions of Creates to clients.
logger.info(
"Withholding redaction %s of create event %s",
event_id,
redacted_event_id,
)
continue
if entry.event.internal_metadata.need_to_check_redaction(): if entry.event.internal_metadata.need_to_check_redaction():
original_domain = get_domain_from_id(original_event.sender) original_domain = get_domain_from_id(original_event.sender)
@ -617,6 +625,10 @@ class EventsWorkerStore(SQLBaseStore):
Deferred[EventBase|None]: if the event should be redacted, a pruned Deferred[EventBase|None]: if the event should be redacted, a pruned
event object. Otherwise, None. event object. Otherwise, None.
""" """
if original_ev.type == "m.room.create":
# we choose to ignore redactions of m.room.create events.
return None
redaction_map = yield self._get_events_from_cache_or_db(redactions) redaction_map = yield self._get_events_from_cache_or_db(redactions)
for redaction_id in redactions: for redaction_id in redactions:

View File

@ -157,3 +157,23 @@ class RedactionsTestCase(HomeserverTestCase):
self.assertEqual(timeline[-2]["event_id"], msg_id) self.assertEqual(timeline[-2]["event_id"], msg_id)
self.assertEqual(timeline[-2]["unsigned"]["redacted_by"], redaction_id) self.assertEqual(timeline[-2]["unsigned"]["redacted_by"], redaction_id)
self.assertEqual(timeline[-2]["content"], {}) self.assertEqual(timeline[-2]["content"], {})
def test_redact_create_event(self):
# control case: an existing event
b = self.helper.send(room_id=self.room_id, tok=self.mod_access_token)
msg_id = b["event_id"]
self._redact_event(self.mod_access_token, self.room_id, msg_id)
# sync the room, to get the id of the create event
timeline = self._sync_room_timeline(self.other_access_token, self.room_id)
create_event_id = timeline[0]["event_id"]
# room moderators cannot send redactions for create events
self._redact_event(
self.mod_access_token, self.room_id, create_event_id, expect_code=403
)
# and nor can normals
self._redact_event(
self.other_access_token, self.room_id, create_event_id, expect_code=403
)