Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit e16ea87

Browse files
authored
Fix inconsistencies in event validation for m.room.create events (#13087)
* Extend the auth rule checks for `m.room.create` events ... and move them up to the top of the function. Since the no auth_events are allowed for m.room.create events, we may as well get the m.room.create event checks out of the way first. * Add a test for create events with prev_events
1 parent d3d8468 commit e16ea87

File tree

3 files changed

+88
-25
lines changed

3 files changed

+88
-25
lines changed

changelog.d/13087.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix some inconsistencies in the event authentication code.

synapse/event_auth.py

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,15 @@ async def check_state_independent_auth_rules(
141141
Raises:
142142
AuthError if the checks fail
143143
"""
144+
# Implementation of https://spec.matrix.org/v1.2/rooms/v9/#authorization-rules
145+
146+
# 1. If type is m.room.create:
147+
if event.type == EventTypes.Create:
148+
_check_create(event)
149+
150+
# 1.5 Otherwise, allow
151+
return
152+
144153
# Check the auth events.
145154
auth_events = await store.get_events(
146155
event.auth_event_ids(),
@@ -180,29 +189,6 @@ async def check_state_independent_auth_rules(
180189

181190
auth_dict[(auth_event.type, auth_event.state_key)] = auth_event_id
182191

183-
# Implementation of https://matrix.org/docs/spec/rooms/v1#authorization-rules
184-
#
185-
# 1. If type is m.room.create:
186-
if event.type == EventTypes.Create:
187-
# 1b. If the domain of the room_id does not match the domain of the sender,
188-
# reject.
189-
sender_domain = get_domain_from_id(event.sender)
190-
room_id_domain = get_domain_from_id(event.room_id)
191-
if room_id_domain != sender_domain:
192-
raise AuthError(
193-
403, "Creation event's room_id domain does not match sender's"
194-
)
195-
196-
# 1c. If content.room_version is present and is not a recognised version, reject
197-
room_version_prop = event.content.get("room_version", "1")
198-
if room_version_prop not in KNOWN_ROOM_VERSIONS:
199-
raise AuthError(
200-
403,
201-
"room appears to have unsupported version %s" % (room_version_prop,),
202-
)
203-
204-
return
205-
206192
# 3. If event does not have a m.room.create in its auth_events, reject.
207193
creation_event = auth_dict.get((EventTypes.Create, ""), None)
208194
if not creation_event:
@@ -324,6 +310,41 @@ def _check_size_limits(event: "EventBase") -> None:
324310
raise EventSizeError("event too large")
325311

326312

313+
def _check_create(event: "EventBase") -> None:
314+
"""Implementation of the auth rules for m.room.create events
315+
316+
Args:
317+
event: The `m.room.create` event to be checked
318+
319+
Raises:
320+
AuthError if the event does not pass the auth rules
321+
"""
322+
assert event.type == EventTypes.Create
323+
324+
# 1.1 If it has any previous events, reject.
325+
if event.prev_event_ids():
326+
raise AuthError(403, "Create event has prev events")
327+
328+
# 1.2 If the domain of the room_id does not match the domain of the sender,
329+
# reject.
330+
sender_domain = get_domain_from_id(event.sender)
331+
room_id_domain = get_domain_from_id(event.room_id)
332+
if room_id_domain != sender_domain:
333+
raise AuthError(403, "Creation event's room_id domain does not match sender's")
334+
335+
# 1.3 If content.room_version is present and is not a recognised version, reject
336+
room_version_prop = event.content.get("room_version", "1")
337+
if room_version_prop not in KNOWN_ROOM_VERSIONS:
338+
raise AuthError(
339+
403,
340+
"room appears to have unsupported version %s" % (room_version_prop,),
341+
)
342+
343+
# 1.4 If content has no creator field, reject.
344+
if EventContentFields.ROOM_CREATOR not in event.content:
345+
raise AuthError(403, "Create event lacks a 'creator' property")
346+
347+
327348
def _can_federate(event: "EventBase", auth_events: StateMap["EventBase"]) -> bool:
328349
creation_event = auth_events.get((EventTypes.Create, ""))
329350
# There should always be a creation event, but if not don't federate.

tests/test_event_auth.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,47 @@ def test_rejected_auth_events(self):
109109
)
110110
)
111111

112+
def test_create_event_with_prev_events(self):
113+
"""A create event with prev_events should be rejected
114+
115+
https://spec.matrix.org/v1.3/rooms/v9/#authorization-rules
116+
1: If type is m.room.create:
117+
1. If it has any previous events, reject.
118+
"""
119+
creator = f"@creator:{TEST_DOMAIN}"
120+
121+
# we make both a good event and a bad event, to check that we are rejecting
122+
# the bad event for the reason we think we are.
123+
good_event = make_event_from_dict(
124+
{
125+
"room_id": TEST_ROOM_ID,
126+
"type": "m.room.create",
127+
"state_key": "",
128+
"sender": creator,
129+
"content": {
130+
"creator": creator,
131+
"room_version": RoomVersions.V9.identifier,
132+
},
133+
"auth_events": [],
134+
"prev_events": [],
135+
},
136+
room_version=RoomVersions.V9,
137+
)
138+
bad_event = make_event_from_dict(
139+
{**good_event.get_dict(), "prev_events": ["$fakeevent"]},
140+
room_version=RoomVersions.V9,
141+
)
142+
143+
event_store = _StubEventSourceStore()
144+
145+
get_awaitable_result(
146+
event_auth.check_state_independent_auth_rules(event_store, good_event)
147+
)
148+
with self.assertRaises(AuthError):
149+
get_awaitable_result(
150+
event_auth.check_state_independent_auth_rules(event_store, bad_event)
151+
)
152+
112153
def test_random_users_cannot_send_state_before_first_pl(self):
113154
"""
114155
Check that, before the first PL lands, the creator is the only user
@@ -564,8 +605,8 @@ def test_join_rules_msc3083_restricted(self) -> None:
564605

565606

566607
# helpers for making events
567-
568-
TEST_ROOM_ID = "!test:room"
608+
TEST_DOMAIN = "example.com"
609+
TEST_ROOM_ID = f"!test_room:{TEST_DOMAIN}"
569610

570611

571612
def _create_event(

0 commit comments

Comments
 (0)