Add sharing existing inbound sessions functionality on new room invites

This commit is contained in:
ariskotsomitopoulos 2022-04-20 12:02:08 +03:00 committed by Valere
parent e2a55fb6f6
commit 34713d5023
5 changed files with 69 additions and 1 deletions

View File

@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.crypto.algorithms
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.internal.crypto.MegolmSessionData
import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService
/**
@ -43,4 +44,6 @@ internal interface IMXDecrypting {
* @param defaultKeysBackupService the keys backup service
*/
fun onRoomKeyEvent(event: Event, defaultKeysBackupService: DefaultKeysBackupService) {}
fun shareKeysWithDevice(exportedKeys: MegolmSessionData?, deviceId: String, userId: String) {}
}

View File

@ -28,7 +28,9 @@ import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventCon
import org.matrix.android.sdk.api.session.events.model.content.RoomKeyContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.internal.crypto.MXOlmDevice
import org.matrix.android.sdk.internal.crypto.OutgoingKeyRequestManager
import org.matrix.android.sdk.internal.crypto.MegolmSessionData
import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction
import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter
import org.matrix.android.sdk.internal.crypto.algorithms.IMXDecrypting
import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
@ -307,4 +309,44 @@ internal class MXMegolmDecryption(
Timber.tag(loggerTag.value).v("ON NEW SESSION $sessionId - $senderKey")
newSessionListener?.onNewSession(roomId, senderKey, sessionId)
}
override fun shareKeysWithDevice(exportedKeys: MegolmSessionData?, deviceId: String, userId: String) {
exportedKeys ?: return
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
runCatching { deviceListManager.downloadKeys(listOf(userId), false) }
.mapCatching {
val deviceInfo = cryptoStore.getUserDevice(userId, deviceId)
if (deviceInfo == null) {
throw RuntimeException()
} else {
val devicesByUser = mapOf(userId to listOf(deviceInfo))
val usersDeviceMap = ensureOlmSessionsForDevicesAction.handle(devicesByUser)
val olmSessionResult = usersDeviceMap.getObject(userId, deviceId)
if (olmSessionResult?.sessionId == null) {
// no session with this device, probably because there
// were no one-time keys.
Timber.tag(loggerTag.value).e("no session with this device $deviceId, probably because there were no one-time keys.")
return@mapCatching
}
Timber.tag(loggerTag.value).i("shareKeysWithDevice() : sharing session ${exportedKeys.sessionId} with device $userId:$deviceId")
val payloadJson = mapOf(
"type" to EventType.FORWARDED_ROOM_KEY,
"content" to exportedKeys
)
val encodedPayload = messageEncrypter.encryptMessage(payloadJson, listOf(deviceInfo))
val sendToDeviceMap = MXUsersDevicesMap<Any>()
sendToDeviceMap.setObject(userId, deviceId, encodedPayload)
Timber.tag(loggerTag.value).i("shareKeysWithDevice() : sending ${exportedKeys.sessionId} to $userId:$deviceId")
val sendToDeviceParams = SendToDeviceTask.Params(EventType.ENCRYPTED, sendToDeviceMap)
try {
sendToDeviceTask.execute(sendToDeviceParams)
} catch (failure: Throwable) {
Timber.tag(loggerTag.value).e(failure, "shareKeysWithDevice() : Failed to send ${exportedKeys.sessionId} to $userId:$deviceId")
}
}
}
}
}
}

View File

@ -66,6 +66,14 @@ internal interface IMXCryptoStore {
*/
fun getInboundGroupSessions(): List<OlmInboundGroupSessionWrapper2>
/**
* Retrieve the known inbound group sessions for the specified room
*
* @param roomId The roomId that the sessions will be returned
* @return the list of all known group sessions, for the provided roomId
*/
fun getInboundGroupSessions(roomId: String): List<OlmInboundGroupSessionWrapper2>
/**
* @return true to unilaterally blacklist all unverified devices.
*/

View File

@ -828,6 +828,18 @@ internal class RealmCryptoStore @Inject constructor(
}
}
override fun getInboundGroupSessions(roomId: String): List<OlmInboundGroupSessionWrapper2> {
return doWithRealm(realmConfiguration) {
it.where<OlmInboundGroupSessionEntity>()
.findAll()
.mapNotNull { inboundGroupSessionEntity ->
inboundGroupSessionEntity.getInboundGroupSession()
}.filter { inboundSession ->
inboundSession.roomId == roomId
}
}
}
override fun removeInboundGroupSession(sessionId: String, senderKey: String) {
val key = OlmInboundGroupSessionEntity.createPrimaryKey(sessionId, senderKey)

View File

@ -23,6 +23,7 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import io.realm.Realm
import io.realm.RealmQuery
import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.identity.ThreePid
import org.matrix.android.sdk.api.session.room.members.MembershipService
import org.matrix.android.sdk.api.session.room.members.RoomMemberQueryParams
@ -50,6 +51,7 @@ internal class DefaultMembershipService @AssistedInject constructor(
private val inviteThreePidTask: InviteThreePidTask,
private val membershipAdminTask: MembershipAdminTask,
private val roomDataSource: RoomDataSource,
private val cryptoService: CryptoService,
@UserId
private val userId: String,
private val queryStringValueProcessor: QueryStringValueProcessor
@ -139,6 +141,7 @@ internal class DefaultMembershipService @AssistedInject constructor(
}
override suspend fun invite(userId: String, reason: String?) {
cryptoService.sendSharedHistoryKeys(roomId, userId)
val params = InviteTask.Params(roomId, userId, reason)
inviteTask.execute(params)
}