summary refs log tree commit diff
path: root/synapse/event_auth.py
diff options
context:
space:
mode:
Diffstat (limited to 'synapse/event_auth.py')
-rw-r--r--synapse/event_auth.py45
1 files changed, 33 insertions, 12 deletions
diff --git a/synapse/event_auth.py b/synapse/event_auth.py
index 84fe9d3c3e..1a7295acfb 100644
--- a/synapse/event_auth.py
+++ b/synapse/event_auth.py
@@ -55,7 +55,7 @@ from synapse.types import (
 
 if typing.TYPE_CHECKING:
     # conditional imports to avoid import cycle
-    from synapse.events import EventBase, FrozenLinearizedEvent
+    from synapse.events import EventBase
     from synapse.events.builder import EventBuilder
 
 logger = logging.getLogger(__name__)
@@ -126,20 +126,13 @@ def validate_event_for_room_version(event: "EventBase") -> None:
             raise AuthError(403, "Event not signed by sending server")
 
     if event.format_version == EventFormatVersions.LINEARIZED:
-        assert isinstance(event, FrozenLinearizedEvent)
-
         # TODO Are these handling DAG-native events properly? Is the null-checks
         # a bypass?
 
-        # CHeck that the authorizing domain signed it.
-        owner_server = event.owner_server
-        if owner_server and not event.signatures.get(owner_server):
-            raise AuthError(403, "Event not signed by owner server")
-
-        # If this is a delegated PDU, check the original domain signed it.
-        delegated_server = event.delegated_server
-        if delegated_server and not event.signatures.get(delegated_server):
-            raise AuthError(403, "Event not signed by delegated server")
+        # Check that the hub server signed it.
+        hub_server = event.hub_server
+        if hub_server and not event.signatures.get(hub_server):
+            raise AuthError(403, "Event not signed by hub server")
 
     is_invite_via_allow_rule = (
         event.room_version.msc3083_join_rules
@@ -293,6 +286,13 @@ def check_state_dependent_auth_rules(
 
     auth_dict = {(e.type, e.state_key): e for e in auth_events}
 
+    # If the event was sent from a hub server it must be the current hub server.
+    if event.room_version.linearized_matrix:
+        if event.hub_server:
+            current_hub_server = get_hub_server(auth_dict)
+            if current_hub_server != event.hub_server:
+                raise AuthError(403, "Event sent from incorrect hub server.")
+
     # additional check for m.federate
     creating_domain = get_domain_from_id(event.room_id)
     originating_domain = get_domain_from_id(event.sender)
@@ -347,6 +347,12 @@ def check_state_dependent_auth_rules(
             logger.debug("Allowing! %s", event)
             return
 
+    # Hub events must be signed by the current hub.
+    if event.type == EventTypes.Hub:
+        current_hub_server = get_hub_server(auth_dict)
+        if not event.signatures.get(current_hub_server):
+            raise AuthError(403, "Unsigned hub event")
+
     _can_send_event(event, auth_dict)
 
     if event.type == EventTypes.PowerLevels:
@@ -1081,6 +1087,16 @@ def _verify_third_party_invite(
     return False
 
 
+def get_hub_server(auth_events: StateMap["EventBase"]) -> str:
+    # The current hub is the sender of the current hub event...
+    hub_event = auth_events.get((EventTypes.Hub, ""), None)
+    if not hub_event:
+        # ...or the room creator if there is no hub event.
+        hub_event = auth_events[(EventTypes.Create, "")]
+
+    return get_domain_from_id(hub_event.sender)
+
+
 def get_public_keys(invite_event: "EventBase") -> List[Dict[str, Any]]:
     public_keys = []
     if "public_key" in invite_event.content:
@@ -1134,4 +1150,9 @@ def auth_types_for_event(
                 )
                 auth_types.add(key)
 
+    # Events sent from a hub server must reference the hub state-event, if one
+    # exists.
+    if event.hub_server:
+        auth_types.add((EventTypes.Hub, ""))
+
     return auth_types