mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-08-06 06:04:11 -04:00
Stop hardcoding trust of old matrix.org key (#5374)
There are a few changes going on here: * We make checking the signature on a key server response optional: if no verify_keys are specified, we trust to TLS to validate the connection. * We change the default config so that it does not require responses to be signed by the old key. * We replace the old 'perspectives' config with 'trusted_key_servers', which is also formatted slightly differently. * We emit a warning to the logs every time we trust a key server response signed by the old key.
This commit is contained in:
parent
833c406b9b
commit
9fbb20a531
6 changed files with 294 additions and 96 deletions
|
@ -585,25 +585,27 @@ class PerspectivesKeyFetcher(BaseV2KeyFetcher):
|
|||
super(PerspectivesKeyFetcher, self).__init__(hs)
|
||||
self.clock = hs.get_clock()
|
||||
self.client = hs.get_http_client()
|
||||
self.perspective_servers = self.config.perspectives
|
||||
self.key_servers = self.config.key_servers
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def get_keys(self, keys_to_fetch):
|
||||
"""see KeyFetcher.get_keys"""
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def get_key(perspective_name, perspective_keys):
|
||||
def get_key(key_server):
|
||||
try:
|
||||
result = yield self.get_server_verify_key_v2_indirect(
|
||||
keys_to_fetch, perspective_name, perspective_keys
|
||||
keys_to_fetch, key_server
|
||||
)
|
||||
defer.returnValue(result)
|
||||
except KeyLookupError as e:
|
||||
logger.warning("Key lookup failed from %r: %s", perspective_name, e)
|
||||
logger.warning(
|
||||
"Key lookup failed from %r: %s", key_server.server_name, e
|
||||
)
|
||||
except Exception as e:
|
||||
logger.exception(
|
||||
"Unable to get key from %r: %s %s",
|
||||
perspective_name,
|
||||
key_server.server_name,
|
||||
type(e).__name__,
|
||||
str(e),
|
||||
)
|
||||
|
@ -613,8 +615,8 @@ class PerspectivesKeyFetcher(BaseV2KeyFetcher):
|
|||
results = yield logcontext.make_deferred_yieldable(
|
||||
defer.gatherResults(
|
||||
[
|
||||
run_in_background(get_key, p_name, p_keys)
|
||||
for p_name, p_keys in self.perspective_servers.items()
|
||||
run_in_background(get_key, server)
|
||||
for server in self.key_servers
|
||||
],
|
||||
consumeErrors=True,
|
||||
).addErrback(unwrapFirstError)
|
||||
|
@ -629,17 +631,15 @@ class PerspectivesKeyFetcher(BaseV2KeyFetcher):
|
|||
|
||||
@defer.inlineCallbacks
|
||||
def get_server_verify_key_v2_indirect(
|
||||
self, keys_to_fetch, perspective_name, perspective_keys
|
||||
self, keys_to_fetch, key_server
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
keys_to_fetch (dict[str, dict[str, int]]):
|
||||
the keys to be fetched. server_name -> key_id -> min_valid_ts
|
||||
|
||||
perspective_name (str): name of the notary server to query for the keys
|
||||
|
||||
perspective_keys (dict[str, VerifyKey]): map of key_id->key for the
|
||||
notary server
|
||||
key_server (synapse.config.key.TrustedKeyServer): notary server to query for
|
||||
the keys
|
||||
|
||||
Returns:
|
||||
Deferred[dict[str, dict[str, synapse.storage.keys.FetchKeyResult]]]: map
|
||||
|
@ -649,6 +649,7 @@ class PerspectivesKeyFetcher(BaseV2KeyFetcher):
|
|||
KeyLookupError if there was an error processing the entire response from
|
||||
the server
|
||||
"""
|
||||
perspective_name = key_server.server_name
|
||||
logger.info(
|
||||
"Requesting keys %s from notary server %s",
|
||||
keys_to_fetch.items(),
|
||||
|
@ -689,11 +690,13 @@ class PerspectivesKeyFetcher(BaseV2KeyFetcher):
|
|||
)
|
||||
|
||||
try:
|
||||
processed_response = yield self._process_perspectives_response(
|
||||
perspective_name,
|
||||
perspective_keys,
|
||||
self._validate_perspectives_response(
|
||||
key_server,
|
||||
response,
|
||||
time_added_ms=time_now_ms,
|
||||
)
|
||||
|
||||
processed_response = yield self.process_v2_response(
|
||||
perspective_name, response, time_added_ms=time_now_ms
|
||||
)
|
||||
except KeyLookupError as e:
|
||||
logger.warning(
|
||||
|
@ -717,28 +720,24 @@ class PerspectivesKeyFetcher(BaseV2KeyFetcher):
|
|||
|
||||
defer.returnValue(keys)
|
||||
|
||||
def _process_perspectives_response(
|
||||
self, perspective_name, perspective_keys, response, time_added_ms
|
||||
def _validate_perspectives_response(
|
||||
self, key_server, response,
|
||||
):
|
||||
"""Parse a 'Server Keys' structure from the result of a /key/query request
|
||||
|
||||
Checks that the entry is correctly signed by the perspectives server, and then
|
||||
passes over to process_v2_response
|
||||
"""Optionally check the signature on the result of a /key/query request
|
||||
|
||||
Args:
|
||||
perspective_name (str): the name of the notary server that produced this
|
||||
result
|
||||
|
||||
perspective_keys (dict[str, VerifyKey]): map of key_id->key for the
|
||||
notary server
|
||||
key_server (synapse.config.key.TrustedKeyServer): the notary server that
|
||||
produced this result
|
||||
|
||||
response (dict): the json-decoded Server Keys response object
|
||||
|
||||
time_added_ms (int): the timestamp to record in server_keys_json
|
||||
|
||||
Returns:
|
||||
Deferred[dict[str, FetchKeyResult]]: map from key_id to result object
|
||||
"""
|
||||
perspective_name = key_server.server_name
|
||||
perspective_keys = key_server.verify_keys
|
||||
|
||||
if perspective_keys is None:
|
||||
# signature checking is disabled on this server
|
||||
return
|
||||
|
||||
if (
|
||||
u"signatures" not in response
|
||||
or perspective_name not in response[u"signatures"]
|
||||
|
@ -751,6 +750,13 @@ class PerspectivesKeyFetcher(BaseV2KeyFetcher):
|
|||
verify_signed_json(response, perspective_name, perspective_keys[key_id])
|
||||
verified = True
|
||||
|
||||
if perspective_name == "matrix.org" and key_id == "ed25519:auto":
|
||||
logger.warning(
|
||||
"Trusting trusted_key_server responses signed by the "
|
||||
"compromised matrix.org signing key 'ed25519:auto'. "
|
||||
"This is a placebo."
|
||||
)
|
||||
|
||||
if not verified:
|
||||
raise KeyLookupError(
|
||||
"Response not signed with a known key: signed with: %r, known keys: %r"
|
||||
|
@ -760,10 +766,6 @@ class PerspectivesKeyFetcher(BaseV2KeyFetcher):
|
|||
)
|
||||
)
|
||||
|
||||
return self.process_v2_response(
|
||||
perspective_name, response, time_added_ms=time_added_ms
|
||||
)
|
||||
|
||||
|
||||
class ServerKeyFetcher(BaseV2KeyFetcher):
|
||||
"""KeyFetcher impl which fetches keys from the origin servers"""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue