Skip to content
This repository was archived by the owner on Oct 15, 2024. It is now read-only.

Commit 6667586

Browse files
authored
clear passphrase cache, fix application crash on auto screen-off (#3108)
clear passphrase chache on screen-off
1 parent 2820f0e commit 6667586

File tree

3 files changed

+32
-22
lines changed

3 files changed

+32
-22
lines changed

app/src/main/java/app/passwordstore/Application.kt

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ import io.sentry.Sentry
3030
import io.sentry.protocol.User
3131
import java.util.concurrent.Executors
3232
import javax.inject.Inject
33-
import kotlinx.coroutines.DelicateCoroutinesApi
34-
import kotlinx.coroutines.GlobalScope
35-
import kotlinx.coroutines.launch
36-
import kotlinx.coroutines.withContext
3733
import logcat.AndroidLogcatLogger
3834
import logcat.LogPriority.DEBUG
3935
import logcat.LogPriority.VERBOSE
@@ -76,27 +72,18 @@ class Application : android.app.Application(), SharedPreferences.OnSharedPrefere
7672
}
7773
scope.user = user
7874
}
79-
setupPassphraseCacheClearAction()
75+
setupScreenOffHandler()
8076
}
8177

82-
@OptIn(DelicateCoroutinesApi::class)
83-
private fun setupPassphraseCacheClearAction() {
84-
if (prefs.getBoolean(PreferenceKeys.CLEAR_PASSPHRASE_CACHE, false)) {
85-
val screenOffReceiver: BroadcastReceiver =
86-
object : BroadcastReceiver() {
87-
override fun onReceive(context: Context, intent: Intent) {
88-
if (intent.action == Intent.ACTION_SCREEN_OFF) {
89-
GlobalScope.launch {
90-
withContext(dispatcherProvider.main()) {
91-
passphraseCache.clearAllCachedPassphrases(context)
92-
}
93-
}
94-
}
95-
}
78+
private fun setupScreenOffHandler() {
79+
val screenOffReceiver: BroadcastReceiver =
80+
object : BroadcastReceiver() {
81+
override fun onReceive(context: Context, intent: Intent) {
82+
if (intent.action == Intent.ACTION_SCREEN_OFF) screenWasOff = true
9683
}
97-
val filter = IntentFilter(Intent.ACTION_SCREEN_OFF)
98-
registerReceiver(screenOffReceiver, filter)
99-
}
84+
}
85+
val filter = IntentFilter(Intent.ACTION_SCREEN_OFF)
86+
registerReceiver(screenOffReceiver, filter)
10087
}
10188

10289
override fun onTerminate() {
@@ -159,5 +146,6 @@ class Application : android.app.Application(), SharedPreferences.OnSharedPrefere
159146
companion object {
160147

161148
lateinit var instance: Application
149+
var screenWasOff: Boolean = true
162150
}
163151
}

app/src/main/java/app/passwordstore/ui/crypto/DecryptActivity.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import android.view.Menu
1111
import android.view.MenuItem
1212
import androidx.fragment.app.setFragmentResultListener
1313
import androidx.lifecycle.lifecycleScope
14+
import app.passwordstore.Application.Companion.screenWasOff
1415
import app.passwordstore.R
1516
import app.passwordstore.crypto.PGPIdentifier
1617
import app.passwordstore.crypto.errors.CryptoHandlerException
@@ -167,6 +168,11 @@ class DecryptActivity : BasePGPActivity() {
167168
askPassphrase(isError, gpgIdentifiers, authResult)
168169
//
169170
is BiometricResult.Success -> {
171+
// clear passphrase cache on first use after application startup or if screen was off
172+
if (screenWasOff && settings.getBoolean(PreferenceKeys.CLEAR_PASSPHRASE_CACHE, false)) {
173+
passphraseCache.clearAllCachedPassphrases(this@DecryptActivity)
174+
screenWasOff = false
175+
}
170176
val cachedPassphrase =
171177
passphraseCache.retrieveCachedPassphrase(this@DecryptActivity, gpgIdentifiers.first())
172178
if (cachedPassphrase != null) {

app/src/main/java/app/passwordstore/ui/settings/PGPSettings.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,22 @@ class PGPSettings(
6565
titleRes = R.string.pref_passphrase_cache_auto_clear_title
6666
summaryRes = R.string.pref_passphrase_cache_auto_clear_summary
6767
defaultValue = false
68+
/* clear cache once when unchecking; this is to prevent a malicious user
69+
* from bypassing cache clearing via the settings */
70+
onCheckedChange { checked ->
71+
if (!checked && BiometricAuthenticator.canAuthenticate(activity)) {
72+
BiometricAuthenticator.authenticate(
73+
activity,
74+
R.string.pref_passphrase_cache_authenticate_clear,
75+
) {
76+
if (it is BiometricAuthenticator.Result.Success)
77+
activity.lifecycleScope.launch {
78+
passphraseCache.clearAllCachedPassphrases(activity)
79+
}
80+
}
81+
}
82+
true
83+
}
6884
}
6985
}
7086
}

0 commit comments

Comments
 (0)