From 5c53ccbbe99dbf098dbb396a65b487f08315d825 Mon Sep 17 00:00:00 2001
From: runge <runge@karlrunge.com>
Date: Fri, 9 Apr 2010 19:34:02 -0400
Subject: Improvements to Java viewer: troubleshooting settings and
 workarounds, misc bug fixes.

---
 classes/ssl/SignedUltraViewerSSL.jar               | Bin 112002 -> 112662 bytes
 classes/ssl/SignedVncViewer.jar                    | Bin 88016 -> 88734 bytes
 classes/ssl/UltraViewerSSL.jar                     | Bin 108926 -> 109588 bytes
 classes/ssl/VncViewer.jar                          | Bin 85036 -> 85754 bytes
 classes/ssl/ss_vncviewer                           | 433 +++++++++++++++++++--
 .../tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch   | 131 ++++++-
 classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch  | 122 ++++--
 7 files changed, 616 insertions(+), 70 deletions(-)

diff --git a/classes/ssl/SignedUltraViewerSSL.jar b/classes/ssl/SignedUltraViewerSSL.jar
index e32079f..7f1c312 100644
Binary files a/classes/ssl/SignedUltraViewerSSL.jar and b/classes/ssl/SignedUltraViewerSSL.jar differ
diff --git a/classes/ssl/SignedVncViewer.jar b/classes/ssl/SignedVncViewer.jar
index 8e54308..b5b0b7d 100644
Binary files a/classes/ssl/SignedVncViewer.jar and b/classes/ssl/SignedVncViewer.jar differ
diff --git a/classes/ssl/UltraViewerSSL.jar b/classes/ssl/UltraViewerSSL.jar
index c037905..e90582a 100644
Binary files a/classes/ssl/UltraViewerSSL.jar and b/classes/ssl/UltraViewerSSL.jar differ
diff --git a/classes/ssl/VncViewer.jar b/classes/ssl/VncViewer.jar
index 862bb20..a78bde3 100644
Binary files a/classes/ssl/VncViewer.jar and b/classes/ssl/VncViewer.jar differ
diff --git a/classes/ssl/ss_vncviewer b/classes/ssl/ss_vncviewer
index 7ad1811..63ddac5 100755
--- a/classes/ssl/ss_vncviewer
+++ b/classes/ssl/ss_vncviewer
@@ -382,7 +382,9 @@ if [ "X$reverse" != "X" ]; then
 			echo "*Warning*: -listen and a single proxy/gateway does not make sense."
 			sleep 2
 		fi
-		SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE
+
+		# we now try to PPROXY_LOOP_THYSELF, set this var to disable that.
+		#SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE
 	fi
 fi
 if [ "X$ssh_cmd" = "X" ]; then
@@ -520,12 +522,6 @@ if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then
 	fi
 fi
 
-# (possibly) tell the vncviewer to only listen on lo: 
-if [ "X$reverse" != "X" -a "X$direct_connect" = "X" ]; then
-	VNCVIEWER_LISTEN_LOCALHOST=1
-	export VNCVIEWER_LISTEN_LOCALHOST
-fi
-
 # rsh mode is an internal/secret thing only I use.
 rsh=""
 if echo "$orig" | grep '^rsh://' > /dev/null; then
@@ -551,11 +547,98 @@ else
 fi
 
 # extract host and disp number:
-host=`echo "$orig" | awk -F: '{print $1}'`
-disp=`echo "$orig" | awk -F: '{print $2}'`
+
+# try to see if it is ipv6 address:
+ipv6=0
+if echo "$orig" | grep '\[' > /dev/null; then
+	# ipv6 [fe80::219:dbff:fee5:3f92%eth1]:5900
+	host=`echo "$orig" | sed -e 's/\].*$//' -e 's/\[//'`
+	disp=`echo "$orig" | sed -e 's/^.*\]://'`
+	ipv6=1
+elif echo "$orig" | grep ':..*:' > /dev/null; then
+	# ipv6 fe80::219:dbff:fee5:3f92%eth1:5900
+	host=`echo "$orig" | sed -e 's/:[^:]*$//'`
+	disp=`echo "$orig" | sed -e 's/^.*://'`
+	ipv6=1
+else
+	# regular host:port
+	host=`echo "$orig" | awk -F: '{print $1}'`
+	disp=`echo "$orig" | awk -F: '{print $2}'`
+fi
+
+if [ "X$reverse" != "X" -a "X$STUNNEL_LISTEN" = "X" -a "X$host" != "X" ]; then
+	STUNNEL_LISTEN=$host
+	echo "set STUNNEL_LISTEN=$STUNNEL_LISTEN"
+fi
+
 if [ "X$host" = "X" ]; then
 	host=$localhost
 fi
+
+if [ "X$SSVNC_IPV6" = "X0" ]; then
+	# disable checking for it.
+	ipv6=0
+#elif [ "X$reverse" != "X" -a "X$ipv6" = "X1" ]; then
+#	ipv6=0
+elif [ "X$ipv6" = "X1" ]; then
+	:
+elif echo "$host" | grep '^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' > /dev/null; then
+	:
+else
+	# regular hostname, can't be sure...
+	host "$host" >/dev/null 2>&1
+	host "$host" >/dev/null 2>&1
+	hout=`host "$host" 2>/dev/null`
+	if echo "$hout" | grep -i 'has ipv6 address' > /dev/null; then
+		if echo "$hout" | grep -i 'has address' > /dev/null; then
+			:
+		else
+			echo "ipv6: "`echo "$hout" | grep -i 'has ipv6 address' | head -n 1`
+			ipv6=1
+		fi
+	fi
+	if [ "X$ipv6" = "X0" ]; then
+		dout=`dig -t any "$host" 2>/dev/null`
+		if echo "$dout" | grep -i "^$host" | grep '[ 	]AAAA[ 	]' > /dev/null; then
+			if echo "$dout" | grep -i "^$host" | grep '[ 	]A[ 	]' > /dev/null; then
+				:
+			else
+				echo "ipv6: "`echo "$dout" | grep -i '[ 	]AAAA[ 	]' | head -n 1`
+				ipv6=1
+			fi
+		fi
+	fi
+	if [ "X$ipv6" = "X0" ]; then
+		sout=`env LOOKUP="$host" \
+		      perl -e '	eval {use Socket};  exit 0 if $@;
+				eval {use Socket6}; exit 0 if $@;
+				@res = getaddrinfo($ENV{LOOKUP}, "daytime", AF_UNSPEC, SOCK_STREAM);
+				$ipv4 = 0;
+				$ipv6 = 0;
+				$ip6 = "";
+				while (scalar(@res) >= 5) {
+					($family, $socktype, $proto, $saddr, $canon, @res) = @res;
+					$ipv4 = 1 if $family == AF_INET;
+					$ipv6 = 1 if $family == AF_INET6;
+					if ($family == AF_INET6 && $ip6 eq "") {
+						my ($host, $port) = getnameinfo($saddr, NI_NUMERICHOST | NI_NUMERICSERV);
+						$ip6 = $host;
+					}
+				}
+				if (! $ipv4 && $ipv6) {
+					print "AF_INET6_ONLY: $ENV{LOOKUP}: $ip6\n";
+				}
+				exit 0;
+			' 2>/dev/null`
+		if echo "$sout" | grep AF_INET6_ONLY > /dev/null; then
+			echo "$sout"
+			ipv6=1
+		fi
+	fi
+fi
+if [ "X$ipv6" = "X1" ]; then
+	echo "ipv6: addr=$host disp=$disp"
+fi
 if [ "X$disp" = "X" ]; then
 	port=""	# probably -listen mode.
 elif [ $disp -lt 0 ]; then
@@ -573,6 +656,21 @@ else
 	port=$disp
 fi
 
+if [ "X$ipv6" = "X1" -a "X$direct_connect" = "X1" ]; then
+	if [ "X$proxy" = "X" -a "X$reverse" = "X" ]; then
+		proxy="ipv6://$host:$port"
+		echo "direct connect: set proxy=$proxy"
+	fi
+fi
+
+# (possibly) tell the vncviewer to only listen on lo: 
+if [ "X$reverse" != "X" ]; then
+	if [ "X$direct_connect" = "X" -o "X$proxy" != "X" -o "X$STUNNEL_LISTEN" != "X" ]; then
+		VNCVIEWER_LISTEN_LOCALHOST=1
+		export VNCVIEWER_LISTEN_LOCALHOST
+	fi
+fi
+
 # try to find an open listening port via netstat(1):
 inuse=""
 if uname | grep Linux > /dev/null; then
@@ -787,6 +885,60 @@ pcode() {
 
 use IO::Socket::INET;
 
+my $have_inet6 = "";
+eval "use IO::Socket::INET6;";
+$have_inet6 = 1 if $@ eq "";
+
+#my $have_sock6 = "";
+#eval "use Socket; use Socket6;";
+#$have_sock6 = 1 if $@ eq "";
+
+if (exists $ENV{PPROXY_LOOP_THYSELF}) {
+	# used for reverse vnc, run a repeating outer loop.
+	print STDERR "PPROXY_LOOP: $ENV{PPROXY_LOOP_THYSELF}\n";
+	my $rm = $ENV{PPROXY_REMOVE};
+	my $lp = $ENV{PPROXY_LOOP_THYSELF};
+	delete $ENV{PPROXY_REMOVE};
+	delete $ENV{PPROXY_LOOP_THYSELF};
+	$ENV{PPROXY_LOOP_THYSELF_MASTER} = $$;
+	my $pid = $$;
+	my $dbg = 0;
+	my $c = 0;
+	use POSIX ":sys_wait_h";
+	while (1) {
+		$pid = fork();
+		last if ! defined $pid;
+		if ($pid eq "0") {
+			last;
+		}
+		$c++;
+		print STDERR "\nPPROXY_LOOP: pid=$$ child=$pid count=$c\n";
+		while (1) {
+			waitpid(-1, WNOHANG);
+			fsleep(0.25);
+			if (! kill 0, $pid) {
+				print STDERR "PPROXY_LOOP: child=$pid gone.\n";
+				last;
+			}
+			print STDERR "PPROXY_LOOP: child=$pid alive.\n" if $dbg;
+			if (! -f $lp) {
+				print STDERR "PPROXY_LOOP: flag file $lp gone, killing $pid\n";
+				kill TERM, $pid;
+				fsleep(0.1);
+				wait;
+				last;
+			}
+			print STDERR "PPROXY_LOOP: file exists $lp\n" if $dbg;
+		}
+		last if ! -f $lp;
+		fsleep(0.25);
+	}
+	if ($pid ne "0") {
+		unlink($0) if $rm;
+		exit 0;
+	}
+}
+
 if (exists $ENV{PPROXY_SLEEP} && $ENV{PPROXY_SLEEP} > 0) {
 	print STDERR "PPROXY_PID: $$\n";
 	sleep $ENV{PPROXY_SLEEP};
@@ -835,7 +987,7 @@ if (exists $ENV{SSVNC_PREDIGESTED_HANDSHAKE})  {
 }
 
 my $have_gettimeofday = 0;
-eval "use Time::HiRes";
+eval "use Time::HiRes;";
 if ($@ eq "") {
 	$have_gettimeofday = 1;
 }
@@ -862,7 +1014,11 @@ my ($mode_1st, $mode_2nd, $mode_3rd) = ("", "", "");
 
 ($first, $mode_1st) = url_parse($first);
 
-my ($proxy_host, $proxy_port) = split(/:/, $first);
+my ($proxy_host, $proxy_port) = ($first, "");
+if ($proxy_host =~ /^(.*):(\d+)$/) {
+	$proxy_host = $1;
+	$proxy_port = $2;
+}
 my $connect = $ENV{PPROXY_DEST};
 
 if ($second ne "") {
@@ -875,13 +1031,15 @@ if ($third ne "") {
 
 
 print STDERR "\n";
-print STDERR "PPROXY v0.3: a tool for Web, SOCKS, and UltraVNC proxies and VeNCrypt bridging.\n";
+print STDERR "PPROXY v0.4: a tool for Web, SOCKS, and UltraVNC proxies and for\n";
+print STDERR "PPROXY v0.4: IPv6 and VNC VeNCrypt bridging.\n";
 print STDERR "proxy_host:       $proxy_host\n";
 print STDERR "proxy_port:       $proxy_port\n";
 print STDERR "proxy_connect:    $connect\n";
 print STDERR "pproxy_params:    $ENV{PPROXY_PROXY}\n";
 print STDERR "pproxy_listen:    $ENV{PPROXY_LISTEN}\n";
 print STDERR "pproxy_reverse:   $ENV{PPROXY_REVERSE}\n";
+print STDERR "io_socket_inet6:  $have_inet6\n";
 print STDERR "\n";
 if (1) {
 	print STDERR "pproxy 1st: $first\t- $mode_1st\n";
@@ -897,15 +1055,29 @@ sub pdie {
 }
 
 if ($ENV{PPROXY_REVERSE} ne "") {
-	my ($rhost, $rport) = split(/:/, $ENV{PPROXY_REVERSE});
+	my ($rhost, $rport) = ($ENV{PPROXY_REVERSE}, "");
+	if ($rhost =~ /^(.*):(\d+)$/) {
+		$rhost = $1;
+		$rport = $2;
+	}
 	$rport = 5900 unless $rport;
+	my $emsg = "";
 	$listen_handle = IO::Socket::INET->new(
 		PeerAddr => $rhost,
 		PeerPort => $rport,
 		Proto => "tcp"
 	);
+	$emsg = $!;
+	if (! $listen_handle && $have_inet6) {
+		eval {$listen_handle = IO::Socket::INET6->new(
+			PeerAddr => $rhost,
+			PeerPort => $rport,
+			Proto => "tcp"
+		);};
+		$emsg .= " / $!";
+	}
 	if (! $listen_handle) {
-		pdie "pproxy: $! -- PPROXY_REVERSE\n";
+		pdie "pproxy: $emsg -- PPROXY_REVERSE\n";
 	}
 	print STDERR "PPROXY_REVERSE: connected to $rhost $rport\n";
 
@@ -914,27 +1086,75 @@ if ($ENV{PPROXY_REVERSE} ne "") {
 	my $maxtry = 12;
 	my $sleep = 5;
 	my $p2 = "";
+	my $emsg = "";
 	for (my $i=0; $i < $maxtry; $i++)  {
-		if ($ENV{PPROXY_LISTEN} =~ /^INADDR_ANY:(.*)/) {
-			my $p = $1;
-			$p2 = "*:$p";
+		my ($if, $p) = ("", $ENV{PPROXY_LISTEN});
+		if ($p =~ /^(.*):(\d+)$/) {
+			$if = $1;
+			$p = $2;
+		}
+		$p2 = "*:$p";
+		if ($if eq "") {
+			$if = "localhost";
+		}
+		print STDERR "pproxy interface: $if\n";
+
+		$emsg = "";
+		if (($if eq "INADDR_ANY6" || $if eq "::") && $have_inet6) {
+			eval {$listen_sock = IO::Socket::INET6->new(
+				Listen    => 2,
+				ReuseAddr => 1,
+				Domain    => AF_INET6,
+				LocalAddr => "::",
+				LocalPort => $p,
+				Proto     => "tcp"
+			);};
+			$p2 = ":::$p";
+		} elsif ($if =~ /^INADDR_ANY/) {
 			$listen_sock = IO::Socket::INET->new(
 				Listen    => 2,
+				ReuseAddr => 1,
 				LocalPort => $p,
 				Proto     => "tcp"
 			);
+		} elsif (($if eq "INADDR_LOOPBACK6" || $if eq "::1") && $have_inet6) {
+			$p2 = "::1:$p";
+			eval {$listen_sock = IO::Socket::INET6->new(
+				Listen    => 2,
+				ReuseAddr => 1,
+				Domain    => AF_INET6,
+				LocalAddr => "::1",
+				LocalPort => $p,
+				Proto     => "tcp"
+			);};
+			$p2 = "::1:$p";
 		} else {
-			$p2 = "localhost:$ENV{PPROXY_LISTEN}";
+			$p2 = "$if:$p";
 			$listen_sock = IO::Socket::INET->new(
 				Listen    => 2,
-				LocalAddr => "127.0.0.1",
-				LocalPort => $ENV{PPROXY_LISTEN},
+				ReuseAddr => 1,
+				LocalAddr => $if,
+				LocalPort => $p,
 				Proto     => "tcp"
 			);
+			$emsg = $!;
+			
+			if (! $listen_sock && $have_inet6) {
+				print STDERR "PPROXY_LISTEN: retry with INET6\n";
+				eval {$listen_sock = IO::Socket::INET6->new(
+					Listen    => 2,
+					ReuseAddr => 1,
+					Domain    => AF_INET6,
+					LocalAddr => $if,
+					LocalPort => $p,
+					Proto     => "tcp"
+				);};
+				$emsg .= " / $!";
+			}
 		}
 		if (! $listen_sock) {
 			if ($i < $maxtry - 1) {
-				warn "pproxy: $!\n";
+				warn "pproxy: $emsg $!\n";
 				warn "Could not listen on port $p2, retrying in $sleep seconds... (Ctrl-C to quit)\n";
 				sleep $sleep;
 			}
@@ -943,7 +1163,7 @@ if ($ENV{PPROXY_REVERSE} ne "") {
 		}
 	}
 	if (! $listen_sock) {
-		pdie "pproxy: $! -- PPROXY_LISTEN\n";
+		pdie "pproxy: $emsg -- PPROXY_LISTEN\n";
 	}
 	print STDERR "pproxy: listening on $p2\n";
 	my $ip;
@@ -953,6 +1173,24 @@ if ($ENV{PPROXY_REVERSE} ne "") {
 	if (! $listen_handle) {
 		pdie "pproxy: $err\n";
 	}
+
+	if ($ENV{PPROXY_LOOP_THYSELF_MASTER}) {
+		my $sml = $ENV{SSVNC_MULTIPLE_LISTEN}; 
+		if ($sml ne "" && $sml ne "0") {
+			setpgrp(0, 0);
+			if (fork()) {
+				close $viewer_sock;
+				wait;
+				exit 0;
+			}
+			if (fork()) {
+				close $viewer_sock;
+				exit 0;
+			}
+			setpgrp(0, 0);
+			$parent = $$;
+		}
+	}
 }
 
 $sock = IO::Socket::INET->new(
@@ -961,15 +1199,27 @@ $sock = IO::Socket::INET->new(
 	Proto => "tcp"
 );
 
+my $err = "";
+
+if (! $sock && $have_inet6) {
+	$err = $!;
+
+	eval {$sock = IO::Socket::INET6->new(
+		PeerAddr => $proxy_host,
+		PeerPort => $proxy_port,
+		Proto => "tcp"
+	);};
+	$err .= " / $!";
+}
+
 if (! $sock) {
-	my $err = $!;
 	unlink($0) if $ENV{PPROXY_REMOVE};
 	pdie "pproxy: $err\n";
 }
 
 unlink($0) if $ENV{PPROXY_REMOVE};
 
-if ($ENV{PPROXY_PROXY} =~ /^vencrypt:/ && $ENV{PPROXY_LISTEN} =~ /^INADDR_ANY:/) {
+if ($ENV{PPROXY_PROXY} =~ /^vencrypt:/ && $ENV{PPROXY_VENCRYPT_REVERSE}) {
 	print STDERR "\nPPROXY: vencrypt+reverse: swapping listen socket with connect socket.\n";
 	my $tmp_swap = $sock;
 	$sock = $listen_handle;
@@ -1116,6 +1366,10 @@ xfer_both();
 
 exit;
 
+sub fsleep {
+	select(undef, undef, undef, shift);
+}
+
 sub url_parse {
 	my $hostport = shift;
 	my $mode = "http";
@@ -1128,11 +1382,14 @@ sub url_parse {
 	} elsif ($hostport =~ m,^https?://(\S*)$,i) {
 		$mode = "http";
 		$hostport = $1;
+	} elsif ($hostport =~ m,^ipv6://(\S*)$,i) {
+		$mode = "ipv6";
+		$hostport = $1;
 	} elsif ($hostport =~ m,^repeater://(\S*)\+(\S*)$,i) {
 		# ultravnc repeater proxy.
 		$hostport = $1;
 		$mode = "repeater:$2";
-		if ($hostport !~ /:\d+/) {
+		if ($hostport !~ /:\d+$/) {
 			$hostport .= ":5900";
 		}
 	} elsif ($hostport =~ m,^vencrypt://(\S*)$,i) {
@@ -1144,7 +1401,7 @@ sub url_parse {
 			$mode = $2;
 		}
 		$mode = "vencrypt:$m";
-		if ($hostport !~ /:\d+/) {
+		if ($hostport !~ /:\d+$/) {
 			$hostport .= ":5900";
 		}
 	}
@@ -1161,6 +1418,8 @@ sub setmode {
 		} else {
 			$ENV{PPROXY_SOCKS} = 1;
 		}
+	} elsif ($mode =~ /^ipv6/i) {
+		$ENV{PPROXY_SOCKS} = 0;
 	} elsif ($mode =~ /^repeater:(.*)/) {
 		$ENV{PPROXY_REPEATER} = $1;
 		$ENV{PPROXY_SOCKS} = "";
@@ -1180,7 +1439,11 @@ sub connection {
 
 	if ($ENV{PPROXY_SOCKS} eq "5") {
 		# SOCKS5
-		my ($h, $p) = split(/:/, $CONNECT);
+		my ($h, $p) = ($CONNECT, "");
+		if ($h =~ /^(.*):(\d+)$/) {
+			$h = $1;
+			$p = $2;
+		}
 		$con .= pack("C", 0x05);
 		$con .= pack("C", 0x01);
 		$con .= pack("C", 0x00);
@@ -1242,9 +1505,13 @@ sub connection {
 			exit(1);
 		}
 
-	} elsif ($ENV{PPROXY_SOCKS} ne "") {
+	} elsif ($ENV{PPROXY_SOCKS} eq "1") {
 		# SOCKS4 SOCKS4a
-		my ($h, $p) = split(/:/, $CONNECT);
+		my ($h, $p) = ($CONNECT, "");
+		if ($h =~ /^(.*):(\d+)$/) {
+			$h = $1;
+			$p = $2;
+		}
 		$con .= pack("C", 0x04);
 		$con .= pack("C", 0x01);
 		$con .= pack("n", $p);
@@ -1296,6 +1563,9 @@ sub connection {
 			close $sock;
 			exit(1);
 		}
+	} elsif ($ENV{PPROXY_SOCKS} eq "0") {
+		# hack for ipv6 "proxy", nothing to do, assume INET6 call worked.
+		;
 	} elsif ($ENV{PPROXY_REPEATER} ne "") {
 		my $rep = $ENV{PPROXY_REPEATER};
 		print STDERR "repeater: $rep\n";
@@ -1582,6 +1852,7 @@ sub do_vencrypt_viewer_bridge {
 	for (my $i=0; $i < $maxtry; $i++)  {
 		$listen_sock = IO::Socket::INET->new(
 			Listen    => 2,
+			ReuseAddr => 1,
 			LocalAddr => "127.0.0.1",
 			LocalPort => $listen,
 			Proto     => "tcp"
@@ -1606,6 +1877,23 @@ sub do_vencrypt_viewer_bridge {
 	if (! $viewer_sock) {
 		die "pproxy: vencrypt_viewer_bridge[$$]: $err\n";
 	}
+	if ($ENV{PPROXY_LOOP_THYSELF_MASTER}) {
+		my $sml = $ENV{SSVNC_MULTIPLE_LISTEN}; 
+		if ($sml ne "" && $sml ne "0") {
+			setpgrp(0, 0);
+			if (fork()) {
+				close $viewer_sock;
+				wait;
+				exit 0;
+			}
+			if (fork()) {
+				close $viewer_sock;
+				exit 0;
+			}
+			setpgrp(0, 0);
+			$parent = $$;
+		}
+	}
 	print STDERR "vencrypt_viewer_bridge[$$]: viewer_sock $viewer_sock\n" if $db;
 
 	print STDERR "pproxy: vencrypt_viewer_bridge[$$]: connecting to 127.0.0.1:$connect\n";
@@ -2055,13 +2343,18 @@ NHAFL_warning() {
 	echo "** Warning: you to manually remove a key from ~/.ssh/known_hosts.)"
 	echo "** Warning: "
 	echo "** Warning: This decreases security: a Man-In-The-Middle attack is possible."
+	echo "** Warning: For chained ssh connections the first ssh leg is secure but the"
+	echo "** Warning: 2nd ssh leg is vulnerable.  For an ssh connection going through"
+	echo "** Warning: a HTTP or SOCKS proxy the ssh connection is vulnerable."
+	echo "** Warning: "
 	echo "** Warning: You can set the SSVNC_SSH_LOCALHOST_AUTH=1 env. var. to disable" 
-	echo "** Warning: using the NoHostAuthenticationForLocalhost ssh option." 
+	echo "** Warning: using the NoHostAuthenticationForLocalhost=yes ssh option." 
 	echo "** Warning: "
 	echo "** Warning: A better solution is to configure (in the SSVNC GUI) the setting:"
 	echo "** Warning: 'Options -> Advanced -> Private SSH KnownHosts file' (or set" 
 	echo "** Warning: SSVNC_KNOWN_HOSTS_FILE directly) to a per-connection known hosts" 
-	echo "** Warning: file.  This yields a both secure and convenient solution." 
+	echo "** Warning: file.  That file holds the 'localhost' cert for this specific" 
+	echo "** Warning: connection.  This yields a both secure and convenient solution." 
 	echo "" 
 }
 
@@ -2243,6 +2536,7 @@ if [ "X$use_ssh" = "X1" ]; then
 
 		nd=`findfree 6600`
 		PPROXY_LISTEN=$nd; export PPROXY_LISTEN
+		# XXX no reverse forever PPROXY_LOOP_THYSELF ...
 		$ptmp &
 		sleep 1
 		if [ "X$ssh_NHAFL" != "X" -a "X$did_ssh_NHAFL" != "X1" ]; then
@@ -2633,6 +2927,16 @@ if [ "X$crl" != "X" ]; then
 	fi
 fi
 
+if [ "X$showcert" = "X1" ]; then
+	if [ "X$ipv6" = "X1" -a "X$proxy" = "X" ]; then
+		proxy="ipv6://$host:$port"
+	fi
+fi
+
+if [ "X$direct_connect" != "X" -a "X$STUNNEL_LISTEN" != "X" ]; then
+	proxy=reverse_direct
+fi
+
 ptmp=""
 if [ "X$proxy" != "X" ]; then
 	ptmp="/tmp/ss_vncviewer${RANDOM}.$$.pl"
@@ -2841,9 +3145,22 @@ if [ "X$direct_connect" != "X" ]; then
 			PPROXY_LISTEN=$use
 			export PPROXY_LISTEN
 		else
-			PPROXY_REVERSE="$localhost:$use"
-			export PPROXY_REVERSE
-			pps=3
+			if [ "X$proxy" = "Xreverse_direct" ]; then
+				PPROXY_LISTEN="$STUNNEL_LISTEN:`expr 5500 + $disp`"
+				PPROXY_DEST="$localhost:$use"
+				PPROXY_PROXY="ipv6://$localhost:$use"	# not always ipv6..
+				export PPROXY_LISTEN PPROXY_DEST PPROXY_PROXY
+				pps=1
+			else
+				PPROXY_REVERSE="$localhost:$use"
+				export PPROXY_LISTEN
+				pps=3
+			fi
+			if [ "X$SSVNC_LISTEN_ONCE" != "X1" ]; then
+				PPROXY_LOOP_THYSELF=`mytmp "/tmp/pproxy_loop_thyself.${RANDOM}.$$"`
+				export PPROXY_LOOP_THYSELF
+				pps=2
+			fi
 			if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then
 				pps=`expr $pps + $SSVNC_EXTRA_SLEEP`
 			fi
@@ -2904,10 +3221,13 @@ if [ "X$direct_connect" != "X" ]; then
 		echo ""
 		trap "final" 0 2 15
 		if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then
-			echo "NOTE: The ultravnc_dsm_helper only runs once.  So after the first LISTEN"
-			echo "      ends, you may have to Press Ctrl-C and restart for another connection."
-			echo ""
-			SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE
+			if [ "X$SSVNC_LISTEN_ONCE" = "X1" ]; then
+				echo "NOTE: The ultravnc_dsm_helper only runs once.  So after the first LISTEN"
+				echo "      ends you must restart the Listening mode.  You may also need to"
+				echo "      Press Ctrl-C to stop the viewer and restart for another connection."
+				echo ""
+			fi
+			#SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE
 			VNCVIEWER_LISTEN_LOCALHOST=1
 			export VNCVIEWER_LISTEN_LOCALHOST
 			dport=`expr 5500 + $disp`
@@ -2917,8 +3237,13 @@ if [ "X$direct_connect" != "X" ]; then
 			echo
 			echo "$ustr &"
 			echo
-			$cmd &
-			dsm_pid=$!
+			if [ "X$SSVNC_LISTEN_ONCE" = "X1" ]; then
+				$cmd &
+				dsm_pid=$!
+			else
+				while [ 1 ]; do $cmd; sleep 1; done &
+				dsm_pid=$!
+			fi
 			sleep 2
 			disp=$use
 			if [ $disp -ge 5500 ]; then
@@ -2935,6 +3260,9 @@ if [ "X$direct_connect" != "X" ]; then
 		echo "$VNCVIEWERCMD" "$@" -listen $disp2
 		echo ""
 		$VNCVIEWERCMD "$@" -listen $disp2
+		if [ "X$PPROXY_LOOP_THYSELF" != "X" ]; then
+			rm -f $PPROXY_LOOP_THYSELF
+		fi
 	fi
 	exit $?
 fi
@@ -2998,6 +3326,8 @@ else
 	hloc=""
 	if [ "X$use_ssh" = "X1" ]; then
 		hloc="$localhost:"
+	elif [ "X$STUNNEL_LISTEN" != "X" ]; then
+		hloc="$STUNNEL_LISTEN:"
 	fi
 	if echo "$proxy" | grep -i '^vencrypt:' > /dev/null; then
 		hloc="$localhost:"
@@ -3127,7 +3457,12 @@ else
 		if echo "$proxy" | grep -i '^vencrypt:' > /dev/null; then
 			pstunnel=`echo "$proxy" | awk -F: '{print $2}'`
 			plisten=`echo "$proxy" | awk -F: '{print $3}'`
-			PPROXY_LISTEN="INADDR_ANY:$plisten"; export PPROXY_LISTEN
+			IF=INADDR_ANY
+			if [ "X$STUNNEL_LISTEN" != "X" ]; then
+				IF=$STUNNEL_LISTEN
+			fi
+			PPROXY_VENCRYPT_REVERSE=1; export PPROXY_VENCRYPT_REVERSE
+			PPROXY_LISTEN="$IF:$plisten"; export PPROXY_LISTEN
 			PPROXY_PROXY="vencrypt://$localhost:$pstunnel"; export PPROXY_PROXY
 			PPROXY_DEST="$localhost:$pstunnel"; export PPROXY_DEST
 			STUNNEL_ONCE=1; export STUNNEL_ONCE
@@ -3140,6 +3475,11 @@ else
 				if [ $N2_trim -le 200 ]; then
 					N2_trim=`expr $N2_trim + 5500`
 				fi
+				if [ "X$SSVNC_LISTEN_ONCE" != "X1" ]; then
+					PPROXY_LOOP_THYSELF=`mytmp "/tmp/pproxy_loop_thyself1.${RANDOM}.$$"`
+					export PPROXY_LOOP_THYSELF
+					PPROXY_LOOP_THYSELF0=$PPROXY_LOOP_THYSELF
+				fi
 				env PPROXY_REMOVE=0 PPROXY_SLEEP=0 PPROXY_VENCRYPT_VIEWER_BRIDGE="-$port1,$port2" $ptmp &
 				sleep 1
 			fi
@@ -3148,6 +3488,10 @@ else
 			PPROXY_SLEEP=1; export PPROXY_SLEEP;
 		fi
 		PPROXY_KILLPID=+1; export PPROXY_KILLPID;
+		if [ "X$SSVNC_LISTEN_ONCE" != "X1" ]; then
+			PPROXY_LOOP_THYSELF=`mytmp "/tmp/pproxy_loop_thyself2.${RANDOM}.$$"`
+			export PPROXY_LOOP_THYSELF
+		fi
 		$ptmp &
 		# Important to have no extra pids generated between here and VNCVIEWERCMD
 	fi
@@ -3157,6 +3501,13 @@ else
 	echo "$VNCVIEWERCMD" "$@" -listen $N2
 	echo ""
 	$VNCVIEWERCMD "$@" -listen $N2
+
+	if [ "X$PPROXY_LOOP_THYSELF" != "X" ]; then
+		rm -f $PPROXY_LOOP_THYSELF
+	fi
+	if [ "X$PPROXY_LOOP_THYSELF0" != "X" ]; then
+		rm -f $PPROXY_LOOP_THYSELF0
+	fi
 fi
 
 sleep 1
diff --git a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch b/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch
index be5a22a..550cc17 100644
--- a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch
+++ b/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch
@@ -38,7 +38,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/Makefile vnc_javasrc/Makefile
  	@$(ExportJavaClasses)
 diff -x VncCanvas.java -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto.java
 --- vnc_javasrc.orig/RfbProto.java	2004-03-04 08:34:25.000000000 -0500
-+++ vnc_javasrc/RfbProto.java	2006-04-16 11:17:37.000000000 -0400
++++ vnc_javasrc/RfbProto.java	2010-03-27 17:58:37.000000000 -0400
 @@ -199,7 +199,21 @@
      host = h;
      port = p;
@@ -71,9 +71,68 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto
      }
  
      serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0');
+@@ -992,6 +1006,19 @@
+     boolean down = (evt.getID() == KeyEvent.KEY_PRESSED);
+ 
+     int key;
++	if (viewer.debugKeyboard) {
++		System.out.println("----------------------------------------");
++		System.out.println("evt.getKeyChar:      " + evt.getKeyChar());
++		System.out.println("getKeyText:          " + KeyEvent.getKeyText(evt.getKeyCode()));
++		System.out.println("evt.getKeyCode:      " + evt.getKeyCode());
++		System.out.println("evt.getID:           " + evt.getID());
++		System.out.println("evt.getKeyLocation:  " + evt.getKeyLocation());
++		System.out.println("evt.isActionKey:     " + evt.isActionKey());
++		System.out.println("evt.isControlDown:   " + evt.isControlDown());
++		System.out.println("evt.getModifiers:    " + evt.getModifiers());
++		System.out.println("getKeyModifiersText: " + KeyEvent.getKeyModifiersText(evt.getModifiers()));
++		System.out.println("evt.paramString:     " + evt.paramString());
++	}
+     if (evt.isActionKey()) {
+ 
+       //
+@@ -1025,6 +1052,13 @@
+         return;
+       }
+ 
++      if(key == 0xffc2 && viewer.mapF5_to_atsign) {
++	 if (viewer.debugKeyboard) {
++	    System.out.println("Mapping: F5 -> AT ");
++	 }
++      	 key = 0x40;
++      }
++
+     } else {
+ 
+       //
+@@ -1036,6 +1070,7 @@
+ 
+       key = keyChar;
+ 
++
+       if (key < 0x20) {
+         if (evt.isControlDown()) {
+           key += 0x60;
+@@ -1121,6 +1156,16 @@
+   int oldModifiers = 0;
+ 
+   void writeModifierKeyEvents(int newModifiers) {
++    if(viewer.forbid_Ctrl_Alt) {
++	if ((newModifiers & CTRL_MASK) != 0 && (newModifiers & ALT_MASK) != 0) {
++		int orig = newModifiers;
++		newModifiers &= ~ALT_MASK;
++		newModifiers &= ~CTRL_MASK;
++		if (viewer.debugKeyboard) {
++			System.out.println("Ctrl+Alt modifiers: " + orig + " -> " + newModifiers);
++		}
++	}
++    }
+     if ((newModifiers & CTRL_MASK) != (oldModifiers & CTRL_MASK))
+       writeKeyEvent(0xffe3, (newModifiers & CTRL_MASK) != 0);
+ 
 diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSLSocketToMe.java
 --- vnc_javasrc.orig/SSLSocketToMe.java	1969-12-31 19:00:00.000000000 -0500
-+++ vnc_javasrc/SSLSocketToMe.java	2010-03-19 12:52:08.000000000 -0400
++++ vnc_javasrc/SSLSocketToMe.java	2010-03-21 12:53:24.000000000 -0400
 @@ -0,0 +1,2055 @@
 +/*
 + * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer.
@@ -1028,7 +1087,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
 +			str += "Pragma: No-Cache\r\n";
 +			str += "\r\n";
 +
-+			System.out.println("sending GET: " + str);
++			System.out.println("sending: " + str);
 +    			OutputStream os = socket.getOutputStream();
 +			String type = "os";
 +
@@ -2132,7 +2191,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
 +}
 diff -x VncCanvas.java -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncViewer.java
 --- vnc_javasrc.orig/VncViewer.java	2004-03-04 08:34:25.000000000 -0500
-+++ vnc_javasrc/VncViewer.java	2010-03-20 19:49:14.000000000 -0400
++++ vnc_javasrc/VncViewer.java	2010-03-27 17:57:04.000000000 -0400
 @@ -29,6 +29,7 @@
  import java.awt.event.*;
  import java.io.*;
@@ -2150,7 +2209,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncView
    boolean showControls;
    boolean offerRelogin;
    boolean showOfflineDesktop;
-@@ -88,6 +89,21 @@
+@@ -88,6 +89,24 @@
    int deferCursorUpdates;
    int deferUpdateRequests;
  
@@ -2168,11 +2227,54 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncView
 +  boolean trustAllVncCerts;
 +  boolean trustUrlVncCert;
 +  boolean debugCerts;
++  boolean debugKeyboard;
++  boolean mapF5_to_atsign;
++  boolean forbid_Ctrl_Alt;
 +
    // Reference to this applet for inter-applet communication.
    public static java.applet.Applet refApplet;
  
-@@ -590,9 +606,28 @@
+@@ -282,10 +301,24 @@
+       validate();
+     }
+ 
+-    while (!tryAuthenticate()) {
+-      authenticator.retry();
+-      authenticatorUnixLogin.retry();
+-    }
++	if (false) {
++		/* a bug on retries: 'Error: bad position: 8' sun.awt.X11.XTextFieldPeer.setCaretPosition(XTextFieldPeer.java:215) */
++		while (!tryAuthenticate()) {
++			authenticator.retry();
++			authenticatorUnixLogin.retry();
++		}
++	} else {
++		/* just try once and not forever... */
++		if (!tryAuthenticate()) {
++    			showConnectionStatus("Authentication Failed.");
++			showMessage("Authentication Failed.");
++			if (!offerRelogin) {
++				fatalError("auth failed.");
++			}
++		} else {
++			//showConnectionStatus("Authentication OK.");
++		}
++	}
+   }
+ 
+ 
+@@ -428,7 +461,10 @@
+     gbc.ipadx = 100;
+     gbc.ipady = 50;
+     gridbag.setConstraints(authPanel, gbc);
++    try {
+     vncContainer.add(authPanel);
++    } catch (Exception e) {
++    }
+ 
+     if (inSeparateFrame) {
+       vncFrame.pack();
+@@ -590,9 +626,28 @@
  	fatalError("HOST parameter not specified");
        }
      }
@@ -2203,7 +2305,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncView
  
      if (inAnApplet) {
        str = readParameter("Open New Window", false);
-@@ -626,6 +661,106 @@
+@@ -626,6 +681,121 @@
  
      // SocketFactory.
      socketFactory = readParameter("SocketFactory", false);
@@ -2306,6 +2408,21 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncView
 +    str = readParameter("debugCerts", false);
 +    if (str != null && str.equalsIgnoreCase("Yes")) {
 +	debugCerts = true;
++    }
++    debugKeyboard = false;
++    str = readParameter("debugKeyboard", false);
++    if (str != null && str.equalsIgnoreCase("Yes")) {
++	debugKeyboard = true;
++    }
++    mapF5_to_atsign = false;
++    str = readParameter("mapF5_to_atsign", false);
++    if (str != null && str.equalsIgnoreCase("Yes")) {
++	mapF5_to_atsign = true;
++    }
++    forbid_Ctrl_Alt = false;
++    str = readParameter("forbid_Ctrl_Alt", false);
++    if (str != null && str.equalsIgnoreCase("Yes")) {
++	forbid_Ctrl_Alt = true;
 +    }
    }
  
diff --git a/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch b/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch
index 8bb6f85..4dbffaf 100644
--- a/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch
+++ b/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch
@@ -1665,7 +1665,7 @@ diff -Naur JavaViewer.orig/OptionsFrame.java JavaViewer/OptionsFrame.java
      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	2008-10-06 13:32:30.000000000 -0400
++++ JavaViewer/RfbProto.java	2010-03-27 17:59:56.000000000 -0400
 @@ -31,6 +31,7 @@
  import java.net.Socket;
  import java.util.*;
@@ -1909,8 +1909,8 @@ diff -Naur JavaViewer.orig/RfbProto.java JavaViewer/RfbProto.java
  		}
 -		
 +		return maxc;
-+	}
-+
+ 	}
+ 
 +	String guess_encoding(char[] chars) {
 +		boolean saw_high_char = false;
 +
@@ -1964,8 +1964,8 @@ diff -Naur JavaViewer.orig/RfbProto.java JavaViewer/RfbProto.java
 +		} else {
 +			return "ISO-8859-1";
 +		}
- 	}
- 
++	}
++
 +
  	//Internally used. Write an rfb message to the server for sending files ONLY 
  	int writeRfbFileTransferMsgForSendFile(
@@ -2642,9 +2642,58 @@ diff -Naur JavaViewer.orig/RfbProto.java JavaViewer/RfbProto.java
  
  		os.write(b);
  	//	}
+@@ -1610,6 +1971,21 @@
+ 
+ 		boolean down = (evt.getID() == KeyEvent.KEY_PRESSED);
+ 
++		if (viewer.debugKeyboard) {
++			System.out.println("----------------------------------------");
++			System.out.println("evt.getKeyChar:      " + evt.getKeyChar());
++			System.out.println("getKeyText:          " + KeyEvent.getKeyText(evt.getKeyCode()));
++			System.out.println("evt.getKeyCode:      " + evt.getKeyCode());
++			System.out.println("evt.getID:           " + evt.getID());
++			System.out.println("evt.getKeyLocation:  " + evt.getKeyLocation());
++			System.out.println("evt.isActionKey:     " + evt.isActionKey());
++			System.out.println("evt.isControlDown:   " + evt.isControlDown());
++			System.out.println("evt.getModifiers:    " + evt.getModifiers());
++			System.out.println("getKeyModifiersText: " + KeyEvent.getKeyModifiersText(evt.getModifiers()));
++			System.out.println("evt.paramString:     " + evt.paramString());
++		}
++
++
+ 		int key;
+ 		if (evt.isActionKey()) {
+ 
+@@ -1685,6 +2061,9 @@
+ 				default :
+ 					return;
+ 			}
++			if (key == 0xffc2 && viewer.mapF5_to_atsign) {
++				key = 0x40;
++			}
+ 
+ 		} else {
+ 
+@@ -1794,6 +2173,16 @@
+ 	int oldModifiers = 0;
+ 
+ 	void writeModifierKeyEvents(int newModifiers) {
++		if(viewer.forbid_Ctrl_Alt) {
++			if ((newModifiers & CTRL_MASK) != 0 && (newModifiers & ALT_MASK) != 0) {
++				int orig = newModifiers;
++				newModifiers &= ~ALT_MASK;
++				newModifiers &= ~CTRL_MASK;
++				if (viewer.debugKeyboard) {
++					System.out.println("Ctrl+Alt modifiers: " + orig + " -> " + newModifiers);
++				}
++			}
++		}
+ 		if ((newModifiers & CTRL_MASK) != (oldModifiers & CTRL_MASK))
+ 			writeKeyEvent(0xffe3, (newModifiers & CTRL_MASK) != 0);
+ 
 diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java
 --- JavaViewer.orig/SSLSocketToMe.java	1969-12-31 19:00:00.000000000 -0500
-+++ JavaViewer/SSLSocketToMe.java	2010-03-19 12:52:08.000000000 -0400
++++ JavaViewer/SSLSocketToMe.java	2010-03-21 12:53:24.000000000 -0400
 @@ -0,0 +1,2055 @@
 +/*
 + * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer.
@@ -3599,7 +3648,7 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java
 +			str += "Pragma: No-Cache\r\n";
 +			str += "\r\n";
 +
-+			System.out.println("sending GET: " + str);
++			System.out.println("sending: " + str);
 +    			OutputStream os = socket.getOutputStream();
 +			String type = "os";
 +
@@ -4826,7 +4875,7 @@ diff -Naur JavaViewer.orig/VncCanvas.java JavaViewer/VncCanvas.java
  						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	2010-03-20 19:50:16.000000000 -0400
++++ JavaViewer/VncViewer.java	2010-03-27 18:00:28.000000000 -0400
 @@ -41,6 +41,7 @@
  import java.io.*;
  import java.net.*;
@@ -4858,7 +4907,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java
    String passwordParam;
    String encPasswordParam;
    boolean showControls;
-@@ -115,28 +116,72 @@
+@@ -115,28 +116,75 @@
    int i;
    // mslogon support 2 end
  
@@ -4878,6 +4927,9 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java
 +boolean trustAllVncCerts;
 +boolean trustUrlVncCert;
 +boolean debugCerts;
++boolean debugKeyboard;
++boolean mapF5_to_atsign;
++boolean forbid_Ctrl_Alt;
 +
 +boolean ignoreMSLogonCheck;
 +boolean delayAuthPanel;
@@ -4937,7 +4989,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java
      // authenticator = new AuthPanel(false);   // mslogon support : go to connectAndAuthenticate()
      if (RecordingFrame.checkSecurity())
        rec = new RecordingFrame(this);
-@@ -147,10 +192,11 @@
+@@ -147,10 +195,11 @@
      cursorUpdatesDef = null;
      eightBitColorsDef = null;
  
@@ -4951,7 +5003,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java
      rfbThread = new Thread(this);
      rfbThread.start();
    }
-@@ -186,6 +232,30 @@
+@@ -186,6 +235,30 @@
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
  
@@ -4982,7 +5034,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java
  	// Add ScrollPanel to applet mode
  
  	// Create a panel which itself is resizeable and can hold
-@@ -286,6 +356,24 @@
+@@ -286,6 +359,24 @@
  
    void connectAndAuthenticate() throws Exception {
  
@@ -5007,7 +5059,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java
      // If "ENCPASSWORD" parameter is set, decrypt the password into
      // the passwordParam string.
  
-@@ -336,7 +424,22 @@
+@@ -336,7 +427,22 @@
      //
  
      
@@ -5031,18 +5083,29 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java
  
      authenticator = new AuthPanel(mslogon);
      
-@@ -390,6 +493,10 @@
+@@ -371,6 +477,7 @@
+      //mslogon support end
+     }
+ 
++    int tries = 0;
+     while (true) {
+       // Wait for user entering a password, or a username and a password
+       synchronized(authenticator) {
+@@ -390,6 +497,13 @@
  	break;
        //mslogon support end
  
 +// begin runge/x11vnc
-+	gotAuth = false;
++      gotAuth = false;
++      if (++tries > 2) {
++         throw new Exception("Incorrect password entered " + tries + " times.");
++      }
 +// end runge/x11vnc
 +
        // Retry on authentication failure.
        authenticator.retry();
      }
-@@ -405,9 +512,11 @@
+@@ -405,9 +519,11 @@
  
    void prologueDetectAuthProtocol() throws Exception {
  
@@ -5056,7 +5119,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java
  
      System.out.println("RFB server supports protocol version " +
  		       rfb.serverMajor + "." + rfb.serverMinor);
-@@ -431,16 +540,36 @@
+@@ -431,16 +547,36 @@
  
    boolean tryAuthenticate(String us, String pw) throws Exception {
      
@@ -5074,10 +5137,10 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java
 -    rfb.writeVersionMsg();
 +		System.out.println("RFB server supports protocol version: " +
 +			       rfb.serverMajor + "." + rfb.serverMinor);
-+
-+		rfb.writeVersionMsg();
  
 -    int authScheme = rfb.readAuthScheme();
++		rfb.writeVersionMsg();
++
 +		authScheme = rfb.readAuthScheme();
 +
 +		gotAuth = true;
@@ -5099,7 +5162,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java
  
      switch (authScheme) {
  
-@@ -629,6 +758,10 @@
+@@ -629,6 +765,10 @@
  
    void doProtocolInitialisation() throws IOException {
  
@@ -5110,7 +5173,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java
      rfb.writeClientInit();
  
      rfb.readServerInit();
-@@ -774,9 +907,28 @@
+@@ -774,9 +914,28 @@
  	fatalError("HOST parameter not specified");
        }
      }
@@ -5141,7 +5204,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java
  
      if (inAnApplet) {
        str = readParameter("Open New Window", false);
-@@ -804,6 +956,143 @@
+@@ -804,6 +963,158 @@
      deferScreenUpdates = readIntParameter("Defer screen updates", 20);
      deferCursorUpdates = readIntParameter("Defer cursor updates", 10);
      deferUpdateRequests = readIntParameter("Defer update requests", 50);
@@ -5256,6 +5319,21 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java
 +    if (str != null && str.equalsIgnoreCase("Yes")) {
 +	debugCerts = true;
 +    }
++    debugKeyboard = false;
++    str = readParameter("debugKeyboard", false);
++    if (str != null && str.equalsIgnoreCase("Yes")) {
++	debugKeyboard = true;
++    }
++    mapF5_to_atsign = false;
++    str = readParameter("mapF5_to_atsign", false);
++    if (str != null && str.equalsIgnoreCase("Yes")) {
++	mapF5_to_atsign = true;
++    }
++    forbid_Ctrl_Alt = false;
++    str = readParameter("forbid_Ctrl_Alt", false);
++    if (str != null && str.equalsIgnoreCase("Yes")) {
++	forbid_Ctrl_Alt = true;
++    }
 +    ignoreMSLogonCheck = false;
 +    str = readParameter("ignoreMSLogonCheck", false);
 +    if (str != null && str.equalsIgnoreCase("Yes")) {
-- 
cgit v1.2.3

