added ssh-key based authentication for clone

This commit is contained in:
zeapo 2014-08-23 18:44:54 +02:00
parent 196813022a
commit 734988be28
4 changed files with 139 additions and 18 deletions

View File

@ -26,6 +26,7 @@ import android.widget.TextView;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;
import com.zeapo.pwdstore.crypto.PgpHandler;
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.JGitInternalException;
import org.eclipse.jgit.api.errors.TransportException;
import org.eclipse.jgit.errors.UnsupportedCredentialItem;
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.OpenSshConfig;
import org.eclipse.jgit.transport.SshSessionFactory;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.eclipse.jgit.util.FS;
@ -128,21 +134,6 @@ public class GitHandler extends Activity {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
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;
}
@ -506,7 +497,112 @@ public class GitHandler extends Activity {
private void invokeWithAuthentication(final GitHandler activity, final Method method) {
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 {
if (protocol.equals("ssh://")) {
final EditText password = new EditText(activity);

View File

@ -1,9 +1,13 @@
package com.zeapo.pwdstore;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@ -12,6 +16,9 @@ import com.zeapo.pwdstore.utils.PasswordRepository;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.net.URI;
public class UserPreference extends PreferenceActivity implements Preference.OnPreferenceClickListener {
@Override
@ -19,6 +26,7 @@ public class UserPreference extends PreferenceActivity implements Preference.OnP
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preference);
findPreference("openpgp_key_id").setOnPreferenceClickListener(this);
findPreference("ssh_key").setOnPreferenceClickListener(this);
getActionBar().setDisplayHomeAsUpEnabled(true);
}
@ -46,6 +54,10 @@ public class UserPreference extends PreferenceActivity implements Preference.OnP
Intent intent = new Intent(this, PgpHandler.class);
intent.putExtra("Operation", "GET_KEY_ID");
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;
}
@ -53,6 +65,14 @@ public class UserPreference extends PreferenceActivity implements Preference.OnP
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
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) {
}
}
}
}
}

View File

@ -15,7 +15,8 @@
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:orientation="horizontal">
<Spinner
android:id="@+id/clone_protocol"
android:layout_width="wrap_content"
@ -24,8 +25,9 @@
android:hint="Repository URI"
android:id="@+id/clone_uri"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
android:layout_height="wrap_content"
android:inputType="textUri"/>
</LinearLayout>
<Spinner
android:layout_width="match_parent"

View File

@ -10,6 +10,9 @@
<EditTextPreference android:title="Username"
android:key="git_remote_username"
android:hint="username"/>
<Preference
android:title="SSH Key"
android:key="ssh_key"/>
</PreferenceCategory>
<PreferenceCategory android:title="Crypto">