1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 18:26:01 +02:00

Support Terminal Ssh Preferences, Proxy, Passphrase and KI authentication

This commit is contained in:
Martin Oberhuber 2006-12-07 15:25:50 +00:00
parent b1691c603d
commit f82b22249e
2 changed files with 238 additions and 26 deletions

View file

@ -8,6 +8,10 @@ Bundle-Localization: plugin
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.tm.terminal,
org.eclipse.ui,
org.eclipse.team.cvs.core;bundle-version="[3.2.0,4.0.0)",
org.eclipse.team.cvs.ssh2;bundle-version="[3.2.0,4.0.0)",
org.eclipse.team.cvs.ui;bundle-version="[3.2.0,4.0.0)",
com.jcraft.jsch;bundle-version="[0.1.28,2.0.0)"
Eclipse-LazyStart: true
Bundle-RequiredExecutionEnvironment: J2SE-1.4

View file

@ -13,17 +13,28 @@ package org.eclipse.tm.terminal.ssh;
import java.io.IOException;
import java.io.InputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin;
import org.eclipse.team.internal.ccvs.ssh2.CVSSSH2Plugin;
import org.eclipse.team.internal.ccvs.ssh2.ISSHContants;
import org.eclipse.team.internal.ccvs.ui.KeyboardInteractiveDialog;
import org.eclipse.team.internal.ccvs.ui.UserValidationDialog;
import org.eclipse.tm.terminal.ITerminalControl;
import org.eclipse.tm.terminal.Logger;
import org.eclipse.tm.terminal.TerminalState;
import com.jcraft.jsch.ChannelShell;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Proxy;
import com.jcraft.jsch.ProxyHTTP;
import com.jcraft.jsch.ProxySOCKS5;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;
@ -35,17 +46,142 @@ class SshConnection extends Thread {
fConn = conn;
fControl.setState(TerminalState.CONNECTING);
}
//----------------------------------------------------------------------
// <copied from org.eclipse.team.cvs.ssh2>
//----------------------------------------------------------------------
private static String current_ssh_home = null;
private static String current_pkeys = ""; //$NON-NLS-1$
static String SSH_HOME_DEFAULT = null;
static {
String ssh_dir_name = ".ssh"; //$NON-NLS-1$
// Windows doesn't like files or directories starting with a dot.
if (Platform.getOS().equals(Platform.OS_WIN32)) {
ssh_dir_name = "ssh"; //$NON-NLS-1$
}
SSH_HOME_DEFAULT = System.getProperty("user.home"); //$NON-NLS-1$
if (SSH_HOME_DEFAULT != null) {
SSH_HOME_DEFAULT = SSH_HOME_DEFAULT + java.io.File.separator + ssh_dir_name;
}
}
// Load ssh prefs from Team/CVS for now.
// TODO do our own preference page.
static void loadSshPrefs(JSch jsch)
{
IPreferenceStore store = CVSSSH2Plugin.getDefault().getPreferenceStore();
String ssh_home = store.getString(ISSHContants.KEY_SSH2HOME);
String pkeys = store.getString(ISSHContants.KEY_PRIVATEKEY);
try {
if (ssh_home.length() == 0)
ssh_home = SSH_HOME_DEFAULT;
if (current_ssh_home == null || !current_ssh_home.equals(ssh_home)) {
loadKnownHosts(jsch, ssh_home);
current_ssh_home = ssh_home;
}
if (!current_pkeys.equals(pkeys)) {
java.io.File file;
String[] pkey = pkeys.split(","); //$NON-NLS-1$
String[] _pkey = current_pkeys.split(","); //$NON-NLS-1$
current_pkeys = ""; //$NON-NLS-1$
for (int i = 0; i < pkey.length; i++) {
file = new java.io.File(pkey[i]);
if (!file.isAbsolute()) {
file = new java.io.File(ssh_home, pkey[i]);
}
if (file.exists()) {
boolean notyet = true;
for (int j = 0; j < _pkey.length; j++) {
if (pkey[i].equals(_pkey[j])) {
notyet = false;
break;
}
}
if (notyet)
jsch.addIdentity(file.getPath());
if (current_pkeys.length() == 0) {
current_pkeys = pkey[i];
} else {
current_pkeys += ("," + pkey[i]); //$NON-NLS-1$
}
}
}
}
} catch (Exception e) {
}
}
static void loadKnownHosts(JSch jsch, String ssh_home){
try {
java.io.File file;
file=new java.io.File(ssh_home, "known_hosts"); //$NON-NLS-1$
jsch.setKnownHosts(file.getPath());
} catch (Exception e) {
}
}
static Proxy loadSshProxyPrefs() {
//TODO Get rid of discouraged access when bug 154100 is fixed
boolean useProxy = CVSProviderPlugin.getPlugin().isUseProxy();
Proxy proxy = null;
if (useProxy) {
String _type = CVSProviderPlugin.getPlugin().getProxyType();
String _host = CVSProviderPlugin.getPlugin().getProxyHost();
String _port = CVSProviderPlugin.getPlugin().getProxyPort();
boolean useAuth = CVSProviderPlugin.getPlugin().isUseProxyAuth();
String _user = ""; //$NON-NLS-1$
String _pass = ""; //$NON-NLS-1$
// Retrieve username and password from keyring.
if(useAuth){
_user=CVSProviderPlugin.getPlugin().getProxyUser();
_pass=CVSProviderPlugin.getPlugin().getProxyPassword();
}
String proxyhost = _host + ":" + _port; //$NON-NLS-1$
if (_type.equals(CVSProviderPlugin.PROXY_TYPE_HTTP)) {
proxy = new ProxyHTTP(proxyhost);
if (useAuth) {
((ProxyHTTP) proxy).setUserPasswd(_user, _pass);
}
} else if (_type.equals(CVSProviderPlugin.PROXY_TYPE_SOCKS5)) {
proxy = new ProxySOCKS5(proxyhost);
if (useAuth) {
((ProxySOCKS5) proxy).setUserPasswd(_user, _pass);
}
}
}
return proxy;
}
//----------------------------------------------------------------------
// </copied from org.eclipse.team.cvs.ssh2>
//----------------------------------------------------------------------
public void run() {
try {
int nTimeout = fConn.getTelnetSettings().getTimeout() * 1000;
String host = fConn.getTelnetSettings().getHost();
String user = fConn.getTelnetSettings().getUser();
String password = fConn.getTelnetSettings().getPassword();
int port=fConn.getTelnetSettings().getPort();
Session session=fConn.getJsch().getSession(user, host, port);
//session.setPassword("your password");
// username and password will be given via UserInfo interface.
UserInfo ui=new MyUserInfo(fConn.getTelnetSettings().getPassword());
loadSshPrefs(fConn.getJsch());
Proxy proxy = loadSshProxyPrefs();
Session session=fConn.getJsch().getSession(user, host, port);
if (proxy != null) {
session.setProxy(proxy);
}
session.setTimeout(0); //never time out once connected
session.setPassword(password);
UserInfo ui=new MyUserInfo(user, password);
session.setUserInfo(ui);
// java.util.Hashtable config=new java.util.Hashtable();
@ -56,26 +192,13 @@ class SshConnection extends Thread {
session.connect(nTimeout); // making connection with timeout.
ChannelShell channel=(ChannelShell) session.openChannel("shell"); //$NON-NLS-1$
//hmm, now it gets a bit complicated
// Input and output streams are somehow confusing
PipedInputStream pin = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream(pin);
PipedOutputStream pout = new PipedOutputStream();
PipedInputStream in = new PipedInputStream(pout);
channel.setInputStream(pin);
channel.setOutputStream(pout);
channel.connect();
fConn.setInputStream(in);
fConn.setOutputStream(out);
fConn.setInputStream(channel.getInputStream());
fConn.setOutputStream(channel.getOutputStream());
fConn.setChannel(channel);
fControl.setState(TerminalState.CONNECTED);
// read data until the connection gets terminated
readDataForever(in);
readDataForever(fConn.getInputStream());
} catch (JSchException e) {
connectFailed(e.getMessage(),e.getMessage());
} catch (IOException e) {
@ -100,10 +223,22 @@ class SshConnection extends Thread {
fControl.setState(TerminalState.CLOSED);
}
protected static Display getStandardDisplay() {
Display display = Display.getCurrent();
if( display==null ) {
display = Display.getDefault();
}
return display;
}
private static class MyUserInfo implements UserInfo {
private String fPassword;
private String fPassphrase;
private int fAttemptCount;
private final String fUser;
public MyUserInfo(String password) {
public MyUserInfo(String user, String password) {
fUser = user;
fPassword = password;
}
public String getPassword() {
@ -119,14 +254,38 @@ class SshConnection extends Thread {
});
return retval[0];
}
private String promptSecret(final String message) {
final String[] retval = new String[1];
final String finUser = fUser;
getStandardDisplay().syncExec(new Runnable() {
public void run() {
//TODO discouraged access: Write our own UserValidationDialog
UserValidationDialog uvd = new UserValidationDialog(null, null,
finUser, message);
uvd.setUsernameMutable(false);
if (uvd.open() == Window.OK) {
retval[0] = uvd.getPassword();
} else {
retval[0] = null;
}
}
});
return retval[0];
}
public String getPassphrase() {
return null;
return fPassphrase;
}
public boolean promptPassphrase(String message) {
return true;
fPassphrase = promptSecret(message);
return (fPassphrase!=null);
}
public boolean promptPassword(final String message) {
return true;
String _password = promptSecret(message);
if (_password!=null) {
fPassword=_password;
return true;
}
return false;
}
public void showMessage(final String message) {
Display.getDefault().syncExec(new Runnable() {
@ -135,6 +294,55 @@ class SshConnection extends Thread {
}
});
}
public String[] promptKeyboardInteractive(final String destination,
final String name, final String instruction,
final String[] prompt, final boolean[] echo)
{
if (prompt.length == 0) {
// No need to prompt, just return an empty String array
return new String[0];
}
try{
if (fAttemptCount == 0 && fPassword != null && prompt.length == 1 && prompt[0].trim().equalsIgnoreCase("password:")) { //$NON-NLS-1$
// Return the provided password the first time but always prompt on subsequent tries
fAttemptCount++;
return new String[] { fPassword };
}
final String[][] finResult = new String[1][];
getStandardDisplay().syncExec(new Runnable() {
public void run() {
//TODO discouraged access: write our own KeyboardInteractiveDialog
KeyboardInteractiveDialog dialog = new KeyboardInteractiveDialog(null,
null, destination, name, instruction, prompt, echo);
dialog.open();
finResult[0]=dialog.getResult();
}
});
String[] result=finResult[0];
if (result == null)
return null; // canceled
if (result.length == 1 && prompt.length == 1 && prompt[0].trim().equalsIgnoreCase("password:")) { //$NON-NLS-1$
fPassword = result[0];
}
fAttemptCount++;
return result;
}
catch(OperationCanceledException e){
return null;
}
}
/**
* Callback to indicate that a connection is about to be attempted
*/
public void aboutToConnect() {
fAttemptCount = 0;
}
/**
* Callback to indicate that a connection was made
*/
public void connectionMade() {
fAttemptCount = 0;
}
}
private void connectFailed(String terminalText, String msg) {