Merge pull request #4166 from matrix-org/erikj/drop_unknown_events

Drop incoming events from federation for unknown rooms
This commit is contained in:
Erik Johnston 2018-11-09 17:59:34 +00:00 committed by GitHub
commit db5a1c059a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 77 additions and 91 deletions

1
changelog.d/4165.misc Normal file
View File

@ -0,0 +1 @@
Drop incoming events from federation for unknown rooms

View File

@ -162,8 +162,30 @@ class FederationServer(FederationBase):
p["age_ts"] = request_time - int(p["age"]) p["age_ts"] = request_time - int(p["age"])
del p["age"] del p["age"]
# We try and pull out an event ID so that if later checks fail we
# can log something sensible. We don't mandate an event ID here in
# case future event formats get rid of the key.
possible_event_id = p.get("event_id", "<Unknown>")
# Now we get the room ID so that we can check that we know the
# version of the room.
room_id = p.get("room_id")
if not room_id:
logger.info(
"Ignoring PDU as does not have a room_id. Event ID: %s",
possible_event_id,
)
continue
try:
# In future we will actually use the room version to parse the
# PDU into an event.
yield self.store.get_room_version(room_id)
except NotFoundError:
logger.info("Ignoring PDU for unknown room_id: %s", room_id)
continue
event = event_from_pdu_json(p) event = event_from_pdu_json(p)
room_id = event.room_id
pdus_by_room.setdefault(room_id, []).append(event) pdus_by_room.setdefault(room_id, []).append(event)
pdu_results = {} pdu_results = {}

View File

@ -202,27 +202,22 @@ class FederationHandler(BaseHandler):
self.room_queues[room_id].append((pdu, origin)) self.room_queues[room_id].append((pdu, origin))
return return
# If we're no longer in the room just ditch the event entirely. This # If we're not in the room just ditch the event entirely. This is
# is probably an old server that has come back and thinks we're still # probably an old server that has come back and thinks we're still in
# in the room (or we've been rejoined to the room by a state reset). # the room (or we've been rejoined to the room by a state reset).
# #
# If we were never in the room then maybe our database got vaped and # Note that if we were never in the room then we would have already
# we should check if we *are* in fact in the room. If we are then we # dropped the event, since we wouldn't know the room version.
# can magically rejoin the room.
is_in_room = yield self.auth.check_host_in_room( is_in_room = yield self.auth.check_host_in_room(
room_id, room_id,
self.server_name self.server_name
) )
if not is_in_room: if not is_in_room:
was_in_room = yield self.store.was_host_joined( logger.info(
pdu.room_id, self.server_name, "[%s %s] Ignoring PDU from %s as we're not in the room",
room_id, event_id, origin,
) )
if was_in_room: defer.returnValue(None)
logger.info(
"[%s %s] Ignoring PDU from %s as we've left the room",
room_id, event_id, origin,
)
defer.returnValue(None)
state = None state = None
auth_chain = [] auth_chain = []
@ -557,86 +552,54 @@ class FederationHandler(BaseHandler):
room_id, event_id, event, room_id, event_id, event,
) )
# FIXME (erikj): Awful hack to make the case where we are not currently event_ids = set()
# in the room work if state:
# If state and auth_chain are None, then we don't need to do this check event_ids |= {e.event_id for e in state}
# as we already know we have enough state in the DB to handle this if auth_chain:
# event. event_ids |= {e.event_id for e in auth_chain}
if state and auth_chain and not event.internal_metadata.is_outlier():
is_in_room = yield self.auth.check_host_in_room( seen_ids = yield self.store.have_seen_events(event_ids)
room_id,
self.server_name if state and auth_chain is not None:
) # If we have any state or auth_chain given to us by the replication
else: # layer, then we should handle them (if we haven't before.)
is_in_room = True
event_infos = []
for e in itertools.chain(auth_chain, state):
if e.event_id in seen_ids:
continue
e.internal_metadata.outlier = True
auth_ids = e.auth_event_ids()
auth = {
(e.type, e.state_key): e for e in auth_chain
if e.event_id in auth_ids or e.type == EventTypes.Create
}
event_infos.append({
"event": e,
"auth_events": auth,
})
seen_ids.add(e.event_id)
if not is_in_room:
logger.info( logger.info(
"[%s %s] Got event for room we're not in", "[%s %s] persisting newly-received auth/state events %s",
room_id, event_id, room_id, event_id, [e["event"].event_id for e in event_infos]
) )
yield self._handle_new_events(origin, event_infos)
try: try:
yield self._persist_auth_tree( context = yield self._handle_new_event(
origin, auth_chain, state, event origin,
) event,
except AuthError as e: state=state,
raise FederationError( )
"ERROR", except AuthError as e:
e.code, raise FederationError(
e.msg, "ERROR",
affected=event_id, e.code,
) e.msg,
affected=event.event_id,
else: )
event_ids = set()
if state:
event_ids |= {e.event_id for e in state}
if auth_chain:
event_ids |= {e.event_id for e in auth_chain}
seen_ids = yield self.store.have_seen_events(event_ids)
if state and auth_chain is not None:
# If we have any state or auth_chain given to us by the replication
# layer, then we should handle them (if we haven't before.)
event_infos = []
for e in itertools.chain(auth_chain, state):
if e.event_id in seen_ids:
continue
e.internal_metadata.outlier = True
auth_ids = e.auth_event_ids()
auth = {
(e.type, e.state_key): e for e in auth_chain
if e.event_id in auth_ids or e.type == EventTypes.Create
}
event_infos.append({
"event": e,
"auth_events": auth,
})
seen_ids.add(e.event_id)
logger.info(
"[%s %s] persisting newly-received auth/state events %s",
room_id, event_id, [e["event"].event_id for e in event_infos]
)
yield self._handle_new_events(origin, event_infos)
try:
context = yield self._handle_new_event(
origin,
event,
state=state,
)
except AuthError as e:
raise FederationError(
"ERROR",
e.code,
e.msg,
affected=event.event_id,
)
room = yield self.store.get_room(room_id) room = yield self.store.get_room(room_id)