Reset backup auth credentials on verification failure.

This commit is contained in:
Cody Henthorne
2025-06-05 11:10:56 -04:00
committed by Greyson Parrelli
parent 297bca4c0f
commit df2e88eaac
4 changed files with 149 additions and 17 deletions

View File

@@ -31,6 +31,7 @@ import org.signal.core.util.requireNonNullBlob
import org.signal.core.util.stream.NonClosingOutputStream
import org.signal.core.util.urlEncode
import org.signal.core.util.withinTransaction
import org.signal.libsignal.zkgroup.VerificationFailedException
import org.signal.libsignal.zkgroup.backups.BackupLevel
import org.signal.libsignal.zkgroup.profiles.ProfileKey
import org.thoughtcrime.securesms.attachments.Attachment
@@ -85,6 +86,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.util.RemoteConfig
import org.thoughtcrime.securesms.util.toMillis
import org.whispersystems.signalservice.api.AccountEntropyPool
import org.whispersystems.signalservice.api.ApplicationErrorAction
import org.whispersystems.signalservice.api.NetworkResult
import org.whispersystems.signalservice.api.StatusCodeErrorAction
import org.whispersystems.signalservice.api.archive.ArchiveGetMediaItemsResponse
@@ -150,6 +152,14 @@ object BackupRepository {
}
}
private val clearAuthCredentials: ApplicationErrorAction = { error ->
if (error.getCause() is VerificationFailedException) {
Log.w(TAG, "Unable to verify/receive credentials, clearing cache to fetch new.", error.getCause())
SignalStore.backup.messageCredentials.clearAll()
SignalStore.backup.mediaCredentials.clearAll()
}
}
/**
* Triggers backup id reservation. As documented, this is safe to perform multiple times.
*/
@@ -1504,7 +1514,9 @@ object BackupRepository {
return if (!RemoteConfig.messageBackups) {
NetworkResult.StatusCodeError(555, null, null, emptyMap(), NonSuccessfulResponseCodeException(555, "Backups disabled!"))
} else if (SignalStore.backup.backupsInitialized) {
getArchiveServiceAccessPair().runOnStatusCodeError(resetInitializedStateErrorAction)
getArchiveServiceAccessPair()
.runOnStatusCodeError(resetInitializedStateErrorAction)
.runOnApplicationError(clearAuthCredentials)
} else if (isPreRestoreDuringRegistration()) {
Log.w(TAG, "Requesting/using auth credentials in pre-restore state", Throwable())
getArchiveServiceAccessPair()
@@ -1519,6 +1531,7 @@ object BackupRepository {
.then { credential -> SignalNetwork.archive.setPublicKey(SignalStore.account.requireAci(), credential.mediaBackupAccess).map { credential } }
.runIfSuccessful { SignalStore.backup.backupsInitialized = true }
.runOnStatusCodeError(resetInitializedStateErrorAction)
.runOnApplicationError(clearAuthCredentials)
}
}

View File

@@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.jobs
import org.signal.core.util.logging.Log
import org.signal.libsignal.zkgroup.VerificationFailedException
import org.thoughtcrime.securesms.attachments.AttachmentId
import org.thoughtcrime.securesms.attachments.Cdn
import org.thoughtcrime.securesms.attachments.DatabaseAttachment
@@ -134,8 +135,13 @@ class CopyAttachmentToArchiveJob private constructor(private val attachmentId: A
}
is NetworkResult.ApplicationError -> {
Log.w(TAG, "[$attachmentId] Encountered a fatal error when trying to upload!")
Result.fatalFailure(RuntimeException(archiveResult.throwable))
if (archiveResult.throwable is VerificationFailedException) {
Log.w(TAG, "[$attachmentId] Encountered a verification failure when trying to upload! Retrying.")
Result.retry(defaultBackoff())
} else {
Log.w(TAG, "[$attachmentId] Encountered a fatal error when trying to upload!")
Result.fatalFailure(RuntimeException(archiveResult.throwable))
}
}
}