Ensure all SignalServiceAddresses have UUIDs.

This commit is contained in:
Greyson Parrelli
2021-08-20 14:03:11 -04:00
committed by Alex Hart
parent 0ab2100fa5
commit 642d1984c4
30 changed files with 134 additions and 255 deletions

View File

@@ -792,7 +792,7 @@ public class RecipientDatabase extends Database {
if (id < 0) {
Log.w(TAG, "[applyStorageSyncContactInsert] Failed to insert. Possibly merging.");
recipientId = getAndPossiblyMerge(insert.getAddress().getUuid().get(), insert.getAddress().getNumber().get(), true);
recipientId = getAndPossiblyMerge(insert.getAddress().getUuid(), insert.getAddress().getNumber().get(), true);
db.update(TABLE_NAME, values, ID_WHERE, SqlUtil.buildArgs(recipientId));
} else {
recipientId = RecipientId.from(id);
@@ -827,7 +827,7 @@ public class RecipientDatabase extends Database {
RecipientId recipientId = getByColumn(STORAGE_SERVICE_ID, Base64.encodeBytes(update.getOld().getId().getRaw())).get();
Log.w(TAG, "[applyStorageSyncContactUpdate] Found user " + recipientId + ". Possibly merging.");
recipientId = getAndPossiblyMerge(update.getNew().getAddress().getUuid().orNull(), update.getNew().getAddress().getNumber().orNull(), true);
recipientId = getAndPossiblyMerge(update.getNew().getAddress().getUuid(), update.getNew().getAddress().getNumber().orNull(), true);
Log.w(TAG, "[applyStorageSyncContactUpdate] Merged into " + recipientId);
db.update(TABLE_NAME, values, ID_WHERE, SqlUtil.buildArgs(recipientId));
@@ -1019,13 +1019,10 @@ public class RecipientDatabase extends Database {
private static @NonNull ContentValues getValuesForStorageContact(@NonNull SignalContactRecord contact, boolean isInsert) {
ContentValues values = new ContentValues();
if (contact.getAddress().getUuid().isPresent()) {
values.put(UUID, contact.getAddress().getUuid().get().toString());
}
ProfileName profileName = ProfileName.fromParts(contact.getGivenName().orNull(), contact.getFamilyName().orNull());
String username = contact.getUsername().orNull();
values.put(UUID, contact.getAddress().getUuid().toString());
values.put(PHONE, contact.getAddress().getNumber().orNull());
values.put(PROFILE_GIVEN_NAME, profileName.getGivenName());
values.put(PROFILE_FAMILY_NAME, profileName.getFamilyName());
@@ -2600,8 +2597,7 @@ public class RecipientDatabase extends Database {
.map(b -> b.getNumber().get())
.toList();
List<String> blockedUuid = Stream.of(blocked)
.filter(b -> b.getUuid().isPresent())
.map(b -> b.getUuid().get().toString().toLowerCase())
.map(b -> b.getUuid().toString().toLowerCase())
.toList();
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();

View File

@@ -45,6 +45,10 @@ public class SessionDatabase extends Database {
}
public void store(@NonNull SignalProtocolAddress address, @NonNull SessionRecord record) {
if (address.getName().charAt(0) == '+') {
throw new IllegalArgumentException("Cannot insert an e164 into this table!");
}
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
try (SQLiteStatement statement = db.compileStatement("INSERT INTO " + TABLE_NAME + " (" + ADDRESS + ", " + DEVICE + ", " + RECORD + ") VALUES (?, ?, ?) " +

View File

@@ -379,10 +379,12 @@ public class MultiDeviceContactUpdateJob extends BaseJob {
}
}
private Optional<VerifiedMessage> getVerifiedMessage(Recipient recipient, Optional<IdentityDatabase.IdentityRecord> identity) throws InvalidNumberException {
private Optional<VerifiedMessage> getVerifiedMessage(Recipient recipient, Optional<IdentityDatabase.IdentityRecord> identity)
throws InvalidNumberException, IOException
{
if (!identity.isPresent()) return Optional.absent();
SignalServiceAddress destination = RecipientUtil.toSignalServiceAddressBestEffort(context, recipient);
SignalServiceAddress destination = RecipientUtil.toSignalServiceAddress(context, recipient);
IdentityKey identityKey = identity.get().getIdentityKey();
VerifiedMessage.VerifiedState state;

View File

@@ -220,7 +220,7 @@ public class PushMediaSendJob extends PushSendJob {
.asExpirationUpdate(message.isExpirationUpdate())
.build();
if (Util.equals(TextSecurePreferences.getLocalUuid(context), address.getUuid().orNull())) {
if (Util.equals(TextSecurePreferences.getLocalUuid(context), address.getUuid())) {
Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
SignalServiceSyncMessage syncMessage = buildSelfSendSyncMessage(context, mediaMessage, syncAccess);

View File

@@ -177,7 +177,7 @@ public class PushTextSendJob extends PushSendJob {
.asEndSessionMessage(message.isEndSession())
.build();
if (Util.equals(TextSecurePreferences.getLocalUuid(context), address.getUuid().orNull())) {
if (Util.equals(TextSecurePreferences.getLocalUuid(context), address.getUuid())) {
Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
SignalServiceSyncMessage syncMessage = buildSelfSendSyncMessage(context, textSecureMessage, syncAccess);

View File

@@ -82,7 +82,7 @@ public class IncomingMessageProcessor {
* one was created. Otherwise null.
*/
public @Nullable String processEnvelope(@NonNull SignalServiceEnvelope envelope) {
if (envelope.hasSource()) {
if (envelope.hasSourceUuid()) {
Recipient.externalHighTrustPush(context, envelope.getSourceAddress());
}

View File

@@ -78,7 +78,7 @@ public final class MessageDecryptionUtil {
*/
public static @NonNull DecryptionResult decrypt(@NonNull Context context, @NonNull SignalServiceEnvelope envelope) {
SignalProtocolStore axolotlStore = new SignalProtocolStoreImpl(context);
SignalServiceAddress localAddress = new SignalServiceAddress(Optional.of(TextSecurePreferences.getLocalUuid(context)), Optional.of(TextSecurePreferences.getLocalNumber(context)));
SignalServiceAddress localAddress = new SignalServiceAddress(TextSecurePreferences.getLocalUuid(context), Optional.of(TextSecurePreferences.getLocalNumber(context)));
SignalServiceCipher cipher = new SignalServiceCipher(localAddress, axolotlStore, ReentrantSessionLock.INSTANCE, UnidentifiedAccessUtil.getCertificateValidator());
List<Job> jobs = new LinkedList<>();

View File

@@ -174,7 +174,7 @@ public class Recipient {
*/
@WorkerThread
public static @NonNull Recipient externalPush(@NonNull Context context, @NonNull SignalServiceAddress signalServiceAddress) {
return externalPush(context, signalServiceAddress.getUuid().orNull(), signalServiceAddress.getNumber().orNull(), false);
return externalPush(context, signalServiceAddress.getUuid(), signalServiceAddress.getNumber().orNull(), false);
}
/**
@@ -187,7 +187,7 @@ public class Recipient {
if (address.getNumber().isPresent()) {
return externalPush(context, null, address.getNumber().get(), false);
} else {
return externalPush(context, address.getUuid().orNull(), null, false);
return externalPush(context, address.getUuid(), null, false);
}
}
@@ -202,7 +202,7 @@ public class Recipient {
*/
@WorkerThread
public static @NonNull Recipient externalHighTrustPush(@NonNull Context context, @NonNull SignalServiceAddress signalServiceAddress) {
return externalPush(context, signalServiceAddress.getUuid().orNull(), signalServiceAddress.getNumber().orNull(), true);
return externalPush(context, signalServiceAddress.getUuid(), signalServiceAddress.getNumber().orNull(), true);
}
/**

View File

@@ -54,7 +54,7 @@ public class RecipientId implements Parcelable, Comparable<RecipientId> {
@AnyThread
public static @NonNull RecipientId from(@NonNull SignalServiceAddress address) {
return from(address.getUuid().orNull(), address.getNumber().orNull(), false);
return from(address.getUuid(), address.getNumber().orNull(), false);
}
/**
@@ -77,7 +77,7 @@ public class RecipientId implements Parcelable, Comparable<RecipientId> {
*/
@AnyThread
public static @NonNull RecipientId fromHighTrust(@NonNull SignalServiceAddress address) {
return from(address.getUuid().orNull(), address.getNumber().orNull(), true);
return from(address.getUuid(), address.getNumber().orNull(), true);
}
/**

View File

@@ -37,22 +37,6 @@ public class RecipientUtil {
private static final String TAG = Log.tag(RecipientUtil.class);
/**
* This method will do it's best to craft a fully-populated {@link SignalServiceAddress} based on
* the provided recipient. This includes performing a possible network request if no UUID is
* available. If the request to get a UUID fails, the exception is swallowed an an E164-only
* recipient is returned.
*/
@WorkerThread
public static @NonNull SignalServiceAddress toSignalServiceAddressBestEffort(@NonNull Context context, @NonNull Recipient recipient) {
try {
return toSignalServiceAddress(context, recipient);
} catch (IOException e) {
Log.w(TAG, "Failed to populate address!", e);
return new SignalServiceAddress(recipient.getUuid().orNull(), recipient.getE164().orNull());
}
}
/**
* This method will do it's best to craft a fully-populated {@link SignalServiceAddress} based on
* the provided recipient. This includes performing a possible network request if no UUID is
@@ -76,7 +60,7 @@ public class RecipientUtil {
Log.i(TAG, "Successfully performed a UUID fetch for " + recipient.getId() + ". Registered: " + state);
}
return new SignalServiceAddress(Optional.fromNullable(recipient.getUuid().orNull()), Optional.fromNullable(recipient.resolve().getE164().orNull()));
return new SignalServiceAddress(recipient.requireUuid(), Optional.fromNullable(recipient.resolve().getE164().orNull()));
}
public static @NonNull List<SignalServiceAddress> toSignalServiceAddresses(@NonNull Context context, @NonNull List<RecipientId> recipients)

View File

@@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
import org.whispersystems.signalservice.api.util.UuidUtil;
import org.whispersystems.signalservice.internal.storage.protos.ContactRecord.IdentityState;
import java.util.Arrays;
@@ -49,7 +50,10 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
if (address == null) {
Log.w(TAG, "No address on the ContentRecord -- marking as invalid.");
return true;
} else if ((self.getUuid().isPresent() && address.getUuid().equals(self.getUuid())) ||
} else if (address.getUuid().equals(UuidUtil.UNKNOWN_UUID)) {
Log.w(TAG, "Found a ContactRecord without a UUID -- marking as invalid.");
return true;
} else if ((self.getUuid().isPresent() && address.getUuid().equals(self.requireUuid())) ||
(self.getE164().isPresent() && address.getNumber().equals(self.getE164())))
{
Log.w(TAG, "Found a ContactRecord for ourselves -- marking as invalid.");
@@ -62,7 +66,7 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
@Override
@NonNull Optional<SignalContactRecord> getMatching(@NonNull SignalContactRecord remote, @NonNull StorageKeyGenerator keyGenerator) {
SignalServiceAddress address = remote.getAddress();
Optional<RecipientId> byUuid = address.getUuid().isPresent() ? recipientDatabase.getByUuid(address.getUuid().get()) : Optional.absent();
Optional<RecipientId> byUuid = recipientDatabase.getByUuid(address.getUuid());
Optional<RecipientId> byE164 = address.getNumber().isPresent() ? recipientDatabase.getByE164(address.getNumber().get()) : Optional.absent();
return byUuid.or(byE164).transform(recipientDatabase::getRecipientSettingsForSync)
@@ -91,7 +95,7 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
}
byte[] unknownFields = remote.serializeUnknownFields();
UUID uuid = remote.getAddress().getUuid().or(local.getAddress().getUuid()).orNull();
UUID uuid = local.getAddress().getUuid() == UuidUtil.UNKNOWN_UUID ? remote.getAddress().getUuid() : local.getAddress().getUuid();
String e164 = remote.getAddress().getNumber().or(local.getAddress().getNumber()).orNull();
SignalServiceAddress address = new SignalServiceAddress(uuid, e164);
byte[] profileKey = remote.getProfileKey().or(local.getProfileKey()).orNull();

View File

@@ -145,7 +145,7 @@ public final class StorageSyncValidations {
if (insert.getContact().isPresent()) {
SignalServiceAddress address = insert.getContact().get().getAddress();
if (self.getE164().get().equals(address.getNumber().or("")) || self.getUuid().get().equals(address.getUuid().orNull())) {
if (self.getE164().get().equals(address.getNumber().or("")) || self.getUuid().get().equals(address.getUuid())) {
throw new SelfAddedAsContactError();
}
}

View File

@@ -74,13 +74,12 @@ public final class ProfileUtil {
@NonNull SignalServiceProfile.RequestType requestType,
@NonNull ProfileService profileService)
{
SignalServiceAddress address = toSignalServiceAddress(context, recipient);
Optional<UnidentifiedAccess> unidentifiedAccess = getUnidentifiedAccess(context, recipient);
Optional<ProfileKey> profileKey = ProfileKeyUtil.profileKeyOptional(recipient.getProfileKey());
return profileService.getProfile(address, profileKey, unidentifiedAccess, requestType)
.map(p -> new Pair<>(recipient, p))
.onErrorReturn(t -> new Pair<>(recipient, ServiceResponse.forUnknownError(t)));
return Single.fromCallable(() -> toSignalServiceAddress(context, recipient))
.flatMap(address -> profileService.getProfile(address, profileKey, unidentifiedAccess, requestType).map(p -> new Pair<>(recipient, p)))
.onErrorReturn(t -> new Pair<>(recipient, ServiceResponse.forUnknownError(t)));
}
public static @Nullable String decryptString(@NonNull ProfileKey profileKey, @Nullable byte[] encryptedString)
@@ -267,11 +266,11 @@ public final class ProfileUtil {
return Optional.absent();
}
private static @NonNull SignalServiceAddress toSignalServiceAddress(@NonNull Context context, @NonNull Recipient recipient) {
private static @NonNull SignalServiceAddress toSignalServiceAddress(@NonNull Context context, @NonNull Recipient recipient) throws IOException {
if (recipient.getRegistered() == RecipientDatabase.RegisteredState.NOT_REGISTERED) {
return new SignalServiceAddress(recipient.getUuid().orNull(), recipient.getE164().orNull());
} else {
return RecipientUtil.toSignalServiceAddressBestEffort(context, recipient);
return RecipientUtil.toSignalServiceAddress(context, recipient);
}
}
}

View File

@@ -25,8 +25,8 @@ class RecipientAccessList(private val recipients: List<Recipient>) : List<Recipi
}
fun requireByAddress(address: SignalServiceAddress): Recipient {
if (address.uuid.isPresent && byUuid.containsKey(address.uuid.get())) {
return byUuid.get(address.uuid.get())!!
if (byUuid.containsKey(address.uuid)) {
return byUuid.get(address.uuid)!!
} else if (address.number.isPresent && byE164.containsKey(address.number.get())) {
return byE164.get(address.number.get())!!
} else {