From a3c5cfd2f49df3663a221ca3544adaf1ad3d705f Mon Sep 17 00:00:00 2001 From: AsamK Date: Sat, 22 Jan 2022 13:21:56 +0100 Subject: [PATCH] Archive old sessions when an identity key has changed --- .../org/asamk/signal/manager/ManagerImpl.java | 18 ++++++++++++++++++ .../signal/manager/helper/IdentityHelper.java | 6 +----- .../signal/manager/helper/ProfileHelper.java | 19 ++++++------------- .../storage/identities/IdentityKeyStore.java | 9 +++++++++ 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java index aab5d230..a080b185 100644 --- a/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java @@ -86,6 +86,8 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; +import io.reactivex.rxjava3.disposables.CompositeDisposable; + public class ManagerImpl implements Manager { private final static Logger logger = LoggerFactory.getLogger(ManagerImpl.class); @@ -101,6 +103,7 @@ public class ManagerImpl implements Manager { private final Set weakHandlers = new HashSet<>(); private final Set messageHandlers = new HashSet<>(); private final List closedListeners = new ArrayList<>(); + private final CompositeDisposable disposable = new CompositeDisposable(); ManagerImpl( SignalAccount account, @@ -141,6 +144,20 @@ public class ManagerImpl implements Manager { this.notifyAll(); } }); + disposable.add(account.getIdentityKeyStore().getIdentityChanges().subscribe(recipientId -> { + logger.trace("Archiving old sessions"); + account.getSessionStore().archiveSessions(recipientId); + account.getSenderKeyStore().deleteSharedWith(recipientId); + final var profile = account.getRecipientStore().getProfile(recipientId); + if (profile != null) { + account.getRecipientStore() + .storeProfile(recipientId, + Profile.newBuilder(profile) + .withUnidentifiedAccessMode(Profile.UnidentifiedAccessMode.UNKNOWN) + .withLastUpdateTimestamp(0) + .build()); + } + })); } @Override @@ -982,6 +999,7 @@ public class ManagerImpl implements Manager { executor.shutdown(); dependencies.getSignalWebSocket().disconnect(); + disposable.dispose(); synchronized (closedListeners) { closedListeners.forEach(Runnable::run); diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/IdentityHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/IdentityHelper.java index f7ec4167..025971a9 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/IdentityHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/IdentityHelper.java @@ -110,11 +110,7 @@ public class IdentityHelper { ) { final var identityKey = identityFailure.getIdentityKey(); if (identityKey != null) { - final var newIdentity = account.getIdentityKeyStore().saveIdentity(recipientId, identityKey, new Date()); - if (newIdentity) { - account.getSessionStore().archiveSessions(recipientId); - account.getSenderKeyStore().deleteSharedWith(recipientId); - } + account.getIdentityKeyStore().saveIdentity(recipientId, identityKey, new Date()); } else { // Retrieve profile to get the current identity key from the server context.getProfileHelper().refreshRecipientProfile(recipientId); diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java index 20a81f7f..f1f5d1de 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java @@ -279,25 +279,18 @@ public final class ProfileHelper { .build(); } - logger.trace("Storing profile"); - account.getProfileStore().storeProfile(recipientId, newProfile); - try { logger.trace("Storing identity"); - var newIdentity = account.getIdentityKeyStore() - .saveIdentity(recipientId, - new IdentityKey(Base64.getDecoder().decode(encryptedProfile.getIdentityKey())), - new Date()); - - if (newIdentity) { - logger.trace("Archiving old sessions"); - account.getSessionStore().archiveSessions(recipientId); - account.getSenderKeyStore().deleteSharedWith(recipientId); - } + final var identityKey = new IdentityKey(Base64.getDecoder().decode(encryptedProfile.getIdentityKey())); + account.getIdentityKeyStore().saveIdentity(recipientId, identityKey, new Date()); } catch (InvalidKeyException ignored) { logger.warn("Got invalid identity key in profile for {}", context.getRecipientHelper().resolveSignalServiceAddress(recipientId).getIdentifier()); } + + logger.trace("Storing profile"); + account.getProfileStore().storeProfile(recipientId, newProfile); + logger.trace("Done handling retrieved profile"); }).doOnError(e -> { logger.warn("Failed to retrieve profile, ignoring: {}", e.getMessage()); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java index 31b717cd..2bc8307b 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java @@ -29,6 +29,9 @@ import java.util.Map; import java.util.Objects; import java.util.regex.Pattern; +import io.reactivex.rxjava3.subjects.PublishSubject; +import io.reactivex.rxjava3.subjects.Subject; + public class IdentityKeyStore implements org.whispersystems.libsignal.state.IdentityKeyStore { private final static Logger logger = LoggerFactory.getLogger(IdentityKeyStore.class); @@ -42,6 +45,7 @@ public class IdentityKeyStore implements org.whispersystems.libsignal.state.Iden private final IdentityKeyPair identityKeyPair; private final int localRegistrationId; private final TrustNewIdentity trustNewIdentity; + private final PublishSubject identityChanges = PublishSubject.create(); private boolean isRetryingDecryption = false; @@ -59,6 +63,10 @@ public class IdentityKeyStore implements org.whispersystems.libsignal.state.Iden this.trustNewIdentity = trustNewIdentity; } + public Subject getIdentityChanges() { + return identityChanges; + } + @Override public IdentityKeyPair getIdentityKeyPair() { return identityKeyPair; @@ -94,6 +102,7 @@ public class IdentityKeyStore implements org.whispersystems.libsignal.state.Iden logger.debug("Storing new identity for recipient {} with trust {}", recipientId, trustLevel); final var newIdentityInfo = new IdentityInfo(recipientId, identityKey, trustLevel, added); storeIdentityLocked(recipientId, newIdentityInfo); + identityChanges.onNext(recipientId); return true; } } -- 2.50.1