diff options
Diffstat (limited to 'app/src/main/java')
9 files changed, 32 insertions, 127 deletions
diff --git a/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt b/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt index d61a6b93..462924ac 100644 --- a/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt +++ b/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt @@ -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 diff --git a/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt b/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt index a78e6b4b..697d0156 100644 --- a/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt @@ -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 { diff --git a/app/src/main/java/app/passwordstore/ui/sshkeygen/ShowSshKeyFragment.kt b/app/src/main/java/app/passwordstore/ui/sshkeygen/ShowSshKeyFragment.kt index b96342e5..4f52b540 100644 --- a/app/src/main/java/app/passwordstore/ui/sshkeygen/ShowSshKeyFragment.kt +++ b/app/src/main/java/app/passwordstore/ui/sshkeygen/ShowSshKeyFragment.kt @@ -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) diff --git a/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt b/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt index 790751f9..34749e4c 100644 --- a/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt @@ -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 diff --git a/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyImportActivity.kt b/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyImportActivity.kt index 0d8ec7bf..a5d276ae 100644 --- a/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyImportActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyImportActivity.kt @@ -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) diff --git a/app/src/main/java/app/passwordstore/util/features/Feature.kt b/app/src/main/java/app/passwordstore/util/features/Feature.kt index f046dbd7..6cea1031 100644 --- a/app/src/main/java/app/passwordstore/util/features/Feature.kt +++ b/app/src/main/java/app/passwordstore/util/features/Feature.kt @@ -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"), } diff --git a/app/src/main/java/app/passwordstore/util/git/operation/GitOperation.kt b/app/src/main/java/app/passwordstore/util/git/operation/GitOperation.kt index d4ccfaab..199fde94 100644 --- a/app/src/main/java/app/passwordstore/util/git/operation/GitOperation.kt +++ b/app/src/main/java/app/passwordstore/util/git/operation/GitOperation.kt @@ -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 } diff --git a/app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt b/app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt index 20bb01d6..86416cd6 100644 --- a/app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt +++ b/app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt @@ -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) } diff --git a/app/src/main/java/app/passwordstore/util/ssh/SSHFacade.kt b/app/src/main/java/app/passwordstore/util/ssh/SSHFacade.kt deleted file mode 100644 index 8d8c8aa6..00000000 --- a/app/src/main/java/app/passwordstore/util/ssh/SSHFacade.kt +++ /dev/null @@ -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) - } - } -} |