diff --git a/synapse/federation/federation_server.py b/synapse/federation/federation_server.py
index 48f26db67c..10e71c78ce 100644
--- a/synapse/federation/federation_server.py
+++ b/synapse/federation/federation_server.py
@@ -425,6 +425,7 @@ class FederationServer(FederationBase):
ret = yield self.handler.on_query_auth(
origin,
event_id,
+ room_id,
signed_auth,
content.get("rejects", []),
content.get("missing", []),
diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py
index 20fb46fc89..12eeb7c4cd 100644
--- a/synapse/handlers/federation.py
+++ b/synapse/handlers/federation.py
@@ -1349,6 +1349,9 @@ class FederationHandler(BaseHandler):
def get_state_for_pdu(self, room_id, event_id):
"""Returns the state at the event. i.e. not including said event.
"""
+
+ yield self._verify_events_in_room([event_id], room_id)
+
state_groups = yield self.store.get_state_groups(
room_id, [event_id]
)
@@ -1391,6 +1394,9 @@ class FederationHandler(BaseHandler):
def get_state_ids_for_pdu(self, room_id, event_id):
"""Returns the state at the event. i.e. not including said event.
"""
+
+ yield self._verify_events_in_room([event_id], room_id)
+
state_groups = yield self.store.get_state_groups_ids(
room_id, [event_id]
)
@@ -1420,6 +1426,8 @@ class FederationHandler(BaseHandler):
if not in_room:
raise AuthError(403, "Host not in room.")
+ yield self._verify_events_in_room(pdu_list, room_id)
+
events = yield self.store.get_backfill_events(
room_id,
pdu_list,
@@ -1706,8 +1714,17 @@ class FederationHandler(BaseHandler):
defer.returnValue(context)
@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):
+ in_room = yield self.auth.check_host_in_room(
+ room_id,
+ origin
+ )
+ if not in_room:
+ raise AuthError(403, "Host not in room.")
+
+ yield self._verify_events_in_room([event_id], room_id)
+
# Just go through and process each event in `remote_auth_chain`. We
# don't want to fall into the trap of `missing` being wrong.
for e in remote_auth_chain:
@@ -2368,3 +2385,19 @@ class FederationHandler(BaseHandler):
)
if "valid" not in response or not response["valid"]:
raise AuthError(403, "Third party certificate was invalid")
+
+ @defer.inlineCallbacks
+ def _verify_events_in_room(self, pdu_ids, room_id):
+ """Checks whether the given PDU IDs are in the given room or not.
+
+ Args:
+ pdu_ids (list): list of PDU IDs
+ room_id (str): the room ID that the PDUs should be in
+
+ Raises:
+ AuthError: if one or more of the PDUs does not belong to the
+ given room.
+ """
+ room_ids = yield self.store.get_room_ids_for_events(pdu_ids)
+ if len(room_ids) != 1 or room_ids[0] != room_id:
+ raise AuthError(403, "Events must belong to the given room")
diff --git a/synapse/storage/event_federation.py b/synapse/storage/event_federation.py
index 8d366d1b91..e860fe1a1e 100644
--- a/synapse/storage/event_federation.py
+++ b/synapse/storage/event_federation.py
@@ -295,6 +295,35 @@ class EventFederationWorkerStore(EventsWorkerStore, SignatureWorkerStore,
get_forward_extremeties_for_room_txn
)
+ def get_room_ids_for_events(self, event_ids):
+ """Get a list of room IDs for which the given events belong.
+
+ Args:
+ event_ids (list): the events to look up the room of
+
+ Returns:
+ list, the room IDs for the events
+ """
+ return self.runInteraction(
+ "get_room_ids_for_events",
+ self._get_room_ids_for_events, event_ids
+ )
+
+ def _get_room_ids_for_events(self, txn, event_ids):
+ logger.debug("_get_room_ids_for_events: %s", repr(event_ids))
+
+ base_sql = (
+ "SELECT DISTINCT room_id FROM events"
+ " WHERE event_id IN (%s)"
+ )
+
+ txn.execute(
+ base_sql % (",".join(["?"] * len(event_ids)),),
+ event_ids
+ )
+
+ return [r[0] for r in txn]
+
def get_backfill_events(self, room_id, event_list, limit):
"""Get a list of Events for a given topic that occurred before (and
including) the events in event_list. Return a list of max size `limit`
|