diff --git a/omemo/backend/liteaxolotlstore.py b/omemo/backend/liteaxolotlstore.py index e6643eb..a3b1f3a 100644 --- a/omemo/backend/liteaxolotlstore.py +++ b/omemo/backend/liteaxolotlstore.py @@ -497,6 +497,12 @@ class LiteAxolotlStore(AxolotlStore): return self._con.execute(query, jids).fetchall() + def hasUndecidedFingerprints(self, jid): + query = '''SELECT public_key as "public_key [pk]" FROM identities + WHERE recipient_id = ? AND trust = ?''' + result = self._con.execute(query, (jid, Trust.UNDECIDED)).fetchall() + return True if result else False + def getTrustedFingerprints(self, jid): query = '''SELECT public_key as "public_key [pk]" FROM identities WHERE recipient_id = ? AND trust = ?''' diff --git a/omemo/backend/state.py b/omemo/backend/state.py index a7a0eae..3f0c1df 100644 --- a/omemo/backend/state.py +++ b/omemo/backend/state.py @@ -88,7 +88,7 @@ class OmemoState(DeviceManager): ik) session.processPreKeyBundle(prekey_bundle) - return self._get_session_cipher(jid, device_id) + self._get_session_cipher(jid, device_id) @property def storage(self): diff --git a/omemo/modules/omemo.py b/omemo/modules/omemo.py index 1aadd38..9dd51d6 100644 --- a/omemo/modules/omemo.py +++ b/omemo/modules/omemo.py @@ -110,6 +110,7 @@ class OMEMO(BaseModule): self._omemo_groupchats = set() self._muc_temp_store = {} self._query_for_bundles = [] + self._device_bundle_querys = [] self._query_for_devicelists = [] def get_own_jid(self, stripped=False): @@ -356,6 +357,14 @@ class OMEMO(BaseModule): self._omemo_groupchats.add(room) log.info('Room config change: non-anonymous') + def _check_for_missing_sessions(self, jid): + devices_without_session = self.backend.devices_without_sessions(jid) + for device_id in devices_without_session: + if device_id in self._device_bundle_querys: + continue + self._device_bundle_querys.append(device_id) + self.request_bundle(jid, device_id) + def are_keys_missing(self, contact_jid): """ Checks if devicekeys are missing and queries the bundles @@ -420,16 +429,19 @@ class OMEMO(BaseModule): self._account, jid, device_id, bundle) return - if self.backend.build_session(jid, device_id, bundle): - log.info('%s => session created for: %s', - self._account, jid) - # Trigger dialog to trust new Fingerprints if - # the Chat Window is Open - ctrl = app.interface.msg_win_mgr.get_control( - jid, self._account) - if ctrl: - app.nec.push_incoming_event( - NetworkEvent('omemo-new-fingerprint', chat_control=ctrl)) + self.backend.build_session(jid, device_id, bundle) + log.info('%s => session created for: %s', + self._account, jid) + # TODO: In MUC we should send a groupchat message + self._send_key_transport_message('chat', jid, [device_id]) + + # Trigger dialog to trust new Fingerprints if + # the Chat Window is Open + ctrl = app.interface.msg_win_mgr.get_control( + jid, self._account) + if ctrl: + app.nec.push_incoming_event( + NetworkEvent('omemo-new-fingerprint', chat_control=ctrl)) def set_devicelist(self): log.info('%s => Publishing own devicelist: %s', @@ -440,24 +452,26 @@ class OMEMO(BaseModule): self.backend.update_devicelist(self._own_jid, [self.backend.own_device]) self.set_devicelist() - def request_devicelist(self, jid=None, fetch_bundle=False): + def request_devicelist(self, jid=None): + if jid is None: + jid = self._own_jid + if jid in self._query_for_devicelists: return self._nbxmpp('OMEMO').request_devicelist( jid, callback=self._devicelist_received, - user_data=(jid, fetch_bundle)) + user_data=jid) self._query_for_devicelists.append(jid) - def _devicelist_received(self, devicelist, user_data): - jid, fetch_bundle = user_data + def _devicelist_received(self, devicelist, jid): if is_error_result(devicelist): log.info('%s => Devicelist request failed: %s %s', self._account, jid, devicelist) devicelist = [] - self._process_devicelist_update(jid, devicelist, fetch_bundle) + self._process_devicelist_update(jid, devicelist) @event_node(nbxmpp.NS_OMEMO_TEMP_DL) def _devicelist_notification_received(self, _con, _stanza, properties): @@ -465,9 +479,9 @@ class OMEMO(BaseModule): if not properties.pubsub_event.empty: devicelist = properties.pubsub_event.data - self._process_devicelist_update(str(properties.jid), devicelist, False) + self._process_devicelist_update(str(properties.jid), devicelist) - def _process_devicelist_update(self, jid, devicelist, fetch_bundle): + def _process_devicelist_update(self, jid, devicelist): own_devices = jid is None or self._con.get_own_jid().bareMatch(jid) if own_devices: jid = self._own_jid @@ -485,8 +499,7 @@ class OMEMO(BaseModule): # overwritten by some other client self.set_devicelist() - elif fetch_bundle: - self.are_keys_missing(jid) + self._check_for_missing_sessions(jid) @staticmethod def _debug_print_stanza(stanza): diff --git a/omemo/plugin.py b/omemo/plugin.py index 5cbda40..d143953 100644 --- a/omemo/plugin.py +++ b/omemo/plugin.py @@ -75,6 +75,7 @@ if not ERROR_MSG: class UserMessages(IntEnum): QUERY_DEVICES = 0 NO_FINGERPRINTS = 1 + UNDECIDED_FINGERPRINTS = 2 class OmemoPlugin(GajimPlugin): @@ -258,16 +259,16 @@ class OmemoPlugin(GajimPlugin): self.print_message(chat_control, UserMessages.NO_FINGERPRINTS) else: # check if we have devices for the contact - if not omemo.backend.get_devices(contact.jid): + if not omemo.backend.get_devices(contact.jid, without_self=True): omemo.request_devicelist(contact.jid, True) self.print_message(chat_control, UserMessages.QUERY_DEVICES) chat_control.sendmessage = False return # check if bundles are missing for some devices - if omemo.are_keys_missing(contact.jid): - log.info('%s => No Trusted Fingerprints for %s', + if omemo.backend.storage.hasUndecidedFingerprints(contact.jid): + log.info('%s => Undecided Fingerprints for %s', account, contact.jid) - self.print_message(chat_control, UserMessages.NO_FINGERPRINTS) + self.print_message(chat_control, UserMessages.UNDECIDED_FINGERPRINTS) chat_control.sendmessage = False else: log.debug('%s => Sending Message to %s', @@ -323,6 +324,8 @@ class OmemoPlugin(GajimPlugin): elif kind == UserMessages.NO_FINGERPRINTS: msg = _('To send an encrypted message, you have to ' 'first trust the fingerprint of your contact!') + elif kind == UserMessages.UNDECIDED_FINGERPRINTS: + msg = _('You have undecided fingerprints') if msg is None: return chat_control.print_conversation_line(msg, 'status', '', None)