From fd0596f9eaab499055a223f06e0686c07b8d9c7c Mon Sep 17 00:00:00 2001 From: jubb Date: Wed, 10 Feb 2021 17:57:08 +1100 Subject: [PATCH] fix: closed groups now propagate properly without self-sends --- .../groups/GroupMessageProcessor.java | 9 ++++++++ .../securesms/jobs/PushDecryptJob.java | 23 +++++++++++++------ .../securesms/jobs/PushGroupSendJob.java | 18 +-------------- .../securesms/loki/api/SessionProtocolImpl.kt | 4 ++-- .../loki/protocol/ClosedGroupsProtocolV2.kt | 1 - .../loki/utilities/KeyPairUtilities.kt | 2 +- .../utilities/UnidentifiedAccessUtil.kt | 2 +- .../api/crypto/SignalServiceCipher.java | 1 - 8 files changed, 30 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java index ab5dede3ea..e6d9090021 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java @@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult; import org.thoughtcrime.securesms.database.MmsDatabase; import org.thoughtcrime.securesms.database.SmsDatabase; +import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.jobs.AvatarDownloadJob; import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob; import org.session.libsignal.utilities.logging.Log; @@ -123,11 +124,19 @@ public class GroupMessageProcessor { { GroupDatabase database = DatabaseFactory.getGroupDatabase(context); + ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context); String id = GroupUtil.getEncodedId(group); + Address address = Address.Companion.fromExternal(context, GroupUtil.getEncodedId(group)); + Recipient recipient = Recipient.from(context, address, false); String userMasterDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context); if (userMasterDevice == null) { userMasterDevice = TextSecurePreferences.getLocalNumber(context); } + if (content.getSender().equals(userMasterDevice)) { + long threadId = threadDatabase.getThreadIdIfExistsFor(recipient); + return threadId == -1 ? null : threadId; + } + if (group.getGroupType() == SignalServiceGroup.GroupType.SIGNAL) { // Loki - Only update the group if the group admin sent the message String masterDevice = MultiDeviceProtocol.shared.getMasterDevice(content.getSender()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java index 1047085422..40cfb1fdc2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java @@ -586,11 +586,15 @@ public class PushDecryptJob extends BaseJob implements InjectableType { } // Handle sync message from ourselves - if (syncTarget != null && !syncTarget.isEmpty()) { + if (syncTarget != null && !syncTarget.isEmpty() || TextSecurePreferences.getLocalNumber(context).equals(content.getSender())) { + Address targetAddress = masterRecipient.getAddress(); + if (message.getGroupInfo().isPresent()) { + targetAddress = Address.Companion.fromSerialized(GroupUtil.getEncodedId(message.getGroupInfo().get())); + } else if (syncTarget != null && !syncTarget.isEmpty()) { + targetAddress = Address.fromSerialized(syncTarget); + } List attachments = PointerAttachment.forPointers(message.getAttachments()); - Address targetAddress = Address.fromSerialized(syncTarget); - OutgoingMediaMessage mediaMessage = new OutgoingMediaMessage(masterRecipient, message.getBody().orNull(), attachments, message.getTimestamp(), -1, @@ -618,7 +622,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType { try { // Check if we have the thread already - long threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(syncTarget); + long threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(targetAddress.serialize()); insertResult = database.insertSecureDecryptedMessageOutbox(mediaMessage, threadID, content.getTimestamp()); @@ -843,8 +847,13 @@ public class PushDecryptJob extends BaseJob implements InjectableType { if (smsMessageId.isPresent() && !message.getGroupInfo().isPresent()) { threadId = database.updateBundleMessageBody(smsMessageId.get(), body).second; - } else if (syncTarget != null && !syncTarget.isEmpty()) { - Address targetAddress = Address.fromSerialized(syncTarget); + } else if (syncTarget != null && !syncTarget.isEmpty() || TextSecurePreferences.getLocalNumber(context).equals(content.getSender())) { + Address targetAddress = masterRecipient.getAddress(); + if (message.getGroupInfo().isPresent()) { + targetAddress = Address.Companion.fromSerialized(GroupUtil.getEncodedId(message.getGroupInfo().get())); + } else if (syncTarget != null && !syncTarget.isEmpty()) { + targetAddress = Address.fromSerialized(syncTarget); + } if (DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(message.getTimestamp(), targetAddress) != null) { Log.d("Loki","Message already exists, don't insert again"); @@ -858,7 +867,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType { if (tm.getMessageBody().length() == 0) { return; } // Check if we have the thread already - long threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(syncTarget); + long threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(targetAddress.serialize()); // Insert the message into the database diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java index e4c8b588df..e5ef36cb0d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java @@ -194,22 +194,6 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType { } if (existingNetworkFailures.isEmpty() && networkFailures.isEmpty() && identityMismatches.isEmpty() && existingIdentityMismatches.isEmpty()) { - Address address = message.getRecipient().getAddress(); - if (!address.isOpenGroup()) { - try { - SignalServiceDataMessage selfSend = getDataMessage(address, message) - .withSyncTarget(address.toGroupString()) - .build(); - // send to ourselves to sync multi-device - Optional syncAccess = UnidentifiedAccessUtil.getAccessForSync(context); - SendMessageResult selfSendResult = messageSender.sendMessage(messageId, localAddress, syncAccess, selfSend); - if (selfSendResult.getLokiAPIError() != null) { - throw selfSendResult.getLokiAPIError(); - } - } catch (Exception e) { - Log.e("Loki", "Error sending message to ourselves", e); - } - } database.markAsSent(messageId, true); markAttachmentsUploaded(messageId, message.getAttachments()); @@ -290,7 +274,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType { } } - public SignalServiceDataMessage.Builder getDataMessage(Address address, OutgoingMediaMessage message) { + public SignalServiceDataMessage.Builder getDataMessage(Address address, OutgoingMediaMessage message) throws IOException { SignalServiceGroup.GroupType groupType = address.isOpenGroup() ? SignalServiceGroup.GroupType.PUBLIC_CHAT : SignalServiceGroup.GroupType.SIGNAL; diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/api/SessionProtocolImpl.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/api/SessionProtocolImpl.kt index 8a8c18565d..e3c5b0aa6a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/api/SessionProtocolImpl.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/api/SessionProtocolImpl.kt @@ -18,10 +18,11 @@ import org.thoughtcrime.securesms.loki.utilities.KeyPairUtilities class SessionProtocolImpl(private val context: Context) : SessionProtocol { + private val sodium by lazy { LazySodiumAndroid(SodiumAndroid()) } + override fun encrypt(plaintext: ByteArray, recipientHexEncodedX25519PublicKey: String): ByteArray { val userED25519KeyPair = KeyPairUtilities.getUserED25519KeyPair(context) ?: throw SessionProtocol.Exception.NoUserED25519KeyPair val recipientX25519PublicKey = Hex.fromStringCondensed(recipientHexEncodedX25519PublicKey.removing05PrefixIfNeeded()) - val sodium = LazySodiumAndroid(SodiumAndroid()) val verificationData = plaintext + userED25519KeyPair.publicKey.asBytes + recipientX25519PublicKey val signature = ByteArray(Sign.BYTES) @@ -47,7 +48,6 @@ class SessionProtocolImpl(private val context: Context) : SessionProtocol { val recipientX25519PrivateKey = x25519KeyPair.privateKey.serialize() val recipientX25519PublicKey = Hex.fromStringCondensed(x25519KeyPair.hexEncodedPublicKey.removing05PrefixIfNeeded()) Log.d("Test", "recipientX25519PublicKey: $recipientX25519PublicKey") - val sodium = LazySodiumAndroid(SodiumAndroid()) val signatureSize = Sign.BYTES val ed25519PublicKeySize = Sign.PUBLICKEYBYTES diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt index 1adc93d44d..c97591b879 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt @@ -70,7 +70,6 @@ object ClosedGroupsProtocolV2 { // Send a closed group update message to all members individually val closedGroupUpdateKind = ClosedGroupUpdateMessageSendJobV2.Kind.New(Hex.fromStringCondensed(groupPublicKey), name, encryptionKeyPair, membersAsData, adminsAsData) for (member in members) { - if (member == userPublicKey) { continue } val job = ClosedGroupUpdateMessageSendJobV2(member, closedGroupUpdateKind) job.setContext(context) job.onRun() // Run the job immediately to make all of this sync diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/KeyPairUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/KeyPairUtilities.kt index e965beeb11..8acd255597 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/KeyPairUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/KeyPairUtilities.kt @@ -14,7 +14,7 @@ import org.session.libsignal.libsignal.ecc.ECKeyPair object KeyPairUtilities { - private val sodium = LazySodiumAndroid(SodiumAndroid()) + private val sodium by lazy { LazySodiumAndroid(SodiumAndroid()) } fun generate(): KeyPairGenerationResult { val seed = sodium.randomBytesBuf(16) diff --git a/libsession/src/main/java/org/session/libsession/messaging/utilities/UnidentifiedAccessUtil.kt b/libsession/src/main/java/org/session/libsession/messaging/utilities/UnidentifiedAccessUtil.kt index 671189778f..56427bfb62 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/utilities/UnidentifiedAccessUtil.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/utilities/UnidentifiedAccessUtil.kt @@ -13,7 +13,7 @@ import org.session.libsignal.service.api.crypto.UnidentifiedAccessPair object UnidentifiedAccessUtil { private val TAG = UnidentifiedAccessUtil::class.simpleName - private val sodium = LazySodiumAndroid(SodiumAndroid()) + private val sodium by lazy { LazySodiumAndroid(SodiumAndroid()) } fun getAccessFor(recipientPublicKey: String): UnidentifiedAccessPair? { try { diff --git a/libsignal/src/main/java/org/session/libsignal/service/api/crypto/SignalServiceCipher.java b/libsignal/src/main/java/org/session/libsignal/service/api/crypto/SignalServiceCipher.java index 608dee89cd..c5424d2cf0 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/api/crypto/SignalServiceCipher.java +++ b/libsignal/src/main/java/org/session/libsignal/service/api/crypto/SignalServiceCipher.java @@ -331,7 +331,6 @@ public class SignalServiceCipher { kotlin.Pair plaintextAndSenderPublicKey = SessionProtocolUtilities.INSTANCE.decryptClosedGroupCiphertext(ciphertext, groupPublicKey, apiDB, sessionProtocolImpl); paddedMessage = plaintextAndSenderPublicKey.getFirst(); String senderPublicKey = plaintextAndSenderPublicKey.getSecond(); - if (senderPublicKey.equals(localAddress.getNumber())) { throw new SelfSendException(); } // Will be caught and ignored in PushDecryptJob metadata = new Metadata(senderPublicKey, 1, envelope.getTimestamp(), false); sessionVersion = sessionCipher.getSessionVersion(); } else if (envelope.isPreKeySignalMessage()) {