From 08a5088c16ae0bd69adc42ac6489adde3a9ad13f Mon Sep 17 00:00:00 2001 From: fiaxh Date: Fri, 2 Aug 2019 03:15:12 +0200 Subject: Rework encryption enabling logic + UI --- plugins/omemo/src/logic/manager.vala | 29 ++++++-- plugins/omemo/src/logic/trust_manager.vala | 111 ++++++++++++++--------------- 2 files changed, 79 insertions(+), 61 deletions(-) (limited to 'plugins/omemo/src/logic') diff --git a/plugins/omemo/src/logic/manager.vala b/plugins/omemo/src/logic/manager.vala index b8862ab8..3fe41a35 100644 --- a/plugins/omemo/src/logic/manager.vala +++ b/plugins/omemo/src/logic/manager.vala @@ -149,7 +149,7 @@ public class Manager : StreamInteractionModule, Object { } if (state.waiting_other_devicelists > 0 && message.counterpart != null) { foreach(Jid jid in get_occupants(((!)message.counterpart).bare_jid, conversation.account)) { - module.request_user_devicelist((!)stream, jid); + module.request_user_devicelist.begin((!)stream, jid); } } } @@ -161,7 +161,7 @@ public class Manager : StreamInteractionModule, Object { XmppStream? stream = stream_interactor.get_stream(account); if(stream == null) return; - stream_interactor.module_manager.get_module(account, StreamModule.IDENTITY).request_user_devicelist((!)stream, jid); + stream_interactor.module_manager.get_module(account, StreamModule.IDENTITY).request_user_devicelist.begin((!)stream, jid); } private void on_account_added(Account account) { @@ -171,7 +171,7 @@ public class Manager : StreamInteractionModule, Object { } private void on_stream_negotiated(Account account, XmppStream stream) { - stream_interactor.module_manager.get_module(account, StreamModule.IDENTITY).request_user_devicelist(stream, account.bare_jid); + stream_interactor.module_manager.get_module(account, StreamModule.IDENTITY).request_user_devicelist.begin(stream, account.bare_jid); } private void on_device_list_loaded(Account account, Jid jid, ArrayList device_list) { @@ -352,7 +352,7 @@ public class Manager : StreamInteractionModule, Object { if (stream == null) return; StreamModule? module = ((!)stream).get_module(StreamModule.IDENTITY); if(module == null) return; - module.request_user_devicelist(stream, account.bare_jid); + module.request_user_devicelist.begin(stream, account.bare_jid); } } @@ -376,6 +376,27 @@ public class Manager : StreamInteractionModule, Object { return trust_manager.is_known_address(conversation.account, conversation.counterpart.bare_jid); } + public async bool ensure_get_keys_for_conversation(Conversation conversation) { + if (stream_interactor.get_module(MucManager.IDENTITY).is_private_room(conversation.account, conversation.counterpart)) { + foreach (Jid offline_member in stream_interactor.get_module(MucManager.IDENTITY).get_offline_members(conversation.counterpart, conversation.account)) { + bool ok = yield ensure_get_keys_for_jid(conversation.account, offline_member); + if (!ok) { + return false; + } + } + return true; + } + + return yield ensure_get_keys_for_jid(conversation.account, conversation.counterpart.bare_jid); + } + + public async bool ensure_get_keys_for_jid(Account account, Jid jid) { + if (trust_manager.is_known_address(account, jid)) return true; + XmppStream? stream = stream_interactor.get_stream(account); + var device_list = yield stream_interactor.module_manager.get_module(account, StreamModule.IDENTITY).request_user_devicelist((!)stream, jid); + return device_list.size > 0; + } + public static void start(StreamInteractor stream_interactor, Database db, TrustManager trust_manager) { Manager m = new Manager(stream_interactor, db, trust_manager); stream_interactor.add_module(m); diff --git a/plugins/omemo/src/logic/trust_manager.vala b/plugins/omemo/src/logic/trust_manager.vala index 7758de75..ded7e995 100644 --- a/plugins/omemo/src/logic/trust_manager.vala +++ b/plugins/omemo/src/logic/trust_manager.vala @@ -269,70 +269,67 @@ public class TrustManager { if (sid <= 0) return false; foreach (StanzaNode key_node in header.get_subnodes("key")) { if (key_node.get_attribute_int("rid") == store.local_registration_id) { - try { - string? payload = encrypted.get_deep_string_content("payload"); - string? iv_node = header.get_deep_string_content("iv"); - string? key_node_content = key_node.get_string_content(); - if (payload == null || iv_node == null || key_node_content == null) continue; - uint8[] key; - uint8[] ciphertext = Base64.decode((!)payload); - uint8[] iv = Base64.decode((!)iv_node); - Gee.List possible_jids = new ArrayList(); - if (conversation.type_ == Conversation.Type.CHAT) { - possible_jids.add(stanza.from); + + string? payload = encrypted.get_deep_string_content("payload"); + string? iv_node = header.get_deep_string_content("iv"); + string? key_node_content = key_node.get_string_content(); + if (payload == null || iv_node == null || key_node_content == null) continue; + uint8[] key; + uint8[] ciphertext = Base64.decode((!)payload); + uint8[] iv = Base64.decode((!)iv_node); + Gee.List possible_jids = new ArrayList(); + if (conversation.type_ == Conversation.Type.CHAT) { + possible_jids.add(stanza.from); + } else { + Jid? real_jid = message.real_jid; + if (real_jid != null) { + possible_jids.add(real_jid); } else { - Jid? real_jid = message.real_jid; - if (real_jid != null) { - possible_jids.add(real_jid); - } else { - // If we don't know the device name (MUC history w/o MAM), test decryption with all keys with fitting device id - foreach (Row row in db.identity_meta.get_with_device_id(sid)) { - possible_jids.add(new Jid(row[db.identity_meta.address_name])); - } + // If we don't know the device name (MUC history w/o MAM), test decryption with all keys with fitting device id + foreach (Row row in db.identity_meta.get_with_device_id(sid)) { + possible_jids.add(new Jid(row[db.identity_meta.address_name])); } } + } - foreach (Jid possible_jid in possible_jids) { - try { - Address address = new Address(possible_jid.bare_jid.to_string(), header.get_attribute_int("sid")); - if (key_node.get_attribute_bool("prekey")) { - PreKeySignalMessage msg = Plugin.get_context().deserialize_pre_key_signal_message(Base64.decode((!)key_node_content)); - SessionCipher cipher = store.create_session_cipher(address); - key = cipher.decrypt_pre_key_signal_message(msg); - } else { - SignalMessage msg = Plugin.get_context().deserialize_signal_message(Base64.decode((!)key_node_content)); - SessionCipher cipher = store.create_session_cipher(address); - key = cipher.decrypt_signal_message(msg); - } - //address.device_id = 0; // TODO: Hack to have address obj live longer - - if (key.length >= 32) { - int authtaglength = key.length - 16; - uint8[] new_ciphertext = new uint8[ciphertext.length + authtaglength]; - uint8[] new_key = new uint8[16]; - Memory.copy(new_ciphertext, ciphertext, ciphertext.length); - Memory.copy((uint8*)new_ciphertext + ciphertext.length, (uint8*)key + 16, authtaglength); - Memory.copy(new_key, key, 16); - ciphertext = new_ciphertext; - key = new_key; - } - - message.body = arr_to_str(aes_decrypt(Cipher.AES_GCM_NOPADDING, key, iv, ciphertext)); - message_device_id_map[message] = address.device_id; - message.encryption = Encryption.OMEMO; - flag.decrypted = true; - } catch (Error e) { - continue; + foreach (Jid possible_jid in possible_jids) { + try { + Address address = new Address(possible_jid.bare_jid.to_string(), header.get_attribute_int("sid")); + if (key_node.get_attribute_bool("prekey")) { + PreKeySignalMessage msg = Plugin.get_context().deserialize_pre_key_signal_message(Base64.decode((!)key_node_content)); + SessionCipher cipher = store.create_session_cipher(address); + key = cipher.decrypt_pre_key_signal_message(msg); + } else { + SignalMessage msg = Plugin.get_context().deserialize_signal_message(Base64.decode((!)key_node_content)); + SessionCipher cipher = store.create_session_cipher(address); + key = cipher.decrypt_signal_message(msg); } - - // If we figured out which real jid a message comes from due to decryption working, save it - if (conversation.type_ == Conversation.Type.GROUPCHAT && message.real_jid == null) { - message.real_jid = possible_jid; + //address.device_id = 0; // TODO: Hack to have address obj live longer + + if (key.length >= 32) { + int authtaglength = key.length - 16; + uint8[] new_ciphertext = new uint8[ciphertext.length + authtaglength]; + uint8[] new_key = new uint8[16]; + Memory.copy(new_ciphertext, ciphertext, ciphertext.length); + Memory.copy((uint8*)new_ciphertext + ciphertext.length, (uint8*)key + 16, authtaglength); + Memory.copy(new_key, key, 16); + ciphertext = new_ciphertext; + key = new_key; } - break; + + message.body = arr_to_str(aes_decrypt(Cipher.AES_GCM_NOPADDING, key, iv, ciphertext)); + message_device_id_map[message] = address.device_id; + message.encryption = Encryption.OMEMO; + flag.decrypted = true; + } catch (Error e) { + continue; } - } catch (Error e) { - warning(@"Signal error while decrypting message: $(e.message)\n"); + + // If we figured out which real jid a message comes from due to decryption working, save it + if (conversation.type_ == Conversation.Type.GROUPCHAT && message.real_jid == null) { + message.real_jid = possible_jid; + } + break; } } } -- cgit v1.2.3-70-g09d2