Add support for setting pre sharing keys mode from .well-known

This commit is contained in:
Jorge Martín 2022-05-24 10:34:14 +02:00
parent 2e1a11e10e
commit 2271df9907
6 changed files with 55 additions and 11 deletions

1
changelog.d/6146.feature Normal file
View File

@ -0,0 +1 @@
Allow .well-known configuration to override key sharing mode

View File

@ -19,6 +19,7 @@ package im.vector.app.features.crypto.keysrequest
enum class OutboundSessionKeySharingStrategy {
/**
* Keys will be sent for the first time when the first message is sent.
* This is handled by the Matrix SDK so there's no need to do it in Vector.
*/
WhenSendingEvent,

View File

@ -33,6 +33,7 @@ import im.vector.app.features.login.ReAuthHelper
import im.vector.app.features.raw.wellknown.ElementWellKnown
import im.vector.app.features.raw.wellknown.getElementWellknown
import im.vector.app.features.raw.wellknown.isSecureBackupRequired
import im.vector.app.features.raw.wellknown.withElementWellKnown
import im.vector.app.features.session.coroutineScope
import im.vector.app.features.settings.VectorPreferences
import kotlinx.coroutines.Dispatchers
@ -134,9 +135,8 @@ class HomeActivityViewModel @AssistedInject constructor(
.onEach { info ->
val isVerified = info.getOrNull()?.isTrusted() ?: false
if (!isVerified && onceTrusted) {
viewModelScope.launch(Dispatchers.IO) {
val elementWellKnown = rawService.getElementWellknown(safeActiveSession.sessionParams)
sessionHasBeenUnverified(elementWellKnown)
rawService.withElementWellKnown(viewModelScope, safeActiveSession.sessionParams) {
sessionHasBeenUnverified(it)
}
}
onceTrusted = isVerified

View File

@ -29,7 +29,6 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.AppStateHandler
import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
@ -56,6 +55,8 @@ import im.vector.app.features.home.room.typing.TypingHelper
import im.vector.app.features.location.LocationSharingServiceConnection
import im.vector.app.features.notifications.NotificationDrawerManager
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
import im.vector.app.features.raw.wellknown.getOutboundSessionKeySharingStrategyOrDefault
import im.vector.app.features.raw.wellknown.withElementWellKnown
import im.vector.app.features.session.coroutineScope
import im.vector.app.features.settings.VectorDataStore
import im.vector.app.features.settings.VectorPreferences
@ -76,6 +77,7 @@ import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.MatrixPatterns
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.raw.RawService
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
import org.matrix.android.sdk.api.session.events.model.EventType
@ -118,6 +120,7 @@ class TimelineViewModel @AssistedInject constructor(
private val vectorDataStore: VectorDataStore,
private val stringProvider: StringProvider,
private val session: Session,
private val rawService: RawService,
private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider,
private val stickerPickerActionHandler: StickerPickerActionHandler,
private val typingHelper: TypingHelper,
@ -196,9 +199,14 @@ class TimelineViewModel @AssistedInject constructor(
chatEffectManager.delegate = this
// Ensure to share the outbound session keys with all members
if (OutboundSessionKeySharingStrategy.WhenEnteringRoom == BuildConfig.outboundSessionKeySharingStrategy && room.roomCryptoService().isEncrypted()) {
if (room.roomCryptoService().isEncrypted()) {
rawService.withElementWellKnown(viewModelScope, session.sessionParams) {
val strategy = it.getOutboundSessionKeySharingStrategyOrDefault()
if (strategy == OutboundSessionKeySharingStrategy.WhenEnteringRoom) {
prepareForEncryption()
}
}
}
// If the user had already accepted the invitation in the room list
if (initialState.isInviteAlreadyAccepted) {
@ -666,13 +674,16 @@ class TimelineViewModel @AssistedInject constructor(
private fun handleComposerFocusChange(action: RoomDetailAction.ComposerFocusChange) {
// Ensure outbound session keys
if (OutboundSessionKeySharingStrategy.WhenTyping == BuildConfig.outboundSessionKeySharingStrategy && room.roomCryptoService().isEncrypted()) {
if (action.focused) {
if (room.roomCryptoService().isEncrypted()) {
rawService.withElementWellKnown(viewModelScope, session.sessionParams) {
val strategy = it.getOutboundSessionKeySharingStrategyOrDefault()
if (strategy == OutboundSessionKeySharingStrategy.WhenTyping && action.focused) {
// Should we add some rate limit here, or do it only once per model lifecycle?
prepareForEncryption()
}
}
}
}
private fun handleJoinAndOpenReplacementRoom() = withState { state ->
val tombstoneContent = state.tombstoneEvent?.getClearContent()?.toModel<RoomTombstoneContent>() ?: return@withState

View File

@ -65,7 +65,14 @@ data class E2EWellKnownConfig(
* clients should fallback to the default value of: ["key", "passphrase"].
*/
@Json(name = "secure_backup_setup_methods")
val secureBackupSetupMethods: List<String>? = null
val secureBackupSetupMethods: List<String>? = null,
/**
* Configuration for sharing keys strategy which should be used instead of [im.vector.app.BuildConfig.outboundSessionKeySharingStrategy].
* One of on_room_opening, on_typing or disabled.
*/
@Json(name = "outbound_keys_pre_sharing_mode")
val outboundsKeyPreSharingMode: String? = null,
)
@JsonClass(generateAdapter = true)

View File

@ -16,6 +16,11 @@
package im.vector.app.features.raw.wellknown
import im.vector.app.BuildConfig
import im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.MatrixPatterns.getServerName
import org.matrix.android.sdk.api.auth.data.SessionParams
import org.matrix.android.sdk.api.extensions.tryOrNull
@ -30,6 +35,25 @@ suspend fun RawService.getElementWellknown(sessionParams: SessionParams): Elemen
fun ElementWellKnown.isE2EByDefault() = elementE2E?.e2eDefault ?: riotE2E?.e2eDefault ?: true
fun ElementWellKnown?.getOutboundSessionKeySharingStrategyOrDefault(): OutboundSessionKeySharingStrategy {
return when (this?.elementE2E?.outboundsKeyPreSharingMode) {
"on_room_opening" -> OutboundSessionKeySharingStrategy.WhenEnteringRoom
"on_typing" -> OutboundSessionKeySharingStrategy.WhenTyping
"disabled" -> OutboundSessionKeySharingStrategy.WhenSendingEvent
else -> BuildConfig.outboundSessionKeySharingStrategy
}
}
fun RawService.withElementWellKnown(
coroutineScope: CoroutineScope,
sessionParams: SessionParams,
block: ((ElementWellKnown?) -> Unit)
) = with(coroutineScope) {
launch(Dispatchers.IO) {
block(getElementWellknown(sessionParams))
}
}
fun ElementWellKnown.isSecureBackupRequired() = elementE2E?.secureBackupRequired
?: riotE2E?.secureBackupRequired
?: false