Skip to content
This repository was archived by the owner on Oct 15, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import android.os.AsyncTask
import com.github.ajalt.timberkt.e
import com.zeapo.pwdstore.PasswordStore
import com.zeapo.pwdstore.R
import com.zeapo.pwdstore.git.config.SshjSessionFactory
import net.schmizz.sshj.userauth.UserAuthException
import org.eclipse.jgit.api.CommitCommand
import org.eclipse.jgit.api.GitCommand
Expand Down Expand Up @@ -147,6 +148,7 @@ class GitAsyncTask(
if (refreshListOnEnd) {
(activity as? PasswordStore)?.resetPasswordList()
}
(SshSessionFactory.getInstance() as? SshjSessionFactory)?.clearCredentials()
SshSessionFactory.setInstance(null)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package com.zeapo.pwdstore.git.config
import android.util.Base64
import com.github.ajalt.timberkt.d
import com.github.ajalt.timberkt.w
import com.zeapo.pwdstore.utils.clear
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import net.schmizz.sshj.SSHClient
Expand All @@ -33,26 +34,56 @@ import kotlin.coroutines.Continuation
import kotlin.coroutines.suspendCoroutine

sealed class SshAuthData {
class Password(val passwordFinder: InteractivePasswordFinder) : SshAuthData()
class PublicKeyFile(val keyFile: File, val passphraseFinder: InteractivePasswordFinder) : SshAuthData()
class Password(val passwordFinder: InteractivePasswordFinder) : SshAuthData() {
override fun clearCredentials() {
passwordFinder.clearPassword()
}
}

class PublicKeyFile(val keyFile: File, val passphraseFinder: InteractivePasswordFinder) : SshAuthData() {
override fun clearCredentials() {
passphraseFinder.clearPassword()
}
}

abstract fun clearCredentials()
}

abstract class InteractivePasswordFinder : PasswordFinder {

abstract fun askForPassword(cont: Continuation<String?>, isRetry: Boolean)

private var isRetry = false
private var shouldRetry = true
private var lastPassword: CharArray? = null

abstract fun askForPassword(cont: Continuation<String?>, isRetry: Boolean)
fun resetForReuse() {
isRetry = false
shouldRetry = true
}

fun clearPassword() {
lastPassword?.clear()
lastPassword = null
}

final override fun reqPassword(resource: Resource<*>?): CharArray {
if (lastPassword != null && !isRetry) {
// This instance successfully authenticated in a previous authentication step and is
// now being reused for a new one. We try the previous password so that the user
// does not have to type it again.
isRetry = true
return lastPassword!!
}
clearPassword()
val password = runBlocking(Dispatchers.Main) {
suspendCoroutine<String?> { cont ->
askForPassword(cont, isRetry)
}
}
isRetry = true
return if (password != null) {
password.toCharArray()
password.toCharArray().also { lastPassword = it }
} else {
shouldRetry = false
CharArray(0)
Expand All @@ -67,6 +98,10 @@ class SshjSessionFactory(private val username: String, private val authData: Ssh
override fun getSession(uri: URIish, credentialsProvider: CredentialsProvider?, fs: FS?, tms: Int): RemoteSession {
return SshjSession(uri, username, authData, hostKeyFile).connect()
}

fun clearCredentials() {
authData.clearCredentials()
}
}

private fun makeTofuHostKeyVerifier(hostKeyFile: File): HostKeyVerifier {
Expand Down Expand Up @@ -105,9 +140,11 @@ private class SshjSession(private val uri: URIish, private val username: String,
when (authData) {
is SshAuthData.Password -> {
ssh.authPassword(username, authData.passwordFinder)
authData.passwordFinder.resetForReuse()
}
is SshAuthData.PublicKeyFile -> {
ssh.authPublickey(username, ssh.loadKeys(authData.keyFile.absolutePath, authData.passphraseFinder))
authData.passphraseFinder.resetForReuse()
}
}
return this
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ fun String.splitLines(): Array<String> {
return split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
}

fun CharArray.clear() {
forEachIndexed { i, _ ->
this[i] = 0.toChar()
}
}

fun Context.resolveAttribute(attr: Int): Int {
val typedValue = TypedValue()
this.theme.resolveAttribute(attr, typedValue, true)
Expand Down