1 12 package org.eclipse.team.internal.ccvs.ssh2; 13 14 import java.util.Enumeration ; 15 16 import org.eclipse.core.runtime.IProgressMonitor; 17 import org.eclipse.core.runtime.OperationCanceledException; 18 import org.eclipse.jsch.core.IJSchService; 19 import org.eclipse.team.internal.ccvs.core.*; 20 import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation; 21 22 import com.jcraft.jsch.*; 23 24 class JSchSession { 25 private static final int SSH_DEFAULT_PORT = 22; 26 private static JSch jsch=new JSch(); 27 private static java.util.Hashtable pool = new java.util.Hashtable (); 28 29 private final Session session; 30 private final UserInfo prompter; 31 private final ICVSRepositoryLocation location; 32 33 protected static int getCVSTimeoutInMillis() { 34 return 60000; 38 } 39 40 43 private static class UserInfoTimer implements UserInfo, UIKeyboardInteractive { 44 45 private UserInfo wrappedInfo; 46 private long startTime; 47 private long endTime; 48 private boolean prompting; 49 50 public UserInfoTimer(UserInfo wrappedInfo) { 51 this.wrappedInfo = wrappedInfo; 52 } 53 54 private synchronized void startTimer() { 55 prompting = true; 56 startTime = System.currentTimeMillis(); 57 } 58 59 private synchronized void endTimer() { 60 prompting = false; 61 endTime = System.currentTimeMillis(); 62 } 63 64 public long getLastDuration() { 65 return Math.max(0, endTime-startTime); 66 } 67 68 public boolean hasPromptExceededTimeout() { 69 if (!isPrompting()) { 70 return getLastDuration() > getCVSTimeoutInMillis(); 71 } 72 return false; 73 } 74 75 public String getPassphrase() { 76 return wrappedInfo.getPassphrase(); 77 } 78 79 public String getPassword() { 80 return wrappedInfo.getPassword(); 81 } 82 83 public boolean promptPassword(String arg0) { 84 try { 85 startTimer(); 86 return wrappedInfo.promptPassword(arg0); 87 } finally { 88 endTimer(); 89 } 90 } 91 92 public boolean promptPassphrase(String arg0) { 93 try { 94 startTimer(); 95 return wrappedInfo.promptPassphrase(arg0); 96 } finally { 97 endTimer(); 98 } 99 } 100 101 public boolean promptYesNo(String arg0) { 102 try { 103 startTimer(); 104 return wrappedInfo.promptYesNo(arg0); 105 } finally { 106 endTimer(); 107 } 108 } 109 110 public void showMessage(String arg0) { 111 if(arg0.length()!=0){ 112 try { 113 startTimer(); 114 wrappedInfo.showMessage(arg0); 115 } finally { 116 endTimer(); 117 } 118 } 119 } 120 121 public String [] promptKeyboardInteractive(String arg0, String arg1, String arg2, String [] arg3, boolean[] arg4) { 122 try { 123 startTimer(); 124 return ((UIKeyboardInteractive)wrappedInfo).promptKeyboardInteractive(arg0, arg1, arg2, arg3, arg4); 125 } finally { 126 endTimer(); 127 } 128 } 129 130 public boolean isPrompting() { 131 return prompting; 132 } 133 } 134 135 139 private static class MyUserInfo implements UserInfo, UIKeyboardInteractive { 140 private String username; 141 private String password; 142 private String passphrase; 143 private ICVSRepositoryLocation location; 144 private IUserAuthenticator authenticator; 145 private int attemptCount; 146 private boolean passwordChanged; 147 148 MyUserInfo(String username, String password, ICVSRepositoryLocation location) { 149 this.location = location; 150 this.username = username; 151 this.password = password; 152 ICVSRepositoryLocation _location=location; 153 if(_location==null){ 154 String dummy=":extssh:dummy@dummy:/"; try{ 156 _location=CVSRepositoryLocation.fromString(dummy); 157 } 158 catch(CVSException e){ 159 } 160 } 161 authenticator = _location.getUserAuthenticator(); 162 163 } 164 public String getPassword() { 165 return password; 166 } 167 public String getPassphrase() { 168 return passphrase; 169 } 170 public boolean promptYesNo(String str) { 171 int prompt = authenticator.prompt( 172 location, 173 IUserAuthenticator.QUESTION, 174 CVSSSH2Messages.JSchSession_5, 175 str, 176 new int[] {IUserAuthenticator.YES_ID, IUserAuthenticator.NO_ID}, 177 0 ); 179 return prompt == 0; 180 } 181 private String promptSecret(String message, boolean includeLocation) throws CVSException{ 182 final String [] _password = new String [1]; 183 IUserInfo info = new IUserInfo() { 184 public String getUsername() { 185 return username; 186 } 187 public boolean isUsernameMutable() { 188 return false; 189 } 190 public void setPassword(String password) { 191 _password[0] = password; 192 } 193 public void setUsername(String username) { 194 } 195 }; 196 try{ 197 authenticator.promptForUserInfo(includeLocation ? location : null, info, message); 198 } 199 catch(OperationCanceledException e){ 200 _password[0]=null; 201 } 202 return _password[0]; 203 } 204 public boolean promptPassphrase(String message) { 205 try{ 206 String _passphrase=promptSecret(message, false); 207 if(_passphrase!=null){ 208 passphrase=_passphrase; 209 } 210 return _passphrase!=null; 211 } 212 catch(CVSException e){ 213 return false; 214 } 215 } 216 public boolean promptPassword(String message) { 217 try{ 218 String _password=promptSecret(message, true); 219 if(_password!=null){ 220 password=_password; 221 if(location!=null) 223 ((CVSRepositoryLocation)location).setPassword(password); 224 } 225 return _password!=null; 226 } 227 catch(CVSException e){ 228 return false; 229 } 230 } 231 public void showMessage(String message) { 232 authenticator.prompt( 233 location, 234 IUserAuthenticator.INFORMATION, 235 CVSSSH2Messages.JSchSession_5, 236 message, 237 new int[] {IUserAuthenticator.OK_ID}, 238 IUserAuthenticator.OK_ID 239 ); 240 241 } 242 public String [] promptKeyboardInteractive(String destination, 243 String name, 244 String instruction, 245 String [] prompt, 246 boolean[] echo){ 247 if (prompt.length == 0) { 248 return new String [0]; 250 } 251 try{ 252 if (attemptCount == 0 && password != null && prompt.length == 1 && prompt[0].trim().equalsIgnoreCase("password:")) { attemptCount++; 255 return new String [] { password }; 256 } 257 String [] result= 258 authenticator.promptForKeyboradInteractive(location, 259 destination, 260 name, 261 instruction, 262 prompt, 263 echo); 264 if (result == null) 265 return null; if (result.length == 1 && prompt.length == 1 && prompt[0].trim().equalsIgnoreCase("password:")) { password = result[0]; 268 passwordChanged = true; 269 } 270 attemptCount++; 271 return result; 272 } 273 catch(OperationCanceledException e){ 274 return null; 275 } 276 catch(CVSException e){ 277 return null; 278 } 279 } 280 281 284 public void aboutToConnect() { 285 attemptCount = 0; 286 passwordChanged = false; 287 } 288 289 292 public void connectionMade() { 293 attemptCount = 0; 294 if (passwordChanged && password != null && location != null) { 295 location.setPassword(password); 297 } 298 } 299 } 300 301 public static boolean isAuthenticationFailure(JSchException ee) { 302 return ee.getMessage().equals("Auth fail"); } 304 305 static JSchSession getSession(ICVSRepositoryLocation location, String username, String password, String hostname, int port, IProgressMonitor monitor) throws JSchException { 306 307 if (port == ICVSRepositoryLocation.USE_DEFAULT_PORT) 308 port = getPort(location); 309 310 String key = getPoolKey(username, hostname, port); 311 312 try { 313 JSchSession jschSession = (JSchSession) pool.get(key); 314 if (jschSession != null && !jschSession.getSession().isConnected()) { 315 pool.remove(key); 316 jschSession = null; 317 } 318 319 if (jschSession == null) { 320 MyUserInfo ui = new MyUserInfo(username, password, location); 321 UserInfoTimer wrapperUI = new UserInfoTimer(ui); 322 ui.aboutToConnect(); 323 324 Session session = null; 325 try { 326 session = createSession(username, password, hostname, port, wrapperUI, monitor); 327 } catch (JSchException e) { 328 if (isAuthenticationFailure(e) && wrapperUI.hasPromptExceededTimeout()) { 329 session = createSession(username, password, hostname, port, wrapperUI, monitor); 331 } else { 332 throw e; 333 } 334 } 335 if (session == null) 336 throw new JSchException("The JSch service is not available"); 337 ui.connectionMade(); 338 JSchSession schSession = new JSchSession(session, location, wrapperUI); 339 pool.put(key, schSession); 340 return schSession; 341 } 342 return jschSession; 343 } catch (JSchException e) { 344 pool.remove(key); 345 if(e.toString().indexOf("Auth cancel")!=-1){ throw new OperationCanceledException(); 347 } 348 throw e; 349 } 350 } 351 352 private static Session createSession(String username, String password, String hostname, int port, UserInfo wrapperUI, IProgressMonitor monitor) throws JSchException { 353 IJSchService service = CVSSSH2Plugin.getDefault().getJSchService(); 354 if (service == null) 355 return null; 356 Session session = service.createSession(hostname, port, username); 357 session.setTimeout(getCVSTimeoutInMillis()); 358 if (password != null) 359 session.setPassword(password); 360 session.setUserInfo(wrapperUI); 361 service.connect(session, getCVSTimeoutInMillis(), monitor); 362 return session; 363 } 364 365 private static String getPoolKey(String username, String hostname, int port) { 366 return username + "@" + hostname + ":" + port; } 368 369 private static String getPoolKey(ICVSRepositoryLocation location){ 370 return location.getUsername() + "@" + location.getHost() + ":" + getPort(location); } 372 373 private static int getPort(ICVSRepositoryLocation location) { 374 int port = location.getPort(); 375 if (port == ICVSRepositoryLocation.USE_DEFAULT_PORT) 376 port = SSH_DEFAULT_PORT; 377 return port; 378 } 379 380 static void shutdown() { 381 if (jsch != null && pool.size() > 0) { 382 for (Enumeration e = pool.elements(); e.hasMoreElements(); ) { 383 JSchSession session = (JSchSession) (e.nextElement()); 384 try { 385 session.getSession().disconnect(); 386 } catch (Exception ee) { 387 } 388 } 389 pool.clear(); 390 } 391 } 392 static JSch getJSch(){ 393 return jsch; 394 } 395 396 private JSchSession(Session session, ICVSRepositoryLocation location, UserInfo prompter) { 397 this.session = session; 398 this.location = location; 399 this.prompter = prompter; 400 } 401 402 public Session getSession() { 403 return session; 404 } 405 406 public UserInfo getPrompter() { 407 return prompter; 408 } 409 410 public boolean hasPromptExceededTimeout() { 411 if (prompter instanceof UserInfoTimer) { 412 UserInfoTimer timer = (UserInfoTimer) prompter; 413 if (!timer.isPrompting()) { 414 return timer.getLastDuration() > getCVSTimeoutInMillis(); 415 } 416 } 417 return false; 418 } 419 420 public void dispose() { 421 if (session.isConnected()) { 422 session.disconnect(); 423 } 424 pool.remove(getPoolKey(location)); 425 } 426 427 } 428 | Popular Tags |