From c819a655a150ccc5e10d6304583b7e62f1a829a0 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Fri, 1 Jun 2018 21:26:35 +0200 Subject: OMEMO: remove omemo device from own list if bundle is broken --- .../messenger/crypto/axolotl/AxolotlService.java | 150 +++++++++++---------- 1 file changed, 80 insertions(+), 70 deletions(-) (limited to 'src/main/java/de/pixart/messenger/crypto/axolotl/AxolotlService.java') diff --git a/src/main/java/de/pixart/messenger/crypto/axolotl/AxolotlService.java b/src/main/java/de/pixart/messenger/crypto/axolotl/AxolotlService.java index d29d0c034..5d2982064 100644 --- a/src/main/java/de/pixart/messenger/crypto/axolotl/AxolotlService.java +++ b/src/main/java/de/pixart/messenger/crypto/axolotl/AxolotlService.java @@ -80,6 +80,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { private final Map fetchDeviceListStatus = new HashMap<>(); private final HashMap> fetchDeviceIdsMap = new HashMap<>(); private final SerialSingleThreadExecutor executor; + private final HashSet cleanedOwnDeviceIds = new HashSet<>(); private int numPublishTriesOnEmptyPep = 0; private boolean pepBroken = false; private int lastDeviceListNotificationHash = 0; @@ -104,7 +105,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } public boolean hasErrorFetchingDeviceList(List jids) { - for(Jid jid : jids) { + for (Jid jid : jids) { if (hasErrorFetchingDeviceList(jid)) { return true; } @@ -144,8 +145,8 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } private static class AxolotlAddressMap { - protected Map> map; protected final Object MAP_LOCK = new Object(); + protected Map> map; public AxolotlAddressMap() { this.map = new HashMap<>(); @@ -503,7 +504,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { axolotlStore.setFingerprintStatus(fp, fingerprintStatus.toUntrusted()); } - public void publishOwnDeviceIdIfNeeded() { + private void publishOwnDeviceIdIfNeeded() { if (pepBroken) { Log.d(Config.LOGTAG, getLogprefix(account) + "publishOwnDeviceIdIfNeeded called, but PEP is broken. Ignoring... "); return; @@ -545,7 +546,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { return devices; } - public void publishOwnDeviceId(Set deviceIds) { + private void publishOwnDeviceId(Set deviceIds) { Set deviceIdsCopy = new HashSet<>(deviceIds); Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "publishing own device ids"); if (deviceIdsCopy.isEmpty()) { @@ -597,11 +598,12 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } if (packet.getType() == IqPacket.TYPE.ERROR) { if (preConditionNotMet) { - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": device list pre condition still not met on second attempt"); + Log.d(Config.LOGTAG,account.getJid().asBareJid()+": device list pre condition still not met on second attempt"); } else if (error != null) { pepBroken = true; Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while publishing own device id" + packet.findChild("error")); } + } } } @@ -816,7 +818,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } } else if (packet.getType() == IqPacket.TYPE.ERROR) { if (preconditionNotMet) { - Log.d(Config.LOGTAG, getLogprefix(account) + "bundle precondition still not met after second attempt"); + Log.d(Config.LOGTAG,getLogprefix(account) + "bundle precondition still not met after second attempt"); } else { Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while publishing bundle: " + error); } @@ -1061,76 +1063,84 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { throw new AssertionError("We should NEVER build a session with ourselves. What happened here?!"); } - try { - IqPacket bundlesPacket = mXmppConnectionService.getIqGenerator().retrieveBundlesForDevice( - Jid.of(address.getName()), address.getDeviceId()); - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Retrieving bundle: " + bundlesPacket); - mXmppConnectionService.sendIqPacket(account, bundlesPacket, new OnIqPacketReceived() { - - @Override - public void onIqPacketReceived(Account account, IqPacket packet) { - if (packet.getType() == IqPacket.TYPE.TIMEOUT) { - fetchStatusMap.put(address, FetchStatus.TIMEOUT); - } else if (packet.getType() == IqPacket.TYPE.RESULT) { - Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received preKey IQ packet, processing..."); - final IqParser parser = mXmppConnectionService.getIqParser(); - final List preKeyBundleList = parser.preKeys(packet); - final PreKeyBundle bundle = parser.bundle(packet); - if (preKeyBundleList.isEmpty() || bundle == null) { - Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "preKey IQ packet invalid: " + packet); - fetchStatusMap.put(address, FetchStatus.ERROR); - finishBuildingSessionsFromPEP(address); - return; - } - Random random = new Random(); - final PreKeyBundle preKey = preKeyBundleList.get(random.nextInt(preKeyBundleList.size())); - if (preKey == null) { - //should never happen - fetchStatusMap.put(address, FetchStatus.ERROR); - finishBuildingSessionsFromPEP(address); - return; - } + final Jid jid = Jid.of(address.getName()); + final boolean oneOfOurs = jid.asBareJid().equals(account.getJid().asBareJid()); + IqPacket bundlesPacket = mXmppConnectionService.getIqGenerator().retrieveBundlesForDevice(jid, address.getDeviceId()); + mXmppConnectionService.sendIqPacket(account, bundlesPacket, (account, packet) -> { + if (packet.getType() == IqPacket.TYPE.TIMEOUT) { + fetchStatusMap.put(address, FetchStatus.TIMEOUT); + } else if (packet.getType() == IqPacket.TYPE.RESULT) { + Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Received preKey IQ packet, processing..."); + final IqParser parser = mXmppConnectionService.getIqParser(); + final List preKeyBundleList = parser.preKeys(packet); + final PreKeyBundle bundle = parser.bundle(packet); + if (preKeyBundleList.isEmpty() || bundle == null) { + Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "preKey IQ packet invalid: " + packet); + fetchStatusMap.put(address, FetchStatus.ERROR); + finishBuildingSessionsFromPEP(address); + return; + } + Random random = new Random(); + final PreKeyBundle preKey = preKeyBundleList.get(random.nextInt(preKeyBundleList.size())); + if (preKey == null) { + //should never happen + fetchStatusMap.put(address, FetchStatus.ERROR); + finishBuildingSessionsFromPEP(address); + return; + } - final PreKeyBundle preKeyBundle = new PreKeyBundle(0, address.getDeviceId(), - preKey.getPreKeyId(), preKey.getPreKey(), - bundle.getSignedPreKeyId(), bundle.getSignedPreKey(), - bundle.getSignedPreKeySignature(), bundle.getIdentityKey()); + final PreKeyBundle preKeyBundle = new PreKeyBundle(0, address.getDeviceId(), + preKey.getPreKeyId(), preKey.getPreKey(), + bundle.getSignedPreKeyId(), bundle.getSignedPreKey(), + bundle.getSignedPreKeySignature(), bundle.getIdentityKey()); - try { - SessionBuilder builder = new SessionBuilder(axolotlStore, address); - builder.process(preKeyBundle); - XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address, bundle.getIdentityKey()); - sessions.put(address, session); - if (Config.X509_VERIFICATION) { - verifySessionWithPEP(session); - } else { - FingerprintStatus status = getFingerprintTrust(CryptoHelper.bytesToHex(bundle.getIdentityKey().getPublicKey().serialize())); - FetchStatus fetchStatus; - if (status != null && status.isVerified()) { - fetchStatus = FetchStatus.SUCCESS_VERIFIED; - } else if (status != null && status.isTrusted()) { - fetchStatus = FetchStatus.SUCCESS_TRUSTED; - } else { - fetchStatus = FetchStatus.SUCCESS; - } - fetchStatusMap.put(address, fetchStatus); - finishBuildingSessionsFromPEP(address); - } - } catch (UntrustedIdentityException | InvalidKeyException e) { - Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Error building session for " + address + ": " - + e.getClass().getName() + ", " + e.getMessage()); - fetchStatusMap.put(address, FetchStatus.ERROR); - finishBuildingSessionsFromPEP(address); - } + try { + SessionBuilder builder = new SessionBuilder(axolotlStore, address); + builder.process(preKeyBundle); + XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address, bundle.getIdentityKey()); + sessions.put(address, session); + if (Config.X509_VERIFICATION) { + verifySessionWithPEP(session); } else { - fetchStatusMap.put(address, FetchStatus.ERROR); - Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while building session:" + packet.findChild("error")); + FingerprintStatus status = getFingerprintTrust(CryptoHelper.bytesToHex(bundle.getIdentityKey().getPublicKey().serialize())); + FetchStatus fetchStatus; + if (status != null && status.isVerified()) { + fetchStatus = FetchStatus.SUCCESS_VERIFIED; + } else if (status != null && status.isTrusted()) { + fetchStatus = FetchStatus.SUCCESS_TRUSTED; + } else { + fetchStatus = FetchStatus.SUCCESS; + } + fetchStatusMap.put(address, fetchStatus); finishBuildingSessionsFromPEP(address); } + } catch (UntrustedIdentityException | InvalidKeyException e) { + Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Error building session for " + address + ": " + + e.getClass().getName() + ", " + e.getMessage()); + fetchStatusMap.put(address, FetchStatus.ERROR); + finishBuildingSessionsFromPEP(address); + if (oneOfOurs && cleanedOwnDeviceIds.add(address.getDeviceId())) { + removeFromDeviceAnnouncement(address.getDeviceId()); + } } - }); - } catch (IllegalArgumentException e) { - Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Got address with invalid jid: " + address.getName()); + } else { + fetchStatusMap.put(address, FetchStatus.ERROR); + Element error = packet.findChild("error"); + boolean itemNotFound = error != null && error.hasChild("item-not-found"); + Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while building session:" + packet.findChild("error")); + finishBuildingSessionsFromPEP(address); + if (oneOfOurs && itemNotFound && cleanedOwnDeviceIds.add(address.getDeviceId())) { + removeFromDeviceAnnouncement(address.getDeviceId()); + } + } + }); + } + + private void removeFromDeviceAnnouncement(Integer id) { + HashSet temp = new HashSet<>(getOwnDeviceIds()); + if (temp.remove(id)) { + Log.d(Config.LOGTAG,account.getJid().asBareJid()+" remove own device id "+id+" from announcement. devices left:"+temp); + publishOwnDeviceId(temp); } } -- cgit v1.2.3