Prevent message search in upgraded rooms we're not in (#6385)

This commit is contained in:
Andrew Morgan 2019-12-11 13:07:25 +00:00 committed by GitHub
parent 54ae52ba96
commit ea0f0ad414
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 16 deletions

1
changelog.d/6385.bugfix Normal file
View file

@ -0,0 +1 @@
Prevent error on trying to search a upgraded room when the server is not in the predecessor room.

View file

@ -1299,7 +1299,7 @@ class FederationHandler(BaseHandler):
# Check whether this room is the result of an upgrade of a room we already know # Check whether this room is the result of an upgrade of a room we already know
# about. If so, migrate over user information # about. If so, migrate over user information
predecessor = yield self.store.get_room_predecessor(room_id) predecessor = yield self.store.get_room_predecessor(room_id)
if not predecessor: if not predecessor or not isinstance(predecessor.get("room_id"), str):
return return
old_room_id = predecessor["room_id"] old_room_id = predecessor["room_id"]
logger.debug( logger.debug(
@ -1542,7 +1542,7 @@ class FederationHandler(BaseHandler):
@defer.inlineCallbacks @defer.inlineCallbacks
def do_remotely_reject_invite(self, target_hosts, room_id, user_id, content): def do_remotely_reject_invite(self, target_hosts, room_id, user_id, content):
origin, event, event_format_version = yield self._make_and_verify_event( origin, event, event_format_version = yield self._make_and_verify_event(
target_hosts, room_id, user_id, "leave", content=content, target_hosts, room_id, user_id, "leave", content=content
) )
# Mark as outlier as we don't have any state for this event; we're not # Mark as outlier as we don't have any state for this event; we're not
# even in the room. # even in the room.

View file

@ -21,7 +21,7 @@ from unpaddedbase64 import decode_base64, encode_base64
from twisted.internet import defer from twisted.internet import defer
from synapse.api.constants import EventTypes, Membership from synapse.api.constants import EventTypes, Membership
from synapse.api.errors import SynapseError from synapse.api.errors import NotFoundError, SynapseError
from synapse.api.filtering import Filter from synapse.api.filtering import Filter
from synapse.storage.state import StateFilter from synapse.storage.state import StateFilter
from synapse.visibility import filter_events_for_client from synapse.visibility import filter_events_for_client
@ -37,6 +37,7 @@ class SearchHandler(BaseHandler):
self._event_serializer = hs.get_event_client_serializer() self._event_serializer = hs.get_event_client_serializer()
self.storage = hs.get_storage() self.storage = hs.get_storage()
self.state_store = self.storage.state self.state_store = self.storage.state
self.auth = hs.get_auth()
@defer.inlineCallbacks @defer.inlineCallbacks
def get_old_rooms_from_upgraded_room(self, room_id): def get_old_rooms_from_upgraded_room(self, room_id):
@ -53,23 +54,38 @@ class SearchHandler(BaseHandler):
room_id (str): id of the room to search through. room_id (str): id of the room to search through.
Returns: Returns:
Deferred[iterable[unicode]]: predecessor room ids Deferred[iterable[str]]: predecessor room ids
""" """
historical_room_ids = [] historical_room_ids = []
while True: # The initial room must have been known for us to get this far
predecessor = yield self.store.get_room_predecessor(room_id) predecessor = yield self.store.get_room_predecessor(room_id)
# If no predecessor, assume we've hit a dead end while True:
if not predecessor: if not predecessor:
# We have reached the end of the chain of predecessors
break break
# Add predecessor's room ID if not isinstance(predecessor.get("room_id"), str):
historical_room_ids.append(predecessor["room_id"]) # This predecessor object is malformed. Exit here
break
# Scan through the old room for further predecessors predecessor_room_id = predecessor["room_id"]
room_id = predecessor["room_id"]
# Don't add it to the list until we have checked that we are in the room
try:
next_predecessor_room = yield self.store.get_room_predecessor(
predecessor_room_id
)
except NotFoundError:
# The predecessor is not a known room, so we are done here
break
historical_room_ids.append(predecessor_room_id)
# And repeat
predecessor = next_predecessor_room
return historical_room_ids return historical_room_ids

View file

@ -278,7 +278,7 @@ class StateGroupWorkerStore(
@defer.inlineCallbacks @defer.inlineCallbacks
def get_room_predecessor(self, room_id): def get_room_predecessor(self, room_id):
"""Get the predecessor room of an upgraded room if one exists. """Get the predecessor of an upgraded room if it exists.
Otherwise return None. Otherwise return None.
Args: Args:
@ -291,14 +291,22 @@ class StateGroupWorkerStore(
* room_id (str): The room ID of the predecessor room * room_id (str): The room ID of the predecessor room
* event_id (str): The ID of the tombstone event in the predecessor room * event_id (str): The ID of the tombstone event in the predecessor room
None if a predecessor key is not found, or is not a dictionary.
Raises: Raises:
NotFoundError if the room is unknown NotFoundError if the given room is unknown
""" """
# Retrieve the room's create event # Retrieve the room's create event
create_event = yield self.get_create_event_for_room(room_id) create_event = yield self.get_create_event_for_room(room_id)
# Return predecessor if present # Retrieve the predecessor key of the create event
return create_event.content.get("predecessor", None) predecessor = create_event.content.get("predecessor", None)
# Ensure the key is a dictionary
if not isinstance(predecessor, dict):
return None
return predecessor
@defer.inlineCallbacks @defer.inlineCallbacks
def get_create_event_for_room(self, room_id): def get_create_event_for_room(self, room_id):
@ -318,7 +326,7 @@ class StateGroupWorkerStore(
# If we can't find the create event, assume we've hit a dead end # If we can't find the create event, assume we've hit a dead end
if not create_id: if not create_id:
raise NotFoundError("Unknown room %s" % (room_id)) raise NotFoundError("Unknown room %s" % (room_id,))
# Retrieve the room's create event and return # Retrieve the room's create event and return
create_event = yield self.get_event(create_id) create_event = yield self.get_event(create_id)