/* -*-mode:java; c-basic-offset:2; -*- */ /******************************************************************************* * Copyright (c) 2003, Atsuhiko Yamanaka, JCraft,Inc. and others. All rights * reserved. This program and the accompanying materials are made available * under the terms of the Common Public License v1.0 which accompanies this * distribution, and is available at http://www.eclipse.org/legal/cpl-v10.html * * Contributors: Atsuhiko Yamanaka, JCraft,Inc. - initial API and * implementation. ******************************************************************************/ package org.eclipse.team.internal.ccvs.ssh2; import java.io.*; import java.net.Socket; import java.net.UnknownHostException; import java.util.*; import org.eclipse.core.runtime.*; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.team.internal.ccvs.core.*; import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation; import org.eclipse.team.internal.ccvs.core.util.Util; import com.jcraft.jsch.*; class JSchSession { private static final int SSH_DEFAULT_PORT = 22; private static JSch jsch=new JSch(); private static java.util.Hashtable pool = new java.util.Hashtable(); private static String current_ssh_home = null; public static class SimpleSocketFactory implements SocketFactory { InputStream in = null; OutputStream out = null; public Socket createSocket(String host, int port) throws IOException, UnknownHostException { Socket socket = null; socket = new Socket(host, port); return socket; } public InputStream getInputStream(Socket socket) throws IOException { if (in == null) in = socket.getInputStream(); return in; } public OutputStream getOutputStream(Socket socket) throws IOException { if (out == null) out = socket.getOutputStream(); return out; } } public static class ResponsiveSocketFacory extends SimpleSocketFactory { private IProgressMonitor monitor; public ResponsiveSocketFacory(IProgressMonitor monitor) { this.monitor = monitor; } public Socket createSocket(String host, int port) throws IOException, UnknownHostException { Socket socket = null; socket = Util.createSocket(host, port, monitor); // Null out the monitor so we don't hold onto anything // (i.e. the SSH2 session will keep a handle to the socket factory around monitor = new NullProgressMonitor(); // Set the socket timeout socket.setSoTimeout(CVSProviderPlugin.getPlugin().getTimeout() * 1000); return socket; } } /** * User information delegates to the IUserAuthenticator. This allows * headless access to the connection method. */ private static class MyUserInfo implements UserInfo, UIKeyboardInteractive { private String username; private String password; private String passphrase; private ICVSRepositoryLocation location; private IUserAuthenticator authenticator; private int attemptCount; private boolean passwordChanged; MyUserInfo(String username, String password, ICVSRepositoryLocation location) { this.location = location; this.username = username; this.password = password; ICVSRepositoryLocation _location=location; if(_location==null){ String dummy=":extssh:dummy@dummy:/"; //$NON-NLS-1$ try{ _location=CVSRepositoryLocation.fromString(dummy); } catch(CVSException e){ } } authenticator = _location.getUserAuthenticator(); } public String getPassword() { return password; } public String getPassphrase() { return passphrase; } public boolean promptYesNo(String str) { int prompt = authenticator.prompt( location, IUserAuthenticator.QUESTION, Policy.bind("JSchSession.5"), //$NON-NLS-1$ str, new int[] {IUserAuthenticator.YES_ID, IUserAuthenticator.NO_ID}, 0 //yes the default ); return prompt == 0; } private String promptSecret(String message, boolean includeLocation) throws CVSException{ final String[] _password = new String[1]; IUserInfo info = new IUserInfo() { public String getUsername() { return username; } public boolean isUsernameMutable() { return false; } public void setPassword(String password) { _password[0] = password; } public void setUsername(String username) { } }; try{ authenticator.promptForUserInfo(includeLocation ? location : null, info, message); } catch(OperationCanceledException e){ _password[0]=null; } return _password[0]; } public boolean promptPassphrase(String message) { try{ String _passphrase=promptSecret(message, false); if(_passphrase!=null){ passphrase=_passphrase; } return _passphrase!=null; } catch(CVSException e){ return false; } } public boolean promptPassword(String message) { try{ String _password=promptSecret(message, true); if(_password!=null){ password=_password; // Cache the password with the repository location on the memory. if(location!=null) ((CVSRepositoryLocation)location).setPassword(password); } return _password!=null; } catch(CVSException e){ return false; } } public void showMessage(String message) { authenticator.prompt( location, IUserAuthenticator.INFORMATION, Policy.bind("JSchSession.5"), //$NON-NLS-1$ message, new int[] {IUserAuthenticator.OK_ID}, IUserAuthenticator.OK_ID ); } public String[] promptKeyboardInteractive(String destination, String name, String instruction, String[] prompt, boolean[] echo){ if (prompt.length == 0) { // No need to prompt, just return an empty String array return new String[0]; } try{ if (attemptCount == 0 && password != 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 attemptCount++; return new String[] { password }; } String[] result= authenticator.promptForKeyboradInteractive(location, destination, name, instruction, prompt, echo); if (result.length == 1 && prompt.length == 1 && prompt[0].trim().equalsIgnoreCase("password:")) { //$NON-NLS-1$ password = result[0]; passwordChanged = true; } attemptCount++; return result; } catch(OperationCanceledException e){ return null; } catch(CVSException e){ return null; } } /** * Callback to indicate that a connection is about to be attempted */ public void aboutToConnect() { attemptCount = 0; passwordChanged = false; } /** * Callback to indicate that a connection was made */ public void connectionMade() { attemptCount = 0; if (passwordChanged && password != null) { // We were prompted for and returned a password so record it with the location location.setPassword(password); } } } static Session getSession(ICVSRepositoryLocation location, String username, String password, String hostname, int port, SocketFactory socketFactory) throws JSchException { if (port == 0) port = SSH_DEFAULT_PORT; IPreferenceStore store = CVSSSH2Plugin.getDefault().getPreferenceStore(); String ssh_home = store.getString(ISSHContants.KEY_SSH2HOME); if (current_ssh_home == null || !current_ssh_home.equals(ssh_home)) { current_ssh_home = ssh_home; if (ssh_home.length() == 0) ssh_home = CVSSSH2Plugin.SSH_HOME_DEFAULT; try { loadKnownHosts(); java.io.File file; String pkeys=store.getString(ISSHContants.KEY_PRIVATEKEY); String[] pkey=pkeys.split(","); //$NON-NLS-1$ for(int i=0; i 0) { for (Enumeration e = pool.elements(); e.hasMoreElements(); ) { Session session = (Session) (e.nextElement()); try { session.disconnect(); } catch (Exception ee) { } } pool.clear(); } } static JSch getJSch(){ return jsch; } }