mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 02:20:39 +00:00
Archive old sessions when an identity key has changed
This commit is contained in:
parent
7d935749aa
commit
a3c5cfd2f4
4 changed files with 34 additions and 18 deletions
|
@ -86,6 +86,8 @@ import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||||
|
|
||||||
public class ManagerImpl implements Manager {
|
public class ManagerImpl implements Manager {
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(ManagerImpl.class);
|
private final static Logger logger = LoggerFactory.getLogger(ManagerImpl.class);
|
||||||
|
@ -101,6 +103,7 @@ public class ManagerImpl implements Manager {
|
||||||
private final Set<ReceiveMessageHandler> weakHandlers = new HashSet<>();
|
private final Set<ReceiveMessageHandler> weakHandlers = new HashSet<>();
|
||||||
private final Set<ReceiveMessageHandler> messageHandlers = new HashSet<>();
|
private final Set<ReceiveMessageHandler> messageHandlers = new HashSet<>();
|
||||||
private final List<Runnable> closedListeners = new ArrayList<>();
|
private final List<Runnable> closedListeners = new ArrayList<>();
|
||||||
|
private final CompositeDisposable disposable = new CompositeDisposable();
|
||||||
|
|
||||||
ManagerImpl(
|
ManagerImpl(
|
||||||
SignalAccount account,
|
SignalAccount account,
|
||||||
|
@ -141,6 +144,20 @@ public class ManagerImpl implements Manager {
|
||||||
this.notifyAll();
|
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
|
@Override
|
||||||
|
@ -982,6 +999,7 @@ public class ManagerImpl implements Manager {
|
||||||
executor.shutdown();
|
executor.shutdown();
|
||||||
|
|
||||||
dependencies.getSignalWebSocket().disconnect();
|
dependencies.getSignalWebSocket().disconnect();
|
||||||
|
disposable.dispose();
|
||||||
|
|
||||||
synchronized (closedListeners) {
|
synchronized (closedListeners) {
|
||||||
closedListeners.forEach(Runnable::run);
|
closedListeners.forEach(Runnable::run);
|
||||||
|
|
|
@ -110,11 +110,7 @@ public class IdentityHelper {
|
||||||
) {
|
) {
|
||||||
final var identityKey = identityFailure.getIdentityKey();
|
final var identityKey = identityFailure.getIdentityKey();
|
||||||
if (identityKey != null) {
|
if (identityKey != null) {
|
||||||
final var newIdentity = account.getIdentityKeyStore().saveIdentity(recipientId, identityKey, new Date());
|
account.getIdentityKeyStore().saveIdentity(recipientId, identityKey, new Date());
|
||||||
if (newIdentity) {
|
|
||||||
account.getSessionStore().archiveSessions(recipientId);
|
|
||||||
account.getSenderKeyStore().deleteSharedWith(recipientId);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Retrieve profile to get the current identity key from the server
|
// Retrieve profile to get the current identity key from the server
|
||||||
context.getProfileHelper().refreshRecipientProfile(recipientId);
|
context.getProfileHelper().refreshRecipientProfile(recipientId);
|
||||||
|
|
|
@ -279,25 +279,18 @@ public final class ProfileHelper {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.trace("Storing profile");
|
|
||||||
account.getProfileStore().storeProfile(recipientId, newProfile);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
logger.trace("Storing identity");
|
logger.trace("Storing identity");
|
||||||
var newIdentity = account.getIdentityKeyStore()
|
final var identityKey = new IdentityKey(Base64.getDecoder().decode(encryptedProfile.getIdentityKey()));
|
||||||
.saveIdentity(recipientId,
|
account.getIdentityKeyStore().saveIdentity(recipientId, identityKey, new Date());
|
||||||
new IdentityKey(Base64.getDecoder().decode(encryptedProfile.getIdentityKey())),
|
|
||||||
new Date());
|
|
||||||
|
|
||||||
if (newIdentity) {
|
|
||||||
logger.trace("Archiving old sessions");
|
|
||||||
account.getSessionStore().archiveSessions(recipientId);
|
|
||||||
account.getSenderKeyStore().deleteSharedWith(recipientId);
|
|
||||||
}
|
|
||||||
} catch (InvalidKeyException ignored) {
|
} catch (InvalidKeyException ignored) {
|
||||||
logger.warn("Got invalid identity key in profile for {}",
|
logger.warn("Got invalid identity key in profile for {}",
|
||||||
context.getRecipientHelper().resolveSignalServiceAddress(recipientId).getIdentifier());
|
context.getRecipientHelper().resolveSignalServiceAddress(recipientId).getIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.trace("Storing profile");
|
||||||
|
account.getProfileStore().storeProfile(recipientId, newProfile);
|
||||||
|
|
||||||
logger.trace("Done handling retrieved profile");
|
logger.trace("Done handling retrieved profile");
|
||||||
}).doOnError(e -> {
|
}).doOnError(e -> {
|
||||||
logger.warn("Failed to retrieve profile, ignoring: {}", e.getMessage());
|
logger.warn("Failed to retrieve profile, ignoring: {}", e.getMessage());
|
||||||
|
|
|
@ -29,6 +29,9 @@ import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.regex.Pattern;
|
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 {
|
public class IdentityKeyStore implements org.whispersystems.libsignal.state.IdentityKeyStore {
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(IdentityKeyStore.class);
|
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 IdentityKeyPair identityKeyPair;
|
||||||
private final int localRegistrationId;
|
private final int localRegistrationId;
|
||||||
private final TrustNewIdentity trustNewIdentity;
|
private final TrustNewIdentity trustNewIdentity;
|
||||||
|
private final PublishSubject<RecipientId> identityChanges = PublishSubject.create();
|
||||||
|
|
||||||
private boolean isRetryingDecryption = false;
|
private boolean isRetryingDecryption = false;
|
||||||
|
|
||||||
|
@ -59,6 +63,10 @@ public class IdentityKeyStore implements org.whispersystems.libsignal.state.Iden
|
||||||
this.trustNewIdentity = trustNewIdentity;
|
this.trustNewIdentity = trustNewIdentity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Subject<RecipientId> getIdentityChanges() {
|
||||||
|
return identityChanges;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IdentityKeyPair getIdentityKeyPair() {
|
public IdentityKeyPair getIdentityKeyPair() {
|
||||||
return identityKeyPair;
|
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);
|
logger.debug("Storing new identity for recipient {} with trust {}", recipientId, trustLevel);
|
||||||
final var newIdentityInfo = new IdentityInfo(recipientId, identityKey, trustLevel, added);
|
final var newIdentityInfo = new IdentityInfo(recipientId, identityKey, trustLevel, added);
|
||||||
storeIdentityLocked(recipientId, newIdentityInfo);
|
storeIdentityLocked(recipientId, newIdentityInfo);
|
||||||
|
identityChanges.onNext(recipientId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue