only cancel reset in onStop

This commit is contained in:
Adam Velebil 2024-04-11 14:44:18 +02:00
parent 074ab9c1d4
commit 8318b5e68b
No known key found for this signature in database
GPG Key ID: C9B1E4A3CBBD2E10
4 changed files with 41 additions and 41 deletions

View File

@ -27,6 +27,4 @@ abstract class AppContextManager {
open fun dispose() {}
open fun onPause() {}
open fun onResume() {}
}

View File

@ -258,8 +258,6 @@ class MainActivity : FlutterFragmentActivity() {
appPreferences.registerListener(sharedPreferencesListener)
preserveConnectionOnPause = false
contextManager?.onResume()
}
override fun onMultiWindowModeChanged(isInMultiWindowMode: Boolean, newConfig: Configuration) {
@ -390,6 +388,7 @@ class MainActivity : FlutterFragmentActivity() {
OperationContext.FidoFingerprints,
OperationContext.FidoPasskeys -> FidoManager(
messenger,
this,
deviceManager,
fidoViewModel,
viewModel,

View File

@ -16,6 +16,7 @@
package com.yubico.authenticator.fido
import androidx.lifecycle.LifecycleOwner
import com.yubico.authenticator.AppContextManager
import com.yubico.authenticator.DialogManager
import com.yubico.authenticator.MainViewModel
@ -23,22 +24,16 @@ import com.yubico.authenticator.NULL
import com.yubico.authenticator.asString
import com.yubico.authenticator.device.DeviceListener
import com.yubico.authenticator.device.DeviceManager
import com.yubico.authenticator.device.Info
import com.yubico.authenticator.device.UnknownDevice
import com.yubico.authenticator.fido.data.FidoCredential
import com.yubico.authenticator.fido.data.FidoFingerprint
import com.yubico.authenticator.fido.data.Session
import com.yubico.authenticator.fido.data.SessionInfo
import com.yubico.authenticator.fido.data.YubiKitFidoSession
import com.yubico.authenticator.setHandler
import com.yubico.authenticator.yubikit.getDeviceInfo
import com.yubico.authenticator.yubikit.withConnection
import com.yubico.yubikit.android.transport.nfc.NfcYubiKeyDevice
import com.yubico.yubikit.android.transport.usb.UsbYubiKeyDevice
import com.yubico.yubikit.core.Transport
import com.yubico.yubikit.core.YubiKeyConnection
import com.yubico.yubikit.core.YubiKeyDevice
import com.yubico.yubikit.core.application.ApplicationNotAvailableException
import com.yubico.yubikit.core.application.CommandState
import com.yubico.yubikit.core.fido.CtapException
import com.yubico.yubikit.core.fido.FidoConnection
@ -54,7 +49,6 @@ import com.yubico.yubikit.fido.ctap.PinUvAuthDummyProtocol
import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol
import com.yubico.yubikit.fido.ctap.PinUvAuthProtocolV1
import com.yubico.yubikit.fido.ctap.PinUvAuthProtocolV2
import com.yubico.yubikit.support.DeviceUtil
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodChannel
import kotlinx.coroutines.CoroutineScope
@ -71,6 +65,7 @@ typealias FidoAction = (Result<YubiKitFidoSession, Exception>) -> Unit
class FidoManager(
messenger: BinaryMessenger,
lifecycleOwner: LifecycleOwner,
private val deviceManager: DeviceManager,
private val fidoViewModel: FidoViewModel,
mainViewModel: MainViewModel,
@ -115,15 +110,14 @@ class FidoManager(
private var pinRetries : Int? = null
private val resetHelper =
FidoResetHelper(deviceManager, fidoViewModel, mainViewModel, connectionHelper, pinStore)
override fun onPause() {
resetHelper.onPause()
}
override fun onResume() {
resetHelper.onResume()
}
FidoResetHelper(
lifecycleOwner,
deviceManager,
fidoViewModel,
mainViewModel,
connectionHelper,
pinStore
)
init {
pinRetries = null
@ -227,6 +221,10 @@ class FidoManager(
logger.debug("This is a different key than previous, invalidating the PIN token")
pinStore.setPin(null)
connectionHelper.cancelPending()
if (resetHelper.inProgress) {
logger.debug("Cannot reset this key")
resetHelper.cancelReset()
}
}
val infoData = fidoSession.cachedInfo

View File

@ -16,6 +16,8 @@
package com.yubico.authenticator.fido
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.yubico.authenticator.MainViewModel
import com.yubico.authenticator.NULL
import com.yubico.authenticator.device.DeviceManager
@ -29,14 +31,11 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable
import org.json.JSONObject
import org.slf4j.LoggerFactory
import java.io.IOException
import java.util.Timer
import java.util.TimerTask
import java.util.concurrent.Executors
import kotlin.concurrent.schedule
import kotlin.coroutines.cancellation.CancellationException
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
@ -67,6 +66,7 @@ fun createCaptureErrorEvent(code: Int) : FidoRegisterFpCaptureErrorEvent {
}
class FidoResetHelper(
private val lifecycleOwner: LifecycleOwner,
private val deviceManager: DeviceManager,
private val fidoViewModel: FidoViewModel,
private val mainViewModel: MainViewModel,
@ -81,8 +81,21 @@ class FidoResetHelper(
private var resetCommandState: CommandState? = null
private var cancelReset: Boolean = false
private val lifecycleObserver = object : DefaultLifecycleObserver {
override fun onStop(owner: LifecycleOwner) {
super.onStop(owner)
if (inProgress) {
logger.debug("Cancelling ongoing reset")
cancelReset()
}
}
}
suspend fun reset(): String {
try {
withContext(Dispatchers.Main) {
lifecycleOwner.lifecycle.addObserver(lifecycleObserver)
}
deviceManager.clearDeviceInfoOnDisconnect = false
inProgress = true
fidoViewModel.updateResetState(FidoResetState.Remove)
@ -96,6 +109,9 @@ class FidoResetHelper(
} catch (e: CancellationException) {
logger.debug("FIDO reset cancelled")
} finally {
withContext(Dispatchers.Main) {
lifecycleOwner.lifecycle.removeObserver(lifecycleObserver)
}
inProgress = false
deviceManager.clearDeviceInfoOnDisconnect = true
}
@ -109,21 +125,6 @@ class FidoResetHelper(
return NULL
}
private var cancellationTimer: TimerTask? = null
fun onPause() {
cancellationTimer?.cancel()
cancellationTimer = Timer().schedule(300) {
// the timer has not been cancelled at this point,
// the application is in PAUSED state longer than 300ms
// cancel ongoing reset
cancelReset()
}
}
fun onResume() {
cancellationTimer?.cancel()
}
private suspend fun waitForUsbDisconnect() = suspendCoroutine { continuation ->
coroutineScope.launch {
cancelReset = false
@ -165,8 +166,12 @@ class FidoResetHelper(
connectionHelper.useSessionUsb(usbYubiKeyDevice) { fidoSession ->
resetCommandState = CommandState()
try {
doReset(fidoSession)
continuation.resume(Unit)
if (cancelReset) {
continuation.resumeWithException(CancellationException())
} else {
doReset(fidoSession)
continuation.resume(Unit)
}
} catch (e: CtapException) {
when (e.ctapError) {
CtapException.ERR_KEEPALIVE_CANCEL -> {