Fix / Error management and clear keys

This commit is contained in:
Valere 2020-01-28 15:35:11 +01:00
parent f021f8110d
commit ca4ed6e1bd
8 changed files with 88 additions and 149 deletions

View File

@ -3,12 +3,19 @@ package im.vector.matrix.android.internal.crypto.crosssigning
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import im.vector.matrix.android.InstrumentedTest import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.common.* import im.vector.matrix.android.common.CommonTestHelper
import im.vector.matrix.android.common.CryptoTestHelper
import im.vector.matrix.android.common.SessionTestParams
import im.vector.matrix.android.common.TestConstants
import im.vector.matrix.android.common.TestMatrixCallback
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
import im.vector.matrix.android.internal.crypto.model.rest.SignatureUploadResponse
import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
import org.junit.Assert.* import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
import org.junit.FixMethodOrder import org.junit.FixMethodOrder
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@ -43,7 +50,7 @@ class XSigningTest : InstrumentedTest {
val userKey = myCrossSigningKeys?.userKey() val userKey = myCrossSigningKeys?.userKey()
assertNotNull("User key should be stored", userKey?.unpaddedBase64PublicKey) assertNotNull("User key should be stored", userKey?.unpaddedBase64PublicKey)
assertTrue("Signing Keys should be trusted", myCrossSigningKeys?.isTrusted == true) assertTrue("Signing Keys should be trusted", myCrossSigningKeys?.isTrusted() == true)
assertTrue("Signing Keys should be trusted", aliceSession.getCrossSigningService().checkUserTrust(aliceSession.myUserId).isVerified()) assertTrue("Signing Keys should be trusted", aliceSession.getCrossSigningService().checkUserTrust(aliceSession.myUserId).isVerified())
@ -88,7 +95,7 @@ class XSigningTest : InstrumentedTest {
assertEquals("Bob keys from alice pov should match", bobKeysFromAlicePOV?.masterKey()?.unpaddedBase64PublicKey, bobSession.getCrossSigningService().getMyCrossSigningKeys()?.masterKey()?.unpaddedBase64PublicKey) assertEquals("Bob keys from alice pov should match", bobKeysFromAlicePOV?.masterKey()?.unpaddedBase64PublicKey, bobSession.getCrossSigningService().getMyCrossSigningKeys()?.masterKey()?.unpaddedBase64PublicKey)
assertEquals("Bob keys from alice pov should match", bobKeysFromAlicePOV?.selfSigningKey()?.unpaddedBase64PublicKey, bobSession.getCrossSigningService().getMyCrossSigningKeys()?.selfSigningKey()?.unpaddedBase64PublicKey) assertEquals("Bob keys from alice pov should match", bobKeysFromAlicePOV?.selfSigningKey()?.unpaddedBase64PublicKey, bobSession.getCrossSigningService().getMyCrossSigningKeys()?.selfSigningKey()?.unpaddedBase64PublicKey)
assertTrue("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV?.isTrusted == false) assertTrue("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV?.isTrusted() == false)
mTestHelper.signout(aliceSession) mTestHelper.signout(aliceSession)
mTestHelper.signout(bobSession) mTestHelper.signout(bobSession)
@ -126,11 +133,11 @@ class XSigningTest : InstrumentedTest {
mTestHelper.await(downloadLatch) mTestHelper.await(downloadLatch)
val bobKeysFromAlicePOV = aliceSession.getCrossSigningService().getUserCrossSigningKeys(bobUserId) val bobKeysFromAlicePOV = aliceSession.getCrossSigningService().getUserCrossSigningKeys(bobUserId)
assertTrue("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV?.isTrusted == false) assertTrue("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV?.isTrusted() == false)
val trustLatch = CountDownLatch(1) val trustLatch = CountDownLatch(1)
aliceSession.getCrossSigningService().trustUser(bobUserId, object : MatrixCallback<SignatureUploadResponse> { aliceSession.getCrossSigningService().trustUser(bobUserId, object : MatrixCallback<Unit> {
override fun onSuccess(data: SignatureUploadResponse) { override fun onSuccess(data: Unit) {
trustLatch.countDown() trustLatch.countDown()
} }
@ -167,8 +174,8 @@ class XSigningTest : InstrumentedTest {
// Manually mark it as trusted from first session // Manually mark it as trusted from first session
val bobSignLatch = CountDownLatch(1) val bobSignLatch = CountDownLatch(1)
bobSession.getCrossSigningService().signDevice(bobSecondDeviceId!!, object : MatrixCallback<SignatureUploadResponse> { bobSession.getCrossSigningService().signDevice(bobSecondDeviceId!!, object : MatrixCallback<Unit> {
override fun onSuccess(data: SignatureUploadResponse) { override fun onSuccess(data: Unit) {
bobSignLatch.countDown() bobSignLatch.countDown()
} }

View File

@ -47,12 +47,12 @@ interface CrossSigningService {
fun getMyCrossSigningKeys(): MXCrossSigningInfo? fun getMyCrossSigningKeys(): MXCrossSigningInfo?
fun canCrossSign(): Boolean fun canCrossSign(): Boolean
fun trustUser(userId: String, callback: MatrixCallback<SignatureUploadResponse>) fun trustUser(userId: String, callback: MatrixCallback<Unit>)
/** /**
* Sign one of your devices and upload the signature * Sign one of your devices and upload the signature
*/ */
fun signDevice(deviceId: String, callback: MatrixCallback<SignatureUploadResponse>) fun signDevice(deviceId: String, callback: MatrixCallback<Unit>)
fun checkDeviceTrust(userId: String, deviceId: String, locallyTrusted: Boolean?) : DeviceTrustResult fun checkDeviceTrust(userId: String, deviceId: String, locallyTrusted: Boolean?) : DeviceTrustResult
} }

View File

@ -1,38 +0,0 @@
/*
* Copyright 2020 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.matrix.android.api.session.crypto.crosssigning
/**
* Defines the account cross signing state.
*
*/
enum class CrossSigningState {
/** Current state is unknown, need to download user keys from server to resolve */
Unknown,
/** Currently dowloading user keys*/
CheckingState,
/** No Cross signing keys are defined on the server */
Disabled,
/** CrossSigning keys are beeing created and uploaded to the server */
Enabling,
/** Cross signing keys exists and are trusted*/
Trusted,
/** Cross signing keys exists but are not yet trusted*/
Untrusted,
/** The local cross signing keys do not match with the server keys*/
Conflicted
}

View File

@ -21,7 +21,6 @@ import dagger.Lazy
import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.auth.data.Credentials
import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService
import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningState
import im.vector.matrix.android.api.session.crypto.crosssigning.MXCrossSigningInfo import im.vector.matrix.android.api.session.crypto.crosssigning.MXCrossSigningInfo
import im.vector.matrix.android.api.util.Optional import im.vector.matrix.android.api.util.Optional
import im.vector.matrix.android.internal.crypto.DeviceListManager import im.vector.matrix.android.internal.crypto.DeviceListManager
@ -30,16 +29,12 @@ import im.vector.matrix.android.internal.crypto.MyDeviceInfoHolder
import im.vector.matrix.android.internal.crypto.model.CryptoCrossSigningKey import im.vector.matrix.android.internal.crypto.model.CryptoCrossSigningKey
import im.vector.matrix.android.internal.crypto.model.KeyUsage import im.vector.matrix.android.internal.crypto.model.KeyUsage
import im.vector.matrix.android.internal.crypto.model.rest.KeysQueryResponse import im.vector.matrix.android.internal.crypto.model.rest.KeysQueryResponse
import im.vector.matrix.android.internal.crypto.model.rest.SignatureUploadResponse
import im.vector.matrix.android.internal.crypto.model.rest.UploadResponseFailure
import im.vector.matrix.android.internal.crypto.model.rest.UploadSignatureQueryBuilder import im.vector.matrix.android.internal.crypto.model.rest.UploadSignatureQueryBuilder
import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
import im.vector.matrix.android.internal.crypto.tasks.UploadSignaturesTask import im.vector.matrix.android.internal.crypto.tasks.UploadSignaturesTask
import im.vector.matrix.android.internal.crypto.tasks.UploadSigningKeysTask import im.vector.matrix.android.internal.crypto.tasks.UploadSigningKeysTask
import im.vector.matrix.android.internal.di.MoshiProvider
import im.vector.matrix.android.internal.di.UserId import im.vector.matrix.android.internal.di.UserId
import im.vector.matrix.android.internal.extensions.foldToCallback
import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.SessionScope
import im.vector.matrix.android.internal.task.TaskConstraints import im.vector.matrix.android.internal.task.TaskConstraints
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor
@ -47,7 +42,6 @@ import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.util.JsonCanonicalizer import im.vector.matrix.android.internal.util.JsonCanonicalizer
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.matrix.olm.OlmPkSigning import org.matrix.olm.OlmPkSigning
import org.matrix.olm.OlmUtility import org.matrix.olm.OlmUtility
import timber.log.Timber import timber.log.Timber
@ -69,8 +63,6 @@ internal class DefaultCrossSigningService @Inject constructor(
private var olmUtility: OlmUtility? = null private var olmUtility: OlmUtility? = null
private var crossSigningState: CrossSigningState = CrossSigningState.Unknown
private var masterPkSigning: OlmPkSigning? = null private var masterPkSigning: OlmPkSigning? = null
private var userPkSigning: OlmPkSigning? = null private var userPkSigning: OlmPkSigning? = null
private var selfSigningPkSigning: OlmPkSigning? = null private var selfSigningPkSigning: OlmPkSigning? = null
@ -152,8 +144,6 @@ internal class DefaultCrossSigningService @Inject constructor(
*/ */
override fun initializeCrossSigning(authParams: UserPasswordAuth?, callback: MatrixCallback<Unit>?) { override fun initializeCrossSigning(authParams: UserPasswordAuth?, callback: MatrixCallback<Unit>?) {
Timber.d("## CrossSigning initializeCrossSigning") Timber.d("## CrossSigning initializeCrossSigning")
// TODO sync that
crossSigningState = CrossSigningState.Enabling
val myUserID = credentials.userId val myUserID = credentials.userId
@ -222,13 +212,10 @@ internal class DefaultCrossSigningService @Inject constructor(
cryptoStore.setUserKeysAsTrusted(myUserID) cryptoStore.setUserKeysAsTrusted(myUserID)
cryptoStore.storePrivateKeysInfo(masterKeyPrivateKey?.toBase64NoPadding(), uskPrivateKey?.toBase64NoPadding(), sskPrivateKey?.toBase64NoPadding()) cryptoStore.storePrivateKeysInfo(masterKeyPrivateKey?.toBase64NoPadding(), uskPrivateKey?.toBase64NoPadding(), sskPrivateKey?.toBase64NoPadding())
// TODO we should ensure that they are sent
// TODO error handling?
uploadSigningKeysTask.configureWith(params) { uploadSigningKeysTask.configureWith(params) {
this.retryCount = 3
this.constraints = TaskConstraints(true) this.constraints = TaskConstraints(true)
this.callback = object : MatrixCallback<KeysQueryResponse> { this.callback = object : MatrixCallback<Unit> {
override fun onSuccess(data: KeysQueryResponse) { override fun onSuccess(data: Unit) {
Timber.i("## CrossSigning - Keys succesfully uploaded") Timber.i("## CrossSigning - Keys succesfully uploaded")
// Sign the current device with SSK // Sign the current device with SSK
@ -261,44 +248,44 @@ internal class DefaultCrossSigningService @Inject constructor(
resetTrustOnKeyChange() resetTrustOnKeyChange()
uploadSignaturesTask.configureWith(UploadSignaturesTask.Params(uploadSignatureQueryBuilder.build())) { uploadSignaturesTask.configureWith(UploadSignaturesTask.Params(uploadSignatureQueryBuilder.build())) {
this.retryCount = 3 //this.retryCount = 3
this.constraints = TaskConstraints(true) this.constraints = TaskConstraints(true)
this.callback = object : MatrixCallback<SignatureUploadResponse> { this.callback = object : MatrixCallback<Unit> {
override fun onSuccess(data: SignatureUploadResponse) { override fun onSuccess(data: Unit) {
Timber.i("## CrossSigning - signatures succesfuly uploaded") Timber.i("## CrossSigning - signatures succesfuly uploaded")
// Force download of my keys now callback?.onSuccess(Unit)
kotlin.runCatching {
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
deviceListManager.downloadKeys(listOf(myUserID), true)
}
}.foldToCallback(object : MatrixCallback<Any> {
override fun onSuccess(data: Any) {
callback?.onSuccess(Unit)
}
override fun onFailure(failure: Throwable) {
callback?.onFailure(failure)
}
})
} }
override fun onFailure(failure: Throwable) { override fun onFailure(failure: Throwable) {
//Clear
Timber.e(failure, "## CrossSigning - Failed to upload signatures") Timber.e(failure, "## CrossSigning - Failed to upload signatures")
clearSigningKeys()
} }
} }
}.executeBy(taskExecutor) }.executeBy(taskExecutor)
crossSigningState = CrossSigningState.Trusted
} }
override fun onFailure(failure: Throwable) { override fun onFailure(failure: Throwable) {
Timber.e(failure, "## CrossSigning - Failed to upload signing keys") Timber.e(failure, "## CrossSigning - Failed to upload signing keys")
clearSigningKeys()
callback?.onFailure(failure) callback?.onFailure(failure)
} }
} }
}.executeBy(taskExecutor) }.executeBy(taskExecutor)
} }
private fun clearSigningKeys() {
this@DefaultCrossSigningService.masterPkSigning?.releaseSigning()
this@DefaultCrossSigningService.userPkSigning?.releaseSigning()
this@DefaultCrossSigningService.selfSigningPkSigning?.releaseSigning()
this@DefaultCrossSigningService.masterPkSigning = null
this@DefaultCrossSigningService.userPkSigning = null
this@DefaultCrossSigningService.selfSigningPkSigning = null
cryptoStore.setMyCrossSigningInfo(null)
cryptoStore.storePrivateKeysInfo(null, null, null)
}
private fun resetTrustOnKeyChange() { private fun resetTrustOnKeyChange() {
Timber.i("## CrossSigning - Clear all other user trust") Timber.i("## CrossSigning - Clear all other user trust")
@ -481,7 +468,7 @@ internal class DefaultCrossSigningService @Inject constructor(
return checkSelfTrust().isVerified() && cryptoStore.getCrossSigningPrivateKeys()?.selfSigned != null return checkSelfTrust().isVerified() && cryptoStore.getCrossSigningPrivateKeys()?.selfSigned != null
} }
override fun trustUser(userId: String, callback: MatrixCallback<SignatureUploadResponse>) { override fun trustUser(userId: String, callback: MatrixCallback<Unit>) {
Timber.d("## CrossSigning - Mark user $userId as trusted ") Timber.d("## CrossSigning - Mark user $userId as trusted ")
// We should have this user keys // We should have this user keys
val otherMasterKeys = getUserCrossSigningKeys(userId)?.masterKey() val otherMasterKeys = getUserCrossSigningKeys(userId)?.masterKey()
@ -513,42 +500,16 @@ internal class DefaultCrossSigningService @Inject constructor(
cryptoStore.setUserKeysAsTrusted(userId, true) cryptoStore.setUserKeysAsTrusted(userId, true)
// TODO update local copy with new signature directly here? kind of local echo of trust? // TODO update local copy with new signature directly here? kind of local echo of trust?
Timber.d("## CrossSigning - Upload signature of $userId MSK signed by USK") Timber.d("## CrossSigning - Upload signature of $userId MSK signed by USK")
val uploadQuery = UploadSignatureQueryBuilder() val uploadQuery = UploadSignatureQueryBuilder()
.withSigningKeyInfo(otherMasterKeys.copyForSignature(credentials.userId, userPubKey, newSignature)) .withSigningKeyInfo(otherMasterKeys.copyForSignature(credentials.userId, userPubKey, newSignature))
.build() .build()
uploadSignaturesTask.configureWith(UploadSignaturesTask.Params(uploadQuery)) { uploadSignaturesTask.configureWith(UploadSignaturesTask.Params(uploadQuery)) {
this.callback = object: MatrixCallback<SignatureUploadResponse> { this.callback = callback
override fun onSuccess(data: SignatureUploadResponse) {
//force a key download to refresh trust?
val uldata = data
kotlin.runCatching {
Timber.d("## CrossSigning - Force download of user keys")
cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
deviceListManager.downloadKeys(listOf(userId), true)
}
}.foldToCallback(object : MatrixCallback<Any> {
override fun onSuccess(data: Any) {
callback.onSuccess(uldata)
}
override fun onFailure(failure: Throwable) {
Timber.e("## CrossSigning - fail to download keys", failure)
callback.onFailure(failure)
}
})
}
override fun onFailure(failure: Throwable) {
Timber.e("## CrossSigning - fail to upload signature", failure)
callback.onFailure(failure)
}
}
}.executeBy(taskExecutor) }.executeBy(taskExecutor)
} }
override fun signDevice(deviceId: String, callback: MatrixCallback<SignatureUploadResponse>) { override fun signDevice(deviceId: String, callback: MatrixCallback<Unit>) {
// This device should be yours // This device should be yours
val device = cryptoStore.getUserDevice(credentials.userId, deviceId) val device = cryptoStore.getUserDevice(credentials.userId, deviceId)
if (device == null) { if (device == null) {
@ -590,22 +551,7 @@ internal class DefaultCrossSigningService @Inject constructor(
.withDeviceInfo(toUpload) .withDeviceInfo(toUpload)
.build() .build()
uploadSignaturesTask.configureWith(UploadSignaturesTask.Params(uploadQuery)) { uploadSignaturesTask.configureWith(UploadSignaturesTask.Params(uploadQuery)) {
this.callback = object : MatrixCallback<SignatureUploadResponse> { this.callback = callback
override fun onFailure(failure: Throwable) {
callback.onFailure(failure)
}
override fun onSuccess(data: SignatureUploadResponse) {
val watchedFailure = data.failures?.get(userId)?.get(deviceId)
if (watchedFailure == null) {
callback.onSuccess(data)
} else {
val failure = MoshiProvider.providesMoshi().adapter(UploadResponseFailure::class.java).fromJson(watchedFailure.toString())?.message
?: watchedFailure.toString()
callback.onFailure(Throwable(failure))
}
}
}
}.executeBy(taskExecutor) }.executeBy(taskExecutor)
} }

View File

@ -23,7 +23,7 @@ import im.vector.matrix.android.internal.task.Task
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import javax.inject.Inject import javax.inject.Inject
internal interface UploadSignaturesTask : Task<UploadSignaturesTask.Params, SignatureUploadResponse> { internal interface UploadSignaturesTask : Task<UploadSignaturesTask.Params, Unit> {
data class Params( data class Params(
val signatures: Map<String, Map<String, Any>> val signatures: Map<String, Map<String, Any>>
) )
@ -34,14 +34,18 @@ internal class DefaultUploadSignaturesTask @Inject constructor(
private val eventBus: EventBus private val eventBus: EventBus
) : UploadSignaturesTask { ) : UploadSignaturesTask {
override suspend fun execute(params: UploadSignaturesTask.Params): SignatureUploadResponse { override suspend fun execute(params: UploadSignaturesTask.Params): Unit {
val executeRequest = executeRequest<SignatureUploadResponse>(eventBus) {
apiCall = cryptoApi.uploadSignatures(params.signatures) try {
val response = executeRequest<SignatureUploadResponse>(eventBus) {
apiCall = cryptoApi.uploadSignatures(params.signatures)
}
if (response.failures?.isNotEmpty() == true) {
throw Throwable(response.failures.toString())
}
return
} catch (f: Failure) {
throw f
} }
if (executeRequest.failures?.isNotEmpty() == true) {
// TODO better
throw Failure.OtherServerError(executeRequest.toString(), 400)
}
return executeRequest
} }
} }

View File

@ -30,7 +30,7 @@ import im.vector.matrix.android.internal.task.Task
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import javax.inject.Inject import javax.inject.Inject
internal interface UploadSigningKeysTask : Task<UploadSigningKeysTask.Params, KeysQueryResponse> { internal interface UploadSigningKeysTask : Task<UploadSigningKeysTask.Params, Unit> {
data class Params( data class Params(
// the device keys to send. // the device keys to send.
val masterKey: CryptoCrossSigningKey, val masterKey: CryptoCrossSigningKey,
@ -42,11 +42,13 @@ internal interface UploadSigningKeysTask : Task<UploadSigningKeysTask.Params, Ke
) )
} }
data class UploadSigningKeys(val failures: Map<String, Any>?) : Failure.FeatureFailure()
internal class DefaultUploadSigningKeysTask @Inject constructor( internal class DefaultUploadSigningKeysTask @Inject constructor(
private val cryptoApi: CryptoApi, private val cryptoApi: CryptoApi,
private val eventBus: EventBus private val eventBus: EventBus
) : UploadSigningKeysTask { ) : UploadSigningKeysTask {
override suspend fun execute(params: UploadSigningKeysTask.Params): KeysQueryResponse { override suspend fun execute(params: UploadSigningKeysTask.Params) {
val uploadQuery = UploadSigningKeysBody( val uploadQuery = UploadSigningKeysBody(
masterKey = params.masterKey.toRest(), masterKey = params.masterKey.toRest(),
userSigningKey = params.userKey.toRest(), userSigningKey = params.userKey.toRest(),
@ -55,9 +57,13 @@ internal class DefaultUploadSigningKeysTask @Inject constructor(
) )
try { try {
// Make a first request to start user-interactive authentication // Make a first request to start user-interactive authentication
return executeRequest(eventBus) { val request = executeRequest<KeysQueryResponse>(eventBus) {
apiCall = cryptoApi.uploadSigningKeys(uploadQuery) apiCall = cryptoApi.uploadSigningKeys(uploadQuery)
} }
if (request.failures?.isNotEmpty() == true) {
throw UploadSigningKeys(request.failures)
}
return
} catch (throwable: Throwable) { } catch (throwable: Throwable) {
if (throwable is Failure.OtherServerError if (throwable is Failure.OtherServerError
&& throwable.httpCode == 401 && throwable.httpCode == 401
@ -73,10 +79,18 @@ internal class DefaultUploadSigningKeysTask @Inject constructor(
null null
}?.let { }?.let {
// Retry with authentication // Retry with authentication
return executeRequest(eventBus) { try {
apiCall = cryptoApi.uploadSigningKeys( val req = executeRequest<KeysQueryResponse>(eventBus) {
uploadQuery.copy(auth = params.userPasswordAuth.copy(session = it.session)) apiCall = cryptoApi.uploadSigningKeys(
) uploadQuery.copy(auth = params.userPasswordAuth.copy(session = it.session))
)
}
if (req.failures?.isNotEmpty() == true) {
throw UploadSigningKeys(req.failures)
}
return
} catch (failure: Throwable) {
throw failure
} }
} }
} }

View File

@ -308,7 +308,7 @@ internal abstract class SASDefaultVerificationTransaction(
if (otherMasterKeyIsVerified && otherUserId != credentials.userId) { if (otherMasterKeyIsVerified && otherUserId != credentials.userId) {
// we should trust this master key // we should trust this master key
// And check verification MSK -> SSK? // And check verification MSK -> SSK?
crossSigningService.trustUser(otherUserId, object : MatrixCallback<SignatureUploadResponse> { crossSigningService.trustUser(otherUserId, object : MatrixCallback<Unit> {
override fun onFailure(failure: Throwable) { override fun onFailure(failure: Throwable) {
Timber.e(failure, "## SAS Verification: Failed to trust User $otherUserId") Timber.e(failure, "## SAS Verification: Failed to trust User $otherUserId")
} }
@ -318,7 +318,7 @@ internal abstract class SASDefaultVerificationTransaction(
if (otherUserId == credentials.userId) { if (otherUserId == credentials.userId) {
// If me it's reasonable to sign and upload the device signature // If me it's reasonable to sign and upload the device signature
// Notice that i might not have the private keys, so may ot be able to do it // Notice that i might not have the private keys, so may ot be able to do it
crossSigningService.signDevice(otherDeviceId!!, object : MatrixCallback<SignatureUploadResponse> { crossSigningService.signDevice(otherDeviceId!!, object : MatrixCallback<Unit> {
override fun onFailure(failure: Throwable) { override fun onFailure(failure: Throwable) {
Timber.w(failure, "## SAS Verification: Failed to sign new device $otherDeviceId") Timber.w(failure, "## SAS Verification: Failed to sign new device $otherDeviceId")
} }

View File

@ -23,7 +23,6 @@ import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.MvRxState
import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.Success import com.airbnb.mvrx.Success
import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.ViewModelContext import com.airbnb.mvrx.ViewModelContext
import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject import com.squareup.inject.assisted.AssistedInject
@ -129,7 +128,14 @@ class CrossSigningSettingsViewModel @AssistedInject constructor(@Assisted privat
} }
} }
} }
_requestLiveData.postValue(LiveEvent(Fail(Throwable("You cannot do that from mobile")))) when (failure) {
is Failure.ServerError -> {
_requestLiveData.postValue(LiveEvent(Fail(Throwable(failure.error.message))))
}
else -> {
_requestLiveData.postValue(LiveEvent(Fail(failure)))
}
}
setState { setState {
copy(isUploadingKeys = false) copy(isUploadingKeys = false)
} }