mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-23 18:15:22 +00:00
fix: closed groups now propagate properly without self-sends
This commit is contained in:
parent
e62eb819c9
commit
fd0596f9ea
@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.database.GroupDatabase;
|
|||||||
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||||
|
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.jobs.AvatarDownloadJob;
|
import org.thoughtcrime.securesms.jobs.AvatarDownloadJob;
|
||||||
import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob;
|
import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob;
|
||||||
import org.session.libsignal.utilities.logging.Log;
|
import org.session.libsignal.utilities.logging.Log;
|
||||||
@ -123,11 +124,19 @@ public class GroupMessageProcessor {
|
|||||||
{
|
{
|
||||||
|
|
||||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||||
|
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
|
||||||
String id = GroupUtil.getEncodedId(group);
|
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);
|
String userMasterDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
||||||
if (userMasterDevice == null) { userMasterDevice = TextSecurePreferences.getLocalNumber(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) {
|
if (group.getGroupType() == SignalServiceGroup.GroupType.SIGNAL) {
|
||||||
// Loki - Only update the group if the group admin sent the message
|
// Loki - Only update the group if the group admin sent the message
|
||||||
String masterDevice = MultiDeviceProtocol.shared.getMasterDevice(content.getSender());
|
String masterDevice = MultiDeviceProtocol.shared.getMasterDevice(content.getSender());
|
||||||
|
@ -586,11 +586,15 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle sync message from ourselves
|
// 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<Attachment> attachments = PointerAttachment.forPointers(message.getAttachments());
|
List<Attachment> attachments = PointerAttachment.forPointers(message.getAttachments());
|
||||||
|
|
||||||
Address targetAddress = Address.fromSerialized(syncTarget);
|
|
||||||
|
|
||||||
OutgoingMediaMessage mediaMessage = new OutgoingMediaMessage(masterRecipient, message.getBody().orNull(),
|
OutgoingMediaMessage mediaMessage = new OutgoingMediaMessage(masterRecipient, message.getBody().orNull(),
|
||||||
attachments,
|
attachments,
|
||||||
message.getTimestamp(), -1,
|
message.getTimestamp(), -1,
|
||||||
@ -618,7 +622,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
try {
|
try {
|
||||||
|
|
||||||
// Check if we have the thread already
|
// 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());
|
insertResult = database.insertSecureDecryptedMessageOutbox(mediaMessage, threadID, content.getTimestamp());
|
||||||
|
|
||||||
@ -843,8 +847,13 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
|
|
||||||
if (smsMessageId.isPresent() && !message.getGroupInfo().isPresent()) {
|
if (smsMessageId.isPresent() && !message.getGroupInfo().isPresent()) {
|
||||||
threadId = database.updateBundleMessageBody(smsMessageId.get(), body).second;
|
threadId = database.updateBundleMessageBody(smsMessageId.get(), body).second;
|
||||||
|
} 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()) {
|
} else if (syncTarget != null && !syncTarget.isEmpty()) {
|
||||||
Address targetAddress = Address.fromSerialized(syncTarget);
|
targetAddress = Address.fromSerialized(syncTarget);
|
||||||
|
}
|
||||||
|
|
||||||
if (DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(message.getTimestamp(), targetAddress) != null) {
|
if (DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(message.getTimestamp(), targetAddress) != null) {
|
||||||
Log.d("Loki","Message already exists, don't insert again");
|
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; }
|
if (tm.getMessageBody().length() == 0) { return; }
|
||||||
|
|
||||||
// Check if we have the thread already
|
// 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
|
// Insert the message into the database
|
||||||
|
@ -194,22 +194,6 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (existingNetworkFailures.isEmpty() && networkFailures.isEmpty() && identityMismatches.isEmpty() && existingIdentityMismatches.isEmpty()) {
|
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<UnidentifiedAccessPair> 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);
|
database.markAsSent(messageId, true);
|
||||||
|
|
||||||
markAttachmentsUploaded(messageId, message.getAttachments());
|
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;
|
SignalServiceGroup.GroupType groupType = address.isOpenGroup() ? SignalServiceGroup.GroupType.PUBLIC_CHAT : SignalServiceGroup.GroupType.SIGNAL;
|
||||||
|
|
||||||
|
@ -18,10 +18,11 @@ import org.thoughtcrime.securesms.loki.utilities.KeyPairUtilities
|
|||||||
|
|
||||||
class SessionProtocolImpl(private val context: Context) : SessionProtocol {
|
class SessionProtocolImpl(private val context: Context) : SessionProtocol {
|
||||||
|
|
||||||
|
private val sodium by lazy { LazySodiumAndroid(SodiumAndroid()) }
|
||||||
|
|
||||||
override fun encrypt(plaintext: ByteArray, recipientHexEncodedX25519PublicKey: String): ByteArray {
|
override fun encrypt(plaintext: ByteArray, recipientHexEncodedX25519PublicKey: String): ByteArray {
|
||||||
val userED25519KeyPair = KeyPairUtilities.getUserED25519KeyPair(context) ?: throw SessionProtocol.Exception.NoUserED25519KeyPair
|
val userED25519KeyPair = KeyPairUtilities.getUserED25519KeyPair(context) ?: throw SessionProtocol.Exception.NoUserED25519KeyPair
|
||||||
val recipientX25519PublicKey = Hex.fromStringCondensed(recipientHexEncodedX25519PublicKey.removing05PrefixIfNeeded())
|
val recipientX25519PublicKey = Hex.fromStringCondensed(recipientHexEncodedX25519PublicKey.removing05PrefixIfNeeded())
|
||||||
val sodium = LazySodiumAndroid(SodiumAndroid())
|
|
||||||
|
|
||||||
val verificationData = plaintext + userED25519KeyPair.publicKey.asBytes + recipientX25519PublicKey
|
val verificationData = plaintext + userED25519KeyPair.publicKey.asBytes + recipientX25519PublicKey
|
||||||
val signature = ByteArray(Sign.BYTES)
|
val signature = ByteArray(Sign.BYTES)
|
||||||
@ -47,7 +48,6 @@ class SessionProtocolImpl(private val context: Context) : SessionProtocol {
|
|||||||
val recipientX25519PrivateKey = x25519KeyPair.privateKey.serialize()
|
val recipientX25519PrivateKey = x25519KeyPair.privateKey.serialize()
|
||||||
val recipientX25519PublicKey = Hex.fromStringCondensed(x25519KeyPair.hexEncodedPublicKey.removing05PrefixIfNeeded())
|
val recipientX25519PublicKey = Hex.fromStringCondensed(x25519KeyPair.hexEncodedPublicKey.removing05PrefixIfNeeded())
|
||||||
Log.d("Test", "recipientX25519PublicKey: $recipientX25519PublicKey")
|
Log.d("Test", "recipientX25519PublicKey: $recipientX25519PublicKey")
|
||||||
val sodium = LazySodiumAndroid(SodiumAndroid())
|
|
||||||
val signatureSize = Sign.BYTES
|
val signatureSize = Sign.BYTES
|
||||||
val ed25519PublicKeySize = Sign.PUBLICKEYBYTES
|
val ed25519PublicKeySize = Sign.PUBLICKEYBYTES
|
||||||
|
|
||||||
|
@ -70,7 +70,6 @@ object ClosedGroupsProtocolV2 {
|
|||||||
// Send a closed group update message to all members individually
|
// Send a closed group update message to all members individually
|
||||||
val closedGroupUpdateKind = ClosedGroupUpdateMessageSendJobV2.Kind.New(Hex.fromStringCondensed(groupPublicKey), name, encryptionKeyPair, membersAsData, adminsAsData)
|
val closedGroupUpdateKind = ClosedGroupUpdateMessageSendJobV2.Kind.New(Hex.fromStringCondensed(groupPublicKey), name, encryptionKeyPair, membersAsData, adminsAsData)
|
||||||
for (member in members) {
|
for (member in members) {
|
||||||
if (member == userPublicKey) { continue }
|
|
||||||
val job = ClosedGroupUpdateMessageSendJobV2(member, closedGroupUpdateKind)
|
val job = ClosedGroupUpdateMessageSendJobV2(member, closedGroupUpdateKind)
|
||||||
job.setContext(context)
|
job.setContext(context)
|
||||||
job.onRun() // Run the job immediately to make all of this sync
|
job.onRun() // Run the job immediately to make all of this sync
|
||||||
|
@ -14,7 +14,7 @@ import org.session.libsignal.libsignal.ecc.ECKeyPair
|
|||||||
|
|
||||||
object KeyPairUtilities {
|
object KeyPairUtilities {
|
||||||
|
|
||||||
private val sodium = LazySodiumAndroid(SodiumAndroid())
|
private val sodium by lazy { LazySodiumAndroid(SodiumAndroid()) }
|
||||||
|
|
||||||
fun generate(): KeyPairGenerationResult {
|
fun generate(): KeyPairGenerationResult {
|
||||||
val seed = sodium.randomBytesBuf(16)
|
val seed = sodium.randomBytesBuf(16)
|
||||||
|
@ -13,7 +13,7 @@ import org.session.libsignal.service.api.crypto.UnidentifiedAccessPair
|
|||||||
|
|
||||||
object UnidentifiedAccessUtil {
|
object UnidentifiedAccessUtil {
|
||||||
private val TAG = UnidentifiedAccessUtil::class.simpleName
|
private val TAG = UnidentifiedAccessUtil::class.simpleName
|
||||||
private val sodium = LazySodiumAndroid(SodiumAndroid())
|
private val sodium by lazy { LazySodiumAndroid(SodiumAndroid()) }
|
||||||
|
|
||||||
fun getAccessFor(recipientPublicKey: String): UnidentifiedAccessPair? {
|
fun getAccessFor(recipientPublicKey: String): UnidentifiedAccessPair? {
|
||||||
try {
|
try {
|
||||||
|
@ -331,7 +331,6 @@ public class SignalServiceCipher {
|
|||||||
kotlin.Pair<byte[], String> plaintextAndSenderPublicKey = SessionProtocolUtilities.INSTANCE.decryptClosedGroupCiphertext(ciphertext, groupPublicKey, apiDB, sessionProtocolImpl);
|
kotlin.Pair<byte[], String> plaintextAndSenderPublicKey = SessionProtocolUtilities.INSTANCE.decryptClosedGroupCiphertext(ciphertext, groupPublicKey, apiDB, sessionProtocolImpl);
|
||||||
paddedMessage = plaintextAndSenderPublicKey.getFirst();
|
paddedMessage = plaintextAndSenderPublicKey.getFirst();
|
||||||
String senderPublicKey = plaintextAndSenderPublicKey.getSecond();
|
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);
|
metadata = new Metadata(senderPublicKey, 1, envelope.getTimestamp(), false);
|
||||||
sessionVersion = sessionCipher.getSessionVersion();
|
sessionVersion = sessionCipher.getSessionVersion();
|
||||||
} else if (envelope.isPreKeySignalMessage()) {
|
} else if (envelope.isPreKeySignalMessage()) {
|
||||||
|
Loading…
Reference in New Issue
Block a user