From ba0fa6e5360ce9350df469724d912be5644ac62b Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Wed, 6 Mar 2019 19:35:00 +0140 Subject: Add OMEMO commands autocompletion --- src/command/cmd_ac.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'src/command/cmd_ac.c') diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index 58ad758a..daf4f3a9 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -69,6 +69,7 @@ static char* _group_autocomplete(ProfWin *window, const char *const input, gbool static char* _bookmark_autocomplete(ProfWin *window, const char *const input, gboolean previous); static char* _otr_autocomplete(ProfWin *window, const char *const input, gboolean previous); static char* _pgp_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _omemo_autocomplete(ProfWin *window, const char *const input, gboolean previous); static char* _connect_autocomplete(ProfWin *window, const char *const input, gboolean previous); static char* _alias_autocomplete(ProfWin *window, const char *const input, gboolean previous); static char* _join_autocomplete(ProfWin *window, const char *const input, gboolean previous); @@ -157,6 +158,7 @@ static Autocomplete bookmark_property_ac; static Autocomplete otr_ac; static Autocomplete otr_log_ac; static Autocomplete otr_policy_ac; +static Autocomplete omemo_ac; static Autocomplete connect_property_ac; static Autocomplete tls_property_ac; static Autocomplete alias_ac; @@ -574,6 +576,10 @@ cmd_ac_init(void) autocomplete_add(otr_policy_ac, "opportunistic"); autocomplete_add(otr_policy_ac, "always"); + omemo_ac = autocomplete_new(); + autocomplete_add(omemo_ac, "gen"); + autocomplete_add(omemo_ac, "start"); + connect_property_ac = autocomplete_new(); autocomplete_add(connect_property_ac, "server"); autocomplete_add(connect_property_ac, "port"); @@ -1052,6 +1058,7 @@ cmd_ac_reset(ProfWin *window) autocomplete_reset(otr_ac); autocomplete_reset(otr_log_ac); autocomplete_reset(otr_policy_ac); + autocomplete_reset(omemo_ac); autocomplete_reset(connect_property_ac); autocomplete_reset(tls_property_ac); autocomplete_reset(alias_ac); @@ -1179,6 +1186,7 @@ cmd_ac_uninit(void) autocomplete_free(otr_ac); autocomplete_free(otr_log_ac); autocomplete_free(otr_policy_ac); + autocomplete_free(omemo_ac); autocomplete_free(connect_property_ac); autocomplete_free(tls_property_ac); autocomplete_free(alias_ac); @@ -1438,6 +1446,7 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input, gboolean previ g_hash_table_insert(ac_funcs, "/autoconnect", _autoconnect_autocomplete); g_hash_table_insert(ac_funcs, "/otr", _otr_autocomplete); g_hash_table_insert(ac_funcs, "/pgp", _pgp_autocomplete); + g_hash_table_insert(ac_funcs, "/omemo", _omemo_autocomplete); g_hash_table_insert(ac_funcs, "/connect", _connect_autocomplete); g_hash_table_insert(ac_funcs, "/alias", _alias_autocomplete); g_hash_table_insert(ac_funcs, "/join", _join_autocomplete); @@ -2117,6 +2126,28 @@ _pgp_autocomplete(ProfWin *window, const char *const input, gboolean previous) return NULL; } +static char* +_omemo_autocomplete(ProfWin *window, const char *const input, gboolean previous) +{ + char *found = NULL; + + jabber_conn_status_t conn_status = connection_get_status(); + + if (conn_status == JABBER_CONNECTED) { + found = autocomplete_param_with_func(input, "/omemo start", roster_contact_autocomplete, previous); + if (found) { + return found; + } + } + + found = autocomplete_param_with_ac(input, "/omemo", omemo_ac, TRUE, previous); + if (found) { + return found; + } + + return NULL; +} + static char* _plugins_autocomplete(ProfWin *window, const char *const input, gboolean previous) { -- cgit 1.4.1-2-gfad0 From b3be504e841be55f917a3841d9cddf4ce076cc04 Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Thu, 7 Mar 2019 19:04:33 +0140 Subject: Add OMEMO fingerprint command --- src/command/cmd_ac.c | 1 + src/command/cmd_defs.c | 9 ++++++--- src/command/cmd_funcs.c | 28 +++++++++++++++++++++++++++ src/command/cmd_funcs.h | 1 + src/omemo/omemo.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ src/omemo/omemo.h | 3 +++ 6 files changed, 90 insertions(+), 3 deletions(-) (limited to 'src/command/cmd_ac.c') diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index daf4f3a9..55f05c7c 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -579,6 +579,7 @@ cmd_ac_init(void) omemo_ac = autocomplete_new(); autocomplete_add(omemo_ac, "gen"); autocomplete_add(omemo_ac, "start"); + autocomplete_add(omemo_ac, "fingerprint"); connect_property_ac = autocomplete_new(); autocomplete_add(connect_property_ac, "server"); diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 3cd8330e..7b2df39b 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -2334,19 +2334,22 @@ static struct cmd_t command_defs[] = parse_args, 1, 2, NULL, CMD_SUBFUNCS( { "gen", cmd_omemo_gen }, - { "start", cmd_omemo_start }) + { "start", cmd_omemo_start }, + { "fingerprint", cmd_omemo_fingerprint }) CMD_NOMAINFUNC CMD_TAGS( CMD_TAG_CHAT, CMD_TAG_UI) CMD_SYN( "/omemo gen", - "/omemo start []") + "/omemo start []", + "/omemo fingerprint") CMD_DESC( "Omemo commands to manage keys, and perform encryption during chat sessions.") CMD_ARGS( { "gen", "Generate OMEMO crytographic materials for current account." }, - { "start []", "Start an OMEMO session with contact, or current recipient if omitted." }) + { "start []", "Start an OMEMO session with contact, or current recipient if omitted." }, + { "fingerprint", "Show current device fingerprint." }) CMD_EXAMPLES( "/omemo gen", "/omemo start buddy@buddychat.org") diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 5ce9b7f4..70940f17 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -7988,3 +7988,31 @@ cmd_omemo_start(ProfWin *window, const char *const command, gchar **args) return TRUE; #endif } + +gboolean +cmd_omemo_fingerprint(ProfWin *window, const char *const command, gchar **args) +{ +#ifdef HAVE_OMEMO + if (connection_get_status() != JABBER_CONNECTED) { + cons_show("You must be connected with an account to load OMEMO information."); + return TRUE; + } + + if (!omemo_loaded()) { + win_println(window, THEME_DEFAULT, '!', "You have not generated or loaded a cryptographic materials, use '/omemo gen'"); + return TRUE; + } + + char *fingerprint = omemo_own_fingerprint(); + char *formated_fingerprint = omemo_format_fingerprint(fingerprint); + cons_show("%s", formated_fingerprint); + + free(fingerprint); + free(formated_fingerprint); + + return TRUE; +#else + cons_show("This version of Profanity has not been built with OMEMO support enabled"); + return TRUE; +#endif +} diff --git a/src/command/cmd_funcs.h b/src/command/cmd_funcs.h index f39e8c17..4809f703 100644 --- a/src/command/cmd_funcs.h +++ b/src/command/cmd_funcs.h @@ -216,5 +216,6 @@ gboolean cmd_form_field(ProfWin *window, char *tag, gchar **args); gboolean cmd_omemo_gen(ProfWin *window, const char *const command, gchar **args); gboolean cmd_omemo_start(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_omemo_fingerprint(ProfWin *window, const char *const command, gchar **args); #endif diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c index 3a771b6b..b293022f 100644 --- a/src/omemo/omemo.c +++ b/src/omemo/omemo.c @@ -679,6 +679,57 @@ omemo_on_message_recv(const char *const from, uint32_t sid, } +char * +omemo_format_fingerprint(const char *const fingerprint) +{ + char *output = malloc(strlen(fingerprint) + strlen(fingerprint) / 8 + 1); + + int i, j; + for (i = 0, j = 0; i < strlen(fingerprint); i++) { + if (i > 0 && i % 8 == 0) { + output[j++] = '-'; + } + output[j++] = fingerprint[i]; + } + + output[strlen(fingerprint) + strlen(fingerprint) / 8] = '\0'; + + return output; +} + +char * +omemo_own_fingerprint() +{ + signal_buffer *public = omemo_ctx.identity_key_store.public; + /* Skip first byte corresponding to signal base type */ + return omemo_fingerprint(signal_buffer_data(public) + 1, signal_buffer_len(public) - 1); +} + +char * +omemo_fingerprint(const unsigned char *const identity_key_public, size_t len) +{ + int i; + char *fingerprint = malloc(len * 2 + 1); + + for (i = 0; i < len; i++) { + fingerprint[i * 2] = (identity_key_public[i] & 0xf0) >> 4; + fingerprint[i * 2] += 0x30; + if (fingerprint[i * 2] > 0x39) { + fingerprint[i * 2] += 0x27; + } + + fingerprint[(i * 2) + 1] = identity_key_public[i] & 0x0f; + fingerprint[(i * 2) + 1] += 0x30; + if (fingerprint[(i * 2) + 1] > 0x39) { + fingerprint[(i * 2) + 1] += 0x27; + } + } + + fingerprint[len * 2] = '\0'; + + return fingerprint; +} + static void lock(void *user_data) { diff --git a/src/omemo/omemo.h b/src/omemo/omemo.h index ef43617d..88c6d27c 100644 --- a/src/omemo/omemo.h +++ b/src/omemo/omemo.h @@ -28,6 +28,9 @@ void omemo_prekeys(GList **prekeys, GList **ids, GList **lengths); void omemo_set_device_list(const char *const jid, GList * device_list); GKeyFile *omemo_sessions_keyfile(void); void omemo_sessions_keyfile_save(void); +char *omemo_fingerprint(const unsigned char *const identity_key_public, size_t len); +char *omemo_format_fingerprint(const char *const fingerprint); +char *omemo_own_fingerprint(); void omemo_start_session(const char *const barejid); void omemo_start_device_session(const char *const jid, uint32_t device_id, GList *prekeys, uint32_t signed_prekey_id, const unsigned char *const signed_prekey, size_t signed_prekey_len, const unsigned char *const signature, size_t signature_len, const unsigned char *const identity_key, size_t identity_key_len); -- cgit 1.4.1-2-gfad0 From 063a5d1c52862065a62b07ec96ca3cde2b4d2955 Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Thu, 7 Mar 2019 19:45:11 +0140 Subject: Add trust command --- src/command/cmd_ac.c | 1 + src/command/cmd_defs.c | 7 +- src/command/cmd_funcs.c | 58 +++++++++++- src/command/cmd_funcs.h | 1 + src/omemo/omemo.c | 244 ++++++++++++++++++++++++++++++++++++++++-------- src/omemo/omemo.h | 4 +- 6 files changed, 268 insertions(+), 47 deletions(-) (limited to 'src/command/cmd_ac.c') diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index 55f05c7c..ce66d507 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -579,6 +579,7 @@ cmd_ac_init(void) omemo_ac = autocomplete_new(); autocomplete_add(omemo_ac, "gen"); autocomplete_add(omemo_ac, "start"); + autocomplete_add(omemo_ac, "trust"); autocomplete_add(omemo_ac, "fingerprint"); connect_property_ac = autocomplete_new(); diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 7b2df39b..200a46d3 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -2331,10 +2331,11 @@ static struct cmd_t command_defs[] = }, { "/omemo", - parse_args, 1, 2, NULL, + parse_args, 1, 3, NULL, CMD_SUBFUNCS( { "gen", cmd_omemo_gen }, { "start", cmd_omemo_start }, + { "trust", cmd_omemo_trust }, { "fingerprint", cmd_omemo_fingerprint }) CMD_NOMAINFUNC CMD_TAGS( @@ -2343,6 +2344,7 @@ static struct cmd_t command_defs[] = CMD_SYN( "/omemo gen", "/omemo start []", + "/omemo trust [] ", "/omemo fingerprint") CMD_DESC( "Omemo commands to manage keys, and perform encryption during chat sessions.") @@ -2352,7 +2354,8 @@ static struct cmd_t command_defs[] = { "fingerprint", "Show current device fingerprint." }) CMD_EXAMPLES( "/omemo gen", - "/omemo start buddy@buddychat.org") + "/omemo start buddy@buddychat.org", + "/omemo trust c4f9c875-144d7a3b-0c4a05b6-ca3be51a-a037f329-0bd3ae62-07f99719-55559d2a") }, }; diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 70940f17..63c3df1b 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -8003,12 +8003,60 @@ cmd_omemo_fingerprint(ProfWin *window, const char *const command, gchar **args) return TRUE; } - char *fingerprint = omemo_own_fingerprint(); - char *formated_fingerprint = omemo_format_fingerprint(fingerprint); - cons_show("%s", formated_fingerprint); - + char *fingerprint = omemo_own_fingerprint(TRUE); + cons_show("%s", fingerprint); free(fingerprint); - free(formated_fingerprint); + + return TRUE; +#else + cons_show("This version of Profanity has not been built with OMEMO support enabled"); + return TRUE; +#endif +} + +gboolean +cmd_omemo_trust(ProfWin *window, const char *const command, gchar **args) +{ +#ifdef HAVE_OMEMO + if (connection_get_status() != JABBER_CONNECTED) { + cons_show("You must be connected with an account to load OMEMO information."); + return TRUE; + } + + if (!args[1]) { + cons_bad_cmd_usage(command); + return TRUE; + } + + if (!omemo_loaded()) { + win_println(window, THEME_DEFAULT, '!', "You have not generated or loaded a cryptographic materials, use '/omemo gen'"); + return TRUE; + } + + char *fingerprint; + char *barejid; + + /* Contact not provided */ + if (!args[2]) { + fingerprint = args[1]; + + if (window->type != WIN_CHAT) { + win_println(window, THEME_DEFAULT, '-', "You must be in a regular chat window to trust a device without providing the contact."); + return TRUE; + } + + ProfChatWin *chatwin = (ProfChatWin*)window; + assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); + barejid = chatwin->barejid; + } else { + char *contact = args[2]; + barejid = roster_barejid_from_name(contact); + if (barejid == NULL) { + barejid = contact; + } + } + + omemo_trust(barejid, fingerprint); return TRUE; #else diff --git a/src/command/cmd_funcs.h b/src/command/cmd_funcs.h index 4809f703..8a11881b 100644 --- a/src/command/cmd_funcs.h +++ b/src/command/cmd_funcs.h @@ -217,5 +217,6 @@ gboolean cmd_form_field(ProfWin *window, char *tag, gchar **args); gboolean cmd_omemo_gen(ProfWin *window, const char *const command, gchar **args); gboolean cmd_omemo_start(ProfWin *window, const char *const command, gchar **args); gboolean cmd_omemo_fingerprint(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_omemo_trust(ProfWin *window, const char *const command, gchar **args); #endif diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c index d649ff7e..3cae3315 100644 --- a/src/omemo/omemo.c +++ b/src/omemo/omemo.c @@ -12,15 +12,16 @@ #include #include "config/account.h" +#include "config/files.h" #include "log.h" -#include "omemo/store.h" #include "omemo/crypto.h" #include "omemo/omemo.h" +#include "omemo/store.h" #include "ui/ui.h" -#include "xmpp/xmpp.h" +#include "ui/window_list.h" #include "xmpp/connection.h" #include "xmpp/omemo.h" -#include "config/files.h" +#include "xmpp/xmpp.h" static gboolean loaded; @@ -33,6 +34,10 @@ static void omemo_log(int level, const char *message, size_t len, void *user_dat static gboolean handle_own_device_list(const char *const jid, GList *device_list); static gboolean handle_device_list_start_session(const char *const jid, GList *device_list); static void free_omemo_key(omemo_key_t *key); +static char * omemo_fingerprint(ec_public_key *identity, gboolean formatted); +static unsigned char *omemo_fingerprint_decode(const char *const fingerprint, size_t *len); +static void cache_device_identity(const char *const jid, uint32_t device_id, ec_public_key *identity); +static void g_hash_table_free(GHashTable *hash_table); typedef gboolean (*OmemoDeviceListHandler)(const char *const jid, GList *device_list); @@ -56,6 +61,7 @@ struct omemo_context_t { GKeyFile *identity_keyfile; GString *sessions_filename; GKeyFile *sessions_keyfile; + GHashTable *known_devices; }; static omemo_context omemo_ctx; @@ -63,7 +69,7 @@ static omemo_context omemo_ctx; void omemo_init(void) { - log_info("Initialising OMEMO"); + log_info("OMEMO: initialising"); signal_crypto_provider crypto_provider = { .random_func = omemo_random_func, .hmac_sha256_init_func = omemo_hmac_sha256_init_func, @@ -155,6 +161,7 @@ omemo_init(void) loaded = FALSE; omemo_ctx.device_list = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)g_list_free); omemo_ctx.device_list_handler = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL); + omemo_ctx.known_devices = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)g_hash_table_free); } void @@ -182,9 +189,9 @@ omemo_on_connect(ProfAccount *account) if (res == -1) { char *errmsg = strerror(errno); if (errmsg) { - log_error("Error creating directory: %s, %s", basedir->str, errmsg); + log_error("OMEMO: error creating directory: %s, %s", basedir->str, errmsg); } else { - log_error("Error creating directory: %s", basedir->str); + log_error("OMEMO: creating directory: %s", basedir->str); } } @@ -270,9 +277,10 @@ omemo_generate_short_term_crypto_materials(ProfAccount *account) void omemo_start_session(const char *const barejid) { - log_info("Start OMEMO session with %s", barejid); + log_info("OMEMO: start session with %s", barejid); GList *device_list = g_hash_table_lookup(omemo_ctx.device_list, barejid); if (!device_list) { + log_info("OMEMO: missing device list for %s", barejid); omemo_devicelist_request(barejid); g_hash_table_insert(omemo_ctx.device_list_handler, strdup(barejid), handle_device_list_start_session); return; @@ -393,7 +401,7 @@ omemo_identity_keyfile_save(void) GError *error = NULL; if (!g_key_file_save_to_file(omemo_ctx.identity_keyfile, omemo_ctx.identity_filename->str, &error)) { - log_error("Error saving OMEMO identity to: %s, %s", omemo_ctx.identity_filename->str, error->message); + log_error("OMEMO: error saving identity to: %s, %s", omemo_ctx.identity_filename->str, error->message); } } @@ -409,7 +417,7 @@ omemo_sessions_keyfile_save(void) GError *error = NULL; if (!g_key_file_save_to_file(omemo_ctx.sessions_keyfile, omemo_ctx.sessions_filename->str, &error)) { - log_error("Error saving OMEMO sessions to: %s, %s", omemo_ctx.sessions_filename->str, error->message); + log_error("OMEMO: error saving sessions to: %s, %s", omemo_ctx.sessions_filename->str, error->message); } } @@ -426,8 +434,26 @@ omemo_start_device_session(const char *const jid, uint32_t device_id, .device_id = device_id, }; + ec_public_key *identity_key; + curve_decode_point(&identity_key, identity_key_raw, identity_key_len, omemo_ctx.signal); + cache_device_identity(jid, device_id, identity_key); + + gboolean trusted = is_trusted_identity(&address, (uint8_t *)identity_key_raw, identity_key_len, &omemo_ctx.identity_key_store); + + ProfChatWin *chatwin = wins_get_chat(jid); + if (chatwin) { + char *fingerprint = omemo_fingerprint(identity_key, TRUE); + + win_println((ProfWin *)chatwin, THEME_DEFAULT, '-', "Available device identity: %s%s", fingerprint, trusted ? " (trusted)" : ""); + free(fingerprint); + } + + if (!trusted) { + goto out; + } + if (!contains_session(&address, omemo_ctx.session_store)) { - log_info("Create OMEMO session with %s device %d", jid, device_id); + int res; session_pre_key_bundle *bundle; signal_protocol_address *address; @@ -437,7 +463,11 @@ omemo_start_device_session(const char *const jid, uint32_t device_id, address->device_id = device_id; session_builder *builder; - session_builder_create(&builder, omemo_ctx.store, address, omemo_ctx.signal); + res = session_builder_create(&builder, omemo_ctx.store, address, omemo_ctx.signal); + if (res != 0) { + log_error("OMEMO: cannot create session builder for %s device %d", jid, device_id); + goto out; + } int prekey_index; gcry_randomize(&prekey_index, sizeof(int), GCRY_STRONG_RANDOM); @@ -448,14 +478,24 @@ omemo_start_device_session(const char *const jid, uint32_t device_id, curve_decode_point(&prekey_public, prekey->data, prekey->length, omemo_ctx.signal); ec_public_key *signed_prekey; curve_decode_point(&signed_prekey, signed_prekey_raw, signed_prekey_len, omemo_ctx.signal); - ec_public_key *identity_key; - curve_decode_point(&identity_key, identity_key_raw, identity_key_len, omemo_ctx.signal); - session_pre_key_bundle_create(&bundle, 0, device_id, prekey->id, prekey_public, signed_prekey_id, signed_prekey, signature, signature_len, identity_key); - session_builder_process_pre_key_bundle(builder, bundle); + res = session_pre_key_bundle_create(&bundle, 0, device_id, prekey->id, prekey_public, signed_prekey_id, signed_prekey, signature, signature_len, identity_key); + if (res != 0) { + log_error("OMEMO: cannot create pre key bundle for %s device %d", jid, device_id); + goto out; + } - g_list_free_full(prekeys, (GDestroyNotify)free_omemo_key); + res = session_builder_process_pre_key_bundle(builder, bundle); + if (res != 0) { + log_error("OMEMO: cannot process pre key bundle for %s device %d", jid, device_id); + goto out; + } + + log_info("OMEMO: create session with %s device %d", jid, device_id); } + +out: + g_list_free_full(prekeys, (GDestroyNotify)free_omemo_key); } gboolean @@ -492,6 +532,7 @@ omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean res = aes128gcm_encrypt(ciphertext, &ciphertext_len, tag, &tag_len, (const unsigned char * const)message, strlen(message), iv, key); if (res != 0) { + log_error("OMEMO: cannot encrypt message"); return FALSE; } @@ -505,16 +546,20 @@ omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean ciphertext_message *ciphertext; session_cipher *cipher; signal_protocol_address address = { - chatwin->barejid, strlen(chatwin->barejid), GPOINTER_TO_INT(device_ids_iter->data) + .name = chatwin->barejid, + .name_len = strlen(chatwin->barejid), + .device_id = GPOINTER_TO_INT(device_ids_iter->data) }; res = session_cipher_create(&cipher, omemo_ctx.store, &address, omemo_ctx.signal); if (res != 0) { + log_error("OMEMO: cannot create cipher for %s device id %d", address.name, address.device_id); continue; } res = session_cipher_encrypt(cipher, key_tag, AES128_GCM_KEY_LENGTH + AES128_GCM_TAG_LENGTH, &ciphertext); if (res != 0) { + log_error("OMEMO: cannot encrypt key for %s device id %d", address.name, address.device_id); continue; } signal_buffer *buffer = ciphertext_message_get_serialized(ciphertext); @@ -531,16 +576,20 @@ omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean ciphertext_message *ciphertext; session_cipher *cipher; signal_protocol_address address = { - barejid, strlen(barejid), GPOINTER_TO_INT(device_ids_iter->data) + .name = barejid, + .name_len = strlen(barejid), + .device_id = GPOINTER_TO_INT(device_ids_iter->data) }; res = session_cipher_create(&cipher, omemo_ctx.store, &address, omemo_ctx.signal); if (res != 0) { + log_error("OMEMO: cannot create cipher for %s device id %d", address.name, address.device_id); continue; } res = session_cipher_encrypt(cipher, key_tag, AES128_GCM_KEY_LENGTH + AES128_GCM_TAG_LENGTH, &ciphertext); if (res != 0) { + log_error("OMEMO: cannot encrypt key for %s device id %d", address.name, address.device_id); continue; } signal_buffer *buffer = ciphertext_message_get_serialized(ciphertext); @@ -583,21 +632,26 @@ omemo_on_message_recv(const char *const from, uint32_t sid, } if (!key) { + log_warning("OMEMO: Received a message with no corresponding key"); return NULL; } session_cipher *cipher; signal_buffer *plaintext_key; signal_protocol_address address = { - from, strlen(from), sid + .name = from, + .name_len = strlen(from), + .device_id = sid }; res = session_cipher_create(&cipher, omemo_ctx.store, &address, omemo_ctx.signal); if (res != 0) { + log_error("OMEMO: cannot create session cipher"); return NULL; } if (key->prekey) { + log_debug("OMEMO: decrypting message with prekey"); pre_key_signal_message *message; pre_key_signal_message_deserialize(&message, key->data, key->length, omemo_ctx.signal); @@ -618,11 +672,13 @@ omemo_on_message_recv(const char *const from, uint32_t sid, /* Try to decrypt message anyway, it will fail */ res = session_cipher_decrypt_pre_key_signal_message(cipher, message, NULL, &plaintext_key); } else { + log_debug("OMEMO: decrypting message with existing session"); signal_message *message; signal_message_deserialize(&message, key->data, key->length, omemo_ctx.signal); res = session_cipher_decrypt_signal_message(cipher, message, NULL, &plaintext_key); } if (res != 0) { + log_debug("OMEMO: cannot to decrypt message key"); return NULL; } @@ -647,13 +703,12 @@ omemo_on_message_recv(const char *const from, uint32_t sid, plaintext[plaintext_len] = '\0'; return (char *)plaintext; - } char * omemo_format_fingerprint(const char *const fingerprint) { - char *output = malloc(strlen(fingerprint) + strlen(fingerprint) / 8 + 1); + char *output = malloc(strlen(fingerprint) + strlen(fingerprint) / 8); int i, j; for (i = 0, j = 0; i < strlen(fingerprint); i++) { @@ -663,42 +718,134 @@ omemo_format_fingerprint(const char *const fingerprint) output[j++] = fingerprint[i]; } - output[strlen(fingerprint) + strlen(fingerprint) / 8] = '\0'; + output[j] = '\0'; return output; } char * -omemo_own_fingerprint() +omemo_own_fingerprint(gboolean formatted) { - signal_buffer *public = omemo_ctx.identity_key_store.public; - /* Skip first byte corresponding to signal base type */ - return omemo_fingerprint(signal_buffer_data(public) + 1, signal_buffer_len(public) - 1); + ec_public_key *identity = ratchet_identity_key_pair_get_public(omemo_ctx.identity_key_pair); + return omemo_fingerprint(identity, formatted); } -char * -omemo_fingerprint(const unsigned char *const identity_key_public, size_t len) +static char * +omemo_fingerprint(ec_public_key *identity, gboolean formatted) { int i; - char *fingerprint = malloc(len * 2 + 1); + signal_buffer *identity_public_key; + + ec_public_key_serialize(&identity_public_key, identity); + size_t identity_public_key_len = signal_buffer_len(identity_public_key); + unsigned char *identity_public_key_data = signal_buffer_data(identity_public_key); + + /* Skip first byte corresponding to signal DJB_TYPE */ + identity_public_key_len--; + identity_public_key_data = &identity_public_key_data[1]; - for (i = 0; i < len; i++) { - fingerprint[i * 2] = (identity_key_public[i] & 0xf0) >> 4; - fingerprint[i * 2] += 0x30; - if (fingerprint[i * 2] > 0x39) { + char *fingerprint = malloc(identity_public_key_len * 2 + 1); + + for (i = 0; i < identity_public_key_len; i++) { + fingerprint[i * 2] = (identity_public_key_data[i] & 0xf0) >> 4; + fingerprint[i * 2] += '0'; + if (fingerprint[i * 2] > '9') { fingerprint[i * 2] += 0x27; } - fingerprint[(i * 2) + 1] = identity_key_public[i] & 0x0f; - fingerprint[(i * 2) + 1] += 0x30; - if (fingerprint[(i * 2) + 1] > 0x39) { + fingerprint[(i * 2) + 1] = identity_public_key_data[i] & 0x0f; + fingerprint[(i * 2) + 1] += '0'; + if (fingerprint[(i * 2) + 1] > '9') { fingerprint[(i * 2) + 1] += 0x27; } } - fingerprint[len * 2] = '\0'; + fingerprint[i * 2] = '\0'; + signal_buffer_free(identity_public_key); + + if (!formatted) { + return fingerprint; + } else { + char *formatted_fingerprint = omemo_format_fingerprint(fingerprint); + free(fingerprint); + return formatted_fingerprint; + } +} + +static unsigned char * +omemo_fingerprint_decode(const char *const fingerprint, size_t *len) +{ + unsigned char *output = malloc(strlen(fingerprint) / 2 + 1); + + int i; + int j; + for (i = 0, j = 0; i < strlen(fingerprint);) { + if (!g_ascii_isxdigit(fingerprint[i])) { + i++; + continue; + } + + output[j] = g_ascii_xdigit_value(fingerprint[i++]) << 4; + output[j] |= g_ascii_xdigit_value(fingerprint[i++]); + j++; + } + + *len = j; - return fingerprint; + return output; +} + +void +omemo_trust(const char *const jid, const char *const fingerprint_formatted) +{ + size_t len; + + GHashTable *known_identities = g_hash_table_lookup(omemo_ctx.known_devices, jid); + if (!known_identities) { + log_warning("OMEMO: cannot trust unknown device: %s", fingerprint_formatted); + cons_show("Cannot trust unknown device: %s", fingerprint_formatted); + return; + } + + /* Unformat fingerprint */ + char *fingerprint = malloc(strlen(fingerprint_formatted)); + int i; + int j; + for (i = 0, j = 0; fingerprint_formatted[i] != '\0'; i++) { + if (!g_ascii_isxdigit(fingerprint_formatted[i])) { + continue; + } + fingerprint[j++] = fingerprint_formatted[i]; + } + + fingerprint[j] = '\0'; + + uint32_t device_id = GPOINTER_TO_INT(g_hash_table_lookup(known_identities, fingerprint)); + free(fingerprint); + + if (!device_id) { + log_warning("OMEMO: cannot trust unknown device: %s", fingerprint_formatted); + cons_show("Cannot trust unknown device: %s", fingerprint_formatted); + return; + } + + /* TODO should not hardcode DJB_TYPE here + * should instead store identity key in known_identities along with + * device_id */ + signal_protocol_address address = { + .name = jid, + .name_len = strlen(jid), + .device_id = device_id, + }; + unsigned char *fingerprint_raw = omemo_fingerprint_decode(fingerprint_formatted, &len); + unsigned char djb_type[] = {'\x05'}; + signal_buffer *buffer = signal_buffer_create(djb_type, 1); + buffer = signal_buffer_append(buffer, fingerprint_raw, len); + save_identity(&address, signal_buffer_data(buffer), signal_buffer_len(buffer), &omemo_ctx.identity_key_store); + free(fingerprint_raw); + signal_buffer_free(buffer); + + omemo_bundle_request(jid, device_id, omemo_start_device_session_handle_bundle, free, strdup(jid)); } static void @@ -843,3 +990,24 @@ load_sessions(void) } } } + +static void +cache_device_identity(const char *const jid, uint32_t device_id, ec_public_key *identity) +{ + GHashTable *known_identities = g_hash_table_lookup(omemo_ctx.known_devices, jid); + if (!known_identities) { + known_identities = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL); + g_hash_table_insert(omemo_ctx.known_devices, strdup(jid), known_identities); + } + + char *fingerprint = omemo_fingerprint(identity, FALSE); + log_info("OMEMO: cache identity for %s:%d: %s", jid, device_id, fingerprint); + g_hash_table_insert(known_identities, fingerprint, GINT_TO_POINTER(device_id)); +} + +static void +g_hash_table_free(GHashTable *hash_table) +{ + g_hash_table_remove_all(hash_table); + g_hash_table_unref(hash_table); +} diff --git a/src/omemo/omemo.h b/src/omemo/omemo.h index 72d3d3aa..5be0e0cd 100644 --- a/src/omemo/omemo.h +++ b/src/omemo/omemo.h @@ -30,9 +30,9 @@ GKeyFile *omemo_identity_keyfile(void); void omemo_identity_keyfile_save(void); GKeyFile *omemo_sessions_keyfile(void); void omemo_sessions_keyfile_save(void); -char *omemo_fingerprint(const unsigned char *const identity_key_public, size_t len); char *omemo_format_fingerprint(const char *const fingerprint); -char *omemo_own_fingerprint(); +char *omemo_own_fingerprint(gboolean formatted); +void omemo_trust(const char *const jid, const char *const fingerprint); void omemo_start_session(const char *const barejid); void omemo_start_device_session(const char *const jid, uint32_t device_id, GList *prekeys, uint32_t signed_prekey_id, const unsigned char *const signed_prekey, size_t signed_prekey_len, const unsigned char *const signature, size_t signature_len, const unsigned char *const identity_key, size_t identity_key_len); -- cgit 1.4.1-2-gfad0 From 2622c2d21a1f120cb39800b8c96b6e5ce916589b Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Wed, 13 Mar 2019 19:43:07 +0140 Subject: Add OMEMO untrust command --- src/command/cmd_ac.c | 1 + src/command/cmd_defs.c | 4 +++- src/command/cmd_funcs.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ src/command/cmd_funcs.h | 1 + src/omemo/omemo.c | 22 +++++++++++++++++++++ src/omemo/omemo.h | 1 + 6 files changed, 80 insertions(+), 1 deletion(-) (limited to 'src/command/cmd_ac.c') diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index ce66d507..588c8b4f 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -580,6 +580,7 @@ cmd_ac_init(void) autocomplete_add(omemo_ac, "gen"); autocomplete_add(omemo_ac, "start"); autocomplete_add(omemo_ac, "trust"); + autocomplete_add(omemo_ac, "untrust"); autocomplete_add(omemo_ac, "fingerprint"); connect_property_ac = autocomplete_new(); diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 200a46d3..70e4595e 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -2336,6 +2336,7 @@ static struct cmd_t command_defs[] = { "gen", cmd_omemo_gen }, { "start", cmd_omemo_start }, { "trust", cmd_omemo_trust }, + { "untrust", cmd_omemo_untrust }, { "fingerprint", cmd_omemo_fingerprint }) CMD_NOMAINFUNC CMD_TAGS( @@ -2355,7 +2356,8 @@ static struct cmd_t command_defs[] = CMD_EXAMPLES( "/omemo gen", "/omemo start buddy@buddychat.org", - "/omemo trust c4f9c875-144d7a3b-0c4a05b6-ca3be51a-a037f329-0bd3ae62-07f99719-55559d2a") + "/omemo trust c4f9c875-144d7a3b-0c4a05b6-ca3be51a-a037f329-0bd3ae62-07f99719-55559d2a", + "/omemo untrust c4f9c875-144d7a3b-0c4a05b6-ca3be51a-a037f329-0bd3ae62-07f99719-55559d2a") }, }; diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index ba55243c..572c0b96 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -8065,3 +8065,55 @@ cmd_omemo_trust(ProfWin *window, const char *const command, gchar **args) return TRUE; #endif } + +gboolean +cmd_omemo_untrust(ProfWin *window, const char *const command, gchar **args) +{ +#ifdef HAVE_OMEMO + if (connection_get_status() != JABBER_CONNECTED) { + cons_show("You must be connected with an account to load OMEMO information."); + return TRUE; + } + + if (!args[1]) { + cons_bad_cmd_usage(command); + return TRUE; + } + + if (!omemo_loaded()) { + win_println(window, THEME_DEFAULT, '!', "You have not generated or loaded a cryptographic materials, use '/omemo gen'"); + return TRUE; + } + + char *fingerprint; + char *barejid; + + /* Contact not provided */ + if (!args[2]) { + fingerprint = args[1]; + + if (window->type != WIN_CHAT) { + win_println(window, THEME_DEFAULT, '-', "You must be in a regular chat window to trust a device without providing the contact."); + return TRUE; + } + + ProfChatWin *chatwin = (ProfChatWin*)window; + assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); + barejid = chatwin->barejid; + } else { + fingerprint = args[2]; + char *contact = args[1]; + barejid = roster_barejid_from_name(contact); + if (barejid == NULL) { + barejid = contact; + } + } + + omemo_untrust(barejid, fingerprint); + + return TRUE; +#else + cons_show("This version of Profanity has not been built with OMEMO support enabled"); + return TRUE; +#endif +} diff --git a/src/command/cmd_funcs.h b/src/command/cmd_funcs.h index 8a11881b..efa8cd83 100644 --- a/src/command/cmd_funcs.h +++ b/src/command/cmd_funcs.h @@ -218,5 +218,6 @@ gboolean cmd_omemo_gen(ProfWin *window, const char *const command, gchar **args) gboolean cmd_omemo_start(ProfWin *window, const char *const command, gchar **args); gboolean cmd_omemo_fingerprint(ProfWin *window, const char *const command, gchar **args); gboolean cmd_omemo_trust(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_omemo_untrust(ProfWin *window, const char *const command, gchar **args); #endif diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c index b45e1834..fceb0363 100644 --- a/src/omemo/omemo.c +++ b/src/omemo/omemo.c @@ -857,6 +857,28 @@ omemo_trust(const char *const jid, const char *const fingerprint_formatted) omemo_bundle_request(jid, device_id, omemo_start_device_session_handle_bundle, free, strdup(jid)); } +void +omemo_untrust(const char *const jid, const char *const fingerprint_formatted) +{ + size_t len; + unsigned char *fingerprint = omemo_fingerprint_decode(fingerprint_formatted, &len); + + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init(&iter, omemo_ctx.identity_key_store.trusted); + while (g_hash_table_iter_next(&iter, &key, &value)) { + signal_buffer *buffer = value; + unsigned char *original = signal_buffer_data(buffer); + /* Skip DJB_TYPE byte */ + original++; + if ((signal_buffer_len(buffer) - 1) == len && memcmp(original, fingerprint, len) == 0) { + g_hash_table_remove(omemo_ctx.identity_key_store.trusted, key); + } + } + free(fingerprint); +} + static void lock(void *user_data) { diff --git a/src/omemo/omemo.h b/src/omemo/omemo.h index 5be0e0cd..7f9b7992 100644 --- a/src/omemo/omemo.h +++ b/src/omemo/omemo.h @@ -33,6 +33,7 @@ void omemo_sessions_keyfile_save(void); char *omemo_format_fingerprint(const char *const fingerprint); char *omemo_own_fingerprint(gboolean formatted); void omemo_trust(const char *const jid, const char *const fingerprint); +void omemo_untrust(const char *const jid, const char *const fingerprint); void omemo_start_session(const char *const barejid); void omemo_start_device_session(const char *const jid, uint32_t device_id, GList *prekeys, uint32_t signed_prekey_id, const unsigned char *const signed_prekey, size_t signed_prekey_len, const unsigned char *const signature, size_t signature_len, const unsigned char *const identity_key, size_t identity_key_len); -- cgit 1.4.1-2-gfad0 From bc541cb8ac6be40a2ee1e38a99de7cf144361a2a Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Tue, 19 Mar 2019 17:10:20 +0100 Subject: Add OMEMO end command --- src/command/cmd_ac.c | 1 + src/command/cmd_defs.c | 3 +++ src/command/cmd_funcs.c | 41 +++++++++++++++++++++++++++++++++++++++++ src/command/cmd_funcs.h | 1 + 4 files changed, 46 insertions(+) (limited to 'src/command/cmd_ac.c') diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index 588c8b4f..8db9c035 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -579,6 +579,7 @@ cmd_ac_init(void) omemo_ac = autocomplete_new(); autocomplete_add(omemo_ac, "gen"); autocomplete_add(omemo_ac, "start"); + autocomplete_add(omemo_ac, "end"); autocomplete_add(omemo_ac, "trust"); autocomplete_add(omemo_ac, "untrust"); autocomplete_add(omemo_ac, "fingerprint"); diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 70e4595e..2d4ae061 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -2335,6 +2335,7 @@ static struct cmd_t command_defs[] = CMD_SUBFUNCS( { "gen", cmd_omemo_gen }, { "start", cmd_omemo_start }, + { "end", cmd_omemo_end }, { "trust", cmd_omemo_trust }, { "untrust", cmd_omemo_untrust }, { "fingerprint", cmd_omemo_fingerprint }) @@ -2346,12 +2347,14 @@ static struct cmd_t command_defs[] = "/omemo gen", "/omemo start []", "/omemo trust [] ", + "/omemo end", "/omemo fingerprint") CMD_DESC( "Omemo commands to manage keys, and perform encryption during chat sessions.") CMD_ARGS( { "gen", "Generate OMEMO crytographic materials for current account." }, { "start []", "Start an OMEMO session with contact, or current recipient if omitted." }, + { "end", "End the current OMEMO session," }, { "fingerprint", "Show current device fingerprint." }) CMD_EXAMPLES( "/omemo gen", diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index f21da6e7..49e20744 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -7995,6 +7995,47 @@ cmd_omemo_start(ProfWin *window, const char *const command, gchar **args) #endif } +gboolean +cmd_omemo_end(ProfWin *window, const char *const command, gchar **args) +{ +#ifdef HAVE_OMEMO + if (connection_get_status() != JABBER_CONNECTED) { + cons_show("You must be connected with an account to load OMEMO information."); + return TRUE; + } + + if (window->type == WIN_CHAT) { + ProfChatWin *chatwin = (ProfChatWin*)window; + assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); + + if (!chatwin->is_omemo) { + win_println(window, THEME_DEFAULT, '!', "You are not currently in an OMEMO session."); + return TRUE; + } + + chatwin->is_omemo = FALSE; + } else if (window->type == WIN_MUC) { + ProfMucWin *mucwin = (ProfMucWin*)window; + assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK); + + if (!mucwin->is_omemo) { + win_println(window, THEME_DEFAULT, '!', "You are not currently in an OMEMO session."); + return TRUE; + } + + mucwin->is_omemo = FALSE; + } else { + win_println(window, THEME_DEFAULT, '-', "You must be in a regular chat window to start an OMEMO session."); + return TRUE; + } + + return TRUE; +#else + cons_show("This version of Profanity has not been built with OMEMO support enabled"); + return TRUE; +#endif +} + gboolean cmd_omemo_fingerprint(ProfWin *window, const char *const command, gchar **args) { diff --git a/src/command/cmd_funcs.h b/src/command/cmd_funcs.h index efa8cd83..21e7a51f 100644 --- a/src/command/cmd_funcs.h +++ b/src/command/cmd_funcs.h @@ -216,6 +216,7 @@ gboolean cmd_form_field(ProfWin *window, char *tag, gchar **args); gboolean cmd_omemo_gen(ProfWin *window, const char *const command, gchar **args); gboolean cmd_omemo_start(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_omemo_end(ProfWin *window, const char *const command, gchar **args); gboolean cmd_omemo_fingerprint(ProfWin *window, const char *const command, gchar **args); gboolean cmd_omemo_trust(ProfWin *window, const char *const command, gchar **args); gboolean cmd_omemo_untrust(ProfWin *window, const char *const command, gchar **args); -- cgit 1.4.1-2-gfad0 From 306706bd2efa61f44a9234241d5de60c8e286abd Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Fri, 22 Mar 2019 19:20:23 +0140 Subject: Add OMEMO log command --- src/command/cmd_ac.c | 14 ++++++++++++++ src/command/cmd_defs.c | 4 ++++ src/command/cmd_funcs.c | 30 ++++++++++++++++++++++++++++++ src/command/cmd_funcs.h | 1 + 4 files changed, 49 insertions(+) (limited to 'src/command/cmd_ac.c') diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index 8db9c035..86ef6ba9 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -159,6 +159,7 @@ static Autocomplete otr_ac; static Autocomplete otr_log_ac; static Autocomplete otr_policy_ac; static Autocomplete omemo_ac; +static Autocomplete omemo_log_ac; static Autocomplete connect_property_ac; static Autocomplete tls_property_ac; static Autocomplete alias_ac; @@ -578,12 +579,18 @@ cmd_ac_init(void) omemo_ac = autocomplete_new(); autocomplete_add(omemo_ac, "gen"); + autocomplete_add(omemo_ac, "log"); autocomplete_add(omemo_ac, "start"); autocomplete_add(omemo_ac, "end"); autocomplete_add(omemo_ac, "trust"); autocomplete_add(omemo_ac, "untrust"); autocomplete_add(omemo_ac, "fingerprint"); + omemo_log_ac = autocomplete_new(); + autocomplete_add(omemo_log_ac, "on"); + autocomplete_add(omemo_log_ac, "off"); + autocomplete_add(omemo_log_ac, "redact"); + connect_property_ac = autocomplete_new(); autocomplete_add(connect_property_ac, "server"); autocomplete_add(connect_property_ac, "port"); @@ -1063,6 +1070,7 @@ cmd_ac_reset(ProfWin *window) autocomplete_reset(otr_log_ac); autocomplete_reset(otr_policy_ac); autocomplete_reset(omemo_ac); + autocomplete_reset(omemo_log_ac); autocomplete_reset(connect_property_ac); autocomplete_reset(tls_property_ac); autocomplete_reset(alias_ac); @@ -1191,6 +1199,7 @@ cmd_ac_uninit(void) autocomplete_free(otr_log_ac); autocomplete_free(otr_policy_ac); autocomplete_free(omemo_ac); + autocomplete_free(omemo_log_ac); autocomplete_free(connect_property_ac); autocomplete_free(tls_property_ac); autocomplete_free(alias_ac); @@ -2144,6 +2153,11 @@ _omemo_autocomplete(ProfWin *window, const char *const input, gboolean previous) } } + found = autocomplete_param_with_ac(input, "/omemo log", omemo_log_ac, TRUE, previous); + if (found) { + return found; + } + found = autocomplete_param_with_ac(input, "/omemo", omemo_ac, TRUE, previous); if (found) { return found; diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 2d4ae061..311b404e 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -2334,6 +2334,7 @@ static struct cmd_t command_defs[] = parse_args, 1, 3, NULL, CMD_SUBFUNCS( { "gen", cmd_omemo_gen }, + { "log", cmd_omemo_log }, { "start", cmd_omemo_start }, { "end", cmd_omemo_end }, { "trust", cmd_omemo_trust }, @@ -2345,6 +2346,7 @@ static struct cmd_t command_defs[] = CMD_TAG_UI) CMD_SYN( "/omemo gen", + "/omemo log on|off|redact", "/omemo start []", "/omemo trust [] ", "/omemo end", @@ -2355,6 +2357,8 @@ static struct cmd_t command_defs[] = { "gen", "Generate OMEMO crytographic materials for current account." }, { "start []", "Start an OMEMO session with contact, or current recipient if omitted." }, { "end", "End the current OMEMO session," }, + { "log on|off", "Enable or disable plaintext logging of OMEMO encrypted messages." }, + { "log redact", "Log OMEMO encrypted messages, but replace the contents with [redacted]. This is the default." }, { "fingerprint", "Show current device fingerprint." }) CMD_EXAMPLES( "/omemo gen", diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 49e20744..d254960d 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -7995,6 +7995,36 @@ cmd_omemo_start(ProfWin *window, const char *const command, gchar **args) #endif } +gboolean +cmd_omemo_log(ProfWin *window, const char *const command, gchar **args) +{ +#ifdef HAVE_OMEMO + char *choice = args[1]; + if (g_strcmp0(choice, "on") == 0) { + prefs_set_string(PREF_OMEMO_LOG, "on"); + cons_show("OMEMO messages will be logged as plaintext."); + if (!prefs_get_boolean(PREF_CHLOG)) { + cons_show("Chat logging is currently disabled, use '/chlog on' to enable."); + } + } else if (g_strcmp0(choice, "off") == 0) { + prefs_set_string(PREF_OMEMO_LOG, "off"); + cons_show("OMEMO message logging disabled."); + } else if (g_strcmp0(choice, "redact") == 0) { + prefs_set_string(PREF_OMEMO_LOG, "redact"); + cons_show("OMEMO messages will be logged as '[redacted]'."); + if (!prefs_get_boolean(PREF_CHLOG)) { + cons_show("Chat logging is currently disabled, use '/chlog on' to enable."); + } + } else { + cons_bad_cmd_usage(command); + } + return TRUE; +#else + cons_show("This version of Profanity has not been built with OMEMO support enabled"); + return TRUE; +#endif +} + gboolean cmd_omemo_end(ProfWin *window, const char *const command, gchar **args) { diff --git a/src/command/cmd_funcs.h b/src/command/cmd_funcs.h index 21e7a51f..3f3385a5 100644 --- a/src/command/cmd_funcs.h +++ b/src/command/cmd_funcs.h @@ -215,6 +215,7 @@ gboolean cmd_wins_swap(ProfWin *window, const char *const command, gchar **args) gboolean cmd_form_field(ProfWin *window, char *tag, gchar **args); gboolean cmd_omemo_gen(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_omemo_log(ProfWin *window, const char *const command, gchar **args); gboolean cmd_omemo_start(ProfWin *window, const char *const command, gchar **args); gboolean cmd_omemo_end(ProfWin *window, const char *const command, gchar **args); gboolean cmd_omemo_fingerprint(ProfWin *window, const char *const command, gchar **args); -- cgit 1.4.1-2-gfad0 From 3d8f47a72416ff4b1ca64bf66071a62e4661d036 Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Mon, 25 Mar 2019 18:30:46 +0140 Subject: Use /omemo fingerprint to show contact fingerprints Don't print fingerprints when they are received --- src/command/cmd_ac.c | 5 ++++ src/command/cmd_defs.c | 4 +-- src/command/cmd_funcs.c | 46 +++++++++++++++++++++++++++++--- src/omemo/omemo.c | 71 ++++++++++++++++++++++++++++++------------------- src/omemo/omemo.h | 2 ++ 5 files changed, 96 insertions(+), 32 deletions(-) (limited to 'src/command/cmd_ac.c') diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index 86ef6ba9..9584543e 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -2153,6 +2153,11 @@ _omemo_autocomplete(ProfWin *window, const char *const input, gboolean previous) } } + found = autocomplete_param_with_func(input, "/omemo fingerprint", roster_contact_autocomplete, previous); + if (found) { + return found; + } + found = autocomplete_param_with_ac(input, "/omemo log", omemo_log_ac, TRUE, previous); if (found) { return found; diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 311b404e..5a3e6873 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -2350,7 +2350,7 @@ static struct cmd_t command_defs[] = "/omemo start []", "/omemo trust [] ", "/omemo end", - "/omemo fingerprint") + "/omemo fingerprint []") CMD_DESC( "Omemo commands to manage keys, and perform encryption during chat sessions.") CMD_ARGS( @@ -2359,7 +2359,7 @@ static struct cmd_t command_defs[] = { "end", "End the current OMEMO session," }, { "log on|off", "Enable or disable plaintext logging of OMEMO encrypted messages." }, { "log redact", "Log OMEMO encrypted messages, but replace the contents with [redacted]. This is the default." }, - { "fingerprint", "Show current device fingerprint." }) + { "fingerprint", "Show contact fingerprints." }) CMD_EXAMPLES( "/omemo gen", "/omemo start buddy@buddychat.org", diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index d254960d..fcbb10b8 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -8080,9 +8080,49 @@ cmd_omemo_fingerprint(ProfWin *window, const char *const command, gchar **args) return TRUE; } - char *fingerprint = omemo_own_fingerprint(TRUE); - cons_show("%s", fingerprint); - free(fingerprint); + Jid *jid; + if (!args[1]) { + if (window->type == WIN_CONSOLE) { + char *fingerprint = omemo_own_fingerprint(TRUE); + cons_show("Your OMEMO fingerprint: %s", fingerprint); + free(fingerprint); + return TRUE; + } else if (window->type == WIN_CHAT) { + ProfChatWin *chatwin = (ProfChatWin*)window; + jid = jid_create(chatwin->barejid); + } else { + win_println(window, THEME_DEFAULT, '-', "You must be in a regular chat window to print fingerprint without providing the contact."); + return TRUE; + } + } else { + jid = jid_create(args[1]); + if (!jid) { + cons_show("%s is not a valid jid", args[1]); + return TRUE; + } + } + + GList *fingerprints = omemo_known_device_identities(jid->barejid); + GList *fingerprint; + + if (!fingerprints) { + win_println(window, THEME_DEFAULT, '-', "There is no known fingerprints for %s", jid->barejid); + return TRUE; + } + + for (fingerprint = fingerprints; fingerprint != NULL; fingerprint = fingerprint->next) { + char *formatted_fingerprint = omemo_format_fingerprint(fingerprint->data); + gboolean trusted = omemo_is_trusted_identity(jid->barejid, fingerprint->data); + + win_println(window, THEME_DEFAULT, '-', "%s's OMEMO fingerprint: %s%s", jid->barejid, formatted_fingerprint, trusted ? " (trusted)" : ""); + + free(formatted_fingerprint); + } + + g_list_free(fingerprints); + + win_println(window, THEME_DEFAULT, '-', "You can trust it with '/omemo trust '"); + win_println(window, THEME_DEFAULT, '-', "You can untrust it with '/omemo untrust '"); return TRUE; #else diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c index 8ec0554f..01eb6b67 100644 --- a/src/omemo/omemo.c +++ b/src/omemo/omemo.c @@ -496,32 +496,6 @@ omemo_start_device_session(const char *const jid, uint32_t device_id, gboolean trusted = is_trusted_identity(&address, (uint8_t *)identity_key_raw, identity_key_len, &omemo_ctx.identity_key_store); - Jid *ownjid = jid_create(connection_get_fulljid()); - if (g_strcmp0(jid, ownjid->barejid) == 0) { - char *fingerprint = omemo_fingerprint(identity_key, TRUE); - - cons_show("Available device identity for %s: %s%s", ownjid->barejid, fingerprint, trusted ? " (trusted)" : ""); - if (trusted) { - cons_show("You can untrust it with '/omemo untrust %s '", ownjid->barejid); - } else { - cons_show("You can trust it with '/omemo trust %s '", ownjid->barejid); - } - free(fingerprint); - } - - ProfChatWin *chatwin = wins_get_chat(jid); - if (chatwin) { - char *fingerprint = omemo_fingerprint(identity_key, TRUE); - - win_println((ProfWin *)chatwin, THEME_DEFAULT, '-', "Available device identity: %s%s", fingerprint, trusted ? " (trusted)" : ""); - if (trusted) { - win_println((ProfWin *)chatwin, THEME_DEFAULT, '-', "You can untrust it with '/omemo untrust '"); - } else { - win_println((ProfWin *)chatwin, THEME_DEFAULT, '-', "You can trust it with '/omemo trust '"); - } - free(fingerprint); - } - if (!trusted) { goto out; } @@ -570,7 +544,6 @@ omemo_start_device_session(const char *const jid, uint32_t device_id, out: SIGNAL_UNREF(identity_key); - jid_destroy(ownjid); } char * @@ -884,6 +857,50 @@ omemo_own_fingerprint(gboolean formatted) return omemo_fingerprint(identity, formatted); } +GList * +omemo_known_device_identities(const char *const jid) +{ + GHashTable *known_identities = g_hash_table_lookup(omemo_ctx.known_devices, jid); + if (!known_identities) { + return NULL; + } + + return g_hash_table_get_keys(known_identities); +} + +gboolean +omemo_is_trusted_identity(const char *const jid, const char *const fingerprint) +{ + GHashTable *known_identities = g_hash_table_lookup(omemo_ctx.known_devices, jid); + if (!known_identities) { + return FALSE; + } + + void *device_id = g_hash_table_lookup(known_identities, fingerprint); + if (!device_id) { + return FALSE; + } + + signal_protocol_address address = { + .name = jid, + .name_len = strlen(jid), + .device_id = GPOINTER_TO_INT(device_id), + }; + + size_t fingerprint_len; + unsigned char *fingerprint_raw = omemo_fingerprint_decode(fingerprint, &fingerprint_len); + unsigned char djb_type[] = {'\x05'}; + signal_buffer *buffer = signal_buffer_create(djb_type, 1); + buffer = signal_buffer_append(buffer, fingerprint_raw, fingerprint_len); + + gboolean trusted = is_trusted_identity(&address, signal_buffer_data(buffer), signal_buffer_len(buffer), &omemo_ctx.identity_key_store); + + free(fingerprint_raw); + signal_buffer_free(buffer); + + return trusted; +} + static char * omemo_fingerprint(ec_public_key *identity, gboolean formatted) { diff --git a/src/omemo/omemo.h b/src/omemo/omemo.h index e9e9cf8d..ec48e183 100644 --- a/src/omemo/omemo.h +++ b/src/omemo/omemo.h @@ -36,6 +36,8 @@ char *omemo_format_fingerprint(const char *const fingerprint); char *omemo_own_fingerprint(gboolean formatted); void omemo_trust(const char *const jid, const char *const fingerprint); void omemo_untrust(const char *const jid, const char *const fingerprint); +GList *omemo_known_device_identities(const char *const jid); +gboolean omemo_is_trusted_identity(const char *const jid, const char *const fingerprint); void omemo_start_session(const char *const barejid); void omemo_start_muc_sessions(const char *const roomjid); -- cgit 1.4.1-2-gfad0 From 678bff9169c81ed20c38698e132d7c8c6118763b Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Mon, 25 Mar 2019 19:07:36 +0140 Subject: Add fingerprint autocompletion --- src/command/cmd_ac.c | 26 ++++++++++++++++++++++++++ src/omemo/omemo.c | 22 +++++++++++++++++++++- src/omemo/omemo.h | 2 ++ 3 files changed, 49 insertions(+), 1 deletion(-) (limited to 'src/command/cmd_ac.c') diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index 9584543e..c700e51b 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -57,6 +57,10 @@ #include "pgp/gpg.h" #endif +#ifdef HAVE_OMEMO +#include "omemo/omemo.h" +#endif + static char* _sub_autocomplete(ProfWin *window, const char *const input, gboolean previous); static char* _notify_autocomplete(ProfWin *window, const char *const input, gboolean previous); static char* _theme_autocomplete(ProfWin *window, const char *const input, gboolean previous); @@ -999,6 +1003,9 @@ cmd_ac_reset(ProfWin *window) presence_reset_sub_request_search(); #ifdef HAVE_LIBGPGME p_gpg_autocomplete_key_reset(); +#endif +#ifdef HAVE_OMEMO + omemo_fingerprint_autocomplete_reset(); #endif autocomplete_reset(help_ac); autocomplete_reset(help_commands_ac); @@ -2158,6 +2165,25 @@ _omemo_autocomplete(ProfWin *window, const char *const input, gboolean previous) return found; } +#ifdef HAVE_OMEMO + if (window->type == WIN_CHAT) { + found = autocomplete_param_with_func(input, "/omemo trust", omemo_fingerprint_autocomplete, previous); + if (found) { + return found; + } + } else { + found = autocomplete_param_with_func(input, "/omemo trust", roster_contact_autocomplete, previous); + if (found) { + return found; + } + + found = autocomplete_param_no_with_func(input, "/omemo trust", 4, omemo_fingerprint_autocomplete, previous); + if (found) { + return found; + } + } +#endif + found = autocomplete_param_with_ac(input, "/omemo log", omemo_log_ac, TRUE, previous); if (found) { return found; diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c index 01eb6b67..1f48224e 100644 --- a/src/omemo/omemo.c +++ b/src/omemo/omemo.c @@ -63,6 +63,7 @@ struct omemo_context_t { GString *sessions_filename; GKeyFile *sessions_keyfile; GHashTable *known_devices; + Autocomplete fingerprint_ac; }; static omemo_context omemo_ctx; @@ -163,6 +164,8 @@ omemo_init(void) omemo_ctx.device_list = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)g_list_free); omemo_ctx.device_list_handler = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL); omemo_ctx.known_devices = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)g_hash_table_free); + + omemo_ctx.fingerprint_ac = autocomplete_new(); } void @@ -1114,6 +1117,18 @@ omemo_key_free(omemo_key_t *key) free(key); } +char* +omemo_fingerprint_autocomplete(const char *const search_str, gboolean previous) +{ + return autocomplete_complete(omemo_ctx.fingerprint_ac, search_str, FALSE, previous); +} + +void +omemo_fingerprint_autocomplete_reset(void) +{ + autocomplete_reset(omemo_ctx.fingerprint_ac); +} + static void load_identity(void) { @@ -1203,7 +1218,12 @@ cache_device_identity(const char *const jid, uint32_t device_id, ec_public_key * char *fingerprint = omemo_fingerprint(identity, FALSE); log_info("OMEMO: cache identity for %s:%d: %s", jid, device_id, fingerprint); - g_hash_table_insert(known_identities, fingerprint, GINT_TO_POINTER(device_id)); + g_hash_table_insert(known_identities, strdup(fingerprint), GINT_TO_POINTER(device_id)); + + char *formatted_fingerprint = omemo_format_fingerprint(fingerprint); + autocomplete_add(omemo_ctx.fingerprint_ac, formatted_fingerprint); + free(formatted_fingerprint); + free(fingerprint); } static void diff --git a/src/omemo/omemo.h b/src/omemo/omemo.h index ec48e183..bbd59b77 100644 --- a/src/omemo/omemo.h +++ b/src/omemo/omemo.h @@ -38,6 +38,8 @@ void omemo_trust(const char *const jid, const char *const fingerprint); void omemo_untrust(const char *const jid, const char *const fingerprint); GList *omemo_known_device_identities(const char *const jid); gboolean omemo_is_trusted_identity(const char *const jid, const char *const fingerprint); +char *omemo_fingerprint_autocomplete(const char *const search_str, gboolean previous); +void omemo_fingerprint_autocomplete_reset(void); void omemo_start_session(const char *const barejid); void omemo_start_muc_sessions(const char *const roomjid); -- cgit 1.4.1-2-gfad0 From 898302243e2890c0d2ffc6c48451718e43a85d23 Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Mon, 1 Apr 2019 13:14:46 +0200 Subject: Add clear_device_list command --- src/command/cmd_ac.c | 1 + src/command/cmd_defs.c | 11 +++++++---- src/command/cmd_funcs.c | 19 +++++++++++++++++++ src/command/cmd_funcs.h | 1 + 4 files changed, 28 insertions(+), 4 deletions(-) (limited to 'src/command/cmd_ac.c') diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index c700e51b..7b6a865b 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -589,6 +589,7 @@ cmd_ac_init(void) autocomplete_add(omemo_ac, "trust"); autocomplete_add(omemo_ac, "untrust"); autocomplete_add(omemo_ac, "fingerprint"); + autocomplete_add(omemo_ac, "clear_device_list"); omemo_log_ac = autocomplete_new(); autocomplete_add(omemo_log_ac, "on"); diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 5a3e6873..b1270f63 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -2339,7 +2339,8 @@ static struct cmd_t command_defs[] = { "end", cmd_omemo_end }, { "trust", cmd_omemo_trust }, { "untrust", cmd_omemo_untrust }, - { "fingerprint", cmd_omemo_fingerprint }) + { "fingerprint", cmd_omemo_fingerprint }, + { "clear_device_list", cmd_omemo_clear_device_list }) CMD_NOMAINFUNC CMD_TAGS( CMD_TAG_CHAT, @@ -2350,7 +2351,8 @@ static struct cmd_t command_defs[] = "/omemo start []", "/omemo trust [] ", "/omemo end", - "/omemo fingerprint []") + "/omemo fingerprint []", + "/omemo clear_device_list") CMD_DESC( "Omemo commands to manage keys, and perform encryption during chat sessions.") CMD_ARGS( @@ -2359,12 +2361,13 @@ static struct cmd_t command_defs[] = { "end", "End the current OMEMO session," }, { "log on|off", "Enable or disable plaintext logging of OMEMO encrypted messages." }, { "log redact", "Log OMEMO encrypted messages, but replace the contents with [redacted]. This is the default." }, - { "fingerprint", "Show contact fingerprints." }) + { "fingerprint", "Show contact fingerprints." }, + { "clear_device_list", "Clear your own device list on server side. Each client will reannounce itself when connected back."}) CMD_EXAMPLES( "/omemo gen", "/omemo start buddy@buddychat.org", "/omemo trust c4f9c875-144d7a3b-0c4a05b6-ca3be51a-a037f329-0bd3ae62-07f99719-55559d2a", - "/omemo untrust c4f9c875-144d7a3b-0c4a05b6-ca3be51a-a037f329-0bd3ae62-07f99719-55559d2a") + "/omemo untrust buddy@buddychat.org c4f9c875-144d7a3b-0c4a05b6-ca3be51a-a037f329-0bd3ae62-07f99719-55559d2a") }, }; diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 369a992f..c2696c31 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -87,6 +87,7 @@ #ifdef HAVE_OMEMO #include "omemo/omemo.h" +#include "xmpp/omemo.h" #endif #ifdef HAVE_GTK @@ -8268,3 +8269,21 @@ cmd_omemo_untrust(ProfWin *window, const char *const command, gchar **args) return TRUE; #endif } + +gboolean +cmd_omemo_clear_device_list(ProfWin *window, const char *const command, gchar **args) +{ +#ifdef HAVE_OMEMO + if (connection_get_status() != JABBER_CONNECTED) { + cons_show("You must be connected with an account to initialize OMEMO."); + return TRUE; + } + + omemo_devicelist_publish(NULL); + cons_show("Cleared OMEMO device list"); + return TRUE; +#else + cons_show("This version of Profanity has not been built with OMEMO support enabled"); + return TRUE; +#endif +} diff --git a/src/command/cmd_funcs.h b/src/command/cmd_funcs.h index 3f3385a5..3410075d 100644 --- a/src/command/cmd_funcs.h +++ b/src/command/cmd_funcs.h @@ -221,5 +221,6 @@ gboolean cmd_omemo_end(ProfWin *window, const char *const command, gchar **args) gboolean cmd_omemo_fingerprint(ProfWin *window, const char *const command, gchar **args); gboolean cmd_omemo_trust(ProfWin *window, const char *const command, gchar **args); gboolean cmd_omemo_untrust(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_omemo_clear_device_list(ProfWin *window, const char *const command, gchar **args); #endif -- cgit 1.4.1-2-gfad0 From e7be3a605bbb47e462265a379d48aad9cc565fc2 Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Mon, 1 Apr 2019 13:53:29 +0200 Subject: Add OMEMO in prefs command --- src/command/cmd_ac.c | 1 + src/command/cmd_defs.c | 5 +++-- src/command/cmd_funcs.c | 4 ++++ src/ui/console.c | 24 ++++++++++++++++++++++++ src/ui/ui.h | 1 + tests/unittests/ui/stub_ui.c | 1 + 6 files changed, 34 insertions(+), 2 deletions(-) (limited to 'src/command/cmd_ac.c') diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index 7b6a865b..0cc28bb3 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -244,6 +244,7 @@ cmd_ac_init(void) autocomplete_add(prefs_ac, "presence"); autocomplete_add(prefs_ac, "otr"); autocomplete_add(prefs_ac, "pgp"); + autocomplete_add(prefs_ac, "omemo"); notify_ac = autocomplete_new(); autocomplete_add(notify_ac, "chat"); diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index b1270f63..ab4112c7 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -2134,7 +2134,7 @@ static struct cmd_t command_defs[] = CMD_MAINFUNC(cmd_prefs) CMD_NOTAGS CMD_SYN( - "/prefs [ui|desktop|chat|log|conn|presence|otr|pgp]") + "/prefs [ui|desktop|chat|log|conn|presence|otr|pgp|omemo]") CMD_DESC( "Show preferences for different areas of functionality. " "Passing no arguments shows all preferences.") @@ -2146,7 +2146,8 @@ static struct cmd_t command_defs[] = { "conn", "Connection handling preferences." }, { "presence", "Chat presence preferences." }, { "otr", "Off The Record preferences." }, - { "pgp", "OpenPGP preferences." }) + { "pgp", "OpenPGP preferences." }, + { "omemo", "OMEMO preferences." }) CMD_NOEXAMPLES }, diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index c2696c31..e1f62ace 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -1679,6 +1679,10 @@ cmd_prefs(ProfWin *window, const char *const command, gchar **args) cons_show(""); cons_show_pgp_prefs(); cons_show(""); + } else if (strcmp(args[0], "omemo") == 0) { + cons_show(""); + cons_show_omemo_prefs(); + cons_show(""); } else { cons_bad_cmd_usage(command); } diff --git a/src/ui/console.c b/src/ui/console.c index e5c12158..260658c8 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -1998,6 +1998,28 @@ cons_show_pgp_prefs(void) cons_alert(); } +void +cons_show_omemo_prefs(void) +{ + cons_show("OMEMO preferences:"); + cons_show(""); + + char *log_value = prefs_get_string(PREF_OMEMO_LOG); + if (strcmp(log_value, "on") == 0) { + cons_show("OMEMO logging (/omemo log) : ON"); + } else if (strcmp(log_value, "off") == 0) { + cons_show("OMEMO logging (/omemo log) : OFF"); + } else { + cons_show("OMEMO logging (/omemo log) : Redacted"); + } + prefs_free_string(log_value); + + char ch = prefs_get_omemo_char(); + cons_show("OMEMO char (/omemo char) : %c", ch); + + cons_alert(); +} + void cons_show_themes(GSList *themes) { @@ -2072,6 +2094,8 @@ cons_prefs(void) cons_show(""); cons_show_pgp_prefs(); cons_show(""); + cons_show_omemo_prefs(); + cons_show(""); cons_alert(); } diff --git a/src/ui/ui.h b/src/ui/ui.h index e3cece81..79701a27 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -252,6 +252,7 @@ void cons_show_presence_prefs(void); void cons_show_connection_prefs(void); void cons_show_otr_prefs(void); void cons_show_pgp_prefs(void); +void cons_show_omemo_prefs(void); void cons_show_account(ProfAccount *account); void cons_debug(const char *const msg, ...); void cons_show_error(const char *const cmd, ...); diff --git a/tests/unittests/ui/stub_ui.c b/tests/unittests/ui/stub_ui.c index e08c3ce1..950036bc 100644 --- a/tests/unittests/ui/stub_ui.c +++ b/tests/unittests/ui/stub_ui.c @@ -338,6 +338,7 @@ void cons_show_presence_prefs(void) {} void cons_show_connection_prefs(void) {} void cons_show_otr_prefs(void) {} void cons_show_pgp_prefs(void) {} +void cons_show_omemo_prefs(void) {} void cons_show_account(ProfAccount *account) { -- cgit 1.4.1-2-gfad0