From 06d81ed9ce7808a23267718ad24c32f957d95109 Mon Sep 17 00:00:00 2001 From: James Booth Date: Sat, 26 Apr 2014 22:08:53 +0100 Subject: [PATCH] Send SMP init message with /otr secret --- src/command/command.c | 1 + src/command/commands.c | 18 ++++++++++++++- src/otr/otr.c | 26 ++++++++++++++++++++- src/otr/otr.h | 2 ++ src/otr/otrlib.h | 2 ++ src/otr/otrlibv3.c | 51 ++++++++++++++++++++++++++++++++++++++++++ 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 #include #include +#include #include #include "otr/otr.h" @@ -387,6 +388,22 @@ _otr_untrust(const char * const recipient) return; } +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) { @@ -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