diff --git a/changelog.d/11885.feature b/changelog.d/11885.feature new file mode 100644 index 000000000000..dde48bdd76a1 --- /dev/null +++ b/changelog.d/11885.feature @@ -0,0 +1 @@ +Support [MSC3667](https://github.com/matrix-org/matrix-doc/pull/3667) in a new room version. \ No newline at end of file diff --git a/synapse/api/room_versions.py b/synapse/api/room_versions.py index 3f85d61b4633..432a8027c9c2 100644 --- a/synapse/api/room_versions.py +++ b/synapse/api/room_versions.py @@ -84,6 +84,8 @@ class RoomVersion: # MSC3787: Adds support for a `knock_restricted` join rule, mixing concepts of # knocks and restricted join rules into the same join condition. msc3787_knock_restricted_join_rule: bool + # MSC3667: Treat string format power levels as invalid, thus denied. + msc3667_int_only_power_levels: bool class RoomVersions: @@ -103,6 +105,7 @@ class RoomVersions: msc2716_historical=False, msc2716_redactions=False, msc3787_knock_restricted_join_rule=False, + msc3667_int_only_power_levels=False, ) V2 = RoomVersion( "2", @@ -120,6 +123,7 @@ class RoomVersions: msc2716_historical=False, msc2716_redactions=False, msc3787_knock_restricted_join_rule=False, + msc3667_int_only_power_levels=False, ) V3 = RoomVersion( "3", @@ -137,6 +141,7 @@ class RoomVersions: msc2716_historical=False, msc2716_redactions=False, msc3787_knock_restricted_join_rule=False, + msc3667_int_only_power_levels=False, ) V4 = RoomVersion( "4", @@ -154,6 +159,7 @@ class RoomVersions: msc2716_historical=False, msc2716_redactions=False, msc3787_knock_restricted_join_rule=False, + msc3667_int_only_power_levels=False, ) V5 = RoomVersion( "5", @@ -171,6 +177,7 @@ class RoomVersions: msc2716_historical=False, msc2716_redactions=False, msc3787_knock_restricted_join_rule=False, + msc3667_int_only_power_levels=False, ) V6 = RoomVersion( "6", @@ -188,6 +195,7 @@ class RoomVersions: msc2716_historical=False, msc2716_redactions=False, msc3787_knock_restricted_join_rule=False, + msc3667_int_only_power_levels=False, ) MSC2176 = RoomVersion( "org.matrix.msc2176", @@ -205,6 +213,7 @@ class RoomVersions: msc2716_historical=False, msc2716_redactions=False, msc3787_knock_restricted_join_rule=False, + msc3667_int_only_power_levels=False, ) V7 = RoomVersion( "7", @@ -222,6 +231,7 @@ class RoomVersions: msc2716_historical=False, msc2716_redactions=False, msc3787_knock_restricted_join_rule=False, + msc3667_int_only_power_levels=False, ) V8 = RoomVersion( "8", @@ -239,6 +249,7 @@ class RoomVersions: msc2716_historical=False, msc2716_redactions=False, msc3787_knock_restricted_join_rule=False, + msc3667_int_only_power_levels=False, ) V9 = RoomVersion( "9", @@ -256,6 +267,7 @@ class RoomVersions: msc2716_historical=False, msc2716_redactions=False, msc3787_knock_restricted_join_rule=False, + msc3667_int_only_power_levels=False, ) MSC2716v3 = RoomVersion( "org.matrix.msc2716v3", @@ -273,6 +285,7 @@ class RoomVersions: msc2716_historical=True, msc2716_redactions=True, msc3787_knock_restricted_join_rule=False, + msc3667_int_only_power_levels=False, ) MSC3787 = RoomVersion( "org.matrix.msc3787", @@ -290,6 +303,45 @@ class RoomVersions: msc2716_historical=False, msc2716_redactions=False, msc3787_knock_restricted_join_rule=True, + msc3667_int_only_power_levels=False, + ) + MSC3667 = RoomVersion( + # v7 + MSC3667 + "org.matrix.msc3667", + RoomDisposition.UNSTABLE, + EventFormatVersions.V3, + StateResolutionVersions.V2, + enforce_key_validity=True, + special_case_aliases_auth=False, + strict_canonicaljson=True, + limit_notifications_power_levels=True, + msc2176_redaction_rules=False, + msc3083_join_rules=False, + msc3375_redaction_rules=False, + msc2403_knocking=True, + msc2716_historical=False, + msc2716_redactions=False, + msc3787_knock_restricted_join_rule=False, + msc3667_int_only_power_levels=True, + ) + MSC3604Opt4 = RoomVersion( + # v9 + MSC3667 + MSC3787 + "org.matrix.msc3604.opt4", + RoomDisposition.UNSTABLE, + EventFormatVersions.V3, + StateResolutionVersions.V2, + enforce_key_validity=True, + special_case_aliases_auth=False, + strict_canonicaljson=True, + limit_notifications_power_levels=True, + msc2176_redaction_rules=False, + msc3083_join_rules=True, + msc3375_redaction_rules=True, + msc2403_knocking=True, + msc2716_historical=False, + msc2716_redactions=False, + msc3787_knock_restricted_join_rule=True, + msc3667_int_only_power_levels=True, ) @@ -308,6 +360,8 @@ class RoomVersions: RoomVersions.V9, RoomVersions.MSC2716v3, RoomVersions.MSC3787, + RoomVersions.MSC3667, + RoomVersions.MSC3604Opt4, ) } diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 4c0b587a7643..bbf50d79767e 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -143,6 +143,22 @@ def check_auth_rules_for_event( Raises: AuthError if the checks fail """ + # Before we get too far into event auth, validate that the event is even + # valid enough to be used + if event.type == EventTypes.PowerLevels: + # If applicable, validate that the known power levels are integers + if room_version_obj.msc3667_int_only_power_levels: + for k, v in event.content.items(): + if k in ["events", "notifications", "users"]: + if type(v) is not dict: + raise AuthError(403, "Not a valid object: %s" % (k,)) + for v2 in v.values(): + if type(v2) is not int: + raise AuthError(403, "Not a valid power level: %s" % (v2,)) + else: + if type(v) is not int: + raise AuthError(403, "Not a valid power level: %s" % (v,)) + # We need to ensure that the auth events are actually for the same room, to # stop people from using powers they've been granted in other rooms for # example.