Skip to content

Commit

Permalink
Use SSHJ for SSH public key authentication (#801)
Browse files Browse the repository at this point in the history
  • Loading branch information
FabianHenneke committed May 28, 2020
1 parent fea82fe commit 97911c5
Show file tree
Hide file tree
Showing 18 changed files with 421 additions and 350 deletions.
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.**
-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

0 comments on commit 97911c5

Please sign in to comment.