Ignore some test in tust. Added some supports flags

This commit is contained in:
valere 2023-03-14 09:57:58 +01:00
parent 238d10d4cb
commit 5f069264d0
20 changed files with 210 additions and 117 deletions

View File

@ -45,6 +45,7 @@ import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.getRoomSummary
import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.api.session.room.failure.JoinRoomFailure
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.send.SendState
@ -83,7 +84,7 @@ class CommonTestHelper internal constructor(context: Context, val cryptoConfig:
}
@OptIn(ExperimentalCoroutinesApi::class)
internal fun runCryptoTest(context: Context, cryptoConfig: MXCryptoConfig? = null, autoSignoutOnClose: Boolean = true, block: suspend CoroutineScope.(CryptoTestHelper, CommonTestHelper) -> Unit) {
internal fun runCryptoTest(context: Context, cryptoConfig: MXCryptoConfig? = null, autoSignoutOnClose: Boolean = true, block: suspend CoroutineScope.(CryptoTestHelper, CommonTestHelper) -> Unit) {
val testHelper = CommonTestHelper(context, cryptoConfig)
val cryptoTestHelper = CryptoTestHelper(testHelper)
return try {
@ -209,18 +210,28 @@ class CommonTestHelper internal constructor(context: Context, val cryptoConfig:
}
})
return messageSent.await()
// return withTimeout(TestConstants.timeOutMillis) { messageSent.await() }
// return withTimeout(TestConstants.timeOutMillis) { messageSent.await() }
}
suspend fun ensureMessage(room: Room, eventId: String, block: ((event: TimelineEvent) -> Boolean)) {
Log.v("#E2E TEST", "ensureMessage room:${room.roomId} <$eventId>")
val timeline = room.timelineService().createTimeline(null, TimelineSettings(60))
val timeline = room.timelineService().createTimeline(null, TimelineSettings(60, buildReadReceipts = false))
// check if not already there?
val existing = withContext(Dispatchers.Main) {
room.getTimelineEvent(eventId)
}
if (existing != null && block(existing)) return Unit.also {
Log.v("#E2E TEST", "Already received")
}
val messageSent = CompletableDeferred<Unit>()
timeline.addListener(object : Timeline.Listener {
override fun onNewTimelineEvents(eventIds: List<String>) {
Log.v("#E2E TEST", "onNewTimelineEvents snapshot is $eventIds")
}
override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
val success = timeline.getSnapshot()
// .filter { it.root.getClearType() == EventType.MESSAGE }
@ -243,13 +254,13 @@ class CommonTestHelper internal constructor(context: Context, val cryptoConfig:
timeline.start()
return messageSent.await()
return messageSent.await()
// withTimeout(TestConstants.timeOutMillis) {
// messageSent.await()
// }
}
fun ensureMessagePromise(room: Room, eventId: String, block: ((event: TimelineEvent) -> Boolean)): CompletableDeferred<Unit> {
fun ensureMessagePromise(room: Room, eventId: String, block: ((event: TimelineEvent) -> Boolean)): CompletableDeferred<Unit> {
val timeline = room.timelineService().createTimeline(null, TimelineSettings(60))
timeline.start()
val messageSent = CompletableDeferred<Unit>()
@ -334,11 +345,11 @@ class CommonTestHelper internal constructor(context: Context, val cryptoConfig:
}
suspend fun waitForAndAcceptInviteInRoom(otherSession: Session, roomID: String) {
retryPeriodically {
retryWithBackoff {
val roomSummary = otherSession.getRoomSummary(roomID)
(roomSummary != null && roomSummary.membership == Membership.INVITE).also {
if (it) {
Log.v("# TEST", "${otherSession.myUserId} can see the invite")
Log.v("#E2E TEST", "${otherSession.myUserId} can see the invite")
}
}
}
@ -354,7 +365,7 @@ class CommonTestHelper internal constructor(context: Context, val cryptoConfig:
}
Log.v("#E2E TEST", "${otherSession.myUserId} waiting for join echo ...")
retryPeriodically {
retryWithBackoff {
val roomSummary = otherSession.getRoomSummary(roomID)
roomSummary != null && roomSummary.membership == Membership.JOIN
}

View File

@ -136,7 +136,9 @@ class CryptoTestHelper(val testHelper: CommonTestHelper) {
suspend fun inviteNewUsersAndWaitForThemToJoin(session: Session, roomId: String, usernames: List<String>): List<Session> {
val newSessions = usernames.map { username ->
testHelper.createAccount(username, SessionTestParams(true)).also {
it.cryptoService().enableKeyGossiping(false)
if (it.cryptoService().supportsDisablingKeyGossiping()) {
it.cryptoService().enableKeyGossiping(false)
}
}
}
@ -560,7 +562,7 @@ class CryptoTestHelper(val testHelper: CommonTestHelper) {
} catch (error: MXCryptoError) {
// nop
}
Log.v("TEST", "ensureCanDecrypt ${event.getClearType()} is ${event.getClearContent()}")
Log.v("#E2E TEST", "ensureCanDecrypt ${event.getClearType()} is ${event.getClearContent()}")
event.getClearType() == EventType.MESSAGE &&
messagesText[index] == event.getClearContent()?.toModel<MessageContent>()?.body
}

View File

@ -20,6 +20,7 @@ import android.util.Log
import androidx.test.filters.LargeTest
import org.amshove.kluent.internal.assertEquals
import org.junit.Assert
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@ -28,6 +29,7 @@ import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
@ -58,15 +60,15 @@ class E2EShareKeysConfigTest : InstrumentedTest {
enableEncryption()
})
commonTestHelper.retryPeriodically {
commonTestHelper.retryWithBackoff {
aliceSession.roomService().getRoomSummary(roomId)?.isEncrypted == true
}
val roomAlice = aliceSession.roomService().getRoom(roomId)!!
// send some messages
val withSession1 = commonTestHelper.sendTextMessage(roomAlice, "Hello", 1)
val withSession1 = commonTestHelper.sendMessageInRoom(roomAlice, "Hello")
aliceSession.cryptoService().discardOutboundSession(roomId)
val withSession2 = commonTestHelper.sendTextMessage(roomAlice, "World", 1)
val withSession2 = commonTestHelper.sendMessageInRoom(roomAlice, "World")
// Create bob account
val bobSession = commonTestHelper.createAccount(TestConstants.USER_BOB, SessionTestParams(withInitialSync = true))
@ -78,7 +80,7 @@ class E2EShareKeysConfigTest : InstrumentedTest {
// Bob has join but should not be able to decrypt history
cryptoTestHelper.ensureCannotDecrypt(
withSession1.map { it.eventId } + withSession2.map { it.eventId },
listOf(withSession1, withSession2),
bobSession,
roomId
)
@ -86,44 +88,53 @@ class E2EShareKeysConfigTest : InstrumentedTest {
// We don't need bob anymore
commonTestHelper.signOutAndClose(bobSession)
// Now let's enable history key sharing on alice side
aliceSession.cryptoService().enableShareKeyOnInvite(true)
if (aliceSession.cryptoService().supportsShareKeysOnInvite()) {
// Now let's enable history key sharing on alice side
aliceSession.cryptoService().enableShareKeyOnInvite(true)
// let's add a new message first
val afterFlagOn = commonTestHelper.sendTextMessage(roomAlice, "After", 1)
// let's add a new message first
val afterFlagOn = commonTestHelper.sendMessageInRoom(roomAlice, "After")
// Worth nothing to check that the session was rotated
Assert.assertNotEquals(
"Session should have been rotated",
withSession2.first().root.content?.get("session_id")!!,
afterFlagOn.first().root.content?.get("session_id")!!
)
// Worth nothing to check that the session was rotated
Assert.assertNotEquals(
"Session should have been rotated",
aliceSession.roomService().getRoom(roomId)?.getTimelineEvent(withSession1)?.root?.content?.get("session_id")!!,
aliceSession.roomService().getRoom(roomId)?.getTimelineEvent(afterFlagOn)?.root?.content?.get("session_id")!!
)
// Invite a new user
val samSession = commonTestHelper.createAccount(TestConstants.USER_SAM, SessionTestParams(withInitialSync = true))
// Invite a new user
val samSession = commonTestHelper.createAccount(TestConstants.USER_SAM, SessionTestParams(withInitialSync = true))
// Let alice invite sam
roomAlice.membershipService().invite(samSession.myUserId)
// Let alice invite sam
roomAlice.membershipService().invite(samSession.myUserId)
commonTestHelper.waitForAndAcceptInviteInRoom(samSession, roomId)
commonTestHelper.waitForAndAcceptInviteInRoom(samSession, roomId)
// Sam shouldn't be able to decrypt messages with the first session, but should decrypt the one with 3rd session
cryptoTestHelper.ensureCannotDecrypt(
withSession1.map { it.eventId } + withSession2.map { it.eventId },
samSession,
roomId
)
// Sam shouldn't be able to decrypt messages with the first session, but should decrypt the one with 3rd session
cryptoTestHelper.ensureCannotDecrypt(
listOf(withSession1, withSession2),
samSession,
roomId
)
cryptoTestHelper.ensureCanDecrypt(
afterFlagOn.map { it.eventId },
samSession,
roomId,
afterFlagOn.map { it.root.getClearContent()?.get("body") as String })
cryptoTestHelper.ensureCanDecrypt(
listOf(afterFlagOn),
samSession,
roomId,
listOf(aliceSession.roomService().getRoom(roomId)?.getTimelineEvent(afterFlagOn)?.root?.getClearContent()?.get("body") as String)
)
}
}
@Test
fun ifSharingDisabledOnAliceSideBobShouldNotShareAliceHistory() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(roomHistoryVisibility = RoomHistoryVisibility.SHARED)
Assume.assumeTrue("Shared key on invite needed to test this",
testData.firstSession.cryptoService().supportsShareKeysOnInvite()
)
val aliceSession = testData.firstSession.also {
it.cryptoService().enableShareKeyOnInvite(false)
}
@ -151,6 +162,11 @@ class E2EShareKeysConfigTest : InstrumentedTest {
@Test
fun ifSharingEnabledOnAliceSideBobShouldShareAliceHistory() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(roomHistoryVisibility = RoomHistoryVisibility.SHARED)
Assume.assumeTrue("Shared key on invite needed to test this",
testData.firstSession.cryptoService().supportsShareKeysOnInvite()
)
val aliceSession = testData.firstSession.also {
it.cryptoService().enableShareKeyOnInvite(true)
}
@ -193,6 +209,11 @@ class E2EShareKeysConfigTest : InstrumentedTest {
@Test
fun testBackupFlagIsCorrect() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val aliceSession = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
Assume.assumeTrue("Shared key on invite needed to test this",
aliceSession.cryptoService().supportsShareKeysOnInvite()
)
aliceSession.cryptoService().enableShareKeyOnInvite(false)
val roomId = aliceSession.roomService().createRoom(CreateRoomParams().apply {
historyVisibility = RoomHistoryVisibility.SHARED
@ -206,9 +227,10 @@ class E2EShareKeysConfigTest : InstrumentedTest {
val roomAlice = aliceSession.roomService().getRoom(roomId)!!
// send some messages
val notSharableMessage = commonTestHelper.sendTextMessage(roomAlice, "Hello", 1)
val notSharableMessage = commonTestHelper.sendMessageInRoom(roomAlice, "Hello")
aliceSession.cryptoService().enableShareKeyOnInvite(true)
val sharableMessage = commonTestHelper.sendTextMessage(roomAlice, "World", 1)
val sharableMessage = commonTestHelper.sendMessageInRoom(roomAlice, "World")
Log.v("#E2E TEST", "Create and start key backup for bob ...")
val keysBackupService = aliceSession.cryptoService().keysBackupService()
@ -224,6 +246,7 @@ class E2EShareKeysConfigTest : InstrumentedTest {
commonTestHelper.signOutAndClose(aliceSession)
val newAliceSession = commonTestHelper.logIntoAccount(aliceSession.myUserId, SessionTestParams(true))
newAliceSession.cryptoService().enableShareKeyOnInvite(true)
newAliceSession.cryptoService().keysBackupService().let { kbs ->
@ -251,15 +274,16 @@ class E2EShareKeysConfigTest : InstrumentedTest {
// Sam shouldn't be able to decrypt messages with the first session, but should decrypt the one with 3rd session
cryptoTestHelper.ensureCannotDecrypt(
notSharableMessage.map { it.eventId },
listOf(notSharableMessage),
samSession,
roomId
)
cryptoTestHelper.ensureCanDecrypt(
sharableMessage.map { it.eventId },
listOf(sharableMessage),
samSession,
roomId,
sharableMessage.map { it.root.getClearContent()?.get("body") as String })
listOf(roomAlice.getTimelineEvent(sharableMessage)?.root?.getClearContent()?.get("body") as String)
)
}
}

View File

@ -53,15 +53,13 @@ class E2eeConfigTest : InstrumentedTest {
val roomAlicePOV = cryptoTestData.firstSession.roomService().getRoom(cryptoTestData.roomId)!!
val sentMessage = testHelper.sendTextMessage(roomAlicePOV, "you are blocked", 1).first()
val sentMessage = testHelper.sendMessageInRoom(roomAlicePOV, "you are blocked")
val roomBobPOV = cryptoTestData.secondSession!!.roomService().getRoom(cryptoTestData.roomId)!!
// ensure other received
testHelper.retryPeriodically {
roomBobPOV.timelineService().getTimelineEvent(sentMessage.eventId) != null
}
testHelper.ensureMessage(roomBobPOV, sentMessage) { true }
cryptoTestHelper.ensureCannotDecrypt(listOf(sentMessage.eventId), cryptoTestData.secondSession!!, cryptoTestData.roomId)
cryptoTestHelper.ensureCannotDecrypt(listOf(sentMessage), cryptoTestData.secondSession!!, cryptoTestData.roomId)
}
@Test
@ -77,19 +75,20 @@ class E2eeConfigTest : InstrumentedTest {
val roomAlicePOV = cryptoTestData.firstSession.roomService().getRoom(cryptoTestData.roomId)!!
val sentMessage = testHelper.sendTextMessage(roomAlicePOV, "you can read", 1).first()
val sentMessage = testHelper.sendMessageInRoom(roomAlicePOV, "you can read")
val roomBobPOV = cryptoTestData.secondSession!!.roomService().getRoom(cryptoTestData.roomId)!!
// ensure other received
testHelper.retryPeriodically {
roomBobPOV.timelineService().getTimelineEvent(sentMessage.eventId) != null
}
testHelper.ensureMessage(roomBobPOV, sentMessage) { true }
cryptoTestHelper.ensureCanDecrypt(
listOf(sentMessage.eventId),
listOf(sentMessage),
cryptoTestData.secondSession!!,
cryptoTestData.roomId,
listOf(sentMessage.getLastMessageContent()!!.body)
listOf(
roomBobPOV.timelineService().getTimelineEvent(sentMessage)?.getLastMessageContent()!!.body
)
)
}

View File

@ -75,8 +75,12 @@ class E2eeSanityTests : InstrumentedTest {
val e2eRoomID = cryptoTestData.roomId
val aliceRoomPOV = aliceSession.getRoom(e2eRoomID)!!
// we want to disable key gossiping to just check initial sending of keys
aliceSession.cryptoService().enableKeyGossiping(false)
cryptoTestData.secondSession?.cryptoService()?.enableKeyGossiping(false)
if (aliceSession.cryptoService().supportsDisablingKeyGossiping()) {
aliceSession.cryptoService().enableKeyGossiping(false)
}
if (cryptoTestData.secondSession?.cryptoService()?.supportsDisablingKeyGossiping() == true) {
cryptoTestData.secondSession?.cryptoService()?.enableKeyGossiping(false)
}
// add some more users and invite them
val otherAccounts = listOf("benoit", "valere", "ganfra") // , "adam", "manu")

View File

@ -22,6 +22,7 @@ import org.amshove.kluent.fail
import org.amshove.kluent.internal.assertEquals
import org.amshove.kluent.internal.assertNotEquals
import org.junit.Assert
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@ -79,9 +80,9 @@ class E2eeShareKeysHistoryTest : InstrumentedTest {
runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val aliceMessageText = "Hello Bob, I am Alice!"
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true, roomHistoryVisibility)
val e2eRoomID = cryptoTestData.roomId
Assume.assumeTrue(cryptoTestData.firstSession.cryptoService().supportsShareKeysOnInvite())
// Alice
val aliceSession = cryptoTestData.firstSession.also {
it.cryptoService().enableShareKeyOnInvite(true)
@ -251,6 +252,8 @@ class E2eeShareKeysHistoryTest : InstrumentedTest {
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true, initRoomHistoryVisibility)
val e2eRoomID = cryptoTestData.roomId
Assume.assumeTrue(cryptoTestData.firstSession.cryptoService().supportsShareKeysOnInvite())
// Alice
val aliceSession = cryptoTestData.firstSession.also {
it.cryptoService().enableShareKeyOnInvite(true)

View File

@ -24,6 +24,7 @@ import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@ -195,11 +196,15 @@ class XSigningTest : InstrumentedTest {
@Test
fun testWarnOnCrossSigningReset() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
val bobSession = cryptoTestData.secondSession
// Remove when https://github.com/matrix-org/matrix-rust-sdk/issues/1129
Assume.assumeTrue("Not yet supported by rust", aliceSession.cryptoService().name() != "rust-sdk")
val aliceAuthParams = UserPasswordAuth(
user = aliceSession.myUserId,
password = TestConstants.PASSWORD

View File

@ -25,6 +25,7 @@ import junit.framework.TestCase.assertTrue
import org.amshove.kluent.shouldBeEqualTo
import org.junit.Assert
import org.junit.Assert.assertNull
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@ -59,6 +60,8 @@ class KeyShareTests : InstrumentedTest {
fun test_DoNotSelfShareIfNotTrusted() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
val aliceSession = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
Assume.assumeTrue("Not supported", aliceSession.cryptoService().supportKeyRequestInspection())
Log.v("#TEST", "=======> AliceSession 1 is ${aliceSession.sessionParams.deviceId}")
// Create an encrypted room and add a message
@ -70,8 +73,9 @@ class KeyShareTests : InstrumentedTest {
)
val room = aliceSession.getRoom(roomId)
assertNotNull(room)
Thread.sleep(4_000)
assertTrue(room?.roomCryptoService()?.isEncrypted() == true)
commonTestHelper.retryWithBackoff {
room?.roomCryptoService()?.isEncrypted() == true
}
val sentEvent = commonTestHelper.sendTextMessage(room!!, "My Message", 1).first()
val sentEventId = sentEvent.eventId
@ -207,6 +211,9 @@ class KeyShareTests : InstrumentedTest {
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
val aliceSession = testData.firstSession
Assume.assumeTrue("Not supported", aliceSession.cryptoService().supportKeyRequestInspection())
val roomFromAlice = aliceSession.getRoom(testData.roomId)!!
val bobSession = testData.secondSession!!
@ -239,6 +246,9 @@ class KeyShareTests : InstrumentedTest {
val testData = cryptoTestHelper.doE2ETestWithAliceInARoom(true)
val aliceSession = testData.firstSession
Assume.assumeTrue("Not supported", aliceSession.cryptoService().supportKeyRequestInspection())
val roomFromAlice = aliceSession.getRoom(testData.roomId)!!
val aliceNewSession = commonTestHelper.logIntoAccount(aliceSession.myUserId, SessionTestParams(true))
@ -274,6 +284,9 @@ class KeyShareTests : InstrumentedTest {
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
val aliceSession = testData.firstSession
Assume.assumeTrue("Not supported", aliceSession.cryptoService().supportKeyRequestInspection())
val bobSession = testData.secondSession!!
val roomFromBob = bobSession.getRoom(testData.roomId)!!
@ -386,6 +399,9 @@ class KeyShareTests : InstrumentedTest {
) { cryptoTestHelper, commonTestHelper ->
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
val aliceSession = testData.firstSession
Assume.assumeTrue("Not supported", aliceSession.cryptoService().supportKeyRequestInspection())
val bobSession = testData.secondSession!!
val roomFromBob = bobSession.getRoom(testData.roomId)!!

View File

@ -20,6 +20,7 @@ import android.util.Log
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import org.junit.Assert
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Rule
import org.junit.Test
@ -153,6 +154,7 @@ class WithHeldTests : InstrumentedTest {
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = testData.firstSession
Assume.assumeTrue("Not supported", aliceSession.cryptoService().supportKeyRequestInspection())
val bobSession = testData.secondSession!!
val aliceInterceptor = testHelper.getTestInterceptor(aliceSession)
@ -222,6 +224,7 @@ class WithHeldTests : InstrumentedTest {
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = testData.firstSession
Assume.assumeTrue("Not supported by rust sdk", aliceSession.cryptoService().supportsForwardedKeyWiththeld())
val bobSession = testData.secondSession!!
val roomAlicePov = aliceSession.getRoom(testData.roomId)!!
@ -236,19 +239,9 @@ class WithHeldTests : InstrumentedTest {
// initialize to force request keys if missing
cryptoTestHelper.initializeCrossSigning(bobSecondSession)
// // wait until alice downloaded the new device
// testHelper.retryWithBackoff {
// aliceSession.cryptoService().getUserDevices(bobSession.myUserId).any { it.deviceId == bobSecondSession.sessionParams.deviceId}
// }
//
// // Trust bob second device from Alice POV
// aliceSession.cryptoService().crossSigningService().trustDevice(bobSecondSession.sessionParams.deviceId)
//
// // wait until bob downloaded alice device
// testHelper.retryWithBackoff {
// bobSecondSession.cryptoService().getUserDevices(aliceSession.myUserId).any { it.deviceId == aliceSession.sessionParams.deviceId}
// }
// bobSecondSession.cryptoService().crossSigningService().trustDevice(aliceSession.sessionParams.deviceId)
// Trust bob second device from Alice POV
aliceSession.cryptoService().crossSigningService().trustDevice(bobSecondSession.sessionParams.deviceId)
bobSecondSession.cryptoService().crossSigningService().trustDevice(aliceSession.sessionParams.deviceId)
var sessionId: String? = null
// Check that the
@ -264,18 +257,10 @@ class WithHeldTests : InstrumentedTest {
timeLineEvent != null
}
mustFail(
message = "This session should not be able to decrypt",
failureBlock = { failure ->
val type = (failure as MXCryptoError.Base).errorType
val technicalMessage = failure.technicalMessage
Assert.assertEquals("Error should be withheld", MXCryptoError.ErrorType.KEYS_WITHHELD, type)
Assert.assertEquals("Cause should be unverified", WithHeldCode.UNVERIFIED.value, technicalMessage)
}
) {
val timeLineEvent = bobSecondSession.getRoom(testData.roomId)?.getTimelineEvent(eventId)
bobSecondSession.cryptoService().decryptEvent(timeLineEvent!!.root, "")
// Check that bob second session requested the key
testHelper.retryPeriodically {
val wc = bobSecondSession.cryptoService().getWithHeldMegolmSession(roomAlicePov.roomId, sessionId!!)
wc?.code == WithHeldCode.UNAUTHORISED
}
// // Check that bob second session requested the key
// testHelper.retryPeriodically {

View File

@ -21,6 +21,7 @@ import org.amshove.kluent.internal.assertFailsWith
import org.junit.Assert
import org.junit.Assert.assertEquals
import org.junit.Assert.fail
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@ -43,6 +44,9 @@ class ReplayAttackTest : InstrumentedTest {
// Alice
val aliceSession = cryptoTestData.firstSession
// Until https://github.com/matrix-org/matrix-rust-sdk/issues/397
Assume.assumeTrue("Not yet supported by rust", cryptoTestData.firstSession.cryptoService().name() != "rust-sdk")
val aliceRoomPOV = aliceSession.roomService().getRoom(e2eRoomID)!!
// Bob

View File

@ -194,6 +194,15 @@ internal class DefaultCryptoService @Inject constructor(
private val isStarting = AtomicBoolean(false)
private val isStarted = AtomicBoolean(false)
override fun name() = "kotlin-sdk"
override fun supportsKeyWithheld() = true
override fun supportKeyRequestInspection() = true
override fun supportsDisablingKeyGossiping() = true
override fun supportsForwardedKeyWiththeld() = true
override suspend fun onStateEvent(roomId: String, event: Event, cryptoStoreAggregator: CryptoStoreAggregator?) {
when (event.type) {
EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
@ -1395,7 +1404,7 @@ internal class DefaultCryptoService @Inject constructor(
throw IllegalArgumentException("Missing algorithm")
}
(alg as? IMXGroupEncryption)?.preshareKey(userIds)
(alg as? IMXGroupEncryption)?.preshareKey(userIds)
}
}

View File

@ -48,6 +48,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.CryptoStoreAggregator
interface CryptoService {
fun name(): String
fun verificationService(): VerificationService
fun crossSigningService(): CrossSigningService
@ -80,6 +81,8 @@ interface CryptoService {
fun getLiveGlobalCryptoConfig(): LiveData<GlobalCryptoConfig>
fun supportsDisablingKeyGossiping(): Boolean
/**
* Enable or disable key gossiping.
* Default is true.
@ -186,6 +189,8 @@ interface CryptoService {
fun addNewSessionListener(newSessionListener: NewSessionListener)
fun removeSessionListener(listener: NewSessionListener)
fun supportKeyRequestInspection(): Boolean
fun getOutgoingRoomKeyRequests(): List<OutgoingKeyRequest>
fun getOutgoingRoomKeyRequestsPaged(): LiveData<PagedList<OutgoingKeyRequest>>

View File

@ -28,4 +28,3 @@ internal class MigrateSessionTo052(realm: DynamicRealm) : RealmMigrator(realm, 5
?.setNullable(EventEntityFields.IS_VERIFICATION_STATE_DIRTY, true)
}
}

View File

@ -43,6 +43,8 @@ import org.matrix.android.sdk.api.session.crypto.model.UnsignedDeviceInfo
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.sync.model.DeviceListResponse
import org.matrix.android.sdk.api.session.sync.model.DeviceOneTimeKeysCountSyncResponse
import org.matrix.android.sdk.api.session.sync.model.ToDeviceSyncResponse
@ -439,6 +441,19 @@ internal class OlmMachine @Inject constructor(
if (event.roomId.isNullOrBlank()) {
throw MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_FIELDS, MXCryptoError.MISSING_FIELDS_REASON)
}
if (event.isRedacted()) {
// we shouldn't attempt to decrypt a redacted event because the content is cleared and decryption will fail because of null algorithm
// Workaround until https://github.com/matrix-org/matrix-rust-sdk/issues/1642
return@withContext MXEventDecryptionResult(
clearEvent = mapOf(
"room_id" to event.roomId,
"type" to EventType.MESSAGE,
"content" to emptyMap<String, Any>(),
"unsigned" to event.unsignedData.toContent()
)
)
}
val serializedEvent = adapter.toJson(event)
val decrypted = inner.decryptRoomEvent(serializedEvent, event.roomId, false, false)
@ -493,7 +508,7 @@ internal class OlmMachine @Inject constructor(
ShieldColor.RED -> {
when (this.message) {
"Encrypted by an unverified device." -> MessageVerificationState.UN_SIGNED_DEVICE
"Encrypted by a device not verified by its owner." -> MessageVerificationState.UN_SIGNED_DEVICE_OF_VERIFIED_USER
"Encrypted by a device not verified by its owner." -> MessageVerificationState.UN_SIGNED_DEVICE
"Encrypted by an unknown or deleted device." -> MessageVerificationState.UNKNOWN_DEVICE
else -> MessageVerificationState.UN_SIGNED_DEVICE
}

View File

@ -53,7 +53,6 @@ import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest
import org.matrix.android.sdk.api.session.crypto.model.MXEncryptEventContentResult
import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult
import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
import org.matrix.android.sdk.api.session.crypto.model.TrailType
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType
@ -141,6 +140,8 @@ internal class RustCryptoService @Inject constructor(
private val isStarting = AtomicBoolean(false)
private val isStarted = AtomicBoolean(false)
override fun name() = "rust-sdk"
override suspend fun onStateEvent(roomId: String, event: Event, cryptoStoreAggregator: CryptoStoreAggregator?) {
when (event.type) {
EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
@ -510,8 +511,8 @@ internal class RustCryptoService @Inject constructor(
// } catch (throwable: Throwable) {
// Timber.e(throwable, "## CRYPTO | onRoomEncryptionEvent ERROR FAILED TO SETUP CRYPTO ")
// } finally {
val userIds = getRoomUserIds(roomId)
setEncryptionInRoom(roomId, event.content?.toModel<EncryptionEventContent>(), userIds)
val userIds = getRoomUserIds(roomId)
setEncryptionInRoom(roomId, event.content?.toModel<EncryptionEventContent>(), userIds)
// }
// }
}
@ -559,7 +560,7 @@ internal class RustCryptoService @Inject constructor(
// know what other servers are in the room at the time they've been invited.
// They therefore will not send device updates if a user logs in whilst
// their state is invite.
olmMachine.updateTrackedUsers(listOf(userId))
olmMachine.updateTrackedUsers(listOf(userId))
} else {
// nop
}
@ -651,8 +652,8 @@ internal class RustCryptoService @Inject constructor(
this.verificationService.onEvent(null, event)
}
}
liveEventManager.get().dispatchOnLiveToDevice(event)
}
liveEventManager.get().dispatchOnLiveToDevice(event)
}
}
/**
@ -717,12 +718,14 @@ internal class RustCryptoService @Inject constructor(
return cryptoStore.getLiveGlobalCryptoConfig()
}
// Until https://github.com/matrix-org/matrix-rust-sdk/issues/1364
override fun supportsDisablingKeyGossiping() = false
override fun enableKeyGossiping(enable: Boolean) {
cryptoStore.enableKeyGossiping(enable)
if (!enable) throw UnsupportedOperationException("Not supported by rust")
}
override fun isKeyGossipingEnabled(): Boolean {
return cryptoStore.isKeyGossipingEnabled()
return true
}
override fun supportsShareKeysOnInvite() = false
@ -730,10 +733,9 @@ internal class RustCryptoService @Inject constructor(
override fun supportsKeyWithheld() = true
override fun supportsForwardedKeyWiththeld() = false
override fun enableShareKeyOnInvite(enable: Boolean) {
if (enable && !supportsShareKeysOnInvite()) {
throw java.lang.UnsupportedOperationException("Enable share key on invite not implemented in rust");
throw java.lang.UnsupportedOperationException("Enable share key on invite not implemented in rust")
}
}
@ -844,19 +846,20 @@ internal class RustCryptoService @Inject constructor(
return "DefaultCryptoService of $myUserId ($deviceId)"
}
// Until https://github.com/matrix-org/matrix-rust-sdk/issues/701
// https://github.com/matrix-org/matrix-rust-sdk/issues/702
override fun supportKeyRequestInspection() = false
override fun getOutgoingRoomKeyRequests(): List<OutgoingKeyRequest> {
return cryptoStore.getOutgoingRoomKeyRequests()
throw UnsupportedOperationException("Not supported by rust")
}
override fun getOutgoingRoomKeyRequestsPaged(): LiveData<PagedList<OutgoingKeyRequest>> {
return cryptoStore.getOutgoingRoomKeyRequestsPaged()
throw UnsupportedOperationException("Not supported by rust")
// return cryptoStore.getOutgoingRoomKeyRequestsPaged()
}
override fun getIncomingRoomKeyRequestsPaged(): LiveData<PagedList<IncomingRoomKeyRequest>> {
return cryptoStore.getGossipingEventsTrail(TrailType.IncomingKeyRequest) {
IncomingRoomKeyRequest.fromEvent(it)
?: IncomingRoomKeyRequest(localCreationTimestamp = 0L)
}
throw UnsupportedOperationException("Not supported by rust")
}
override suspend fun manuallyAcceptRoomKeyRequest(request: IncomingRoomKeyRequest) {
@ -864,25 +867,23 @@ internal class RustCryptoService @Inject constructor(
}
override fun getIncomingRoomKeyRequests(): List<IncomingRoomKeyRequest> {
return emptyList()
throw UnsupportedOperationException("Not supported by rust")
}
override fun getGossipingEventsTrail(): LiveData<PagedList<AuditTrail>> {
return cryptoStore.getGossipingEventsTrail()
throw UnsupportedOperationException("Not supported by rust")
}
override fun getGossipingEvents(): List<AuditTrail> {
return cryptoStore.getGossipingEvents()
throw UnsupportedOperationException("Not supported by rust")
}
override fun getSharedWithInfo(roomId: String?, sessionId: String): MXUsersDevicesMap<Int> {
// TODO not exposed in rust?
return cryptoStore.getSharedWithInfo(roomId, sessionId)
throw UnsupportedOperationException("Not supported by rust")
}
override fun getWithHeldMegolmSession(roomId: String, sessionId: String): RoomKeyWithHeldContent? {
// TODO not exposed in rust.
return cryptoStore.getWithHeldMegolmSession(roomId, sessionId)
throw UnsupportedOperationException("Not supported by rust")
}
override fun logDbUsageInfo() {

View File

@ -242,6 +242,9 @@ class BugReporter @Inject constructor(
activeSessionHolder.getSafeActiveSession()
?.takeIf { !mIsCancelled && withKeyRequestHistory }
?.cryptoService()
?.takeIf {
it.supportKeyRequestInspection()
}
?.getGossipingEvents()
?.let { GossipingEventsSerializer().serialize(it) }
?.toByteArray()

View File

@ -187,6 +187,7 @@ class VectorPreferences @Inject constructor(
const val SETTINGS_PREF_SPACE_CATEGORY = "SETTINGS_PREF_SPACE_CATEGORY"
private const val SETTINGS_DEVELOPER_MODE_PREFERENCE_KEY = "SETTINGS_DEVELOPER_MODE_PREFERENCE_KEY"
const val SETTINGS_DEVELOPER_MODE_KEY_REQUEST_AUDIT_KEY = "SETTINGS_DEVELOPER_MODE_KEY_REQUEST_AUDIT_KEY"
private const val SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY = "SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY"
private const val SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY = "SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY"
private const val SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY = "SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY"

View File

@ -73,6 +73,10 @@ class VectorSettingsAdvancedSettingsFragment :
copyToClipboard(requireActivity(), session.sessionParams.credentials.accessToken)
true
}
findPreference<VectorPreference>(VectorPreferences.SETTINGS_DEVELOPER_MODE_KEY_REQUEST_AUDIT_KEY)?.apply {
isVisible = session.cryptoService().supportKeyRequestInspection()
}
}
private fun setupRageShakeSection() {

View File

@ -52,11 +52,13 @@ class GossipingEventsPaperTrailViewModel @AssistedInject constructor(
setState {
copy(events = Loading())
}
session.cryptoService().getGossipingEventsTrail()
.asFlow()
.execute {
copy(events = it)
}
if (session.cryptoService().supportKeyRequestInspection()) {
session.cryptoService().getGossipingEventsTrail()
.asFlow()
.execute {
copy(events = it)
}
}
}
override fun handle(action: EmptyAction) {}

View File

@ -90,6 +90,7 @@
<im.vector.app.core.preference.VectorPreference
android:persistent="false"
android:key="SETTINGS_DEVELOPER_MODE_KEY_REQUEST_AUDIT_KEY"
android:title="@string/settings_key_requests"
app:fragment="im.vector.app.features.settings.devtools.KeyRequestsFragment" />