DroidFS/app/src/main/java/sushi/hardcore/droidfs/ChangePasswordActivity.kt

189 lines
8.2 KiB
Kotlin
Raw Normal View History

2020-07-17 16:35:39 +02:00
package sushi.hardcore.droidfs
2022-03-05 12:51:02 +01:00
import android.annotation.SuppressLint
2020-07-17 16:35:39 +02:00
import android.os.Build
import android.os.Bundle
2022-04-17 17:38:49 +02:00
import android.text.InputType
2022-03-05 12:51:02 +01:00
import android.view.MenuItem
import android.view.View
2020-07-17 16:35:39 +02:00
import android.widget.Toast
2022-04-20 15:17:33 +02:00
import androidx.lifecycle.lifecycleScope
2021-06-11 20:23:54 +02:00
import sushi.hardcore.droidfs.databinding.ActivityChangePasswordBinding
import sushi.hardcore.droidfs.filesystems.CryfsVolume
import sushi.hardcore.droidfs.filesystems.EncryptedVolume
2022-06-18 21:13:16 +02:00
import sushi.hardcore.droidfs.filesystems.GocryptfsVolume
import sushi.hardcore.droidfs.util.ObjRef
import sushi.hardcore.droidfs.util.WidgetUtil
2021-11-09 11:12:09 +01:00
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
2020-07-17 16:35:39 +02:00
import java.util.*
2022-03-05 12:51:02 +01:00
class ChangePasswordActivity: BaseActivity() {
2021-06-11 20:23:54 +02:00
private lateinit var binding: ActivityChangePasswordBinding
2022-06-18 21:13:16 +02:00
private lateinit var volume: SavedVolume
2022-03-05 12:51:02 +01:00
private lateinit var volumeDatabase: VolumeDatabase
private var fingerprintProtector: FingerprintProtector? = null
private var usfFingerprint: Boolean = false
2021-06-11 20:23:54 +02:00
2020-07-17 16:35:39 +02:00
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
2022-03-05 12:51:02 +01:00
volume = intent.getParcelableExtra("volume")!!
2021-06-11 20:23:54 +02:00
binding = ActivityChangePasswordBinding.inflate(layoutInflater)
setContentView(binding.root)
2022-03-05 12:51:02 +01:00
title = getString(R.string.change_password)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
binding.textVolumeName.text = volume.name
volumeDatabase = VolumeDatabase(this)
usfFingerprint = sharedPrefs.getBoolean("usf_fingerprint", false)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
fingerprintProtector = FingerprintProtector.new(this, themeValue, volumeDatabase)
if (fingerprintProtector != null && volume.encryptedHash != null) {
binding.textCurrentPasswordLabel.visibility = View.GONE
binding.editCurrentPassword.visibility = View.GONE
2020-07-17 16:35:39 +02:00
}
}
2022-03-05 12:51:02 +01:00
if (!usfFingerprint || fingerprintProtector == null) {
binding.checkboxSavePassword.visibility = View.GONE
}
2022-04-17 17:38:49 +02:00
if (sharedPrefs.getBoolean(ConstValues.PIN_PASSWORDS_KEY, false)) {
arrayOf(binding.editCurrentPassword, binding.editNewPassword, binding.editPasswordConfirm).forEach {
it.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_VARIATION_PASSWORD
}
}
2022-03-05 12:51:02 +01:00
binding.editPasswordConfirm.setOnEditorActionListener { _, _, _ ->
changeVolumePassword()
2020-07-17 16:35:39 +02:00
true
}
2022-03-05 12:51:02 +01:00
binding.button.setOnClickListener { changeVolumePassword() }
2020-07-17 16:35:39 +02:00
}
2022-03-05 12:51:02 +01:00
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return if (item.itemId == android.R.id.home) {
finish()
true
} else super.onOptionsItemSelected(item)
}
private fun showCurrentPasswordInput() {
binding.textCurrentPasswordLabel.visibility = View.VISIBLE
binding.editCurrentPassword.visibility = View.VISIBLE
2020-07-17 16:35:39 +02:00
}
2022-03-05 12:51:02 +01:00
private fun changeVolumePassword() {
val newPassword = WidgetUtil.encodeEditTextContent(binding.editNewPassword)
val newPasswordConfirm = WidgetUtil.encodeEditTextContent(binding.editPasswordConfirm)
2022-03-05 12:51:02 +01:00
@SuppressLint("NewApi")
2020-08-25 14:10:46 +02:00
if (!newPassword.contentEquals(newPasswordConfirm)) {
Toast.makeText(this, R.string.passwords_mismatch, Toast.LENGTH_SHORT).show()
Arrays.fill(newPassword, 0)
2020-08-25 14:10:46 +02:00
} else {
2022-03-05 12:51:02 +01:00
var changeWithCurrentPassword = true
volume.encryptedHash?.let { encryptedHash ->
volume.iv?.let { iv ->
fingerprintProtector?.let {
changeWithCurrentPassword = false
it.listener = object : FingerprintProtector.Listener {
override fun onHashStorageReset() {
showCurrentPasswordInput()
volume.encryptedHash = null
volume.iv = null
}
2022-03-05 12:51:02 +01:00
override fun onPasswordHashDecrypted(hash: ByteArray) {
changeVolumePassword(newPassword, hash)
}
override fun onPasswordHashSaved() {}
override fun onFailed(pending: Boolean) {
Arrays.fill(newPassword, 0)
2020-07-28 22:25:10 +02:00
}
2020-07-17 16:35:39 +02:00
}
2022-03-05 12:51:02 +01:00
it.loadPasswordHash(volume.name, encryptedHash, iv)
2020-07-28 22:25:10 +02:00
}
2022-03-05 12:51:02 +01:00
}
}
if (changeWithCurrentPassword) {
changeVolumePassword(newPassword)
}
}
Arrays.fill(newPasswordConfirm, 0)
2022-03-05 12:51:02 +01:00
}
private fun changeVolumePassword(newPassword: ByteArray, givenHash: ByteArray? = null) {
val returnedHash: ObjRef<ByteArray?>? = if (binding.checkboxSavePassword.isChecked) {
ObjRef(null)
} else {
null
2022-04-20 15:17:33 +02:00
}
val currentPassword = if (givenHash == null) {
WidgetUtil.encodeEditTextContent(binding.editCurrentPassword)
} else {
null
2022-04-20 15:17:33 +02:00
}
object : LoadingTask<Boolean>(this, themeValue, R.string.loading_msg_change_password) {
override suspend fun doTask(): Boolean {
val success = if (volume.type == EncryptedVolume.GOCRYPTFS_VOLUME_TYPE) {
GocryptfsVolume.changePassword(
volume.getFullPath(filesDir.path),
currentPassword,
givenHash,
newPassword,
returnedHash?.apply { value = ByteArray(GocryptfsVolume.KeyLen) }?.value
)
} else {
CryfsVolume.changePassword(
volume.getFullPath(filesDir.path),
filesDir.path,
currentPassword,
givenHash,
newPassword,
returnedHash
)
}
2022-04-20 15:17:33 +02:00
if (success) {
2022-03-05 12:51:02 +01:00
if (volumeDatabase.isHashSaved(volume.name)) {
volumeDatabase.removeHash(volume)
}
2020-08-25 14:10:46 +02:00
}
2022-03-05 12:51:02 +01:00
if (currentPassword != null)
Arrays.fill(currentPassword, 0)
Arrays.fill(newPassword, 0)
2022-03-05 12:51:02 +01:00
if (givenHash != null)
Arrays.fill(givenHash, 0)
2022-04-20 15:17:33 +02:00
return success
}
}.startTask(lifecycleScope) { success ->
if (success) {
@SuppressLint("NewApi") // if fingerprintProtector is null checkboxSavePassword is hidden
if (binding.checkboxSavePassword.isChecked && returnedHash != null) {
fingerprintProtector!!.let {
it.listener = object : FingerprintProtector.Listener {
override fun onHashStorageReset() {
// retry
it.savePasswordHash(volume, returnedHash.value!!)
2022-04-20 15:17:33 +02:00
}
override fun onPasswordHashDecrypted(hash: ByteArray) {}
override fun onPasswordHashSaved() {
Arrays.fill(returnedHash.value!!, 0)
2022-04-20 15:17:33 +02:00
finish()
}
override fun onFailed(pending: Boolean) {
if (!pending) {
Arrays.fill(returnedHash.value!!, 0)
2022-04-20 15:17:33 +02:00
finish()
}
}
}
it.savePasswordHash(volume, returnedHash.value!!)
2022-04-20 15:17:33 +02:00
}
} else {
finish()
}
} else {
CustomAlertDialogBuilder(this, themeValue)
.setTitle(R.string.error)
.setMessage(R.string.change_password_failed)
.setPositiveButton(R.string.ok, null)
.show()
2020-07-17 16:35:39 +02:00
}
2020-07-28 22:25:10 +02:00
}
2020-07-17 16:35:39 +02:00
}
}