Rotate profile key when learning of a block by a linked device.

This commit is contained in:
Cody Henthorne
2025-08-14 13:19:58 -04:00
committed by Jeffrey Starke
parent cd26929d39
commit 9ccdbb8e40
5 changed files with 52 additions and 15 deletions

View File

@@ -860,7 +860,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
}
}
fun applyStorageSyncContactInsert(insert: SignalContactRecord) {
fun applyStorageSyncContactInsert(insert: SignalContactRecord, rotateProfileKeyOnBlock: Boolean): Boolean {
val db = writableDatabase
val threadDatabase = threads
val values = getValuesForStorageContact(insert, true)
@@ -877,6 +877,12 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
recipientId = RecipientId.from(id)
}
val profileKeyRotated = if (insert.proto.blocked) {
RecipientUtil.updateProfileSharingAfterBlock(Recipient.resolved(recipientId), rotateProfileKeyOnBlock)
} else {
false
}
if (insert.proto.identityKey.isNotEmpty() && (insert.proto.signalAci != null || insert.proto.signalPni != null)) {
try {
val serviceId: ServiceId = insert.proto.signalAci ?: insert.proto.signalPni!!
@@ -892,9 +898,11 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
}
threadDatabase.applyStorageSyncUpdate(recipientId, insert)
return profileKeyRotated
}
fun applyStorageSyncContactUpdate(update: StorageRecordUpdate<SignalContactRecord>) {
fun applyStorageSyncContactUpdate(update: StorageRecordUpdate<SignalContactRecord>, rotateProfileKeyOnBlock: Boolean): Boolean {
val db = writableDatabase
val identityStore = AppDependencies.protocolStore.aci().identities()
val values = getValuesForStorageContact(update.new, false)
@@ -925,6 +933,12 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
db.update(TABLE_NAME, clearValues, ID_WHERE, SqlUtil.buildArgs(recipientId))
}
val profileKeyRotated = if (update.new.proto.blocked && !update.old.proto.blocked) {
RecipientUtil.updateProfileSharingAfterBlock(Recipient.resolved(recipientId), rotateProfileKeyOnBlock)
} else {
false
}
try {
val oldIdentityRecord = identityStore.getIdentityRecord(recipientId)
if (update.new.proto.identityKey.isNotEmpty() && update.new.proto.signalAci != null) {
@@ -948,6 +962,8 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
threads.applyStorageSyncUpdate(recipientId, update.new)
AppDependencies.databaseObserver.notifyRecipientChanged(recipientId)
return profileKeyRotated
}
private fun resolvePotentialUsernameConflicts(username: String?, recipientId: RecipientId) {

View File

@@ -90,6 +90,7 @@ import org.thoughtcrime.securesms.payments.MobileCoinPublicAddress
import org.thoughtcrime.securesms.ratelimit.RateLimitUtil
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.recipients.RecipientUtil
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkCredentials
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkRoomId
import org.thoughtcrime.securesms.service.webrtc.links.SignalCallLinkState
@@ -1170,7 +1171,7 @@ object SyncMessageProcessor {
}
MessageRequestResponse.Type.BLOCK -> {
SignalDatabase.recipients.setBlocked(recipient.id, true)
SignalDatabase.recipients.setProfileSharing(recipient.id, false)
RecipientUtil.updateProfileSharingAfterBlock(recipient, true)
SignalDatabase.messages.insertMessageOutbox(
message = OutgoingMessage.blockedMessage(recipient, System.currentTimeMillis(), TimeUnit.SECONDS.toMillis(recipient.expiresInSeconds.toLong())),
threadId = threadId
@@ -1178,7 +1179,7 @@ object SyncMessageProcessor {
}
MessageRequestResponse.Type.BLOCK_AND_DELETE -> {
SignalDatabase.recipients.setBlocked(recipient.id, true)
SignalDatabase.recipients.setProfileSharing(recipient.id, false)
RecipientUtil.updateProfileSharingAfterBlock(recipient, true)
if (threadId > 0) {
SignalDatabase.threads.deleteConversation(threadId, syncThreadDelete = false)
}
@@ -1191,7 +1192,7 @@ object SyncMessageProcessor {
}
MessageRequestResponse.Type.BLOCK_AND_SPAM -> {
SignalDatabase.recipients.setBlocked(recipient.id, true)
SignalDatabase.recipients.setProfileSharing(recipient.id, false)
RecipientUtil.updateProfileSharingAfterBlock(recipient, true)
SignalDatabase.messages.insertMessageOutbox(
message = OutgoingMessage.reportSpamMessage(recipient, System.currentTimeMillis(), TimeUnit.SECONDS.toMillis(recipient.expiresInSeconds.toLong())),
threadId = threadId

View File

@@ -176,18 +176,30 @@ public class RecipientUtil {
SignalDatabase.recipients().setBlocked(recipient.getId(), true);
insertBlockedUpdate(recipient, SignalDatabase.threads().getOrCreateThreadIdFor(recipient));
if (recipient.isSystemContact() || recipient.isProfileSharing() || isProfileSharedViaGroup(recipient)) {
SignalDatabase.recipients().setProfileSharing(recipient.getId(), false);
AppDependencies.getJobManager().startChain(new RefreshOwnProfileJob())
.then(new RotateProfileKeyJob())
.enqueue();
}
RecipientUtil.updateProfileSharingAfterBlock(recipient, true);
AppDependencies.getJobManager().add(new MultiDeviceBlockedUpdateJob());
StorageSyncHelper.scheduleSyncForDataChange();
}
@WorkerThread
public static boolean updateProfileSharingAfterBlock(@NonNull Recipient recipient, boolean rotateProfileKeyOnBlock) {
if (recipient.isSystemContact() || recipient.isProfileSharing() || isProfileSharedViaGroup(recipient)) {
SignalDatabase.recipients().setProfileSharing(recipient.getId(), false);
if (rotateProfileKeyOnBlock) {
Log.i(TAG, "Rotating profile key");
AppDependencies.getJobManager().startChain(new RefreshOwnProfileJob())
.then(new RotateProfileKeyJob())
.enqueue();
return true;
}
}
return false;
}
@WorkerThread
public static void unblock(@NonNull Recipient recipient) {
if (!isBlockable(recipient)) {

View File

@@ -48,6 +48,8 @@ class ContactRecordProcessor(
}
}
private var rotateProfileKeyOnBlock = true
constructor() : this(
selfAci = SignalStore.account.aci,
selfPni = SignalStore.account.pni,
@@ -247,11 +249,17 @@ class ContactRecordProcessor(
}
override fun insertLocal(record: SignalContactRecord) {
recipientTable.applyStorageSyncContactInsert(record)
val profileKeyRotated = recipientTable.applyStorageSyncContactInsert(record, rotateProfileKeyOnBlock)
if (profileKeyRotated) {
rotateProfileKeyOnBlock = false
}
}
override fun updateLocal(update: StorageRecordUpdate<SignalContactRecord>) {
recipientTable.applyStorageSyncContactUpdate(update)
val profileKeyRotated = recipientTable.applyStorageSyncContactUpdate(update, rotateProfileKeyOnBlock)
if (profileKeyRotated) {
rotateProfileKeyOnBlock = false
}
}
override fun compare(lhs: SignalContactRecord, rhs: SignalContactRecord): Int {