clear passphrase cache, fix application crash on auto screen-off (#3108)
clear passphrase chache on screen-off
This commit is contained in:
parent
2820f0ed63
commit
66675864ae
3 changed files with 32 additions and 22 deletions
|
@ -30,10 +30,6 @@ import io.sentry.Sentry
|
||||||
import io.sentry.protocol.User
|
import io.sentry.protocol.User
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import logcat.AndroidLogcatLogger
|
import logcat.AndroidLogcatLogger
|
||||||
import logcat.LogPriority.DEBUG
|
import logcat.LogPriority.DEBUG
|
||||||
import logcat.LogPriority.VERBOSE
|
import logcat.LogPriority.VERBOSE
|
||||||
|
@ -76,27 +72,18 @@ class Application : android.app.Application(), SharedPreferences.OnSharedPrefere
|
||||||
}
|
}
|
||||||
scope.user = user
|
scope.user = user
|
||||||
}
|
}
|
||||||
setupPassphraseCacheClearAction()
|
setupScreenOffHandler()
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(DelicateCoroutinesApi::class)
|
private fun setupScreenOffHandler() {
|
||||||
private fun setupPassphraseCacheClearAction() {
|
val screenOffReceiver: BroadcastReceiver =
|
||||||
if (prefs.getBoolean(PreferenceKeys.CLEAR_PASSPHRASE_CACHE, false)) {
|
object : BroadcastReceiver() {
|
||||||
val screenOffReceiver: BroadcastReceiver =
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
object : BroadcastReceiver() {
|
if (intent.action == Intent.ACTION_SCREEN_OFF) screenWasOff = true
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
|
||||||
if (intent.action == Intent.ACTION_SCREEN_OFF) {
|
|
||||||
GlobalScope.launch {
|
|
||||||
withContext(dispatcherProvider.main()) {
|
|
||||||
passphraseCache.clearAllCachedPassphrases(context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
val filter = IntentFilter(Intent.ACTION_SCREEN_OFF)
|
}
|
||||||
registerReceiver(screenOffReceiver, filter)
|
val filter = IntentFilter(Intent.ACTION_SCREEN_OFF)
|
||||||
}
|
registerReceiver(screenOffReceiver, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTerminate() {
|
override fun onTerminate() {
|
||||||
|
@ -159,5 +146,6 @@ class Application : android.app.Application(), SharedPreferences.OnSharedPrefere
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
lateinit var instance: Application
|
lateinit var instance: Application
|
||||||
|
var screenWasOff: Boolean = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.fragment.app.setFragmentResultListener
|
import androidx.fragment.app.setFragmentResultListener
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import app.passwordstore.Application.Companion.screenWasOff
|
||||||
import app.passwordstore.R
|
import app.passwordstore.R
|
||||||
import app.passwordstore.crypto.PGPIdentifier
|
import app.passwordstore.crypto.PGPIdentifier
|
||||||
import app.passwordstore.crypto.errors.CryptoHandlerException
|
import app.passwordstore.crypto.errors.CryptoHandlerException
|
||||||
|
@ -167,6 +168,11 @@ class DecryptActivity : BasePGPActivity() {
|
||||||
askPassphrase(isError, gpgIdentifiers, authResult)
|
askPassphrase(isError, gpgIdentifiers, authResult)
|
||||||
//
|
//
|
||||||
is BiometricResult.Success -> {
|
is BiometricResult.Success -> {
|
||||||
|
// clear passphrase cache on first use after application startup or if screen was off
|
||||||
|
if (screenWasOff && settings.getBoolean(PreferenceKeys.CLEAR_PASSPHRASE_CACHE, false)) {
|
||||||
|
passphraseCache.clearAllCachedPassphrases(this@DecryptActivity)
|
||||||
|
screenWasOff = false
|
||||||
|
}
|
||||||
val cachedPassphrase =
|
val cachedPassphrase =
|
||||||
passphraseCache.retrieveCachedPassphrase(this@DecryptActivity, gpgIdentifiers.first())
|
passphraseCache.retrieveCachedPassphrase(this@DecryptActivity, gpgIdentifiers.first())
|
||||||
if (cachedPassphrase != null) {
|
if (cachedPassphrase != null) {
|
||||||
|
|
|
@ -65,6 +65,22 @@ class PGPSettings(
|
||||||
titleRes = R.string.pref_passphrase_cache_auto_clear_title
|
titleRes = R.string.pref_passphrase_cache_auto_clear_title
|
||||||
summaryRes = R.string.pref_passphrase_cache_auto_clear_summary
|
summaryRes = R.string.pref_passphrase_cache_auto_clear_summary
|
||||||
defaultValue = false
|
defaultValue = false
|
||||||
|
/* clear cache once when unchecking; this is to prevent a malicious user
|
||||||
|
* from bypassing cache clearing via the settings */
|
||||||
|
onCheckedChange { checked ->
|
||||||
|
if (!checked && BiometricAuthenticator.canAuthenticate(activity)) {
|
||||||
|
BiometricAuthenticator.authenticate(
|
||||||
|
activity,
|
||||||
|
R.string.pref_passphrase_cache_authenticate_clear,
|
||||||
|
) {
|
||||||
|
if (it is BiometricAuthenticator.Result.Success)
|
||||||
|
activity.lifecycleScope.launch {
|
||||||
|
passphraseCache.clearAllCachedPassphrases(activity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue