Remove UUIDs from GV1 membership lists.

master
Greyson Parrelli 2020-07-27 16:37:08 -04:00
parent 1ab61beeb9
commit 5c110ca359
10 changed files with 60 additions and 59 deletions

View File

@ -36,6 +36,7 @@ import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupC
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@ -122,12 +123,15 @@ final class GroupManagerV1 {
RecipientId groupRecipientId = DatabaseFactory.getRecipientDatabase(context).getOrInsertFromGroupId(groupId);
Recipient groupRecipient = Recipient.resolved(groupRecipientId);
List<GroupContext.Member> uuidMembers = new LinkedList<>();
List<String> e164Members = new LinkedList<>();
List<GroupContext.Member> uuidMembers = new ArrayList<>(members.size());
List<String> e164Members = new ArrayList<>(members.size());
for (RecipientId member : members) {
Recipient recipient = Recipient.resolved(member);
uuidMembers.add(GroupV1MessageProcessor.createMember(RecipientUtil.toSignalServiceAddress(context, recipient)));
if (recipient.hasE164()) {
e164Members.add(recipient.requireE164());
uuidMembers.add(GroupV1MessageProcessor.createMember(recipient.requireE164()));
}
}
GroupContext.Builder groupContextBuilder = GroupContext.newBuilder()
@ -135,7 +139,9 @@ final class GroupManagerV1 {
.setType(GroupContext.Type.UPDATE)
.addAllMembersE164(e164Members)
.addAllMembers(uuidMembers);
if (groupName != null) groupContextBuilder.setName(groupName);
GroupContext groupContext = groupContextBuilder.build();
if (avatar != null) {

View File

@ -101,7 +101,7 @@ public final class GroupV1MessageProcessor {
if (group.getMembers().isPresent()) {
for (SignalServiceAddress member : group.getMembers().get()) {
members.add(Recipient.externalPush(context, member).getId());
members.add(Recipient.externalGV1Member(context, member).getId());
}
}
@ -131,8 +131,10 @@ public final class GroupV1MessageProcessor {
Set<RecipientId> recordMembers = new HashSet<>(groupRecord.getMembers());
Set<RecipientId> messageMembers = new HashSet<>();
for (SignalServiceAddress messageMember : group.getMembers().get()) {
messageMembers.add(Recipient.externalPush(context, messageMember).getId());
if (group.getMembers().isPresent()) {
for (SignalServiceAddress messageMember : group.getMembers().get()) {
messageMembers.add(Recipient.externalGV1Member(context, messageMember).getId());
}
}
Set<RecipientId> addedMembers = new HashSet<>(messageMembers);
@ -150,18 +152,19 @@ public final class GroupV1MessageProcessor {
database.updateMembers(id, new LinkedList<>(unionMembers));
builder.clearMembers();
builder.clearMembersE164();
for (RecipientId addedMember : addedMembers) {
Recipient recipient = Recipient.resolved(addedMember);
if (recipient.getE164().isPresent()) {
builder.addMembersE164(recipient.getE164().get());
builder.addMembersE164(recipient.requireE164());
builder.addMembers(createMember(recipient.requireE164()));
}
builder.addMembers(createMember(RecipientUtil.toSignalServiceAddress(context, recipient)));
}
} else {
builder.clearMembers();
builder.clearMembersE164();
}
if (missingMembers.size() > 0) {
@ -287,6 +290,8 @@ public final class GroupV1MessageProcessor {
.map(a -> a.getNumber().get())
.toList());
builder.addAllMembers(Stream.of(group.getMembers().get())
.filter(address -> address.getNumber().isPresent())
.map(address -> address.getNumber().get())
.map(GroupV1MessageProcessor::createMember)
.toList());
}
@ -294,17 +299,9 @@ public final class GroupV1MessageProcessor {
return builder;
}
public static GroupContext.Member createMember(SignalServiceAddress address) {
public static GroupContext.Member createMember(@NonNull String e164) {
GroupContext.Member.Builder member = GroupContext.Member.newBuilder();
if (address.getUuid().isPresent()) {
member.setUuid(address.getUuid().get().toString());
}
if (address.getNumber().isPresent()) {
member.setE164(address.getNumber().get());
}
member.setE164(e164);
return member.build();
}
}

View File

@ -323,8 +323,8 @@ public final class PushGroupSendJob extends PushSendJob {
GroupContext groupContext = properties.getGroupContext();
SignalServiceAttachment avatar = attachmentPointers.isEmpty() ? null : attachmentPointers.get(0);
SignalServiceGroup.Type type = properties.isQuit() ? SignalServiceGroup.Type.QUIT : SignalServiceGroup.Type.UPDATE;
List<SignalServiceAddress> members = Stream.of(groupContext.getMembersList())
.map(m -> new SignalServiceAddress(UuidUtil.parseOrNull(m.getUuid()), m.getE164()))
List<SignalServiceAddress> members = Stream.of(groupContext.getMembersE164List())
.map(e164 -> new SignalServiceAddress(null, e164))
.toList();
SignalServiceGroup group = new SignalServiceGroup(type, groupId.getDecodedId(), groupContext.getName(), members, avatar);
SignalServiceDataMessage groupDataMessage = SignalServiceDataMessage.newBuilder()

View File

@ -3,6 +3,8 @@ package org.thoughtcrime.securesms.mms;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.annimon.stream.Stream;
import org.signal.storageservice.protos.groups.local.DecryptedMember;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.groups.GroupMasterKey;
@ -11,6 +13,7 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.Base64;
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.util.UuidUtil;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContextV2;
@ -123,20 +126,13 @@ public final class MessageGroupContext {
@Override
public @NonNull List<RecipientId> getMembersListExcludingSelf() {
List<GroupContext.Member> membersList = groupContext.getMembersList();
if (membersList.isEmpty()) {
return Collections.emptyList();
} else {
LinkedList<RecipientId> members = new LinkedList<>();
RecipientId selfId = Recipient.self().getId();
for (GroupContext.Member member : membersList) {
RecipientId recipient = RecipientId.from(UuidUtil.parseOrNull(member.getUuid()), member.getE164());
if (!Recipient.self().getId().equals(recipient)) {
members.add(recipient);
}
}
return members;
}
return Stream.of(groupContext.getMembersE164List())
.map(e164 -> new SignalServiceAddress(null, e164))
.map(RecipientId::from)
.filterNot(selfId::equals)
.toList();
}
}

View File

@ -157,6 +157,20 @@ public class Recipient {
return externalPush(context, signalServiceAddress.getUuid().orNull(), signalServiceAddress.getNumber().orNull(), false);
}
/**
* Returns a fully-populated {@link Recipient} based off of a {@link SignalServiceAddress},
* creating one in the database if necessary. We special-case GV1 members because we want to
* prioritize E164 addresses and not use the UUIDs if possible.
*/
@WorkerThread
public static @NonNull Recipient externalGV1Member(@NonNull Context context, @NonNull SignalServiceAddress address) {
if (address.getNumber().isPresent()) {
return externalPush(context, null, address.getNumber().get(), false);
} else {
return externalPush(context, address.getUuid().orNull(), null, false);
}
}
/**
* Returns a fully-populated {@link Recipient} based off of a {@link SignalServiceAddress},
* creating one in the database if necessary. This should only used for high-trust sources,

View File

@ -1060,19 +1060,12 @@ public class SignalServiceMessageSender {
for (SignalServiceAddress address : group.getMembers().get()) {
if (address.getNumber().isPresent()) {
builder.addMembersE164(address.getNumber().get());
}
GroupContext.Member.Builder memberBuilder = GroupContext.Member.newBuilder();
if (address.getUuid().isPresent()) {
memberBuilder.setUuid(address.getUuid().get().toString());
}
if (address.getNumber().isPresent()) {
GroupContext.Member.Builder memberBuilder = GroupContext.Member.newBuilder();
memberBuilder.setE164(address.getNumber().get());
}
builder.addMembers(memberBuilder.build());
builder.addMembers(memberBuilder.build());
}
}
}

View File

@ -873,8 +873,8 @@ public final class SignalServiceContent {
members = new ArrayList<>(content.getGroup().getMembersCount());
for (SignalServiceProtos.GroupContext.Member member : content.getGroup().getMembersList()) {
if (SignalServiceAddress.isValidAddress(member.getUuid(), member.getE164())) {
members.add(new SignalServiceAddress(UuidUtil.parseOrNull(member.getUuid()), member.getE164()));
if (SignalServiceAddress.isValidAddress(null, member.getE164())) {
members.add(new SignalServiceAddress(null, member.getE164()));
} else {
throw new ProtocolInvalidMessageException(new InvalidMessageException("GroupContext.Member had no address!"), null, 0);
}

View File

@ -61,8 +61,8 @@ public class DeviceGroupsInputStream extends ChunkedInputStream{
List<SignalServiceAddress> addressMembers = new ArrayList<>(members.size());
for (GroupDetails.Member member : members) {
if (SignalServiceAddress.isValidAddress(member.getUuid(), member.getE164())) {
addressMembers.add(new SignalServiceAddress(UuidUtil.parseOrNull(member.getUuid()), member.getE164()));
if (SignalServiceAddress.isValidAddress(null, member.getE164())) {
addressMembers.add(new SignalServiceAddress(null, member.getE164()));
} else {
throw new IOException("Missing group member address!");
}

View File

@ -65,18 +65,13 @@ public class DeviceGroupsOutputStream extends ChunkedOutputStream {
List<String> membersE164 = new ArrayList<>(group.getMembers().size());
for (SignalServiceAddress address : group.getMembers()) {
GroupDetails.Member.Builder builder = GroupDetails.Member.newBuilder();
if (address.getUuid().isPresent()) {
builder.setUuid(address.getUuid().get().toString());
}
if (address.getNumber().isPresent()) {
builder.setE164(address.getNumber().get());
membersE164.add(address.getNumber().get());
}
members.add(builder.build());
GroupDetails.Member.Builder builder = GroupDetails.Member.newBuilder();
builder.setE164(address.getNumber().get());
members.add(builder.build());
}
}
groupDetails.addAllMembers(members);

View File

@ -435,7 +435,7 @@ message GroupContext {
}
message Member {
optional string uuid = 1;
// 1 is reserved
optional string e164 = 2;
}
@ -479,7 +479,7 @@ message GroupDetails {
}
message Member {
optional string uuid = 1;
// 1 is reserved
optional string e164 = 2;
}