diff options
-rw-r--r-- | src/command/command.c | 4 | ||||
-rw-r--r-- | src/command/commands.c | 35 | ||||
-rw-r--r-- | src/otr/otr.c | 36 | ||||
-rw-r--r-- | src/otr/otr.h | 2 | ||||
-rw-r--r-- | src/otr/otrlibv3.c | 30 | ||||
-rw-r--r-- | src/ui/core.c | 18 | ||||
-rw-r--r-- | src/ui/ui.h | 2 |
7 files changed, 118 insertions, 9 deletions
diff --git a/src/command/command.c b/src/command/command.c index 54df170d..d7a60495 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -594,7 +594,7 @@ static struct cmd_t command_defs[] = NULL } } }, { "/otr", - cmd_otr, parse_args, 1, 2, NULL, + cmd_otr, parse_args, 1, 3, NULL, { "/otr gen|myfp|theirfp|start|end|trust|untrust|log|warn|libver|policy", "Off The Record encryption commands.", { "/otr gen|myfp|theirfp|start|end|trust|untrust|log|warn|libver|policy", "--------------------------------------------------------------------", @@ -1071,6 +1071,8 @@ cmd_init(void) autocomplete_add(otr_ac, "warn"); autocomplete_add(otr_ac, "libver"); autocomplete_add(otr_ac, "policy"); + autocomplete_add(otr_ac, "question"); + autocomplete_add(otr_ac, "answer"); otr_log_ac = autocomplete_new(); autocomplete_add(otr_log_ac, "on"); diff --git a/src/command/commands.c b/src/command/commands.c index 75f3c793..ad508cc7 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -2804,6 +2804,41 @@ cmd_otr(gchar **args, struct cmd_help_t help) } } return TRUE; + } else if (strcmp(args[0], "question") == 0) { + char *question = args[1]; + char *answer = args[2]; + + if (question == NULL || answer == NULL) { + cons_show("Usage: %s", help.usage); + return TRUE; + } else { + 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 *recipient = ui_current_recipient(); + otr_smp_question(recipient, question, answer); + } + return TRUE; + } + } else if (strcmp(args[0], "answer") == 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 *answer = args[1]; + if (answer == NULL) { + cons_show("Usage: %s", help.usage); + } else { + char *recipient = ui_current_recipient(); + otr_smp_answer(recipient, answer); + } + } + return TRUE; } else { cons_show("Usage: %s", help.usage); return TRUE; diff --git a/src/otr/otr.c b/src/otr/otr.c index 2ad8e752..043dc30f 100644 --- a/src/otr/otr.c +++ b/src/otr/otr.c @@ -451,6 +451,40 @@ _otr_smp_secret(const char * const recipient, const char *secret) } static void +_otr_smp_question(const char * const recipient, const char *question, const char *answer) +{ + ConnContext *context = otrlib_context_find(user_state, recipient, jid); + + if (context == NULL) { + return; + } + + if (context->msgstate != OTRL_MSGSTATE_ENCRYPTED) { + return; + } + + otrl_message_initiate_smp_q(user_state, &ops, NULL, context, question, (const unsigned char*)answer, strlen(answer)); + ui_otr_authetication_waiting(recipient); +} + +static void +_otr_smp_answer(const char * const recipient, const char *answer) +{ + ConnContext *context = otrlib_context_find(user_state, recipient, jid); + + if (context == NULL) { + return; + } + + if (context->msgstate != OTRL_MSGSTATE_ENCRYPTED) { + return; + } + + // if recipient initiated SMP, send response, else initialise + otrl_message_respond_smp(user_state, &ops, NULL, context, (const unsigned char*)answer, strlen(answer)); +} + +static void _otr_end_session(const char * const recipient) { otrlib_end_session(user_state, recipient, jid, &ops); @@ -560,4 +594,6 @@ otr_init_module(void) otr_decrypt_message = _otr_decrypt_message; otr_free_message = _otr_free_message; otr_smp_secret = _otr_smp_secret; + otr_smp_question = _otr_smp_question; + otr_smp_answer = _otr_smp_answer; } diff --git a/src/otr/otr.h b/src/otr/otr.h index f2f20d17..87b34b45 100644 --- a/src/otr/otr.h +++ b/src/otr/otr.h @@ -49,6 +49,8 @@ void (*otr_trust)(const char * const recipient); void (*otr_untrust)(const char * const recipient); void (*otr_smp_secret)(const char * const recipient, const char *secret); +void (*otr_smp_question)(const char * const recipient, const char *question, const char *answer); +void (*otr_smp_answer)(const char * const recipient, const char *answer); void (*otr_end_session)(const char * const recipient); diff --git a/src/otr/otrlibv3.c b/src/otr/otrlibv3.c index 7ec8a492..92ca3602 100644 --- a/src/otr/otrlibv3.c +++ b/src/otr/otrlibv3.c @@ -132,6 +132,18 @@ otrlib_handle_tlvs(OtrlUserState user_state, OtrlMessageAppOps *ops, ConnContext g_hash_table_insert(smp_initiators, strdup(context->username), strdup(context->username)); } } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q); + if (tlv) { + if (nextMsg != OTRL_SMP_EXPECT1) { + otrl_message_abort_smp(user_state, ops, NULL, context); + } else { + char *question = (char *)tlv->data; + char *eoq = memchr(question, '\0', tlv->len); + if (eoq) { + ui_smp_recipient_initiated_q(context->username, question); + } + } + } tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2); if (tlv) { if (nextMsg != OTRL_SMP_EXPECT2) { @@ -146,14 +158,16 @@ otrlib_handle_tlvs(OtrlUserState user_state, OtrlMessageAppOps *ops, ConnContext otrl_message_abort_smp(user_state, ops, NULL, context); } else { context->smstate->nextExpected = OTRL_SMP_EXPECT1; - if ((context->active_fingerprint->trust != NULL) && (context->active_fingerprint->trust[0] != '\0')) { - ui_smp_successful(context->username); - ui_trust(context->username); - otr_trust(context->username); - } else { - ui_smp_unsuccessful_sender(context->username); - ui_untrust(context->username); - otr_untrust(context->username); + if (context->smstate->received_question == 0) { + if ((context->active_fingerprint->trust != NULL) && (context->active_fingerprint->trust[0] != '\0')) { + ui_smp_successful(context->username); + ui_trust(context->username); + otr_trust(context->username); + } else { + ui_smp_unsuccessful_sender(context->username); + ui_untrust(context->username); + otr_untrust(context->username); + } } } } diff --git a/src/ui/core.c b/src/ui/core.c index 987d8570..bc4a9587 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -801,6 +801,23 @@ _ui_smp_recipient_initiated(const char * const recipient) } static void +_ui_smp_recipient_initiated_q(const char * const recipient, const char *question) +{ + ProfWin *window = wins_get_by_recipient(recipient); + if (window == NULL) { + return; + } else { + win_vprint_line(window, '!', 0, "%s wants to authenticate your identity with the following question:", recipient); + win_vprint_line(window, '!', 0, " %s", question); + win_vprint_line(window, '!', 0, "use '/otr answer <answer>'."); + win_update_virtual(window); + if (wins_is_current(window)) { + ui_current_page_off(); + } + } +} + +static void _ui_smp_unsuccessful_sender(const char * const recipient) { ProfWin *window = wins_get_by_recipient(recipient); @@ -2090,6 +2107,7 @@ ui_init_module(void) ui_trust = _ui_trust; ui_untrust = _ui_untrust; ui_smp_recipient_initiated = _ui_smp_recipient_initiated; + ui_smp_recipient_initiated_q = _ui_smp_recipient_initiated_q; ui_smp_successful = _ui_smp_successful; ui_smp_unsuccessful_sender = _ui_smp_unsuccessful_sender; ui_smp_unsuccessful_receiver = _ui_smp_unsuccessful_receiver; diff --git a/src/ui/ui.h b/src/ui/ui.h index 9bf07fd1..5e850c6c 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -64,6 +64,8 @@ void (*ui_gone_insecure)(const char * const recipient); void (*ui_trust)(const char * const recipient); void (*ui_untrust)(const char * const recipient); void (*ui_smp_recipient_initiated)(const char * const recipient); +void (*ui_smp_recipient_initiated_q)(const char * const recipient, const char *question); + void (*ui_smp_successful)(const char * const recipient); void (*ui_smp_unsuccessful_sender)(const char * const recipient); void (*ui_smp_unsuccessful_receiver)(const char * const recipient); |