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

Commit

Permalink
Pass room version object into event_auth.check and check_redaction (#…
Browse files Browse the repository at this point in the history
…6788)

These are easier to work with than the strings and we normally have one around.

This fixes `FederationHander._persist_auth_tree` which was passing a
RoomVersion object into event_auth.check instead of a string.
  • Loading branch information
richvdh committed Jan 28, 2020
1 parent 02b44db commit a8ce7ae
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 34 deletions.
1 change: 1 addition & 0 deletions changelog.d/6788.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Record room versions in the `rooms` table.
7 changes: 5 additions & 2 deletions synapse/api/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
MissingClientTokenError,
ResourceLimitError,
)
from synapse.api.room_versions import KNOWN_ROOM_VERSIONS
from synapse.config.server import is_threepid_reserved
from synapse.types import StateMap, UserID
from synapse.util.caches import CACHE_SIZE_FACTOR, register_cache
Expand Down Expand Up @@ -77,15 +78,17 @@ def __init__(self, hs):
self._account_validity = hs.config.account_validity

@defer.inlineCallbacks
def check_from_context(self, room_version, event, context, do_sig_check=True):
def check_from_context(self, room_version: str, event, context, do_sig_check=True):
prev_state_ids = yield context.get_prev_state_ids()
auth_events_ids = yield self.compute_auth_events(
event, prev_state_ids, for_verification=True
)
auth_events = yield self.store.get_events(auth_events_ids)
auth_events = {(e.type, e.state_key): e for e in itervalues(auth_events)}

room_version_obj = KNOWN_ROOM_VERSIONS[room_version]
event_auth.check(
room_version, event, auth_events=auth_events, do_sig_check=do_sig_check
room_version_obj, event, auth_events=auth_events, do_sig_check=do_sig_check
)

@defer.inlineCallbacks
Expand Down
34 changes: 21 additions & 13 deletions synapse/event_auth.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright 2014 - 2016 OpenMarket Ltd
# Copyright 2020 The Matrix.org Foundation C.I.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -23,17 +24,27 @@

from synapse.api.constants import EventTypes, JoinRules, Membership
from synapse.api.errors import AuthError, EventSizeError, SynapseError
from synapse.api.room_versions import KNOWN_ROOM_VERSIONS, EventFormatVersions
from synapse.api.room_versions import (
KNOWN_ROOM_VERSIONS,
EventFormatVersions,
RoomVersion,
)
from synapse.types import UserID, get_domain_from_id

logger = logging.getLogger(__name__)


def check(room_version, event, auth_events, do_sig_check=True, do_size_check=True):
def check(
room_version_obj: RoomVersion,
event,
auth_events,
do_sig_check=True,
do_size_check=True,
):
""" Checks if this event is correctly authed.
Args:
room_version (str): the version of the room
room_version_obj: the version of the room
event: the event being checked.
auth_events (dict: event-key -> event): the existing room state.
Expand Down Expand Up @@ -97,10 +108,11 @@ def check(room_version, event, auth_events, do_sig_check=True, do_size_check=Tru
403, "Creation event's room_id domain does not match sender's"
)

room_version = event.content.get("room_version", "1")
if room_version not in KNOWN_ROOM_VERSIONS:
room_version_prop = event.content.get("room_version", "1")
if room_version_prop not in KNOWN_ROOM_VERSIONS:
raise AuthError(
403, "room appears to have unsupported version %s" % (room_version,)
403,
"room appears to have unsupported version %s" % (room_version_prop,),
)
# FIXME
logger.debug("Allowing! %s", event)
Expand Down Expand Up @@ -160,7 +172,7 @@ def check(room_version, event, auth_events, do_sig_check=True, do_size_check=Tru
_check_power_levels(event, auth_events)

if event.type == EventTypes.Redaction:
check_redaction(room_version, event, auth_events)
check_redaction(room_version_obj, event, auth_events)

logger.debug("Allowing! %s", event)

Expand Down Expand Up @@ -386,7 +398,7 @@ def _can_send_event(event, auth_events):
return True


def check_redaction(room_version, event, auth_events):
def check_redaction(room_version_obj: RoomVersion, event, auth_events):
"""Check whether the event sender is allowed to redact the target event.
Returns:
Expand All @@ -406,11 +418,7 @@ def check_redaction(room_version, event, auth_events):
if user_level >= redact_level:
return False

v = KNOWN_ROOM_VERSIONS.get(room_version)
if not v:
raise RuntimeError("Unrecognized room version %r" % (room_version,))

if v.event_format == EventFormatVersions.V1:
if room_version_obj.event_format == EventFormatVersions.V1:
redacter_domain = get_domain_from_id(event.event_id)
redactee_domain = get_domain_from_id(event.redacts)
if redacter_domain == redactee_domain:
Expand Down
18 changes: 11 additions & 7 deletions synapse/handlers/federation.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
from synapse.api.room_versions import KNOWN_ROOM_VERSIONS, RoomVersion, RoomVersions
from synapse.crypto.event_signing import compute_event_signature
from synapse.event_auth import auth_types_for_event
from synapse.events import EventBase, room_version_to_event_format
from synapse.events import EventBase
from synapse.events.snapshot import EventContext
from synapse.events.validator import EventValidator
from synapse.logging.context import (
Expand Down Expand Up @@ -1198,7 +1198,7 @@ def do_invite_join(self, target_hosts, room_id, joinee, content):
"""
logger.debug("Joining %s to %s", joinee, room_id)

origin, event, room_version = yield self._make_and_verify_event(
origin, event, room_version_obj = yield self._make_and_verify_event(
target_hosts,
room_id,
joinee,
Expand Down Expand Up @@ -1227,7 +1227,7 @@ def do_invite_join(self, target_hosts, room_id, joinee, content):
except ValueError:
pass

event_format_version = room_version_to_event_format(room_version.identifier)
event_format_version = room_version_obj.event_format
ret = yield self.federation_client.send_join(
target_hosts, event, event_format_version
)
Expand All @@ -1251,14 +1251,14 @@ def do_invite_join(self, target_hosts, room_id, joinee, content):
room_id=room_id,
room_creator_user_id="",
is_public=False,
room_version=room_version,
room_version=room_version_obj,
)
except Exception:
# FIXME
pass

yield self._persist_auth_tree(
origin, auth_chain, state, event, room_version
origin, auth_chain, state, event, room_version_obj
)

# Check whether this room is the result of an upgrade of a room we already know
Expand Down Expand Up @@ -2022,6 +2022,7 @@ def _check_for_soft_fail(

if do_soft_fail_check:
room_version = yield self.store.get_room_version(event.room_id)
room_version_obj = KNOWN_ROOM_VERSIONS[room_version]

# Calculate the "current state".
if state is not None:
Expand Down Expand Up @@ -2071,7 +2072,9 @@ def _check_for_soft_fail(
}

try:
event_auth.check(room_version, event, auth_events=current_auth_events)
event_auth.check(
room_version_obj, event, auth_events=current_auth_events
)
except AuthError as e:
logger.warning("Soft-failing %r because %s", event, e)
event.internal_metadata.soft_failed = True
Expand Down Expand Up @@ -2155,6 +2158,7 @@ def do_auth(self, origin, event, context, auth_events):
defer.Deferred[EventContext]: updated context object
"""
room_version = yield self.store.get_room_version(event.room_id)
room_version_obj = KNOWN_ROOM_VERSIONS[room_version]

try:
context = yield self._update_auth_events_and_context_for_auth(
Expand All @@ -2172,7 +2176,7 @@ def do_auth(self, origin, event, context, auth_events):
)

try:
event_auth.check(room_version, event, auth_events=auth_events)
event_auth.check(room_version_obj, event, auth_events=auth_events)
except AuthError as e:
logger.warning("Failed auth resolution for %r because %s", event, e)
context.rejected = RejectedReason.AUTH_ERROR
Expand Down
8 changes: 6 additions & 2 deletions synapse/handlers/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
NotFoundError,
SynapseError,
)
from synapse.api.room_versions import RoomVersions
from synapse.api.room_versions import KNOWN_ROOM_VERSIONS, RoomVersions
from synapse.api.urls import ConsentURIBuilder
from synapse.events.validator import EventValidator
from synapse.logging.context import run_in_background
Expand Down Expand Up @@ -962,9 +962,13 @@ def is_inviter_member_event(e):
)
auth_events = yield self.store.get_events(auth_events_ids)
auth_events = {(e.type, e.state_key): e for e in auth_events.values()}

room_version = yield self.store.get_room_version(event.room_id)
room_version_obj = KNOWN_ROOM_VERSIONS[room_version]

if event_auth.check_redaction(room_version, event, auth_events=auth_events):
if event_auth.check_redaction(
room_version_obj, event, auth_events=auth_events
):
# this user doesn't have 'redact' rights, so we need to do some more
# checks on the original event. Let's start by checking the original
# event exists.
Expand Down
4 changes: 2 additions & 2 deletions synapse/state/v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ def _resolve_auth_events(events, auth_events):
try:
# The signatures have already been checked at this point
event_auth.check(
RoomVersions.V1.identifier,
RoomVersions.V1,
event,
auth_events,
do_sig_check=False,
Expand All @@ -299,7 +299,7 @@ def _resolve_normal_events(events, auth_events):
try:
# The signatures have already been checked at this point
event_auth.check(
RoomVersions.V1.identifier,
RoomVersions.V1,
event,
auth_events,
do_sig_check=False,
Expand Down
4 changes: 3 additions & 1 deletion synapse/state/v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from synapse import event_auth
from synapse.api.constants import EventTypes
from synapse.api.errors import AuthError
from synapse.api.room_versions import KNOWN_ROOM_VERSIONS
from synapse.events import EventBase
from synapse.types import StateMap

Expand Down Expand Up @@ -402,6 +403,7 @@ def _iterative_auth_checks(
Deferred[StateMap[str]]: Returns the final updated state
"""
resolved_state = base_state.copy()
room_version_obj = KNOWN_ROOM_VERSIONS[room_version]

for event_id in event_ids:
event = event_map[event_id]
Expand Down Expand Up @@ -430,7 +432,7 @@ def _iterative_auth_checks(

try:
event_auth.check(
room_version,
room_version_obj,
event,
auth_events,
do_sig_check=False,
Expand Down
11 changes: 4 additions & 7 deletions tests/test_event_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def test_random_users_cannot_send_state_before_first_pl(self):

# creator should be able to send state
event_auth.check(
RoomVersions.V1.identifier,
RoomVersions.V1,
_random_state_event(creator),
auth_events,
do_sig_check=False,
Expand All @@ -47,7 +47,7 @@ def test_random_users_cannot_send_state_before_first_pl(self):
self.assertRaises(
AuthError,
event_auth.check,
RoomVersions.V1.identifier,
RoomVersions.V1,
_random_state_event(joiner),
auth_events,
do_sig_check=False,
Expand Down Expand Up @@ -76,18 +76,15 @@ def test_state_default_level(self):
self.assertRaises(
AuthError,
event_auth.check,
RoomVersions.V1.identifier,
RoomVersions.V1,
_random_state_event(pleb),
auth_events,
do_sig_check=False,
),

# king should be able to send state
event_auth.check(
RoomVersions.V1.identifier,
_random_state_event(king),
auth_events,
do_sig_check=False,
RoomVersions.V1, _random_state_event(king), auth_events, do_sig_check=False,
)


Expand Down

0 comments on commit a8ce7ae

Please sign in to comment.