mirror of
https://github.com/android-password-store/Android-Password-Store
synced 2025-08-30 22:05:19 +00:00
added ssh-key based authentication for clone
This commit is contained in:
@@ -26,6 +26,7 @@ import android.widget.TextView;
|
|||||||
import com.jcraft.jsch.JSch;
|
import com.jcraft.jsch.JSch;
|
||||||
import com.jcraft.jsch.JSchException;
|
import com.jcraft.jsch.JSchException;
|
||||||
import com.jcraft.jsch.Session;
|
import com.jcraft.jsch.Session;
|
||||||
|
import com.jcraft.jsch.UserInfo;
|
||||||
import com.zeapo.pwdstore.crypto.PgpHandler;
|
import com.zeapo.pwdstore.crypto.PgpHandler;
|
||||||
import com.zeapo.pwdstore.utils.PasswordRepository;
|
import com.zeapo.pwdstore.utils.PasswordRepository;
|
||||||
|
|
||||||
@@ -36,10 +37,15 @@ import org.apache.commons.io.FileUtils;
|
|||||||
import org.eclipse.jgit.api.errors.InvalidRemoteException;
|
import org.eclipse.jgit.api.errors.InvalidRemoteException;
|
||||||
import org.eclipse.jgit.api.errors.JGitInternalException;
|
import org.eclipse.jgit.api.errors.JGitInternalException;
|
||||||
import org.eclipse.jgit.api.errors.TransportException;
|
import org.eclipse.jgit.api.errors.TransportException;
|
||||||
|
import org.eclipse.jgit.errors.UnsupportedCredentialItem;
|
||||||
import org.eclipse.jgit.merge.MergeStrategy;
|
import org.eclipse.jgit.merge.MergeStrategy;
|
||||||
|
import org.eclipse.jgit.transport.CredentialItem;
|
||||||
|
import org.eclipse.jgit.transport.CredentialsProvider;
|
||||||
|
import org.eclipse.jgit.transport.CredentialsProviderUserInfo;
|
||||||
import org.eclipse.jgit.transport.JschConfigSessionFactory;
|
import org.eclipse.jgit.transport.JschConfigSessionFactory;
|
||||||
import org.eclipse.jgit.transport.OpenSshConfig;
|
import org.eclipse.jgit.transport.OpenSshConfig;
|
||||||
import org.eclipse.jgit.transport.SshSessionFactory;
|
import org.eclipse.jgit.transport.SshSessionFactory;
|
||||||
|
import org.eclipse.jgit.transport.URIish;
|
||||||
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
|
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
|
||||||
import org.eclipse.jgit.util.FS;
|
import org.eclipse.jgit.util.FS;
|
||||||
|
|
||||||
@@ -128,21 +134,6 @@ public class GitHandler extends Activity {
|
|||||||
@Override
|
@Override
|
||||||
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
|
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
|
||||||
String selection = ((Spinner) findViewById(R.id.connection_mode)).getSelectedItem().toString();
|
String selection = ((Spinner) findViewById(R.id.connection_mode)).getSelectedItem().toString();
|
||||||
|
|
||||||
if (selection.equalsIgnoreCase("ssh-key (not yet implemented)")) {
|
|
||||||
new AlertDialog.Builder(activity)
|
|
||||||
.setMessage("Authentication method not implemented yet")
|
|
||||||
.setPositiveButton("OK",
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
|
||||||
dialog.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
).show();
|
|
||||||
((Button) findViewById(R.id.clone_button)).setEnabled(false);
|
|
||||||
} else {
|
|
||||||
((Button) findViewById(R.id.clone_button)).setEnabled(true);
|
|
||||||
}
|
|
||||||
connectionMode = selection;
|
connectionMode = selection;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -506,7 +497,112 @@ public class GitHandler extends Activity {
|
|||||||
private void invokeWithAuthentication(final GitHandler activity, final Method method) {
|
private void invokeWithAuthentication(final GitHandler activity, final Method method) {
|
||||||
|
|
||||||
if (connectionMode.equalsIgnoreCase("ssh-key")) {
|
if (connectionMode.equalsIgnoreCase("ssh-key")) {
|
||||||
|
final File sshKey = new File(getFilesDir() + "/.ssh_key");
|
||||||
|
if (!sshKey.exists()) {
|
||||||
|
new AlertDialog.Builder(this)
|
||||||
|
.setMessage("Please import your SSH key file in the preferences")
|
||||||
|
.setTitle("No SSH key")
|
||||||
|
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
try {
|
||||||
|
Intent intent = new Intent(getApplicationContext(), UserPreference.class);
|
||||||
|
startActivity(intent);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Exception caught :(");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
// Do nothing...
|
||||||
|
}
|
||||||
|
}).show();
|
||||||
|
} else {
|
||||||
|
final EditText passphrase = new EditText(activity);
|
||||||
|
passphrase.setHint("Passphrase");
|
||||||
|
passphrase.setWidth(LinearLayout.LayoutParams.MATCH_PARENT);
|
||||||
|
passphrase.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||||
|
|
||||||
|
new AlertDialog.Builder(activity)
|
||||||
|
.setTitle("Authenticate")
|
||||||
|
.setMessage("Please provide the passphrase for your SSH key. Leave it empty if there is no passphrase.")
|
||||||
|
.setView(passphrase)
|
||||||
|
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
|
|
||||||
|
SshSessionFactory.setInstance(new GitConfigSessionFactory());
|
||||||
|
try {
|
||||||
|
|
||||||
|
JschConfigSessionFactory sessionFactory = new JschConfigSessionFactory() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected JSch
|
||||||
|
getJSch(final OpenSshConfig.Host hc, FS fs) throws JSchException {
|
||||||
|
JSch jsch = super.getJSch(hc, fs);
|
||||||
|
jsch.removeAllIdentity();
|
||||||
|
jsch.addIdentity(sshKey.getAbsolutePath());
|
||||||
|
return jsch;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(OpenSshConfig.Host hc, Session session) {
|
||||||
|
session.setConfig("StrictHostKeyChecking", "no");
|
||||||
|
|
||||||
|
CredentialsProvider provider = new CredentialsProvider() {
|
||||||
|
@Override
|
||||||
|
public boolean isInteractive() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supports(CredentialItem... items) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCredentialItem {
|
||||||
|
for (CredentialItem item : items) {
|
||||||
|
if (item instanceof CredentialItem.Username) {
|
||||||
|
((CredentialItem.Username) item).setValue(settings.getString("git_remote_username", "git"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (item instanceof CredentialItem.StringType) {
|
||||||
|
((CredentialItem.StringType) item).setValue(passphrase.getText().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
UserInfo userInfo = new CredentialsProviderUserInfo(session, provider);
|
||||||
|
session.setUserInfo(userInfo);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SshSessionFactory.setInstance(sessionFactory);
|
||||||
|
|
||||||
|
|
||||||
|
CloneCommand cmd = Git.cloneRepository()
|
||||||
|
.setDirectory(localDir)
|
||||||
|
.setURI(hostname)
|
||||||
|
.setBare(false)
|
||||||
|
.setNoCheckout(false)
|
||||||
|
.setCloneAllBranches(true);
|
||||||
|
|
||||||
|
new CloneTask(activity).execute(cmd);
|
||||||
|
|
||||||
|
} catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
}).show();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (protocol.equals("ssh://")) {
|
if (protocol.equals("ssh://")) {
|
||||||
final EditText password = new EditText(activity);
|
final EditText password = new EditText(activity);
|
||||||
|
@@ -1,9 +1,13 @@
|
|||||||
package com.zeapo.pwdstore;
|
package com.zeapo.pwdstore;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceActivity;
|
import android.preference.PreferenceActivity;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
@@ -12,6 +16,9 @@ import com.zeapo.pwdstore.utils.PasswordRepository;
|
|||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
public class UserPreference extends PreferenceActivity implements Preference.OnPreferenceClickListener {
|
public class UserPreference extends PreferenceActivity implements Preference.OnPreferenceClickListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -19,6 +26,7 @@ public class UserPreference extends PreferenceActivity implements Preference.OnP
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
addPreferencesFromResource(R.xml.preference);
|
addPreferencesFromResource(R.xml.preference);
|
||||||
findPreference("openpgp_key_id").setOnPreferenceClickListener(this);
|
findPreference("openpgp_key_id").setOnPreferenceClickListener(this);
|
||||||
|
findPreference("ssh_key").setOnPreferenceClickListener(this);
|
||||||
|
|
||||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
getActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
}
|
}
|
||||||
@@ -46,6 +54,10 @@ public class UserPreference extends PreferenceActivity implements Preference.OnP
|
|||||||
Intent intent = new Intent(this, PgpHandler.class);
|
Intent intent = new Intent(this, PgpHandler.class);
|
||||||
intent.putExtra("Operation", "GET_KEY_ID");
|
intent.putExtra("Operation", "GET_KEY_ID");
|
||||||
startActivityForResult(intent, 0);
|
startActivityForResult(intent, 0);
|
||||||
|
} else if (pref.getKey().equals("ssh_key")) {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||||
|
intent.setType("file/*");
|
||||||
|
startActivityForResult(intent, 1);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -53,6 +65,14 @@ public class UserPreference extends PreferenceActivity implements Preference.OnP
|
|||||||
protected void onActivityResult(int requestCode, int resultCode,
|
protected void onActivityResult(int requestCode, int resultCode,
|
||||||
Intent data) {
|
Intent data) {
|
||||||
if (resultCode == RESULT_OK) {
|
if (resultCode == RESULT_OK) {
|
||||||
|
if (requestCode == 1) {
|
||||||
|
Uri sshFile = data.getData();
|
||||||
|
try {
|
||||||
|
FileUtils.copyFile(new File(sshFile.getPath()), new File(getFilesDir() + "/.ssh_key"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,7 +15,8 @@
|
|||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
<Spinner
|
<Spinner
|
||||||
android:id="@+id/clone_protocol"
|
android:id="@+id/clone_protocol"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -24,8 +25,9 @@
|
|||||||
android:hint="Repository URI"
|
android:hint="Repository URI"
|
||||||
android:id="@+id/clone_uri"
|
android:id="@+id/clone_uri"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content"
|
||||||
</LinearLayout>
|
android:inputType="textUri"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@@ -10,6 +10,9 @@
|
|||||||
<EditTextPreference android:title="Username"
|
<EditTextPreference android:title="Username"
|
||||||
android:key="git_remote_username"
|
android:key="git_remote_username"
|
||||||
android:hint="username"/>
|
android:hint="username"/>
|
||||||
|
<Preference
|
||||||
|
android:title="SSH Key"
|
||||||
|
android:key="ssh_key"/>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory android:title="Crypto">
|
<PreferenceCategory android:title="Crypto">
|
||||||
|
Reference in New Issue
Block a user