Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

Use SSHJ for SSH public key authentication #801

Merged
merged 3 commits into from
May 28, 2020
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/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ dependencies {
exclude group: 'org.apache.httpcomponents', module: 'httpclient'
}
implementation deps.third_party.jsch
implementation deps.third_party.sshj
implementation deps.third_party.bouncycastle
implementation deps.third_party.openpgp_ktx
implementation deps.third_party.ssh_auth
implementation deps.third_party.timber
Expand Down
9 changes: 9 additions & 0 deletions app/lint.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?><!--
~ Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
~ SPDX-License-Identifier: GPL-3.0-only
-->
<lint>
<issue id="InvalidPackage">
<ignore regexp="X509LDAPCertStoreSpi" />
</issue>
</lint>
3 changes: 3 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@
-dontobfuscate
-keep class com.jcraft.jsch.**
msfjarvis marked this conversation as resolved.
Show resolved Hide resolved
-keep class org.eclipse.jgit.internal.JGitText { *; }
-keep class org.bouncycastle.jcajce.provider.** { *; }
-keep class org.bouncycastle.jce.provider.** { *; }
-keep class !org.bouncycastle.jce.provider.X509LDAPCertStoreSpi { *; }
22 changes: 22 additions & 0 deletions app/src/main/java/com/zeapo/pwdstore/Application.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import androidx.preference.PreferenceManager
import com.github.ajalt.timberkt.Timber.DebugTree
import com.github.ajalt.timberkt.Timber.plant
import com.haroldadmin.whatthestack.WhatTheStack
import org.bouncycastle.jce.provider.BouncyCastleProvider
import java.security.Security

@Suppress("Unused")
class Application : android.app.Application(), SharedPreferences.OnSharedPreferenceChangeListener {
Expand All @@ -29,6 +31,7 @@ class Application : android.app.Application(), SharedPreferences.OnSharedPrefere
}
prefs?.registerOnSharedPreferenceChangeListener(this)
setNightMode()
setUpBouncyCastle()
}

override fun onTerminate() {
Expand All @@ -42,6 +45,25 @@ class Application : android.app.Application(), SharedPreferences.OnSharedPrefere
}
}

private fun setUpBouncyCastle() {
// Replace the Android BC provider with the Java BouncyCastle provider since the former does
// not include all the required algorithms.
// TODO: Verify that we are indeed using the fast Android-native implementation whenever
// possible.
// Note: This may affect crypto operations in other parts of the application.
val bcIndex = Security.getProviders().indexOfFirst {
it.name == BouncyCastleProvider.PROVIDER_NAME
}
if (bcIndex == -1) {
// No Android BC found, install Java BC at lowest priority.
Security.addProvider(BouncyCastleProvider())
} else {
// Replace Android BC with Java BC, inserted at the same position.
Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME)
Security.insertProviderAt(BouncyCastleProvider(), bcIndex + 1)
}
}

private fun setNightMode() {
AppCompatDelegate.setDefaultNightMode(when (prefs?.getString("app_theme", getString(R.string.app_theme_def))) {
"light" -> MODE_NIGHT_NO
Expand Down
10 changes: 5 additions & 5 deletions app/src/main/java/com/zeapo/pwdstore/git/BaseGitActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,11 @@ abstract class BaseGitActivity : AppCompatActivity() {
}
if (PasswordRepository.isInitialized)
PasswordRepository.addRemote("origin", newUrl, true)
// HTTPS authentication sends the password to the server, so we must wipe the password when
// the server is changed.
if (previousUrl.isNotEmpty() && newUrl != previousUrl && protocol == Protocol.Https)
// When the server changes, remote password and host key file should be deleted.
if (previousUrl.isNotEmpty() && newUrl != previousUrl) {
encryptedSettings.edit { remove("https_password") }
File("$filesDir/.host_key").delete()
}
url = newUrl
return GitUpdateUrlResult.Ok
}
Expand Down Expand Up @@ -201,8 +202,7 @@ abstract class BaseGitActivity : AppCompatActivity() {
return
}
}
op.executeAfterAuthentication(connectionMode, serverUser,
File("$filesDir/.ssh_key"), identity)
op.executeAfterAuthentication(connectionMode, serverUser, identity)
} catch (e: Exception) {
e.printStackTrace()
MaterialAlertDialogBuilder(this).setMessage(e.message).show()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ class BreakOutOfDetached(fileDir: File, callingActivity: Activity) : GitOperatio
.execute(*this.commands.toTypedArray())
}

override fun onError(errorMessage: String) {
override fun onError(err: Exception) {
MaterialAlertDialogBuilder(callingActivity)
.setTitle(callingActivity.resources.getString(R.string.jgit_error_dialog_title))
.setMessage("Error occurred when checking out another branch operation $errorMessage")
.setMessage("Error occurred when checking out another branch operation ${err.message}")
.setPositiveButton(callingActivity.resources.getString(R.string.dialog_ok)) { _, _ ->
callingActivity.finish()
}.show()
Expand Down
31 changes: 3 additions & 28 deletions app/src/main/java/com/zeapo/pwdstore/git/CloneOperation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,43 +34,18 @@ class CloneOperation(fileDir: File, callingActivity: Activity) : GitOperation(fi
return this
}

/**
* sets the authentication for user/pwd scheme
*
* @param username the username
* @param password the password
* @return the current object
*/
public override fun setAuthentication(username: String, password: String): CloneOperation {
super.setAuthentication(username, password)
return this
}

/**
* sets the authentication for the ssh-key scheme
*
* @param sshKey the ssh-key file
* @param username the username
* @param passphrase the passphrase
* @return the current object
*/
public override fun setAuthentication(sshKey: File, username: String, passphrase: String): CloneOperation {
super.setAuthentication(sshKey, username, passphrase)
return this
}

override fun execute() {
(this.command as? CloneCommand)?.setCredentialsProvider(this.provider)
GitAsyncTask(callingActivity, false, this, Intent()).execute(this.command)
}

override fun onError(errorMessage: String) {
super.onError(errorMessage)
override fun onError(err: Exception) {
super.onError(err)
MaterialAlertDialogBuilder(callingActivity)
.setTitle(callingActivity.resources.getString(R.string.jgit_error_dialog_title))
.setMessage("Error occurred during the clone operation, " +
callingActivity.resources.getString(R.string.jgit_error_dialog_text) +
errorMessage +
err.message +
"\nPlease check the FAQ for possible reasons why this error might occur.")
.setPositiveButton(callingActivity.resources.getString(R.string.dialog_ok)) { _, _ -> }
.show()
Expand Down
145 changes: 0 additions & 145 deletions app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.java

This file was deleted.

Loading