From 0f03dd648c0072b0a7665d505711d4582a138f5f Mon Sep 17 00:00:00 2001 From: Greg Watson Date: Mon, 15 Aug 2016 16:54:33 -0400 Subject: [PATCH] Bug 499679 - Add methods to IRemoteConnectionHostService. Also moves JshUserUnfo to it's own class. Change-Id: I9be57eb45ad3c74843142045c6b300e4a6fb22fd Signed-off-by: Greg Watson --- .../META-INF/MANIFEST.MF | 2 +- bundles/org.eclipse.remote.core/pom.xml | 2 +- .../core/IRemoteConnectionHostService.java | 24 +++ .../local/LocalConnectionHostService.java | 15 ++ .../internal/jsch/core/JSchConnection.java | 194 ++---------------- .../internal/jsch/core/JSchUserInfo.java | 179 ++++++++++++++++ .../remote/telnet/core/TelnetConnection.java | 15 ++ 7 files changed, 248 insertions(+), 183 deletions(-) create mode 100644 bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchUserInfo.java diff --git a/bundles/org.eclipse.remote.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.remote.core/META-INF/MANIFEST.MF index 6b50341e72b..c896fa15561 100644 --- a/bundles/org.eclipse.remote.core/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.remote.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.remote.core;singleton:=true -Bundle-Version: 2.1.0.qualifier +Bundle-Version: 3.0.0.qualifier Bundle-Activator: org.eclipse.remote.internal.core.RemoteCorePlugin Bundle-Vendor: %pluginProvider Bundle-ActivationPolicy: lazy diff --git a/bundles/org.eclipse.remote.core/pom.xml b/bundles/org.eclipse.remote.core/pom.xml index f46f38bddd3..37e8ecaff41 100644 --- a/bundles/org.eclipse.remote.core/pom.xml +++ b/bundles/org.eclipse.remote.core/pom.xml @@ -11,6 +11,6 @@ org.eclipse.remote.core - 2.1.0-SNAPSHOT + 3.0.0-SNAPSHOT eclipse-plugin diff --git a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/IRemoteConnectionHostService.java b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/IRemoteConnectionHostService.java index 995054aa3a5..927fe545311 100644 --- a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/IRemoteConnectionHostService.java +++ b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/IRemoteConnectionHostService.java @@ -37,7 +37,31 @@ public interface IRemoteConnectionHostService extends IRemoteConnection.Service * @return timeout */ int getTimeout(); + + /** + * Get the pass phrase associated with this connection. + * + * @return pass phrase + * @since 3.0 + */ + String getPassphrase(); + + /** + * Get the password associated with this connection. + * + * @return password + * @since 3.0 + */ + String getPassword(); + /** + * Get the value of the use password authentication flag. If true, the connection will try using a password first. + * + * @return use password authentication flag + * @since 3.0 + */ + boolean usePassword(); + /** * Obtain the flag that indicates a login shell should be started once the connection is established * diff --git a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/services/local/LocalConnectionHostService.java b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/services/local/LocalConnectionHostService.java index 8afc56c3ec6..3b2b37867af 100644 --- a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/services/local/LocalConnectionHostService.java +++ b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/services/local/LocalConnectionHostService.java @@ -50,6 +50,16 @@ public class LocalConnectionHostService implements IRemoteConnectionHostService } } + @Override + public String getPassphrase() { + return ""; //$NON-NLS-1$ + } + + @Override + public String getPassword() { + return ""; //$NON-NLS-1$ + } + @Override public int getPort() { return 0; @@ -109,4 +119,9 @@ public class LocalConnectionHostService implements IRemoteConnectionHostService public void setUsername(String username) { // Ignored } + + @Override + public boolean usePassword() { + return false; + } } diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java index 40f2954bf7c..ae5a0f36578 100644 --- a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java @@ -12,7 +12,6 @@ *******************************************************************************/ package org.eclipse.remote.internal.jsch.core; -import java.net.PasswordAuthentication; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -48,8 +47,6 @@ import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.ChannelShell; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; -import com.jcraft.jsch.UIKeyboardInteractive; -import com.jcraft.jsch.UserInfo; /** * @since 5.0 @@ -72,175 +69,6 @@ public class JSchConnection implements IRemoteConnectionControlService, IRemoteC public static final String USE_LOGIN_SHELL_ATTR = "JSCH_USE_LOGIN_SHELL_ATTR"; //$NON-NLS-1$ public static final String LOGIN_SHELL_COMMAND_ATTR = "JSCH_LOGIN_SHELL_COMMAND_ATTR"; //$NON-NLS-1$ - /** - * Class to supply credentials from connection attributes without user interaction. - */ - private class JSchUserInfo implements UserInfo, UIKeyboardInteractive { - private boolean firstTryPassphrase = true; - - /* - * (non-Javadoc) - * - * @see com.jcraft.jsch.UserInfo#getPassphrase() - */ - @Override - public String getPassphrase() { - if (logging) { - System.out.println("getPassphrase"); //$NON-NLS-1$ - } - return JSchConnection.this.getPassphrase(); - } - - /* - * (non-Javadoc) - * - * @see com.jcraft.jsch.UserInfo#getPassword() - */ - @Override - public String getPassword() { - if (logging) { - System.out.println("getPassword"); //$NON-NLS-1$ - } - return JSchConnection.this.getPassword(); - } - - /* - * (non-Javadoc) - * - * @see com.jcraft.jsch.UIKeyboardInteractive#promptKeyboardInteractive(java.lang.String, java.lang.String, - * java.lang.String, java.lang.String[], boolean[]) - */ - @Override - public String[] promptKeyboardInteractive(String destination, String name, String instruction, String[] prompt, - boolean[] echo) { - if (logging) { - System.out.println("promptKeyboardInteractive:" + destination + ":" + name + ":" + instruction); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ - for (String p : prompt) { - System.out.println(" " + p); //$NON-NLS-1$ - } - } - - IUserAuthenticatorService authService = fRemoteConnection.getService(IUserAuthenticatorService.class); - if (authService != null) { - String[] result = authService.prompt(destination, name, instruction, prompt, echo); - if (result != null) { - if (prompt.length == 1 && prompt[0].trim().equalsIgnoreCase("password:")) { //$NON-NLS-1$ - IRemoteConnectionWorkingCopy wc = fRemoteConnection.getWorkingCopy(); - wc.setSecureAttribute(PASSWORD_ATTR, result[0]); - try { - wc.save(); - } catch (RemoteConnectionException e) { - Activator.log(e.getStatus()); - } - } - } - return result; - } - return null; - } - - /* - * (non-Javadoc) - * - * @see com.jcraft.jsch.UserInfo#promptPassphrase(java.lang.String) - */ - @Override - public boolean promptPassphrase(String message) { - if (logging) { - System.out.println("promptPassphrase:" + message); //$NON-NLS-1$ - } - if (firstTryPassphrase && !getPassphrase().equals("")) { //$NON-NLS-1$ - firstTryPassphrase = false; - return true; - } - IUserAuthenticatorService authService = fRemoteConnection.getService(IUserAuthenticatorService.class); - if (authService != null) { - PasswordAuthentication auth = authService.prompt(getUsername(), message); - if (auth == null) { - return false; - } - IRemoteConnectionWorkingCopy wc = fRemoteConnection.getWorkingCopy(); - wc.setAttribute(USERNAME_ATTR, auth.getUserName()); - wc.setSecureAttribute(PASSPHRASE_ATTR, new String(auth.getPassword())); - try { - wc.save(); - } catch (RemoteConnectionException e) { - Activator.log(e.getStatus()); - } - return true; - } - return false; - } - - /* - * (non-Javadoc) - * - * @see com.jcraft.jsch.UserInfo#promptPassword(java.lang.String) - */ - @Override - public boolean promptPassword(String message) { - if (logging) { - System.out.println("promptPassword:" + message); //$NON-NLS-1$ - } - IUserAuthenticatorService authService = fRemoteConnection.getService(IUserAuthenticatorService.class); - if (authService != null) { - PasswordAuthentication auth = authService.prompt(getUsername(), message); - if (auth == null) { - return false; - } - IRemoteConnectionWorkingCopy wc = fRemoteConnection.getWorkingCopy(); - wc.setAttribute(USERNAME_ATTR, auth.getUserName()); - wc.setSecureAttribute(PASSWORD_ATTR, new String(auth.getPassword())); - try { - wc.save(); - } catch (RemoteConnectionException e) { - Activator.log(e.getStatus()); - } - return true; - } - return false; - } - - /* - * (non-Javadoc) - * - * @see com.jcraft.jsch.UserInfo#promptYesNo(java.lang.String) - */ - @Override - public boolean promptYesNo(String message) { - if (logging) { - System.out.println("promptYesNo:" + message); //$NON-NLS-1$ - } - IUserAuthenticatorService authService = fRemoteConnection.getService(IUserAuthenticatorService.class); - if (authService != null) { - int prompt = authService.prompt(IUserAuthenticatorService.QUESTION, Messages.AuthInfo_Authentication_message, - message, new int[] { IUserAuthenticatorService.YES, IUserAuthenticatorService.NO }, - IUserAuthenticatorService.YES); - return prompt == IUserAuthenticatorService.YES; - } - return true; - } - - /* - * (non-Javadoc) - * - * @see com.jcraft.jsch.UserInfo#showMessage(java.lang.String) - */ - @Override - public void showMessage(String message) { - if (logging) { - System.out.println("showMessage:" + message); //$NON-NLS-1$ - } - IUserAuthenticatorService authService = fRemoteConnection.getService(IUserAuthenticatorService.class); - if (authService != null) { - authService.prompt(IUserAuthenticatorService.INFORMATION, Messages.AuthInfo_Authentication_message, message, - new int[] { IUserAuthenticatorService.OK }, IUserAuthenticatorService.OK); - } - } - } - - private final boolean logging = false; - public static final int DEFAULT_PORT = 22; public static final int DEFAULT_TIMEOUT = 0; public static final boolean DEFAULT_IS_PASSWORD = false; @@ -789,7 +617,7 @@ public class JSchConnection implements IRemoteConnectionControlService, IRemoteC return hasOpenSession() && isFullySetup; } - public boolean isPasswordAuth() { + public boolean usePassword() { String str = fRemoteConnection.getAttribute(IS_PASSWORD_ATTR); return !str.isEmpty() ? Boolean.parseBoolean(str) : DEFAULT_IS_PASSWORD; } @@ -925,14 +753,17 @@ public class JSchConnection implements IRemoteConnectionControlService, IRemoteC private Session newSession(IProgressMonitor monitor) throws RemoteConnectionException { SubMonitor progress = SubMonitor.convert(monitor, 10); try { - Session session = fJSchService.createSession(getHostname(), getPort(), getUsername()); - session.setUserInfo(new JSchUserInfo()); - if (isPasswordAuth()) { + IRemoteConnectionWorkingCopy wc = getRemoteConnection().getWorkingCopy(); + IRemoteConnectionHostService hostService = wc.getService(IRemoteConnectionHostService.class); + IUserAuthenticatorService authService = wc.getService(IUserAuthenticatorService.class); + Session session = fJSchService.createSession(hostService.getHostname(), hostService.getPort(), hostService.getUsername()); + session.setUserInfo(new JSchUserInfo(hostService, authService)); + if (hostService.usePassword()) { session.setConfig("PreferredAuthentications", "password,keyboard-interactive,gssapi-with-mic,publickey"); //$NON-NLS-1$ //$NON-NLS-2$ } else { session.setConfig("PreferredAuthentications", "publickey,gssapi-with-mic,password,keyboard-interactive"); //$NON-NLS-1$ //$NON-NLS-2$ } - String password = getPassword(); + String password = hostService.getPassword(); if (!password.isEmpty()) { session.setPassword(password); } @@ -948,11 +779,12 @@ public class JSchConnection implements IRemoteConnectionControlService, IRemoteC session.connect(getTimeout() * 1000); // the fJSchService doesn't pass the timeout correctly } } - if (!progress.isCanceled()) { - fSessions.add(session); - return session; + if (progress.isCanceled()) { + return null; } - return null; + wc.save(); + fSessions.add(session); + return session; } catch (OperationCanceledException e) { throw new RemoteConnectionException(Messages.JSchConnection_0); } catch (JSchException e) { diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchUserInfo.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchUserInfo.java new file mode 100644 index 00000000000..3ab7bd6e5bb --- /dev/null +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchUserInfo.java @@ -0,0 +1,179 @@ +/******************************************************************************* + * Copyright (c) 2007, 2015 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - Initial API and implementation + * Patrick Tasse - [462418] use stored password on non-preferred password based authentication + * Martin Oberhuber - [468889] Support Eclipse older than Mars + *******************************************************************************/ +package org.eclipse.remote.internal.jsch.core; + +import java.net.PasswordAuthentication; + +import org.eclipse.remote.core.IRemoteConnectionHostService; +import org.eclipse.remote.core.IUserAuthenticatorService; +import org.eclipse.remote.internal.jsch.core.messages.Messages; + +import com.jcraft.jsch.UIKeyboardInteractive; +import com.jcraft.jsch.UserInfo; + +/** + * Class to supply credentials from connection attributes without user interaction. + */ +public class JSchUserInfo implements UserInfo, UIKeyboardInteractive { + private boolean logging = false; + private boolean firstTryPassphrase = true; + + private final IRemoteConnectionHostService hostService; + private IUserAuthenticatorService userAuthenticatorService; + + public JSchUserInfo(IRemoteConnectionHostService hostService) { + this.hostService = hostService; + } + + public JSchUserInfo(IRemoteConnectionHostService hostService, IUserAuthenticatorService userAuthenticatorService) { + this(hostService); + this.userAuthenticatorService = userAuthenticatorService; + } + + /* + * (non-Javadoc) + * + * @see com.jcraft.jsch.UserInfo#getPassphrase() + */ + @Override + public String getPassphrase() { + if (logging) { + System.out.println("getPassphrase"); //$NON-NLS-1$ + } + return hostService.getPassphrase(); + } + + /* + * (non-Javadoc) + * + * @see com.jcraft.jsch.UserInfo#getPassword() + */ + @Override + public String getPassword() { + if (logging) { + System.out.println("getPassword"); //$NON-NLS-1$ + } + return hostService.getPassword(); + } + + /* + * (non-Javadoc) + * + * @see com.jcraft.jsch.UIKeyboardInteractive#promptKeyboardInteractive(java.lang.String, java.lang.String, + * java.lang.String, java.lang.String[], boolean[]) + */ + @Override + public String[] promptKeyboardInteractive(String destination, String name, String instruction, String[] prompt, + boolean[] echo) { + if (logging) { + System.out.println("promptKeyboardInteractive:" + destination + ":" + name + ":" + instruction); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + for (String p : prompt) { + System.out.println(" " + p); //$NON-NLS-1$ + } + } + + if (userAuthenticatorService != null) { + String[] result = userAuthenticatorService.prompt(destination, name, instruction, prompt, echo); + if (result != null) { + if (prompt.length == 1 && prompt[0].trim().equalsIgnoreCase("password:")) { //$NON-NLS-1$ + hostService.setPassword(result[0]); + } + } + return result; + } + return null; + } + + /* + * (non-Javadoc) + * + * @see com.jcraft.jsch.UserInfo#promptPassphrase(java.lang.String) + */ + @Override + public boolean promptPassphrase(String message) { + if (logging) { + System.out.println("promptPassphrase:" + message); //$NON-NLS-1$ + } + if (firstTryPassphrase && !getPassphrase().equals("")) { //$NON-NLS-1$ + firstTryPassphrase = false; + return true; + } + if (userAuthenticatorService != null) { + PasswordAuthentication auth = userAuthenticatorService.prompt(hostService.getUsername(), message); + if (auth == null) { + return false; + } + hostService.setUsername(auth.getUserName()); + hostService.setPassphrase(new String(auth.getPassword())); + return true; + } + return false; + } + + /* + * (non-Javadoc) + * + * @see com.jcraft.jsch.UserInfo#promptPassword(java.lang.String) + */ + @Override + public boolean promptPassword(String message) { + if (logging) { + System.out.println("promptPassword:" + message); //$NON-NLS-1$ + } + if (userAuthenticatorService != null) { + PasswordAuthentication auth = userAuthenticatorService.prompt(hostService.getUsername(), message); + if (auth == null) { + return false; + } + hostService.setUsername(auth.getUserName()); + hostService.setPassword(new String(auth.getPassword())); + return true; + } + return false; + } + + /* + * (non-Javadoc) + * + * @see com.jcraft.jsch.UserInfo#promptYesNo(java.lang.String) + */ + @Override + public boolean promptYesNo(String message) { + if (logging) { + System.out.println("promptYesNo:" + message); //$NON-NLS-1$ + } + if (userAuthenticatorService != null) { + int prompt = userAuthenticatorService.prompt(IUserAuthenticatorService.QUESTION, Messages.AuthInfo_Authentication_message, + message, new int[] { IUserAuthenticatorService.YES, IUserAuthenticatorService.NO }, + IUserAuthenticatorService.YES); + return prompt == IUserAuthenticatorService.YES; + } + return true; + } + + /* + * (non-Javadoc) + * + * @see com.jcraft.jsch.UserInfo#showMessage(java.lang.String) + */ + @Override + public void showMessage(String message) { + if (logging) { + System.out.println("showMessage:" + message); //$NON-NLS-1$ + } + if (userAuthenticatorService != null) { + userAuthenticatorService.prompt(IUserAuthenticatorService.INFORMATION, Messages.AuthInfo_Authentication_message, message, + new int[] { IUserAuthenticatorService.OK }, IUserAuthenticatorService.OK); + } + } +} diff --git a/bundles/org.eclipse.remote.telnet.core/src/org/eclipse/remote/telnet/core/TelnetConnection.java b/bundles/org.eclipse.remote.telnet.core/src/org/eclipse/remote/telnet/core/TelnetConnection.java index c1e37101978..bf2a81fa289 100644 --- a/bundles/org.eclipse.remote.telnet.core/src/org/eclipse/remote/telnet/core/TelnetConnection.java +++ b/bundles/org.eclipse.remote.telnet.core/src/org/eclipse/remote/telnet/core/TelnetConnection.java @@ -208,4 +208,19 @@ public class TelnetConnection implements IRemoteConnectionControlService, IRemot protected void terminated(TelnetCommandShell shell) { shells.remove(shell); } + + @Override + public String getPassphrase() { + return ""; //$NON-NLS-1$ + } + + @Override + public String getPassword() { + return remoteConnection.getSecureAttribute(PASSWORD_ATTR); + } + + @Override + public boolean usePassword() { + return true; + } }