sshclient.java

来自「一个非常好的ssh客户端实现」· Java 代码 · 共 1,227 行 · 第 1/3 页

JAVA
1,227
字号
/****************************************************************************** * * Copyright (c) 1999-2003 AppGate Network Security AB. All Rights Reserved. *  * This file contains Original Code and/or Modifications of Original Code as * defined in and that are subject to the MindTerm Public Source License, * Version 2.0, (the 'License'). You may not use this file except in compliance * with the License. *  * You should have received a copy of the MindTerm Public Source License * along with this software; see the file LICENSE.  If not, write to * AppGate Network Security AB, Otterhallegatan 2, SE-41118 Goteborg, SWEDEN * *****************************************************************************/package com.mindbright.ssh;import java.net.*;import java.io.*;import java.math.BigInteger;import java.util.Vector;import com.mindbright.jca.security.MessageDigest;import com.mindbright.jca.security.SignatureException;import com.mindbright.jca.security.interfaces.RSAPublicKey;import com.mindbright.jca.security.interfaces.RSAPrivateCrtKey;import com.mindbright.security.publickey.RSAAlgorithm;import com.mindbright.util.SecureRandomAndPad;import com.mindbright.terminal.*;/** * This class contains the main functionality for setting up a connection to a * ssh-server. It can be used both to implement a "full" ssh-client, or it can * be used to fire off a singe command on the server (both in a background * thread and in the current-/foreground-thread). A set of properties can be * used to control different aspects of the connection. These are fetched from * an object implementing the <code>SSHClientUser</code>-interface.  The * authentication can be done in different ways, all which is handled through an * object implementing the <code>SSHAuthenticator</code>-interface. The * console-output of the <code>SSHClient</code> is (optionally) handled through * an object implementing the <code>SSHConsole</code>-interface.  <p> * * A class realizing a full interactive ssh-client is * <code>SSHInteractiveClient</code>. The <code>SSHClient</code>-class * is also used transparently from the <code>SSHSocket</code>- and <code>SSHServerSocket</code>- * classes (through the <code>SSHSocketFactory</code>- and  <code>SSHSocketImpl</code>-classes). * * @author  Mats Andersson * @version 0.96, 26/11/98 * @see     SSHAuthenticator * @see     SSHClientUser * @see     SSHConsole  */public class SSHClient extends SSH {  static public class AuthFailException extends IOException {    public AuthFailException(String msg) {      super(msg);    }    public AuthFailException() {      this("permission denied");    }  }  static public class ExitMonitor implements Runnable {    SSHClient client;    long      msTimeout;    public ExitMonitor(SSHClient client, long msTimeout) {      this.msTimeout  = msTimeout;      this.client     = client;    }    public ExitMonitor(SSHClient client) {      this(client, 0);    }    public void run() {      client.waitForExit(msTimeout);      // If we have allready exited gracefully don't report...      //      if(!client.gracefulExit)	client.disconnect(false);    }  }  private class KeepAliveThread extends Thread {      int interval;      public KeepAliveThread(int i) {	  super("SSH1KeepAlive");	  interval = i;      }      public synchronized void setInterval(int i) {	  interval = i;      }      public void run() {	  int i;	  SSHPduOutputStream ignmsg;	  while(true) {	      try {		  synchronized(this) {		      i = interval;		  }		  sleep(1000 * i);		  if(SSHClient.this.controller != null) {		      ignmsg = new SSHPduOutputStream(MSG_DEBUG,						      controller.sndCipher,						      controller.sndComp,						      rand);		      ignmsg.writeString("heartbeat");		      controller.transmit(ignmsg);		  }	      } catch (Exception e) {		  // !!!	      }	  }      }  }  // Local port forwarding  //  public static class LocalForward {    protected String localHost;    protected int    localPort;    protected String remoteHost;    protected int    remotePort;    protected String plugin;    public LocalForward(String localHost, int localPort, String remoteHost, int remotePort, String plugin) {      this.localHost  = localHost;      this.localPort  = localPort;      this.remoteHost = remoteHost;      this.remotePort = remotePort;      this.plugin     = plugin;    }  }  // Remote port forwarding  //  public static class RemoteForward {    protected int    remotePort;    protected String localHost;    protected int    localPort;    protected String plugin;    public RemoteForward(int remotePort, String localHost, int localPort, String plugin) {      this.remotePort = remotePort;      this.localHost  = localHost;      this.localPort  = localPort;      this.plugin     = plugin;    }  }  protected Thread             myThread;  protected KeepAliveThread    keepAliveThread;  protected SecureRandomAndPad rand;  protected InetAddress serverAddr;  protected InetAddress serverRealAddr = null;  protected InetAddress localAddr;  protected String      srvVersionStr;  protected int         srvVersionMajor;  protected int         srvVersionMinor;  protected Vector localForwards;  protected Vector remoteForwards;  protected String commandLine;  protected SSHChannelController controller;  protected SSHConsole           console;  protected SSHAuthenticator     authenticator;  protected SSHClientUser        user;  protected SSHInteractor        interactor;  protected Socket               sshSocket;  protected BufferedInputStream  sshIn;  protected BufferedOutputStream sshOut;  protected boolean gracefulExit;  protected boolean isConnected;  protected boolean isOpened;  boolean usedOTP;  protected int refCount;  // !!! KLUDGE  protected boolean havePORTFtp     = false;  protected int     firstFTPPort    = 0;  protected boolean activateTunnels = true;  // !!! KLUDGE  public SSHClient(SSHAuthenticator authenticator, SSHClientUser user) {    this.user           = user;    this.authenticator  = authenticator;    this.interactor     = user.getInteractor();    this.srvVersionStr  = null;    this.refCount       = 0;    this.usedOTP        = false;    try {	this.localAddr = InetAddress.getByName("0.0.0.0");    } catch (UnknownHostException e) {	if(interactor != null)	    interactor.alert("FATAL: Could not create local InetAddress: " + e.getMessage());    }    clearAllForwards();  }  public void setConsole(SSHConsole console) {    this.console = console;    if(controller != null)      controller.console = console;  }  public SSHConsole getConsole() {    return console;  }  public InetAddress getServerAddr() {    return serverAddr;  }  public InetAddress getServerRealAddr() {    if(serverRealAddr == null)      return serverAddr;    return serverRealAddr;  }  public void setServerRealAddr(InetAddress realAddr) {    serverRealAddr = realAddr;  }  public InetAddress getLocalAddr() {    return localAddr;  }  public void setLocalAddr(String addr) throws UnknownHostException {    localAddr = InetAddress.getByName(addr);  }  public String getServerVersion() {    return srvVersionStr;  }  public void addLocalPortForward(int localPort, String remoteHost, int remotePort, String plugin)    throws IOException {    addLocalPortForward(localAddr.getHostAddress(), localPort, remoteHost, remotePort, plugin);  }  public void addLocalPortForward(String localHost, int localPort, String remoteHost, int remotePort, String plugin)    throws IOException {    delLocalPortForward(localHost, localPort);    localForwards.addElement(new LocalForward(localHost, localPort, remoteHost, remotePort, plugin));    if(isOpened) {      try {	requestLocalPortForward(localHost, localPort, remoteHost, remotePort, plugin);      } catch(IOException e) {	delLocalPortForward(localHost, localPort);	throw e;      }    }  }  public void delLocalPortForward(String localHost, int port) {    if(port == -1) {      if(isOpened)	controller.killListenChannels();      localForwards = new Vector();    } else {      for(int i = 0; i < localForwards.size(); i++) {	LocalForward fwd = (LocalForward) localForwards.elementAt(i);	if(fwd.localPort == port && fwd.localHost.equals(localHost)) {	  localForwards.removeElementAt(i);	  if(isOpened)	    controller.killListenChannel(fwd.localHost, fwd.localPort);	  break;	}      }    }  }  public void addRemotePortForward(int remotePort, String localHost, int localPort, String plugin) {    delRemotePortForward(remotePort);    remoteForwards.addElement(new RemoteForward(remotePort, localHost, localPort, plugin));  }  public void delRemotePortForward(int port) {    if(port == -1) {      remoteForwards = new Vector();    } else {      for(int i = 0; i < remoteForwards.size(); i++) {	RemoteForward fwd = (RemoteForward) remoteForwards.elementAt(i);	if(fwd.remotePort == port) {	  remoteForwards.removeElementAt(i);	  break;	}      }    }  }  public void delRemotePortForward(String plugin) {    for(int i = 0; i < remoteForwards.size(); i++) {      RemoteForward fwd = (RemoteForward) remoteForwards.elementAt(i);      if(fwd.plugin.equals(plugin)) {        remoteForwards.removeElementAt(i);	i--;      }    }  }  public void clearAllForwards() {    this.localForwards  = new Vector();    this.remoteForwards = new Vector();  }  public void startExitMonitor() {    startExitMonitor(0);  }  public void startExitMonitor(long msTimeout) {      Thread t = new Thread(new ExitMonitor(this, msTimeout));      t.setName("ExitMonitor");      t.start();  }  public synchronized int addRef() {    return ++refCount;  }  public void forcedDisconnect() {      if(controller != null) {          controller.sendDisconnect("exit");          controller.killAll();      } else if (interactor != null) {          interactor.disconnected(this, false);      }  }  public synchronized int delRef() {    if(--refCount <= 0) {      forcedDisconnect();      waitForExit(2000);    }    return refCount;  }  public void waitForExit(long msTimeout) {    try {      controller.waitForExit(msTimeout);    } catch(InterruptedException e) {      if(interactor != null)	  interactor.alert("Error when shutting down SSHClient: " + e.getMessage());      controller.killAll();    }    try {      if(sshSocket != null)	sshSocket.close();    } catch (IOException e) {      // !!!    }  }  public void doSingleCommand(String commandLine, boolean background, long msTimeout)    throws IOException {    this.commandLine = commandLine;    bootSSH(false);    if(background)      startExitMonitor(msTimeout);    else      waitForExit(msTimeout);  }  public void bootSSH(boolean haveCnxWatch) throws IOException {      bootSSH(haveCnxWatch, false);  }  public void bootSSH(boolean haveCnxWatch, boolean releaseConnection) throws IOException {    try {      myThread = Thread.currentThread();      rand = secureRandom();      // Give the interactor a chance to hold us until the user wants to      // "connect" (e.g. with a dialog with server, username, password,      // proxy-info)      //      if(interactor != null)	  interactor.startNewSession(this);      // We first ask for the ssh server address since this might      // typically be a prompt in the SSHClientUser      //      String serverAddrStr = user.getSrvHost();      // When the SSHClientUser has reported which host to connect to we report      // this to the interactor as sessionStarted      //      if(interactor != null)	  interactor.sessionStarted(this);      // It's the responsibility of the SSHClientUser to establish a proxied      // connection if that is needed, the SSHClient does not want to know about      // proxies. If a proxy is not needed getProxyConnection() just returns      // null.      //      sshSocket = user.getProxyConnection();      if(sshSocket == null) {	  serverAddr = InetAddress.getByName(serverAddrStr);	  sshSocket  = new Socket(serverAddr, user.getSrvPort());      } else {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?