Fix unneeded re-uploade of key got from backup

and disabled prompting for untrusted key sharing
This commit is contained in:
Valere 2022-03-29 15:56:34 +02:00
parent cc107498eb
commit 88cf1a5e67
5 changed files with 183 additions and 135 deletions

View File

@ -20,6 +20,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
@ -168,6 +169,11 @@ internal class OutgoingKeyRequestManager @Inject constructor(
sequencer.post { sequencer.post {
cryptoStore.deleteOutgoingRoomKeyRequestInState(OutgoingRoomKeyRequestState.SENT) cryptoStore.deleteOutgoingRoomKeyRequestInState(OutgoingRoomKeyRequestState.SENT)
} }
sequencer.post {
delay(1000)
perSessionBackupQueryRateLimiter.refreshBackupInfoIfNeeded(true)
}
} }
} }
} }

View File

@ -68,7 +68,7 @@ internal class PerSessionBackupQueryRateLimiter @Inject constructor(
var backupWasCheckedFromServer: Boolean = false var backupWasCheckedFromServer: Boolean = false
var now = System.currentTimeMillis() var now = System.currentTimeMillis()
private fun refreshBackupInfoIfNeeded(force: Boolean = false) { fun refreshBackupInfoIfNeeded(force: Boolean = false) {
if (backupWasCheckedFromServer && !force) return if (backupWasCheckedFromServer && !force) return
Timber.tag(loggerTag.value).v("Checking if can access a backup") Timber.tag(loggerTag.value).v("Checking if can access a backup")
backupWasCheckedFromServer = true backupWasCheckedFromServer = true

View File

@ -63,16 +63,11 @@ import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.RoomKeysBack
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.UpdateKeysBackupVersionBody import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.UpdateKeysBackupVersionBody
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.CreateKeysBackupVersionTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.CreateKeysBackupVersionTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.DeleteBackupTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.DeleteBackupTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.DeleteRoomSessionDataTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.DeleteRoomSessionsDataTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.DeleteSessionsDataTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.GetKeysBackupLastVersionTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.GetKeysBackupLastVersionTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.GetKeysBackupVersionTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.GetKeysBackupVersionTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.GetRoomSessionDataTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.GetRoomSessionDataTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.GetRoomSessionsDataTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.GetRoomSessionsDataTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.GetSessionsDataTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.GetSessionsDataTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreRoomSessionDataTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreRoomSessionsDataTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreSessionsDataTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreSessionsDataTask
import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.UpdateKeysBackupVersionTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.UpdateKeysBackupVersionTask
import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper2 import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper2
@ -112,16 +107,11 @@ internal class DefaultKeysBackupService @Inject constructor(
// Tasks // Tasks
private val createKeysBackupVersionTask: CreateKeysBackupVersionTask, private val createKeysBackupVersionTask: CreateKeysBackupVersionTask,
private val deleteBackupTask: DeleteBackupTask, private val deleteBackupTask: DeleteBackupTask,
private val deleteRoomSessionDataTask: DeleteRoomSessionDataTask,
private val deleteRoomSessionsDataTask: DeleteRoomSessionsDataTask,
private val deleteSessionDataTask: DeleteSessionsDataTask,
private val getKeysBackupLastVersionTask: GetKeysBackupLastVersionTask, private val getKeysBackupLastVersionTask: GetKeysBackupLastVersionTask,
private val getKeysBackupVersionTask: GetKeysBackupVersionTask, private val getKeysBackupVersionTask: GetKeysBackupVersionTask,
private val getRoomSessionDataTask: GetRoomSessionDataTask, private val getRoomSessionDataTask: GetRoomSessionDataTask,
private val getRoomSessionsDataTask: GetRoomSessionsDataTask, private val getRoomSessionsDataTask: GetRoomSessionsDataTask,
private val getSessionsDataTask: GetSessionsDataTask, private val getSessionsDataTask: GetSessionsDataTask,
private val storeRoomSessionDataTask: StoreRoomSessionDataTask,
private val storeSessionsDataTask: StoreRoomSessionsDataTask,
private val storeSessionDataTask: StoreSessionsDataTask, private val storeSessionDataTask: StoreSessionsDataTask,
private val updateKeysBackupVersionTask: UpdateKeysBackupVersionTask, private val updateKeysBackupVersionTask: UpdateKeysBackupVersionTask,
// Task executor // Task executor
@ -168,58 +158,63 @@ internal class DefaultKeysBackupService @Inject constructor(
override fun prepareKeysBackupVersion(password: String?, override fun prepareKeysBackupVersion(password: String?,
progressListener: ProgressListener?, progressListener: ProgressListener?,
callback: MatrixCallback<MegolmBackupCreationInfo>) { callback: MatrixCallback<MegolmBackupCreationInfo>) {
cryptoCoroutineScope.launch(coroutineDispatchers.main) { cryptoCoroutineScope.launch(coroutineDispatchers.io) {
runCatching { try {
withContext(coroutineDispatchers.crypto) { val olmPkDecryption = OlmPkDecryption()
val olmPkDecryption = OlmPkDecryption() val signalableMegolmBackupAuthData = if (password != null) {
val signalableMegolmBackupAuthData = if (password != null) { // Generate a private key from the password
// Generate a private key from the password val backgroundProgressListener = if (progressListener == null) {
val backgroundProgressListener = if (progressListener == null) { null
null } else {
} else { object : ProgressListener {
object : ProgressListener { override fun onProgress(progress: Int, total: Int) {
override fun onProgress(progress: Int, total: Int) { uiHandler.post {
uiHandler.post { try {
try { progressListener.onProgress(progress, total)
progressListener.onProgress(progress, total) } catch (e: Exception) {
} catch (e: Exception) { Timber.e(e, "prepareKeysBackupVersion: onProgress failure")
Timber.e(e, "prepareKeysBackupVersion: onProgress failure")
}
} }
} }
} }
} }
val generatePrivateKeyResult = generatePrivateKeyWithPassword(password, backgroundProgressListener)
SignalableMegolmBackupAuthData(
publicKey = olmPkDecryption.setPrivateKey(generatePrivateKeyResult.privateKey),
privateKeySalt = generatePrivateKeyResult.salt,
privateKeyIterations = generatePrivateKeyResult.iterations
)
} else {
val publicKey = olmPkDecryption.generateKey()
SignalableMegolmBackupAuthData(
publicKey = publicKey
)
} }
val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, signalableMegolmBackupAuthData.signalableJSONDictionary()) val generatePrivateKeyResult = generatePrivateKeyWithPassword(password, backgroundProgressListener)
SignalableMegolmBackupAuthData(
val signedMegolmBackupAuthData = MegolmBackupAuthData( publicKey = olmPkDecryption.setPrivateKey(generatePrivateKeyResult.privateKey),
publicKey = signalableMegolmBackupAuthData.publicKey, privateKeySalt = generatePrivateKeyResult.salt,
privateKeySalt = signalableMegolmBackupAuthData.privateKeySalt, privateKeyIterations = generatePrivateKeyResult.iterations
privateKeyIterations = signalableMegolmBackupAuthData.privateKeyIterations,
signatures = objectSigner.signObject(canonicalJson)
) )
} else {
val publicKey = olmPkDecryption.generateKey()
MegolmBackupCreationInfo( SignalableMegolmBackupAuthData(
algorithm = MXCRYPTO_ALGORITHM_MEGOLM_BACKUP, publicKey = publicKey
authData = signedMegolmBackupAuthData,
recoveryKey = computeRecoveryKey(olmPkDecryption.privateKey())
) )
} }
}.foldToCallback(callback)
val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, signalableMegolmBackupAuthData.signalableJSONDictionary())
val signedMegolmBackupAuthData = MegolmBackupAuthData(
publicKey = signalableMegolmBackupAuthData.publicKey,
privateKeySalt = signalableMegolmBackupAuthData.privateKeySalt,
privateKeyIterations = signalableMegolmBackupAuthData.privateKeyIterations,
signatures = objectSigner.signObject(canonicalJson)
)
val creationInfo = MegolmBackupCreationInfo(
algorithm = MXCRYPTO_ALGORITHM_MEGOLM_BACKUP,
authData = signedMegolmBackupAuthData,
recoveryKey = computeRecoveryKey(olmPkDecryption.privateKey())
)
uiHandler.post {
callback.onSuccess(creationInfo)
}
} catch (failure: Throwable) {
uiHandler.post {
callback.onFailure(failure)
}
}
} }
} }
@ -267,41 +262,39 @@ internal class DefaultKeysBackupService @Inject constructor(
} }
override fun deleteBackup(version: String, callback: MatrixCallback<Unit>?) { override fun deleteBackup(version: String, callback: MatrixCallback<Unit>?) {
cryptoCoroutineScope.launch(coroutineDispatchers.main) { cryptoCoroutineScope.launch(coroutineDispatchers.io) {
withContext(coroutineDispatchers.crypto) { // If we're currently backing up to this backup... stop.
// If we're currently backing up to this backup... stop. // (We start using it automatically in createKeysBackupVersion so this is symmetrical).
// (We start using it automatically in createKeysBackupVersion so this is symmetrical). if (keysBackupVersion != null && version == keysBackupVersion?.version) {
if (keysBackupVersion != null && version == keysBackupVersion?.version) { resetKeysBackupData()
resetKeysBackupData() keysBackupVersion = null
keysBackupVersion = null keysBackupStateManager.state = KeysBackupState.Unknown
keysBackupStateManager.state = KeysBackupState.Unknown }
}
deleteBackupTask deleteBackupTask
.configureWith(DeleteBackupTask.Params(version)) { .configureWith(DeleteBackupTask.Params(version)) {
this.callback = object : MatrixCallback<Unit> { this.callback = object : MatrixCallback<Unit> {
private fun eventuallyRestartBackup() { private fun eventuallyRestartBackup() {
// Do not stay in KeysBackupState.Unknown but check what is available on the homeserver // Do not stay in KeysBackupState.Unknown but check what is available on the homeserver
if (state == KeysBackupState.Unknown) { if (state == KeysBackupState.Unknown) {
checkAndStartKeysBackup() checkAndStartKeysBackup()
}
}
override fun onSuccess(data: Unit) {
eventuallyRestartBackup()
uiHandler.post { callback?.onSuccess(Unit) }
}
override fun onFailure(failure: Throwable) {
eventuallyRestartBackup()
uiHandler.post { callback?.onFailure(failure) }
} }
} }
override fun onSuccess(data: Unit) {
eventuallyRestartBackup()
uiHandler.post { callback?.onSuccess(Unit) }
}
override fun onFailure(failure: Throwable) {
eventuallyRestartBackup()
uiHandler.post { callback?.onFailure(failure) }
}
} }
.executeBy(taskExecutor) }
} .executeBy(taskExecutor)
} }
} }
@ -480,10 +473,11 @@ internal class DefaultKeysBackupService @Inject constructor(
if (authData == null) { if (authData == null) {
Timber.w("trustKeyBackupVersion:trust: Key backup is missing required data") Timber.w("trustKeyBackupVersion:trust: Key backup is missing required data")
uiHandler.post {
callback.onFailure(IllegalArgumentException("Missing element")) callback.onFailure(IllegalArgumentException("Missing element"))
}
} else { } else {
cryptoCoroutineScope.launch(coroutineDispatchers.main) { cryptoCoroutineScope.launch(coroutineDispatchers.io) {
val updateKeysBackupVersionBody = withContext(coroutineDispatchers.crypto) { val updateKeysBackupVersionBody = withContext(coroutineDispatchers.crypto) {
// Get current signatures, or create an empty set // Get current signatures, or create an empty set
val myUserSignatures = authData.signatures?.get(userId).orEmpty().toMutableMap() val myUserSignatures = authData.signatures?.get(userId).orEmpty().toMutableMap()
@ -535,11 +529,15 @@ internal class DefaultKeysBackupService @Inject constructor(
checkAndStartWithKeysBackupVersion(newKeysBackupVersion) checkAndStartWithKeysBackupVersion(newKeysBackupVersion)
callback.onSuccess(data) uiHandler.post {
callback.onSuccess(data)
}
} }
override fun onFailure(failure: Throwable) { override fun onFailure(failure: Throwable) {
callback.onFailure(failure) uiHandler.post {
callback.onFailure(failure)
}
} }
} }
} }
@ -553,15 +551,14 @@ internal class DefaultKeysBackupService @Inject constructor(
callback: MatrixCallback<Unit>) { callback: MatrixCallback<Unit>) {
Timber.v("trustKeysBackupVersionWithRecoveryKey: version ${keysBackupVersion.version}") Timber.v("trustKeysBackupVersionWithRecoveryKey: version ${keysBackupVersion.version}")
cryptoCoroutineScope.launch(coroutineDispatchers.main) { cryptoCoroutineScope.launch(coroutineDispatchers.io) {
val isValid = withContext(coroutineDispatchers.crypto) { val isValid = isValidRecoveryKeyForKeysBackupVersion(recoveryKey, keysBackupVersion)
isValidRecoveryKeyForKeysBackupVersion(recoveryKey, keysBackupVersion)
}
if (!isValid) { if (!isValid) {
Timber.w("trustKeyBackupVersionWithRecoveryKey: Invalid recovery key.") Timber.w("trustKeyBackupVersionWithRecoveryKey: Invalid recovery key.")
uiHandler.post {
callback.onFailure(IllegalArgumentException("Invalid recovery key or password")) callback.onFailure(IllegalArgumentException("Invalid recovery key or password"))
}
} else { } else {
trustKeysBackupVersion(keysBackupVersion, true, callback) trustKeysBackupVersion(keysBackupVersion, true, callback)
} }
@ -573,15 +570,14 @@ internal class DefaultKeysBackupService @Inject constructor(
callback: MatrixCallback<Unit>) { callback: MatrixCallback<Unit>) {
Timber.v("trustKeysBackupVersionWithPassphrase: version ${keysBackupVersion.version}") Timber.v("trustKeysBackupVersionWithPassphrase: version ${keysBackupVersion.version}")
cryptoCoroutineScope.launch(coroutineDispatchers.main) { cryptoCoroutineScope.launch(coroutineDispatchers.io) {
val recoveryKey = withContext(coroutineDispatchers.crypto) { val recoveryKey = recoveryKeyFromPassword(password, keysBackupVersion, null)
recoveryKeyFromPassword(password, keysBackupVersion, null)
}
if (recoveryKey == null) { if (recoveryKey == null) {
Timber.w("trustKeysBackupVersionWithPassphrase: Key backup is missing required data") Timber.w("trustKeysBackupVersionWithPassphrase: Key backup is missing required data")
uiHandler.post {
callback.onFailure(IllegalArgumentException("Missing element")) callback.onFailure(IllegalArgumentException("Missing element"))
}
} else { } else {
// Check trust using the recovery key // Check trust using the recovery key
trustKeysBackupVersionWithRecoveryKey(keysBackupVersion, recoveryKey, callback) trustKeysBackupVersionWithRecoveryKey(keysBackupVersion, recoveryKey, callback)
@ -592,30 +588,23 @@ internal class DefaultKeysBackupService @Inject constructor(
override fun onSecretKeyGossip(secret: String) { override fun onSecretKeyGossip(secret: String) {
Timber.i("## CrossSigning - onSecretKeyGossip") Timber.i("## CrossSigning - onSecretKeyGossip")
cryptoCoroutineScope.launch(coroutineDispatchers.main) { cryptoCoroutineScope.launch(coroutineDispatchers.io) {
try { try {
when (val keysBackupLastVersionResult = getKeysBackupLastVersionTask.execute(Unit)) { when (val keysBackupLastVersionResult = getKeysBackupLastVersionTask.execute(Unit)) {
KeysBackupLastVersionResult.NoKeysBackup -> { KeysBackupLastVersionResult.NoKeysBackup -> {
Timber.d("No keys backup found") Timber.d("No keys backup found")
} }
is KeysBackupLastVersionResult.KeysBackup -> { // we don't want to start immediately downloading all as it can take very long
val keysBackupVersion = keysBackupLastVersionResult.keysVersionResult
val recoveryKey = computeRecoveryKey(secret.fromBase64()) // val importResult = awaitCallback<ImportRoomKeysResult> {
if (isValidRecoveryKeyForKeysBackupVersion(recoveryKey, keysBackupVersion)) { // restoreKeysWithRecoveryKey(keysBackupVersion, recoveryKey, null, null, null, it)
awaitCallback<Unit> { // }
trustKeysBackupVersion(keysBackupVersion, true, it) withContext(coroutineDispatchers.crypto) {
} cryptoStore.saveBackupRecoveryKey(recoveryKey, keysBackupVersion.version)
val importResult = awaitCallback<ImportRoomKeysResult> {
restoreKeysWithRecoveryKey(keysBackupVersion, recoveryKey, null, null, null, it)
}
withContext(coroutineDispatchers.crypto) {
cryptoStore.saveBackupRecoveryKey(recoveryKey, keysBackupVersion.version)
}
Timber.i("onSecretKeyGossip: Recovered keys $importResult")
} else {
Timber.e("onSecretKeyGossip: Recovery key is not valid ${keysBackupVersion.version}")
}
} }
Timber.i("onSecretKeyGossip: saved valid backup key")
} else {
Timber.e("onSecretKeyGossip: Recovery key is not valid ${keysBackupVersion.version}")
} }
} catch (failure: Throwable) { } catch (failure: Throwable) {
Timber.e("onSecretKeyGossip: failed to trust key backup version ${keysBackupVersion?.version}") Timber.e("onSecretKeyGossip: failed to trust key backup version ${keysBackupVersion?.version}")
@ -678,9 +667,9 @@ internal class DefaultKeysBackupService @Inject constructor(
callback: MatrixCallback<ImportRoomKeysResult>) { callback: MatrixCallback<ImportRoomKeysResult>) {
Timber.v("restoreKeysWithRecoveryKey: From backup version: ${keysVersionResult.version}") Timber.v("restoreKeysWithRecoveryKey: From backup version: ${keysVersionResult.version}")
cryptoCoroutineScope.launch(coroutineDispatchers.main) { cryptoCoroutineScope.launch(coroutineDispatchers.io) {
runCatching { runCatching {
val decryption = withContext(coroutineDispatchers.crypto) { val decryption = withContext(coroutineDispatchers.computation) {
// Check if the recovery is valid before going any further // Check if the recovery is valid before going any further
if (!isValidRecoveryKeyForKeysBackupVersion(recoveryKey, keysVersionResult)) { if (!isValidRecoveryKeyForKeysBackupVersion(recoveryKey, keysVersionResult)) {
Timber.e("restoreKeysWithRecoveryKey: Invalid recovery key for this keys version") Timber.e("restoreKeysWithRecoveryKey: Invalid recovery key for this keys version")
@ -749,7 +738,19 @@ internal class DefaultKeysBackupService @Inject constructor(
} }
result result
} }
}.foldToCallback(callback) }.foldToCallback(object : MatrixCallback<ImportRoomKeysResult> {
override fun onSuccess(data: ImportRoomKeysResult) {
uiHandler.post {
callback.onSuccess(data)
}
}
override fun onFailure(failure: Throwable) {
uiHandler.post {
callback.onFailure(failure)
}
}
})
} }
} }
@ -761,7 +762,7 @@ internal class DefaultKeysBackupService @Inject constructor(
callback: MatrixCallback<ImportRoomKeysResult>) { callback: MatrixCallback<ImportRoomKeysResult>) {
Timber.v("[MXKeyBackup] restoreKeyBackup with password: From backup version: ${keysBackupVersion.version}") Timber.v("[MXKeyBackup] restoreKeyBackup with password: From backup version: ${keysBackupVersion.version}")
cryptoCoroutineScope.launch(coroutineDispatchers.main) { cryptoCoroutineScope.launch(coroutineDispatchers.io) {
runCatching { runCatching {
val progressListener = if (stepProgressListener != null) { val progressListener = if (stepProgressListener != null) {
object : ProgressListener { object : ProgressListener {
@ -786,7 +787,19 @@ internal class DefaultKeysBackupService @Inject constructor(
restoreKeysWithRecoveryKey(keysBackupVersion, recoveryKey, roomId, sessionId, stepProgressListener, it) restoreKeysWithRecoveryKey(keysBackupVersion, recoveryKey, roomId, sessionId, stepProgressListener, it)
} }
} }
}.foldToCallback(callback) }.foldToCallback(object : MatrixCallback<ImportRoomKeysResult> {
override fun onSuccess(data: ImportRoomKeysResult) {
uiHandler.post {
callback.onSuccess(data)
}
}
override fun onFailure(failure: Throwable) {
uiHandler.post {
callback.onFailure(failure)
}
}
})
} }
} }

View File

@ -740,14 +740,23 @@ internal class RealmCryptoStore @Inject constructor(
if (sessionIdentifier != null) { if (sessionIdentifier != null) {
val key = OlmInboundGroupSessionEntity.createPrimaryKey(sessionIdentifier, session.senderKey) val key = OlmInboundGroupSessionEntity.createPrimaryKey(sessionIdentifier, session.senderKey)
val realmOlmInboundGroupSession = OlmInboundGroupSessionEntity().apply { val existing = realm.where<OlmInboundGroupSessionEntity>()
primaryKey = key .equalTo(OlmInboundGroupSessionEntityFields.PRIMARY_KEY, key)
sessionId = sessionIdentifier .findFirst()
senderKey = session.senderKey
putInboundGroupSession(session)
}
realm.insertOrUpdate(realmOlmInboundGroupSession) if (existing != null) {
// we want to keep the existing backup status
existing.putInboundGroupSession(session)
} else {
val realmOlmInboundGroupSession = OlmInboundGroupSessionEntity().apply {
primaryKey = key
sessionId = sessionIdentifier
senderKey = session.senderKey
putInboundGroupSession(session)
}
realm.insertOrUpdate(realmOlmInboundGroupSession)
}
} }
} }
} }
@ -876,17 +885,32 @@ internal class RealmCryptoStore @Inject constructor(
return return
} }
doRealmTransaction(realmConfiguration) { doRealmTransaction(realmConfiguration) { realm ->
olmInboundGroupSessionWrappers.forEach { olmInboundGroupSessionWrapper -> olmInboundGroupSessionWrappers.forEach { olmInboundGroupSessionWrapper ->
try { try {
val sessionIdentifier = olmInboundGroupSessionWrapper.olmInboundGroupSession?.sessionIdentifier()
val key = OlmInboundGroupSessionEntity.createPrimaryKey( val key = OlmInboundGroupSessionEntity.createPrimaryKey(
olmInboundGroupSessionWrapper.olmInboundGroupSession?.sessionIdentifier(), sessionIdentifier,
olmInboundGroupSessionWrapper.senderKey) olmInboundGroupSessionWrapper.senderKey)
it.where<OlmInboundGroupSessionEntity>() val existing = realm.where<OlmInboundGroupSessionEntity>()
.equalTo(OlmInboundGroupSessionEntityFields.PRIMARY_KEY, key) .equalTo(OlmInboundGroupSessionEntityFields.PRIMARY_KEY, key)
.findFirst() .findFirst()
?.backedUp = true
if (existing != null) {
existing.backedUp = true
} else {
// ... might be in cache but not yet persisted, create a record to persist backedup state
val realmOlmInboundGroupSession = OlmInboundGroupSessionEntity().apply {
primaryKey = key
sessionId = sessionIdentifier
senderKey = olmInboundGroupSessionWrapper.senderKey
putInboundGroupSession(olmInboundGroupSessionWrapper)
backedUp = true
}
realm.insertOrUpdate(realmOlmInboundGroupSession)
}
} catch (e: OlmException) { } catch (e: OlmException) {
Timber.e(e, "OlmException") Timber.e(e, "OlmException")
} }

View File

@ -68,6 +68,9 @@ class KeyRequestHandler @Inject constructor(
var session: Session? = null var session: Session? = null
// This functionality is disabled in element for now. As it could be prone to social attacks
var enablePromptingForRequest = false
fun start(session: Session) { fun start(session: Session) {
this.session = session this.session = session
session.cryptoService().verificationService().addListener(this) session.cryptoService().verificationService().addListener(this)
@ -92,6 +95,8 @@ class KeyRequestHandler @Inject constructor(
* @param request the key request. * @param request the key request.
*/ */
override fun onRoomKeyRequest(request: IncomingRoomKeyRequest) { override fun onRoomKeyRequest(request: IncomingRoomKeyRequest) {
if (!enablePromptingForRequest) return
val userId = request.userId val userId = request.userId
val deviceId = request.deviceId val deviceId = request.deviceId
val requestId = request.requestId val requestId = request.requestId