comparison sat/plugins/plugin_xep_0384.py @ 3218:806a7936a591

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.
author Goffi <goffi@goffi.org>
date Wed, 18 Mar 2020 19:56:05 +0100
parents 8d92d4d829fb
children e756e0eb1be4
comparison
equal deleted inserted replaced
3217:0469c53ed5dd 3218:806a7936a591
53 C.PI_NAME: "OMEMO", 53 C.PI_NAME: "OMEMO",
54 C.PI_IMPORT_NAME: "XEP-0384", 54 C.PI_IMPORT_NAME: "XEP-0384",
55 C.PI_TYPE: "SEC", 55 C.PI_TYPE: "SEC",
56 C.PI_PROTOCOLS: ["XEP-0384"], 56 C.PI_PROTOCOLS: ["XEP-0384"],
57 C.PI_DEPENDENCIES: ["XEP-0163", "XEP-0280", "XEP-0334", "XEP-0060"], 57 C.PI_DEPENDENCIES: ["XEP-0163", "XEP-0280", "XEP-0334", "XEP-0060"],
58 C.PI_RECOMMENDATIONS: ["XEP-0045", "XEP-0359"], 58 C.PI_RECOMMENDATIONS: ["XEP-0045", "XEP-0359", C.TEXT_CMDS],
59 C.PI_MAIN: "OMEMO", 59 C.PI_MAIN: "OMEMO",
60 C.PI_HANDLER: "no", 60 C.PI_HANDLER: "no",
61 C.PI_DESCRIPTION: _("""Implementation of OMEMO"""), 61 C.PI_DESCRIPTION: _("""Implementation of OMEMO"""),
62 } 62 }
63 63
316 jid = jid.userhost() 316 jid = jid.userhost()
317 new_device_p = self._session.newDeviceList(jid, devices) 317 new_device_p = self._session.newDeviceList(jid, devices)
318 return promise2Deferred(new_device_p) 318 return promise2Deferred(new_device_p)
319 319
320 def getDevices(self, bare_jid=None): 320 def getDevices(self, bare_jid=None):
321 bare_jid = bare_jid.userhost()
321 get_devices_p = self._session.getDevices(bare_jid=bare_jid) 322 get_devices_p = self._session.getDevices(bare_jid=bare_jid)
322 return promise2Deferred(get_devices_p) 323 return promise2Deferred(get_devices_p)
323 324
324 def buildSession(self, bare_jid, device, bundle): 325 def buildSession(self, bare_jid, device, bundle):
325 bare_jid = bare_jid.userhost() 326 bare_jid = bare_jid.userhost()
326 build_session_p = self._session.buildSession(bare_jid, device, bundle) 327 build_session_p = self._session.buildSession(bare_jid, device, bundle)
327 return promise2Deferred(build_session_p) 328 return promise2Deferred(build_session_p)
329
330 def deleteSession(self, bare_jid, device):
331 bare_jid = bare_jid.userhost()
332 delete_session_p = self._session.deleteSession(bare_jid=bare_jid, device=device)
333 return promise2Deferred(delete_session_p)
328 334
329 def encryptMessage(self, bare_jids, message, bundles=None, expect_problems=None): 335 def encryptMessage(self, bare_jids, message, bundles=None, expect_problems=None):
330 """Encrypt a message 336 """Encrypt a message
331 337
332 @param bare_jids(iterable[jid.JID]): destinees of the message 338 @param bare_jids(iterable[jid.JID]): destinees of the message
374 bare_jid = bare_jid.userhost() 380 bare_jid = bare_jid.userhost()
375 get_trust_p = self._session.getTrustForJID(bare_jid=bare_jid) 381 get_trust_p = self._session.getTrustForJID(bare_jid=bare_jid)
376 return promise2Deferred(get_trust_p) 382 return promise2Deferred(get_trust_p)
377 383
378 384
379 class OMEMO(object): 385 class OMEMO:
380 386
381 def __init__(self, host): 387 def __init__(self, host):
382 log.info(_("OMEMO plugin initialization (omemo module v{version})").format( 388 log.info(_("OMEMO plugin initialization (omemo module v{version})").format(
383 version=omemo.__version__)) 389 version=omemo.__version__))
384 version = tuple(map(int, omemo.__version__.split('.')[:3])) 390 version = tuple(map(int, omemo.__version__.split('.')[:3]))
400 pep.addPEPEvent( 406 pep.addPEPEvent(
401 "OMEMO_DEVICES", NS_OMEMO_DEVICES, 407 "OMEMO_DEVICES", NS_OMEMO_DEVICES,
402 lambda itemsEvent, profile: defer.ensureDeferred( 408 lambda itemsEvent, profile: defer.ensureDeferred(
403 self.onNewDevices(itemsEvent, profile)) 409 self.onNewDevices(itemsEvent, profile))
404 ) 410 )
411 try:
412 self.text_cmds = self.host.plugins[C.TEXT_CMDS]
413 except KeyError:
414 log.info(_("Text commands not available"))
415 else:
416 self.text_cmds.registerTextCommands(self)
417
418 # Text commands #
419
420 async def cmd_omemo_reset(self, client, mess_data):
421 """reset OMEMO session (use only if encryption is broken)
422
423 @command(one2one):
424 """
425 if not client.encryption.isEncryptionRequested(mess_data, NS_OMEMO):
426 feedback = _(
427 "You need to have OMEMO encryption activated to reset the session")
428 self.text_cmds.feedBack(client, feedback, mess_data)
429 return False
430 to_jid = mess_data["to"].userhostJID()
431 session = client._xep_0384_session
432 devices = await session.getDevices(to_jid)
433
434 for device in devices['active']:
435 log.debug(f"deleting session for device {device}")
436 await session.deleteSession(to_jid, device=device)
437
438 log.debug("Sending an empty message to trigger key exchange")
439 await client.sendMessage(to_jid, {'': ''})
440
441 feedback = _("OMEMO session has been reset")
442 self.text_cmds.feedBack(client, feedback, mess_data)
443 return False
405 444
406 @defer.inlineCallbacks 445 @defer.inlineCallbacks
407 def trustUICb(self, xmlui_data, trust_data, expect_problems=None, 446 def trustUICb(self, xmlui_data, trust_data, expect_problems=None,
408 profile=C.PROF_KEY_NONE): 447 profile=C.PROF_KEY_NONE):
409 if C.bool(xmlui_data.get('cancelled', 'false')): 448 if C.bool(xmlui_data.get('cancelled', 'false')):
649 688
650 devices = self.parseDevices(items) 689 devices = self.parseDevices(items)
651 defer.returnValue(devices) 690 defer.returnValue(devices)
652 691
653 async def setDevices(self, client, devices): 692 async def setDevices(self, client, devices):
654 log.debug(f"setting devices with {', '.join(devices)}") 693 log.debug(f"setting devices with {', '.join(str(d) for d in devices)}")
655 list_elt = domish.Element((NS_OMEMO, 'list')) 694 list_elt = domish.Element((NS_OMEMO, 'list'))
656 for device in devices: 695 for device in devices:
657 device_elt = list_elt.addElement('device') 696 device_elt = list_elt.addElement('device')
658 device_elt['id'] = str(device) 697 device_elt['id'] = str(device)
659 try: 698 try:
792 log.warning(_("Can't set bundle: {reason}").format(reason=e)) 831 log.warning(_("Can't set bundle: {reason}").format(reason=e))
793 832
794 ## PEP node events callbacks 833 ## PEP node events callbacks
795 834
796 async def onNewDevices(self, itemsEvent, profile): 835 async def onNewDevices(self, itemsEvent, profile):
836 log.debug("devices list has been updated")
797 client = self.host.getClient(profile) 837 client = self.host.getClient(profile)
798 try: 838 try:
799 omemo_session = client._xep_0384_session 839 omemo_session = client._xep_0384_session
800 except AttributeError: 840 except AttributeError:
801 await client._xep_0384_ready 841 await client._xep_0384_ready