From 391de9e11a9b3ebdee4f89a807ed19f8288ec84d Mon Sep 17 00:00:00 2001 From: mathieui Date: Sun, 11 Jan 2015 13:50:45 +0100 Subject: Fix a bug in the OTR plugin if the plugin attempted to start or refresh an OTR session on its own and the current tab was not this particular one, it would tb. Also make poezio beep and make tab states change for SMP actions. And update the documentation a bit. --- plugins/otr.py | 101 ++++++++++++++++++++++++++------------------------------- 1 file changed, 46 insertions(+), 55 deletions(-) diff --git a/plugins/otr.py b/plugins/otr.py index 4f6c5a77..8b8dbb04 100644 --- a/plugins/otr.py +++ b/plugins/otr.py @@ -78,37 +78,21 @@ Command added to Conversation Tabs and Private Tabs: - The ``abort`` command aborts an ongoing verification - The ``ask`` command start a verification, with a question or not - - The ``answer`` command answers a verification and ends the smp session + - The ``answer`` command sends back the answer and finishes the verification -To use OTR, make sure the plugin is loaded (if not, then do ``/load otr``). +Managing trust +-------------- -A simple workflow looks like this: +An OTR conversation can be started with a simple ``/otr start`` and the +conversation will be encrypted. However it is very often useful to check +that your are talking to the right person. -.. code-block:: none +To this end, two actions are available, and a message explaining both +will be prompted each time an **untrusted** conversation is started: - /otr start - -The status of the OTR encryption should appear in the bar between the chat and -the input as ``OTR: encrypted``. - -Then you use ``fpr``/``ourfpr`` to check the fingerprints, and confirm your respective -identities out-of-band. - -You can then use - -.. code-block:: none - - /otr trust - -To set the key as trusted, which will be shown when you start or refresh a conversation -(the trust status will be in a bold font and if the key is untrusted, the remote fingerprint -will be shown). - -Once you’re done, end the OTR session with - -.. code-block:: none - - /otr end +- Checking the knowledge of a shared secret through the use of :term:`/otrsmp` +- Exchanging fingerprints (``/otr fpr`` and ``/otr ourfpr``) out of band (in a secure channel) to check that both match, + then use ``/otr trust`` to add then to the list of trusted fingerprints for this JID. Files ----- @@ -582,7 +566,7 @@ class Plugin(BasePlugin): except UnencryptedMessage as err: # received an unencrypted message inside an OTR session self.unencrypted_message_received(err, ctx, msg, tab, format_dict) - self.command_otr('start') + self.otr_start(tab, tab.name, format_dict) return except NotOTRMessage as err: # ignore non-otr messages @@ -591,7 +575,7 @@ class Plugin(BasePlugin): # but do an additional check because of a bug with potr and py3k if ctx.state != STATE_PLAINTEXT or ctx.getPolicy('REQUIRE_ENCRYPTION'): self.unencrypted_message_received(err, ctx, msg, tab, format_dict) - self.command_otr('start') + self.otr_start(tab, tab.name, format_dict) return except ErrorReceived as err: # Received an OTR error @@ -680,6 +664,7 @@ class Plugin(BasePlugin): else: tab.add_message(SMP_FAIL % format_dict, typ=0) ctx.reset_smp() + hl(tab) self.core.refresh_window() def unencrypted_message_received(self, err, ctx, msg, tab, format_dict): @@ -796,7 +781,7 @@ class Plugin(BasePlugin): del msg['body'] del msg['replace'] del msg['html'] - self.command_otr('start') + self.otr_start(tab, name, format_dict) def display_encryption_status(self, jid): """ @@ -841,31 +826,7 @@ class Plugin(BasePlugin): ctx = self.find_encrypted_context_with_matching(safeJID(name).bare) ctx.disconnect() elif action == 'start' or action == 'refresh': - otr = self.get_context(name) - secs = self.config.get('timeout', 3) - if isinstance(tab, DynamicConversationTab) and tab.locked_resource: - was_locked = True - else: - was_locked = False - def notify_otr_timeout(): - nonlocal otr - if isinstance(tab, DynamicConversationTab) and not was_locked: - if tab.locked_resource: - name = safeJID(tab.name) - name.resource = tab.locked_resource - name = name.full - otr = self.get_context(name) - if otr.state != STATE_ENCRYPTED: - format_dict['secs'] = secs - text = OTR_NOT_ENABLED % format_dict - tab.add_message(text, typ=0) - self.core.refresh_window() - if secs > 0: - event = self.api.create_delayed_event(secs, notify_otr_timeout) - self.api.add_timed_event(event) - body = self.contexts[name].sendMessage(0, b'?OTRv?').decode() - self.core.xmpp.send_message(mto=name, mtype='chat', mbody=body) - tab.add_message(OTR_REQUEST % format_dict, typ=0) + self.otr_start(tab, name, format_dict) elif action == 'ourfpr': format_dict['fpr'] = self.account.getPrivkey() tab.add_message(OTR_OWN_FPR % format_dict, typ=0) @@ -910,6 +871,36 @@ class Plugin(BasePlugin): tab.add_message(TRUST_REMOVED % format_dict, typ=0) self.core.refresh_window() + def otr_start(self, tab, name, format_dict): + """ + Start an otr conversation with a contact + """ + otr = self.get_context(name) + secs = self.config.get('timeout', 3) + if isinstance(tab, DynamicConversationTab) and tab.locked_resource: + was_locked = True + else: + was_locked = False + def notify_otr_timeout(): + otr = self.get_context(name) + if isinstance(tab, DynamicConversationTab) and not was_locked: + if tab.locked_resource: + name = safeJID(tab.name) + name.resource = tab.locked_resource + name = name.full + otr = self.get_context(name) + if otr.state != STATE_ENCRYPTED: + format_dict['secs'] = secs + text = OTR_NOT_ENABLED % format_dict + tab.add_message(text, typ=0) + self.core.refresh_window() + if secs > 0: + event = self.api.create_delayed_event(secs, notify_otr_timeout) + self.api.add_timed_event(event) + body = self.contexts[name].sendMessage(0, b'?OTRv?').decode() + self.core.xmpp.send_message(mto=name, mtype='chat', mbody=body) + tab.add_message(OTR_REQUEST % format_dict, typ=0) + @staticmethod def completion_otr(the_input): """ -- cgit v1.2.3