forked from MirrorHub/synapse
parent
2b2985b5cf
commit
7967b36efe
4 changed files with 32 additions and 26 deletions
1
changelog.d/9961.bugfix
Normal file
1
changelog.d/9961.bugfix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fix a bug introduced in Synapse 1.29.0 which caused `m.room_key_request` to-device messages sent from one user to another to be dropped.
|
|
@ -116,9 +116,12 @@ class EventTypes:
|
||||||
MSC1772_SPACE_PARENT = "org.matrix.msc1772.space.parent"
|
MSC1772_SPACE_PARENT = "org.matrix.msc1772.space.parent"
|
||||||
|
|
||||||
|
|
||||||
|
class ToDeviceEventTypes:
|
||||||
|
RoomKeyRequest = "m.room_key_request"
|
||||||
|
|
||||||
|
|
||||||
class EduTypes:
|
class EduTypes:
|
||||||
Presence = "m.presence"
|
Presence = "m.presence"
|
||||||
RoomKeyRequest = "m.room_key_request"
|
|
||||||
|
|
||||||
|
|
||||||
class RejectedReason:
|
class RejectedReason:
|
||||||
|
|
|
@ -44,7 +44,6 @@ from synapse.api.errors import (
|
||||||
SynapseError,
|
SynapseError,
|
||||||
UnsupportedRoomVersionError,
|
UnsupportedRoomVersionError,
|
||||||
)
|
)
|
||||||
from synapse.api.ratelimiting import Ratelimiter
|
|
||||||
from synapse.api.room_versions import KNOWN_ROOM_VERSIONS
|
from synapse.api.room_versions import KNOWN_ROOM_VERSIONS
|
||||||
from synapse.events import EventBase
|
from synapse.events import EventBase
|
||||||
from synapse.federation.federation_base import FederationBase, event_from_pdu_json
|
from synapse.federation.federation_base import FederationBase, event_from_pdu_json
|
||||||
|
@ -865,14 +864,6 @@ class FederationHandlerRegistry:
|
||||||
# EDU received.
|
# EDU received.
|
||||||
self._edu_type_to_instance = {} # type: Dict[str, List[str]]
|
self._edu_type_to_instance = {} # type: Dict[str, List[str]]
|
||||||
|
|
||||||
# A rate limiter for incoming room key requests per origin.
|
|
||||||
self._room_key_request_rate_limiter = Ratelimiter(
|
|
||||||
store=hs.get_datastore(),
|
|
||||||
clock=self.clock,
|
|
||||||
rate_hz=self.config.rc_key_requests.per_second,
|
|
||||||
burst_count=self.config.rc_key_requests.burst_count,
|
|
||||||
)
|
|
||||||
|
|
||||||
def register_edu_handler(
|
def register_edu_handler(
|
||||||
self, edu_type: str, handler: Callable[[str, JsonDict], Awaitable[None]]
|
self, edu_type: str, handler: Callable[[str, JsonDict], Awaitable[None]]
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -926,16 +917,6 @@ class FederationHandlerRegistry:
|
||||||
if not self.config.use_presence and edu_type == EduTypes.Presence:
|
if not self.config.use_presence and edu_type == EduTypes.Presence:
|
||||||
return
|
return
|
||||||
|
|
||||||
# If the incoming room key requests from a particular origin are over
|
|
||||||
# the limit, drop them.
|
|
||||||
if (
|
|
||||||
edu_type == EduTypes.RoomKeyRequest
|
|
||||||
and not await self._room_key_request_rate_limiter.can_do_action(
|
|
||||||
None, origin
|
|
||||||
)
|
|
||||||
):
|
|
||||||
return
|
|
||||||
|
|
||||||
# Check if we have a handler on this instance
|
# Check if we have a handler on this instance
|
||||||
handler = self.edu_handlers.get(edu_type)
|
handler = self.edu_handlers.get(edu_type)
|
||||||
if handler:
|
if handler:
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING, Any, Dict
|
from typing import TYPE_CHECKING, Any, Dict
|
||||||
|
|
||||||
from synapse.api.constants import EduTypes
|
from synapse.api.constants import ToDeviceEventTypes
|
||||||
from synapse.api.errors import SynapseError
|
from synapse.api.errors import SynapseError
|
||||||
from synapse.api.ratelimiting import Ratelimiter
|
from synapse.api.ratelimiting import Ratelimiter
|
||||||
from synapse.logging.context import run_in_background
|
from synapse.logging.context import run_in_background
|
||||||
|
@ -79,6 +79,8 @@ class DeviceMessageHandler:
|
||||||
ReplicationUserDevicesResyncRestServlet.make_client(hs)
|
ReplicationUserDevicesResyncRestServlet.make_client(hs)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# a rate limiter for room key requests. The keys are
|
||||||
|
# (sending_user_id, sending_device_id).
|
||||||
self._ratelimiter = Ratelimiter(
|
self._ratelimiter = Ratelimiter(
|
||||||
store=self.store,
|
store=self.store,
|
||||||
clock=hs.get_clock(),
|
clock=hs.get_clock(),
|
||||||
|
@ -100,12 +102,25 @@ class DeviceMessageHandler:
|
||||||
for user_id, by_device in content["messages"].items():
|
for user_id, by_device in content["messages"].items():
|
||||||
# we use UserID.from_string to catch invalid user ids
|
# we use UserID.from_string to catch invalid user ids
|
||||||
if not self.is_mine(UserID.from_string(user_id)):
|
if not self.is_mine(UserID.from_string(user_id)):
|
||||||
logger.warning("Request for keys for non-local user %s", user_id)
|
logger.warning("To-device message to non-local user %s", user_id)
|
||||||
raise SynapseError(400, "Not a user here")
|
raise SynapseError(400, "Not a user here")
|
||||||
|
|
||||||
if not by_device:
|
if not by_device:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Ratelimit key requests by the sending user.
|
||||||
|
if message_type == ToDeviceEventTypes.RoomKeyRequest:
|
||||||
|
allowed, _ = await self._ratelimiter.can_do_action(
|
||||||
|
None, (sender_user_id, None)
|
||||||
|
)
|
||||||
|
if not allowed:
|
||||||
|
logger.info(
|
||||||
|
"Dropping room_key_request from %s to %s due to rate limit",
|
||||||
|
sender_user_id,
|
||||||
|
user_id,
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
messages_by_device = {
|
messages_by_device = {
|
||||||
device_id: {
|
device_id: {
|
||||||
"content": message_content,
|
"content": message_content,
|
||||||
|
@ -192,13 +207,19 @@ class DeviceMessageHandler:
|
||||||
for user_id, by_device in messages.items():
|
for user_id, by_device in messages.items():
|
||||||
# Ratelimit local cross-user key requests by the sending device.
|
# Ratelimit local cross-user key requests by the sending device.
|
||||||
if (
|
if (
|
||||||
message_type == EduTypes.RoomKeyRequest
|
message_type == ToDeviceEventTypes.RoomKeyRequest
|
||||||
and user_id != sender_user_id
|
and user_id != sender_user_id
|
||||||
and await self._ratelimiter.can_do_action(
|
):
|
||||||
|
allowed, _ = await self._ratelimiter.can_do_action(
|
||||||
requester, (sender_user_id, requester.device_id)
|
requester, (sender_user_id, requester.device_id)
|
||||||
)
|
)
|
||||||
):
|
if not allowed:
|
||||||
continue
|
logger.info(
|
||||||
|
"Dropping room_key_request from %s to %s due to rate limit",
|
||||||
|
sender_user_id,
|
||||||
|
user_id,
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
# we use UserID.from_string to catch invalid user ids
|
# we use UserID.from_string to catch invalid user ids
|
||||||
if self.is_mine(UserID.from_string(user_id)):
|
if self.is_mine(UserID.from_string(user_id)):
|
||||||
|
|
Loading…
Reference in a new issue