Clear all sender key knowledge for a device after a 409/410.
This commit is contained in:
parent
7c8549bf5e
commit
d40bb2d9ee
6 changed files with 50 additions and 29 deletions
|
@ -12,8 +12,6 @@ import org.whispersystems.libsignal.state.IdentityKeyStore;
|
||||||
import org.whispersystems.libsignal.state.PreKeyRecord;
|
import org.whispersystems.libsignal.state.PreKeyRecord;
|
||||||
import org.whispersystems.libsignal.state.PreKeyStore;
|
import org.whispersystems.libsignal.state.PreKeyStore;
|
||||||
import org.whispersystems.libsignal.state.SessionRecord;
|
import org.whispersystems.libsignal.state.SessionRecord;
|
||||||
import org.whispersystems.libsignal.state.SessionStore;
|
|
||||||
import org.whispersystems.libsignal.state.SignalProtocolStore;
|
|
||||||
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||||
import org.whispersystems.libsignal.state.SignedPreKeyStore;
|
import org.whispersystems.libsignal.state.SignedPreKeyStore;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceProtocolStore;
|
import org.whispersystems.signalservice.api.SignalServiceProtocolStore;
|
||||||
|
@ -172,7 +170,7 @@ public class SignalProtocolStoreImpl implements SignalServiceProtocolStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearSenderKeySharedWith(DistributionId distributionId, Collection<SignalProtocolAddress> addresses) {
|
public void clearSenderKeySharedWith(Collection<SignalProtocolAddress> addresses) {
|
||||||
senderKeyStore.clearSenderKeySharedWith(distributionId, addresses);
|
senderKeyStore.clearSenderKeySharedWith(addresses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,9 +62,9 @@ public final class SignalSenderKeyStore implements SignalServiceSenderKeyStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearSenderKeySharedWith(DistributionId distributionId, Collection<SignalProtocolAddress> addresses) {
|
public void clearSenderKeySharedWith(Collection<SignalProtocolAddress> addresses) {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
DatabaseFactory.getSenderKeySharedDatabase(context).delete(distributionId, addresses);
|
DatabaseFactory.getSenderKeySharedDatabase(context).deleteAllFor(addresses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,26 @@ public class SenderKeySharedDatabase extends Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all shared statuses for a given recipientId.
|
* Clear the shared status for all distributionIds for a set of addresses.
|
||||||
|
*/
|
||||||
|
public void deleteAllFor(@NonNull Collection<SignalProtocolAddress> addresses) {
|
||||||
|
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||||
|
String query = ADDRESS + " = ? AND " + DEVICE + " = ?";
|
||||||
|
|
||||||
|
db.beginTransaction();
|
||||||
|
try {
|
||||||
|
for (SignalProtocolAddress address : addresses) {
|
||||||
|
db.delete(TABLE_NAME, query, SqlUtil.buildArgs(address.getName(), address.getDeviceId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
db.setTransactionSuccessful();
|
||||||
|
} finally {
|
||||||
|
db.endTransaction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the shared status for all distributionIds for a given recipientId.
|
||||||
*/
|
*/
|
||||||
public void deleteAllFor(@NonNull RecipientId recipientId) {
|
public void deleteAllFor(@NonNull RecipientId recipientId) {
|
||||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||||
|
|
|
@ -252,7 +252,7 @@ public final class GroupSendUtil {
|
||||||
allResults.addAll(results);
|
allResults.addAll(results);
|
||||||
|
|
||||||
int successCount = (int) results.stream().filter(SendMessageResult::isSuccess).count();
|
int successCount = (int) results.stream().filter(SendMessageResult::isSuccess).count();
|
||||||
Log.d(TAG, "Successfully using 1:1 to " + successCount + "/" + targets.size() + " legacy targets.");
|
Log.d(TAG, "Successfully sent using 1:1 to " + successCount + "/" + targets.size() + " legacy targets.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return allResults;
|
return allResults;
|
||||||
|
|
|
@ -119,6 +119,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -1800,20 +1801,12 @@ public class SignalServiceMessageSender {
|
||||||
for (GroupMismatchedDevices mismatched : e.getMismatchedDevices()) {
|
for (GroupMismatchedDevices mismatched : e.getMismatchedDevices()) {
|
||||||
SignalServiceAddress address = new SignalServiceAddress(UuidUtil.parse(mismatched.getUuid()), Optional.absent());
|
SignalServiceAddress address = new SignalServiceAddress(UuidUtil.parse(mismatched.getUuid()), Optional.absent());
|
||||||
handleMismatchedDevices(socket, address, mismatched.getDevices());
|
handleMismatchedDevices(socket, address, mismatched.getDevices());
|
||||||
List<SignalProtocolAddress> clearAddresses = mismatched.getDevices().getExtraDevices().stream()
|
|
||||||
.map(device -> new SignalProtocolAddress(address.getIdentifier(), device))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
store.clearSenderKeySharedWith(distributionId, clearAddresses);
|
|
||||||
}
|
}
|
||||||
} catch (GroupStaleDevicesException e) {
|
} catch (GroupStaleDevicesException e) {
|
||||||
Log.w(TAG, "[sendGroupMessage] Handling stale devices.", e);
|
Log.w(TAG, "[sendGroupMessage] Handling stale devices.", e);
|
||||||
for (GroupStaleDevices stale : e.getStaleDevices()) {
|
for (GroupStaleDevices stale : e.getStaleDevices()) {
|
||||||
SignalServiceAddress address = new SignalServiceAddress(UuidUtil.parse(stale.getUuid()), Optional.absent());
|
SignalServiceAddress address = new SignalServiceAddress(UuidUtil.parse(stale.getUuid()), Optional.absent());
|
||||||
handleStaleDevices(address, stale.getDevices());
|
handleStaleDevices(address, stale.getDevices());
|
||||||
List<SignalProtocolAddress> clearAddresses = stale.getDevices().getStaleDevices().stream()
|
|
||||||
.map(device -> new SignalProtocolAddress(address.getIdentifier(), device))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
store.clearSenderKeySharedWith(distributionId, clearAddresses);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1998,14 +1991,7 @@ public class SignalServiceMessageSender {
|
||||||
throws IOException, UntrustedIdentityException
|
throws IOException, UntrustedIdentityException
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
for (int extraDeviceId : mismatchedDevices.getExtraDevices()) {
|
archiveSessions(recipient, mismatchedDevices.getExtraDevices());
|
||||||
if (recipient.getUuid().isPresent()) {
|
|
||||||
store.archiveSession(new SignalProtocolAddress(recipient.getUuid().get().toString(), extraDeviceId));
|
|
||||||
}
|
|
||||||
if (recipient.getNumber().isPresent()) {
|
|
||||||
store.archiveSession(new SignalProtocolAddress(recipient.getNumber().get(), extraDeviceId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int missingDeviceId : mismatchedDevices.getMissingDevices()) {
|
for (int missingDeviceId : mismatchedDevices.getMissingDevices()) {
|
||||||
PreKeyBundle preKey = socket.getPreKey(recipient, missingDeviceId);
|
PreKeyBundle preKey = socket.getPreKey(recipient, missingDeviceId);
|
||||||
|
@ -2023,14 +2009,32 @@ public class SignalServiceMessageSender {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleStaleDevices(SignalServiceAddress recipient, StaleDevices staleDevices) {
|
private void handleStaleDevices(SignalServiceAddress recipient, StaleDevices staleDevices) {
|
||||||
for (int staleDeviceId : staleDevices.getStaleDevices()) {
|
archiveSessions(recipient, staleDevices.getStaleDevices());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void archiveSessions(SignalServiceAddress recipient, List<Integer> devices) {
|
||||||
|
List<SignalProtocolAddress> addressesToClear = convertToProtocolAddresses(recipient, devices);
|
||||||
|
|
||||||
|
for (SignalProtocolAddress address : addressesToClear) {
|
||||||
|
store.archiveSession(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
store.clearSenderKeySharedWith(addressesToClear);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SignalProtocolAddress> convertToProtocolAddresses(SignalServiceAddress recipient, List<Integer> devices) {
|
||||||
|
List<SignalProtocolAddress> addresses = new ArrayList<>(devices.size());
|
||||||
|
|
||||||
|
for (int staleDeviceId : devices) {
|
||||||
if (recipient.getUuid().isPresent()) {
|
if (recipient.getUuid().isPresent()) {
|
||||||
store.archiveSession(new SignalProtocolAddress(recipient.getUuid().get().toString(), staleDeviceId));
|
addresses.add(new SignalProtocolAddress(recipient.getUuid().get().toString(), staleDeviceId));
|
||||||
}
|
}
|
||||||
if (recipient.getNumber().isPresent()) {
|
if (recipient.getNumber().isPresent()) {
|
||||||
store.archiveSession(new SignalProtocolAddress(recipient.getNumber().get(), staleDeviceId));
|
addresses.add(new SignalProtocolAddress(recipient.getNumber().get(), staleDeviceId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return addresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<UnidentifiedAccess> getTargetUnidentifiedAccess(Optional<UnidentifiedAccessPair> unidentifiedAccess) {
|
private Optional<UnidentifiedAccess> getTargetUnidentifiedAccess(Optional<UnidentifiedAccessPair> unidentifiedAccess) {
|
||||||
|
|
|
@ -23,7 +23,7 @@ public interface SignalServiceSenderKeyStore extends SenderKeyStore {
|
||||||
void markSenderKeySharedWith(DistributionId distributionId, Collection<SignalProtocolAddress> addresses);
|
void markSenderKeySharedWith(DistributionId distributionId, Collection<SignalProtocolAddress> addresses);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the provided addresses as not knowing about the provided distributionId.
|
* Marks the provided addresses as not knowing about any distributionIds.
|
||||||
*/
|
*/
|
||||||
void clearSenderKeySharedWith(DistributionId distributionId, Collection<SignalProtocolAddress> addresses);
|
void clearSenderKeySharedWith(Collection<SignalProtocolAddress> addresses);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue