Commit 3110c0e3 authored by runge's avatar runge

Add SSL support to UltraVNC Java Viewer (has filetransfer gui). Fix UltraVNC...

Add SSL support to UltraVNC Java Viewer (has filetransfer gui).  Fix UltraVNC bugs and improve FTP gui a bit.
parent c49eee2c
EXTRA_DIST=VncViewer.jar index.vnc SignedVncViewer.jar proxy.vnc README ss_vncviewer onetimekey
EXTRA_DIST=VncViewer.jar index.vnc SignedVncViewer.jar proxy.vnc README ss_vncviewer onetimekey UltraViewerSSL.jar SignedUltraViewerSSL.jar ultra.vnc ultrasigned.vnc
......@@ -69,4 +69,18 @@ Running Java SSL VncViewer from the command line:
java -cp ./VncViewer.jar VncViewer HOST <thehost> PORT <theport>
substitute <thehost> and <theport> with the actual values.
You can add any other parameters, e.g.: ignoreProxy yes
---------------------------------------------------------------
UltraVNC:
The UltraVNC java viewer has also been patched to support SSL. Various
bugs in the UltraVNC java viewer were also fixed. This viewer can be
useful because is support UltraVNC filetransfer, and so it works on
Unix, etc.
UltraViewerSSL.jar
SignedUltraViewerSSL.jar
ultra.vnc
ultraproxy.vnc
ultravnc-102-JavaViewer-ssl-etc.patch
......@@ -260,6 +260,12 @@ if [ "X$use_ssh" = "X1" -a "X$use_sshssl" = "X" ]; then
fi
fi
if echo "$orig" | grep '^V[Nn][Cc]://' > /dev/null; then
SSVNC_NO_ENC_WARN=1
export SSVNC_NO_ENC_WARN
orig=`echo "$orig" | sed -e 's/^...:/vnc:/'`
fi
if echo "$orig" | grep '^vnc://' > /dev/null; then
orig=`echo "$orig" | sed -e 's,vnc://,,'`
verify=""
......@@ -271,9 +277,14 @@ elif echo "$orig" | grep '^vncs://' > /dev/null; then
orig=`echo "$orig" | sed -e 's,vncs://,,'`
elif echo "$orig" | grep '^vncssl://' > /dev/null; then
orig=`echo "$orig" | sed -e 's,vncssl://,,'`
elif echo "$orig" | grep '^vnc+ssl://' > /dev/null; then
orig=`echo "$orig" | sed -e 's,vnc.ssl://,,'`
elif echo "$orig" | grep '^vncssh://' > /dev/null; then
orig=`echo "$orig" | sed -e 's,vncssh://,,'`
use_ssh=1
elif echo "$orig" | grep '^vnc+ssh://' > /dev/null; then
orig=`echo "$orig" | sed -e 's,vnc.ssh://,,'`
use_ssh=1
fi
if [ "X$reverse" != "X" -a "X$direct_connect" = "X" ]; then
VNCVIEWER_LISTEN_LOCALHOST=1
......@@ -314,6 +325,8 @@ if uname | grep Linux > /dev/null; then
inuse=`netstat -ant | egrep 'LISTEN|WAIT|ESTABLISH|CLOSE' | awk '{print $4}' | sed 's/^.*://'`
elif uname | grep SunOS > /dev/null; then
inuse=`netstat -an -f inet -P tcp | grep LISTEN | awk '{print $1}' | sed 's/^.*\.//'`
elif uname | grep -i bsd > /dev/null; then
inuse=`netstat -ant -f inet | grep LISTEN | awk '{print $4}' | sed 's/^.*\.//'`
# add others...
fi
......@@ -412,6 +425,31 @@ if echo "$0" | grep vncip > /dev/null; then
VNCVIEWERCMD="$VNCIPCMD"
fi
rchk() {
if [ "X$BASH_VERSION" = "X" ]; then
RANDOM=`date +%S``sh -c 'echo $$'``ps -elf 2>&1 | sum 2>&1 | awk '{print $1}'`
fi
}
rchk
mytmp() {
tf=$1
rm -rf "$tf" || exit 1
if [ -d "$tf" ]; then
echo "tmp file $tf still exists as a directory."
exit 1
elif [ -L "$tf" ]; then
echo "tmp file $tf still exists as a symlink."
exit 1
elif [ -f "$tf" ]; then
echo "tmp file $tf still exists."
exit 1
fi
touch "$tf" || exit 1
chmod 600 "$tf" || exit 1
rchk
}
if [ "X$use_ssh" = "X1" ]; then
ssh_port="22"
ssh_host="$host"
......@@ -472,28 +510,88 @@ if [ "X$use_ssh" = "X1" ]; then
if [ "X$SS_VNCVIEWER_USE_C" != "X" ]; then
C="-C"
fi
if [ "X$reverse" = "X" ]; then
getport=""
if echo "$ssh_cmd" | egrep "^(PORT=|P=)" > /dev/null; then
getport=1
PORT=""
ssh_cmd=`echo "$ssh_cmd" | sed -e 's/^PORT=[ ]*//' -e 's/^P=//'`
SSVNC_NO_ENC_WARN=1
if [ "X$use_sshssl" = "X" ]; then
direct_connect=1
fi
fi
if [ "X$getport" != "X" ]; then
ssh_redir="-D ${use}"
elif [ "X$reverse" = "X" ]; then
ssh_redir="-L ${use}:${vnc_host}:${port}"
else
ssh_redir="-R ${port}:${vnc_host}:${use}"
fi
pmark=`sh -c 'echo $$'`
# the -t option actually speeds up typing response via VNC!!
if [ "X$SS_VNCVIEWER_SSH_ONLY" != "X" ]; then
echo "$ssh -x -p $ssh_port $targ $C $ssh_args $ssh_host \"$info\""
echo ""
$ssh -x -p $ssh_port $targ $C $ssh_args $ssh_host "$ssh_cmd"
exit $?
elif [ "X$SS_VNCVIEWER_NO_F" != "X" ]; then
echo "$ssh -x -p $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host \"$info\""
echo ""
$ssh -x -p $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host "$ssh_cmd"
rc=$?
elif [ "X$getport" != "X" ]; then
echo "$ssh -x -f -p $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host \"$info\""
echo ""
tport=/tmp/tport${RANDOM}.$$
mytmp $tport
$ssh -x -f -p $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host "$ssh_cmd" > $tport
rc=$?
stty sane
i=0
while [ $i -lt 10 ]; do
sleep 1
PORT=`grep "^PORT=" $tport | head -1 | sed -e 's/PORT=//' -e 's/\r//g'`
if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then
break
fi
vnss=`sed -e 's/\r//g' $tport | egrep -i '^(New.* desktop is|A VNC server is already running).*:[0-9[0-9]*$' | head -1 | awk '{print $NF}'`
if [ "X$vnss" != "X" ]; then
PORT=`echo "$vnss" | awk -F: '{print $2}'`
if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then
if [ $PORT -lt 100 ]; then
PORT=`expr $PORT + 5900`
fi
fi
if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then
break
fi
fi
i=`expr $i + 1`
done
echo "PORT=$PORT" 1>&2
PPROXY_SOCKS=1
export PPROXY_SOCKS
host="localhost"
port="$PORT"
proxy="localhost:$use"
rm -f $tport
else
echo "$ssh -x -f -p $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host \"$info\""
echo ""
$ssh -x -f -p $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host "$ssh_cmd"
rc=$?
fi
if [ "$?" != "0" ]; then
if [ "$rc" != "0" ]; then
echo ""
echo "ssh to $ssh_host failed."
exit 1
......@@ -511,7 +609,9 @@ if [ "X$use_ssh" = "X1" ]; then
fi
c=`expr $c + 1`
done
if [ "X$ssh_cmd" = "Xsleep $ssh_sleep" ] ; then
if [ "X$getport" != "X" ]; then
:
elif [ "X$ssh_cmd" = "Xsleep $ssh_sleep" ] ; then
sleep 1
else
# let any command get started a bit.
......@@ -521,7 +621,7 @@ if [ "X$use_ssh" = "X1" ]; then
#reset
stty sane
#echo "pssh=\"$pssh\""
if [ "X$use_sshssl" = "X" ]; then
if [ "X$use_sshssl" = "X" -a "X$getport" = "X" ]; then
echo "Running viewer:"
trap "final" 0 2 15
......@@ -547,7 +647,12 @@ if [ "X$use_ssh" = "X1" ]; then
port=$use
use=$use2
N=`expr $use - 5900`
proxy=""
if [ "X$getport" != "X" ]; then
host="$host0"
port="$port0"
else
proxy=""
fi
fi
fi
......@@ -565,53 +670,33 @@ if [ "X$mycert" != "X" ]; then
cert="cert = $mycert"
fi
mytmp() {
tf=$1
rm -rf "$tf" || exit 1
if [ -d "$tf" ]; then
echo "tmp file $tf still exists as a directory."
exit 1
elif [ -L "$tf" ]; then
echo "tmp file $tf still exists as a symlink."
exit 1
elif [ -f "$tf" ]; then
echo "tmp file $tf still exists."
exit 1
fi
touch "$tf" || exit 1
chmod 600 "$tf" || exit 1
}
if echo "$RANDOM" | grep '[^0-9]' > /dev/null; then
RANDOM=`date +%S`
fi
pcode() {
tf=$1
SSVNC_PROXY=$proxy; export SSVNC_PROXY
SSVNC_DEST="$host:$port"; export SSVNC_DEST
PPROXY_PROXY=$proxy; export PPROXY_PROXY
PPROXY_DEST="$host:$port"; export PPROXY_DEST
cod='#!/usr/bin/perl
# A hack to glue stunnel to a Web proxy for client connections.
# A hack to glue stunnel to a Web proxy or SOCKS for client connections.
use IO::Socket::INET;
my ($first, $second) = split(/,/, $ENV{SSVNC_PROXY});
my ($first, $second) = split(/,/, $ENV{PPROXY_PROXY});
my ($proxy_host, $proxy_port) = split(/:/, $first);
my $connect = $ENV{SSVNC_DEST};
my $connect = $ENV{PPROXY_DEST};
print STDERR "\nperl script for web proxing:\n";
print STDERR "\nPPROXY v0.0: a tool for Web proxies and SOCKS connections.\n";
print STDERR "proxy_host: $proxy_host\n";
print STDERR "proxy_port: $proxy_port\n";
print STDERR "proxy_connect: $connect\n";
my $listen_handle = "";
if ($ENV{SSVNC_LISTEN} != "") {
if ($ENV{PPROXY_LISTEN} != "") {
my $listen_sock = IO::Socket::INET->new(
Listen => 2,
LocalAddr => "localhost",
LocalPort => $ENV{SSVNC_LISTEN},
Proto => "tcp");
LocalPort => $ENV{PPROXY_LISTEN},
Proto => "tcp"
);
if (! $listen_sock) {
die "perl proxy: $!\n";
}
......@@ -625,7 +710,8 @@ if ($ENV{SSVNC_LISTEN} != "") {
my $sock = IO::Socket::INET->new(
PeerAddr => $proxy_host,
PeerPort => $proxy_port,
Proto => "tcp");
Proto => "tcp"
);
if (! $sock) {
unlink($0);
......@@ -633,24 +719,77 @@ if (! $sock) {
}
my $con = "";
if ($second ne "") {
my $con0 = "";
if ($ENV{PPROXY_SOCKS} ne "") {
$second = "";
my ($h, $p) = split(/:/, $connect);
$con .= pack("C", 0x04);
$con .= pack("C", 0x01);
$con .= pack("n", $p);
my $SOCKS_4a = 0;
if ($h eq "localhost" || $h eq "127.0.0.1") {
$con .= pack("C", 127);
$con .= pack("C", 0);
$con .= pack("C", 0);
$con .= pack("C", 1);
} elsif ($h =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) {
$con .= pack("C", $1);
$con .= pack("C", $2);
$con .= pack("C", $3);
$con .= pack("C", $4);
} else {
$con .= pack("C", 0);
$con .= pack("C", 0);
$con .= pack("C", 0);
$con .= pack("C", 3);
$SOCKS_4a = 1;
}
$con .= "nobody";
$con .= pack("C", 0);
if ($SOCKS_4a) {
$con .= $h;
$con .= pack("C", 0);
}
$con0 = "SOCKS4 via $proxy_host:$proxy_port to $h:$p\n\n";
} elsif ($second ne "") {
$con = "CONNECT $second HTTP/1.1\r\n";
$con .= "Host: $second\r\n\r\n";
$con0 = $con;
} else {
$con = "CONNECT $connect HTTP/1.1\r\n";
$con .= "Host: $connect\r\n\r\n";
$con0 = $con;
}
print STDERR "proxy_request1:\n$con";
print STDERR "proxy_request1:\n$con0";
print $sock $con;
unlink($0);
my $rep = "";
while ($rep !~ /\r\n\r\n/) {
my $c = getc($sock);
print STDERR $c;
$rep .= $c;
if ($ENV{PPROXY_SOCKS} ne "") {
$rep = "HTTP/1.0 200";
for (my $i = 0; $i < 8; $i++) {
my $c;
sysread($sock, $c, 1);
my $s = unpack("C", $c);
if ($i == 0) {
$rep = "" if $s != 0x0;
} elsif ($i == 1) {
$rep = "" if $s != 0x5a;
}
}
} else {
while ($rep !~ /\r\n\r\n/) {
my $c;
sysread($sock, $c, 1);
print STDERR $c;
$rep .= $c;
}
}
if ($rep !~ m,HTTP/.* 200,) {
die "proxy error: $rep\n";
......@@ -665,7 +804,8 @@ if ($second ne "") {
$rep = "";
while ($rep !~ /\r\n\r\n/) {
my $c = getc($sock);
my $c;
sysread($sock, $c, 1);
print STDERR $c;
$rep .= $c;
}
......@@ -743,8 +883,8 @@ if [ "X$proxy" != "X" ]; then
if [ "X$showcert" != "X1" -a "X$direct_connect" = "X" ]; then
if uname | grep Darwin >/dev/null; then
nd=`expr $use + 333`
SSVNC_LISTEN=$nd
export SSVNC_LISTEN
PPROXY_LISTEN=$nd
export PPROXY_LISTEN
$ptmp 2>/dev/null &
sleep 3
host="localhost"
......@@ -762,8 +902,8 @@ fi
if [ "X$showcert" = "X1" ]; then
if [ "X$proxy" != "X" ]; then
SSVNC_LISTEN=$use
export SSVNC_LISTEN
PPROXY_LISTEN=$use
export PPROXY_LISTEN
$ptmp 2>/dev/null &
sleep 3
host="localhost"
......@@ -774,24 +914,29 @@ if [ "X$showcert" = "X1" ]; then
fi
if [ "X$direct_connect" != "X" ]; then
echo ""
echo "Running viewer for direct connection:"
echo ""
echo "** NOTE: THERE WILL BE NO SSL OR SSH ENCRYPTION **"
echo ""
if type printf > /dev/null 2>&1; then
if [ "X$getport" = "X" ]; then
echo ""
echo "Running viewer for direct connection:"
echo ""
echo "** NOTE: THERE WILL BE NO SSL OR SSH ENCRYPTION **"
echo ""
fi
if [ "X$SSVNC_NO_ENC_WARN" != "X" ]; then
sleep 1
elif type printf > /dev/null 2>&1; then
printf "Are you sure you want to continue? [y]/n "
read x
else
echo -n "Are you sure you want to continue? [y]/n "
read x
fi
read x
if [ "X$x" = "Xn" ]; then
exit 1
fi
echo ""
if [ "X$ptmp" != "X" ]; then
SSVNC_LISTEN=$use
export SSVNC_LISTEN
PPROXY_LISTEN=$use
export PPROXY_LISTEN
$ptmp &
if [ "X$reverse" = "X" ]; then
sleep 2
......@@ -816,8 +961,6 @@ if [ "X$direct_connect" != "X" ]; then
exit $?
fi
##debug = 7
## debug = 6
tmp=/tmp/ss_vncviewer${RANDOM}.$$
mytmp "$tmp"
......
<!--
index.vnc - default HTML page for TightVNC Java viewer applet, to be
used with Xvnc. On any file ending in .vnc, the HTTP server embedded in
Xvnc will substitute the following variables when preceded by a dollar:
USER, DESKTOP, DISPLAY, APPLETWIDTH, APPLETHEIGHT, WIDTH, HEIGHT, PORT,
PARAMS. Use two dollar signs ($$) to get a dollar sign in the generated
HTML page.
NOTE: the $PARAMS variable is not supported by the standard VNC, so
make sure you have TightVNC on the server side, if you're using this
variable.
-->
<HTML>
<TITLE>
$USER's $DESKTOP desktop ($DISPLAY)
</TITLE>
<APPLET CODE=VncViewer.class ARCHIVE=UltraViewerSSL.jar
WIDTH=$APPLETWIDTH HEIGHT=$APPLETHEIGHT>
<param name=PORT value=$PORT>
<param name="Open New Window" value=yes>
<param name="ignoreMSLogonCheck" value=yes>
$PARAMS
</APPLET>
<BR>
<A href="http://www.ultravnc.com/">UltraVNC site</A>
</HTML>
<!--
index.vnc - default HTML page for TightVNC Java viewer applet, to be
used with Xvnc. On any file ending in .vnc, the HTTP server embedded in
Xvnc will substitute the following variables when preceded by a dollar:
USER, DESKTOP, DISPLAY, APPLETWIDTH, APPLETHEIGHT, WIDTH, HEIGHT, PORT,
PARAMS. Use two dollar signs ($$) to get a dollar sign in the generated
HTML page.
NOTE: the $PARAMS variable is not supported by the standard VNC, so
make sure you have TightVNC on the server side, if you're using this
variable.
-->
<HTML>
<TITLE>
$USER's $DESKTOP desktop ($DISPLAY)
</TITLE>
<APPLET CODE=VncViewer.class ARCHIVE=SignedUltraViewerSSL.jar
WIDTH=$APPLETWIDTH HEIGHT=$APPLETHEIGHT>
<param name=PORT value=$PORT>
<param name="Open New Window" value=yes>
<param name="ignoreMSLogonCheck" value=yes>
$PARAMS
</APPLET>
<BR>
<A href="http://www.ultravnc.com/">UltraVNC site</A>
</HTML>
diff -Naur JavaViewer.orig/ButtonPanel.java JavaViewer/ButtonPanel.java
--- JavaViewer.orig/ButtonPanel.java 2004-12-12 20:51:02.000000000 -0500
+++ JavaViewer/ButtonPanel.java 2007-05-16 15:50:54.000000000 -0400
@@ -163,9 +163,12 @@
}
else if (evt.getSource() == ftpButton)
{
+// begin runge/x11vnc
+ viewer.ftp.setSavedLocations();
+// end runge/x11vnc
viewer.ftp.setVisible(!viewer.ftp.isVisible());
viewer.rfb.readServerDriveList();
-
+
}
}
}
diff -Naur JavaViewer.orig/FTPFrame.java JavaViewer/FTPFrame.java
--- JavaViewer.orig/FTPFrame.java 2005-03-15 23:53:14.000000000 -0500
+++ JavaViewer/FTPFrame.java 2007-05-16 16:05:15.000000000 -0400
@@ -26,6 +26,10 @@
import java.util.Vector;
import javax.swing.*;
+// begin runge/x11vnc
+import java.util.Arrays;
+// end runge/x11vnc
+
/*
* Created on Feb 25, 2004
@@ -80,6 +84,17 @@
private File localSelection = null; // Holds the currently selected local file
private String remoteSelection = null; // Holds the currently selected remote file
public String selectedTable = null;
+
+// begin runge/x11vnc
+ private javax.swing.JButton viewButton = null;
+ public File saveLocalDirectory = null;
+ public long saveLocalDirectoryTime = 0;
+ public int saveLocalDirectoryCount = 0;
+ public String saveRemoteDirectory = null;
+ public long saveRemoteDirectoryTime = 0;
+ public int saveRemoteDirectoryCount = 0;
+ private boolean localCurrentIsDir = true;
+// end runge/x11vnc
// sf@2004 - Separate directories and files for better lisibility
private ArrayList DirsList;
@@ -125,11 +140,59 @@
void refreshRemoteLocation()
{
+
remoteList.clear();
remoteFileTable.setListData(remoteList);
+System.out.println("refreshRemoteLocation '" + remoteLocation.getText() + "'"); // runge/x11vnc
viewer.rfb.readServerDirectory(remoteLocation.getText());
}
+// begin runge/x11vnc
+ public void setSavedLocations() {
+ saveLocalDirectory = currentLocalDirectory;
+ saveLocalDirectoryTime = System.currentTimeMillis();
+ saveLocalDirectoryCount = 0;
+
+ if (remoteLocation != null) {
+ saveRemoteDirectory = remoteLocation.getText();
+System.out.println("RemoteSave '" + saveRemoteDirectory + "'");
+ }
+ saveRemoteDirectoryTime = System.currentTimeMillis();
+ saveRemoteDirectoryCount = 0;
+ }
+
+ private File saveLocalHack(File dir) {
+ saveLocalDirectoryCount++;
+System.out.println("L " + saveLocalDirectoryCount + " dt: " + (System.currentTimeMillis() - saveLocalDirectoryTime) + " - " + saveLocalDirectory);
+ if (System.currentTimeMillis() > saveLocalDirectoryTime + 2000 || saveLocalDirectoryCount > 2) {
+ saveLocalDirectory = null;
+ }
+ if (saveLocalDirectory != null) {
+ currentLocalDirectory = saveLocalDirectory;
+ localLocation.setText(saveLocalDirectory.toString());
+ return saveLocalDirectory;
+ } else {
+ return dir;
+ }
+ }
+
+ private String saveRemoteHack(String indrive) {
+ saveRemoteDirectoryCount++;
+System.out.println("R " + saveRemoteDirectoryCount + " - " + saveRemoteDirectory);
+ if (saveRemoteDirectory != null && saveRemoteDirectoryCount > 1) {
+ saveRemoteDirectory = null;
+ }
+ if (saveRemoteDirectory != null) {
+ if (! saveRemoteDirectory.equals("")) {
+System.out.println("saveRemoteHack setText + refreshRemoteLocation '" + saveRemoteDirectory + "'");
+ return saveRemoteDirectory;
+ }
+ }
+ return indrive;
+ }
+// end runge/x11vnc
+
+
/*
* Prints the list of drives on the remote directory and returns a String[].
* str takes as string like A:fC:lD:lE:lF:lG:cH:c
@@ -185,6 +248,7 @@
stopButton.setVisible(true);
stopButton.setEnabled(true);
receiveButton.setEnabled(false);
+ viewButton.setEnabled(false); // runge/x11vnc
remoteTopButton.setEnabled(false);
sendButton.setEnabled(false);
remoteFileTable.setEnabled(false);
@@ -207,6 +271,7 @@
stopButton.setVisible(false);
stopButton.setEnabled(false);
receiveButton.setEnabled(true);
+ viewButton.setEnabled(true); // runge/x11vnc
remoteTopButton.setEnabled(true);
sendButton.setEnabled(true);
remoteFileTable.setEnabled(true);
@@ -405,6 +470,7 @@
buttonPanel = new javax.swing.JPanel();
buttonPanel.setLayout(null);
buttonPanel.add(getReceiveButton(), null);
+ buttonPanel.add(getViewButton(), null); // runge/x11vnc
buttonPanel.add(getNewFolderButton(), null);
buttonPanel.add(getCloseButton(), null);
buttonPanel.add(getDeleteButton(), null);
@@ -422,7 +488,7 @@
private javax.swing.JButton getSendButton() {
if (sendButton == null) {
sendButton = new javax.swing.JButton();
- sendButton.setBounds(20, 30, 97, 25);
+ sendButton.setBounds(15, 30, 107, 25); // runge/x11vnc
sendButton.setText("Send >>");
sendButton.setName("sendButton");
sendButton.addActionListener(this);
@@ -438,7 +504,7 @@
private javax.swing.JButton getReceiveButton() {
if (receiveButton == null) {
receiveButton = new javax.swing.JButton();
- receiveButton.setBounds(20, 60, 97, 25);
+ receiveButton.setBounds(15, 60, 107, 25); // runge/x11vnc
receiveButton.setText("<< Receive");
receiveButton.setName("receiveButton");
receiveButton.addActionListener(this);
@@ -453,7 +519,7 @@
private javax.swing.JButton getDeleteButton() {
if (deleteButton == null) {
deleteButton = new javax.swing.JButton();
- deleteButton.setBounds(20, 110, 97, 25);
+ deleteButton.setBounds(15, 110, 107, 25); // runge/x11vnc
deleteButton.setText("Delete File");
deleteButton.setName("deleteButton");
deleteButton.addActionListener(this);
@@ -468,7 +534,7 @@
private javax.swing.JButton getNewFolderButton() {
if (newFolderButton == null) {
newFolderButton = new javax.swing.JButton();
- newFolderButton.setBounds(20, 140, 97, 25);
+ newFolderButton.setBounds(15, 140, 107, 25); // runge/x11vnc
newFolderButton.setText("New Folder");
newFolderButton.setName("newFolderButton");
newFolderButton.addActionListener(this);
@@ -476,6 +542,24 @@
return newFolderButton;
}
+// begin runge/x11vnc
+ /**
+ * This method initializes viewButton
+ *
+ * @return javax.swing.JButton
+ */
+ private javax.swing.JButton getViewButton() {
+ if (viewButton == null) {
+ viewButton = new javax.swing.JButton();
+ viewButton.setBounds(15, 170, 107, 25);
+ viewButton.setText("View File");
+ viewButton.setName("viewButton");
+ viewButton.addActionListener(this);
+ }
+ return viewButton;
+ }
+// end runge/x11vnc
+
/**
* This method initializes stopButton
*
@@ -486,7 +570,7 @@
if (stopButton == null)
{
stopButton = new javax.swing.JButton();
- stopButton.setBounds(20, 200, 97, 25);
+ stopButton.setBounds(15, 200, 107, 25); // runge/x11vnc
stopButton.setText("Stop");
stopButton.setName("stopButton");
stopButton.addActionListener(this);
@@ -503,7 +587,7 @@
private javax.swing.JButton getCloseButton() {
if (closeButton == null) {
closeButton = new javax.swing.JButton();
- closeButton.setBounds(20, 325, 97, 25);
+ closeButton.setBounds(15, 325, 107, 25); // runge/x11vnc
closeButton.setText("Close");
closeButton.setName("closeButton");
closeButton.addActionListener(this);
@@ -829,12 +913,19 @@
{
doReceive();
}
+// begin runge/x11vnc
+ else if (evt.getSource() == viewButton)
+ {
+ doView();
+ }
+// end runge/x11vnc
else if (evt.getSource() == localDrivesComboBox)
{
changeLocalDrive();
}
else if (evt.getSource() == remoteDrivesComboBox)
{
+System.out.println("remoteDrivesComboBox"); // runge/x11vnc
changeRemoteDrive();
remoteList.clear();
remoteFileTable.setListData(remoteList);
@@ -845,6 +936,7 @@
}
else if (evt.getSource() == remoteTopButton)
{
+System.out.println("remoteTopButton"); // runge/x11vnc
changeRemoteDrive();
}
else if(evt.getSource() == deleteButton)
@@ -979,6 +1071,56 @@
viewer.rfb.requestRemoteFile(remoteFileName,localDestinationPath);
}
+// begin runge/x11vnc
+ private void doView()
+ {
+ System.out.println("View Button Pressed");
+
+ if (selectedTable == null) {
+ return;
+ }
+ if (selectedTable.equals("remote")) {
+ viewRemote();
+ } else if (selectedTable.equals("local")) {
+ viewLocal();
+ }
+ }
+
+ private File doReceiveTmp()
+ {
+
+ if (remoteFileTable == null) {
+ return null;
+ }
+ String sFileName = ((String) this.remoteFileTable.getSelectedValue());
+ if (sFileName == null) {
+ return null;
+ }
+
+ // sf@2004 - Directory can't be transfered
+ if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]"))
+ {
+ return null;
+ }
+
+ File tmp = null;
+ try {
+ tmp = File.createTempFile("ULTRAFTP", ".txt");
+ } catch (Exception e) {
+ return null;
+ }
+
+ //updateHistory("Downloaded " + localSelection.toString());
+ String remoteFileName = this.remoteLocation.getText();
+ remoteFileName+= ((String) this.remoteFileTable.getSelectedValue()).substring(1);
+
+ String localDestinationPath = tmp.getAbsolutePath();
+ viewer.rfb.requestRemoteFile(remoteFileName,localDestinationPath);
+ System.out.println("ReceiveTmp: " + localDestinationPath);
+ return tmp;
+ }
+// end runge/x11vnc
+
private void doSend()
{
System.out.println("Send Button Pressed");
@@ -1035,8 +1177,11 @@
if (!updateDriveList) {
String drive = remoteDrivesComboBox.getSelectedItem().toString().substring(0,1)+ ":\\";
+System.out.println("changeRemoteDrive-A " + drive); // runge/x11vnc
+ drive = saveRemoteHack(drive);
viewer.rfb.readServerDirectory(drive);
remoteLocation.setText(drive);
+System.out.println("changeRemoteDrive-B " + drive); // runge/x11vnc
}
remoteList.clear();
remoteFileTable.setListData(remoteList);
@@ -1048,6 +1193,7 @@
private void changeLocalDrive()
{
File currentDrive = new File(localDrivesComboBox.getSelectedItem().toString());
+System.out.println("changeLocalDrive " + currentDrive.toString()); // runge/x11vnc
if(currentDrive.canRead())
{
localSelection = null;
@@ -1060,6 +1206,7 @@
localStatus.setText("WARNING: Drive " + localDrivesComboBox.getSelectedItem().toString());
connectionStatus.setText(" > WARNING - Local Drive unavailable (possibly restricted access or media not present)");
}
+
}
/**
* Determines which FileTable was double-clicked and updates the table
@@ -1101,7 +1248,7 @@
String name = (remoteFileTable.getSelectedValue().toString()).substring(1);
if( !name.substring(0, 2).equals(" ["))
remoteSelection = remoteLocation.getText() + name.substring(0, name.length());
-
+
}
/*
@@ -1115,10 +1262,38 @@
localFileTable.setBackground(new Color(255, 255, 255));
File currentSelection = new File(currentLocalDirectory, getTrimmedSelection());
- if(currentSelection.isFile())
+// begin runge/x11vnc
+ // localSelection = currentSelection.getAbsoluteFile();
+ if(currentSelection.isFile()) {
localSelection = currentSelection.getAbsoluteFile();
+ localCurrentIsDir = false;
+ } else {
+ localCurrentIsDir = true;
+ }
+// end runge/x11vnc
}
+
+// begin runge/x11vnc
+ private void viewRemote() {
+ File tmp = doReceiveTmp();
+ if (tmp == null) {
+ return;
+ }
+ TextViewer tv = new TextViewer("Remote: " + remoteSelection, tmp, true);
+ }
+ private void viewLocal() {
+ if (localSelection == null) {
+ return;
+ }
+ if (localCurrentIsDir) {
+ return;
+ }
+ File loc = new File(localSelection.toString());
+ TextViewer tv = new TextViewer("Local: " + localSelection.toString(), loc, false);
+ }
+// end runge/x11vnc
+
/**
* Updates the Remote File Table based on selection. Called from mouseClicked handler
*/
@@ -1149,6 +1324,7 @@
remoteSelection = remoteLocation.getText() + name.substring(0, name.length());
drive = remoteLocation.getText();
// ??
+ viewRemote(); // runge/x11vnc
}
else
{
@@ -1163,6 +1339,7 @@
}
//remoteLocation.setText(drive);
}
+
/**
* Updates the Local File Table based on selection. Called from MouseClicked handler
*/
@@ -1188,6 +1365,7 @@
else if (currentSelection.isFile())
{
localSelection = currentSelection.getAbsoluteFile();
+ viewLocal(); // runge/x11vnc
}
else if (currentSelection.isDirectory())
{
@@ -1247,9 +1425,20 @@
*/
public void changeLocalDirectory(File dir)
{
+ dir = saveLocalHack(dir); // runge/x11vnc
+
currentLocalDirectory = dir; // Updates Global
File allFiles[] = dir.listFiles(); // Reads files
String[] contents = dir.list();
+// begin runge/x11vnc
+System.out.println("changeLocalDirectory: " + dir.toString());
+ if (contents != null) {
+ java.util.Arrays.sort(contents, String.CASE_INSENSITIVE_ORDER);
+ for (int i = 0; i < contents.length; i++) {
+ allFiles[i] = new File(dir, contents[i]);
+ }
+ }
+// end runge/x11vnc
localList.clear();
localList.addElement(" [..]");
@@ -1296,3 +1485,135 @@
}
} // @jve:visual-info decl-index=0 visual-constraint="10,10"
+
+// begin runge/x11vnc
+class TextViewer extends JFrame implements ActionListener {
+
+ JTextArea textArea = new JTextArea(35, 80);
+ File file = null;
+ JButton refreshButton;
+ JButton dismissButton;
+ Timer tim = null;
+ int rcnt = 0;
+ int tms = 250;
+ boolean delete_it = false;
+
+ public TextViewer(String s, File f, boolean d) {
+
+ delete_it = d;
+ file = f;
+
+ JScrollPane scrollPane = new JScrollPane(textArea,
+ JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+ JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+
+ textArea.setEditable(false);
+ textArea.setFont(new Font("Monospaced", Font.PLAIN, 12));
+
+
+ refreshButton = new JButton();
+ refreshButton.setText("Reload");
+ refreshButton.setName("refreshButton");
+ refreshButton.addActionListener(this);
+
+ dismissButton = new JButton();
+ dismissButton.setText("Dismiss");
+ dismissButton.setName("dismissButton");
+ dismissButton.addActionListener(this);
+
+ JPanel buttons = new JPanel();
+ buttons.setLayout(new BorderLayout());
+ buttons.add(refreshButton, BorderLayout.WEST);
+ buttons.add(dismissButton, BorderLayout.EAST);
+
+ JPanel content = new JPanel();
+ content.setLayout(new BorderLayout());
+ content.add(scrollPane, BorderLayout.CENTER);
+ content.add(buttons, BorderLayout.SOUTH);
+
+ ActionListener tsk = new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ // System.out.println("tsk");
+ refresh();
+ }
+ };
+ tim = new Timer(tms, tsk);
+ tim.start();
+
+ this.setContentPane(content);
+ this.setTitle("TextViewer - " + s);
+ this.pack();
+ this.setVisible(true);
+ }
+
+ private void refresh() {
+
+ rcnt++;
+ if (rcnt * tms > 3000 && tim != null) {
+ tim.stop();
+ tim = null;
+ }
+ BufferedReader input = null;
+ StringBuffer contents = new StringBuffer();
+ try {
+ if (input == null) {
+ input = new BufferedReader(new FileReader(file));
+ }
+ String line = null;
+ int i = 0;
+ while (( line = input.readLine()) != null) {
+ if (i == 0) {
+ // System.out.println("read");
+ }
+ i++;
+ contents.append(line);
+ contents.append(System.getProperty("line.separator"));
+ }
+ } catch (Exception e) {
+ ;
+ } finally {
+ try {
+ if (input != null) {
+ input.close();
+ input = null;
+ }
+ } catch (Exception e) {
+ ;
+ }
+ }
+
+ textArea.setText(contents.toString());
+ textArea.setCaretPosition(0);
+ }
+
+ public void actionPerformed(ActionEvent evt) {
+
+ if (evt.getSource() == refreshButton) {
+ refresh();
+ }
+ if (evt.getSource() == dismissButton) {
+ cleanse();
+ this.dispose();
+ }
+ }
+
+ private void cleanse() {
+ if (delete_it && file != null) {
+ try {
+ file.delete();
+ file = null;
+ } catch (Exception e) {
+ ;
+ }
+ }
+ }
+
+ protected void finalize() throws Throwable {
+ try {
+ cleanse();
+ } finally {
+ super.finalize();
+ }
+ }
+}
+// end runge/x11vnc
diff -Naur JavaViewer.orig/OptionsFrame.java JavaViewer/OptionsFrame.java
--- JavaViewer.orig/OptionsFrame.java 2005-11-21 18:50:16.000000000 -0500
+++ JavaViewer/OptionsFrame.java 2007-05-13 22:18:30.000000000 -0400
@@ -144,7 +144,10 @@
choices[jpegQualityIndex].select("6");
choices[cursorUpdatesIndex].select("Enable");
choices[useCopyRectIndex].select("Yes");
- choices[eightBitColorsIndex].select("64");
+// begin runge/x11vnc
+// choices[eightBitColorsIndex].select("64");
+ choices[eightBitColorsIndex].select("Full");
+// end runge/x11vnc
choices[mouseButtonIndex].select("Normal");
choices[viewOnlyIndex].select("No");
choices[shareDesktopIndex].select("Yes");
diff -Naur JavaViewer.orig/RfbProto.java JavaViewer/RfbProto.java
--- JavaViewer.orig/RfbProto.java 2006-05-24 15:14:40.000000000 -0400
+++ JavaViewer/RfbProto.java 2007-05-16 15:57:07.000000000 -0400
@@ -199,6 +199,10 @@
// playback.
int numUpdatesInSession;
+// begin runge/x11vnc
+ int readServerDriveListCnt = -1;
+ long readServerDriveListTime = 0;
+// end runge/x11vnc
//
// Constructor. Make TCP connection to RFB server.
//
@@ -207,7 +211,27 @@
viewer = v;
host = h;
port = p;
- sock = new Socket(host, port);
+// begin runge/x11vnc
+// sock = new Socket(host, port);
+ if (! viewer.disableSSL) {
+ System.out.println("new SSLSocketToMe");
+ SSLSocketToMe ssl;
+ try {
+ ssl = new SSLSocketToMe(host, port, v);
+ } catch (Exception e) {
+ throw new IOException(e.getMessage());
+ }
+
+ try {
+ sock = ssl.connectSock();
+ } catch (Exception es) {
+ throw new IOException(es.getMessage());
+ }
+ } else {
+ sock = new Socket(host, port);
+ }
+// end runge/x11vnc
+
is =
new DataInputStream(
new BufferedInputStream(sock.getInputStream(), 16384));
@@ -1263,11 +1287,47 @@
|| dwFileAttributes == 369623040)
{
fileName = " [" + fileName + "]";
- remoteDirsList.add(fileName); // sf@2004
+// begin runge/x11vnc
+// remoteDirsList.add(fileName); // sf@2004
+ int i = -1;
+ String t1 = fileName.toLowerCase();
+ for (int j = 0; j < remoteDirsList.size(); j++) {
+ String t = (String) remoteDirsList.get(j);
+ String t2 = t.toLowerCase();
+ if (t1.compareTo(t2) < 0) {
+ i = j;
+ break;
+ }
+ }
+ if (i >= 0) {
+ remoteDirsList.add(i, fileName);
+ } else {
+ remoteDirsList.add(fileName);
+ }
+// end runge/x11vnc
}
else
{
- remoteFilesList.add(" " + fileName); // sf@2004
+// begin runge/x11vnc
+// remoteFilesList.add(" " + fileName); // sf@2004
+
+ fileName = " " + fileName;
+ int i = -1;
+ String t1 = fileName.toLowerCase();
+ for (int j = 0; j < remoteFilesList.size(); j++) {
+ String t = (String) remoteFilesList.get(j);
+ String t2 = t.toLowerCase();
+ if (t1.compareTo(t2) < 0) {
+ i = j;
+ break;
+ }
+ }
+ if (i >= 0) {
+ remoteFilesList.add(i, fileName);
+ } else {
+ remoteFilesList.add(fileName);
+ }
+// end runge/x11vnc
}
// a.add(fileName);
@@ -1289,6 +1349,16 @@
remoteDirsList.clear();
remoteFilesList.clear();
+// begin runge/x11vnc
+ // Hack for double listing at startup... probably libvncserver bug..
+ readServerDriveListCnt++;
+ if (readServerDriveListCnt == 2) {
+ if (System.currentTimeMillis() - readServerDriveListTime < 1500) {
+System.out.println("readServerDriveListCnt skip " + readServerDriveListCnt);
+ return;
+ }
+ }
+// end runge/x11vnc
viewer.ftp.printDirectory(a);
}
@@ -1312,6 +1382,10 @@
0,
0,
null);
+// begin runge/x11vnc
+ readServerDriveListCnt = 0;
+ readServerDriveListTime = System.currentTimeMillis();
+// end runge/x11vnc
}
catch (IOException e)
{
diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java
--- JavaViewer.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500
+++ JavaViewer/SSLSocketToMe.java 2007-04-29 20:40:35.000000000 -0400
@@ -0,0 +1,1421 @@
+/*
+ * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer.
+ *
+ * Copyright (c) 2006 Karl J. Runge <runge@karlrunge.com>
+ * All rights reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ */
+
+import java.net.*;
+import java.io.*;
+import javax.net.ssl.*;
+import java.util.*;
+
+import java.security.*;
+import java.security.cert.*;
+import java.security.spec.*;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+
+import java.awt.*;
+import java.awt.event.*;
+
+public class SSLSocketToMe {
+
+ /* basic member data: */
+ String host;
+ int port;
+ VncViewer viewer;
+ boolean debug = true;
+
+ /* sockets */
+ SSLSocket socket = null;
+ SSLSocketFactory factory;
+
+ /* fallback for Proxy connection */
+ boolean proxy_in_use = false;
+ boolean proxy_is_https = false;
+ boolean proxy_failure = false;
+ public DataInputStream is = null;
+ public OutputStream os = null;
+
+ String proxy_dialog_host = null;
+ int proxy_dialog_port = 0;
+
+ Socket proxySock;
+ DataInputStream proxy_is;
+ OutputStream proxy_os;
+
+ /* trust contexts */
+ SSLContext trustloc_ctx;
+ SSLContext trustall_ctx;
+ SSLContext trusturl_ctx;
+ SSLContext trustone_ctx;
+
+ TrustManager[] trustAllCerts;
+ TrustManager[] trustUrlCert;
+ TrustManager[] trustOneCert;
+
+ boolean use_url_cert_for_auth = true;
+ boolean user_wants_to_see_cert = true;
+
+ /* cert(s) we retrieve from VNC server */
+ java.security.cert.Certificate[] trustallCerts = null;
+ java.security.cert.Certificate[] trusturlCerts = null;
+
+ byte[] hex2bytes(String s) {
+ byte[] bytes = new byte[s.length()/2];
+ for (int i=0; i<s.length()/2; i++) {
+ int j = 2*i;
+ try {
+ int val = Integer.parseInt(s.substring(j, j+2), 16);
+ if (val > 127) {
+ val -= 256;
+ }
+ Integer I = new Integer(val);
+ bytes[i] = Byte.decode(I.toString()).byteValue();
+
+ } catch (Exception e) {
+ ;
+ }
+ }
+ return bytes;
+ }
+
+ SSLSocketToMe(String h, int p, VncViewer v) throws Exception {
+ host = h;
+ port = p;
+ viewer = v;
+
+ /* we will first try default factory for certification: */
+
+ factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
+
+ dbg("SSL startup: " + host + " " + port);
+
+ /* create trust managers used if initial handshake fails: */
+
+ trustAllCerts = new TrustManager[] {
+ /*
+ * this one accepts everything.
+ */
+ new X509TrustManager() {
+ public java.security.cert.X509Certificate[]
+ getAcceptedIssuers() {
+ return null;
+ }
+ public void checkClientTrusted(
+ java.security.cert.X509Certificate[] certs,
+ String authType) {
+ /* empty */
+ }
+ public void checkServerTrusted(
+ java.security.cert.X509Certificate[] certs,
+ String authType) {
+ /* empty */
+ dbg("ALL: an untrusted connect to grab cert.");
+ }
+ }
+ };
+
+ trustUrlCert = new TrustManager[] {
+ /*
+ * this one accepts only the retrieved server cert
+ * by SSLSocket by this applet.
+ */
+ new X509TrustManager() {
+ public java.security.cert.X509Certificate[]
+ getAcceptedIssuers() {
+ return null;
+ }
+ public void checkClientTrusted(
+ java.security.cert.X509Certificate[] certs,
+ String authType) throws CertificateException {
+ throw new CertificateException("No Clients");
+ }
+ public void checkServerTrusted(
+ java.security.cert.X509Certificate[] certs,
+ String authType) throws CertificateException {
+ if (trusturlCerts == null) {
+ throw new CertificateException(
+ "No Trust url Certs array.");
+ }
+ if (trusturlCerts.length < 1) {
+ throw new CertificateException(
+ "No Trust url Certs.");
+ }
+ if (trusturlCerts.length > 1) {
+ int i;
+ boolean ok = true;
+ for (i = 0; i < trusturlCerts.length - 1; i++) {
+ if (! trusturlCerts[i].equals(trusturlCerts[i+1])) {
+ ok = false;
+ }
+ }
+ if (! ok) {
+ throw new CertificateException(
+ "Too many Trust url Certs: "
+ + trusturlCerts.length
+ );
+ }
+ }
+ if (certs == null) {
+ throw new CertificateException(
+ "No this-certs array.");
+ }
+ if (certs.length < 1) {
+ throw new CertificateException(
+ "No this-certs Certs.");
+ }
+ if (certs.length > 1) {
+ int i;
+ boolean ok = true;
+ for (i = 0; i < certs.length - 1; i++) {
+ if (! certs[i].equals(certs[i+1])) {
+ ok = false;
+ }
+ }
+ if (! ok) {
+ throw new CertificateException(
+ "Too many this-certs: "
+ + certs.length
+ );
+ }
+ }
+ if (! trusturlCerts[0].equals(certs[0])) {
+ throw new CertificateException(
+ "Server Cert Changed != URL.");
+ }
+ dbg("URL: trusturlCerts[0] matches certs[0]");
+ }
+ }
+ };
+ trustOneCert = new TrustManager[] {
+ /*
+ * this one accepts only the retrieved server cert
+ * by SSLSocket by this applet.
+ */
+ new X509TrustManager() {
+ public java.security.cert.X509Certificate[]
+ getAcceptedIssuers() {
+ return null;
+ }
+ public void checkClientTrusted(
+ java.security.cert.X509Certificate[] certs,
+ String authType) throws CertificateException {
+ throw new CertificateException("No Clients");
+ }
+ public void checkServerTrusted(
+ java.security.cert.X509Certificate[] certs,
+ String authType) throws CertificateException {
+ if (trustallCerts == null) {
+ throw new CertificateException(
+ "No Trust All Server Certs array.");
+ }
+ if (trustallCerts.length < 1) {
+ throw new CertificateException(
+ "No Trust All Server Certs.");
+ }
+ if (trustallCerts.length > 1) {
+ int i;
+ boolean ok = true;
+ for (i = 0; i < trustallCerts.length - 1; i++) {
+ if (! trustallCerts[i].equals(trustallCerts[i+1])) {
+ ok = false;
+ }
+ }
+ if (! ok) {
+ throw new CertificateException(
+ "Too many Trust All Server Certs: "
+ + trustallCerts.length
+ );
+ }
+ }
+ if (certs == null) {
+ throw new CertificateException(
+ "No this-certs array.");
+ }
+ if (certs.length < 1) {
+ throw new CertificateException(
+ "No this-certs Certs.");
+ }
+ if (certs.length > 1) {
+ int i;
+ boolean ok = true;
+ for (i = 0; i < certs.length - 1; i++) {
+ if (! certs[i].equals(certs[i+1])) {
+ ok = false;
+ }
+ }
+ if (! ok) {
+ throw new CertificateException(
+ "Too many this-certs: "
+ + certs.length
+ );
+ }
+ }
+ if (! trustallCerts[0].equals(certs[0])) {
+ throw new CertificateException(
+ "Server Cert Changed != TRUSTALL.");
+ }
+ dbg("ONE: trustallCerts[0] matches certs[0]");
+ }
+ }
+ };
+
+ /*
+ * They are used:
+ *
+ * 1) to retrieve the server cert in case of failure to
+ * display it to the user.
+ * 2) to subsequently connect to the server if user agrees.
+ */
+
+ KeyManager[] mykey = null;
+
+ if (viewer.oneTimeKey != null && viewer.oneTimeKey.equals("PROMPT")) {
+ ClientCertDialog d = new ClientCertDialog();
+ viewer.oneTimeKey = d.queryUser();
+ }
+
+ if (viewer.oneTimeKey != null && viewer.oneTimeKey.indexOf(",") > 0) {
+ int idx = viewer.oneTimeKey.indexOf(",");
+
+ String onetimekey = viewer.oneTimeKey.substring(0, idx);
+ byte[] key = hex2bytes(onetimekey);
+ String onetimecert = viewer.oneTimeKey.substring(idx+1);
+ byte[] cert = hex2bytes(onetimecert);
+
+ KeyFactory kf = KeyFactory.getInstance("RSA");
+ PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key );
+ PrivateKey ff = kf.generatePrivate (keysp);
+ //dbg("ff " + ff);
+ String cert_str = new String(cert);
+
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ Collection c = cf.generateCertificates(new ByteArrayInputStream(cert));
+ Certificate[] certs = new Certificate[c.toArray().length];
+ if (c.size() == 1) {
+ Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert));
+ //dbg("tmpcert" + tmpcert);
+ certs[0] = tmpcert;
+ } else {
+ certs = (Certificate[]) c.toArray();
+ }
+
+ KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(null, null);
+ ks.setKeyEntry("onetimekey", ff, "".toCharArray(), certs);
+ String da = KeyManagerFactory.getDefaultAlgorithm();
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(da);
+ kmf.init(ks, "".toCharArray());
+
+ mykey = kmf.getKeyManagers();
+ }
+
+
+ /* trust loc certs: */
+ try {
+ trustloc_ctx = SSLContext.getInstance("SSL");
+ trustloc_ctx.init(mykey, null, new
+ java.security.SecureRandom());
+
+ } catch (Exception e) {
+ String msg = "SSL trustloc_ctx FAILED.";
+ dbg(msg);
+ throw new Exception(msg);
+ }
+
+ /* trust all certs: */
+ try {
+ trustall_ctx = SSLContext.getInstance("SSL");
+ trustall_ctx.init(mykey, trustAllCerts, new
+ java.security.SecureRandom());
+
+ } catch (Exception e) {
+ String msg = "SSL trustall_ctx FAILED.";
+ dbg(msg);
+ throw new Exception(msg);
+ }
+
+ /* trust url certs: */
+ try {
+ trusturl_ctx = SSLContext.getInstance("SSL");
+ trusturl_ctx.init(mykey, trustUrlCert, new
+ java.security.SecureRandom());
+
+ } catch (Exception e) {
+ String msg = "SSL trusturl_ctx FAILED.";
+ dbg(msg);
+ throw new Exception(msg);
+ }
+
+ /* trust the one cert from server: */
+ try {
+ trustone_ctx = SSLContext.getInstance("SSL");
+ trustone_ctx.init(mykey, trustOneCert, new
+ java.security.SecureRandom());
+
+ } catch (Exception e) {
+ String msg = "SSL trustone_ctx FAILED.";
+ dbg(msg);
+ throw new Exception(msg);
+ }
+ }
+
+ boolean browser_cert_match() {
+ String msg = "Browser URL accept previously accepted cert";
+
+ if (user_wants_to_see_cert) {
+ return false;
+ }
+
+ if (trustallCerts != null && trusturlCerts != null) {
+ if (trustallCerts.length == 1 && trusturlCerts.length == 1) {
+ if (trustallCerts[0].equals(trusturlCerts[0])) {
+ System.out.println(msg);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public void check_for_proxy() {
+
+ boolean result = false;
+
+ trusturlCerts = null;
+ proxy_in_use = false;
+ if (viewer.ignoreProxy) {
+ return;
+ }
+
+ String ustr = "https://" + host + ":";
+ if (viewer.httpsPort != null) {
+ ustr += viewer.httpsPort;
+ } else {
+ ustr += port; // hmmm
+ }
+ ustr += viewer.urlPrefix + "/check.https.proxy.connection";
+ dbg("ustr is: " + ustr);
+
+
+ try {
+ URL url = new URL(ustr);
+ HttpsURLConnection https = (HttpsURLConnection)
+ url.openConnection();
+
+ https.setUseCaches(false);
+ https.setRequestMethod("GET");
+ https.setRequestProperty("Pragma", "No-Cache");
+ https.setRequestProperty("Proxy-Connection",
+ "Keep-Alive");
+ https.setDoInput(true);
+
+ https.connect();
+
+ trusturlCerts = https.getServerCertificates();
+ if (trusturlCerts == null) {
+ dbg("set trusturlCerts to null...");
+ } else {
+ dbg("set trusturlCerts to non-null");
+ }
+
+ if (https.usingProxy()) {
+ proxy_in_use = true;
+ proxy_is_https = true;
+ dbg("HTTPS proxy in use. There may be connection problems.");
+ }
+ Object output = https.getContent();
+ https.disconnect();
+ result = true;
+
+ } catch(Exception e) {
+ dbg("HttpsURLConnection: " + e.getMessage());
+ }
+
+ if (proxy_in_use) {
+ return;
+ }
+
+ ustr = "http://" + host + ":" + port;
+ ustr += viewer.urlPrefix + "/index.vnc";
+
+ try {
+ URL url = new URL(ustr);
+ HttpURLConnection http = (HttpURLConnection)
+ url.openConnection();
+
+ http.setUseCaches(false);
+ http.setRequestMethod("GET");
+ http.setRequestProperty("Pragma", "No-Cache");
+ http.setRequestProperty("Proxy-Connection",
+ "Keep-Alive");
+ http.setDoInput(true);
+
+ http.connect();
+
+ if (http.usingProxy()) {
+ proxy_in_use = true;
+ proxy_is_https = false;
+ dbg("HTTP proxy in use. There may be connection problems.");
+ }
+ Object output = http.getContent();
+ http.disconnect();
+
+ } catch(Exception e) {
+ dbg("HttpURLConnection: " + e.getMessage());
+ }
+ }
+
+ public Socket connectSock() throws IOException {
+
+ /*
+ * first try a https connection to detect a proxy, and
+ * also grab the VNC server cert.
+ */
+ check_for_proxy();
+
+ if (viewer.trustAllVncCerts) {
+ dbg("viewer.trustAllVncCerts-0 using trustall_ctx");
+ factory = trustall_ctx.getSocketFactory();
+ } else if (use_url_cert_for_auth && trusturlCerts != null) {
+ dbg("using trusturl_ctx");
+ factory = trusturl_ctx.getSocketFactory();
+ } else {
+ dbg("using trustloc_ctx");
+ factory = trustloc_ctx.getSocketFactory();
+ }
+
+ socket = null;
+ try {
+ if (proxy_in_use && viewer.forceProxy) {
+ throw new Exception("forcing proxy (forceProxy)");
+ } else if (viewer.CONNECT != null) {
+ throw new Exception("forcing CONNECT");
+ }
+
+ socket = (SSLSocket) factory.createSocket(host, port);
+
+ } catch (Exception esock) {
+ dbg("esock: " + esock.getMessage());
+ if (proxy_in_use || viewer.CONNECT != null) {
+ proxy_failure = true;
+ if (proxy_in_use) {
+ dbg("HTTPS proxy in use. Trying to go with it.");
+ } else {
+ dbg("viewer.CONNECT reverse proxy in use. Trying to go with it.");
+ }
+ try {
+ socket = proxy_socket(factory);
+ } catch (Exception e) {
+ dbg("err proxy_socket: " + e.getMessage());
+ }
+ }
+ }
+
+ try {
+ socket.startHandshake();
+ dbg("Server Connection Verified on 1st try.");
+
+ java.security.cert.Certificate[] currentTrustedCerts;
+ BrowserCertsDialog bcd;
+
+ SSLSession sess = socket.getSession();
+ currentTrustedCerts = sess.getPeerCertificates();
+
+ if (viewer.trustAllVncCerts) {
+ dbg("viewer.trustAllVncCerts-1");
+ } else if (currentTrustedCerts == null || currentTrustedCerts.length < 1) {
+ socket.close();
+ socket = null;
+ throw new SSLHandshakeException("no current certs");
+ }
+
+ String serv = "";
+ try {
+ CertInfo ci = new CertInfo(currentTrustedCerts[0]);
+ serv = ci.get_certinfo("CN");
+ } catch (Exception e) {
+ ;
+ }
+
+ if (viewer.trustAllVncCerts) {
+ dbg("viewer.trustAllVncCerts-2");
+ user_wants_to_see_cert = false;
+ } else if (viewer.trustUrlVncCert) {
+ dbg("viewer.trustUrlVncCert-1");
+ user_wants_to_see_cert = false;
+ } else {
+ bcd = new BrowserCertsDialog(serv, host + ":" + port);
+ bcd.queryUser();
+ if (bcd.showCertDialog) {
+ String msg = "user wants to see cert";
+ dbg(msg);
+ user_wants_to_see_cert = true;
+ throw new SSLHandshakeException(msg);
+ } else {
+ user_wants_to_see_cert = false;
+ dbg("bcd: user said yes, accept it");
+ }
+ }
+
+ } catch (SSLHandshakeException eh) {
+ dbg("Could not automatically verify Server.");
+ dbg("msg: " + eh.getMessage());
+
+ socket.close();
+ socket = null;
+
+ /*
+ * Reconnect, trusting any cert, so we can grab
+ * the cert to show it to the user. The connection
+ * is not used for anything else.
+ */
+ factory = trustall_ctx.getSocketFactory();
+ if (proxy_failure) {
+ socket = proxy_socket(factory);
+ } else {
+ socket = (SSLSocket) factory.createSocket(host, port);
+ }
+
+ try {
+ socket.startHandshake();
+ dbg("TrustAll Server Connection Verified.");
+
+ /* grab the cert: */
+ try {
+ SSLSession sess = socket.getSession();
+ trustallCerts = sess.getPeerCertificates();
+ } catch (Exception e) {
+ throw new Exception("Could not get " +
+ "Peer Certificate");
+ }
+
+ if (viewer.trustAllVncCerts) {
+ dbg("viewer.trustAllVncCerts-3");
+ } else if (! browser_cert_match()) {
+ /*
+ * close socket now, we will reopen after
+ * dialog if user agrees to use the cert.
+ */
+ socket.close();
+ socket = null;
+
+ /* dialog with user to accept cert or not: */
+
+ TrustDialog td= new TrustDialog(host, port,
+ trustallCerts);
+
+ if (! td.queryUser()) {
+ String msg = "User decided against it.";
+ dbg(msg);
+ throw new IOException(msg);
+ }
+ }
+
+ } catch (Exception ehand2) {
+ dbg("** Could not TrustAll Verify Server.");
+
+ throw new IOException(ehand2.getMessage());
+ }
+
+ /*
+ * Now connect a 3rd time, using the cert
+ * retrieved during connection 2 (that the user
+ * likely blindly agreed to).
+ */
+
+ factory = trustone_ctx.getSocketFactory();
+ if (proxy_failure) {
+ socket = proxy_socket(factory);
+ } else {
+ socket = (SSLSocket) factory.createSocket(host, port);
+ }
+
+ try {
+ socket.startHandshake();
+ dbg("TrustAll Server Connection Verified #3.");
+
+ } catch (Exception ehand3) {
+ dbg("** Could not TrustAll Verify Server #3.");
+
+ throw new IOException(ehand3.getMessage());
+ }
+ }
+
+ if (socket != null && viewer.GET) {
+ String str = "GET ";
+ str += viewer.urlPrefix;
+ str += "/request.https.vnc.connection";
+ str += " HTTP/1.0\r\n";
+ str += "Pragma: No-Cache\r\n";
+ str += "\r\n";
+ System.out.println("sending GET: " + str);
+ OutputStream os = socket.getOutputStream();
+ os.write(str.getBytes());
+ os.flush();
+ if (false) {
+ String rep = "";
+ DataInputStream is = new DataInputStream(
+ new BufferedInputStream(socket.getInputStream(), 16384));
+ while (true) {
+ rep += readline(is);
+ if (rep.indexOf("\r\n\r\n") >= 0) {
+ break;
+ }
+ }
+ System.out.println("rep: " + rep);
+ }
+ }
+
+ dbg("SSL returning socket to caller.");
+ return (Socket) socket;
+ }
+
+ private void dbg(String s) {
+ if (debug) {
+ System.out.println(s);
+ }
+ }
+
+ private int gint(String s) {
+ int n = -1;
+ try {
+ Integer I = new Integer(s);
+ n = I.intValue();
+ } catch (Exception ex) {
+ return -1;
+ }
+ return n;
+ }
+
+ public SSLSocket proxy_socket(SSLSocketFactory factory) {
+ Properties props = null;
+ String proxyHost = null;
+ int proxyPort = 0;
+ String proxyHost_nossl = null;
+ int proxyPort_nossl = 0;
+ String str;
+
+ /* see if we can guess the proxy info from Properties: */
+ try {
+ props = System.getProperties();
+ } catch (Exception e) {
+ dbg("props failed: " + e.getMessage());
+ }
+ if (props != null) {
+ dbg("\n---------------\nAll props:");
+ props.list(System.out);
+ dbg("\n---------------\n\n");
+
+ for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) {
+ String s = (String) e.nextElement();
+ String v = System.getProperty(s);
+ String s2 = s.toLowerCase();
+ String v2 = v.toLowerCase();
+
+ if (s2.indexOf("proxy") < 0 && v2.indexOf("proxy") < 0) {
+ continue;
+ }
+ if (v2.indexOf("https") < 0) {
+ continue;
+ }
+
+ if (s2.indexOf("proxy.https.host") >= 0) {
+ proxyHost = v2;
+ continue;
+ }
+ if (s2.indexOf("proxy.https.port") >= 0) {
+ proxyPort = gint(v2);
+ continue;
+ }
+ if (s2.indexOf("proxy.http.host") >= 0) {
+ proxyHost_nossl = v2;
+ continue;
+ }
+ if (s2.indexOf("proxy.http.port") >= 0) {
+ proxyPort_nossl = gint(v2);
+ continue;
+ }
+
+ String[] pieces = v.split("[,;]");
+ for (int i = 0; i < pieces.length; i++) {
+ String p = pieces[i];
+ int j = p.indexOf("https");
+ if (j < 0) {
+ continue;
+ }
+ j = p.indexOf("=", j);
+ if (j < 0) {
+ continue;
+ }
+ p = p.substring(j+1);
+ String [] hp = p.split(":");
+ if (hp.length != 2) {
+ continue;
+ }
+ if (hp[0].length() > 1 && hp[1].length() > 1) {
+
+ proxyPort = gint(hp[1]);
+ if (proxyPort < 0) {
+ continue;
+ }
+ proxyHost = new String(hp[0]);
+ break;
+ }
+ }
+ }
+ }
+ if (proxyHost != null) {
+ if (proxyHost_nossl != null && proxyPort_nossl > 0) {
+ dbg("Using http proxy info instead of https.");
+ proxyHost = proxyHost_nossl;
+ proxyPort = proxyPort_nossl;
+ }
+ }
+
+ if (proxy_in_use) {
+ if (proxy_dialog_host != null && proxy_dialog_port > 0) {
+ proxyHost = proxy_dialog_host;
+ proxyPort = proxy_dialog_port;
+ }
+ if (proxyHost != null) {
+ dbg("Lucky us! we figured out the Proxy parameters: " + proxyHost + " " + proxyPort);
+ } else {
+ /* ask user to help us: */
+ ProxyDialog pd = new ProxyDialog(proxyHost, proxyPort);
+ pd.queryUser();
+ proxyHost = pd.getHost();
+ proxyPort = pd.getPort();
+ proxy_dialog_host = new String(proxyHost);
+ proxy_dialog_port = proxyPort;
+ dbg("User said host: " + pd.getHost() + " port: " + pd.getPort());
+ }
+
+ dbg("proxy_in_use psocket:");
+ proxySock = psocket(proxyHost, proxyPort);
+ if (proxySock == null) {
+ dbg("1-a sadly, returning a null socket");
+ return null;
+ }
+ String hp = host + ":" + port;
+
+ String req1 = "CONNECT " + hp + " HTTP/1.1\r\n"
+ + "Host: " + hp + "\r\n\r\n";
+
+ dbg("requesting1: " + req1);
+
+ try {
+ proxy_os.write(req1.getBytes());
+ String reply = readline(proxy_is);
+
+ dbg("proxy replied1: " + reply.trim());
+
+ if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) {
+ proxySock.close();
+ proxySock = psocket(proxyHost, proxyPort);
+ if (proxySock == null) {
+ dbg("2-a sadly, returning a null socket");
+ return null;
+ }
+ }
+ } catch(Exception e) {
+ dbg("sock prob1: " + e.getMessage());
+ }
+
+ while (true) {
+ String line = readline(proxy_is);
+ dbg("proxy line1: " + line.trim());
+ if (line.equals("\r\n") || line.equals("\n")) {
+ break;
+ }
+ }
+ } else if (viewer.CONNECT != null) {
+ dbg("viewer.CONNECT psocket:");
+ proxySock = psocket(host, port);
+ if (proxySock == null) {
+ dbg("1-b sadly, returning a null socket");
+ return null;
+ }
+ }
+
+ if (viewer.CONNECT != null) {
+ String hp = viewer.CONNECT;
+ String req2 = "CONNECT " + hp + " HTTP/1.1\r\n"
+ + "Host: " + hp + "\r\n\r\n";
+
+ dbg("requesting2: " + req2);
+
+ try {
+ proxy_os.write(req2.getBytes());
+ String reply = readline(proxy_is);
+
+ dbg("proxy replied2: " + reply.trim());
+
+ if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) {
+ proxySock.close();
+ proxySock = psocket(proxyHost, proxyPort);
+ if (proxySock == null) {
+ dbg("2-b sadly, returning a null socket");
+ return null;
+ }
+ }
+ } catch(Exception e) {
+ dbg("sock prob2: " + e.getMessage());
+ }
+
+ while (true) {
+ String line = readline(proxy_is);
+ dbg("proxy line2: " + line.trim());
+ if (line.equals("\r\n") || line.equals("\n")) {
+ break;
+ }
+ }
+
+ }
+
+ Socket sslsock = null;
+ try {
+ sslsock = factory.createSocket(proxySock, host, port, true);
+ } catch(Exception e) {
+ dbg("sslsock prob: " + e.getMessage());
+ dbg("3 sadly, returning a null socket");
+ }
+
+ return (SSLSocket) sslsock;
+ }
+
+ Socket psocket(String h, int p) {
+ Socket psock = null;
+ try {
+ psock = new Socket(h, p);
+ proxy_is = new DataInputStream(new BufferedInputStream(
+ psock.getInputStream(), 16384));
+ proxy_os = psock.getOutputStream();
+ } catch(Exception e) {
+ dbg("psocket prob: " + e.getMessage());
+ return null;
+ }
+
+ return psock;
+ }
+
+ String readline(DataInputStream i) {
+ byte[] ba = new byte[1];
+ String s = new String("");
+ ba[0] = 0;
+ try {
+ while (ba[0] != 0xa) {
+ ba[0] = (byte) i.readUnsignedByte();
+ s += new String(ba);
+ }
+ } catch (Exception e) {
+ ;
+ }
+ return s;
+ }
+}
+
+class TrustDialog implements ActionListener {
+ String msg, host, text;
+ int port;
+ java.security.cert.Certificate[] trustallCerts = null;
+ boolean viewing_cert = false;
+ boolean trust_this_session = false;
+
+ /*
+ * this is the gui to show the user the cert and info and ask
+ * them if they want to continue using this cert.
+ */
+
+ Button ok, cancel, viewcert;
+ TextArea textarea;
+ Checkbox accept, deny;
+ Dialog dialog;
+
+ String s1 = "Accept this certificate temporarily for this session";
+ String s2 = "Do not accept this certificate and do not connect to"
+ + " this VNC server";
+ String ln = "\n---------------------------------------------------\n\n";
+
+ TrustDialog (String h, int p, java.security.cert.Certificate[] s) {
+ host = h;
+ port = p;
+ trustallCerts = s;
+
+ msg = "VNC Server " + host + ":" + port + " Not Verified";
+ }
+
+ public boolean queryUser() {
+
+ /* create and display the dialog for unverified cert. */
+
+ Frame frame = new Frame(msg);
+
+ dialog = new Dialog(frame, true);
+
+ String infostr = "";
+ if (trustallCerts.length == 1) {
+ CertInfo ci = new CertInfo(trustallCerts[0]);
+ infostr = ci.get_certinfo("all");
+ }
+
+ text = "\n"
++ "Unable to verify the identity of\n"
++ "\n"
++ " " + host + ":" + port + "\n"
++ "\n"
++ infostr
++ "\n"
++ "as a trusted VNC server.\n"
++ "\n"
++ "This may be due to:\n"
++ "\n"
++ " - Your requesting to View the Certificate before accepting.\n"
++ "\n"
++ " - The VNC server using a Self-Signed Certificate.\n"
++ "\n"
++ " - The VNC server using a Certificate Authority not recognized by your\n"
++ " Browser or Java Plugin runtime.\n"
++ "\n"
++ " - The use of an Apache SSL portal employing CONNECT proxying and the\n"
++ " Apache web server has a certificate different from the VNC server's. \n"
++ "\n"
++ " - A Man-In-The-Middle attack impersonating as the VNC server you wish\n"
++ " to connect to. (Wouldn't that be exciting!!)\n"
++ "\n"
++ "By safely copying the VNC server's Certificate (or using a common\n"
++ "Certificate Authority certificate) you can configure your Web Browser or\n"
++ "Java Plugin to automatically authenticate this Server.\n"
++ "\n"
++ "If you do so, then you will only have to click \"Yes\" when this VNC\n"
++ "Viewer applet asks you whether to trust your Browser/Java Plugin's\n"
++ "acceptance of the certificate. (except for the Apache portal case above.)\n"
+;
+
+ /* the accept / do-not-accept radio buttons: */
+ CheckboxGroup checkbox = new CheckboxGroup();
+ accept = new Checkbox(s1, true, checkbox);
+ deny = new Checkbox(s2, false, checkbox);
+
+ /* put the checkboxes in a panel: */
+ Panel check = new Panel();
+ check.setLayout(new GridLayout(2, 1));
+
+ check.add(accept);
+ check.add(deny);
+
+ /* make the 3 buttons: */
+ ok = new Button("OK");
+ cancel = new Button("Cancel");
+ viewcert = new Button("View Certificate");
+
+ ok.addActionListener(this);
+ cancel.addActionListener(this);
+ viewcert.addActionListener(this);
+
+ /* put the buttons in their own panel: */
+ Panel buttonrow = new Panel();
+ buttonrow.setLayout(new FlowLayout(FlowLayout.LEFT));
+ buttonrow.add(viewcert);
+ buttonrow.add(ok);
+ buttonrow.add(cancel);
+
+ /* label at the top: */
+ Label label = new Label(msg, Label.CENTER);
+ label.setFont(new Font("Helvetica", Font.BOLD, 16));
+
+ /* textarea in the middle */
+ textarea = new TextArea(text, 36, 64,
+ TextArea.SCROLLBARS_VERTICAL_ONLY);
+ textarea.setEditable(false);
+
+ /* put the two panels in their own panel at bottom: */
+ Panel bot = new Panel();
+ bot.setLayout(new GridLayout(2, 1));
+ bot.add(check);
+ bot.add(buttonrow);
+
+ /* now arrange things inside the dialog: */
+ dialog.setLayout(new BorderLayout());
+
+ dialog.add("North", label);
+ dialog.add("South", bot);
+ dialog.add("Center", textarea);
+
+ dialog.pack();
+ dialog.resize(dialog.preferredSize());
+
+ dialog.show(); /* block here til OK or Cancel pressed. */
+
+ return trust_this_session;
+ }
+
+ public synchronized void actionPerformed(ActionEvent evt) {
+
+ if (evt.getSource() == viewcert) {
+ /* View Certificate button clicked */
+ if (viewing_cert) {
+ /* show the original info text: */
+ textarea.setText(text);
+ viewcert.setLabel("View Certificate");
+ viewing_cert = false;
+ } else {
+ int i;
+ /* show all (likely just one) certs: */
+ textarea.setText("");
+ for (i=0; i < trustallCerts.length; i++) {
+ int j = i + 1;
+ textarea.append("Certificate[" +
+ j + "]\n\n");
+ textarea.append(
+ trustallCerts[i].toString());
+ textarea.append(ln);
+ }
+ viewcert.setLabel("View Info");
+ viewing_cert = true;
+
+ textarea.setCaretPosition(0);
+ }
+
+ } else if (evt.getSource() == ok) {
+ /* OK button clicked */
+ if (accept.getState()) {
+ trust_this_session = true;
+ } else {
+ trust_this_session = false;
+ }
+ dialog.dispose();
+
+ } else if (evt.getSource() == cancel) {
+ /* Cancel button clicked */
+ trust_this_session = false;
+
+ dialog.dispose();
+ }
+ }
+
+ String get_certinfo() {
+ String all = "";
+ String fields[] = {"CN", "OU", "O", "L", "C"};
+ int i;
+ if (trustallCerts.length < 1) {
+ all = "";
+ return all;
+ }
+ String cert = trustallCerts[0].toString();
+
+ /*
+ * For now we simply scrape the cert string, there must
+ * be an API for this... perhaps optionValue?
+ */
+
+ for (i=0; i < fields.length; i++) {
+ int f, t, t1, t2;
+ String sub, mat = fields[i] + "=";
+
+ f = cert.indexOf(mat, 0);
+ if (f > 0) {
+ t1 = cert.indexOf(", ", f);
+ t2 = cert.indexOf("\n", f);
+ if (t1 < 0 && t2 < 0) {
+ continue;
+ } else if (t1 < 0) {
+ t = t2;
+ } else if (t2 < 0) {
+ t = t1;
+ } else if (t1 < t2) {
+ t = t1;
+ } else {
+ t = t2;
+ }
+ if (t > f) {
+ sub = cert.substring(f, t);
+ all = all + " " + sub + "\n";
+ }
+ }
+ }
+ return all;
+ }
+}
+
+class ProxyDialog implements ActionListener {
+ String guessedHost = null;
+ String guessedPort = null;
+ /*
+ * this is the gui to show the user the cert and info and ask
+ * them if they want to continue using this cert.
+ */
+
+ Button ok;
+ Dialog dialog;
+ TextField entry;
+ String reply = "";
+
+ ProxyDialog (String h, int p) {
+ guessedHost = h;
+ try {
+ guessedPort = Integer.toString(p);
+ } catch (Exception e) {
+ guessedPort = "8080";
+ }
+ }
+
+ public void queryUser() {
+
+ /* create and display the dialog for unverified cert. */
+
+ Frame frame = new Frame("Need Proxy host:port");
+
+ dialog = new Dialog(frame, true);
+
+
+ Label label = new Label("Please Enter your https Proxy info as host:port", Label.CENTER);
+ //label.setFont(new Font("Helvetica", Font.BOLD, 16));
+ entry = new TextField(30);
+ ok = new Button("OK");
+ ok.addActionListener(this);
+
+ String guess = "";
+ if (guessedHost != null) {
+ guess = guessedHost + ":" + guessedPort;
+ }
+ entry.setText(guess);
+
+ dialog.setLayout(new BorderLayout());
+ dialog.add("North", label);
+ dialog.add("Center", entry);
+ dialog.add("South", ok);
+ dialog.pack();
+ dialog.resize(dialog.preferredSize());
+
+ dialog.show(); /* block here til OK or Cancel pressed. */
+ return;
+ }
+
+ public String getHost() {
+ int i = reply.indexOf(":");
+ if (i < 0) {
+ return "unknown";
+ }
+ String h = reply.substring(0, i);
+ return h;
+ }
+
+ public int getPort() {
+ int i = reply.indexOf(":");
+ int p = 8080;
+ if (i < 0) {
+ return p;
+ }
+ i++;
+ String ps = reply.substring(i);
+ try {
+ Integer I = new Integer(ps);
+ p = I.intValue();
+ } catch (Exception e) {
+ ;
+ }
+ return p;
+ }
+
+ public synchronized void actionPerformed(ActionEvent evt) {
+ System.out.println(evt.getActionCommand());
+ if (evt.getSource() == ok) {
+ reply = entry.getText();
+ dialog.dispose();
+ }
+ }
+}
+
+class ClientCertDialog implements ActionListener {
+
+ Button ok;
+ Dialog dialog;
+ TextField entry;
+ String reply = "";
+
+ ClientCertDialog() {
+ ;
+ }
+
+ public String queryUser() {
+
+ /* create and display the dialog for unverified cert. */
+
+ Frame frame = new Frame("Enter SSL Client Cert+Key String");
+
+ dialog = new Dialog(frame, true);
+
+
+ Label label = new Label("Please Enter the SSL Client Cert+Key String 308204c0...,...522d2d0a", Label.CENTER);
+ entry = new TextField(30);
+ ok = new Button("OK");
+ ok.addActionListener(this);
+
+ dialog.setLayout(new BorderLayout());
+ dialog.add("North", label);
+ dialog.add("Center", entry);
+ dialog.add("South", ok);
+ dialog.pack();
+ dialog.resize(dialog.preferredSize());
+
+ dialog.show(); /* block here til OK or Cancel pressed. */
+ return reply;
+ }
+
+ public synchronized void actionPerformed(ActionEvent evt) {
+ System.out.println(evt.getActionCommand());
+ if (evt.getSource() == ok) {
+ reply = entry.getText();
+ dialog.dispose();
+ }
+ }
+}
+
+class BrowserCertsDialog implements ActionListener {
+ Button yes, no;
+ Dialog dialog;
+ String vncServer;
+ String hostport;
+ public boolean showCertDialog = true;
+
+ BrowserCertsDialog(String serv, String hp) {
+ vncServer = serv;
+ hostport = hp;
+ }
+
+ public void queryUser() {
+
+ /* create and display the dialog for unverified cert. */
+
+ Frame frame = new Frame("Use Browser/JVM Certs?");
+
+ dialog = new Dialog(frame, true);
+
+ String m = "";
+m += "\n";
+m += "This VNC Viewer applet does not have its own keystore to track\n";
+m += "SSL certificates, and so cannot authenticate the certificate\n";
+m += "of the VNC Server:\n";
+m += "\n";
+m += " " + hostport + "\n\n " + vncServer + "\n";
+m += "\n";
+m += "on its own.\n";
+m += "\n";
+m += "However, it has noticed that your Web Browser or Java VM Plugin\n";
+m += "has previously accepted the same certificate. You may have set\n";
+m += "this up permanently or just for this session, or the server\n";
+m += "certificate was signed by a CA cert that your Web Browser or\n";
+m += "Java VM Plugin has.\n";
+m += "\n";
+m += "Should this VNC Viewer applet now connect to the above VNC server?\n";
+m += "\n";
+
+// String m = "\nShould this VNC Viewer applet use your Browser/JVM certs to\n";
+// m += "authenticate the VNC Server:\n";
+// m += "\n " + hostport + "\n\n " + vncServer + "\n\n";
+// m += "(NOTE: this *includes* any certs you have Just Now accepted in a\n";
+// m += "dialog box with your Web Browser or Java Applet Plugin)\n\n";
+
+ TextArea textarea = new TextArea(m, 20, 64,
+ TextArea.SCROLLBARS_VERTICAL_ONLY);
+ textarea.setEditable(false);
+ yes = new Button("Yes");
+ yes.addActionListener(this);
+ no = new Button("No, Let Me See the Certificate.");
+ no.addActionListener(this);
+
+ dialog.setLayout(new BorderLayout());
+ dialog.add("North", textarea);
+ dialog.add("Center", yes);
+ dialog.add("South", no);
+ dialog.pack();
+ dialog.resize(dialog.preferredSize());
+
+ dialog.show(); /* block here til Yes or No pressed. */
+ return;
+ }
+
+ public synchronized void actionPerformed(ActionEvent evt) {
+ System.out.println(evt.getActionCommand());
+ if (evt.getSource() == yes) {
+ showCertDialog = false;
+ dialog.dispose();
+ } else if (evt.getSource() == no) {
+ showCertDialog = true;
+ dialog.dispose();
+ }
+ }
+}
+
+class CertInfo {
+ String fields[] = {"CN", "OU", "O", "L", "C"};
+ java.security.cert.Certificate cert;
+ String certString = "";
+
+ CertInfo(java.security.cert.Certificate c) {
+ cert = c;
+ certString = cert.toString();
+ }
+
+ String get_certinfo(String which) {
+ int i;
+ String cs = new String(certString);
+ String all = "";
+
+ /*
+ * For now we simply scrape the cert string, there must
+ * be an API for this... perhaps optionValue?
+ */
+ for (i=0; i < fields.length; i++) {
+ int f, t, t1, t2;
+ String sub, mat = fields[i] + "=";
+
+ f = cs.indexOf(mat, 0);
+ if (f > 0) {
+ t1 = cs.indexOf(", ", f);
+ t2 = cs.indexOf("\n", f);
+ if (t1 < 0 && t2 < 0) {
+ continue;
+ } else if (t1 < 0) {
+ t = t2;
+ } else if (t2 < 0) {
+ t = t1;
+ } else if (t1 < t2) {
+ t = t1;
+ } else {
+ t = t2;
+ }
+ if (t > f) {
+ sub = cs.substring(f, t);
+ all = all + " " + sub + "\n";
+ if (which.equals(fields[i])) {
+ return sub;
+ }
+ }
+ }
+ }
+ if (which.equals("all")) {
+ return all;
+ } else {
+ return "";
+ }
+ }
+}
diff -Naur JavaViewer.orig/VncCanvas.java JavaViewer/VncCanvas.java
--- JavaViewer.orig/VncCanvas.java 2005-11-21 18:50:18.000000000 -0500
+++ JavaViewer/VncCanvas.java 2007-05-16 15:57:36.000000000 -0400
@@ -27,6 +27,9 @@
import java.lang.*;
import java.util.zip.*;
+// begin runge/x11vnc
+import java.util.Collections;
+// end runge/x11vnc
//
// VncCanvas is a subclass of Canvas which draws a VNC desktop on it.
@@ -85,6 +88,22 @@
cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
+// begin runge/x11vnc
+// kludge to not show any Java cursor in the canvas since we are
+// showing the soft cursor (should be a user setting...)
+Cursor dot = Toolkit.getDefaultToolkit().createCustomCursor(
+ Toolkit.getDefaultToolkit().createImage(new byte[4]), new Point(0,0),
+ "dot");
+this.setCursor(dot);
+
+// while we are at it... get rid of the keyboard traversals that
+// make it so we can't type a Tab character:
+this.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
+ Collections.EMPTY_SET);
+this.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
+ Collections.EMPTY_SET);
+// end runge/x11vnc
+
colors = new Color[256];
// sf@2005 - Now Default
for (int i = 0; i < 256; i++)
@@ -237,6 +256,9 @@
}
else
{
+// begin runge/x11vnc
+ viewer.options.oldEightBitColors = viewer.options.eightBitColors;
+// end runge/x11vnc
rfb.writeSetPixelFormat(
32,
24,
@@ -1532,9 +1554,14 @@
else
{
result =
- 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF)
- << 16 | (pixBuf[i * 4 + 2] & 0xFF)
- << 8 | (pixBuf[i * 4 + 3] & 0xFF);
+// begin runge/x11vnc
+// 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF)
+// << 16 | (pixBuf[i * 4 + 2] & 0xFF)
+// << 8 | (pixBuf[i * 4 + 3] & 0xFF);
+ 0xFF000000 | (pixBuf[i * 4 + 2] & 0xFF)
+ << 16 | (pixBuf[i * 4 + 1] & 0xFF)
+ << 8 | (pixBuf[i * 4 + 0] & 0xFF);
+// end runge/x11vnc
}
} else {
result = 0; // Transparent pixel
@@ -1565,9 +1592,14 @@
else
{
result =
- 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF)
- << 16 | (pixBuf[i * 4 + 2] & 0xFF)
- << 8 | (pixBuf[i * 4 + 3] & 0xFF);
+// begin runge/x11vnc
+// 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF)
+// << 16 | (pixBuf[i * 4 + 2] & 0xFF)
+// << 8 | (pixBuf[i * 4 + 3] & 0xFF);
+ 0xFF000000 | (pixBuf[i * 4 + 2] & 0xFF)
+ << 16 | (pixBuf[i * 4 + 1] & 0xFF)
+ << 8 | (pixBuf[i * 4 + 0] & 0xFF);
+// end runge/x11vnc
}
} else {
result = 0; // Transparent pixel
diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java
--- JavaViewer.orig/VncViewer.java 2006-05-24 15:14:40.000000000 -0400
+++ JavaViewer/VncViewer.java 2007-05-15 15:09:10.000000000 -0400
@@ -115,6 +115,22 @@
int i;
// mslogon support 2 end
+// begin runge/x11vnc
+boolean disableSSL;
+boolean GET;
+String CONNECT;
+String urlPrefix;
+String httpsPort;
+String oneTimeKey;
+boolean forceProxy;
+boolean ignoreProxy;
+boolean trustAllVncCerts;
+boolean trustUrlVncCert;
+
+boolean ignoreMSLogonCheck;
+// end runge/x11vnc
+
+
//
// init()
//
@@ -336,7 +352,12 @@
//
- prologueDetectAuthProtocol() ;
+// begin runge/x11vnc
+// prologueDetectAuthProtocol() ;
+ if (ignoreMSLogonCheck == false) {
+ prologueDetectAuthProtocol() ;
+ }
+// end runge/x11vnc
authenticator = new AuthPanel(mslogon);
@@ -435,7 +456,7 @@
rfb.readVersionMsg();
- System.out.println("RFB server supports protocol version " +
+ System.out.println("RFB server supports protocol version: " +
rfb.serverMajor + "." + rfb.serverMinor);
rfb.writeVersionMsg();
@@ -804,6 +825,75 @@
deferScreenUpdates = readIntParameter("Defer screen updates", 20);
deferCursorUpdates = readIntParameter("Defer cursor updates", 10);
deferUpdateRequests = readIntParameter("Defer update requests", 50);
+
+// begin runge/x11vnc
+ // SSL
+ disableSSL = false;
+ str = readParameter("DisableSSL", false);
+ if (str != null && str.equalsIgnoreCase("Yes"))
+ disableSSL = true;
+
+ httpsPort = readParameter("httpsPort", false);
+
+ // Extra GET, CONNECT string:
+ CONNECT = readParameter("CONNECT", false);
+ if (CONNECT != null) {
+ CONNECT = CONNECT.replaceAll(" ", ":");
+ }
+
+ GET = false;
+ str = readParameter("GET", false);
+ if (str != null && str.equalsIgnoreCase("Yes")) {
+ GET = true;
+ }
+ if (str != null && str.equalsIgnoreCase("1")) {
+ GET = true;
+ }
+
+ urlPrefix = readParameter("urlPrefix", false);
+ if (urlPrefix != null) {
+ urlPrefix = urlPrefix.replaceAll("%2F", "/");
+ urlPrefix = urlPrefix.replaceAll("%2f", "/");
+ urlPrefix = urlPrefix.replaceAll("_2F_", "/");
+ if (urlPrefix.indexOf("/") != 0) {
+ urlPrefix = "/" + urlPrefix;
+ }
+ } else {
+ urlPrefix = "";
+ }
+ System.out.println("urlPrefix: '" + urlPrefix + "'");
+
+ oneTimeKey = readParameter("oneTimeKey", false);
+ if (oneTimeKey != null) {
+ System.out.println("oneTimeKey: is set");
+ }
+
+ forceProxy = false;
+ str = readParameter("forceProxy", false);
+ if (str != null && str.equalsIgnoreCase("Yes")) {
+ forceProxy = true;
+ }
+ ignoreProxy = false;
+ str = readParameter("ignoreProxy", false);
+ if (str != null && str.equalsIgnoreCase("Yes")) {
+ ignoreProxy = true;
+ }
+ trustAllVncCerts = false;
+ str = readParameter("trustAllVncCerts", false);
+ if (str != null && str.equalsIgnoreCase("Yes")) {
+ trustAllVncCerts = true;
+ }
+ trustUrlVncCert = false;
+ str = readParameter("trustUrlVncCert", false);
+ if (str != null && str.equalsIgnoreCase("Yes")) {
+ trustUrlVncCert = true;
+ }
+ ignoreMSLogonCheck = false;
+ str = readParameter("ignoreMSLogonCheck", false);
+ if (str != null && str.equalsIgnoreCase("Yes")) {
+ ignoreMSLogonCheck = true;
+ }
+// end runge/x11vnc
}
public String readParameter(String name, boolean required) {
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment