blob: 482ee292dd2c80dbc22ae9909c35407c6fc0d9a6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Atsuhiko Yamanaka, JCraft,Inc. - initial API and implementation.
* IBM Corporation - ongoing maintenance
* Atsuhiko Yamanaka, JCraft,Inc. - copying this class from o.e.team.cvs.ssh2.JSchSession.
*******************************************************************************/
package org.eclipse.jsch.internal.core;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jsch.core.IJSchLocation;
import com.jcraft.jsch.UIKeyboardInteractive;
/**
* User information delegates to the IUserAuthenticator. This allows
* head-less access to the connection method.
* @since 1.1
*/
class UserInfoImpl implements com.jcraft.jsch.UserInfo, UIKeyboardInteractive{
private String username;
private String password;
private String passphrase;
private IJSchLocation location;
private IUserAuthenticator authenticator;
private int attemptCount;
private boolean passwordChanged;
private long startTime;
private long endTime;
private boolean prompting;
private long timeout;
private int reuse=0;
UserInfoImpl(IJSchLocation location, IUserAuthenticator authenticator, long timeout){
this.location=location;
this.username=location.getUsername();
this.password=location.getPassword();
this.authenticator=authenticator;
this.timeout=timeout;
}
@Override
public String getPassword(){
return password;
}
@Override
public String getPassphrase(){
return passphrase;
}
@Override
public boolean promptYesNo(String str){
int prompt=authenticator.prompt(location, IUserAuthenticator.QUESTION,
Messages.JSchSession_5, str, new int[] {IUserAuthenticator.YES_ID,
IUserAuthenticator.NO_ID}, 0 //yes the default
);
return prompt==0;
}
private String promptSecret(String message, boolean includeLocation){
final String[] _password=new String[1];
final String username=location.getUsername();
IUserInfo info=new IUserInfo(){
@Override
public String getUsername(){
return username;
}
@Override
public boolean isUsernameMutable(){
return false;
}
@Override
public void setPassword(String password){
_password[0]=password;
}
@Override
public void setUsername(String username){
//
}
};
try{
authenticator.promptForUserInfo(includeLocation ? location : null,
info, message);
}
catch(OperationCanceledException e){
_password[0]=null;
}
return _password[0];
}
@Override
public boolean promptPassphrase(String message){
try{
startTimer();
String _passphrase=promptSecret(message, false);
if(_passphrase!=null){
passphrase=_passphrase;
}
return _passphrase!=null;
}
catch(OperationCanceledException e){
// The prompt was canceled, but the next authentication
// method should be tried.
return false;
}
finally{
endTimer();
}
}
@Override
public boolean promptPassword(String message){
try{
startTimer();
String _password=promptSecret(message, true);
if(_password!=null){
password=_password;
// Cache the password with the repository location on the memory.
if(location!=null)
location.setPassword(password);
}
return _password!=null;
}
finally{
endTimer();
}
}
@Override
public void showMessage(String message){
authenticator.prompt(location, IUserAuthenticator.INFORMATION,
Messages.JSchSession_5, message,
new int[] {IUserAuthenticator.OK_ID}, IUserAuthenticator.OK_ID);
}
@Override
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{
startTimer();
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==null)
return null; // canceled
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;
}
finally{
endTimer();
}
}
/**
* 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&&location!=null){
// We were prompted for and returned a password so record it with the location
location.setPassword(password);
}
}
private synchronized void startTimer(){
prompting=true;
startTime=System.currentTimeMillis();
}
private synchronized void endTimer(){
prompting=false;
endTime=System.currentTimeMillis();
}
public long getLastDuration(){
return Math.max(0, endTime-startTime);
}
public boolean hasPromptExceededTimeout(){
if(!isPrompting()){
return getLastDuration()>timeout;
}
return false;
}
public boolean isPrompting(){
return prompting;
}
public synchronized int incReuse(){
return reuse++;
}
String getUsername(){
return username;
}
}