about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJames Booth <boothj5@gmail.com>2014-04-26 22:08:53 +0100
committerJames Booth <boothj5@gmail.com>2014-04-26 22:08:53 +0100
commit06d81ed9ce7808a23267718ad24c32f957d95109 (patch)
tree06a6c112edba7a853ae23132f6158d10d4d0a20a
parentf44cf86f23f7b4183c5864a74e42b9f632c2c640 (diff)
downloadprofani-tty-06d81ed9ce7808a23267718ad24c32f957d95109.tar.gz
Send SMP init message with /otr secret
-rw-r--r--src/command/command.c1
-rw-r--r--src/command/commands.c18
-rw-r--r--src/otr/otr.c26
-rw-r--r--src/otr/otr.h2
-rw-r--r--src/otr/otrlib.h2
-rw-r--r--src/otr/otrlibv3.c51
6 files changed, 98 insertions, 2 deletions
diff --git a/src/command/command.c b/src/command/command.c
index 95a6158e..54df170d 100644
--- a/src/command/command.c
+++ b/src/command/command.c
@@ -1066,6 +1066,7 @@ cmd_init(void)
     autocomplete_add(otr_ac, "theirfp");
     autocomplete_add(otr_ac, "trust");
     autocomplete_add(otr_ac, "untrust");
+    autocomplete_add(otr_ac, "secret");
     autocomplete_add(otr_ac, "log");
     autocomplete_add(otr_ac, "warn");
     autocomplete_add(otr_ac, "libver");
diff --git a/src/command/commands.c b/src/command/commands.c
index 940a7f5a..915fbe17 100644
--- a/src/command/commands.c
+++ b/src/command/commands.c
@@ -2788,7 +2788,23 @@ cmd_otr(gchar **args, struct cmd_help_t help)
             otr_untrust(recipient);
         }
         return TRUE;
-
+    } else if (strcmp(args[0], "secret") == 0) {
+        win_type_t win_type = ui_current_win_type();
+        if (win_type != WIN_CHAT) {
+            ui_current_print_line("You must be in an OTR session to trust a recipient.");
+        } else if (!ui_current_win_is_otr()) {
+            ui_current_print_formatted_line('!', 0, "You are not currently in an OTR session.");
+        } else {
+            char *secret = args[1];
+            if (secret == NULL) {
+                cons_show("Usage: %s", help.usage);
+            } else {
+                char *recipient = ui_current_recipient();
+                otr_smp_init_secret(recipient, secret);
+                ui_current_print_formatted_line('!', 0, "OTR secret entered", secret);
+            }
+        }
+        return TRUE;
     } else {
         cons_show("Usage: %s", help.usage);
         return TRUE;
diff --git a/src/otr/otr.c b/src/otr/otr.c
index e80086af..462f6666 100644
--- a/src/otr/otr.c
+++ b/src/otr/otr.c
@@ -23,6 +23,7 @@
 #include <libotr/proto.h>
 #include <libotr/privkey.h>
 #include <libotr/message.h>
+#include <libotr/sm.h>
 #include <glib.h>
 
 #include "otr/otr.h"
@@ -388,6 +389,22 @@ _otr_untrust(const char * const recipient)
 }
 
 static void
+_otr_smp_init_secret(const char * const recipient, const char *secret)
+{
+    ConnContext *context = otrlib_context_find(user_state, recipient, jid);
+
+    if (context == NULL) {
+        return;
+    }
+
+    if (context->msgstate != OTRL_MSGSTATE_ENCRYPTED) {
+        return;
+    }
+
+    otrl_message_initiate_smp(user_state, &ops, NULL, context, (const unsigned char*)secret, strlen(secret));
+}
+
+static void
 _otr_end_session(const char * const recipient)
 {
     otrlib_end_session(user_state, recipient, jid, &ops);
@@ -441,15 +458,21 @@ _otr_decrypt_message(const char * const from, const char * const message, gboole
 
     // internal libotr message
     if (result == 1) {
+        ConnContext *context = otrlib_context_find(user_state, from, jid);
+
+        // common tlv handling
         OtrlTLV *tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
         if (tlv) {
-            ConnContext *context = otrlib_context_find(user_state, from, jid);
 
             if (context != NULL) {
                 otrl_context_force_plaintext(context);
                 ui_gone_insecure(from);
             }
         }
+
+        // library version specific tlv handling
+        otrlib_handle_tlvs(user_state, &ops, context, tlvs);
+
         return NULL;
 
     // message was decrypted, return to user
@@ -489,4 +512,5 @@ otr_init_module(void)
     otr_encrypt_message = _otr_encrypt_message;
     otr_decrypt_message = _otr_decrypt_message;
     otr_free_message = _otr_free_message;
+    otr_smp_init_secret = _otr_smp_init_secret;
 }
diff --git a/src/otr/otr.h b/src/otr/otr.h
index 5239c033..39eecab6 100644
--- a/src/otr/otr.h
+++ b/src/otr/otr.h
@@ -40,6 +40,8 @@ gboolean (*otr_is_trusted)(const char * const recipient);
 void (*otr_trust)(const char * const recipient);
 void (*otr_untrust)(const char * const recipient);
 
+void (*otr_smp_init_secret)(const char * const recipient, const char *secret);
+
 void (*otr_end_session)(const char * const recipient);
 
 char * (*otr_get_my_fingerprint)(void);
diff --git a/src/otr/otrlib.h b/src/otr/otrlib.h
index 0986c59b..df2144a6 100644
--- a/src/otr/otrlib.h
+++ b/src/otr/otrlib.h
@@ -39,4 +39,6 @@ gcry_error_t otrlib_encrypt_message(OtrlUserState user_state, OtrlMessageAppOps
 int otrlib_decrypt_message(OtrlUserState user_state, OtrlMessageAppOps *ops, char *jid, const char * const from,
     const char * const message, char **decrypted, OtrlTLV **tlvs);
 
+void otrlib_handle_tlvs(OtrlUserState user_state, OtrlMessageAppOps *ops, ConnContext *context, OtrlTLV *tlvs);
+
 #endif
diff --git a/src/otr/otrlibv3.c b/src/otr/otrlibv3.c
index d1495c9a..01714f9f 100644
--- a/src/otr/otrlibv3.c
+++ b/src/otr/otrlibv3.c
@@ -106,3 +106,54 @@ otrlib_decrypt_message(OtrlUserState user_state, OtrlMessageAppOps *ops, char *j
         NULL,
         NULL);
 }
+
+void
+otrlib_handle_tlvs(OtrlUserState user_state, OtrlMessageAppOps *ops, ConnContext *context, OtrlTLV *tlvs)
+{
+    NextExpectedSMP nextMsg = context->smstate->nextExpected;
+    OtrlTLV *tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1);
+    if (tlv) {
+        if (nextMsg != OTRL_SMP_EXPECT1) {
+            otrl_message_abort_smp(user_state, ops, NULL, context);
+        } else {
+            cons_debug("%s initiated SMP", context->username);
+            // [get secret from user and continue SMP];
+        }
+    }
+    tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2);
+    if (tlv) {
+        if (nextMsg != OTRL_SMP_EXPECT2) {
+            otrl_message_abort_smp(user_state, ops, NULL, context);
+        } else {
+            // If we received TLV2, we will send TLV3 and expect TLV4
+            context->smstate->nextExpected = OTRL_SMP_EXPECT4;
+        }
+    }
+    tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3);
+    if (tlv) {
+        if (nextMsg != OTRL_SMP_EXPECT3) {
+            otrl_message_abort_smp(user_state, ops, NULL, context);
+        } else {
+            // If we received TLV3, we will send TLV4
+            // We will not expect more messages, so prepare for next SMP
+            context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+            // Report result to user
+        }
+    }
+    tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4);
+    if (tlv) {
+        if (nextMsg != OTRL_SMP_EXPECT4) {
+            otrl_message_abort_smp(user_state, ops, NULL, context);
+        } else {
+            // We will not expect more messages, so prepare for next SMP
+            context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+            // Report result to user
+        }
+    }
+    tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT);
+    if (tlv) {
+        // The message we are waiting for will not arrive, so reset
+        // and prepare for the next SMP
+        context->smstate->nextExpected = OTRL_SMP_EXPECT1;
+    }
+}
\ No newline at end of file