Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support MSC3757: Restricting who can overwrite a state event #17513

Merged
merged 29 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7855b97
Support MSC3757
AndrewFerr Jun 13, 2024
6ec215b
Add changelog
AndrewFerr Aug 1, 2024
6a69213
Run power level tests on MSC3757 rooms
AndrewFerr Aug 7, 2024
e481238
Check if @-prefixed state key is not a user ID
AndrewFerr Aug 8, 2024
248025d
Test MSC3757 auth rules
AndrewFerr Aug 8, 2024
a12238d
Support MSC3757 for room versions 9 and 11
AndrewFerr Aug 8, 2024
663da8d
Skip redundant characters for some string searches
AndrewFerr Aug 12, 2024
c4cc4d8
Add explicit field to room version for MSC3757
AndrewFerr Aug 15, 2024
5657863
Parametrize fewer power level unit tests
AndrewFerr Aug 15, 2024
e9d22ba
Lint
AndrewFerr Aug 15, 2024
228d6b4
Return 400 for @-prefixed, non-userID state key
AndrewFerr Sep 4, 2024
e175871
Define test event type string once
AndrewFerr Sep 4, 2024
a841921
Lint
AndrewFerr Sep 4, 2024
772d35a
Refactor state key parsing
AndrewFerr Sep 5, 2024
ba2ce94
Split & comment allow conditions
AndrewFerr Sep 5, 2024
77af387
Drop support for room version 9
AndrewFerr Sep 5, 2024
6f429b6
Refactor unit tests
AndrewFerr Sep 5, 2024
defeb6e
Use one expression for commented allow conditions
AndrewFerr Sep 5, 2024
426f52b
Narrow caught error type
AndrewFerr Sep 9, 2024
8c203af
Remove license header from new test file
AndrewFerr Sep 11, 2024
0d901f7
Run Complement tests
AndrewFerr Sep 16, 2024
b16fa10
Make suffix test actually use suffix
AndrewFerr Sep 23, 2024
77fc9d2
Test suffixed key without separator
AndrewFerr Sep 23, 2024
c0dceaf
Lock non-owned-state tests to non-MSC room version
AndrewFerr Sep 23, 2024
e1fa3ef
Test user ID in middle of state key
AndrewFerr Sep 23, 2024
7bcd7a0
Rename admin to "room creator"
AndrewFerr Sep 25, 2024
d28c17b
Test state with key of a user ID not in the room
AndrewFerr Sep 25, 2024
792b065
Always check the errcode in failure responses
AndrewFerr Sep 25, 2024
89b20d4
Merge branch 'develop' into af/msc3757
sandhose Sep 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/17513.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add implementation of restricting who can overwrite a state event as proposed by [MSC3757](https://github.com/matrix-org/matrix-spec-proposals/pull/3757).
58 changes: 58 additions & 0 deletions synapse/api/room_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ class RoomVersion:
# support the flag. Unknown flags are ignored by the evaluator, making conditions
# fail if used.
msc3931_push_features: Tuple[str, ...] # values from PushRuleRoomFlag
# MSC3757: Restricting who can overwrite a state event
msc3757_enabled: bool


class RoomVersions:
Expand All @@ -128,6 +130,7 @@ class RoomVersions:
knock_restricted_join_rule=False,
enforce_int_power_levels=False,
msc3931_push_features=(),
msc3757_enabled=False,
)
V2 = RoomVersion(
"2",
Expand All @@ -147,6 +150,7 @@ class RoomVersions:
knock_restricted_join_rule=False,
enforce_int_power_levels=False,
msc3931_push_features=(),
msc3757_enabled=False,
)
V3 = RoomVersion(
"3",
Expand All @@ -166,6 +170,7 @@ class RoomVersions:
knock_restricted_join_rule=False,
enforce_int_power_levels=False,
msc3931_push_features=(),
msc3757_enabled=False,
)
V4 = RoomVersion(
"4",
Expand All @@ -185,6 +190,7 @@ class RoomVersions:
knock_restricted_join_rule=False,
enforce_int_power_levels=False,
msc3931_push_features=(),
msc3757_enabled=False,
)
V5 = RoomVersion(
"5",
Expand All @@ -204,6 +210,7 @@ class RoomVersions:
knock_restricted_join_rule=False,
enforce_int_power_levels=False,
msc3931_push_features=(),
msc3757_enabled=False,
)
V6 = RoomVersion(
"6",
Expand All @@ -223,6 +230,7 @@ class RoomVersions:
knock_restricted_join_rule=False,
enforce_int_power_levels=False,
msc3931_push_features=(),
msc3757_enabled=False,
)
V7 = RoomVersion(
"7",
Expand All @@ -242,6 +250,7 @@ class RoomVersions:
knock_restricted_join_rule=False,
enforce_int_power_levels=False,
msc3931_push_features=(),
msc3757_enabled=False,
)
V8 = RoomVersion(
"8",
Expand All @@ -261,6 +270,7 @@ class RoomVersions:
knock_restricted_join_rule=False,
enforce_int_power_levels=False,
msc3931_push_features=(),
msc3757_enabled=False,
)
V9 = RoomVersion(
"9",
Expand All @@ -280,6 +290,7 @@ class RoomVersions:
knock_restricted_join_rule=False,
enforce_int_power_levels=False,
msc3931_push_features=(),
msc3757_enabled=False,
)
V10 = RoomVersion(
"10",
Expand All @@ -299,6 +310,7 @@ class RoomVersions:
knock_restricted_join_rule=True,
enforce_int_power_levels=True,
msc3931_push_features=(),
msc3757_enabled=False,
)
MSC1767v10 = RoomVersion(
# MSC1767 (Extensible Events) based on room version "10"
Expand All @@ -319,6 +331,28 @@ class RoomVersions:
knock_restricted_join_rule=True,
enforce_int_power_levels=True,
msc3931_push_features=(PushRuleRoomFlag.EXTENSIBLE_EVENTS,),
msc3757_enabled=False,
)
MSC3757v10 = RoomVersion(
sandhose marked this conversation as resolved.
Show resolved Hide resolved
# MSC3757 (Restricting who can overwrite a state event) based on room version "10"
"org.matrix.msc3757.10",
RoomDisposition.UNSTABLE,
EventFormatVersions.ROOM_V4_PLUS,
StateResolutionVersions.V2,
enforce_key_validity=True,
special_case_aliases_auth=False,
strict_canonicaljson=True,
limit_notifications_power_levels=True,
implicit_room_creator=False,
updated_redaction_rules=False,
restricted_join_rule=True,
restricted_join_rule_fix=True,
knock_join_rule=True,
msc3389_relation_redactions=False,
knock_restricted_join_rule=True,
enforce_int_power_levels=True,
msc3931_push_features=(),
msc3757_enabled=True,
)
V11 = RoomVersion(
"11",
Expand All @@ -338,6 +372,28 @@ class RoomVersions:
knock_restricted_join_rule=True,
enforce_int_power_levels=True,
msc3931_push_features=(),
msc3757_enabled=False,
)
MSC3757v11 = RoomVersion(
# MSC3757 (Restricting who can overwrite a state event) based on room version "11"
"org.matrix.msc3757.11",
RoomDisposition.UNSTABLE,
EventFormatVersions.ROOM_V4_PLUS,
StateResolutionVersions.V2,
enforce_key_validity=True,
special_case_aliases_auth=False,
strict_canonicaljson=True,
limit_notifications_power_levels=True,
implicit_room_creator=True, # Used by MSC3820
updated_redaction_rules=True, # Used by MSC3820
restricted_join_rule=True,
restricted_join_rule_fix=True,
knock_join_rule=True,
msc3389_relation_redactions=False,
knock_restricted_join_rule=True,
enforce_int_power_levels=True,
msc3931_push_features=(),
msc3757_enabled=True,
)


Expand All @@ -355,6 +411,8 @@ class RoomVersions:
RoomVersions.V9,
RoomVersions.V10,
RoomVersions.V11,
RoomVersions.MSC3757v10,
RoomVersions.MSC3757v11,
)
}

Expand Down
37 changes: 31 additions & 6 deletions synapse/event_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ def check_state_dependent_auth_rules(
RoomVersions.V9,
RoomVersions.V10,
RoomVersions.MSC1767v10,
RoomVersions.MSC3757v10,
}


Expand Down Expand Up @@ -790,9 +791,10 @@ def get_send_level(


def _can_send_event(event: "EventBase", auth_events: StateMap["EventBase"]) -> bool:
state_key = event.get_state_key()
power_levels_event = get_power_level_event(auth_events)

send_level = get_send_level(event.type, event.get("state_key"), power_levels_event)
send_level = get_send_level(event.type, state_key, power_levels_event)
user_level = get_user_power_level(event.user_id, auth_events)

if user_level < send_level:
Expand All @@ -803,11 +805,34 @@ def _can_send_event(event: "EventBase", auth_events: StateMap["EventBase"]) -> b
errcode=Codes.INSUFFICIENT_POWER,
)

# Check state_key
if hasattr(event, "state_key"):
if event.state_key.startswith("@"):
if event.state_key != event.user_id:
raise AuthError(403, "You are not allowed to set others state")
if (
state_key is not None
and state_key.startswith("@")
and state_key != event.user_id
):
if event.room_version.msc3757_enabled:
try:
colon_idx = state_key.index(":", 1)
suffix_idx = state_key.find("_", colon_idx + 1)
AndrewFerr marked this conversation as resolved.
Show resolved Hide resolved
state_key_user_id = (
state_key[:suffix_idx] if suffix_idx != -1 else state_key
AndrewFerr marked this conversation as resolved.
Show resolved Hide resolved
)
if not UserID.is_valid(state_key_user_id):
raise ValueError
except ValueError:
raise SynapseError(
400,
"State key neither equals a valid user ID, nor starts with one plus an underscore",
errcode=Codes.BAD_JSON,
)
if (
# sender is owner of the state key
state_key_user_id == event.user_id
# sender has higher PL than the owner of the state key
or user_level > get_user_power_level(state_key_user_id, auth_events)
):
return True
raise AuthError(403, "You are not allowed to set others state")

return True

Expand Down
Loading
Loading