mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
fix: better challenge channel implementation
This commit is contained in:
@@ -42,8 +42,6 @@ import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
|
|||||||
import com.kunzisoft.keepass.database.element.node.Node
|
import com.kunzisoft.keepass.database.element.node.Node
|
||||||
import com.kunzisoft.keepass.database.element.node.NodeId
|
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||||
import com.kunzisoft.keepass.database.element.node.Type
|
import com.kunzisoft.keepass.database.element.node.Type
|
||||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
|
||||||
import com.kunzisoft.keepass.hardware.HardwareKeyActivity
|
|
||||||
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
||||||
import com.kunzisoft.keepass.model.ProgressMessage
|
import com.kunzisoft.keepass.model.ProgressMessage
|
||||||
import com.kunzisoft.keepass.model.SnapFileDatabaseInfo
|
import com.kunzisoft.keepass.model.SnapFileDatabaseInfo
|
||||||
@@ -188,20 +186,6 @@ class DatabaseTaskProvider(private var context: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var requestChallengeListener = object: DatabaseTaskNotificationService.RequestChallengeListener {
|
|
||||||
override fun onChallengeResponseRequested(
|
|
||||||
hardwareKey: HardwareKey,
|
|
||||||
seed: ByteArray?
|
|
||||||
) {
|
|
||||||
HardwareKeyActivity
|
|
||||||
.launchHardwareKeyActivity(
|
|
||||||
context,
|
|
||||||
hardwareKey,
|
|
||||||
seed
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startDialog(progressMessage: ProgressMessage) {
|
private fun startDialog(progressMessage: ProgressMessage) {
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
activity.lifecycleScope.launch {
|
activity.lifecycleScope.launch {
|
||||||
@@ -259,14 +243,12 @@ class DatabaseTaskProvider(private var context: Context) {
|
|||||||
service?.addDatabaseListener(databaseListener)
|
service?.addDatabaseListener(databaseListener)
|
||||||
service?.addDatabaseFileInfoListener(databaseInfoListener)
|
service?.addDatabaseFileInfoListener(databaseInfoListener)
|
||||||
service?.addActionTaskListener(actionTaskListener)
|
service?.addActionTaskListener(actionTaskListener)
|
||||||
service?.setRequestChallengeListener(requestChallengeListener)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeServiceListeners(service: DatabaseTaskNotificationService.ActionTaskBinder?) {
|
private fun removeServiceListeners(service: DatabaseTaskNotificationService.ActionTaskBinder?) {
|
||||||
service?.removeActionTaskListener(actionTaskListener)
|
service?.removeActionTaskListener(actionTaskListener)
|
||||||
service?.removeDatabaseFileInfoListener(databaseInfoListener)
|
service?.removeDatabaseFileInfoListener(databaseInfoListener)
|
||||||
service?.removeDatabaseListener(databaseListener)
|
service?.removeDatabaseListener(databaseListener)
|
||||||
service?.removeRequestChallengeListener()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindService() {
|
private fun bindService() {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.kunzisoft.keepass.hardware
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.activity.result.ActivityResult
|
import androidx.activity.result.ActivityResult
|
||||||
import androidx.activity.result.ActivityResultCallback
|
import androidx.activity.result.ActivityResultCallback
|
||||||
@@ -96,7 +97,7 @@ class HardwareKeyActivity: DatabaseActivity(){
|
|||||||
seed: ByteArray?
|
seed: ByteArray?
|
||||||
) {
|
) {
|
||||||
context.startActivity(Intent(context, HardwareKeyActivity::class.java).apply {
|
context.startActivity(Intent(context, HardwareKeyActivity::class.java).apply {
|
||||||
//flags = FLAG_ACTIVITY_NEW_TASK
|
flags = FLAG_ACTIVITY_NEW_TASK
|
||||||
putExtra(DATA_HARDWARE_KEY, hardwareKey.value)
|
putExtra(DATA_HARDWARE_KEY, hardwareKey.value)
|
||||||
putExtra(DATA_SEED, seed)
|
putExtra(DATA_SEED, seed)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import com.kunzisoft.keepass.database.element.node.Node
|
|||||||
import com.kunzisoft.keepass.database.element.node.NodeId
|
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||||
import com.kunzisoft.keepass.database.element.node.Type
|
import com.kunzisoft.keepass.database.element.node.Type
|
||||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||||
|
import com.kunzisoft.keepass.hardware.HardwareKeyActivity
|
||||||
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
||||||
import com.kunzisoft.keepass.model.ProgressMessage
|
import com.kunzisoft.keepass.model.ProgressMessage
|
||||||
import com.kunzisoft.keepass.model.SnapFileDatabaseInfo
|
import com.kunzisoft.keepass.model.SnapFileDatabaseInfo
|
||||||
@@ -75,8 +76,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
private var mDatabaseInfoListeners = mutableListOf<DatabaseInfoListener>()
|
private var mDatabaseInfoListeners = mutableListOf<DatabaseInfoListener>()
|
||||||
private var mActionTaskBinder = ActionTaskBinder()
|
private var mActionTaskBinder = ActionTaskBinder()
|
||||||
private var mActionTaskListeners = mutableListOf<ActionTaskListener>()
|
private var mActionTaskListeners = mutableListOf<ActionTaskListener>()
|
||||||
// Channel to connect asynchronously a listener or a response
|
// Channel to connect asynchronously a response
|
||||||
private var mRequestChallengeListenerChannel: Channel<RequestChallengeListener>? = null
|
|
||||||
private var mResponseChallengeChannel: Channel<ByteArray?>? = null
|
private var mResponseChallengeChannel: Channel<ByteArray?>? = null
|
||||||
|
|
||||||
private var mActionRunning = false
|
private var mActionRunning = false
|
||||||
@@ -123,30 +123,6 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
fun removeActionTaskListener(actionTaskListener: ActionTaskListener) {
|
fun removeActionTaskListener(actionTaskListener: ActionTaskListener) {
|
||||||
mActionTaskListeners.remove(actionTaskListener)
|
mActionTaskListeners.remove(actionTaskListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
fun setRequestChallengeListener(requestChallengeListener: RequestChallengeListener) {
|
|
||||||
mainScope.launch {
|
|
||||||
val requestChannel = mRequestChallengeListenerChannel
|
|
||||||
if (requestChannel == null || requestChannel.isEmpty) {
|
|
||||||
initializeChallengeResponse()
|
|
||||||
mRequestChallengeListenerChannel?.send(requestChallengeListener)
|
|
||||||
} else {
|
|
||||||
cancelChallengeResponse(R.string.error_challenge_already_requested)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removeRequestChallengeListener() {
|
|
||||||
mainScope.launch {
|
|
||||||
try {
|
|
||||||
mRequestChallengeListenerChannel?.cancel()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.w(TAG, "Request challenge listener cannot be closed.", e)
|
|
||||||
}
|
|
||||||
mRequestChallengeListenerChannel = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DatabaseListener {
|
interface DatabaseListener {
|
||||||
@@ -249,32 +225,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initializeChallengeResponse() {
|
|
||||||
// Init the channels
|
|
||||||
if (mRequestChallengeListenerChannel == null) {
|
|
||||||
mRequestChallengeListenerChannel = Channel(0)
|
|
||||||
}
|
|
||||||
if (mResponseChallengeChannel == null) {
|
|
||||||
mResponseChallengeChannel = Channel(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun closeChallengeResponse() {
|
|
||||||
mRequestChallengeListenerChannel?.close()
|
|
||||||
mResponseChallengeChannel?.close()
|
|
||||||
mRequestChallengeListenerChannel = null
|
|
||||||
mResponseChallengeChannel = null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun cancelChallengeResponse(@StringRes error: Int) {
|
|
||||||
mRequestChallengeListenerChannel?.cancel(CancellationException(getString(error)))
|
|
||||||
mRequestChallengeListenerChannel = null
|
|
||||||
mResponseChallengeChannel?.cancel(CancellationException(getString(error)))
|
|
||||||
mResponseChallengeChannel = null
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
private fun respondToChallenge(response: ByteArray) {
|
private fun sendResponseToChallenge(response: ByteArray) {
|
||||||
mainScope.launch {
|
mainScope.launch {
|
||||||
val responseChannel = mResponseChallengeChannel
|
val responseChannel = mResponseChallengeChannel
|
||||||
if (responseChannel == null || responseChannel.isEmpty) {
|
if (responseChannel == null || responseChannel.isEmpty) {
|
||||||
@@ -289,6 +241,23 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun initializeChallengeResponse() {
|
||||||
|
// Init the channels
|
||||||
|
if (mResponseChallengeChannel == null) {
|
||||||
|
mResponseChallengeChannel = Channel(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun closeChallengeResponse() {
|
||||||
|
mResponseChallengeChannel?.close()
|
||||||
|
mResponseChallengeChannel = null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun cancelChallengeResponse(@StringRes error: Int) {
|
||||||
|
mResponseChallengeChannel?.cancel(CancellationException(getString(error)))
|
||||||
|
mResponseChallengeChannel = null
|
||||||
|
}
|
||||||
|
|
||||||
override fun onBind(intent: Intent): IBinder? {
|
override fun onBind(intent: Intent): IBinder? {
|
||||||
super.onBind(intent)
|
super.onBind(intent)
|
||||||
return mActionTaskBinder
|
return mActionTaskBinder
|
||||||
@@ -326,12 +295,6 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
stopSelf()
|
stopSelf()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intentAction == ACTION_CHALLENGE_RESPONDED) {
|
|
||||||
intent.getByteArrayExtra(DATA_BYTES)?.let {
|
|
||||||
respondToChallenge(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val actionRunnable: ActionRunnable? = when (intentAction) {
|
val actionRunnable: ActionRunnable? = when (intentAction) {
|
||||||
ACTION_DATABASE_CREATE_TASK -> buildDatabaseCreateActionTask(intent, database)
|
ACTION_DATABASE_CREATE_TASK -> buildDatabaseCreateActionTask(intent, database)
|
||||||
ACTION_DATABASE_LOAD_TASK -> buildDatabaseLoadActionTask(intent, database)
|
ACTION_DATABASE_LOAD_TASK -> buildDatabaseLoadActionTask(intent, database)
|
||||||
@@ -362,7 +325,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK,
|
ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK,
|
||||||
ACTION_DATABASE_UPDATE_PARALLELISM_TASK,
|
ACTION_DATABASE_UPDATE_PARALLELISM_TASK,
|
||||||
ACTION_DATABASE_UPDATE_ITERATIONS_TASK -> buildDatabaseUpdateElementActionTask(intent, database)
|
ACTION_DATABASE_UPDATE_ITERATIONS_TASK -> buildDatabaseUpdateElementActionTask(intent, database)
|
||||||
ACTION_DATABASE_SAVE -> buildDatabaseSave(intent, database)
|
ACTION_DATABASE_SAVE -> buildDatabaseSaveActionTask(intent, database)
|
||||||
|
ACTION_CHALLENGE_RESPONDED -> buildChallengeRespondedActionTask(intent)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,7 +350,6 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
database, mProgressMessage
|
database, mProgressMessage
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
actionRunnable
|
actionRunnable
|
||||||
@@ -659,8 +622,12 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
}
|
}
|
||||||
// Send the request
|
// Send the request
|
||||||
notifyProgressMessage()
|
notifyProgressMessage()
|
||||||
val challengeResponseRequestListener = mRequestChallengeListenerChannel?.receive()
|
HardwareKeyActivity
|
||||||
challengeResponseRequestListener?.onChallengeResponseRequested(hardwareKey, seed)
|
.launchHardwareKeyActivity(
|
||||||
|
this@DatabaseTaskNotificationService,
|
||||||
|
hardwareKey,
|
||||||
|
seed
|
||||||
|
)
|
||||||
// Wait the response
|
// Wait the response
|
||||||
mProgressMessage.apply {
|
mProgressMessage.apply {
|
||||||
messageId = R.string.waiting_challenge_response
|
messageId = R.string.waiting_challenge_response
|
||||||
@@ -1108,7 +1075,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
/**
|
/**
|
||||||
* Save database without parameter
|
* Save database without parameter
|
||||||
*/
|
*/
|
||||||
private fun buildDatabaseSave(intent: Intent, database: Database): ActionRunnable? {
|
private fun buildDatabaseSaveActionTask(intent: Intent, database: Database): ActionRunnable? {
|
||||||
return if (intent.hasExtra(SAVE_DATABASE_KEY)) {
|
return if (intent.hasExtra(SAVE_DATABASE_KEY)) {
|
||||||
|
|
||||||
var databaseCopyUri: Uri? = null
|
var databaseCopyUri: Uri? = null
|
||||||
@@ -1129,6 +1096,24 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun buildChallengeRespondedActionTask(intent: Intent): ActionRunnable? {
|
||||||
|
return if (intent.hasExtra(DATA_BYTES)) {
|
||||||
|
object : ActionRunnable() {
|
||||||
|
override fun onStartRun() {}
|
||||||
|
override fun onActionRun() {
|
||||||
|
mainScope.launch {
|
||||||
|
intent.getByteArrayExtra(DATA_BYTES)?.let { response ->
|
||||||
|
sendResponseToChallenge(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
override fun onFinishRun() {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val TAG = DatabaseTaskNotificationService::class.java.name
|
private val TAG = DatabaseTaskNotificationService::class.java.name
|
||||||
|
|||||||
Reference in New Issue
Block a user