148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood/* 248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Please refer to the LICENSE.txt for licensing details. 448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.awt.BorderLayout; 648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.awt.Color; 748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.awt.FlowLayout; 848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.awt.Font; 948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.awt.event.ActionEvent; 1048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.awt.event.ActionListener; 1148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.awt.event.KeyAdapter; 1248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.awt.event.KeyEvent; 1348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.io.File; 1448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.io.IOException; 1548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.io.InputStream; 1648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport java.io.OutputStream; 1748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 1848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport javax.swing.BoxLayout; 1948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport javax.swing.JButton; 2048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport javax.swing.JDialog; 2148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport javax.swing.JFrame; 2248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport javax.swing.JLabel; 2348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport javax.swing.JOptionPane; 2448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport javax.swing.JPanel; 2548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport javax.swing.JPasswordField; 2648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport javax.swing.JTextArea; 2748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport javax.swing.JTextField; 2848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport javax.swing.SwingUtilities; 2948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 3048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.Connection; 3148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.InteractiveCallback; 3248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.KnownHosts; 3348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.ServerHostKeyVerifier; 3448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodimport ch.ethz.ssh2.Session; 3548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 3648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood/** 3748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 3848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * This is a very primitive SSH-2 dumb terminal (Swing based). 3948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 4048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * The purpose of this class is to demonstrate: 4148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 4248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * - Verifying server hostkeys with an existing known_hosts file 4348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * - Displaying fingerprints of server hostkeys 4448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * - Adding a server hostkey to a known_hosts file (+hashing the hostname for security) 4548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * - Authentication with DSA, RSA, password and keyboard-interactive methods 4648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 4748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 4848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodpublic class SwingShell 4948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood{ 5048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 5148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* 5248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * NOTE: to get this feature to work, replace the "tilde" with your home directory, 5348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * at least my JVM does not understand it. Need to check the specs. 5448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 5548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 5648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood static final String knownHostPath = "~/.ssh/known_hosts"; 5748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood static final String idDSAPath = "~/.ssh/id_dsa"; 5848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood static final String idRSAPath = "~/.ssh/id_rsa"; 5948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 6048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood JFrame loginFrame = null; 6148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood JLabel hostLabel; 6248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood JLabel userLabel; 6348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood JTextField hostField; 6448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood JTextField userField; 6548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood JButton loginButton; 6648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 6748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood KnownHosts database = new KnownHosts(); 6848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 6948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public SwingShell() 7048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 7148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood File knownHostFile = new File(knownHostPath); 7248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (knownHostFile.exists()) 7348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 7448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood try 7548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 7648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood database.addHostkeys(knownHostFile); 7748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 7848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood catch (IOException e) 7948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 8048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 8148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 8248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 8348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 8448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 8548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * This dialog displays a number of text lines and a text field. 8648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * The text field can either be plain text or a password field. 8748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 8848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood class EnterSomethingDialog extends JDialog 8948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 9048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private static final long serialVersionUID = 1L; 9148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 9248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood JTextField answerField; 9348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood JPasswordField passwordField; 9448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 9548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final boolean isPassword; 9648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 9748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String answer; 9848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 9948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public EnterSomethingDialog(JFrame parent, String title, String content, boolean isPassword) 10048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 10148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this(parent, title, new String[] { content }, isPassword); 10248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 10348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 10448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public EnterSomethingDialog(JFrame parent, String title, String[] content, boolean isPassword) 10548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 10648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood super(parent, title, true); 10748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 10848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.isPassword = isPassword; 10948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 11048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood JPanel pan = new JPanel(); 11148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood pan.setLayout(new BoxLayout(pan, BoxLayout.Y_AXIS)); 11248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 11348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood for (int i = 0; i < content.length; i++) 11448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 11548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if ((content[i] == null) || (content[i] == "")) 11648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood continue; 11748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood JLabel contentLabel = new JLabel(content[i]); 11848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood pan.add(contentLabel); 11948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 12048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 12148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 12248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood answerField = new JTextField(20); 12348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood passwordField = new JPasswordField(20); 12448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 12548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (isPassword) 12648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood pan.add(passwordField); 12748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood else 12848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood pan.add(answerField); 12948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 13048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood KeyAdapter kl = new KeyAdapter() 13148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 13248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void keyTyped(KeyEvent e) 13348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 13448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (e.getKeyChar() == '\n') 13548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood finish(); 13648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 13748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood }; 13848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 13948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood answerField.addKeyListener(kl); 14048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood passwordField.addKeyListener(kl); 14148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 14248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood getContentPane().add(BorderLayout.CENTER, pan); 14348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 14448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood setResizable(false); 14548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood pack(); 14648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood setLocationRelativeTo(null); 14748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 14848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 14948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private void finish() 15048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 15148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (isPassword) 15248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood answer = new String(passwordField.getPassword()); 15348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood else 15448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood answer = answerField.getText(); 15548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 15648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood dispose(); 15748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 15848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 15948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 16048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 16148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * TerminalDialog is probably the worst terminal emulator ever written - implementing 16248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * a real vt100 is left as an exercise to the reader, i.e., to you =) 16348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 16448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 16548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood class TerminalDialog extends JDialog 16648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 16748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private static final long serialVersionUID = 1L; 16848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 16948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood JPanel botPanel; 17048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood JButton logoffButton; 17148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood JTextArea terminalArea; 17248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 17348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood Session sess; 17448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood InputStream in; 17548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood OutputStream out; 17648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 17748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int x, y; 17848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 17948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 18048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * This thread consumes output from the remote server and displays it in 18148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the terminal window. 18248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 18348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 18448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood class RemoteConsumer extends Thread 18548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 18648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood char[][] lines = new char[y][]; 18748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int posy = 0; 18848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int posx = 0; 18948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 19048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private void addText(byte[] data, int len) 19148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 19248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood for (int i = 0; i < len; i++) 19348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 19448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood char c = (char) (data[i] & 0xff); 19548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 19648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (c == 8) // Backspace, VERASE 19748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 19848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (posx < 0) 19948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood continue; 20048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood posx--; 20148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood continue; 20248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 20348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 20448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (c == '\r') 20548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 20648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood posx = 0; 20748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood continue; 20848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 20948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 21048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (c == '\n') 21148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 21248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood posy++; 21348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (posy >= y) 21448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 21548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood for (int k = 1; k < y; k++) 21648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood lines[k - 1] = lines[k]; 21748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood posy--; 21848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood lines[y - 1] = new char[x]; 21948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood for (int k = 0; k < x; k++) 22048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood lines[y - 1][k] = ' '; 22148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 22248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood continue; 22348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 22448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 22548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (c < 32) 22648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 22748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood continue; 22848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 22948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 23048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (posx >= x) 23148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 23248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood posx = 0; 23348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood posy++; 23448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (posy >= y) 23548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 23648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood posy--; 23748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood for (int k = 1; k < y; k++) 23848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood lines[k - 1] = lines[k]; 23948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood lines[y - 1] = new char[x]; 24048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood for (int k = 0; k < x; k++) 24148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood lines[y - 1][k] = ' '; 24248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 24348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 24448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 24548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (lines[posy] == null) 24648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 24748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood lines[posy] = new char[x]; 24848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood for (int k = 0; k < x; k++) 24948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood lines[posy][k] = ' '; 25048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 25148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 25248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood lines[posy][posx] = c; 25348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood posx++; 25448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 25548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 25648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood StringBuffer sb = new StringBuffer(x * y); 25748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 25848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood for (int i = 0; i < lines.length; i++) 25948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 26048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (i != 0) 26148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood sb.append('\n'); 26248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 26348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (lines[i] != null) 26448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 26548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood sb.append(lines[i]); 26648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 26748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 26848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 26948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood setContent(sb.toString()); 27048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 27148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 27248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void run() 27348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 27448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood byte[] buff = new byte[8192]; 27548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 27648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood try 27748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 27848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood while (true) 27948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 28048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int len = in.read(buff); 28148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (len == -1) 28248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return; 28348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood addText(buff, len); 28448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 28548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 28648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood catch (Exception e) 28748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 28848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 28948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 29048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 29148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 29248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public TerminalDialog(JFrame parent, String title, Session sess, int x, int y) throws IOException 29348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 29448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood super(parent, title, true); 29548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 29648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.sess = sess; 29748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 29848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood in = sess.getStdout(); 29948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood out = sess.getStdin(); 30048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 30148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.x = x; 30248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.y = y; 30348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 30448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood botPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); 30548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 30648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood logoffButton = new JButton("Logout"); 30748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood botPanel.add(logoffButton); 30848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 30948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood logoffButton.addActionListener(new ActionListener() 31048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 31148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void actionPerformed(ActionEvent e) 31248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 31348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Dispose the dialog, "setVisible(true)" method will return */ 31448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood dispose(); 31548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 31648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood }); 31748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 31848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood Font f = new Font("Monospaced", Font.PLAIN, 16); 31948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 32048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood terminalArea = new JTextArea(y, x); 32148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood terminalArea.setFont(f); 32248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood terminalArea.setBackground(Color.BLACK); 32348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood terminalArea.setForeground(Color.ORANGE); 32448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* This is a hack. We cannot disable the caret, 32548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * since setting editable to false also changes 32648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the meaning of the TAB key - and I want to use it in bash. 32748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * Again - this is a simple DEMO terminal =) 32848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 32948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood terminalArea.setCaretColor(Color.BLACK); 33048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 33148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood KeyAdapter kl = new KeyAdapter() 33248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 33348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void keyTyped(KeyEvent e) 33448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 33548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int c = e.getKeyChar(); 33648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 33748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood try 33848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 33948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood out.write(c); 34048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 34148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood catch (IOException e1) 34248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 34348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 34448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood e.consume(); 34548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 34648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood }; 34748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 34848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood terminalArea.addKeyListener(kl); 34948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 35048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood getContentPane().add(terminalArea, BorderLayout.CENTER); 35148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood getContentPane().add(botPanel, BorderLayout.PAGE_END); 35248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 35348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood setResizable(false); 35448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood pack(); 35548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood setLocationRelativeTo(parent); 35648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 35748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood new RemoteConsumer().start(); 35848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 35948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 36048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void setContent(String lines) 36148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 36248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // setText is thread safe, it does not have to be called from 36348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // the Swing GUI thread. 36448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood terminalArea.setText(lines); 36548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 36648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 36748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 36848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 36948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * This ServerHostKeyVerifier asks the user on how to proceed if a key cannot be found 37048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * in the in-memory database. 37148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 37248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 37348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood class AdvancedVerifier implements ServerHostKeyVerifier 37448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 37548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public boolean verifyServerHostKey(String hostname, int port, String serverHostKeyAlgorithm, 37648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood byte[] serverHostKey) throws Exception 37748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 37848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final String host = hostname; 37948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final String algo = serverHostKeyAlgorithm; 38048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 38148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String message; 38248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 38348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Check database */ 38448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 38548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int result = database.verifyHostkey(hostname, serverHostKeyAlgorithm, serverHostKey); 38648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 38748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood switch (result) 38848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 38948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood case KnownHosts.HOSTKEY_IS_OK: 39048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return true; 39148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 39248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood case KnownHosts.HOSTKEY_IS_NEW: 39348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood message = "Do you want to accept the hostkey (type " + algo + ") from " + host + " ?\n"; 39448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood break; 39548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 39648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood case KnownHosts.HOSTKEY_HAS_CHANGED: 39748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood message = "WARNING! Hostkey for " + host + " has changed!\nAccept anyway?\n"; 39848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood break; 39948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 40048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood default: 40148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IllegalStateException(); 40248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 40348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 40448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Include the fingerprints in the message */ 40548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 40648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String hexFingerprint = KnownHosts.createHexFingerprint(serverHostKeyAlgorithm, serverHostKey); 40748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String bubblebabbleFingerprint = KnownHosts.createBubblebabbleFingerprint(serverHostKeyAlgorithm, 40848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood serverHostKey); 40948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 41048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood message += "Hex Fingerprint: " + hexFingerprint + "\nBubblebabble Fingerprint: " + bubblebabbleFingerprint; 41148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 41248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Now ask the user */ 41348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 41448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int choice = JOptionPane.showConfirmDialog(loginFrame, message); 41548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 41648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (choice == JOptionPane.YES_OPTION) 41748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 41848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Be really paranoid. We use a hashed hostname entry */ 41948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 42048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String hashedHostname = KnownHosts.createHashedHostname(hostname); 42148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 42248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Add the hostkey to the in-memory database */ 42348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 42448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood database.addHostkey(new String[] { hashedHostname }, serverHostKeyAlgorithm, serverHostKey); 42548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 42648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Also try to add the key to a known_host file */ 42748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 42848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood try 42948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 43048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood KnownHosts.addHostkeyToFile(new File(knownHostPath), new String[] { hashedHostname }, 43148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood serverHostKeyAlgorithm, serverHostKey); 43248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 43348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood catch (IOException ignore) 43448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 43548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 43648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 43748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return true; 43848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 43948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 44048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (choice == JOptionPane.CANCEL_OPTION) 44148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 44248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new Exception("The user aborted the server hostkey verification."); 44348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 44448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 44548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return false; 44648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 44748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 44848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 44948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 45048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * The logic that one has to implement if "keyboard-interactive" autentication shall be 45148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * supported. 45248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 45348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 45448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood class InteractiveLogic implements InteractiveCallback 45548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 45648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int promptCount = 0; 45748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String lastError; 45848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 45948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public InteractiveLogic(String lastError) 46048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 46148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.lastError = lastError; 46248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 46348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 46448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* the callback may be invoked several times, depending on how many questions-sets the server sends */ 46548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 46648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public String[] replyToChallenge(String name, String instruction, int numPrompts, String[] prompt, 46748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean[] echo) throws IOException 46848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 46948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String[] result = new String[numPrompts]; 47048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 47148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood for (int i = 0; i < numPrompts; i++) 47248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 47348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* Often, servers just send empty strings for "name" and "instruction" */ 47448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 47548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String[] content = new String[] { lastError, name, instruction, prompt[i] }; 47648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 47748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (lastError != null) 47848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 47948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* show lastError only once */ 48048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood lastError = null; 48148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 48248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 48348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood EnterSomethingDialog esd = new EnterSomethingDialog(loginFrame, "Keyboard Interactive Authentication", 48448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood content, !echo[i]); 48548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 48648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood esd.setVisible(true); 48748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 48848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (esd.answer == null) 48948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IOException("Login aborted by user"); 49048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 49148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood result[i] = esd.answer; 49248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood promptCount++; 49348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 49448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 49548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return result; 49648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 49748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 49848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* We maintain a prompt counter - this enables the detection of situations where the ssh 49948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * server is signaling "authentication failed" even though it did not send a single prompt. 50048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 50148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 50248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public int getPromptCount() 50348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 50448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return promptCount; 50548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 50648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 50748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 50848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /** 50948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * The SSH-2 connection is established in this thread. 51048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * If we would not use a separate thread (e.g., put this code in 51148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * the event handler of the "Login" button) then the GUI would not 51248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * be responsive (missing window repaints if you move the window etc.) 51348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 51448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood class ConnectionThread extends Thread 51548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 51648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String hostname; 51748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String username; 51848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 51948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public ConnectionThread(String hostname, String username) 52048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 52148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.hostname = hostname; 52248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood this.username = username; 52348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 52448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 52548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void run() 52648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 52748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood Connection conn = new Connection(hostname); 52848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 52948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood try 53048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 53148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* 53248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 53348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * CONNECT AND VERIFY SERVER HOST KEY (with callback) 53448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 53548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 53648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 53748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String[] hostkeyAlgos = database.getPreferredServerHostkeyAlgorithmOrder(hostname); 53848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 53948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (hostkeyAlgos != null) 54048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood conn.setServerHostKeyAlgorithms(hostkeyAlgos); 54148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 54248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood conn.connect(new AdvancedVerifier()); 54348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 54448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* 54548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 54648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * AUTHENTICATION PHASE 54748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 54848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 54948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 55048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean enableKeyboardInteractive = true; 55148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean enableDSA = true; 55248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean enableRSA = true; 55348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 55448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String lastError = null; 55548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 55648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood while (true) 55748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 55848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if ((enableDSA || enableRSA) && conn.isAuthMethodAvailable(username, "publickey")) 55948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 56048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (enableDSA) 56148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 56248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood File key = new File(idDSAPath); 56348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 56448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (key.exists()) 56548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 56648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood EnterSomethingDialog esd = new EnterSomethingDialog(loginFrame, "DSA Authentication", 56748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood new String[] { lastError, "Enter DSA private key password:" }, true); 56848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood esd.setVisible(true); 56948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 57048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean res = conn.authenticateWithPublicKey(username, key, esd.answer); 57148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 57248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (res == true) 57348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood break; 57448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 57548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood lastError = "DSA authentication failed."; 57648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 57748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood enableDSA = false; // do not try again 57848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 57948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 58048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (enableRSA) 58148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 58248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood File key = new File(idRSAPath); 58348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 58448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (key.exists()) 58548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 58648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood EnterSomethingDialog esd = new EnterSomethingDialog(loginFrame, "RSA Authentication", 58748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood new String[] { lastError, "Enter RSA private key password:" }, true); 58848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood esd.setVisible(true); 58948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 59048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean res = conn.authenticateWithPublicKey(username, key, esd.answer); 59148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 59248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (res == true) 59348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood break; 59448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 59548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood lastError = "RSA authentication failed."; 59648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 59748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood enableRSA = false; // do not try again 59848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 59948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 60048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood continue; 60148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 60248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 60348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (enableKeyboardInteractive && conn.isAuthMethodAvailable(username, "keyboard-interactive")) 60448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 60548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood InteractiveLogic il = new InteractiveLogic(lastError); 60648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 60748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean res = conn.authenticateWithKeyboardInteractive(username, il); 60848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 60948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (res == true) 61048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood break; 61148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 61248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (il.getPromptCount() == 0) 61348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 61448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // aha. the server announced that it supports "keyboard-interactive", but when 61548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // we asked for it, it just denied the request without sending us any prompt. 61648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // That happens with some server versions/configurations. 61748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood // We just disable the "keyboard-interactive" method and notify the user. 61848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 61948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood lastError = "Keyboard-interactive does not work."; 62048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 62148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood enableKeyboardInteractive = false; // do not try this again 62248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 62348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood else 62448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 62548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood lastError = "Keyboard-interactive auth failed."; // try again, if possible 62648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 62748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 62848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood continue; 62948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 63048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 63148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (conn.isAuthMethodAvailable(username, "password")) 63248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 63348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood final EnterSomethingDialog esd = new EnterSomethingDialog(loginFrame, 63448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood "Password Authentication", 63548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood new String[] { lastError, "Enter password for " + username }, true); 63648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 63748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood esd.setVisible(true); 63848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 63948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (esd.answer == null) 64048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IOException("Login aborted by user"); 64148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 64248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood boolean res = conn.authenticateWithPassword(username, esd.answer); 64348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 64448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if (res == true) 64548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood break; 64648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 64748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood lastError = "Password authentication failed."; // try again, if possible 64848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 64948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood continue; 65048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 65148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 65248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood throw new IOException("No supported authentication methods available."); 65348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 65448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 65548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* 65648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 65748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * AUTHENTICATION OK. DO SOMETHING. 65848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 65948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 66048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 66148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood Session sess = conn.openSession(); 66248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 66348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int x_width = 90; 66448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood int y_width = 30; 66548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 66648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood sess.requestPTY("dumb", x_width, y_width, 0, 0, null); 66748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood sess.startShell(); 66848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 66948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood TerminalDialog td = new TerminalDialog(loginFrame, username + "@" + hostname, sess, x_width, y_width); 67048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 67148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* The following call blocks until the dialog has been closed */ 67248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 67348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood td.setVisible(true); 67448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 67548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 67648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood catch (IOException e) 67748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 67848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood //e.printStackTrace(); 67948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood JOptionPane.showMessageDialog(loginFrame, "Exception: " + e.getMessage()); 68048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 68148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 68248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* 68348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 68448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * CLOSE THE CONNECTION. 68548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 68648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 68748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 68848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood conn.close(); 68948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 69048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood /* 69148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 69248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * CLOSE THE LOGIN FRAME - APPLICATION WILL BE EXITED (no more frames) 69348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood * 69448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood */ 69548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 69648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood Runnable r = new Runnable() 69748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 69848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void run() 69948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 70048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginFrame.dispose(); 70148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 70248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood }; 70348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 70448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood SwingUtilities.invokeLater(r); 70548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 70648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 70748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 70848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood void loginPressed() 70948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 71048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String hostname = hostField.getText().trim(); 71148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood String username = userField.getText().trim(); 71248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 71348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood if ((hostname.length() == 0) || (username.length() == 0)) 71448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 71548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood JOptionPane.showMessageDialog(loginFrame, "Please fill out both fields!"); 71648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood return; 71748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 71848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 71948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginButton.setEnabled(false); 72048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood hostField.setEnabled(false); 72148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood userField.setEnabled(false); 72248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 72348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood ConnectionThread ct = new ConnectionThread(hostname, username); 72448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 72548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood ct.start(); 72648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 72748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 72848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood void showGUI() 72948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 73048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginFrame = new JFrame("Ganymed SSH2 SwingShell"); 73148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 73248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood hostLabel = new JLabel("Hostname:"); 73348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood userLabel = new JLabel("Username:"); 73448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 73548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood hostField = new JTextField("", 20); 73648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood userField = new JTextField("", 10); 73748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 73848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginButton = new JButton("Login"); 73948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 74048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginButton.addActionListener(new ActionListener() 74148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 74248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void actionPerformed(java.awt.event.ActionEvent e) 74348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 74448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginPressed(); 74548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 74648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood }); 74748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 74848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood JPanel loginPanel = new JPanel(); 74948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 75048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginPanel.add(hostLabel); 75148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginPanel.add(hostField); 75248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginPanel.add(userLabel); 75348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginPanel.add(userField); 75448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginPanel.add(loginButton); 75548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 75648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginFrame.getRootPane().setDefaultButton(loginButton); 75748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 75848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginFrame.getContentPane().add(loginPanel, BorderLayout.PAGE_START); 75948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood //loginFrame.getContentPane().add(textArea, BorderLayout.CENTER); 76048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 76148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 76248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 76348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginFrame.pack(); 76448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginFrame.setResizable(false); 76548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginFrame.setLocationRelativeTo(null); 76648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood loginFrame.setVisible(true); 76748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 76848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 76948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood void startGUI() 77048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 77148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood Runnable r = new Runnable() 77248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 77348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public void run() 77448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 77548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood showGUI(); 77648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 77748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood }; 77848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 77948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood SwingUtilities.invokeLater(r); 78048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 78148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 78248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood 78348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public static void main(String[] args) 78448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood { 78548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood SwingShell client = new SwingShell(); 78648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood client.startGUI(); 78748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood } 78848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood} 789