mirror of
https://github.com/android-password-store/Android-Password-Store
synced 2025-08-30 05:48:09 +00:00
Revert "feat: put new SSH layer behind a feature flag"
This reverts commit fb8d74fc1f01c73a4afc3003978ac4ad86e7b890.
This commit is contained in:
parent
424f654be0
commit
4d5b32d98b
@ -15,6 +15,7 @@ import androidx.fragment.app.FragmentActivity
|
||||
import app.passwordstore.R
|
||||
import app.passwordstore.data.repo.PasswordRepository
|
||||
import app.passwordstore.injection.prefs.GitPreferences
|
||||
import app.passwordstore.ssh.SSHKeyManager
|
||||
import app.passwordstore.ui.git.config.GitConfigActivity
|
||||
import app.passwordstore.ui.git.config.GitServerConfigActivity
|
||||
import app.passwordstore.ui.proxy.ProxySelectorActivity
|
||||
@ -28,7 +29,6 @@ import app.passwordstore.util.extensions.snackbar
|
||||
import app.passwordstore.util.extensions.unsafeLazy
|
||||
import app.passwordstore.util.settings.GitSettings
|
||||
import app.passwordstore.util.settings.PreferenceKeys
|
||||
import app.passwordstore.util.ssh.SSHFacade
|
||||
import com.github.michaelbull.result.onFailure
|
||||
import com.github.michaelbull.result.runCatching
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
@ -44,11 +44,11 @@ import de.Maxr1998.modernpreferences.helpers.switch
|
||||
|
||||
class RepositorySettings(
|
||||
private val activity: FragmentActivity,
|
||||
private val sshFacade: SSHFacade,
|
||||
private val sshKeyManager: SSHKeyManager,
|
||||
) : SettingsProvider {
|
||||
private val generateSshKey =
|
||||
activity.registerForActivityResult(StartActivityForResult()) {
|
||||
showSshKeyPref?.visible = sshFacade.canShowPublicKey()
|
||||
showSshKeyPref?.visible = sshKeyManager.canShowPublicKey()
|
||||
}
|
||||
|
||||
private val hiltEntryPoint by unsafeLazy {
|
||||
@ -113,7 +113,7 @@ class RepositorySettings(
|
||||
showSshKeyPref =
|
||||
pref(PreferenceKeys.SSH_SEE_KEY) {
|
||||
titleRes = R.string.pref_ssh_see_key_title
|
||||
visible = PasswordRepository.isGitRepo() && sshFacade.canShowPublicKey()
|
||||
visible = PasswordRepository.isGitRepo() && sshKeyManager.canShowPublicKey()
|
||||
onClick {
|
||||
ShowSshKeyFragment().show(activity.supportFragmentManager, "public_key")
|
||||
true
|
||||
|
@ -11,8 +11,8 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.os.BundleCompat
|
||||
import app.passwordstore.R
|
||||
import app.passwordstore.databinding.ActivityPreferenceRecyclerviewBinding
|
||||
import app.passwordstore.ssh.SSHKeyManager
|
||||
import app.passwordstore.util.extensions.viewBinding
|
||||
import app.passwordstore.util.ssh.SSHFacade
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import de.Maxr1998.modernpreferences.Preference
|
||||
@ -24,7 +24,7 @@ import javax.inject.Inject
|
||||
@AndroidEntryPoint
|
||||
class SettingsActivity : AppCompatActivity() {
|
||||
|
||||
@Inject lateinit var sshFacade: SSHFacade
|
||||
@Inject lateinit var sshKeyManager: SSHKeyManager
|
||||
private lateinit var repositorySettings: RepositorySettings
|
||||
private val miscSettings = MiscSettings(this)
|
||||
private val autofillSettings = AutofillSettings(this)
|
||||
@ -40,7 +40,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(binding.root)
|
||||
Preference.Config.dialogBuilderFactory = { context -> MaterialAlertDialogBuilder(context) }
|
||||
repositorySettings = RepositorySettings(this, sshFacade)
|
||||
repositorySettings = RepositorySettings(this, sshKeyManager)
|
||||
val screen =
|
||||
screen(this) {
|
||||
subScreen {
|
||||
|
@ -9,7 +9,7 @@ import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import app.passwordstore.R
|
||||
import app.passwordstore.util.ssh.SSHFacade
|
||||
import app.passwordstore.ssh.SSHKeyManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import javax.inject.Inject
|
||||
@ -17,11 +17,11 @@ import javax.inject.Inject
|
||||
@AndroidEntryPoint
|
||||
class ShowSshKeyFragment : DialogFragment() {
|
||||
|
||||
@Inject lateinit var sshFacade: SSHFacade
|
||||
@Inject lateinit var sshKeyManager: SSHKeyManager
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val activity = requireActivity()
|
||||
val publicKey = sshFacade.publicKey()
|
||||
val publicKey = sshKeyManager.publicKey()
|
||||
return MaterialAlertDialogBuilder(requireActivity()).run {
|
||||
setMessage(getString(R.string.ssh_keygen_message, publicKey))
|
||||
setTitle(R.string.your_public_key)
|
||||
|
@ -18,12 +18,12 @@ import app.passwordstore.R
|
||||
import app.passwordstore.databinding.ActivitySshKeygenBinding
|
||||
import app.passwordstore.injection.prefs.GitPreferences
|
||||
import app.passwordstore.ssh.SSHKeyAlgorithm
|
||||
import app.passwordstore.ssh.SSHKeyManager
|
||||
import app.passwordstore.util.auth.BiometricAuthenticator
|
||||
import app.passwordstore.util.auth.BiometricAuthenticator.Result
|
||||
import app.passwordstore.util.coroutines.DispatcherProvider
|
||||
import app.passwordstore.util.extensions.keyguardManager
|
||||
import app.passwordstore.util.extensions.viewBinding
|
||||
import app.passwordstore.util.ssh.SSHFacade
|
||||
import com.github.michaelbull.result.fold
|
||||
import com.github.michaelbull.result.runCatching
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
@ -40,7 +40,7 @@ class SshKeyGenActivity : AppCompatActivity() {
|
||||
private var sshKeyAlgorithm = SSHKeyAlgorithm.ECDSA
|
||||
private val binding by viewBinding(ActivitySshKeygenBinding::inflate)
|
||||
@GitPreferences @Inject lateinit var gitPrefs: SharedPreferences
|
||||
@Inject lateinit var sshFacade: SSHFacade
|
||||
@Inject lateinit var sshKeyManager: SSHKeyManager
|
||||
@Inject lateinit var dispatcherProvider: DispatcherProvider
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@ -49,7 +49,7 @@ class SshKeyGenActivity : AppCompatActivity() {
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
with(binding) {
|
||||
generate.setOnClickListener {
|
||||
if (sshFacade.keyExists()) {
|
||||
if (sshKeyManager.keyExists()) {
|
||||
MaterialAlertDialogBuilder(this@SshKeyGenActivity).run {
|
||||
setTitle(R.string.ssh_keygen_existing_title)
|
||||
setMessage(R.string.ssh_keygen_existing_message)
|
||||
@ -127,7 +127,7 @@ class SshKeyGenActivity : AppCompatActivity() {
|
||||
if (result !is Result.Success)
|
||||
throw UserNotAuthenticatedException(getString(R.string.biometric_auth_generic_failure))
|
||||
}
|
||||
sshFacade.generateKey(sshKeyAlgorithm, requireAuthentication)
|
||||
sshKeyManager.generateKey(sshKeyAlgorithm, requireAuthentication)
|
||||
}
|
||||
}
|
||||
// Check if we still need this
|
||||
|
@ -12,7 +12,7 @@ import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import app.passwordstore.R
|
||||
import app.passwordstore.util.ssh.SSHFacade
|
||||
import app.passwordstore.ssh.SSHKeyManager
|
||||
import com.github.michaelbull.result.onFailure
|
||||
import com.github.michaelbull.result.runCatching
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
@ -23,7 +23,7 @@ import kotlinx.coroutines.launch
|
||||
@AndroidEntryPoint
|
||||
class SshKeyImportActivity : AppCompatActivity() {
|
||||
|
||||
@Inject lateinit var sshFacade: SSHFacade
|
||||
@Inject lateinit var sshKeyManager: SSHKeyManager
|
||||
|
||||
private val sshKeyImportAction =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri: Uri? ->
|
||||
@ -33,7 +33,7 @@ class SshKeyImportActivity : AppCompatActivity() {
|
||||
}
|
||||
runCatching {
|
||||
lifecycleScope.launch {
|
||||
sshFacade.importKey(uri)
|
||||
sshKeyManager.importKey(uri)
|
||||
Toast.makeText(
|
||||
this@SshKeyImportActivity,
|
||||
resources.getString(R.string.ssh_key_success_dialog_title),
|
||||
@ -55,7 +55,7 @@ class SshKeyImportActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (sshFacade.keyExists()) {
|
||||
if (sshKeyManager.keyExists()) {
|
||||
MaterialAlertDialogBuilder(this@SshKeyImportActivity).run {
|
||||
setTitle(R.string.ssh_keygen_existing_title)
|
||||
setMessage(R.string.ssh_keygen_existing_message)
|
||||
|
@ -13,9 +13,6 @@ enum class Feature(
|
||||
val configKey: String,
|
||||
) {
|
||||
|
||||
/** Opt into the new SSH layer implemented as a freestanding module. */
|
||||
EnableNewSSHLayer(false, "enable_new_ssh"),
|
||||
|
||||
/** Opt into a cache layer for PGP passphrases. */
|
||||
EnablePGPPassphraseCache(false, "enable_gpg_passphrase_cache"),
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import app.passwordstore.R
|
||||
import app.passwordstore.data.repo.PasswordRepository
|
||||
import app.passwordstore.ssh.SSHKeyManager
|
||||
import app.passwordstore.ui.sshkeygen.SshKeyGenActivity
|
||||
import app.passwordstore.ui.sshkeygen.SshKeyImportActivity
|
||||
import app.passwordstore.util.auth.BiometricAuthenticator
|
||||
@ -22,7 +23,6 @@ import app.passwordstore.util.git.GitCommandExecutor
|
||||
import app.passwordstore.util.git.sshj.SshAuthMethod
|
||||
import app.passwordstore.util.git.sshj.SshjSessionFactory
|
||||
import app.passwordstore.util.settings.AuthMode
|
||||
import app.passwordstore.util.ssh.SSHFacade
|
||||
import com.github.michaelbull.result.Err
|
||||
import com.github.michaelbull.result.Ok
|
||||
import com.github.michaelbull.result.Result
|
||||
@ -71,7 +71,7 @@ abstract class GitOperation(protected val callingActivity: FragmentActivity) {
|
||||
callingActivity.applicationContext,
|
||||
GitOperationEntryPoint::class.java
|
||||
)
|
||||
private val sshFacade = hiltEntryPoint.sshFacade()
|
||||
private val sshKeyManager = hiltEntryPoint.sshKeyManager()
|
||||
protected val repository = PasswordRepository.repository!!
|
||||
protected val git = Git(repository)
|
||||
private val authActivity
|
||||
@ -121,8 +121,7 @@ abstract class GitOperation(protected val callingActivity: FragmentActivity) {
|
||||
authMethod: SshAuthMethod,
|
||||
credentialsProvider: CredentialsProvider? = null
|
||||
) {
|
||||
sshSessionFactory =
|
||||
SshjSessionFactory(authMethod, hostKeyFile, sshFacade, hiltEntryPoint.dispatcherProvider())
|
||||
sshSessionFactory = SshjSessionFactory(authMethod, hostKeyFile, sshKeyManager, hiltEntryPoint.dispatcherProvider())
|
||||
commands.filterIsInstance<TransportCommand<*, *>>().forEach { command ->
|
||||
command.setTransportConfigCallback { transport: Transport ->
|
||||
(transport as? SshTransport)?.sshSessionFactory = sshSessionFactory
|
||||
@ -170,8 +169,8 @@ abstract class GitOperation(protected val callingActivity: FragmentActivity) {
|
||||
suspend fun executeAfterAuthentication(authMode: AuthMode): Result<Unit, Throwable> {
|
||||
when (authMode) {
|
||||
AuthMode.SshKey ->
|
||||
if (sshFacade.keyExists()) {
|
||||
if (sshFacade.needsAuthentication()) {
|
||||
if (sshKeyManager.keyExists()) {
|
||||
if (sshKeyManager.needsAuthentication()) {
|
||||
val result =
|
||||
withContext(hiltEntryPoint.dispatcherProvider().main()) {
|
||||
suspendCoroutine { cont ->
|
||||
@ -248,7 +247,7 @@ abstract class GitOperation(protected val callingActivity: FragmentActivity) {
|
||||
@EntryPoint
|
||||
@InstallIn(SingletonComponent::class)
|
||||
interface GitOperationEntryPoint {
|
||||
fun sshFacade(): SSHFacade
|
||||
fun sshKeyManager(): SSHKeyManager
|
||||
|
||||
fun dispatcherProvider(): DispatcherProvider
|
||||
}
|
||||
|
@ -6,10 +6,10 @@ package app.passwordstore.util.git.sshj
|
||||
|
||||
import android.util.Base64
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import app.passwordstore.ssh.SSHKeyManager
|
||||
import app.passwordstore.util.coroutines.DispatcherProvider
|
||||
import app.passwordstore.util.git.operation.CredentialFinder
|
||||
import app.passwordstore.util.settings.AuthMode
|
||||
import app.passwordstore.util.ssh.SSHFacade
|
||||
import com.github.michaelbull.result.getOrElse
|
||||
import com.github.michaelbull.result.runCatching
|
||||
import java.io.File
|
||||
@ -71,7 +71,7 @@ abstract class InteractivePasswordFinder(private val dispatcherProvider: Dispatc
|
||||
class SshjSessionFactory(
|
||||
private val authMethod: SshAuthMethod,
|
||||
private val hostKeyFile: File,
|
||||
private val sshFacade: SSHFacade,
|
||||
private val sshKeyManager: SSHKeyManager,
|
||||
private val dispatcherProvider: DispatcherProvider,
|
||||
) : SshSessionFactory() {
|
||||
|
||||
@ -84,12 +84,10 @@ class SshjSessionFactory(
|
||||
tms: Int
|
||||
): RemoteSession {
|
||||
return currentSession
|
||||
?: SshjSession(uri, uri.user, authMethod, hostKeyFile, sshFacade, dispatcherProvider)
|
||||
.connect()
|
||||
.also {
|
||||
logcat { "New SSH connection created" }
|
||||
currentSession = it
|
||||
}
|
||||
?: SshjSession(uri, uri.user, authMethod, hostKeyFile, dispatcherProvider, sshKeyManager).connect().also {
|
||||
logcat { "New SSH connection created" }
|
||||
currentSession = it
|
||||
}
|
||||
}
|
||||
|
||||
fun close() {
|
||||
@ -130,8 +128,8 @@ private class SshjSession(
|
||||
private val username: String,
|
||||
private val authMethod: SshAuthMethod,
|
||||
private val hostKeyFile: File,
|
||||
private val sshFacade: SSHFacade,
|
||||
private val dispatcherProvider: DispatcherProvider,
|
||||
private val sshKeyManager: SSHKeyManager,
|
||||
) : RemoteSession {
|
||||
|
||||
private lateinit var ssh: SSHClient
|
||||
@ -167,10 +165,7 @@ private class SshjSession(
|
||||
is SshAuthMethod.SshKey -> {
|
||||
val pubkeyAuth =
|
||||
AuthPublickey(
|
||||
sshFacade.keyProvider(
|
||||
ssh,
|
||||
CredentialFinder(authMethod.activity, AuthMode.SshKey, dispatcherProvider)
|
||||
)
|
||||
sshKeyManager.keyProvider(ssh, CredentialFinder(authMethod.activity, AuthMode.SshKey, dispatcherProvider))
|
||||
)
|
||||
ssh.auth(username, pubkeyAuth, passwordAuth)
|
||||
}
|
||||
|
@ -1,86 +0,0 @@
|
||||
package app.passwordstore.util.ssh
|
||||
|
||||
import android.net.Uri
|
||||
import app.passwordstore.ssh.SSHKeyAlgorithm
|
||||
import app.passwordstore.ssh.SSHKeyManager
|
||||
import app.passwordstore.util.features.Feature
|
||||
import app.passwordstore.util.features.Features
|
||||
import app.passwordstore.util.git.operation.CredentialFinder
|
||||
import app.passwordstore.util.git.sshj.SshKey
|
||||
import javax.inject.Inject
|
||||
import net.schmizz.sshj.SSHClient
|
||||
import net.schmizz.sshj.userauth.keyprovider.KeyProvider
|
||||
|
||||
/** A wrapper around [SshKey] and [SSHKeyManager] to allow switching between them at runtime. */
|
||||
class SSHFacade
|
||||
@Inject
|
||||
constructor(
|
||||
private val features: Features,
|
||||
private val sshKeyManager: SSHKeyManager,
|
||||
) {
|
||||
|
||||
private val useNewSSH
|
||||
get() = features.isEnabled(Feature.EnableNewSSHLayer)
|
||||
|
||||
fun canShowPublicKey(): Boolean {
|
||||
return if (useNewSSH) {
|
||||
sshKeyManager.canShowPublicKey()
|
||||
} else {
|
||||
SshKey.canShowSshPublicKey
|
||||
}
|
||||
}
|
||||
|
||||
fun publicKey(): String? {
|
||||
return if (useNewSSH) {
|
||||
sshKeyManager.publicKey()
|
||||
} else {
|
||||
SshKey.sshPublicKey
|
||||
}
|
||||
}
|
||||
|
||||
fun keyExists(): Boolean {
|
||||
return if (useNewSSH) {
|
||||
sshKeyManager.keyExists()
|
||||
} else {
|
||||
SshKey.exists
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun generateKey(keyAlgorithm: SSHKeyAlgorithm, requireAuthentication: Boolean) {
|
||||
if (useNewSSH) {
|
||||
sshKeyManager.generateKey(keyAlgorithm, requireAuthentication)
|
||||
} else {
|
||||
when (keyAlgorithm) {
|
||||
SSHKeyAlgorithm.RSA ->
|
||||
SshKey.generateKeystoreNativeKey(SshKey.Algorithm.Rsa, requireAuthentication)
|
||||
SSHKeyAlgorithm.ECDSA ->
|
||||
SshKey.generateKeystoreNativeKey(SshKey.Algorithm.Ecdsa, requireAuthentication)
|
||||
SSHKeyAlgorithm.ED25519 -> SshKey.generateKeystoreWrappedEd25519Key(requireAuthentication)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun importKey(uri: Uri) {
|
||||
if (useNewSSH) {
|
||||
sshKeyManager.importKey(uri)
|
||||
} else {
|
||||
SshKey.import(uri)
|
||||
}
|
||||
}
|
||||
|
||||
fun needsAuthentication(): Boolean {
|
||||
return if (useNewSSH) {
|
||||
sshKeyManager.needsAuthentication()
|
||||
} else {
|
||||
SshKey.mustAuthenticate
|
||||
}
|
||||
}
|
||||
|
||||
fun keyProvider(client: SSHClient, credentialFinder: CredentialFinder): KeyProvider? {
|
||||
return if (useNewSSH) {
|
||||
sshKeyManager.keyProvider(client, credentialFinder)
|
||||
} else {
|
||||
SshKey.provide(client, credentialFinder)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user