# HG changeset patch # User Goffi # Date 1584557765 -3600 # Node ID 806a7936a5919ebd9af2dcc776e696615c88d5d3 # Parent 0469c53ed5dde83ff28304331f60f3f179cf0c29 plugin XEP-0384: added "/omemo_reset" text command: this command will delete all sessions with peer entity, and send empty message to trigger a new key exchange. diff -r 0469c53ed5dd -r 806a7936a591 sat/plugins/plugin_xep_0384.py --- a/sat/plugins/plugin_xep_0384.py Wed Mar 18 19:54:07 2020 +0100 +++ b/sat/plugins/plugin_xep_0384.py Wed Mar 18 19:56:05 2020 +0100 @@ -55,7 +55,7 @@ C.PI_TYPE: "SEC", C.PI_PROTOCOLS: ["XEP-0384"], C.PI_DEPENDENCIES: ["XEP-0163", "XEP-0280", "XEP-0334", "XEP-0060"], - C.PI_RECOMMENDATIONS: ["XEP-0045", "XEP-0359"], + C.PI_RECOMMENDATIONS: ["XEP-0045", "XEP-0359", C.TEXT_CMDS], C.PI_MAIN: "OMEMO", C.PI_HANDLER: "no", C.PI_DESCRIPTION: _("""Implementation of OMEMO"""), @@ -318,6 +318,7 @@ return promise2Deferred(new_device_p) def getDevices(self, bare_jid=None): + bare_jid = bare_jid.userhost() get_devices_p = self._session.getDevices(bare_jid=bare_jid) return promise2Deferred(get_devices_p) @@ -326,6 +327,11 @@ build_session_p = self._session.buildSession(bare_jid, device, bundle) return promise2Deferred(build_session_p) + def deleteSession(self, bare_jid, device): + bare_jid = bare_jid.userhost() + delete_session_p = self._session.deleteSession(bare_jid=bare_jid, device=device) + return promise2Deferred(delete_session_p) + def encryptMessage(self, bare_jids, message, bundles=None, expect_problems=None): """Encrypt a message @@ -376,7 +382,7 @@ return promise2Deferred(get_trust_p) -class OMEMO(object): +class OMEMO: def __init__(self, host): log.info(_("OMEMO plugin initialization (omemo module v{version})").format( @@ -402,6 +408,39 @@ lambda itemsEvent, profile: defer.ensureDeferred( self.onNewDevices(itemsEvent, profile)) ) + try: + self.text_cmds = self.host.plugins[C.TEXT_CMDS] + except KeyError: + log.info(_("Text commands not available")) + else: + self.text_cmds.registerTextCommands(self) + + # Text commands # + + async def cmd_omemo_reset(self, client, mess_data): + """reset OMEMO session (use only if encryption is broken) + + @command(one2one): + """ + if not client.encryption.isEncryptionRequested(mess_data, NS_OMEMO): + feedback = _( + "You need to have OMEMO encryption activated to reset the session") + self.text_cmds.feedBack(client, feedback, mess_data) + return False + to_jid = mess_data["to"].userhostJID() + session = client._xep_0384_session + devices = await session.getDevices(to_jid) + + for device in devices['active']: + log.debug(f"deleting session for device {device}") + await session.deleteSession(to_jid, device=device) + + log.debug("Sending an empty message to trigger key exchange") + await client.sendMessage(to_jid, {'': ''}) + + feedback = _("OMEMO session has been reset") + self.text_cmds.feedBack(client, feedback, mess_data) + return False @defer.inlineCallbacks def trustUICb(self, xmlui_data, trust_data, expect_problems=None, @@ -651,7 +690,7 @@ defer.returnValue(devices) async def setDevices(self, client, devices): - log.debug(f"setting devices with {', '.join(devices)}") + log.debug(f"setting devices with {', '.join(str(d) for d in devices)}") list_elt = domish.Element((NS_OMEMO, 'list')) for device in devices: device_elt = list_elt.addElement('device') @@ -794,6 +833,7 @@ ## PEP node events callbacks async def onNewDevices(self, itemsEvent, profile): + log.debug("devices list has been updated") client = self.host.getClient(profile) try: omemo_session = client._xep_0384_session