Merge pull request #3641 from matrix-org/rav/room_id_check

Validation for events/rooms in fed requests
This commit is contained in:
Richard van der Hoff 2018-08-02 14:22:05 +01:00 committed by GitHub
commit a937497cf5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 40 additions and 12 deletions

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

@ -0,0 +1 @@
Fix a potential event disclosure issue

View file

@ -425,6 +425,7 @@ class FederationServer(FederationBase):
ret = yield self.handler.on_query_auth( ret = yield self.handler.on_query_auth(
origin, origin,
event_id, event_id,
room_id,
signed_auth, signed_auth,
content.get("rejects", []), content.get("rejects", []),
content.get("missing", []), content.get("missing", []),

View file

@ -1349,6 +1349,11 @@ class FederationHandler(BaseHandler):
def get_state_for_pdu(self, room_id, event_id): def get_state_for_pdu(self, room_id, event_id):
"""Returns the state at the event. i.e. not including said event. """Returns the state at the event. i.e. not including said event.
""" """
event = yield self.store.get_event(
event_id, allow_none=False, check_room_id=room_id,
)
state_groups = yield self.store.get_state_groups( state_groups = yield self.store.get_state_groups(
room_id, [event_id] room_id, [event_id]
) )
@ -1359,8 +1364,7 @@ class FederationHandler(BaseHandler):
(e.type, e.state_key): e for e in state (e.type, e.state_key): e for e in state
} }
event = yield self.store.get_event(event_id) if event.is_state():
if event and event.is_state():
# Get previous state # Get previous state
if "replaces_state" in event.unsigned: if "replaces_state" in event.unsigned:
prev_id = event.unsigned["replaces_state"] prev_id = event.unsigned["replaces_state"]
@ -1391,6 +1395,10 @@ class FederationHandler(BaseHandler):
def get_state_ids_for_pdu(self, room_id, event_id): def get_state_ids_for_pdu(self, room_id, event_id):
"""Returns the state at the event. i.e. not including said event. """Returns the state at the event. i.e. not including said event.
""" """
event = yield self.store.get_event(
event_id, allow_none=False, check_room_id=room_id,
)
state_groups = yield self.store.get_state_groups_ids( state_groups = yield self.store.get_state_groups_ids(
room_id, [event_id] room_id, [event_id]
) )
@ -1399,8 +1407,7 @@ class FederationHandler(BaseHandler):
_, state = state_groups.items().pop() _, state = state_groups.items().pop()
results = state results = state
event = yield self.store.get_event(event_id) if event.is_state():
if event and event.is_state():
# Get previous state # Get previous state
if "replaces_state" in event.unsigned: if "replaces_state" in event.unsigned:
prev_id = event.unsigned["replaces_state"] prev_id = event.unsigned["replaces_state"]
@ -1706,8 +1713,19 @@ class FederationHandler(BaseHandler):
defer.returnValue(context) defer.returnValue(context)
@defer.inlineCallbacks @defer.inlineCallbacks
def on_query_auth(self, origin, event_id, remote_auth_chain, rejects, def on_query_auth(self, origin, event_id, room_id, remote_auth_chain, rejects,
missing): missing):
in_room = yield self.auth.check_host_in_room(
room_id,
origin
)
if not in_room:
raise AuthError(403, "Host not in room.")
event = yield self.store.get_event(
event_id, allow_none=False, check_room_id=room_id
)
# Just go through and process each event in `remote_auth_chain`. We # Just go through and process each event in `remote_auth_chain`. We
# don't want to fall into the trap of `missing` being wrong. # don't want to fall into the trap of `missing` being wrong.
for e in remote_auth_chain: for e in remote_auth_chain:
@ -1717,7 +1735,6 @@ class FederationHandler(BaseHandler):
pass pass
# Now get the current auth_chain for the event. # Now get the current auth_chain for the event.
event = yield self.store.get_event(event_id)
local_auth_chain = yield self.store.get_auth_chain( local_auth_chain = yield self.store.get_auth_chain(
[auth_id for auth_id, _ in event.auth_events], [auth_id for auth_id, _ in event.auth_events],
include_given=True include_given=True

View file

@ -343,6 +343,7 @@ class EventFederationWorkerStore(EventsWorkerStore, SignatureWorkerStore,
table="events", table="events",
keyvalues={ keyvalues={
"event_id": event_id, "event_id": event_id,
"room_id": room_id,
}, },
retcol="depth", retcol="depth",
allow_none=True, allow_none=True,

View file

@ -19,7 +19,7 @@ from canonicaljson import json
from twisted.internet import defer from twisted.internet import defer
from synapse.api.errors import SynapseError from synapse.api.errors import NotFoundError
# these are only included to make the type annotations work # these are only included to make the type annotations work
from synapse.events import EventBase # noqa: F401 from synapse.events import EventBase # noqa: F401
from synapse.events import FrozenEvent from synapse.events import FrozenEvent
@ -76,7 +76,7 @@ class EventsWorkerStore(SQLBaseStore):
@defer.inlineCallbacks @defer.inlineCallbacks
def get_event(self, event_id, check_redacted=True, def get_event(self, event_id, check_redacted=True,
get_prev_content=False, allow_rejected=False, get_prev_content=False, allow_rejected=False,
allow_none=False): allow_none=False, check_room_id=None):
"""Get an event from the database by event_id. """Get an event from the database by event_id.
Args: Args:
@ -87,7 +87,9 @@ class EventsWorkerStore(SQLBaseStore):
include the previous states content in the unsigned field. include the previous states content in the unsigned field.
allow_rejected (bool): If True return rejected events. allow_rejected (bool): If True return rejected events.
allow_none (bool): If True, return None if no event found, if allow_none (bool): If True, return None if no event found, if
False throw an exception. False throw a NotFoundError
check_room_id (str|None): if not None, check the room of the found event.
If there is a mismatch, behave as per allow_none.
Returns: Returns:
Deferred : A FrozenEvent. Deferred : A FrozenEvent.
@ -99,10 +101,16 @@ class EventsWorkerStore(SQLBaseStore):
allow_rejected=allow_rejected, allow_rejected=allow_rejected,
) )
if not events and not allow_none: event = events[0] if events else None
raise SynapseError(404, "Could not find event %s" % (event_id,))
defer.returnValue(events[0] if events else None) if event is not None and check_room_id is not None:
if event.room_id != check_room_id:
event = None
if event is None and not allow_none:
raise NotFoundError("Could not find event %s" % (event_id,))
defer.returnValue(event)
@defer.inlineCallbacks @defer.inlineCallbacks
def get_events(self, event_ids, check_redacted=True, def get_events(self, event_ids, check_redacted=True,