@@ -56,12 +56,24 @@ def __init__(self):
5656
5757class OnlyLoginSelf (CustomPuppetError ):
5858 def __init__ (self ):
59- super ().__init__ ("You may only replace your puppet with your own Matrix account." )
59+ super ().__init__ ("You may only enable double puppeting with your own Matrix account." )
60+
61+
62+ class EncryptionKeysFound (CustomPuppetError ):
63+ def __init__ (self ):
64+ super ().__init__ (
65+ "The given access token is for a device that has encryption keys set up. "
66+ "Please provide a fresh token, don't reuse one from another client."
67+ )
6068
6169
6270class HomeserverURLNotFound (CustomPuppetError ):
6371 def __init__ (self , domain : str ):
64- super ().__init__ (f"Could not discover a valid homeserver URL for { domain } " )
72+ super ().__init__ (
73+ f"Could not discover a valid homeserver URL for { domain } ."
74+ " Please ensure a client .well-known file is set up, or ask the bridge administrator "
75+ "to add the homeserver URL to the bridge config."
76+ )
6577
6678
6779class OnlyLoginTrustedDomain (CustomPuppetError ):
@@ -235,7 +247,7 @@ async def switch_mxid(
235247 self .base_url = base_url
236248 self .intent = self ._fresh_intent ()
237249
238- await self .start (start_sync_task = start_sync_task )
250+ await self .start (start_sync_task = start_sync_task , check_e2ee_keys = True )
239251
240252 try :
241253 del self .by_custom_mxid [prev_mxid ]
@@ -255,7 +267,21 @@ async def try_start(self, retry_auto_login: bool = True) -> None:
255267 except Exception :
256268 self .log .exception ("Failed to initialize custom mxid" )
257269
258- async def start (self , retry_auto_login : bool = False , start_sync_task : bool = True ) -> None :
270+ async def _invalidate_double_puppet (self ) -> None :
271+ if self .custom_mxid and self .by_custom_mxid .get (self .custom_mxid ) == self :
272+ del self .by_custom_mxid [self .custom_mxid ]
273+ self .custom_mxid = None
274+ self .access_token = None
275+ self .next_batch = None
276+ await self .save ()
277+ self .intent = self ._fresh_intent ()
278+
279+ async def start (
280+ self ,
281+ retry_auto_login : bool = False ,
282+ start_sync_task : bool = True ,
283+ check_e2ee_keys : bool = False ,
284+ ) -> None :
259285 """Initialize the custom account this puppet uses. Should be called at startup to start
260286 the /sync task. Is called by :meth:`switch_mxid` automatically."""
261287 if not self .is_real_user :
@@ -271,17 +297,24 @@ async def start(self, retry_auto_login: bool = False, start_sync_task: bool = Tr
271297 self .log .warning (f"Got { e .errcode } while trying to initialize custom mxid" )
272298 whoami = None
273299 if not whoami or whoami .user_id != self .custom_mxid :
274- if self .custom_mxid and self .by_custom_mxid .get (self .custom_mxid ) == self :
275- del self .by_custom_mxid [self .custom_mxid ]
276300 prev_custom_mxid = self .custom_mxid
277- self .custom_mxid = None
278- self .access_token = None
279- self .next_batch = None
280- await self .save ()
281- self .intent = self ._fresh_intent ()
301+ await self ._invalidate_double_puppet ()
282302 if whoami and whoami .user_id != prev_custom_mxid :
283303 raise OnlyLoginSelf ()
284304 raise InvalidAccessToken ()
305+ if check_e2ee_keys :
306+ try :
307+ devices = await self .intent .query_keys ({whoami .user_id : [whoami .device_id ]})
308+ device_keys = devices .device_keys .get (whoami .user_id , {}).get (whoami .device_id )
309+ except Exception :
310+ self .log .warning (
311+ "Failed to query keys to check if double puppeting token was reused" ,
312+ exc_info = True ,
313+ )
314+ else :
315+ if device_keys and len (device_keys .keys ) > 0 :
316+ await self ._invalidate_double_puppet ()
317+ raise EncryptionKeysFound ()
285318 if self .sync_with_custom_puppets and start_sync_task :
286319 if self ._sync_task :
287320 self ._sync_task .cancel ()
0 commit comments