def verify_json_for_server(self, server_name, json_object): logger.debug("Verifying for %s", server_name) key_ids = signature_ids(json_object, server_name) if not key_ids: raise SynapseError( 400, "Not signed with a supported algorithm", Codes.UNAUTHORIZED, ) try: verify_key = yield self.get_server_verify_key(server_name, key_ids) except IOError: raise SynapseError( 502, "Error downloading keys for %s" % (server_name, ), Codes.UNAUTHORIZED, ) except: raise SynapseError( 401, "No key for %s with id %s" % (server_name, key_ids), Codes.UNAUTHORIZED, ) try: verify_signed_json(json_object, server_name, verify_key) except: raise SynapseError( 401, "Invalid signature for server %s with key %s:%s" % (server_name, verify_key.alg, verify_key.version), Codes.UNAUTHORIZED, )
def verify_json_for_server(self, server_name, json_object): logger.debug("Verifying for %s", server_name) key_ids = signature_ids(json_object, server_name) if not key_ids: raise SynapseError( 400, "Not signed with a supported algorithm", Codes.UNAUTHORIZED, ) try: verify_key = yield self.get_server_verify_key(server_name, key_ids) except IOError: raise SynapseError( 502, "Error downloading keys for %s" % (server_name,), Codes.UNAUTHORIZED, ) except: raise SynapseError( 401, "No key for %s with id %s" % (server_name, key_ids), Codes.UNAUTHORIZED, ) try: verify_signed_json(json_object, server_name, verify_key) except: raise SynapseError( 401, "Invalid signature for server %s with key %s:%s" % ( server_name, verify_key.alg, verify_key.version ), Codes.UNAUTHORIZED, )
def verify_json_objects_for_server(self, server_and_json): """Bulk verfies signatures of json objects, bulk fetching keys as necessary. Args: server_and_json (list): List of pairs of (server_name, json_object) Returns: list of deferreds indicating success or failure to verify each json object's signature for the given server_name. """ group_id_to_json = {} group_id_to_group = {} group_ids = [] next_group_id = 0 deferreds = {} for server_name, json_object in server_and_json: logger.debug("Verifying for %s", server_name) group_id = next_group_id next_group_id += 1 group_ids.append(group_id) key_ids = signature_ids(json_object, server_name) if not key_ids: deferreds[group_id] = defer.fail(SynapseError( 400, "Not signed with a supported algorithm", Codes.UNAUTHORIZED, )) else: deferreds[group_id] = defer.Deferred() group = KeyGroup(server_name, group_id, key_ids) group_id_to_group[group_id] = group group_id_to_json[group_id] = json_object @defer.inlineCallbacks def handle_key_deferred(group, deferred): server_name = group.server_name try: _, _, key_id, verify_key = yield deferred except IOError as e: logger.warn( "Got IOError when downloading keys for %s: %s %s", server_name, type(e).__name__, str(e.message), ) raise SynapseError( 502, "Error downloading keys for %s" % (server_name,), Codes.UNAUTHORIZED, ) except Exception as e: logger.exception( "Got Exception when downloading keys for %s: %s %s", server_name, type(e).__name__, str(e.message), ) raise SynapseError( 401, "No key for %s with id %s" % (server_name, key_ids), Codes.UNAUTHORIZED, ) json_object = group_id_to_json[group.group_id] try: verify_signed_json(json_object, server_name, verify_key) except: raise SynapseError( 401, "Invalid signature for server %s with key %s:%s" % ( server_name, verify_key.alg, verify_key.version ), Codes.UNAUTHORIZED, ) server_to_deferred = { server_name: defer.Deferred() for server_name, _ in server_and_json } # We want to wait for any previous lookups to complete before # proceeding. wait_on_deferred = self.wait_for_previous_lookups( [server_name for server_name, _ in server_and_json], server_to_deferred, ) # Actually start fetching keys. wait_on_deferred.addBoth( lambda _: self.get_server_verify_keys(group_id_to_group, deferreds) ) # When we've finished fetching all the keys for a given server_name, # resolve the deferred passed to `wait_for_previous_lookups` so that # any lookups waiting will proceed. server_to_gids = {} def remove_deferreds(res, server_name, group_id): server_to_gids[server_name].discard(group_id) if not server_to_gids[server_name]: server_to_deferred.pop(server_name).callback(None) return res for g_id, deferred in deferreds.items(): server_name = group_id_to_group[g_id].server_name server_to_gids.setdefault(server_name, set()).add(g_id) deferred.addBoth(remove_deferreds, server_name, g_id) # Pass those keys to handle_key_deferred so that the json object # signatures can be verified return [ handle_key_deferred( group_id_to_group[g_id], deferreds[g_id], ) for g_id in group_ids ]
def verify_json_objects_for_server(self, server_and_json): """Bulk verfies signatures of json objects, bulk fetching keys as necessary. Args: server_and_json (list): List of pairs of (server_name, json_object) Returns: list of deferreds indicating success or failure to verify each json object's signature for the given server_name. """ group_id_to_json = {} group_id_to_group = {} group_ids = [] next_group_id = 0 deferreds = {} for server_name, json_object in server_and_json: logger.debug("Verifying for %s", server_name) group_id = next_group_id next_group_id += 1 group_ids.append(group_id) key_ids = signature_ids(json_object, server_name) if not key_ids: deferreds[group_id] = defer.fail( SynapseError( 400, "Not signed with a supported algorithm", Codes.UNAUTHORIZED, )) else: deferreds[group_id] = defer.Deferred() group = KeyGroup(server_name, group_id, key_ids) group_id_to_group[group_id] = group group_id_to_json[group_id] = json_object @defer.inlineCallbacks def handle_key_deferred(group, deferred): server_name = group.server_name try: _, _, key_id, verify_key = yield deferred except IOError as e: logger.warn( "Got IOError when downloading keys for %s: %s %s", server_name, type(e).__name__, str(e.message), ) raise SynapseError( 502, "Error downloading keys for %s" % (server_name, ), Codes.UNAUTHORIZED, ) except Exception as e: logger.exception( "Got Exception when downloading keys for %s: %s %s", server_name, type(e).__name__, str(e.message), ) raise SynapseError( 401, "No key for %s with id %s" % (server_name, key_ids), Codes.UNAUTHORIZED, ) json_object = group_id_to_json[group.group_id] try: verify_signed_json(json_object, server_name, verify_key) except: raise SynapseError( 401, "Invalid signature for server %s with key %s:%s" % (server_name, verify_key.alg, verify_key.version), Codes.UNAUTHORIZED, ) server_to_deferred = { server_name: defer.Deferred() for server_name, _ in server_and_json } # We want to wait for any previous lookups to complete before # proceeding. wait_on_deferred = self.wait_for_previous_lookups( [server_name for server_name, _ in server_and_json], server_to_deferred, ) # Actually start fetching keys. wait_on_deferred.addBoth(lambda _: self.get_server_verify_keys( group_id_to_group, deferreds)) # When we've finished fetching all the keys for a given server_name, # resolve the deferred passed to `wait_for_previous_lookups` so that # any lookups waiting will proceed. server_to_gids = {} def remove_deferreds(res, server_name, group_id): server_to_gids[server_name].discard(group_id) if not server_to_gids[server_name]: d = server_to_deferred.pop(server_name, None) if d: d.callback(None) return res for g_id, deferred in deferreds.items(): server_name = group_id_to_group[g_id].server_name server_to_gids.setdefault(server_name, set()).add(g_id) deferred.addBoth(remove_deferreds, server_name, g_id) # Pass those keys to handle_key_deferred so that the json object # signatures can be verified return [ handle_key_deferred( group_id_to_group[g_id], deferreds[g_id], ) for g_id in group_ids ]