aboutsummaryrefslogtreecommitdiffstats
path: root/java/com/tigervnc
diff options
context:
space:
mode:
authorBrian Hinz <bphinz@users.sourceforge.net>2012-04-05 03:37:50 +0000
committerBrian Hinz <bphinz@users.sourceforge.net>2012-04-05 03:37:50 +0000
commitcf0e312b59e1c0afb4996188afafc8835eec191d (patch)
tree4a644800acad93b144100955d380991efa3faf1e /java/com/tigervnc
parentb3ea375488ddb5ca8f9e90f7be95a269571262ad (diff)
downloadtigervnc-cf0e312b59e1c0afb4996188afafc8835eec191d.tar.gz
tigervnc-cf0e312b59e1c0afb4996188afafc8835eec191d.zip
adds experimental support for SSH tunneling to the Java client. Has not been tested with large desktop sizes yet. CMakeLists.txt needs some rework.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4882 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'java/com/tigervnc')
-rw-r--r--java/com/tigervnc/network/TcpListener.java2
-rw-r--r--java/com/tigervnc/network/TcpSocket.java34
-rw-r--r--java/com/tigervnc/vncviewer/CConn.java2
-rw-r--r--java/com/tigervnc/vncviewer/PasswdDialog.java90
-rw-r--r--java/com/tigervnc/vncviewer/VncViewer.java100
5 files changed, 204 insertions, 24 deletions
diff --git a/java/com/tigervnc/network/TcpListener.java b/java/com/tigervnc/network/TcpListener.java
index 4cc8c0da..cb0a69aa 100644
--- a/java/com/tigervnc/network/TcpListener.java
+++ b/java/com/tigervnc/network/TcpListener.java
@@ -100,7 +100,7 @@ public class TcpListener extends SocketListener {
// Accept an incoming connection
try {
- if (selector.select() > 0) {
+ if (selector.select(0) > 0) {
Set keys = selector.selectedKeys();
Iterator iter = keys.iterator();
while (iter.hasNext()) {
diff --git a/java/com/tigervnc/network/TcpSocket.java b/java/com/tigervnc/network/TcpSocket.java
index 9277dd14..1d127f50 100644
--- a/java/com/tigervnc/network/TcpSocket.java
+++ b/java/com/tigervnc/network/TcpSocket.java
@@ -171,29 +171,23 @@ public class TcpSocket extends Socket {
return ((InetSocketAddress)((SocketDescriptor)getFd()).socket().getRemoteSocketAddress()).getPort();
}
+ /* Tunnelling support. */
+ public static int findFreeTcpPort() {
+ java.net.ServerSocket sock;
+ int port;
+ try {
+ sock = new java.net.ServerSocket(0);
+ port = sock.getLocalPort();
+ sock.close();
+ } catch (java.io.IOException e) {
+ throw new SocketException("unable to create socket: "+e.toString());
+ }
+ return port;
+ }
+
private boolean closeFd;
static LogWriter vlog = new LogWriter("TcpSocket");
}
-/* Tunnelling support. */
-/*
-public int findFreeTcpPort() {
- int sock;
-
- if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- throw SocketException("unable to create socket", errorNumber);
-
- int port = 0;
- if (bind (sock, (struct sockaddr *)&addr, sizeof (addr)) < 0)
- throw SocketException("unable to find free port", errorNumber);
-
- socklen_t n = sizeof(addr);
- if (getsockname (sock, (struct sockaddr *)&addr, &n) < 0)
- throw SocketException("unable to get port number", errorNumber);
-
- closesocket(sock);
- return ntohs(addr.sin_port);
-}
-*/
diff --git a/java/com/tigervnc/vncviewer/CConn.java b/java/com/tigervnc/vncviewer/CConn.java
index a87ddaea..053bef2a 100644
--- a/java/com/tigervnc/vncviewer/CConn.java
+++ b/java/com/tigervnc/vncviewer/CConn.java
@@ -314,7 +314,7 @@ public class CConn extends CConnection
}
}
if (passwd != null)
- passwd.append(dlg.passwdEntry.getText());
+ passwd.append(new String(dlg.passwdEntry.getPassword()));
return true;
}
diff --git a/java/com/tigervnc/vncviewer/PasswdDialog.java b/java/com/tigervnc/vncviewer/PasswdDialog.java
index d947828d..51c268fa 100644
--- a/java/com/tigervnc/vncviewer/PasswdDialog.java
+++ b/java/com/tigervnc/vncviewer/PasswdDialog.java
@@ -18,10 +18,14 @@
package com.tigervnc.vncviewer;
+import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
+import com.jcraft.jsch.*;
-class PasswdDialog extends Dialog implements KeyListener{
+class PasswdDialog extends Dialog implements KeyListener,
+ UserInfo,
+ UIKeyboardInteractive {
public PasswdDialog(String title, boolean userDisabled, boolean passwdDisabled) {
super(true);
@@ -79,8 +83,90 @@ class PasswdDialog extends Dialog implements KeyListener{
}
}
+ public String getPassword(){
+ return new String(passwdEntry.getPassword());
+ }
+ public String getPassphrase(){ return null; }
+ public boolean promptPassphrase(String message){ return false; }
+ public boolean promptPassword(String message){
+ setTitle(message);
+ showDialog();
+ if (passwdEntry != null)
+ return true;
+ return false;
+ }
+ public void showMessage(String message){
+ JOptionPane.showMessageDialog(null, message);
+ }
+ public boolean promptYesNo(String str){
+ Object[] options={ "yes", "no" };
+ int foo=JOptionPane.showOptionDialog(null,
+ str,
+ "Warning",
+ JOptionPane.DEFAULT_OPTION,
+ JOptionPane.WARNING_MESSAGE,
+ null, options, options[0]);
+ return foo==0;
+ }
+ public String[] promptKeyboardInteractive(String destination,
+ String name,
+ String instruction,
+ String[] prompt,
+ boolean[] echo){
+ Container panel = new JPanel();
+ panel.setLayout(new GridBagLayout());
+
+ GridBagConstraints gbc =
+ new GridBagConstraints(0,0,1,1,1,1,
+ GridBagConstraints.NORTHWEST,
+ GridBagConstraints.NONE,
+ new Insets(0,0,0,0),0,0);
+ gbc.weightx = 1.0;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.gridx = 0;
+ panel.add(new JLabel(instruction), gbc);
+ gbc.gridy++;
+
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+
+ JTextField[] texts=new JTextField[prompt.length];
+ for(int i=0; i<prompt.length; i++){
+ gbc.fill = GridBagConstraints.NONE;
+ gbc.gridx = 0;
+ gbc.weightx = 1;
+ panel.add(new JLabel(prompt[i]),gbc);
+
+ gbc.gridx = 1;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.weighty = 1;
+ if(echo[i]){
+ texts[i]=new JTextField(20);
+ }
+ else{
+ texts[i]=new JPasswordField(20);
+ }
+ panel.add(texts[i], gbc);
+ gbc.gridy++;
+ }
+
+ if(JOptionPane.showConfirmDialog(null, panel,
+ destination+": "+name,
+ JOptionPane.OK_CANCEL_OPTION,
+ JOptionPane.QUESTION_MESSAGE)
+ ==JOptionPane.OK_OPTION){
+ String[] response=new String[prompt.length];
+ for(int i=0; i<prompt.length; i++){
+ response[i]=texts[i].getText();
+ }
+ return response;
+ }
+ else{
+ return null; // cancel
+ }
+ }
+
JLabel userLabel;
JTextField userEntry;
JLabel passwdLabel;
- JTextField passwdEntry;
+ JPasswordField passwdEntry;
}
diff --git a/java/com/tigervnc/vncviewer/VncViewer.java b/java/com/tigervnc/vncviewer/VncViewer.java
index 91504d2c..f7d1f62a 100644
--- a/java/com/tigervnc/vncviewer/VncViewer.java
+++ b/java/com/tigervnc/vncviewer/VncViewer.java
@@ -33,15 +33,21 @@ import java.awt.Graphics;
import java.awt.Image;
import java.io.InputStream;
import java.io.IOException;
+import java.io.File;
import java.lang.Character;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
+import java.util.ArrayList;
+import java.util.Iterator;
import javax.swing.*;
import com.tigervnc.rdr.*;
import com.tigervnc.rfb.*;
import com.tigervnc.network.*;
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.Session;
+
public class VncViewer extends java.applet.Applet implements Runnable
{
public static final String about1 = "TigerVNC Viewer for Java";
@@ -130,6 +136,82 @@ public class VncViewer extends java.applet.Applet implements Runnable
System.exit(1);
}
+ /* Tunnelling support. */
+ private void interpretViaParam(StringParameter gatewayHost,
+ StringParameter remoteHost, IntParameter remotePort,
+ StringParameter vncServerName, IntParameter localPort)
+ {
+ final int SERVER_PORT_OFFSET = 5900;;
+ int pos = vncServerName.getValueStr().indexOf(":");
+ if (pos == -1)
+ remotePort.setParam(""+SERVER_PORT_OFFSET+"");
+ else {
+ int portOffset = SERVER_PORT_OFFSET;
+ int len;
+ pos++;
+ len = vncServerName.getValueStr().substring(pos).length();
+ if (vncServerName.getValueStr().substring(pos, pos).equals(":")) {
+ /* Two colons is an absolute port number, not an offset. */
+ pos++;
+ len--;
+ portOffset = 0;
+ }
+ try {
+ if (len <= 0 || !vncServerName.getValueStr().substring(pos).matches("[0-9]+"))
+ usage();
+ portOffset += Integer.parseInt(vncServerName.getValueStr().substring(pos));
+ remotePort.setParam(""+portOffset+"");
+ } catch (java.lang.NumberFormatException e) {
+ usage();
+ }
+ }
+
+ if (vncServerName != null)
+ remoteHost.setParam(vncServerName.getValueStr().split(":")[0]);
+
+ gatewayHost.setParam(via.getValueStr());
+ vncServerName.setParam("localhost::"+localPort.getValue());
+ }
+
+ private void
+ createTunnel(String gatewayHost, String remoteHost,
+ int remotePort, int localPort)
+ {
+ try{
+ JSch jsch=new JSch();
+ String homeDir = new String("");
+ try {
+ homeDir = System.getProperty("user.home");
+ } catch(java.security.AccessControlException e) {
+ System.out.println("Cannot access user.home system property");
+ }
+ // NOTE: jsch does not support all ciphers. User may be
+ // prompted to accept host key authenticy even if
+ // the key is in the known_hosts file.
+ File knownHosts = new File(homeDir+"/.ssh/known_hosts");
+ if (knownHosts.exists() && knownHosts.canRead())
+ jsch.setKnownHosts(knownHosts.getAbsolutePath());
+ ArrayList<File> privateKeys = new ArrayList<File>();
+ privateKeys.add(new File(homeDir+"/.ssh/id_rsa"));
+ privateKeys.add(new File(homeDir+"/.ssh/id_dsa"));
+ for (Iterator i = privateKeys.iterator(); i.hasNext();) {
+ File privateKey = (File)i.next();
+ if (privateKey.exists() && privateKey.canRead())
+ jsch.addIdentity(privateKey.getAbsolutePath());
+ }
+ // username and passphrase will be given via UserInfo interface.
+ PasswdDialog dlg = new PasswdDialog(new String("SSH Authentication"), false, false);
+ dlg.userEntry.setText((String)System.getProperties().get("user.name"));
+ Session session=jsch.getSession(dlg.userEntry.getText(), gatewayHost, 22);
+ session.setUserInfo(dlg);
+ session.connect();
+
+ session.setPortForwardingL(localPort, remoteHost, remotePort);
+ } catch (java.lang.Exception e) {
+ System.out.println(e);
+ }
+ }
+
public VncViewer() {
applet = true;
firstApplet = true;
@@ -193,6 +275,21 @@ public class VncViewer extends java.applet.Applet implements Runnable
CConn cc = null;
Socket sock = null;
+ /* Tunnelling support. */
+ if (via.getValueStr() != null) {
+ StringParameter gatewayHost = new StringParameter("", "", "");
+ StringParameter remoteHost = new StringParameter("", "", "localhost");
+ IntParameter localPort =
+ new IntParameter("", "", TcpSocket.findFreeTcpPort());
+ IntParameter remotePort = new IntParameter("", "", 5900);
+ if (vncServerName.getValueStr() == null)
+ usage();
+ interpretViaParam(gatewayHost, remoteHost, remotePort,
+ vncServerName, localPort);
+ createTunnel(gatewayHost.getValueStr(), remoteHost.getValueStr(),
+ remotePort.getValue(), localPort.getValue());
+ }
+
if (listenMode.getValue()) {
int port = 5500;
@@ -322,6 +419,9 @@ public class VncViewer extends java.applet.Applet implements Runnable
= new BoolParameter("AcceptBell",
"Produce a system beep when requested to by the server.",
true);
+ StringParameter via
+ = new StringParameter("via", "Gateway to tunnel via", null);
+
BoolParameter customCompressLevel
= new BoolParameter("CustomCompressLevel",
"Use custom compression level. "+