Fix obtaining pgp identifiers to decrypting file. (#3009)

This commit is contained in:
Oleh Kopeykin 2024-04-17 21:49:31 +03:00 committed by GitHub
parent 882aba8228
commit 86466819a9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 40 additions and 17 deletions

View file

@ -14,8 +14,10 @@ import android.view.autofill.AutofillManager
import androidx.fragment.app.setFragmentResultListener import androidx.fragment.app.setFragmentResultListener
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import app.passwordstore.R import app.passwordstore.R
import app.passwordstore.crypto.PGPIdentifier
import app.passwordstore.data.crypto.PGPPassphraseCache import app.passwordstore.data.crypto.PGPPassphraseCache
import app.passwordstore.data.passfile.PasswordEntry import app.passwordstore.data.passfile.PasswordEntry
import app.passwordstore.data.repo.PasswordRepository
import app.passwordstore.ui.crypto.BasePGPActivity import app.passwordstore.ui.crypto.BasePGPActivity
import app.passwordstore.ui.crypto.PasswordDialog import app.passwordstore.ui.crypto.PasswordDialog
import app.passwordstore.util.auth.BiometricAuthenticator import app.passwordstore.util.auth.BiometricAuthenticator
@ -92,7 +94,10 @@ class AutofillDecryptActivity : BasePGPActivity() {
action: AutofillAction, action: AutofillAction,
authResult: Result, authResult: Result,
) { ) {
val gpgIdentifiers = getPGPIdentifiers("") ?: return val gpgIdentifiers =
getPGPIdentifiers(
getParentPath(filePath, PasswordRepository.getRepositoryDirectory().toString())
) ?: return
lifecycleScope.launch(dispatcherProvider.main()) { lifecycleScope.launch(dispatcherProvider.main()) {
when (authResult) { when (authResult) {
// Internally handled by the prompt dialog // Internally handled by the prompt dialog
@ -101,7 +106,8 @@ class AutofillDecryptActivity : BasePGPActivity() {
is Result.CanceledBySystem, is Result.CanceledBySystem,
is Result.CanceledByUser, is Result.CanceledByUser,
is Result.Failure, is Result.Failure,
is Result.HardwareUnavailableOrDisabled -> askPassphrase(filePath, clientState, action) is Result.HardwareUnavailableOrDisabled ->
askPassphrase(filePath, gpgIdentifiers, clientState, action)
// //
is Result.Success -> { is Result.Success -> {
val cachedPassphrase = val cachedPassphrase =
@ -110,23 +116,34 @@ class AutofillDecryptActivity : BasePGPActivity() {
gpgIdentifiers.first() gpgIdentifiers.first()
) )
if (cachedPassphrase != null) { if (cachedPassphrase != null) {
decryptWithPassphrase(File(filePath), clientState, action, cachedPassphrase) decryptWithPassphrase(
File(filePath),
gpgIdentifiers,
clientState,
action,
cachedPassphrase
)
} else { } else {
askPassphrase(filePath, clientState, action) askPassphrase(filePath, gpgIdentifiers, clientState, action)
} }
} }
} }
} }
} }
private fun askPassphrase(filePath: String, clientState: Bundle, action: AutofillAction) { private fun askPassphrase(
filePath: String,
identifiers: List<PGPIdentifier>,
clientState: Bundle,
action: AutofillAction,
) {
val dialog = PasswordDialog() val dialog = PasswordDialog()
dialog.show(supportFragmentManager, "PASSWORD_DIALOG") dialog.show(supportFragmentManager, "PASSWORD_DIALOG")
dialog.setFragmentResultListener(PasswordDialog.PASSWORD_RESULT_KEY) { key, bundle -> dialog.setFragmentResultListener(PasswordDialog.PASSWORD_RESULT_KEY) { key, bundle ->
if (key == PasswordDialog.PASSWORD_RESULT_KEY) { if (key == PasswordDialog.PASSWORD_RESULT_KEY) {
val value = bundle.getString(PasswordDialog.PASSWORD_RESULT_KEY)!! val value = bundle.getString(PasswordDialog.PASSWORD_RESULT_KEY)!!
lifecycleScope.launch(dispatcherProvider.main()) { lifecycleScope.launch(dispatcherProvider.main()) {
decryptWithPassphrase(File(filePath), clientState, action, value) decryptWithPassphrase(File(filePath), identifiers, clientState, action, value)
} }
} }
} }
@ -134,11 +151,12 @@ class AutofillDecryptActivity : BasePGPActivity() {
private suspend fun decryptWithPassphrase( private suspend fun decryptWithPassphrase(
filePath: File, filePath: File,
identifiers: List<PGPIdentifier>,
clientState: Bundle, clientState: Bundle,
action: AutofillAction, action: AutofillAction,
password: String, password: String,
) { ) {
val credentials = decryptCredential(filePath, password) val credentials = decryptCredential(filePath, password, identifiers)
if (credentials == null) { if (credentials == null) {
setResult(RESULT_CANCELED) setResult(RESULT_CANCELED)
} else { } else {
@ -159,8 +177,11 @@ class AutofillDecryptActivity : BasePGPActivity() {
withContext(dispatcherProvider.main()) { finish() } withContext(dispatcherProvider.main()) { finish() }
} }
private suspend fun decryptCredential(file: File, password: String): Credentials? { private suspend fun decryptCredential(
val gpgIdentifiers = getPGPIdentifiers("") ?: return null file: File,
password: String,
identifiers: List<PGPIdentifier>,
): Credentials? {
runCatching { file.readBytes().inputStream() } runCatching { file.readBytes().inputStream() }
.onFailure { e -> .onFailure { e ->
logcat(ERROR) { e.asLog("File to decrypt not found") } logcat(ERROR) { e.asLog("File to decrypt not found") }
@ -172,7 +193,7 @@ class AutofillDecryptActivity : BasePGPActivity() {
val outputStream = ByteArrayOutputStream() val outputStream = ByteArrayOutputStream()
repository.decrypt( repository.decrypt(
password, password,
gpgIdentifiers, identifiers,
encryptedInput, encryptedInput,
outputStream, outputStream,
) )
@ -185,7 +206,7 @@ class AutofillDecryptActivity : BasePGPActivity() {
} }
.onSuccess { result -> .onSuccess { result ->
return runCatching { return runCatching {
passphraseCache.cachePassphrase(this, gpgIdentifiers.first(), password) passphraseCache.cachePassphrase(this, identifiers.first(), password)
val entry = passwordEntryFactory.create(result.toByteArray()) val entry = passwordEntryFactory.create(result.toByteArray())
AutofillPreferences.credentialsFromStoreEntry(this, file, entry, directoryStructure) AutofillPreferences.credentialsFromStoreEntry(this, file, entry, directoryStructure)
} }

View file

@ -154,7 +154,7 @@ class DecryptActivity : BasePGPActivity() {
} }
private fun decrypt(isError: Boolean, authResult: BiometricResult) { private fun decrypt(isError: Boolean, authResult: BiometricResult) {
val gpgIdentifiers = getPGPIdentifiers("") ?: return val gpgIdentifiers = getPGPIdentifiers(relativeParentPath) ?: return
lifecycleScope.launch(dispatcherProvider.main()) { lifecycleScope.launch(dispatcherProvider.main()) {
when (authResult) { when (authResult) {
// Internally handled by the prompt dialog // Internally handled by the prompt dialog
@ -199,6 +199,7 @@ class DecryptActivity : BasePGPActivity() {
val passphrase = bundle.getString(PasswordDialog.PASSWORD_RESULT_KEY)!! val passphrase = bundle.getString(PasswordDialog.PASSWORD_RESULT_KEY)!!
lifecycleScope.launch(dispatcherProvider.main()) { lifecycleScope.launch(dispatcherProvider.main()) {
decryptWithPassphrase(passphrase, gpgIdentifiers, authResult) { decryptWithPassphrase(passphrase, gpgIdentifiers, authResult) {
if (authResult is BiometricResult.Success) {
passphraseCache.cachePassphrase( passphraseCache.cachePassphrase(
this@DecryptActivity, this@DecryptActivity,
gpgIdentifiers.first(), gpgIdentifiers.first(),
@ -209,6 +210,7 @@ class DecryptActivity : BasePGPActivity() {
} }
} }
} }
}
private suspend fun decryptWithPassphrase( private suspend fun decryptWithPassphrase(
passphrase: String, passphrase: String,