mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-09-04 18:21:54 +03:00
fix(matrix): bind and bound SAS requests
This commit is contained in:
@@ -80,6 +80,7 @@ _MSGTYPE_MAP = {"m.image": "image", "m.audio": "audio", "m.video": "video", "m.f
|
|||||||
_SAS_METHOD = "m.sas.v1"
|
_SAS_METHOD = "m.sas.v1"
|
||||||
_SAS_REQUEST_MAX_AGE_MS = 10 * 60 * 1000
|
_SAS_REQUEST_MAX_AGE_MS = 10 * 60 * 1000
|
||||||
_SAS_REQUEST_MAX_FUTURE_MS = 5 * 60 * 1000
|
_SAS_REQUEST_MAX_FUTURE_MS = 5 * 60 * 1000
|
||||||
|
_SAS_REQUEST_MAX_PENDING = 256
|
||||||
|
|
||||||
MATRIX_MEDIA_EVENT_FILTER = (RoomMessageMedia, RoomEncryptedMedia)
|
MATRIX_MEDIA_EVENT_FILTER = (RoomMessageMedia, RoomEncryptedMedia)
|
||||||
MatrixMediaEvent: TypeAlias = RoomMessageMedia | RoomEncryptedMedia
|
MatrixMediaEvent: TypeAlias = RoomMessageMedia | RoomEncryptedMedia
|
||||||
@@ -759,6 +760,16 @@ class MatrixChannel(BaseChannel):
|
|||||||
if request.timestamp_ms >= oldest_allowed
|
if request.timestamp_ms >= oldest_allowed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _remember_sas_verification_request(
|
||||||
|
self,
|
||||||
|
transaction_id: str,
|
||||||
|
request: _SasVerificationRequest,
|
||||||
|
) -> None:
|
||||||
|
self._sas_verification_requests[transaction_id] = request
|
||||||
|
while len(self._sas_verification_requests) > _SAS_REQUEST_MAX_PENDING:
|
||||||
|
oldest_transaction_id = next(iter(self._sas_verification_requests))
|
||||||
|
self._sas_verification_requests.pop(oldest_transaction_id)
|
||||||
|
|
||||||
async def _send_sas_control_message(
|
async def _send_sas_control_message(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
@@ -849,7 +860,7 @@ class MatrixChannel(BaseChannel):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
if sent:
|
if sent:
|
||||||
self._sas_verification_requests[transaction_id] = request
|
self._remember_sas_verification_request(transaction_id, request)
|
||||||
return
|
return
|
||||||
|
|
||||||
if event_type == "m.key.verification.done":
|
if event_type == "m.key.verification.done":
|
||||||
@@ -882,6 +893,16 @@ class MatrixChannel(BaseChannel):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(event, KeyVerificationStart):
|
if isinstance(event, KeyVerificationStart):
|
||||||
|
request = self._sas_verification_requests.get(transaction_id)
|
||||||
|
from_device = str(getattr(event, "from_device", "") or "")
|
||||||
|
if request is not None and (
|
||||||
|
request.sender != sender or request.device_id != from_device
|
||||||
|
):
|
||||||
|
self.logger.warning(
|
||||||
|
"Ignoring Matrix SAS start for transaction {} from unexpected device",
|
||||||
|
transaction_id,
|
||||||
|
)
|
||||||
|
return
|
||||||
if "emoji" not in (getattr(event, "short_authentication_string", None) or []):
|
if "emoji" not in (getattr(event, "short_authentication_string", None) or []):
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
"Ignoring Matrix SAS verification from {} without emoji support",
|
"Ignoring Matrix SAS verification from {} without emoji support",
|
||||||
|
|||||||
@@ -241,10 +241,12 @@ class _FakeKeyVerificationStart:
|
|||||||
*,
|
*,
|
||||||
sender: str = "@alice:matrix.org",
|
sender: str = "@alice:matrix.org",
|
||||||
transaction_id: str = "tx1",
|
transaction_id: str = "tx1",
|
||||||
|
from_device: str = "ALICEDEVICE",
|
||||||
short_authentication_string: list[str] | None = None,
|
short_authentication_string: list[str] | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.sender = sender
|
self.sender = sender
|
||||||
self.transaction_id = transaction_id
|
self.transaction_id = transaction_id
|
||||||
|
self.from_device = from_device
|
||||||
self.short_authentication_string = short_authentication_string or ["emoji"]
|
self.short_authentication_string = short_authentication_string or ["emoji"]
|
||||||
|
|
||||||
|
|
||||||
@@ -477,6 +479,65 @@ async def test_sas_verification_request_sends_ready_to_allowed_device(monkeypatc
|
|||||||
assert channel._sas_verification_requests["tx1"].device_id == "ALICEDEVICE"
|
assert channel._sas_verification_requests["tx1"].device_id == "ALICEDEVICE"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_sas_verification_requests_are_bounded(monkeypatch) -> None:
|
||||||
|
monkeypatch.setattr(matrix_module.time, "time", lambda: 1_000.0)
|
||||||
|
channel = MatrixChannel(
|
||||||
|
_make_config(
|
||||||
|
allow_from=["@alice:matrix.org"],
|
||||||
|
e2ee_enabled=True,
|
||||||
|
sas_verification=True,
|
||||||
|
),
|
||||||
|
MessageBus(),
|
||||||
|
)
|
||||||
|
client = _FakeAsyncClient("", "", "", None)
|
||||||
|
client.device_id = "BOTDEVICE"
|
||||||
|
channel.client = client
|
||||||
|
|
||||||
|
for index in range(matrix_module._SAS_REQUEST_MAX_PENDING + 1):
|
||||||
|
await channel._handle_key_verification_event(_unknown_verification_event(
|
||||||
|
"m.key.verification.request",
|
||||||
|
transaction_id=f"tx-{index}",
|
||||||
|
from_device="ALICEDEVICE",
|
||||||
|
methods=["m.sas.v1"],
|
||||||
|
timestamp=1_000_000,
|
||||||
|
))
|
||||||
|
|
||||||
|
assert len(channel._sas_verification_requests) == matrix_module._SAS_REQUEST_MAX_PENDING
|
||||||
|
assert "tx-0" not in channel._sas_verification_requests
|
||||||
|
assert f"tx-{matrix_module._SAS_REQUEST_MAX_PENDING}" in channel._sas_verification_requests
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_sas_verification_start_must_match_requested_device(monkeypatch) -> None:
|
||||||
|
_patch_key_verification_events(monkeypatch)
|
||||||
|
monkeypatch.setattr(matrix_module.time, "time", lambda: 1_000.0)
|
||||||
|
channel = MatrixChannel(
|
||||||
|
_make_config(
|
||||||
|
allow_from=["@alice:matrix.org"],
|
||||||
|
e2ee_enabled=True,
|
||||||
|
sas_verification=True,
|
||||||
|
),
|
||||||
|
MessageBus(),
|
||||||
|
)
|
||||||
|
client = _FakeAsyncClient("", "", "", None)
|
||||||
|
client.device_id = "BOTDEVICE"
|
||||||
|
channel.client = client
|
||||||
|
|
||||||
|
await channel._handle_key_verification_event(_unknown_verification_event(
|
||||||
|
"m.key.verification.request",
|
||||||
|
from_device="ALICEDEVICE",
|
||||||
|
methods=["m.sas.v1"],
|
||||||
|
timestamp=1_000_000,
|
||||||
|
))
|
||||||
|
await channel._handle_key_verification_event(
|
||||||
|
_FakeKeyVerificationStart(from_device="OTHERDEVICE")
|
||||||
|
)
|
||||||
|
|
||||||
|
assert client.accept_key_verification_calls == []
|
||||||
|
assert channel._sas_verification_requests["tx1"].device_id == "ALICEDEVICE"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("sender", "methods", "timestamp"),
|
("sender", "methods", "timestamp"),
|
||||||
|
|||||||
Reference in New Issue
Block a user