Compare commits
6 Commits
4f41f37309
...
de29d1f106
Author | SHA1 | Date |
---|---|---|
![]() |
de29d1f106 | |
![]() |
b08b7c71fc | |
![]() |
74eaac0052 | |
![]() |
7cb1e4846a | |
![]() |
1b4dda5a8d | |
![]() |
6d559bab03 |
|
@ -1 +1 @@
|
||||||
Fix a bug with cross-signing devices with remote users when they did not share a room with any user on the local homeserver.
|
Fix a bug with cross-signing devices belonging to remote users who did not share a room with any user on the local homeserver.
|
||||||
|
|
|
@ -407,12 +407,12 @@ class TransportLayerClient(object):
|
||||||
"<user_id>": {
|
"<user_id>": {
|
||||||
"<device_id>": {...}
|
"<device_id>": {...}
|
||||||
} }
|
} }
|
||||||
"master_keys": {
|
"master_key": {
|
||||||
"<user_id>": {...}
|
"<user_id>": {...}
|
||||||
} }
|
} }
|
||||||
"self_signing_keys": {
|
"self_signing_key": {
|
||||||
"<user_id>": {...}
|
"<user_id>": {...}
|
||||||
} } }
|
} }
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
destination(str): The server to query.
|
destination(str): The server to query.
|
||||||
|
@ -436,9 +436,22 @@ class TransportLayerClient(object):
|
||||||
{
|
{
|
||||||
"stream_id": "...",
|
"stream_id": "...",
|
||||||
"devices": [ { ... } ],
|
"devices": [ { ... } ],
|
||||||
"master_key": { ... },
|
"master_key": {
|
||||||
"self_signing_key: { ... }
|
"user_id": "<user_id>",
|
||||||
|
"usage": [...],
|
||||||
|
"keys": {...},
|
||||||
|
"signatures": {
|
||||||
|
"<user_id>": {...}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"self_signing_key": {
|
||||||
|
"user_id": "<user_id>",
|
||||||
|
"usage": [...],
|
||||||
|
"keys": {...},
|
||||||
|
"signatures": {
|
||||||
|
"<user_id>": {...}
|
||||||
|
}
|
||||||
|
} }
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
destination(str): The server to query.
|
destination(str): The server to query.
|
||||||
|
|
|
@ -989,20 +989,24 @@ class E2eKeysHandler(object):
|
||||||
user_id, key_type, from_user_id
|
user_id, key_type, from_user_id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if key:
|
||||||
|
# We found a copy of this key in our database. Decode and return it
|
||||||
|
key_id, verify_key = get_verify_key_from_cross_signing_key(key)
|
||||||
|
return key, key_id, verify_key
|
||||||
|
|
||||||
# If we couldn't find the key locally, and we're looking for keys of
|
# If we couldn't find the key locally, and we're looking for keys of
|
||||||
# another user then attempt to fetch the missing key from the remote
|
# another user then attempt to fetch the missing key from the remote
|
||||||
# user's server.
|
# user's server.
|
||||||
#
|
#
|
||||||
# We may run into this in possible edge cases where a user tries to
|
# We may run into this in possible edge cases where a user tries to
|
||||||
# cross-sign a remote user, but does not share any rooms with them yet.
|
# cross-sign a remote user, but does not share any rooms with them yet.
|
||||||
# Thus, we would not have their key list yet. We fetch the key here,
|
# Thus, we would not have their key list yet. We instead fetch the key,
|
||||||
# store it and notify clients of new, associated device IDs.
|
# store it and notify clients of new, associated device IDs.
|
||||||
if (
|
if self.is_mine(user) or key_type not in ["master", "self_signing"]:
|
||||||
key is None
|
# Note that master and self_signing keys are the only cross-signing keys we
|
||||||
and not self.is_mine(user)
|
# can request over federation
|
||||||
# We only get "master" and "self_signing" keys from remote servers
|
return
|
||||||
and key_type in ["master", "self_signing"]
|
|
||||||
):
|
|
||||||
(
|
(
|
||||||
key,
|
key,
|
||||||
key_id,
|
key_id,
|
||||||
|
@ -1010,19 +1014,8 @@ class E2eKeysHandler(object):
|
||||||
) = yield self._retrieve_cross_signing_keys_for_remote_user(user, key_type)
|
) = yield self._retrieve_cross_signing_keys_for_remote_user(user, key_type)
|
||||||
|
|
||||||
if key is None:
|
if key is None:
|
||||||
logger.warning("No %s key found for %s", key_type, user_id)
|
|
||||||
raise NotFoundError("No %s key found for %s" % (key_type, user_id))
|
raise NotFoundError("No %s key found for %s" % (key_type, user_id))
|
||||||
|
|
||||||
try:
|
|
||||||
key_id, verify_key = get_verify_key_from_cross_signing_key(key)
|
|
||||||
except ValueError as e:
|
|
||||||
logger.warning(
|
|
||||||
"Invalid %s key retrieved: %s - %s %s", key_type, key, type(e), e,
|
|
||||||
)
|
|
||||||
raise SynapseError(
|
|
||||||
502, "Invalid %s key retrieved from remote server" % (key_type,)
|
|
||||||
)
|
|
||||||
|
|
||||||
return key, key_id, verify_key
|
return key, key_id, verify_key
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@ -1058,22 +1051,33 @@ class E2eKeysHandler(object):
|
||||||
return None, None, None
|
return None, None, None
|
||||||
|
|
||||||
# Process each of the retrieved cross-signing keys
|
# Process each of the retrieved cross-signing keys
|
||||||
final_key = None
|
desired_key = None
|
||||||
final_key_id = None
|
desired_key_id = None
|
||||||
final_verify_key = None
|
desired_verify_key = None
|
||||||
device_ids = []
|
retrieved_device_ids = []
|
||||||
for key_type in ["master", "self_signing"]:
|
for key_type in ["master", "self_signing"]:
|
||||||
key_content = remote_result.get(key_type + "_key")
|
key_content = remote_result.get(key_type + "_key")
|
||||||
if not key_content:
|
if not key_content:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# At the same time, store this key in the db for
|
# Ensure these keys belong to the correct user
|
||||||
# subsequent queries
|
if "user_id" not in key_content:
|
||||||
yield self.store.set_e2e_cross_signing_key(
|
logger.warning(
|
||||||
user.to_string(), key_type, key_content
|
"Invalid %s key retrieved, missing user_id field: %s",
|
||||||
|
key_type,
|
||||||
|
key_content,
|
||||||
)
|
)
|
||||||
|
continue
|
||||||
|
if user.to_string() != key_content["user_id"]:
|
||||||
|
logger.warning(
|
||||||
|
"Found %s key of user %s when querying for keys of user %s",
|
||||||
|
key_type,
|
||||||
|
key_content["user_id"],
|
||||||
|
user.to_string(),
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
# Note down the device ID attached to this key
|
# Validate the key contents
|
||||||
try:
|
try:
|
||||||
# verify_key is a VerifyKey from signedjson, which uses
|
# verify_key is a VerifyKey from signedjson, which uses
|
||||||
# .version to denote the portion of the key ID after the
|
# .version to denote the portion of the key ID after the
|
||||||
|
@ -1088,19 +1092,28 @@ class E2eKeysHandler(object):
|
||||||
e,
|
e,
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
device_ids.append(verify_key.version)
|
|
||||||
|
# Note down the device ID attached to this key
|
||||||
|
retrieved_device_ids.append(verify_key.version)
|
||||||
|
|
||||||
# If this is the desired key type, save it and its ID/VerifyKey
|
# If this is the desired key type, save it and its ID/VerifyKey
|
||||||
if key_type == desired_key_type:
|
if key_type == desired_key_type:
|
||||||
final_key = key_content
|
desired_key = key_content
|
||||||
final_verify_key = verify_key
|
desired_verify_key = verify_key
|
||||||
final_key_id = key_id
|
desired_key_id = key_id
|
||||||
|
|
||||||
|
# At the same time, store this key in the db for subsequent queries
|
||||||
|
yield self.store.set_e2e_cross_signing_key(
|
||||||
|
user.to_string(), key_type, key_content
|
||||||
|
)
|
||||||
|
|
||||||
# Notify clients that new devices for this user have been discovered
|
# Notify clients that new devices for this user have been discovered
|
||||||
if device_ids:
|
if retrieved_device_ids:
|
||||||
yield self.device_handler.notify_device_update(user.to_string(), device_ids)
|
yield self.device_handler.notify_device_update(
|
||||||
|
user.to_string(), retrieved_device_ids
|
||||||
|
)
|
||||||
|
|
||||||
return final_key, final_key_id, final_verify_key
|
return desired_key, desired_key_id, desired_verify_key
|
||||||
|
|
||||||
|
|
||||||
def _check_cross_signing_key(key, user_id, key_type, signing_key=None):
|
def _check_cross_signing_key(key, user_id, key_type, signing_key=None):
|
||||||
|
|
Loading…
Reference in New Issue