Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Prevent federation user keys query from returning device names if disallowed #14304

Merged
merged 4 commits into from
Oct 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/14304.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix a bug introduced in 1.34.0 where device names would be returned via a federation user key query request when `allow_device_name_lookup_over_federation` was set to `false`.
37 changes: 33 additions & 4 deletions synapse/handlers/e2e_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@

class E2eKeysHandler:
def __init__(self, hs: "HomeServer"):
self.config = hs.config
self.store = hs.get_datastores().main
self.federation = hs.get_federation_client()
self.device_handler = hs.get_device_handler()
Expand Down Expand Up @@ -431,13 +432,17 @@ async def get_cross_signing_keys_from_cache(
@trace
@cancellable
async def query_local_devices(
self, query: Mapping[str, Optional[List[str]]]
self,
query: Mapping[str, Optional[List[str]]],
include_displaynames: bool = True,
) -> Dict[str, Dict[str, dict]]:
"""Get E2E device keys for local users

Args:
query: map from user_id to a list
of devices to query (None for all devices)
include_displaynames: Whether to include device displaynames in the returned
device details.

Returns:
A map from user_id -> device_id -> device details
Expand Down Expand Up @@ -469,7 +474,9 @@ async def query_local_devices(
# make sure that each queried user appears in the result dict
result_dict[user_id] = {}

results = await self.store.get_e2e_device_keys_for_cs_api(local_query)
results = await self.store.get_e2e_device_keys_for_cs_api(
local_query, include_displaynames
)

# Build the result structure
for user_id, device_keys in results.items():
Expand All @@ -482,11 +489,33 @@ async def query_local_devices(
async def on_federation_query_client_keys(
self, query_body: Dict[str, Dict[str, Optional[List[str]]]]
) -> JsonDict:
"""Handle a device key query from a federated server"""
"""Handle a device key query from a federated server:

Handles the path: GET /_matrix/federation/v1/users/keys/query

Args:
query_body: The body of the query request. Should contain a key
"device_keys" that map to a dictionary of user ID's -> list of
device IDs. If the list of device IDs is empty, all devices of
that user will be queried.

Returns:
A json dictionary containing the following:
- device_keys: A dictionary containing the requested device information.
- master_keys: An optional dictionary of user ID -> master cross-signing
key info.
- self_signing_key: An optional dictionary of user ID -> self-signing
key info.
"""
device_keys_query: Dict[str, Optional[List[str]]] = query_body.get(
"device_keys", {}
)
res = await self.query_local_devices(device_keys_query)
res = await self.query_local_devices(
device_keys_query,
include_displaynames=(
self.config.federation.allow_device_name_lookup_over_federation
),
)
ret = {"device_keys": res}

# add in the cross-signing keys
Expand Down
17 changes: 12 additions & 5 deletions synapse/storage/databases/main/end_to_end_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,15 @@ async def get_e2e_device_keys_for_federation_query(
@trace
@cancellable
async def get_e2e_device_keys_for_cs_api(
self, query_list: List[Tuple[str, Optional[str]]]
self,
query_list: List[Tuple[str, Optional[str]]],
include_displaynames: bool = True,
) -> Dict[str, Dict[str, JsonDict]]:
"""Fetch a list of device keys, formatted suitably for the C/S API.
Args:
query_list(list): List of pairs of user_ids and device_ids.
query_list: List of pairs of user_ids and device_ids.
include_displaynames: Whether to include the displayname of returned devices
(if one exists).
Returns:
Dict mapping from user-id to dict mapping from device_id to
key data. The key data will be a dict in the same format as the
Expand All @@ -166,9 +170,12 @@ async def get_e2e_device_keys_for_cs_api(
continue

r["unsigned"] = {}
display_name = device_info.display_name
if display_name is not None:
r["unsigned"]["device_display_name"] = display_name
if include_displaynames:
# Include the device's display name in the "unsigned" dictionary
display_name = device_info.display_name
if display_name is not None:
r["unsigned"]["device_display_name"] = display_name

rv[user_id][device_id] = r

return rv
Expand Down