summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/otr.py101
1 files 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):
"""