diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt index f3c33dd3..39d6fe48 100644 --- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt +++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt @@ -74,6 +74,11 @@ class UserPreference : AppCompatActivity() { true } + findPreference("ssh_key_clear_passphrase").onPreferenceClickListener = Preference.OnPreferenceClickListener { + sharedPreferences.edit().putString("ssh_key_passphrase", null).apply() + it.isEnabled = false + true + } findPreference("git_server_info").onPreferenceClickListener = Preference.OnPreferenceClickListener { val intent = Intent(callingActivity, GitActivity::class.java) @@ -155,6 +160,7 @@ class UserPreference : AppCompatActivity() { findPreference("pref_select_external").summary = preferenceManager.sharedPreferences.getString("git_external_repo", getString(R.string.no_repo_selected)) findPreference("ssh_see_key").isEnabled = sharedPreferences.getBoolean("use_generated_key", false) findPreference("git_delete_repo").isEnabled = !sharedPreferences.getBoolean("git_external", false) + findPreference("ssh_key_clear_passphrase").isEnabled = sharedPreferences.getString("ssh_key_passphrase", null)?.isNotEmpty() ?: false val keyPref = findPreference("openpgp_key_id_pref") val selectedKeys: Array = ArrayList(sharedPreferences.getStringSet("openpgp_key_ids_set", HashSet())).toTypedArray() if (selectedKeys.isEmpty()) { diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java b/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java index fe8a083c..45189652 100644 --- a/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitOperation.java @@ -1,11 +1,17 @@ package com.zeapo.pwdstore.git; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.DialogInterface; import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; import android.support.annotation.Nullable; import android.support.v7.app.AlertDialog; import android.text.InputType; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.CheckBox; import android.widget.EditText; import android.widget.LinearLayout; @@ -19,6 +25,7 @@ import com.zeapo.pwdstore.git.config.SshConfigSessionFactory; import com.zeapo.pwdstore.utils.PasswordRepository; import org.eclipse.jgit.api.GitCommand; +import org.eclipse.jgit.diff.Edit; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.transport.JschConfigSessionFactory; import org.eclipse.jgit.transport.SshSessionFactory; @@ -140,10 +147,11 @@ public abstract class GitOperation { } }).show(); } else { - final EditText passphrase = new EditText(callingActivity); - passphrase.setHint("Passphrase"); - passphrase.setWidth(LinearLayout.LayoutParams.MATCH_PARENT); - passphrase.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); + LayoutInflater layoutInflater = LayoutInflater.from(callingActivity.getApplicationContext()); + @SuppressLint("InflateParams") final View dialogView = layoutInflater.inflate(R.layout.git_passphrase_layout, null); + final EditText passphrase = (EditText) dialogView.findViewById(R.id.sshkey_passphrase); + final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(callingActivity.getApplicationContext()); + final String sshKeyPassphrase = settings.getString("ssh_key_passphrase", null); if (showError) { passphrase.setError("Wrong passphrase"); } @@ -152,25 +160,40 @@ public abstract class GitOperation { final KeyPair keyPair = KeyPair.load(jsch, callingActivity.getFilesDir() + "/.ssh_key"); if (keyPair.isEncrypted()) { - new AlertDialog.Builder(callingActivity) - .setTitle(callingActivity.getResources().getString(R.string.passphrase_dialog_title)) - .setMessage(callingActivity.getResources().getString(R.string.passphrase_dialog_text)) - .setView(passphrase) - .setPositiveButton(callingActivity.getResources().getString(R.string.dialog_ok), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - if (keyPair.decrypt(passphrase.getText().toString())) { - // Authenticate using the ssh-key and then execute the command - setAuthentication(sshKey, username, passphrase.getText().toString()).execute(); - } else { - // call back the method - executeAfterAuthentication(connectionMode, username, sshKey, true); - } - } - }).setNegativeButton(callingActivity.getResources().getString(R.string.dialog_cancel), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - // Do nothing. + if (sshKeyPassphrase != null && !sshKeyPassphrase.isEmpty()) { + if (keyPair.decrypt(sshKeyPassphrase)) { + // Authenticate using the ssh-key and then execute the command + setAuthentication(sshKey, username, sshKeyPassphrase).execute(); + } else { + // call back the method + executeAfterAuthentication(connectionMode, username, sshKey, true); } - }).show(); + } else { + new AlertDialog.Builder(callingActivity) + .setTitle(callingActivity.getResources().getString(R.string.passphrase_dialog_title)) + .setMessage(callingActivity.getResources().getString(R.string.passphrase_dialog_text)) + .setView(dialogView) + .setPositiveButton(callingActivity.getResources().getString(R.string.dialog_ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + if (keyPair.decrypt(passphrase.getText().toString())) { + boolean rememberPassphrase = ((CheckBox) dialogView.findViewById(R.id.sshkey_remember_passphrase)).isChecked(); + if (rememberPassphrase) { + settings.edit().putString("ssh_key_passphrase", passphrase.getText().toString()).apply(); + } + // Authenticate using the ssh-key and then execute the command + setAuthentication(sshKey, username, passphrase.getText().toString()).execute(); + } else { + settings.edit().putString("ssh_key_passphrase", null).apply(); + // call back the method + executeAfterAuthentication(connectionMode, username, sshKey, true); + } + } + }).setNegativeButton(callingActivity.getResources().getString(R.string.dialog_cancel), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + // Do nothing. + } + }).show(); + } } else { setAuthentication(sshKey, username, "").execute(); } diff --git a/app/src/main/res/layout/git_passphrase_layout.xml b/app/src/main/res/layout/git_passphrase_layout.xml new file mode 100644 index 00000000..d82a0b55 --- /dev/null +++ b/app/src/main/res/layout/git_passphrase_layout.xml @@ -0,0 +1,34 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7805ad08..e39cb6f5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -46,7 +46,7 @@ Import Generate Authenticate - Please provide the passphrase for your SSH key. Leave it empty if there is no passphrase. + Please provide the passphrase for your SSH key Please provide the password for this repository @@ -208,4 +208,5 @@ Push was rejected by remote, reason: Remote rejected non-fast-forward push. Check receive.denyNonFastForwards variable in config file of destination repository. Error occurred during the push operation: + Clear ssh-key saved passphrase diff --git a/app/src/main/res/xml/preference.xml b/app/src/main/res/xml/preference.xml index 87e77aae..23e68577 100644 --- a/app/src/main/res/xml/preference.xml +++ b/app/src/main/res/xml/preference.xml @@ -13,6 +13,9 @@ +