diff --git a/changelog.d/18475.feature b/changelog.d/18475.feature new file mode 100644 index 00000000000..06c13db43e5 --- /dev/null +++ b/changelog.d/18475.feature @@ -0,0 +1 @@ +Make ACLs apply to EDUs per [MSC4163](https://github.com/matrix-org/matrix-spec-proposals/pull/4163). diff --git a/synapse/federation/federation_server.py b/synapse/federation/federation_server.py index 2f2c78babce..8979f06b3d0 100644 --- a/synapse/federation/federation_server.py +++ b/synapse/federation/federation_server.py @@ -551,6 +551,53 @@ async def _process_edu(edu_dict: JsonDict) -> None: edu_type=edu_dict["edu_type"], content=edu_dict["content"], ) + + # Server ACL's apply to `EduTypes.TYPING` per MSC4163: + # + # > For typing notifications (m.typing), the room_id field inside + # > content should be checked, with the typing notification ignored if + # > the origin of the request is a server which is forbidden by the + # > room's ACL. Ignoring the typing notification means that the EDU + # > MUST be dropped upon receipt. + if edu.edu_type == EduTypes.TYPING: + origin_host, _ = parse_server_name(origin) + room_id = edu.content["room_id"] + try: + await self.check_server_matches_acl(origin_host, room_id) + except AuthError: + logger.warning( + "Ignoring typing EDU for room %s from banned server", room_id + ) + return + + # Server ACL's apply to `EduTypes.RECEIPT` per MSC4163: + # + # > For read receipts (m.receipt), all receipts inside a room_id + # > inside content should be ignored if the origin of the request is + # > forbidden by the room's ACL. + if edu.edu_type == EduTypes.RECEIPT: + origin_host, _ = parse_server_name(origin) + to_remove = set() + for room_id in edu.content.keys(): + try: + await self.check_server_matches_acl(origin_host, room_id) + except AuthError: + to_remove.add(room_id) + + if to_remove: + logger.warning( + "Ignoring receipts in EDU for rooms %s from banned server %s", + to_remove, + origin_host, + ) + + for room_id in to_remove: + edu.content.pop(room_id) + + if not edu.content: + # If we've removed all the rooms, we can just ignore the whole EDU + return + try: await self.registry.on_edu(edu.edu_type, origin, edu.content) except Exception: