Block sends on CDS lookups.

master
Greyson Parrelli 2020-08-06 10:50:20 -04:00
parent b2d4c5d14b
commit 5923fa0cd5
17 changed files with 85 additions and 54 deletions

View File

@ -122,7 +122,7 @@ android {
buildConfigField "String", "CONTENT_PROXY_HOST", "\"contentproxy.signal.org\""
buildConfigField "int", "CONTENT_PROXY_PORT", "443"
buildConfigField "String", "SIGNAL_AGENT", "\"OWA\""
buildConfigField "String", "CDS_MRENCLAVE", "\"cd6cfc342937b23b1bdd3bbf9721aa5615ac9ff50a75c5527d441cd3276826c9\""
buildConfigField "String", "CDS_MRENCLAVE", "\"bd123560b01c8fa92935bc5ae15cd2064e5c45215f23f0bd40364d521329d2ad\""
buildConfigField "String", "KBS_ENCLAVE_NAME", "\"fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe\""
buildConfigField "String", "KBS_MRENCLAVE", "\"a3baab19ef6ce6f34ab9ebb25ba722725ae44a8872dc0ff08ad6d83a9489de87\""
buildConfigField "String", "UNIDENTIFIED_SENDER_TRUST_ROOT", "\"BXu6QIKVz5MA8gstzfOgRQGqyLqOwNKHL6INkv3IHWMF\""
@ -197,7 +197,7 @@ android {
buildConfigField "String", "SIGNAL_CDN2_URL", "\"https://cdn2-staging.signal.org\""
buildConfigField "String", "SIGNAL_CONTACT_DISCOVERY_URL", "\"https://api-staging.directory.signal.org\""
buildConfigField "String", "SIGNAL_KEY_BACKUP_URL", "\"https://api-staging.backup.signal.org\""
buildConfigField "String", "CDS_MRENCLAVE", "\"b657cad56d518827b0938949bb1e5727a9a4db358dd6a88e55e710a89ffa50bd\""
buildConfigField "String", "CDS_MRENCLAVE", "\"bd123560b01c8fa92935bc5ae15cd2064e5c45215f23f0bd40364d521329d2ad\""
buildConfigField "String", "KBS_ENCLAVE_NAME", "\"823a3b2c037ff0cbe305cc48928cfcc97c9ed4a8ca6d49af6f7d6981fb60a4e9\""
buildConfigField "String", "UNIDENTIFIED_SENDER_TRUST_ROOT", "\"BbqY1DzohE4NUZoVF+L18oUPrK3kILllLEJh2UnPSsEx\""
buildConfigField "String", "ZKGROUP_SERVER_PUBLIC_PARAMS", "\"ABSY21VckQcbSXVNCGRYJcfWHiAMZmpTtTELcDmxgdFbtp/bWsSxZdMKzfCp8rvIs8ocCU3B37fT3r4Mi5qAemeGeR2X+/YmOGR5ofui7tD5mDQfstAI9i+4WpMtIe8KC3wU5w3Inq3uNWVmoGtpKndsNfwJrCg0Hd9zmObhypUnSkfYn2ooMOOnBpfdanRtrvetZUayDMSC5iSRcXKpdls=\""

View File

@ -45,6 +45,7 @@ import org.thoughtcrime.securesms.sms.IncomingJoinedMessage;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.ProfileUtil;
import org.thoughtcrime.securesms.util.SetUtil;
import org.thoughtcrime.securesms.util.Stopwatch;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional;
@ -90,6 +91,7 @@ public class DirectoryHelper {
return;
}
Stopwatch stopwatch = new Stopwatch("full");
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
Set<String> databaseNumbers = sanitizeNumbers(recipientDatabase.getAllPhoneNumbers());
Set<String> systemNumbers = sanitizeNumbers(ContactAccessor.getInstance().getAllContactsWithNumbers(context));
@ -103,6 +105,8 @@ public class DirectoryHelper {
result = ContactDiscoveryV1.getDirectoryResult(databaseNumbers, systemNumbers);
}
stopwatch.split("network");
if (result.getNumberRewrites().size() > 0) {
Log.i(TAG, "[getDirectoryResult] Need to rewrite some numbers.");
recipientDatabase.updatePhoneNumbers(result.getNumberRewrites());
@ -139,16 +143,21 @@ public class DirectoryHelper {
}
StorageSyncHelper.scheduleSyncForDataChange();
stopwatch.split("disk");
stopwatch.stop(TAG);
}
@WorkerThread
public static RegisteredState refreshDirectoryFor(@NonNull Context context, @NonNull Recipient recipient, boolean notifyOfNewUsers) throws IOException {
Stopwatch stopwatch = new Stopwatch("single");
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
RegisteredState originalRegisteredState = recipient.resolve().getRegistered();
RegisteredState newRegisteredState = null;
if (recipient.hasUuid() && !recipient.hasE164()) {
boolean isRegistered = isUuidRegistered(context, recipient);
stopwatch.split("uuid-network");
if (isRegistered) {
boolean idChanged = recipientDatabase.markRegistered(recipient.getId(), recipient.getUuid().get());
if (idChanged) {
@ -158,6 +167,9 @@ public class DirectoryHelper {
recipientDatabase.markUnregistered(recipient.getId());
}
stopwatch.split("uuid-disk");
stopwatch.stop(TAG);
return isRegistered ? RegisteredState.REGISTERED : RegisteredState.NOT_REGISTERED;
}
@ -174,6 +186,8 @@ public class DirectoryHelper {
result = ContactDiscoveryV1.getDirectoryResult(recipient.getE164().get());
}
stopwatch.split("e164-network");
if (result.getNumberRewrites().size() > 0) {
Log.i(TAG, "[getDirectoryResult] Need to rewrite some numbers.");
recipientDatabase.updatePhoneNumbers(result.getNumberRewrites());
@ -210,6 +224,9 @@ public class DirectoryHelper {
StorageSyncHelper.scheduleSyncForDataChange();
}
stopwatch.split("e164-disk");
stopwatch.stop(TAG);
return newRegisteredState;
}

View File

@ -390,7 +390,7 @@ public class RecipientDatabase extends Database {
throw new IllegalArgumentException("Must provide a UUID or E164!");
}
if (!FeatureFlags.recipientTrust()) {
if (!FeatureFlags.cds()) {
highTrust = true;
}

View File

@ -132,8 +132,8 @@ public class LeaveGroupJob extends BaseJob {
throws IOException, UntrustedIdentityException
{
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
List<SignalServiceAddress> addresses = Stream.of(destinations).map(Recipient::resolved).map(t -> RecipientUtil.toSignalServiceAddress(context, t)).toList();
List<SignalServiceAddress> memberAddresses = Stream.of(members).map(Recipient::resolved).map(t -> RecipientUtil.toSignalServiceAddress(context, t)).toList();
List<SignalServiceAddress> addresses = RecipientUtil.toSignalServiceAddresses(context, destinations);
List<SignalServiceAddress> memberAddresses = RecipientUtil.toSignalServiceAddresses(context, members);
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(destinations).map(Recipient::resolved).map(recipient -> UnidentifiedAccessUtil.getAccessFor(context, recipient)).toList();
SignalServiceGroup serviceGroup = new SignalServiceGroup(SignalServiceGroup.Type.QUIT, groupId.getDecodedId(), name, memberAddresses, null);
SignalServiceDataMessage.Builder dataMessage = SignalServiceDataMessage.newBuilder()

View File

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

View File

@ -124,7 +124,7 @@ public class ProfileKeySendJob extends BaseJob {
private List<Recipient> deliver(@NonNull Recipient conversationRecipient, @NonNull List<Recipient> destinations) throws IOException, UntrustedIdentityException {
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
List<SignalServiceAddress> addresses = Stream.of(destinations).map(t -> RecipientUtil.toSignalServiceAddress(context, t)).toList();
List<SignalServiceAddress> addresses = RecipientUtil.toSignalServiceAddressesFromResolved(context, destinations);
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(destinations).map(recipient -> UnidentifiedAccessUtil.getAccessFor(context, recipient)).toList();
SignalServiceDataMessage.Builder dataMessage = SignalServiceDataMessage.newBuilder()
.asProfileKeyUpdate(true)

View File

@ -287,7 +287,7 @@ public final class PushGroupSendJob extends PushSendJob {
List<SharedContact> sharedContacts = getSharedContactsFor(message);
List<Preview> previews = getPreviewsFor(message);
List<SignalServiceDataMessage.Mention> mentions = getMentionsFor(message.getMentions());
List<SignalServiceAddress> addresses = Stream.of(destinations).map(this::getPushAddress).toList();
List<SignalServiceAddress> addresses = RecipientUtil.toSignalServiceAddressesFromResolved(context, destinations);
List<Attachment> attachments = Stream.of(message.getAttachments()).filterNot(Attachment::isSticker).toList();
List<SignalServiceAttachment> attachmentPointers = getAttachmentPointersFor(attachments);
boolean isRecipientUpdate = destinations.size() != DatabaseFactory.getGroupReceiptDatabase(context).getGroupReceiptInfo(messageId).size();

View File

@ -154,7 +154,7 @@ public final class PushGroupSilentUpdateSendJob extends BaseJob {
throws IOException, UntrustedIdentityException
{
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
List<SignalServiceAddress> addresses = Stream.of(destinations).map(t -> RecipientUtil.toSignalServiceAddress(context, t)).toList();
List<SignalServiceAddress> addresses = RecipientUtil.toSignalServiceAddressesFromResolved(context, destinations);
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(destinations).map(recipient -> UnidentifiedAccessUtil.getAccessFor(context, recipient)).toList();
SignalServiceGroupV2 group = SignalServiceGroupV2.fromProtobuf(groupContextV2);

View File

@ -198,7 +198,7 @@ public class PushMediaSendJob extends PushSendJob {
Recipient messageRecipient = message.getRecipient().fresh();
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
SignalServiceAddress address = getPushAddress(messageRecipient);
SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, messageRecipient);
List<Attachment> attachments = Stream.of(message.getAttachments()).filterNot(Attachment::isSticker).toList();
List<SignalServiceAttachment> serviceAttachments = getAttachmentPointersFor(attachments);
Optional<byte[]> profileKey = getProfileKey(messageRecipient);

View File

@ -111,23 +111,6 @@ public abstract class PushSendJob extends SendJob {
return Optional.of(ProfileKeyUtil.getProfileKey(context));
}
protected SignalServiceAddress getPushAddress(@NonNull Recipient recipient) {
return RecipientUtil.toSignalServiceAddress(context, recipient);
}
protected List<SignalServiceAttachment> getAttachmentsFor(List<Attachment> parts) {
List<SignalServiceAttachment> attachments = new LinkedList<>();
for (final Attachment attachment : parts) {
SignalServiceAttachment converted = getAttachmentFor(attachment);
if (converted != null) {
attachments.add(converted);
}
}
return attachments;
}
protected SignalServiceAttachment getAttachmentFor(Attachment attachment) {
try {
if (attachment.getDataUri() == null || attachment.getSize() == 0) throw new IOException("Assertion failed, outgoing attachment has no data!");

View File

@ -158,7 +158,7 @@ public class PushTextSendJob extends PushSendJob {
Recipient messageRecipient = message.getIndividualRecipient().fresh();
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
SignalServiceAddress address = getPushAddress(messageRecipient);
SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, messageRecipient);
Optional<byte[]> profileKey = getProfileKey(messageRecipient);
Optional<UnidentifiedAccessPair> unidentifiedAccess = UnidentifiedAccessUtil.getAccessFor(context, messageRecipient);

View File

@ -209,7 +209,7 @@ public class ReactionSendJob extends BaseJob {
throws IOException, UntrustedIdentityException
{
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
List<SignalServiceAddress> addresses = Stream.of(destinations).map(t -> RecipientUtil.toSignalServiceAddress(context, t)).toList();
List<SignalServiceAddress> addresses = RecipientUtil.toSignalServiceAddressesFromResolved(context, destinations);
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(destinations).map(recipient -> UnidentifiedAccessUtil.getAccessFor(context, recipient)).toList();
SignalServiceDataMessage.Builder dataMessage = SignalServiceDataMessage.newBuilder()
.withTimestamp(System.currentTimeMillis())
@ -230,6 +230,7 @@ public class ReactionSendJob extends BaseJob {
boolean remove,
@NonNull Recipient targetAuthor,
long targetSentTimestamp)
throws IOException
{
return new SignalServiceDataMessage.Reaction(reaction.getEmoji(),
remove,

View File

@ -165,7 +165,7 @@ public class RemoteDeleteSendJob extends BaseJob {
throws IOException, UntrustedIdentityException
{
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
List<SignalServiceAddress> addresses = Stream.of(destinations).map(t -> RecipientUtil.toSignalServiceAddress(context, t)).toList();
List<SignalServiceAddress> addresses = RecipientUtil.toSignalServiceAddressesFromResolved(context, destinations);
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(destinations).map(recipient -> UnidentifiedAccessUtil.getAccessFor(context, recipient)).toList();
SignalServiceDataMessage.Builder dataMessage = SignalServiceDataMessage.newBuilder()
.withTimestamp(System.currentTimeMillis())

View File

@ -107,7 +107,7 @@ public class TypingSendJob extends BaseJob {
recipients = Stream.of(recipients).map(Recipient::resolve).toList();
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
List<SignalServiceAddress> addresses = Stream.of(recipients).map(r -> RecipientUtil.toSignalServiceAddress(context, r)).toList();
List<SignalServiceAddress> addresses = RecipientUtil.toSignalServiceAddressesFromResolved(context, recipients);
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(recipients).map(r -> UnidentifiedAccessUtil.getAccessFor(context, r)).toList();
SignalServiceTypingMessage typingMessage = new SignalServiceTypingMessage(typing ? Action.STARTED : Action.STOPPED, System.currentTimeMillis(), groupId);

View File

@ -29,6 +29,8 @@ import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class RecipientUtil {
@ -40,7 +42,24 @@ public class RecipientUtil {
* available.
*/
@WorkerThread
public static @NonNull SignalServiceAddress toSignalServiceAddress(@NonNull Context context, @NonNull Recipient recipient) {
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
* available.
*/
@WorkerThread
public static @NonNull SignalServiceAddress toSignalServiceAddress(@NonNull Context context, @NonNull Recipient recipient)
throws IOException
{
recipient = recipient.resolve();
if (!recipient.getUuid().isPresent() && !recipient.getE164().isPresent()) {
@ -49,19 +68,39 @@ public class RecipientUtil {
if (FeatureFlags.cds() && !recipient.getUuid().isPresent()) {
Log.i(TAG, recipient.getId() + " is missing a UUID...");
try {
RegisteredState state = DirectoryHelper.refreshDirectoryFor(context, recipient, false);
recipient = Recipient.resolved(recipient.getId());
Log.i(TAG, "Successfully performed a UUID fetch for " + recipient.getId() + ". Registered: " + state);
} catch (IOException e) {
Log.w(TAG, "Failed to fetch a UUID for " + recipient.getId() + ". Scheduling a future fetch and building an address without one.");
ApplicationDependencies.getJobManager().add(new DirectoryRefreshJob(recipient, false));
}
RegisteredState state = DirectoryHelper.refreshDirectoryFor(context, recipient, false);
recipient = Recipient.resolved(recipient.getId());
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()));
}
public static @NonNull List<SignalServiceAddress> toSignalServiceAddresses(@NonNull Context context, @NonNull List<RecipientId> recipients)
throws IOException
{
List<SignalServiceAddress> addresses = new ArrayList<>(recipients.size());
for (RecipientId id : recipients) {
addresses.add(toSignalServiceAddress(context, Recipient.resolved(id)));
}
return addresses;
}
public static @NonNull List<SignalServiceAddress> toSignalServiceAddressesFromResolved(@NonNull Context context, @NonNull List<Recipient> recipients)
throws IOException
{
List<SignalServiceAddress> addresses = new ArrayList<>(recipients.size());
for (Recipient recipient : recipients) {
addresses.add(toSignalServiceAddress(context, recipient));
}
return addresses;
}
public static boolean isBlockable(@NonNull Recipient recipient) {
Recipient resolved = recipient.resolve();
return resolved.isPushGroup() || resolved.hasServiceIdentifier();

View File

@ -55,8 +55,7 @@ public final class FeatureFlags {
private static final String GROUPS_V2 = "android.groupsv2.2";
private static final String GROUPS_V2_CREATE = "android.groupsv2.create.2";
private static final String GROUPS_V2_CAPACITY = "android.groupsv2.capacity";
private static final String CDS = "android.cds";
private static final String RECIPIENT_TRUST = "android.recipientTrust";
private static final String CDS = "android.cds.2";
private static final String INTERNAL_USER = "android.internalUser";
private static final String MENTIONS = "android.mentions";
@ -71,7 +70,6 @@ public final class FeatureFlags {
GROUPS_V2,
GROUPS_V2_CREATE,
GROUPS_V2_CAPACITY,
RECIPIENT_TRUST,
INTERNAL_USER,
MENTIONS
);
@ -95,8 +93,7 @@ public final class FeatureFlags {
*/
private static final Set<String> HOT_SWAPPABLE = Sets.newHashSet(
ATTACHMENTS_V3,
GROUPS_V2_CREATE,
RECIPIENT_TRUST
GROUPS_V2_CREATE
);
/**
@ -104,8 +101,7 @@ public final class FeatureFlags {
*/
private static final Set<String> STICKY = Sets.newHashSet(
GROUPS_V2,
GROUPS_V2_OLD,
RECIPIENT_TRUST
GROUPS_V2_OLD
);
/**
@ -174,7 +170,7 @@ public final class FeatureFlags {
Log.i(TAG, "[Disk] After : " + result.getDisk().toString());
}
/** Creating usernames, sending messages by username. Requires {@link #uuidOnlyContacts()}. */
/** Creating usernames, sending messages by username. */
public static synchronized boolean usernames() {
return getBoolean(USERNAMES, false);
}
@ -218,11 +214,6 @@ public final class FeatureFlags {
return getBoolean(CDS, false);
}
/** Whether or not we allow different trust levels for recipient address sources. */
public static boolean recipientTrust() {
return getBoolean(RECIPIENT_TRUST, false);
}
/** Whether or not we allow mentions send support in groups. */
public static boolean mentions() {
return getBoolean(MENTIONS, false);

View File

@ -68,7 +68,7 @@ public final class ProfileUtil {
@NonNull Recipient recipient,
@NonNull SignalServiceProfile.RequestType requestType)
{
SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, recipient);
SignalServiceAddress address = RecipientUtil.toSignalServiceAddressBestEffort(context, recipient);
Optional<UnidentifiedAccess> unidentifiedAccess = getUnidentifiedAccess(context, recipient);
Optional<ProfileKey> profileKey = ProfileKeyUtil.profileKeyOptional(recipient.getProfileKey());