0
0
Fork 1
mirror of https://mau.dev/maunium/synapse.git synced 2024-12-13 13:03:27 +01:00

Move some event auth checks out to a different method (#13065)

* Add auth events to events used in tests

* Move some event auth checks out to a different method

Some of the event auth checks apply to an event's auth_events, rather than the
state at the event - which means they can play no part in state
resolution. Move them out to a separate method.

* Rename check_auth_rules_for_event

Now it only checks the state-dependent auth rules, it needs a better name.
This commit is contained in:
Richard van der Hoff 2022-06-15 19:48:22 +01:00 committed by GitHub
parent cba1c5cbc2
commit 8ecf6be1e1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 219 additions and 98 deletions

1
changelog.d/13065.misc Normal file
View file

@ -0,0 +1 @@
Avoid rechecking event auth rules which are independent of room state.

View file

@ -15,11 +15,12 @@
import logging import logging
import typing import typing
from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Union from typing import Any, Collection, Dict, Iterable, List, Optional, Set, Tuple, Union
from canonicaljson import encode_canonical_json from canonicaljson import encode_canonical_json
from signedjson.key import decode_verify_key_bytes from signedjson.key import decode_verify_key_bytes
from signedjson.sign import SignatureVerifyException, verify_signed_json from signedjson.sign import SignatureVerifyException, verify_signed_json
from typing_extensions import Protocol
from unpaddedbase64 import decode_base64 from unpaddedbase64 import decode_base64
from synapse.api.constants import ( from synapse.api.constants import (
@ -35,7 +36,8 @@ from synapse.api.room_versions import (
EventFormatVersions, EventFormatVersions,
RoomVersion, RoomVersion,
) )
from synapse.types import StateMap, UserID, get_domain_from_id from synapse.storage.databases.main.events_worker import EventRedactBehaviour
from synapse.types import MutableStateMap, StateMap, UserID, get_domain_from_id
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
# conditional imports to avoid import cycle # conditional imports to avoid import cycle
@ -45,6 +47,17 @@ if typing.TYPE_CHECKING:
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class _EventSourceStore(Protocol):
async def get_events(
self,
event_ids: Collection[str],
redact_behaviour: EventRedactBehaviour,
get_prev_content: bool = False,
allow_rejected: bool = False,
) -> Dict[str, "EventBase"]:
...
def validate_event_for_room_version(event: "EventBase") -> None: def validate_event_for_room_version(event: "EventBase") -> None:
"""Ensure that the event complies with the limits, and has the right signatures """Ensure that the event complies with the limits, and has the right signatures
@ -112,47 +125,52 @@ def validate_event_for_room_version(event: "EventBase") -> None:
raise AuthError(403, "Event not signed by authorising server") raise AuthError(403, "Event not signed by authorising server")
def check_auth_rules_for_event( async def check_state_independent_auth_rules(
store: _EventSourceStore,
event: "EventBase", event: "EventBase",
auth_events: Iterable["EventBase"],
) -> None: ) -> None:
"""Check that an event complies with the auth rules """Check that an event complies with auth rules that are independent of room state
Checks whether an event passes the auth rules with a given set of state events Runs through the first few auth rules, which are independent of room state. (Which
means that we only need to them once for each received event)
Assumes that we have already checked that the event is the right shape (it has
enough signatures, has a room ID, etc). In other words:
- it's fine for use in state resolution, when we have already decided whether to
accept the event or not, and are now trying to decide whether it should make it
into the room state
- when we're doing the initial event auth, it is only suitable in combination with
a bunch of other tests.
Args: Args:
store: the datastore; used to fetch the auth events for validation
event: the event being checked. event: the event being checked.
auth_events: the room state to check the events against.
Raises: Raises:
AuthError if the checks fail AuthError if the checks fail
""" """
# We need to ensure that the auth events are actually for the same room, to # Check the auth events.
# stop people from using powers they've been granted in other rooms for auth_events = await store.get_events(
# example. event.auth_event_ids(),
# redact_behaviour=EventRedactBehaviour.as_is,
# Arguably we don't need to do this when we're just doing state res, as presumably allow_rejected=True,
# the state res algorithm isn't silly enough to give us events from different rooms. )
# Still, it's easier to do it anyway.
room_id = event.room_id room_id = event.room_id
for auth_event in auth_events: auth_dict: MutableStateMap[str] = {}
for auth_event_id in event.auth_event_ids():
auth_event = auth_events.get(auth_event_id)
# we should have all the auth events by now, so if we do not, that suggests
# a synapse programming error
if auth_event is None:
raise RuntimeError(
f"Event {event.event_id} has unknown auth event {auth_event_id}"
)
# 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.
if auth_event.room_id != room_id: if auth_event.room_id != room_id:
raise AuthError( raise AuthError(
403, 403,
"During auth for event %s in room %s, found event %s in the state " "During auth for event %s in room %s, found event %s in the state "
"which is in room %s" "which is in room %s"
% (event.event_id, room_id, auth_event.event_id, auth_event.room_id), % (event.event_id, room_id, auth_event_id, auth_event.room_id),
) )
# We also need to check that the auth event itself is not rejected.
if auth_event.rejected_reason: if auth_event.rejected_reason:
raise AuthError( raise AuthError(
403, 403,
@ -160,6 +178,8 @@ def check_auth_rules_for_event(
% (event.event_id, auth_event.event_id), % (event.event_id, auth_event.event_id),
) )
auth_dict[(auth_event.type, auth_event.state_key)] = auth_event_id
# Implementation of https://matrix.org/docs/spec/rooms/v1#authorization-rules # Implementation of https://matrix.org/docs/spec/rooms/v1#authorization-rules
# #
# 1. If type is m.room.create: # 1. If type is m.room.create:
@ -181,16 +201,46 @@ def check_auth_rules_for_event(
"room appears to have unsupported version %s" % (room_version_prop,), "room appears to have unsupported version %s" % (room_version_prop,),
) )
logger.debug("Allowing! %s", event)
return return
auth_dict = {(e.type, e.state_key): e for e in auth_events}
# 3. If event does not have a m.room.create in its auth_events, reject. # 3. If event does not have a m.room.create in its auth_events, reject.
creation_event = auth_dict.get((EventTypes.Create, ""), None) creation_event = auth_dict.get((EventTypes.Create, ""), None)
if not creation_event: if not creation_event:
raise AuthError(403, "No create event in auth events") raise AuthError(403, "No create event in auth events")
def check_state_dependent_auth_rules(
event: "EventBase",
auth_events: Iterable["EventBase"],
) -> None:
"""Check that an event complies with auth rules that depend on room state
Runs through the parts of the auth rules that check an event against bits of room
state.
Note:
- it's fine for use in state resolution, when we have already decided whether to
accept the event or not, and are now trying to decide whether it should make it
into the room state
- when we're doing the initial event auth, it is only suitable in combination with
a bunch of other tests (including, but not limited to, check_state_independent_auth_rules).
Args:
event: the event being checked.
auth_events: the room state to check the events against.
Raises:
AuthError if the checks fail
"""
# there are no state-dependent auth rules for create events.
if event.type == EventTypes.Create:
logger.debug("Allowing! %s", event)
return
auth_dict = {(e.type, e.state_key): e for e in auth_events}
# additional check for m.federate # additional check for m.federate
creating_domain = get_domain_from_id(event.room_id) creating_domain = get_domain_from_id(event.room_id)
originating_domain = get_domain_from_id(event.sender) originating_domain = get_domain_from_id(event.sender)

View file

@ -23,7 +23,10 @@ from synapse.api.constants import (
) )
from synapse.api.errors import AuthError, Codes, SynapseError from synapse.api.errors import AuthError, Codes, SynapseError
from synapse.api.room_versions import RoomVersion from synapse.api.room_versions import RoomVersion
from synapse.event_auth import check_auth_rules_for_event from synapse.event_auth import (
check_state_dependent_auth_rules,
check_state_independent_auth_rules,
)
from synapse.events import EventBase from synapse.events import EventBase
from synapse.events.builder import EventBuilder from synapse.events.builder import EventBuilder
from synapse.events.snapshot import EventContext from synapse.events.snapshot import EventContext
@ -52,9 +55,10 @@ class EventAuthHandler:
context: EventContext, context: EventContext,
) -> None: ) -> None:
"""Check an event passes the auth rules at its own auth events""" """Check an event passes the auth rules at its own auth events"""
await check_state_independent_auth_rules(self._store, event)
auth_event_ids = event.auth_event_ids() auth_event_ids = event.auth_event_ids()
auth_events_by_id = await self._store.get_events(auth_event_ids) auth_events_by_id = await self._store.get_events(auth_event_ids)
check_auth_rules_for_event(event, auth_events_by_id.values()) check_state_dependent_auth_rules(event, auth_events_by_id.values())
def compute_auth_events( def compute_auth_events(
self, self,

View file

@ -50,7 +50,8 @@ from synapse.api.errors import (
from synapse.api.room_versions import KNOWN_ROOM_VERSIONS, RoomVersion, RoomVersions from synapse.api.room_versions import KNOWN_ROOM_VERSIONS, RoomVersion, RoomVersions
from synapse.event_auth import ( from synapse.event_auth import (
auth_types_for_event, auth_types_for_event,
check_auth_rules_for_event, check_state_dependent_auth_rules,
check_state_independent_auth_rules,
validate_event_for_room_version, validate_event_for_room_version,
) )
from synapse.events import EventBase from synapse.events import EventBase
@ -1430,7 +1431,9 @@ class FederationEventHandler:
allow_rejected=True, allow_rejected=True,
) )
def prep(event: EventBase) -> Optional[Tuple[EventBase, EventContext]]: events_and_contexts_to_persist: List[Tuple[EventBase, EventContext]] = []
async def prep(event: EventBase) -> None:
with nested_logging_context(suffix=event.event_id): with nested_logging_context(suffix=event.event_id):
auth = [] auth = []
for auth_event_id in event.auth_event_ids(): for auth_event_id in event.auth_event_ids():
@ -1444,7 +1447,7 @@ class FederationEventHandler:
event, event,
auth_event_id, auth_event_id,
) )
return None return
auth.append(ae) auth.append(ae)
# we're not bothering about room state, so flag the event as an outlier. # we're not bothering about room state, so flag the event as an outlier.
@ -1453,17 +1456,20 @@ class FederationEventHandler:
context = EventContext.for_outlier(self._storage_controllers) context = EventContext.for_outlier(self._storage_controllers)
try: try:
validate_event_for_room_version(event) validate_event_for_room_version(event)
check_auth_rules_for_event(event, auth) await check_state_independent_auth_rules(self._store, event)
check_state_dependent_auth_rules(event, auth)
except AuthError as e: except AuthError as e:
logger.warning("Rejecting %r because %s", event, e) logger.warning("Rejecting %r because %s", event, e)
context.rejected = RejectedReason.AUTH_ERROR context.rejected = RejectedReason.AUTH_ERROR
return event, context events_and_contexts_to_persist.append((event, context))
for event in fetched_events:
await prep(event)
events_to_persist = (x for x in (prep(event) for event in fetched_events) if x)
await self.persist_events_and_notify( await self.persist_events_and_notify(
room_id, room_id,
tuple(events_to_persist), events_and_contexts_to_persist,
# Mark these events backfilled as they're historic events that will # Mark these events backfilled as they're historic events that will
# eventually be backfilled. For example, missing events we fetch # eventually be backfilled. For example, missing events we fetch
# during backfill should be marked as backfilled as well. # during backfill should be marked as backfilled as well.
@ -1515,7 +1521,8 @@ class FederationEventHandler:
# ... and check that the event passes auth at those auth events. # ... and check that the event passes auth at those auth events.
try: try:
check_auth_rules_for_event(event, claimed_auth_events) await check_state_independent_auth_rules(self._store, event)
check_state_dependent_auth_rules(event, claimed_auth_events)
except AuthError as e: except AuthError as e:
logger.warning( logger.warning(
"While checking auth of %r against auth_events: %s", event, e "While checking auth of %r against auth_events: %s", event, e
@ -1563,7 +1570,7 @@ class FederationEventHandler:
auth_events_for_auth = calculated_auth_event_map auth_events_for_auth = calculated_auth_event_map
try: try:
check_auth_rules_for_event(event, auth_events_for_auth.values()) check_state_dependent_auth_rules(event, auth_events_for_auth.values())
except AuthError as e: except AuthError as e:
logger.warning("Failed auth resolution for %r because %s", event, e) logger.warning("Failed auth resolution for %r because %s", event, e)
context.rejected = RejectedReason.AUTH_ERROR context.rejected = RejectedReason.AUTH_ERROR
@ -1663,7 +1670,7 @@ class FederationEventHandler:
) )
try: try:
check_auth_rules_for_event(event, current_auth_events) check_state_dependent_auth_rules(event, current_auth_events)
except AuthError as e: except AuthError as e:
logger.warning( logger.warning(
"Soft-failing %r (from %s) because %s", "Soft-failing %r (from %s) because %s",

View file

@ -330,7 +330,7 @@ def _resolve_auth_events(
auth_events[(prev_event.type, prev_event.state_key)] = prev_event auth_events[(prev_event.type, prev_event.state_key)] = prev_event
try: try:
# The signatures have already been checked at this point # The signatures have already been checked at this point
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
event, event,
auth_events.values(), auth_events.values(),
) )
@ -347,7 +347,7 @@ def _resolve_normal_events(
for event in _ordered_events(events): for event in _ordered_events(events):
try: try:
# The signatures have already been checked at this point # The signatures have already been checked at this point
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
event, event,
auth_events.values(), auth_events.values(),
) )

View file

@ -573,7 +573,7 @@ async def _iterative_auth_checks(
auth_events[key] = event_map[ev_id] auth_events[key] = event_map[ev_id]
try: try:
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
event, event,
auth_events.values(), auth_events.values(),
) )

View file

@ -1,4 +1,4 @@
# Copyright 2018 New Vector Ltd # Copyright 2018-2022 The Matrix.org Foundation C.I.C.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -13,7 +13,7 @@
# limitations under the License. # limitations under the License.
import unittest import unittest
from typing import Optional from typing import Collection, Dict, Iterable, List, Optional
from parameterized import parameterized from parameterized import parameterized
@ -22,8 +22,41 @@ from synapse.api.constants import EventContentFields
from synapse.api.errors import AuthError from synapse.api.errors import AuthError
from synapse.api.room_versions import EventFormatVersions, RoomVersion, RoomVersions from synapse.api.room_versions import EventFormatVersions, RoomVersion, RoomVersions
from synapse.events import EventBase, make_event_from_dict from synapse.events import EventBase, make_event_from_dict
from synapse.storage.databases.main.events_worker import EventRedactBehaviour
from synapse.types import JsonDict, get_domain_from_id from synapse.types import JsonDict, get_domain_from_id
from tests.test_utils import get_awaitable_result
class _StubEventSourceStore:
"""A stub implementation of the EventSourceStore"""
def __init__(self):
self._store: Dict[str, EventBase] = {}
def add_event(self, event: EventBase):
self._store[event.event_id] = event
def add_events(self, events: Iterable[EventBase]):
for event in events:
self._store[event.event_id] = event
async def get_events(
self,
event_ids: Collection[str],
redact_behaviour: EventRedactBehaviour,
get_prev_content: bool = False,
allow_rejected: bool = False,
) -> Dict[str, EventBase]:
assert allow_rejected
assert not get_prev_content
assert redact_behaviour == EventRedactBehaviour.as_is
results = {}
for e in event_ids:
if e in self._store:
results[e] = self._store[e]
return results
class EventAuthTestCase(unittest.TestCase): class EventAuthTestCase(unittest.TestCase):
def test_rejected_auth_events(self): def test_rejected_auth_events(self):
@ -36,11 +69,15 @@ class EventAuthTestCase(unittest.TestCase):
_join_event(RoomVersions.V9, creator), _join_event(RoomVersions.V9, creator),
] ]
event_store = _StubEventSourceStore()
event_store.add_events(auth_events)
# creator should be able to send state # creator should be able to send state
event_auth.check_auth_rules_for_event( event = _random_state_event(RoomVersions.V9, creator, auth_events)
_random_state_event(RoomVersions.V9, creator), get_awaitable_result(
auth_events, event_auth.check_state_independent_auth_rules(event_store, event)
) )
event_auth.check_state_dependent_auth_rules(event, auth_events)
# ... but a rejected join_rules event should cause it to be rejected # ... but a rejected join_rules event should cause it to be rejected
rejected_join_rules = _join_rules_event( rejected_join_rules = _join_rules_event(
@ -50,23 +87,27 @@ class EventAuthTestCase(unittest.TestCase):
) )
rejected_join_rules.rejected_reason = "stinky" rejected_join_rules.rejected_reason = "stinky"
auth_events.append(rejected_join_rules) auth_events.append(rejected_join_rules)
event_store.add_event(rejected_join_rules)
self.assertRaises( with self.assertRaises(AuthError):
AuthError, get_awaitable_result(
event_auth.check_auth_rules_for_event, event_auth.check_state_independent_auth_rules(
_random_state_event(RoomVersions.V9, creator), event_store,
auth_events, _random_state_event(RoomVersions.V9, creator),
) )
)
# ... even if there is *also* a good join rules # ... even if there is *also* a good join rules
auth_events.append(_join_rules_event(RoomVersions.V9, creator, "public")) auth_events.append(_join_rules_event(RoomVersions.V9, creator, "public"))
event_store.add_event(rejected_join_rules)
self.assertRaises( with self.assertRaises(AuthError):
AuthError, get_awaitable_result(
event_auth.check_auth_rules_for_event, event_auth.check_state_independent_auth_rules(
_random_state_event(RoomVersions.V9, creator), event_store,
auth_events, _random_state_event(RoomVersions.V9, creator),
) )
)
def test_random_users_cannot_send_state_before_first_pl(self): def test_random_users_cannot_send_state_before_first_pl(self):
""" """
@ -82,7 +123,7 @@ class EventAuthTestCase(unittest.TestCase):
] ]
# creator should be able to send state # creator should be able to send state
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_random_state_event(RoomVersions.V1, creator), _random_state_event(RoomVersions.V1, creator),
auth_events, auth_events,
) )
@ -90,7 +131,7 @@ class EventAuthTestCase(unittest.TestCase):
# joiner should not be able to send state # joiner should not be able to send state
self.assertRaises( self.assertRaises(
AuthError, AuthError,
event_auth.check_auth_rules_for_event, event_auth.check_state_dependent_auth_rules,
_random_state_event(RoomVersions.V1, joiner), _random_state_event(RoomVersions.V1, joiner),
auth_events, auth_events,
) )
@ -119,13 +160,13 @@ class EventAuthTestCase(unittest.TestCase):
# pleb should not be able to send state # pleb should not be able to send state
self.assertRaises( self.assertRaises(
AuthError, AuthError,
event_auth.check_auth_rules_for_event, event_auth.check_state_dependent_auth_rules,
_random_state_event(RoomVersions.V1, pleb), _random_state_event(RoomVersions.V1, pleb),
auth_events, auth_events,
), ),
# king should be able to send state # king should be able to send state
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_random_state_event(RoomVersions.V1, king), _random_state_event(RoomVersions.V1, king),
auth_events, auth_events,
) )
@ -140,27 +181,27 @@ class EventAuthTestCase(unittest.TestCase):
] ]
# creator should be able to send aliases # creator should be able to send aliases
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_alias_event(RoomVersions.V1, creator), _alias_event(RoomVersions.V1, creator),
auth_events, auth_events,
) )
# Reject an event with no state key. # Reject an event with no state key.
with self.assertRaises(AuthError): with self.assertRaises(AuthError):
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_alias_event(RoomVersions.V1, creator, state_key=""), _alias_event(RoomVersions.V1, creator, state_key=""),
auth_events, auth_events,
) )
# If the domain of the sender does not match the state key, reject. # If the domain of the sender does not match the state key, reject.
with self.assertRaises(AuthError): with self.assertRaises(AuthError):
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_alias_event(RoomVersions.V1, creator, state_key="test.com"), _alias_event(RoomVersions.V1, creator, state_key="test.com"),
auth_events, auth_events,
) )
# Note that the member does *not* need to be in the room. # Note that the member does *not* need to be in the room.
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_alias_event(RoomVersions.V1, other), _alias_event(RoomVersions.V1, other),
auth_events, auth_events,
) )
@ -175,24 +216,24 @@ class EventAuthTestCase(unittest.TestCase):
] ]
# creator should be able to send aliases # creator should be able to send aliases
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_alias_event(RoomVersions.V6, creator), _alias_event(RoomVersions.V6, creator),
auth_events, auth_events,
) )
# No particular checks are done on the state key. # No particular checks are done on the state key.
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_alias_event(RoomVersions.V6, creator, state_key=""), _alias_event(RoomVersions.V6, creator, state_key=""),
auth_events, auth_events,
) )
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_alias_event(RoomVersions.V6, creator, state_key="test.com"), _alias_event(RoomVersions.V6, creator, state_key="test.com"),
auth_events, auth_events,
) )
# Per standard auth rules, the member must be in the room. # Per standard auth rules, the member must be in the room.
with self.assertRaises(AuthError): with self.assertRaises(AuthError):
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_alias_event(RoomVersions.V6, other), _alias_event(RoomVersions.V6, other),
auth_events, auth_events,
) )
@ -220,12 +261,12 @@ class EventAuthTestCase(unittest.TestCase):
# on room V1, pleb should be able to modify the notifications power level. # on room V1, pleb should be able to modify the notifications power level.
if allow_modification: if allow_modification:
event_auth.check_auth_rules_for_event(pl_event, auth_events) event_auth.check_state_dependent_auth_rules(pl_event, auth_events)
else: else:
# But an MSC2209 room rejects this change. # But an MSC2209 room rejects this change.
with self.assertRaises(AuthError): with self.assertRaises(AuthError):
event_auth.check_auth_rules_for_event(pl_event, auth_events) event_auth.check_state_dependent_auth_rules(pl_event, auth_events)
def test_join_rules_public(self): def test_join_rules_public(self):
""" """
@ -243,14 +284,14 @@ class EventAuthTestCase(unittest.TestCase):
} }
# Check join. # Check join.
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_join_event(RoomVersions.V6, pleb), _join_event(RoomVersions.V6, pleb),
auth_events.values(), auth_events.values(),
) )
# A user cannot be force-joined to a room. # A user cannot be force-joined to a room.
with self.assertRaises(AuthError): with self.assertRaises(AuthError):
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_member_event(RoomVersions.V6, pleb, "join", sender=creator), _member_event(RoomVersions.V6, pleb, "join", sender=creator),
auth_events.values(), auth_events.values(),
) )
@ -260,7 +301,7 @@ class EventAuthTestCase(unittest.TestCase):
RoomVersions.V6, pleb, "ban" RoomVersions.V6, pleb, "ban"
) )
with self.assertRaises(AuthError): with self.assertRaises(AuthError):
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_join_event(RoomVersions.V6, pleb), _join_event(RoomVersions.V6, pleb),
auth_events.values(), auth_events.values(),
) )
@ -269,7 +310,7 @@ class EventAuthTestCase(unittest.TestCase):
auth_events[("m.room.member", pleb)] = _member_event( auth_events[("m.room.member", pleb)] = _member_event(
RoomVersions.V6, pleb, "leave" RoomVersions.V6, pleb, "leave"
) )
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_join_event(RoomVersions.V6, pleb), _join_event(RoomVersions.V6, pleb),
auth_events.values(), auth_events.values(),
) )
@ -278,7 +319,7 @@ class EventAuthTestCase(unittest.TestCase):
auth_events[("m.room.member", pleb)] = _member_event( auth_events[("m.room.member", pleb)] = _member_event(
RoomVersions.V6, pleb, "join" RoomVersions.V6, pleb, "join"
) )
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_join_event(RoomVersions.V6, pleb), _join_event(RoomVersions.V6, pleb),
auth_events.values(), auth_events.values(),
) )
@ -287,7 +328,7 @@ class EventAuthTestCase(unittest.TestCase):
auth_events[("m.room.member", pleb)] = _member_event( auth_events[("m.room.member", pleb)] = _member_event(
RoomVersions.V6, pleb, "invite", sender=creator RoomVersions.V6, pleb, "invite", sender=creator
) )
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_join_event(RoomVersions.V6, pleb), _join_event(RoomVersions.V6, pleb),
auth_events.values(), auth_events.values(),
) )
@ -309,14 +350,14 @@ class EventAuthTestCase(unittest.TestCase):
# A join without an invite is rejected. # A join without an invite is rejected.
with self.assertRaises(AuthError): with self.assertRaises(AuthError):
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_join_event(RoomVersions.V6, pleb), _join_event(RoomVersions.V6, pleb),
auth_events.values(), auth_events.values(),
) )
# A user cannot be force-joined to a room. # A user cannot be force-joined to a room.
with self.assertRaises(AuthError): with self.assertRaises(AuthError):
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_member_event(RoomVersions.V6, pleb, "join", sender=creator), _member_event(RoomVersions.V6, pleb, "join", sender=creator),
auth_events.values(), auth_events.values(),
) )
@ -326,7 +367,7 @@ class EventAuthTestCase(unittest.TestCase):
RoomVersions.V6, pleb, "ban" RoomVersions.V6, pleb, "ban"
) )
with self.assertRaises(AuthError): with self.assertRaises(AuthError):
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_join_event(RoomVersions.V6, pleb), _join_event(RoomVersions.V6, pleb),
auth_events.values(), auth_events.values(),
) )
@ -336,7 +377,7 @@ class EventAuthTestCase(unittest.TestCase):
RoomVersions.V6, pleb, "leave" RoomVersions.V6, pleb, "leave"
) )
with self.assertRaises(AuthError): with self.assertRaises(AuthError):
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_join_event(RoomVersions.V6, pleb), _join_event(RoomVersions.V6, pleb),
auth_events.values(), auth_events.values(),
) )
@ -345,7 +386,7 @@ class EventAuthTestCase(unittest.TestCase):
auth_events[("m.room.member", pleb)] = _member_event( auth_events[("m.room.member", pleb)] = _member_event(
RoomVersions.V6, pleb, "join" RoomVersions.V6, pleb, "join"
) )
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_join_event(RoomVersions.V6, pleb), _join_event(RoomVersions.V6, pleb),
auth_events.values(), auth_events.values(),
) )
@ -354,7 +395,7 @@ class EventAuthTestCase(unittest.TestCase):
auth_events[("m.room.member", pleb)] = _member_event( auth_events[("m.room.member", pleb)] = _member_event(
RoomVersions.V6, pleb, "invite", sender=creator RoomVersions.V6, pleb, "invite", sender=creator
) )
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_join_event(RoomVersions.V6, pleb), _join_event(RoomVersions.V6, pleb),
auth_events.values(), auth_events.values(),
) )
@ -376,7 +417,7 @@ class EventAuthTestCase(unittest.TestCase):
} }
with self.assertRaises(AuthError): with self.assertRaises(AuthError):
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_join_event(RoomVersions.V6, pleb), _join_event(RoomVersions.V6, pleb),
auth_events.values(), auth_events.values(),
) )
@ -413,7 +454,7 @@ class EventAuthTestCase(unittest.TestCase):
EventContentFields.AUTHORISING_USER: "@creator:example.com" EventContentFields.AUTHORISING_USER: "@creator:example.com"
}, },
) )
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
authorised_join_event, authorised_join_event,
auth_events.values(), auth_events.values(),
) )
@ -429,7 +470,7 @@ class EventAuthTestCase(unittest.TestCase):
pl_auth_events[("m.room.member", "@inviter:foo.test")] = _join_event( pl_auth_events[("m.room.member", "@inviter:foo.test")] = _join_event(
RoomVersions.V8, "@inviter:foo.test" RoomVersions.V8, "@inviter:foo.test"
) )
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_join_event( _join_event(
RoomVersions.V8, RoomVersions.V8,
pleb, pleb,
@ -442,7 +483,7 @@ class EventAuthTestCase(unittest.TestCase):
# A join which is missing an authorised server is rejected. # A join which is missing an authorised server is rejected.
with self.assertRaises(AuthError): with self.assertRaises(AuthError):
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_join_event(RoomVersions.V8, pleb), _join_event(RoomVersions.V8, pleb),
auth_events.values(), auth_events.values(),
) )
@ -455,7 +496,7 @@ class EventAuthTestCase(unittest.TestCase):
{"invite": 100, "users": {"@other:example.com": 150}}, {"invite": 100, "users": {"@other:example.com": 150}},
) )
with self.assertRaises(AuthError): with self.assertRaises(AuthError):
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_join_event( _join_event(
RoomVersions.V8, RoomVersions.V8,
pleb, pleb,
@ -469,7 +510,7 @@ class EventAuthTestCase(unittest.TestCase):
# A user cannot be force-joined to a room. (This uses an event which # A user cannot be force-joined to a room. (This uses an event which
# *would* be valid, but is sent be a different user.) # *would* be valid, but is sent be a different user.)
with self.assertRaises(AuthError): with self.assertRaises(AuthError):
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_member_event( _member_event(
RoomVersions.V8, RoomVersions.V8,
pleb, pleb,
@ -487,7 +528,7 @@ class EventAuthTestCase(unittest.TestCase):
RoomVersions.V8, pleb, "ban" RoomVersions.V8, pleb, "ban"
) )
with self.assertRaises(AuthError): with self.assertRaises(AuthError):
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
authorised_join_event, authorised_join_event,
auth_events.values(), auth_events.values(),
) )
@ -496,7 +537,7 @@ class EventAuthTestCase(unittest.TestCase):
auth_events[("m.room.member", pleb)] = _member_event( auth_events[("m.room.member", pleb)] = _member_event(
RoomVersions.V8, pleb, "leave" RoomVersions.V8, pleb, "leave"
) )
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
authorised_join_event, authorised_join_event,
auth_events.values(), auth_events.values(),
) )
@ -506,7 +547,7 @@ class EventAuthTestCase(unittest.TestCase):
auth_events[("m.room.member", pleb)] = _member_event( auth_events[("m.room.member", pleb)] = _member_event(
RoomVersions.V8, pleb, "join" RoomVersions.V8, pleb, "join"
) )
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_join_event(RoomVersions.V8, pleb), _join_event(RoomVersions.V8, pleb),
auth_events.values(), auth_events.values(),
) )
@ -516,7 +557,7 @@ class EventAuthTestCase(unittest.TestCase):
auth_events[("m.room.member", pleb)] = _member_event( auth_events[("m.room.member", pleb)] = _member_event(
RoomVersions.V8, pleb, "invite", sender=creator RoomVersions.V8, pleb, "invite", sender=creator
) )
event_auth.check_auth_rules_for_event( event_auth.check_state_dependent_auth_rules(
_join_event(RoomVersions.V8, pleb), _join_event(RoomVersions.V8, pleb),
auth_events.values(), auth_events.values(),
) )
@ -539,6 +580,7 @@ def _create_event(
"state_key": "", "state_key": "",
"sender": user_id, "sender": user_id,
"content": {"creator": user_id}, "content": {"creator": user_id},
"auth_events": [],
}, },
room_version=room_version, room_version=room_version,
) )
@ -559,6 +601,7 @@ def _member_event(
"sender": sender or user_id, "sender": sender or user_id,
"state_key": user_id, "state_key": user_id,
"content": {"membership": membership, **(additional_content or {})}, "content": {"membership": membership, **(additional_content or {})},
"auth_events": [],
"prev_events": [], "prev_events": [],
}, },
room_version=room_version, room_version=room_version,
@ -609,7 +652,22 @@ def _alias_event(room_version: RoomVersion, sender: str, **kwargs) -> EventBase:
return make_event_from_dict(data, room_version=room_version) return make_event_from_dict(data, room_version=room_version)
def _random_state_event(room_version: RoomVersion, sender: str) -> EventBase: def _build_auth_dict_for_room_version(
room_version: RoomVersion, auth_events: Iterable[EventBase]
) -> List:
if room_version.event_format == EventFormatVersions.V1:
return [(e.event_id, "not_used") for e in auth_events]
else:
return [e.event_id for e in auth_events]
def _random_state_event(
room_version: RoomVersion,
sender: str,
auth_events: Optional[Iterable[EventBase]] = None,
) -> EventBase:
if auth_events is None:
auth_events = []
return make_event_from_dict( return make_event_from_dict(
{ {
"room_id": TEST_ROOM_ID, "room_id": TEST_ROOM_ID,
@ -618,6 +676,7 @@ def _random_state_event(room_version: RoomVersion, sender: str) -> EventBase:
"sender": sender, "sender": sender,
"state_key": "", "state_key": "",
"content": {"membership": "join"}, "content": {"membership": "join"},
"auth_events": _build_auth_dict_for_room_version(room_version, auth_events),
}, },
room_version=room_version, room_version=room_version,
) )