Compare commits

...

3 Commits

Author SHA1 Message Date
Erik Johnston
e314499074 Merge branch 'develop' into anoa-codex/limit-key-upload-to-one-per-device 2025-06-25 10:10:31 +01:00
Andrew Morgan
5be825cb09 newsfile 2025-06-04 13:15:00 +01:00
anoa's Codex Agent
cdf88b5706 Disallow device key changes 2025-06-04 13:09:27 +01:00
4 changed files with 69 additions and 3 deletions

1
changelog.d/18512.misc Normal file
View File

@@ -0,0 +1 @@
Prevent users from changing their device keys once they've already been set.

View File

@@ -42,6 +42,7 @@ import attr
from canonicaljson import encode_canonical_json
from synapse.api.constants import DeviceKeyAlgorithms
from synapse.api.errors import Codes, StoreError
from synapse.appservice import (
TransactionOneTimeKeysCount,
TransactionUnusedFallbackKeys,
@@ -1619,9 +1620,16 @@ class EndToEndKeyStore(EndToEndKeyWorkerStore, SQLBaseStore):
# returns unicode while encode_canonical_json returns bytes.
new_key_json = encode_canonical_json(device_keys).decode("utf-8")
if old_key_json == new_key_json:
log_kv({"Message": "Device key already stored."})
return False
if old_key_json is not None:
if old_key_json == new_key_json:
log_kv({"Message": "Device key already stored."})
return False
raise StoreError(
400,
"Device keys for this device have already been uploaded",
Codes.INVALID_PARAM,
)
self.db_pool.simple_upsert_txn(
txn,

View File

@@ -149,6 +149,48 @@ class E2eKeysHandlerTestCase(unittest.HomeserverTestCase):
SynapseError,
)
def test_change_device_keys(self) -> None:
"""uploading different device keys should fail"""
local_user = "@boris:" + self.hs.hostname
device_id = "xyz"
keys1 = {
"user_id": local_user,
"device_id": device_id,
"algorithms": ["m.olm.curve25519-aes-sha2"],
"keys": {"ed25519:" + device_id: "key1"},
}
keys2 = {
"user_id": local_user,
"device_id": device_id,
"algorithms": ["m.olm.curve25519-aes-sha2"],
"keys": {"ed25519:" + device_id: "key2"},
}
# initial upload succeeds
self.get_success(
self.handler.upload_keys_for_user(
local_user, device_id, {"device_keys": keys1}
)
)
# uploading the same keys again should be fine
self.get_success(
self.handler.upload_keys_for_user(
local_user, device_id, {"device_keys": keys1}
)
)
# uploading different keys should fail
self.get_failure(
self.handler.upload_keys_for_user(
local_user, device_id, {"device_keys": keys2}
),
SynapseError,
)
def test_claim_one_time_key(self) -> None:
local_user = "@boris:" + self.hs.hostname
device_id = "xyz"

View File

@@ -21,6 +21,7 @@
from twisted.test.proto_helpers import MemoryReactor
from synapse.api.errors import StoreError
from synapse.server import HomeServer
from synapse.util import Clock
@@ -65,6 +66,20 @@ class EndToEndKeyStoreTestCase(HomeserverTestCase):
)
self.assertFalse(changed)
def test_change_key_rejected(self) -> None:
now = 1470174257070
json = {"key": "value"}
json2 = {"key": "other"}
self.get_success(self.store.store_device("user", "device", None))
self.get_success(self.store.set_e2e_device_keys("user", "device", now, json))
self.get_failure(
self.store.set_e2e_device_keys("user", "device", now, json2),
StoreError,
)
def test_get_key_with_device_name(self) -> None:
now = 1470174257070
json = {"key": "value"}