Skip to content

Commit

Permalink
Prevent suspended users from sending encrypted messages (#18157)
Browse files Browse the repository at this point in the history
Missed in the first round.
  • Loading branch information
H-Shay authored Feb 21, 2025
1 parent caa1f9d commit 8fd7148
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 7 deletions.
1 change: 1 addition & 0 deletions changelog.d/18157.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Prevent suspended users from sending encrypted messages.
32 changes: 27 additions & 5 deletions synapse/handlers/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -644,11 +644,33 @@ async def create_event(
"""
await self.auth_blocking.check_auth_blocking(requester=requester)

if event_dict["type"] == EventTypes.Message:
requester_suspended = await self.store.get_user_suspended_status(
requester.user.to_string()
)
if requester_suspended:
requester_suspended = await self.store.get_user_suspended_status(
requester.user.to_string()
)
if requester_suspended:
# We want to allow suspended users to perform "corrective" actions
# asked of them by server admins, such as redact their messages and
# leave rooms.
if event_dict["type"] in ["m.room.redaction", "m.room.member"]:
if event_dict["type"] == "m.room.redaction":
event = await self.store.get_event(
event_dict["content"]["redacts"], allow_none=True
)
if event:
if event.sender != requester.user.to_string():
raise SynapseError(
403,
"You can only redact your own events while account is suspended.",
Codes.USER_ACCOUNT_SUSPENDED,
)
if event_dict["type"] == "m.room.member":
if event_dict["content"]["membership"] != "leave":
raise SynapseError(
403,
"Changing membership while account is suspended is not allowed.",
Codes.USER_ACCOUNT_SUSPENDED,
)
else:
raise SynapseError(
403,
"Sending messages while account is suspended is not allowed.",
Expand Down
102 changes: 100 additions & 2 deletions tests/rest/client/test_rooms.py
Original file line number Diff line number Diff line change
Expand Up @@ -1371,6 +1371,23 @@ def test_suspended_user_cannot_invite_to_room(self) -> None:
)
self.assertEqual(channel.json_body["errcode"], "M_USER_SUSPENDED")

def test_suspended_user_can_leave_room(self) -> None:
channel = self.make_request(
"POST", f"/join/{self.room1}", access_token=self.tok1
)
self.assertEqual(channel.code, 200)

# set the user as suspended
self.get_success(self.store.set_user_suspended_status(self.user1, True))

# leave room
channel = self.make_request(
"POST",
f"/rooms/{self.room1}/leave",
access_token=self.tok1,
)
self.assertEqual(channel.code, 200)


class RoomAppserviceTsParamTestCase(unittest.HomeserverTestCase):
servlets = [
Expand Down Expand Up @@ -3989,10 +4006,25 @@ def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
self.user2 = self.register_user("teresa", "hackme")
self.tok2 = self.login("teresa", "hackme")

self.room1 = self.helper.create_room_as(room_creator=self.user1, tok=self.tok1)
self.admin = self.register_user("admin", "pass", True)
self.admin_tok = self.login("admin", "pass")

self.room1 = self.helper.create_room_as(
room_creator=self.user1, tok=self.tok1, room_version="11"
)
self.store = hs.get_datastores().main

def test_suspended_user_cannot_send_message_to_room(self) -> None:
self.room2 = self.helper.create_room_as(
room_creator=self.user1, is_public=False, tok=self.tok1
)
self.helper.send_state(
self.room2,
EventTypes.RoomEncryption,
{EventContentFields.ENCRYPTION_ALGORITHM: "m.megolm.v1.aes-sha2"},
tok=self.tok1,
)

def test_suspended_user_cannot_send_message_to_public_room(self) -> None:
# set the user as suspended
self.get_success(self.store.set_user_suspended_status(self.user1, True))

Expand All @@ -4004,6 +4036,24 @@ def test_suspended_user_cannot_send_message_to_room(self) -> None:
)
self.assertEqual(channel.json_body["errcode"], "M_USER_SUSPENDED")

def test_suspended_user_cannot_send_message_to_encrypted_room(self) -> None:
channel = self.make_request(
"PUT",
f"/_synapse/admin/v1/suspend/{self.user1}",
{"suspend": True},
access_token=self.admin_tok,
)
self.assertEqual(channel.code, 200)
self.assertEqual(channel.json_body, {f"user_{self.user1}_suspended": True})

channel = self.make_request(
"PUT",
f"/rooms/{self.room2}/send/m.room.encrypted/1",
access_token=self.tok1,
content={},
)
self.assertEqual(channel.json_body["errcode"], "M_USER_SUSPENDED")

def test_suspended_user_cannot_change_profile_data(self) -> None:
# set the user as suspended
self.get_success(self.store.set_user_suspended_status(self.user1, True))
Expand Down Expand Up @@ -4069,3 +4119,51 @@ def test_suspended_user_cannot_redact_messages_other_than_their_own(self) -> Non
shorthand=False,
)
self.assertEqual(channel.code, 200)

channel = self.make_request(
"PUT",
f"/_matrix/client/v3/rooms/{self.room1}/send/m.room.redaction/3456346",
access_token=self.tok1,
content={"reason": "bogus", "redacts": event_id},
shorthand=False,
)
self.assertEqual(channel.json_body["errcode"], "M_USER_SUSPENDED")

channel = self.make_request(
"PUT",
f"/_matrix/client/v3/rooms/{self.room1}/send/m.room.redaction/3456346",
access_token=self.tok1,
content={"reason": "bogus", "redacts": event_id2},
shorthand=False,
)
self.assertEqual(channel.code, 200)

def test_suspended_user_cannot_ban_others(self) -> None:
# user to ban joins room user1 created
self.make_request("POST", f"/rooms/{self.room1}/join", access_token=self.tok2)

# suspend user1
self.get_success(self.store.set_user_suspended_status(self.user1, True))

# user1 tries to ban other user while suspended
channel = self.make_request(
"POST",
f"/_matrix/client/v3/rooms/{self.room1}/ban",
access_token=self.tok1,
content={"reason": "spite", "user_id": self.user2},
shorthand=False,
)
self.assertEqual(channel.json_body["errcode"], "M_USER_SUSPENDED")

# un-suspend user1
self.get_success(self.store.set_user_suspended_status(self.user1, False))

# ban now goes through
channel = self.make_request(
"POST",
f"/_matrix/client/v3/rooms/{self.room1}/ban",
access_token=self.tok1,
content={"reason": "spite", "user_id": self.user2},
shorthand=False,
)
self.assertEqual(channel.code, 200)

0 comments on commit 8fd7148

Please sign in to comment.