OMEMO: remove omemo device from own list if bundle is broken

This commit is contained in:
Daniel Gultsch 2018-05-28 22:08:20 +02:00
parent 9706c7e953
commit c8a0bf7090
1 changed files with 75 additions and 66 deletions

View File

@ -83,6 +83,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
private int numPublishTriesOnEmptyPep = 0; private int numPublishTriesOnEmptyPep = 0;
private boolean pepBroken = false; private boolean pepBroken = false;
private int lastDeviceListNotificationHash = 0; private int lastDeviceListNotificationHash = 0;
private final HashSet<Integer> cleanedOwnDeviceIds = new HashSet<>();
private Set<XmppAxolotlSession> postponedSessions = new HashSet<>(); //sessions stored here will receive after mam catchup treatment private Set<XmppAxolotlSession> postponedSessions = new HashSet<>(); //sessions stored here will receive after mam catchup treatment
private AtomicBoolean changeAccessMode = new AtomicBoolean(false); private AtomicBoolean changeAccessMode = new AtomicBoolean(false);
@ -503,7 +504,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
axolotlStore.setFingerprintStatus(fp, fingerprintStatus.toUntrusted()); axolotlStore.setFingerprintStatus(fp, fingerprintStatus.toUntrusted());
} }
public void publishOwnDeviceIdIfNeeded() { private void publishOwnDeviceIdIfNeeded() {
if (pepBroken) { if (pepBroken) {
Log.d(Config.LOGTAG, getLogprefix(account) + "publishOwnDeviceIdIfNeeded called, but PEP is broken. Ignoring... "); Log.d(Config.LOGTAG, getLogprefix(account) + "publishOwnDeviceIdIfNeeded called, but PEP is broken. Ignoring... ");
return; return;
@ -545,7 +546,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
return devices; return devices;
} }
public void publishOwnDeviceId(Set<Integer> deviceIds) { private void publishOwnDeviceId(Set<Integer> deviceIds) {
Set<Integer> deviceIdsCopy = new HashSet<>(deviceIds); Set<Integer> deviceIdsCopy = new HashSet<>(deviceIds);
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "publishing own device ids"); Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "publishing own device ids");
if (deviceIdsCopy.isEmpty()) { if (deviceIdsCopy.isEmpty()) {
@ -1062,76 +1063,84 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
throw new AssertionError("We should NEVER build a session with ourselves. What happened here?!"); throw new AssertionError("We should NEVER build a session with ourselves. What happened here?!");
} }
try { final Jid jid = Jid.of(address.getName());
IqPacket bundlesPacket = mXmppConnectionService.getIqGenerator().retrieveBundlesForDevice( final boolean oneOfOurs = jid.asBareJid().equals(account.getJid().asBareJid());
Jid.of(address.getName()), address.getDeviceId()); IqPacket bundlesPacket = mXmppConnectionService.getIqGenerator().retrieveBundlesForDevice(jid, address.getDeviceId());
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Retrieving bundle: " + bundlesPacket); mXmppConnectionService.sendIqPacket(account, bundlesPacket, (account, packet) -> {
mXmppConnectionService.sendIqPacket(account, bundlesPacket, new OnIqPacketReceived() { 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<PreKeyBundle> 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;
}
@Override final PreKeyBundle preKeyBundle = new PreKeyBundle(0, address.getDeviceId(),
public void onIqPacketReceived(Account account, IqPacket packet) { preKey.getPreKeyId(), preKey.getPreKey(),
if (packet.getType() == IqPacket.TYPE.TIMEOUT) { bundle.getSignedPreKeyId(), bundle.getSignedPreKey(),
fetchStatusMap.put(address, FetchStatus.TIMEOUT); bundle.getSignedPreKeySignature(), bundle.getIdentityKey());
} 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<PreKeyBundle> 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(), try {
preKey.getPreKeyId(), preKey.getPreKey(), SessionBuilder builder = new SessionBuilder(axolotlStore, address);
bundle.getSignedPreKeyId(), bundle.getSignedPreKey(), builder.process(preKeyBundle);
bundle.getSignedPreKeySignature(), bundle.getIdentityKey()); XmppAxolotlSession session = new XmppAxolotlSession(account, axolotlStore, address, bundle.getIdentityKey());
sessions.put(address, session);
try { if (Config.X509_VERIFICATION) {
SessionBuilder builder = new SessionBuilder(axolotlStore, address); verifySessionWithPEP(session);
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);
}
} else { } else {
fetchStatusMap.put(address, FetchStatus.ERROR); FingerprintStatus status = getFingerprintTrust(CryptoHelper.bytesToHex(bundle.getIdentityKey().getPublicKey().serialize()));
Log.d(Config.LOGTAG, getLogprefix(account) + "Error received while building session:" + packet.findChild("error")); 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); 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());
}
} }
}); } else {
} catch (IllegalArgumentException e) { fetchStatusMap.put(address, FetchStatus.ERROR);
Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Got address with invalid jid: " + address.getName()); 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<Integer> 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);
} }
} }