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