All Downloads are FREE. Search and download functionalities are using the official Maven repository.

JSSHTerminal.SSHSession Maven / Gradle / Ivy

The newest version!
package JSSHTerminal;

import com.jcraft.jsch.*;

import javax.swing.*;
import java.io.*;

/**
 * SSH session
 */
public final class SSHSession implements UserInfo {

  private final static int NAGLE_PERIOD = 50; // Nagle period in ms

  private TerminalEmulator terminal = null;
  private JSchSession jschsession = null;
  private JTextField passwordField = new JPasswordField(20);
  private String _password = null;
  private String _command = null;
  private MainPanel _parent;

  private Reader in = null;
  private Writer out = null;
  private ChannelShell channel = null;
  private Thread pumpThread;
  private Thread nagleThread;
  final private char[] inBuffer = new char[65536];
  private int inBufferPos = 0;
  private boolean answerYes = false;
  private boolean x11forwarding = false;
  private int retryCount;
  private int sshPort = 22;

  /**
   * @param parent Parent terminal frame
   * @param width  Width of the terminal. For example, 80.
   * @param height Height of the terminal. For example, 25.
   * @param scrollSize Scrollbar buffer size
   */
  public SSHSession(MainPanel parent, int width, int height, int scrollSize)  {

    _parent = parent;
    terminal = new TerminalEmulator(width, height,scrollSize);
    terminal.reset();
    _parent.repaint();
    retryCount = 0;

    String defaultSSHDir = System.getProperty("user.home") + "/.ssh";

    // Known host
    JSch jSch = JSchSession.getJSch();
    try {
      jSch.setKnownHosts(defaultSSHDir+"/known_hosts");
    } catch (JSchException e) {
      System.out.println("Warning, jSch.setKnownHosts() failed " + e.getMessage());
    }

    // Id Key
    File f = new File(defaultSSHDir+"/id_dsa");
    if(f.exists()) {
      try {
        jSch.addIdentity(f.getAbsolutePath());
      } catch (JSchException e) {
        System.out.println("addIdentity(~/.ssh/id_dsa) " + e.getMessage());
      }
    }

    f = new File(defaultSSHDir+"/id_rsa");
    if(f.exists()) {
      try {
        jSch.addIdentity(f.getAbsolutePath());
      } catch (JSchException e) {
        System.out.println("addIdentity(~/.ssh/id_rsa) " + e.getMessage());
      }
    }

  }

  /**
   * Sets the SSH port
   * @param port Port number
   */
  public void setSshPort(int port) {
    sshPort = port;
  }

  /**
   * Automatically answer yes to question
   * @param enable true to enable, false otherwise
   */
  public void setAnswerYes(boolean enable) {
    answerYes = enable;
  }

  /**
   * Enable X11 forwarding
   * @param enable true to enable, false otherwise
   */
  public void setX11Forwarding(boolean enable) {
    x11forwarding = enable;
  }

  /**
   * Execute the given command
   * @param cmd Command to be executed (Do not add \n at the end)
   */
  public void execCommand(String cmd) throws IOException {
    write(cmd);
    write(TerminalEmulator.getCodeENTER());
  }

  /**
   * Connect to a host using name and password.
   * @param host Host to connect
   * @param user username
   * @param password password (if null, password will be prompted)
   * @throws IOException
   */
  public void connect(String host, String user, String password) throws IOException {

    _password = password;
    try {

      jschsession = JSchSession.getSession(user, null, host, sshPort, this, null);

      // Jump hosts
      /*
      int port = jschsession.getSession().setPortForwardingL(0, "draco1", sshPort);
      JSchSession session2 = JSchSession.getSession("dserver",null,"127.0.0.1",port,this,null);
      channel = (ChannelShell)session2.getSession().openChannel("shell");
      */
      channel = (ChannelShell)jschsession.getSession().openChannel("shell");

      if(x11forwarding) {

        channel.setXForwarding(true);
        Object[] di = getDisplayInfo();
        String x11Host = di[1].toString();
        int x11Port = ((Integer)di[2]).intValue();
        setCookieFromXauth(di);
        jschsession.getSession().setX11Host(x11Host);
        jschsession.getSession().setX11Port(x11Port);
        //System.out.println("X11 forwarding " + x11Host + ":" + (x11Port-6000));

      }

      out = new OutputStreamWriter(channel.getOutputStream());
      in = new InputStreamReader(channel.getInputStream());
      channel.setPtyType("xterm");
      channel.connect();

    } catch (JSchException e) {
      throw new IOException(e.getMessage());
    }

    pumpThread = new Thread(new Runnable() {
      @Override
      public void run() {
        pump();
      }
    });
    pumpThread.start();

    nagleThread = new Thread(new Runnable() {
      @Override
      public void run() {
        naggle();
      }
    });
    nagleThread.start();

  }


  // Returns Display info
  Object[] getDisplayInfo() {

    String display = System.getenv("DISPLAY");
    if(display==null)
      return new Object[]{"localhost:0.0","127.0.0.1",6000};

    String x11Host = "127.0.0.1";
    int x11Port = 6000;

    int commaIdx = display.indexOf(':');
    if (commaIdx >= 0) {

      // :port.display or hostname:port.display
      if(commaIdx!=0) {
        // hostname:port.display
        x11Host = display.substring(0, commaIdx);
      }

      int pointIdx = display.lastIndexOf('.');
      if (pointIdx == -1) pointIdx = display.length();
      String pStr = display.substring(commaIdx + 1, pointIdx);
      try {
        x11Port = 6000 + Integer.parseInt(pStr);
      } catch (NumberFormatException e) {
      }

    }

    return new Object[] {
        display,x11Host,x11Port
    };

  }


  void setCookieFromXauth(Object[] di) {

    if(((Integer)di[2]).intValue()==6000)
      return;

    // We have a forwarded connection, cookie must be set
    try {

      // xauth list $DISPLAY
      // hostname/unix:11  MIT-MAGIC-COOKIE-1  40f02ff3cbdc0c5716b2ebd1611f357e

      String display = di[0].toString();
      String arg;
      if(display.startsWith(":"))
        arg = di[1].toString() + display;
      else
        arg = display;

      Process p = Runtime.getRuntime().exec("xauth list " + arg);
      p.waitFor();

      StringBuffer output = new StringBuffer();
      BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
      String line = reader.readLine();
      if( line!=null ) {
        String[] lines = line.split("  ");
        if(lines.length!=3) {
          System.out.println("Warning, no xauth data :" + line);
          return;
        }
        jschsession.getSession().setX11Cookie(lines[2]);
      } else {
        System.out.println("Warning, no xauth data" );
      }

    } catch (IOException e1) {
      System.out.println("Warning, no xauth data : :" + e1.getMessage());
    } catch (InterruptedException e2) {
      System.out.println("Warning, no xauth data : :" + e2.getMessage());
    }

  }

  public boolean isConnected() {
    return jschsession!=null;
  }

  public void close() {

    if(jschsession!=null) {
      jschsession.dispose();

      try {
        if(pumpThread!=null) pumpThread.join();
        if(nagleThread!=null) nagleThread.join();
      } catch (InterruptedException e) {}
      jschsession = null;
    }

  }


  void write(byte[] buff) throws IOException {

    int len = buff.length;
    char[] cout = new char[len];
    for(int i=0;i0 ) {
          terminal.write(inBuffer,inBufferPos);
          inBufferPos = 0;
          write(terminal.read());
          _parent.repaint();
          _parent.updateScrollBar();
        }
      }
      try {
        Thread.sleep(NAGLE_PERIOD);
      } catch (InterruptedException e) {}

    }

  }

  private void pump() {

    char[] buf = new char[1024];
    int len;

    try {
      try {
        while ((len = in.read(buf)) >= 0) {
          synchronized (inBuffer) {
            if(inBufferPos+len > inBuffer.length) {
              terminal.write(inBuffer,inBufferPos);
              terminal.write(buf,len);
              inBufferPos = 0;
              _parent.updateScrollBar();
              _parent.repaint();
            } else {
              System.arraycopy(buf,0,inBuffer,inBufferPos,len);
              inBufferPos+=len;
            }
          }
        }
      } catch (IOException e) {
        System.out.println(e.getMessage());
      } finally {
        closeQuietly(in);
        closeQuietly(out);
      }
    } catch (Throwable e) {
      e.printStackTrace();
    }

    jschsession = null;
    _parent.exitFrame();

  }


  private void closeQuietly(Closeable c) {

    try {
      if (c != null) c.close();
    } catch (IOException e) {
      // silently ignore
    }

  }

  @Override
  public String getPassphrase() {
    return null;
  }

  @Override
  public String getPassword() {
    retryCount++;
    return _password;
  }

  @Override
  public boolean promptPassword(String message) {

    if(_password!=null && retryCount==0) return true;

    JPanel panel = new JPanel();
    panel.add(passwordField);
    passwordField.requestFocusInWindow();
    JOptionPane pane = new JOptionPane(panel,
        JOptionPane.QUESTION_MESSAGE,
        JOptionPane.OK_CANCEL_OPTION) {
      public void selectInitialValue() {
      }
    };

    JDialog dialog = pane.createDialog(_parent,
        message);
    dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
    dialog.setVisible(true);
    Object o = pane.getValue();

    if (o != null && ((Integer) o).intValue() == JOptionPane.OK_OPTION) {
      _password = passwordField.getText();
      return true;
    } else {
      return false;
    }

  }

  @Override
  public boolean promptPassphrase(String s) {
    return true;
  }

  @Override
  public boolean promptYesNo(String str) {

    if(answerYes)
        return true;

    Object[] options = {"Yes", "No"};
    int ok = JOptionPane.showOptionDialog(_parent, str,
        "Warning", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
        null, options, options[0]);
    return ok == 0;

  }

  @Override
  public void showMessage(String s) {
    JOptionPane.showMessageDialog(_parent, s, "Message", JOptionPane.INFORMATION_MESSAGE);
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy