mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-05-03 13:44:48 -04:00
Update the MSC3083 support to verify if joins are from an authorized server. (#10254)
This commit is contained in:
parent
4fb92d93ea
commit
228decfce1
17 changed files with 632 additions and 98 deletions
|
@ -106,6 +106,18 @@ def check(
|
|||
if not event.signatures.get(event_id_domain):
|
||||
raise AuthError(403, "Event not signed by sending server")
|
||||
|
||||
is_invite_via_allow_rule = (
|
||||
event.type == EventTypes.Member
|
||||
and event.membership == Membership.JOIN
|
||||
and "join_authorised_via_users_server" in event.content
|
||||
)
|
||||
if is_invite_via_allow_rule:
|
||||
authoriser_domain = get_domain_from_id(
|
||||
event.content["join_authorised_via_users_server"]
|
||||
)
|
||||
if not event.signatures.get(authoriser_domain):
|
||||
raise AuthError(403, "Event not signed by authorising server")
|
||||
|
||||
# Implementation of https://matrix.org/docs/spec/rooms/v1#authorization-rules
|
||||
#
|
||||
# 1. If type is m.room.create:
|
||||
|
@ -177,7 +189,7 @@ def check(
|
|||
# https://github.com/vector-im/vector-web/issues/1208 hopefully
|
||||
if event.type == EventTypes.ThirdPartyInvite:
|
||||
user_level = get_user_power_level(event.user_id, auth_events)
|
||||
invite_level = _get_named_level(auth_events, "invite", 0)
|
||||
invite_level = get_named_level(auth_events, "invite", 0)
|
||||
|
||||
if user_level < invite_level:
|
||||
raise AuthError(403, "You don't have permission to invite users")
|
||||
|
@ -285,8 +297,8 @@ def _is_membership_change_allowed(
|
|||
user_level = get_user_power_level(event.user_id, auth_events)
|
||||
target_level = get_user_power_level(target_user_id, auth_events)
|
||||
|
||||
# FIXME (erikj): What should we do here as the default?
|
||||
ban_level = _get_named_level(auth_events, "ban", 50)
|
||||
invite_level = get_named_level(auth_events, "invite", 0)
|
||||
ban_level = get_named_level(auth_events, "ban", 50)
|
||||
|
||||
logger.debug(
|
||||
"_is_membership_change_allowed: %s",
|
||||
|
@ -336,8 +348,6 @@ def _is_membership_change_allowed(
|
|||
elif target_in_room: # the target is already in the room.
|
||||
raise AuthError(403, "%s is already in the room." % target_user_id)
|
||||
else:
|
||||
invite_level = _get_named_level(auth_events, "invite", 0)
|
||||
|
||||
if user_level < invite_level:
|
||||
raise AuthError(403, "You don't have permission to invite users")
|
||||
elif Membership.JOIN == membership:
|
||||
|
@ -345,16 +355,41 @@ def _is_membership_change_allowed(
|
|||
# * They are not banned.
|
||||
# * They are accepting a previously sent invitation.
|
||||
# * They are already joined (it's a NOOP).
|
||||
# * The room is public or restricted.
|
||||
# * The room is public.
|
||||
# * The room is restricted and the user meets the allows rules.
|
||||
if event.user_id != target_user_id:
|
||||
raise AuthError(403, "Cannot force another user to join.")
|
||||
elif target_banned:
|
||||
raise AuthError(403, "You are banned from this room")
|
||||
elif join_rule == JoinRules.PUBLIC or (
|
||||
elif join_rule == JoinRules.PUBLIC:
|
||||
pass
|
||||
elif (
|
||||
room_version.msc3083_join_rules
|
||||
and join_rule == JoinRules.MSC3083_RESTRICTED
|
||||
):
|
||||
pass
|
||||
# This is the same as public, but the event must contain a reference
|
||||
# to the server who authorised the join. If the event does not contain
|
||||
# the proper content it is rejected.
|
||||
#
|
||||
# Note that if the caller is in the room or invited, then they do
|
||||
# not need to meet the allow rules.
|
||||
if not caller_in_room and not caller_invited:
|
||||
authorising_user = event.content.get("join_authorised_via_users_server")
|
||||
|
||||
if authorising_user is None:
|
||||
raise AuthError(403, "Join event is missing authorising user.")
|
||||
|
||||
# The authorising user must be in the room.
|
||||
key = (EventTypes.Member, authorising_user)
|
||||
member_event = auth_events.get(key)
|
||||
_check_joined_room(member_event, authorising_user, event.room_id)
|
||||
|
||||
authorising_user_level = get_user_power_level(
|
||||
authorising_user, auth_events
|
||||
)
|
||||
if authorising_user_level < invite_level:
|
||||
raise AuthError(403, "Join event authorised by invalid server.")
|
||||
|
||||
elif join_rule == JoinRules.INVITE or (
|
||||
room_version.msc2403_knocking and join_rule == JoinRules.KNOCK
|
||||
):
|
||||
|
@ -369,7 +404,7 @@ def _is_membership_change_allowed(
|
|||
if target_banned and user_level < ban_level:
|
||||
raise AuthError(403, "You cannot unban user %s." % (target_user_id,))
|
||||
elif target_user_id != event.user_id:
|
||||
kick_level = _get_named_level(auth_events, "kick", 50)
|
||||
kick_level = get_named_level(auth_events, "kick", 50)
|
||||
|
||||
if user_level < kick_level or user_level <= target_level:
|
||||
raise AuthError(403, "You cannot kick user %s." % target_user_id)
|
||||
|
@ -445,7 +480,7 @@ def get_send_level(
|
|||
|
||||
|
||||
def _can_send_event(event: EventBase, auth_events: StateMap[EventBase]) -> bool:
|
||||
power_levels_event = _get_power_level_event(auth_events)
|
||||
power_levels_event = get_power_level_event(auth_events)
|
||||
|
||||
send_level = get_send_level(event.type, event.get("state_key"), power_levels_event)
|
||||
user_level = get_user_power_level(event.user_id, auth_events)
|
||||
|
@ -485,7 +520,7 @@ def check_redaction(
|
|||
"""
|
||||
user_level = get_user_power_level(event.user_id, auth_events)
|
||||
|
||||
redact_level = _get_named_level(auth_events, "redact", 50)
|
||||
redact_level = get_named_level(auth_events, "redact", 50)
|
||||
|
||||
if user_level >= redact_level:
|
||||
return False
|
||||
|
@ -600,7 +635,7 @@ def _check_power_levels(
|
|||
)
|
||||
|
||||
|
||||
def _get_power_level_event(auth_events: StateMap[EventBase]) -> Optional[EventBase]:
|
||||
def get_power_level_event(auth_events: StateMap[EventBase]) -> Optional[EventBase]:
|
||||
return auth_events.get((EventTypes.PowerLevels, ""))
|
||||
|
||||
|
||||
|
@ -616,7 +651,7 @@ def get_user_power_level(user_id: str, auth_events: StateMap[EventBase]) -> int:
|
|||
Returns:
|
||||
the user's power level in this room.
|
||||
"""
|
||||
power_level_event = _get_power_level_event(auth_events)
|
||||
power_level_event = get_power_level_event(auth_events)
|
||||
if power_level_event:
|
||||
level = power_level_event.content.get("users", {}).get(user_id)
|
||||
if not level:
|
||||
|
@ -640,8 +675,8 @@ def get_user_power_level(user_id: str, auth_events: StateMap[EventBase]) -> int:
|
|||
return 0
|
||||
|
||||
|
||||
def _get_named_level(auth_events: StateMap[EventBase], name: str, default: int) -> int:
|
||||
power_level_event = _get_power_level_event(auth_events)
|
||||
def get_named_level(auth_events: StateMap[EventBase], name: str, default: int) -> int:
|
||||
power_level_event = get_power_level_event(auth_events)
|
||||
|
||||
if not power_level_event:
|
||||
return default
|
||||
|
@ -728,7 +763,9 @@ def get_public_keys(invite_event: EventBase) -> List[Dict[str, Any]]:
|
|||
return public_keys
|
||||
|
||||
|
||||
def auth_types_for_event(event: Union[EventBase, EventBuilder]) -> Set[Tuple[str, str]]:
|
||||
def auth_types_for_event(
|
||||
room_version: RoomVersion, event: Union[EventBase, EventBuilder]
|
||||
) -> Set[Tuple[str, str]]:
|
||||
"""Given an event, return a list of (EventType, StateKey) that may be
|
||||
needed to auth the event. The returned list may be a superset of what
|
||||
would actually be required depending on the full state of the room.
|
||||
|
@ -760,4 +797,12 @@ def auth_types_for_event(event: Union[EventBase, EventBuilder]) -> Set[Tuple[str
|
|||
)
|
||||
auth_types.add(key)
|
||||
|
||||
if room_version.msc3083_join_rules and membership == Membership.JOIN:
|
||||
if "join_authorised_via_users_server" in event.content:
|
||||
key = (
|
||||
EventTypes.Member,
|
||||
event.content["join_authorised_via_users_server"],
|
||||
)
|
||||
auth_types.add(key)
|
||||
|
||||
return auth_types
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue