Skip to content

Commit

Permalink
Merge branch 'release/1.6.14' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
bmarty committed Apr 2, 2024
2 parents effdca1 + f7095d8 commit 310cecf
Show file tree
Hide file tree
Showing 46 changed files with 1,650 additions and 136 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -3,6 +3,7 @@
/local.properties
# idea files: exclude everything except dictionnaries
.idea/caches
.idea/copilot
.idea/libraries
.idea/inspectionProfiles
.idea/sonarlint
Expand Down
18 changes: 16 additions & 2 deletions CHANGES.md
@@ -1,12 +1,26 @@
Changes in Element v1.6.14 (2024-04-02)
=======================================

Bugfixes 🐛
----------
- Fix send button blinking once for each character you are typing in RTE. ([#send_button_blinking](https://github.com/element-hq/element-android/issues/send_button_blinking))
- Fix infinite loading on secure backup setup ("Re-Authentication needed" bottom sheet). ([#8786](https://github.com/element-hq/element-android/issues/8786))

Other changes
-------------
- Improve UTD reporting by adding additional fields to the report. ([#8780](https://github.com/element-hq/element-android/issues/8780))
- Add a report user action in the message bottom sheet and on the user profile page. ([#8796](https://github.com/element-hq/element-android/issues/8796))


Changes in Element v1.6.12 (2024-02-16)
=======================================

This update provides important security fixes, please update now.

Security fixes 🔐
-----------------
- Add a check on incoming intent. ([#1506 internal](https://github.com/matrix-org/internal-config/issues/1506))
- Store temporary files created for Camera in the media folder. ([#1505 internal](https://github.com/matrix-org/internal-config/issues/1505))
- Add a check on incoming intent. [CVE-2024-26131](https://www.cve.org/CVERecord?id=CVE-2024-26131) / [GHSA-j6pr-fpc8-q9vm](https://github.com/element-hq/element-android/security/advisories/GHSA-j6pr-fpc8-q9vm)
- Store temporary files created for Camera in a dedicated media folder. [CVE-2024-26132](https://www.cve.org/CVERecord?id=CVE-2024-26132) / [GHSA-8wj9-cx7h-pvm4](https://github.com/element-hq/element-android/security/advisories/GHSA-8wj9-cx7h-pvm4)

Bugfixes 🐛
----------
Expand Down
2 changes: 1 addition & 1 deletion dependencies.gradle
Expand Up @@ -101,7 +101,7 @@ ext.libs = [
],
element : [
'opusencoder' : "io.element.android:opusencoder:1.1.0",
'wysiwyg' : "io.element.android:wysiwyg:2.29.0"
'wysiwyg' : "io.element.android:wysiwyg:2.35.0"
],
squareup : [
'moshi' : "com.squareup.moshi:moshi:$moshi",
Expand Down
2 changes: 2 additions & 0 deletions fastlane/metadata/android/en-US/changelogs/40106140.txt
@@ -0,0 +1,2 @@
Main changes in this version: Bugfixes and improvements.
Full changelog: https://github.com/element-hq/element-android/releases
3 changes: 3 additions & 0 deletions library/ui-strings/src/main/res/values/strings.xml
Expand Up @@ -1953,8 +1953,11 @@
<string name="content_reported_as_spam_content">"This content was reported as spam.\n\nIf you don't want to see any more content from this user, you can ignore them to hide their messages."</string>
<string name="content_reported_as_inappropriate_title">"Reported as inappropriate"</string>
<string name="content_reported_as_inappropriate_content">"This content was reported as inappropriate.\n\nIf you don't want to see any more content from this user, you can ignore them to hide their messages."</string>
<string name="user_reported_as_inappropriate_title">"Reported user"</string>
<string name="user_reported_as_inappropriate_content">"The user has been reported.\n\nIf you don't want to see any more content from this user, you can ignore them to hide their messages."</string>

<string name="message_ignore_user">Ignore user</string>
<string name="message_report_user">Report user</string>

<string name="room_list_quick_actions_notifications_all_noisy">"All messages (noisy)"</string>
<string name="room_list_quick_actions_notifications_all">"All messages"</string>
Expand Down
2 changes: 1 addition & 1 deletion matrix-sdk-android/build.gradle
Expand Up @@ -62,7 +62,7 @@ android {
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'

buildConfigField "String", "SDK_VERSION", "\"1.6.12\""
buildConfigField "String", "SDK_VERSION", "\"1.6.14\""

buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\""
Expand Down
Expand Up @@ -16,6 +16,7 @@

package org.matrix.android.sdk.api.session

import org.matrix.android.sdk.api.session.crypto.MXCryptoError
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.util.JsonDict

Expand All @@ -27,7 +28,7 @@ interface LiveEventListener {

fun onEventDecrypted(event: Event, clearEvent: JsonDict)

fun onEventDecryptionError(event: Event, throwable: Throwable)
fun onEventDecryptionError(event: Event, cryptoError: MXCryptoError)

fun onLiveToDeviceEvent(event: Event)

Expand Down
Expand Up @@ -22,10 +22,12 @@ import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult
import org.matrix.android.sdk.api.session.events.model.Event
import javax.inject.Inject

internal class DecryptRoomEventUseCase @Inject constructor(private val olmMachine: OlmMachine) {
internal class DecryptRoomEventUseCase @Inject constructor(
private val cryptoService: RustCryptoService
) {

suspend operator fun invoke(event: Event): MXEventDecryptionResult {
return olmMachine.decryptRoomEvent(event)
return cryptoService.decryptEvent(event, "")
}

suspend fun decryptAndSaveResult(event: Event) {
Expand Down
Expand Up @@ -172,8 +172,6 @@ internal class Device @AssistedInject constructor(
* This will not fetch out fresh data from the Rust side.
**/
internal fun toCryptoDeviceInfo(): CryptoDeviceInfo {
// val keys = innerDevice.keys.map { (keyId, key) -> keyId to key }.toMap()

return CryptoDeviceInfo(
deviceId = innerDevice.deviceId,
userId = innerDevice.userId,
Expand Down
Expand Up @@ -189,18 +189,21 @@ internal class OlmMachine @Inject constructor(
is OwnUserIdentity -> ownIdentity.trustsOurOwnDevice()
else -> false
}
val ownDevice = inner.getDevice(userId(), deviceId, 0u)!!
val creationTime = ownDevice.firstTimeSeenTs.toLong()

return CryptoDeviceInfo(
deviceId(),
userId(),
// TODO pass the algorithms here.
listOf(),
ownDevice.algorithms,
keys,
mapOf(),
UnsignedDeviceInfo(),
UnsignedDeviceInfo(
deviceDisplayName = ownDevice.displayName
),
DeviceTrustLevel(crossSigningVerified, locallyVerified = true),
false,
null
creationTime
)
}

Expand Down Expand Up @@ -291,7 +294,7 @@ internal class OlmMachine @Inject constructor(
// checking the returned to devices to check for room keys.
// XXX Anyhow there is now proper signaling we should soon stop parsing them manually
receiveSyncChanges.toDeviceEvents.map {
outAdapter.fromJson(it) ?: Event()
outAdapter.fromJson(it) ?: Event()
}
}

Expand Down Expand Up @@ -882,6 +885,7 @@ internal class OlmMachine @Inject constructor(
inner.queryMissingSecretsFromOtherSessions()
}
}

@Throws(CryptoStoreException::class)
suspend fun enableBackupV1(key: String, version: String) {
return withContext(coroutineDispatchers.computation) {
Expand Down
Expand Up @@ -497,8 +497,11 @@ internal class RustCryptoService @Inject constructor(
@Throws(MXCryptoError::class)
override suspend fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult {
return try {
olmMachine.decryptRoomEvent(event)
olmMachine.decryptRoomEvent(event).also {
liveEventManager.get().dispatchLiveEventDecrypted(event, it)
}
} catch (mxCryptoError: MXCryptoError) {
liveEventManager.get().dispatchLiveEventDecryptionFailed(event, mxCryptoError)
if (mxCryptoError is MXCryptoError.Base && (
mxCryptoError.errorType == MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID ||
mxCryptoError.errorType == MXCryptoError.ErrorType.UNKNOWN_MESSAGE_INDEX)) {
Expand Down
Expand Up @@ -22,6 +22,7 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.LiveEventListener
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 timber.log.Timber
Expand Down Expand Up @@ -75,7 +76,7 @@ internal class StreamEventsManager @Inject constructor() {
}
}

fun dispatchLiveEventDecryptionFailed(event: Event, error: Throwable) {
fun dispatchLiveEventDecryptionFailed(event: Event, error: MXCryptoError) {
Timber.v("## dispatchLiveEventDecryptionFailed ${event.eventId}")
coroutineScope.launch {
listeners.forEach {
Expand Down
2 changes: 1 addition & 1 deletion vector-app/build.gradle
Expand Up @@ -37,7 +37,7 @@ ext.versionMinor = 6
// Note: even values are reserved for regular release, odd values for hotfix release.
// When creating a hotfix, you should decrease the value, since the current value
// is the value for the next regular release.
ext.versionPatch = 12
ext.versionPatch = 14

static def getGitTimestamp() {
def cmd = 'git show -s --format=%ct'
Expand Down
3 changes: 3 additions & 0 deletions vector-app/src/main/java/im/vector/app/VectorApplication.kt
Expand Up @@ -51,6 +51,7 @@ import im.vector.app.core.debug.LeakDetector
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.pushers.FcmHelper
import im.vector.app.core.resources.BuildMeta
import im.vector.app.features.analytics.DecryptionFailureTracker
import im.vector.app.features.analytics.VectorAnalytics
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.configuration.VectorConfiguration
Expand Down Expand Up @@ -100,6 +101,7 @@ class VectorApplication :
@Inject lateinit var callManager: WebRtcCallManager
@Inject lateinit var invitesAcceptor: InvitesAcceptor
@Inject lateinit var autoRageShaker: AutoRageShaker
@Inject lateinit var decryptionFailureTracker: DecryptionFailureTracker
@Inject lateinit var vectorFileLogger: VectorFileLogger
@Inject lateinit var vectorAnalytics: VectorAnalytics
@Inject lateinit var flipperProxy: FlipperProxy
Expand Down Expand Up @@ -130,6 +132,7 @@ class VectorApplication :
vectorAnalytics.init()
invitesAcceptor.initialize()
autoRageShaker.initialize()
decryptionFailureTracker.start()
vectorUncaughtExceptionHandler.activate()

// Remove Log handler statically added by Jitsi
Expand Down
3 changes: 2 additions & 1 deletion vector/src/main/java/im/vector/app/UISIDetector.kt
Expand Up @@ -18,6 +18,7 @@ package im.vector.app

import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.LiveEventListener
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
import org.matrix.android.sdk.api.session.events.model.toModel
Expand Down Expand Up @@ -84,7 +85,7 @@ class UISIDetector(private val timeoutMillis: Long = 30_000L) : LiveEventListene
}
}

override fun onEventDecryptionError(event: Event, throwable: Throwable) {
override fun onEventDecryptionError(event: Event, cryptoError: MXCryptoError) {
val eventId = event.eventId
val roomId = event.roomId
if (!enabled || eventId == null || roomId == null) return
Expand Down
Expand Up @@ -23,7 +23,6 @@ import im.vector.app.core.pushers.UnregisterUnifiedPushUseCase
import im.vector.app.core.services.GuardServiceStarter
import im.vector.app.core.session.ConfigureAndStartSessionUseCase
import im.vector.app.features.analytics.DecryptionFailureTracker
import im.vector.app.features.analytics.plan.Error
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.crypto.keysrequest.KeyRequestHandler
import im.vector.app.features.crypto.verification.IncomingVerificationRequestHandler
Expand Down Expand Up @@ -75,11 +74,6 @@ class ActiveSessionHolder @Inject constructor(
session.callSignalingService().addCallListener(callManager)
imageManager.onSessionStarted(session)
guardServiceStarter.start()
decryptionFailureTracker.currentModule = if (session.cryptoService().name() == "rust-sdk") {
Error.CryptoModule.Rust
} else {
Error.CryptoModule.Native
}
}

suspend fun clearActiveSession() {
Expand Down
@@ -0,0 +1,76 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package im.vector.app.features.analytics

import im.vector.app.features.analytics.plan.Error
import org.matrix.android.sdk.api.session.crypto.MXCryptoError

data class DecryptionFailure(
val timeStamp: Long,
val roomId: String,
val failedEventId: String,
val error: MXCryptoError,
val wasVisibleOnScreen: Boolean,
val ownIdentityTrustedAtTimeOfDecryptionFailure: Boolean,
// If this is set, it means that the event was decrypted but late. Will be -1 if
// the event was not decrypted after the maximum wait time.
val timeToDecryptMillis: Long? = null,
val isMatrixDotOrg: Boolean,
val isFederated: Boolean? = null,
val eventLocalAgeAtDecryptionFailure: Long? = null
)

fun DecryptionFailure.toAnalyticsEvent(): Error {
val errorMsg = (error as? MXCryptoError.Base)?.technicalMessage ?: error.message
return Error(
context = "mxc_crypto_error_type|${errorMsg}",
domain = Error.Domain.E2EE,
name = this.toAnalyticsErrorName(),
// this is deprecated keep for backward compatibility
cryptoModule = Error.CryptoModule.Rust,
cryptoSDK = Error.CryptoSDK.Rust,
eventLocalAgeMillis = eventLocalAgeAtDecryptionFailure?.toInt(),
isFederated = isFederated,
isMatrixDotOrg = isMatrixDotOrg,
timeToDecryptMillis = timeToDecryptMillis?.toInt() ?: -1,
wasVisibleToUser = wasVisibleOnScreen,
userTrustsOwnIdentity = ownIdentityTrustedAtTimeOfDecryptionFailure,
)
}

private fun DecryptionFailure.toAnalyticsErrorName(): Error.Name {
val error = this.error
val name = if (error is MXCryptoError.Base) {
when (error.errorType) {
MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID,
MXCryptoError.ErrorType.KEYS_WITHHELD -> Error.Name.OlmKeysNotSentError
MXCryptoError.ErrorType.OLM -> Error.Name.OlmUnspecifiedError
MXCryptoError.ErrorType.UNKNOWN_MESSAGE_INDEX -> Error.Name.OlmIndexError
else -> Error.Name.UnknownError
}
} else {
Error.Name.UnknownError
}
// check if it's an expected UTD!
val localAge = this.eventLocalAgeAtDecryptionFailure
val isHistorical = localAge != null && localAge < 0
if (isHistorical && !this.ownIdentityTrustedAtTimeOfDecryptionFailure) {
return Error.Name.HistoricalMessage
}

return name
}

0 comments on commit 310cecf

Please sign in to comment.