Commit 6153bd69 authored by runge's avatar runge

Update java and scripts in classes/ssl. x11vnc: declare crypt() on all platforms. more wishes.

parent 00a9a0ea
...@@ -3,7 +3,23 @@ ...@@ -3,7 +3,23 @@
# ss_vncviewer: wrapper for vncviewer to use an stunnel SSL tunnel # ss_vncviewer: wrapper for vncviewer to use an stunnel SSL tunnel
# or an SSH tunnel. # or an SSH tunnel.
# #
# Copyright (c) 2006-2008 by Karl J. Runge <runge@karlrunge.com> # Copyright (c) 2006-2009 by Karl J. Runge <runge@karlrunge.com>
#
# ss_vncviewer 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; either version 2 of the License, or (at
# your option) any later version.
#
# ss_vncviewer 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 ss_vncviewer; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
# or see <http://www.gnu.org/licenses/>.
#
# #
# You must have stunnel(8) installed on the system and in your PATH # You must have stunnel(8) installed on the system and in your PATH
# (however, see the -ssh option below, in which case you will need ssh(1) # (however, see the -ssh option below, in which case you will need ssh(1)
...@@ -129,7 +145,7 @@ fi ...@@ -129,7 +145,7 @@ fi
# #
# turn on verbose debugging output # turn on verbose debugging output
if [ "X$SS_DEBUG" != "X" ]; then if [ "X$SS_DEBUG" != "X" -a "X$SS_DEBUG" != "X0" ]; then
set -xv set -xv
fi fi
...@@ -141,6 +157,7 @@ if uname | grep Darwin >/dev/null; then ...@@ -141,6 +157,7 @@ if uname | grep Darwin >/dev/null; then
fi fi
# work out which stunnel to use (debian installs as stunnel4) # work out which stunnel to use (debian installs as stunnel4)
stunnel_set_here=""
if [ "X$STUNNEL" = "X" ]; then if [ "X$STUNNEL" = "X" ]; then
check_stunnel=1 check_stunnel=1
if [ "X$SSVNC_BASEDIRNAME" != "X" ]; then if [ "X$SSVNC_BASEDIRNAME" != "X" ]; then
...@@ -161,6 +178,7 @@ if [ "X$STUNNEL" = "X" ]; then ...@@ -161,6 +178,7 @@ if [ "X$STUNNEL" = "X" ]; then
STUNNEL=stunnel STUNNEL=stunnel
fi fi
fi fi
stunnel_set_here=1
fi fi
help() { help() {
...@@ -217,10 +235,12 @@ if [ "X$1" = "X-viewerflavor" ]; then ...@@ -217,10 +235,12 @@ if [ "X$1" = "X-viewerflavor" ]; then
str=`$VNCVIEWERCMD -h 2>&1 | head -n 5` str=`$VNCVIEWERCMD -h 2>&1 | head -n 5`
if echo "$str" | grep -i 'TightVNC.viewer' > /dev/null; then if echo "$str" | grep -i 'TightVNC.viewer' > /dev/null; then
echo "tightvnc" echo "tightvnc"
elif echo "$str" | grep -i 'RealVNC.Ltd' > /dev/null; then
echo "realvnc4"
elif echo "$str" | grep -i 'VNC viewer version 3' > /dev/null; then elif echo "$str" | grep -i 'VNC viewer version 3' > /dev/null; then
echo "realvnc3" echo "realvnc3"
elif echo "$str" | grep -i 'VNC viewer .*Edition 4' > /dev/null; then
echo "realvnc4"
elif echo "$str" | grep -i 'RealVNC.Ltd' > /dev/null; then
echo "realvnc4"
else else
echo "unknown" echo "unknown"
fi fi
...@@ -287,6 +307,8 @@ do ...@@ -287,6 +307,8 @@ do
;; ;;
"-ssvnc_encodings") shift; VNCVIEWER_ENCODINGS="$1"; export VNCVIEWER_ENCODINGS "-ssvnc_encodings") shift; VNCVIEWER_ENCODINGS="$1"; export VNCVIEWER_ENCODINGS
;; ;;
"-ssvnc_extra_opts") shift; VNCVIEWERCMD_EXTRA_OPTS="$1"; export VNCVIEWERCMD_EXTRA_OPTS
;;
"-rfbversion") shift; VNCVIEWER_RFBVERSION="$1"; export VNCVIEWER_RFBVERSION "-rfbversion") shift; VNCVIEWER_RFBVERSION="$1"; export VNCVIEWER_RFBVERSION
;; ;;
"-nobell") VNCVIEWER_NOBELL=1; export VNCVIEWER_NOBELL "-nobell") VNCVIEWER_NOBELL=1; export VNCVIEWER_NOBELL
...@@ -438,7 +460,12 @@ if echo "$proxy" | egrep "vencrypt://" > /dev/null; then ...@@ -438,7 +460,12 @@ if echo "$proxy" | egrep "vencrypt://" > /dev/null; then
vtmp=`mytmp "$vtmp"` vtmp=`mytmp "$vtmp"`
SSVNC_PREDIGESTED_HANDSHAKE="$vtmp" SSVNC_PREDIGESTED_HANDSHAKE="$vtmp"
export SSVNC_PREDIGESTED_HANDSHAKE export SSVNC_PREDIGESTED_HANDSHAKE
#echo "SSVNC_PREDIGESTED_HANDSHAKE=$SSVNC_PREDIGESTED_HANDSHAKE" if [ "X$SSVNC_USE_OURS" = "X" ]; then
NEED_VENCRYPT_VIEWER_BRIDGE=1
fi
fi
if [ "X$SSVNC_USE_OURS" = "X" ]; then
VNCVIEWERCMD_EXTRA_OPTS=""
fi fi
...@@ -654,6 +681,9 @@ final() { ...@@ -654,6 +681,9 @@ final() {
if [ "X$tail_pid" != "X" ]; then if [ "X$tail_pid" != "X" ]; then
kill -TERM $tail_pid kill -TERM $tail_pid
fi fi
if [ "X$tail_pid2" != "X" ]; then
kill -TERM $tail_pid2
fi
} }
if [ "X$reverse" = "X" ]; then if [ "X$reverse" = "X" ]; then
...@@ -687,6 +717,12 @@ if echo "$0" | grep vncip > /dev/null; then ...@@ -687,6 +717,12 @@ if echo "$0" | grep vncip > /dev/null; then
VNCVIEWERCMD="$VNCIPCMD" VNCVIEWERCMD="$VNCIPCMD"
fi fi
if echo "$VNCVIEWERCMD" | egrep -i '^(xmessage|sleep )' > /dev/null; then
:
elif [ "X$VNCVIEWERCMD_EXTRA_OPTS" != "X" ]; then
VNCVIEWERCMD="$VNCVIEWERCMD $VNCVIEWERCMD_EXTRA_OPTS"
fi
# trick for the undocumented rsh://host:port method. # trick for the undocumented rsh://host:port method.
rsh_setup() { rsh_setup() {
if echo "$ssh_host" | grep '@' > /dev/null; then if echo "$ssh_host" | grep '@' > /dev/null; then
...@@ -719,24 +755,56 @@ rsh_viewer() { ...@@ -719,24 +755,56 @@ rsh_viewer() {
fi fi
} }
check_perl() {
if type "$1" > /dev/null 2>&1; then
:
elif [ ! -x "$1" ]; then
echo ""
echo "*******************************************************"
echo "** Problem finding the Perl command '$1': **"
echo ""
type "perl"
echo ""
echo "** Perhaps you need to install the Perl package. **"
echo "*******************************************************"
echo ""
sleep 5
fi
}
# this is the PPROXY tool. used only here for now... # this is the PPROXY tool. used only here for now...
pcode() { pcode() {
tf=$1 tf=$1
PPROXY_PROXY=$proxy; export PPROXY_PROXY PPROXY_PROXY=$proxy; export PPROXY_PROXY
PPROXY_DEST="$host:$port"; export PPROXY_DEST PPROXY_DEST="$host:$port"; export PPROXY_DEST
check_perl /usr/bin/perl
cod='#!/usr/bin/perl cod='#!/usr/bin/perl
# A hack to glue stunnel to a Web proxy or SOCKS for client connections. # A hack to glue stunnel to a Web or SOCKS proxy, UltraVNC repeater for
# client connections.
# Also acts as a VeNCrypt bridge (by redirecting to stunnel.)
use IO::Socket::INET; use IO::Socket::INET;
if (exists $ENV{PPROXY_SLEEP}) { if (exists $ENV{PPROXY_SLEEP} && $ENV{PPROXY_SLEEP} > 0) {
print STDERR "PPROXY_PID: $$\n"; print STDERR "PPROXY_PID: $$\n";
sleep $ENV{PPROXY_SLEEP}; sleep $ENV{PPROXY_SLEEP};
} }
foreach my $var (qw(PPROXY_PROXY PPROXY_SOCKS PPROXY_DEST PPROXY_LISTEN foreach my $var (qw(
PPROXY_REVERSE PPROXY_REPEATER PPROXY_REMOVE PPROXY_KILLPID PPROXY_SLEEP)) { PPROXY_DEST
PPROXY_KILLPID
PPROXY_LISTEN
PPROXY_PROXY
PPROXY_REMOVE
PPROXY_REPEATER
PPROXY_REVERSE
PPROXY_SLEEP
PPROXY_SOCKS
PPROXY_VENCRYPT
PPROXY_VENCRYPT_VIEWER_BRIDGE
)) {
if (0 || $ENV{SS_DEBUG} || $ENV{SSVNC_VENCRYPT_DEBUG}) { if (0 || $ENV{SS_DEBUG} || $ENV{SSVNC_VENCRYPT_DEBUG}) {
print STDERR "$var: $ENV{$var}\n"; print STDERR "$var: $ENV{$var}\n";
} }
...@@ -779,14 +847,14 @@ sub gettime { ...@@ -779,14 +847,14 @@ sub gettime {
return $t; return $t;
} }
sub append_handshake { my $listen_handle = "";
my $str = shift; my $sock = "";
if ($handshake_file) { my $parent = $$;
if (open(HSF, ">>$handshake_file")) {
print HSF $str; if ($ENV{PPROXY_VENCRYPT_VIEWER_BRIDGE}) {
close HSF; my ($from, $to) = split(/,/, $ENV{PPROXY_VENCRYPT_VIEWER_BRIDGE});
} do_vencrypt_viewer_bridge($from, $to);
} exit 0;
} }
my ($first, $second, $third) = split(/,/, $ENV{PPROXY_PROXY}, 3); my ($first, $second, $third) = split(/,/, $ENV{PPROXY_PROXY}, 3);
...@@ -807,7 +875,7 @@ if ($third ne "") { ...@@ -807,7 +875,7 @@ if ($third ne "") {
print STDERR "\n"; print STDERR "\n";
print STDERR "PPROXY v0.2: a tool for Web proxies and SOCKS connections.\n"; print STDERR "PPROXY v0.3: a tool for Web, SOCKS, and UltraVNC proxies and VeNCrypt bridging.\n";
print STDERR "proxy_host: $proxy_host\n"; print STDERR "proxy_host: $proxy_host\n";
print STDERR "proxy_port: $proxy_port\n"; print STDERR "proxy_port: $proxy_port\n";
print STDERR "proxy_connect: $connect\n"; print STDERR "proxy_connect: $connect\n";
...@@ -822,7 +890,12 @@ if (1) { ...@@ -822,7 +890,12 @@ if (1) {
print STDERR "\n"; print STDERR "\n";
} }
my $listen_handle = ""; sub pdie {
my $msg = shift;
kill_proxy_pids();
die "$msg";
}
if ($ENV{PPROXY_REVERSE} ne "") { if ($ENV{PPROXY_REVERSE} ne "") {
my ($rhost, $rport) = split(/:/, $ENV{PPROXY_REVERSE}); my ($rhost, $rport) = split(/:/, $ENV{PPROXY_REVERSE});
$rport = 5900 unless $rport; $rport = 5900 unless $rport;
...@@ -832,20 +905,26 @@ if ($ENV{PPROXY_REVERSE} ne "") { ...@@ -832,20 +905,26 @@ if ($ENV{PPROXY_REVERSE} ne "") {
Proto => "tcp" Proto => "tcp"
); );
if (! $listen_handle) { if (! $listen_handle) {
die "pproxy: $! -- PPROXY_REVERSE\n"; pdie "pproxy: $! -- PPROXY_REVERSE\n";
} }
print STDERR "PPROXY_REVERSE: connected to $rhost $rport\n"; print STDERR "PPROXY_REVERSE: connected to $rhost $rport\n";
} elsif ($ENV{PPROXY_LISTEN} ne "") { } elsif ($ENV{PPROXY_LISTEN} ne "") {
my $listen_sock = ""; my $listen_sock = "";
my $maxtry = 12;
my $sleep = 5;
my $p2 = "";
for (my $i=0; $i < $maxtry; $i++) {
if ($ENV{PPROXY_LISTEN} =~ /^INADDR_ANY:(.*)/) { if ($ENV{PPROXY_LISTEN} =~ /^INADDR_ANY:(.*)/) {
my $p = $1; my $p = $1;
$p2 = "*:$p";
$listen_sock = IO::Socket::INET->new( $listen_sock = IO::Socket::INET->new(
Listen => 2, Listen => 2,
LocalPort => $p, LocalPort => $p,
Proto => "tcp" Proto => "tcp"
); );
} else { } else {
$p2 = "localhost:$ENV{PPROXY_LISTEN}";
$listen_sock = IO::Socket::INET->new( $listen_sock = IO::Socket::INET->new(
Listen => 2, Listen => 2,
LocalAddr => "127.0.0.1", LocalAddr => "127.0.0.1",
...@@ -854,17 +933,29 @@ if ($ENV{PPROXY_REVERSE} ne "") { ...@@ -854,17 +933,29 @@ if ($ENV{PPROXY_REVERSE} ne "") {
); );
} }
if (! $listen_sock) { if (! $listen_sock) {
die "pproxy: $! -- PPROXY_LISTEN\n"; if ($i < $maxtry - 1) {
warn "pproxy: $!\n";
warn "Could not listen on port $p2, retrying in $sleep seconds... (Ctrl-C to quit)\n";
sleep $sleep;
}
} else {
last;
}
}
if (! $listen_sock) {
pdie "pproxy: $! -- PPROXY_LISTEN\n";
} }
print STDERR "pproxy: listening on $p2\n";
my $ip; my $ip;
($listen_handle, $ip) = $listen_sock->accept(); ($listen_handle, $ip) = $listen_sock->accept();
my $err = $!;
close $listen_sock;
if (! $listen_handle) { if (! $listen_handle) {
die "pproxy: $!\n"; pdie "pproxy: $err\n";
} }
close $listen_sock;
} }
my $sock = IO::Socket::INET->new( $sock = IO::Socket::INET->new(
PeerAddr => $proxy_host, PeerAddr => $proxy_host,
PeerPort => $proxy_port, PeerPort => $proxy_port,
Proto => "tcp" Proto => "tcp"
...@@ -873,13 +964,13 @@ my $sock = IO::Socket::INET->new( ...@@ -873,13 +964,13 @@ my $sock = IO::Socket::INET->new(
if (! $sock) { if (! $sock) {
my $err = $!; my $err = $!;
unlink($0) if $ENV{PPROXY_REMOVE}; unlink($0) if $ENV{PPROXY_REMOVE};
die "pproxy: $err\n"; pdie "pproxy: $err\n";
} }
unlink($0) if $ENV{PPROXY_REMOVE}; unlink($0) if $ENV{PPROXY_REMOVE};
if ($ENV{PPROXY_PROXY} =~ /^vencrypt:/ && $ENV{PPROXY_LISTEN} =~ /^INADDR_ANY:/) { if ($ENV{PPROXY_PROXY} =~ /^vencrypt:/ && $ENV{PPROXY_LISTEN} =~ /^INADDR_ANY:/) {
print STDERR "PPROXY: vencrypt+reverse: swapping listen socket with connect socket.\n"; print STDERR "\nPPROXY: vencrypt+reverse: swapping listen socket with connect socket.\n";
my $tmp_swap = $sock; my $tmp_swap = $sock;
$sock = $listen_handle; $sock = $listen_handle;
$listen_handle = $tmp_swap; $listen_handle = $tmp_swap;
...@@ -906,58 +997,123 @@ if ($second ne "") { ...@@ -906,58 +997,123 @@ if ($second ne "") {
connection($connect, 1); connection($connect, 1);
} }
$parent = $$; sub kill_proxy_pids() {
$child = fork; if ($ENV{PPROXY_VENCRYPT_VIEWER_BRIDGE}) {
if (! defined $child) { return;
}
if ($ENV{PPROXY_KILLPID}) { if ($ENV{PPROXY_KILLPID}) {
foreach my $p (split(/,/, $ENV{PPROXY_KILLPID})) { foreach my $p (split(/,/, $ENV{PPROXY_KILLPID})) {
if ($p =~ /^(\+|-)/) { if ($p =~ /^(\+|-)/) {
$p = $parent + $p; $p = $parent + $p;
} }
print STDERR "kill TERM, $p (PPROXY_KILLPID)\n";
kill "TERM", $p; kill "TERM", $p;
} }
} }
exit 1;
} }
if ($child) { sub xfer {
print STDERR "pproxy parent\[$$] STDIN -> socket\n"; my($in, $out) = @_;
$RIN = $WIN = $EIN = "";
$ROUT = "";
vec($RIN, fileno($in), 1) = 1;
vec($WIN, fileno($in), 1) = 1;
$EIN = $RIN | $WIN;
while (1) {
my $nf = 0;
while (! $nf) {
$nf = select($ROUT=$RIN, undef, undef, undef);
}
my $len = sysread($in, $buf, 8192);
if (! defined($len)) {
next if $! =~ /^Interrupted/;
print STDERR "pproxy[$$]: $!\n";
last;
} elsif ($len == 0) {
print STDERR "pproxy[$$]: Input is EOF.\n";
last;
}
my $offset = 0;
my $quit = 0;
while ($len) {
my $written = syswrite($out, $buf, $len, $offset);
if (! defined $written) {
print STDERR "pproxy[$$]: Output is EOF. $!\n";
$quit = 1;
last;
}
$len -= $written;
$offset += $written;
}
last if $quit;
}
close($out);
close($in);
print STDERR "pproxy[$$]: finished xfer.\n";
}
sub handler {
print STDERR "pproxy[$$]: got SIGTERM.\n";
close $listen_handle if $listen_handle;
close $sock if $sock;
exit;
}
sub xfer_both {
$child = fork;
if (! defined $child) {
kill_proxy_pids();
exit 1;
}
$SIG{TERM} = "handler";
if ($child) {
if ($listen_handle) { if ($listen_handle) {
print STDERR "pproxy parent[$$] listen_handle -> socket\n";
xfer($listen_handle, $sock); xfer($listen_handle, $sock);
} else { } else {
print STDERR "pproxy parent[$$] STDIN -> socket\n";
xfer(STDIN, $sock); xfer(STDIN, $sock);
} }
select(undef, undef, undef, 0.25); select(undef, undef, undef, 0.25);
if (kill 0, $child) { if (kill 0, $child) {
select(undef, undef, undef, 1.5); select(undef, undef, undef, 0.9);
print STDERR "pproxy\[$$]: kill TERM $child\n"; if (kill 0, $child) {
print STDERR "pproxy[$$]: kill TERM child $child\n";
kill "TERM", $child; kill "TERM", $child;
} else {
print STDERR "pproxy[$$]: child $child gone.\n";
} }
} else { }
print STDERR "pproxy child \[$$] socket -> STDOUT\n"; } else {
select(undef, undef, undef, 0.05);
if ($listen_handle) { if ($listen_handle) {
print STDERR "pproxy child [$$] socket -> listen_handle\n\n";
xfer($sock, $listen_handle); xfer($sock, $listen_handle);
} else { } else {
print STDERR "pproxy child [$$] socket -> STDOUT\n\n";
xfer($sock, STDOUT); xfer($sock, STDOUT);
} }
select(undef, undef, undef, 0.25); select(undef, undef, undef, 0.25);
if (kill 0, $parent) { if (kill 0, $parent) {
select(undef, undef, undef, 1.5); select(undef, undef, undef, 0.8);
print STDERR "pproxy\[$$]: kill TERM $parent\n"; if (kill 0, $parent) {
print STDERR "pproxy[$$]: kill TERM parent $parent\n";
kill "TERM", $parent; kill "TERM", $parent;
} else {
print STDERR "pproxy[$$]: parent $parent gone.\n";
} }
}
if ($ENV{PPROXY_KILLPID} ne "") {
if ($ENV{PPROXY_KILLPID}) {
foreach my $p (split(/,/, $ENV{PPROXY_KILLPID})) {
if ($p =~ /^(\+|-)/) {
$p = $parent + $p;
}
print STDERR "kill TERM, $p (PPROXY_KILLPID)\n";
kill "TERM", $p;
} }
} }
kill_proxy_pids();
} }
xfer_both();
exit; exit;
sub url_parse { sub url_parse {
...@@ -1186,13 +1342,14 @@ sub connection { ...@@ -1186,13 +1342,14 @@ sub connection {
sub vdie { sub vdie {
append_handshake("done\n"); append_handshake("done\n");
close $sock; close $sock;
kill_proxy_pids();
exit(1); exit(1);
} }
sub anontls_handshake { sub anontls_handshake {
my ($vmode, $db) = @_; my ($vmode, $db) = @_;
print STDERR "PPROXY: Doing ANONTLS Handshake\n"; print STDERR "\nPPROXY: Doing ANONTLS Handshake\n";
my $psec = pack("C", $rfbSecTypeAnonTls); my $psec = pack("C", $rfbSecTypeAnonTls);
syswrite($sock, $psec, 1); syswrite($sock, $psec, 1);
...@@ -1204,7 +1361,7 @@ sub vencrypt_handshake { ...@@ -1204,7 +1361,7 @@ sub vencrypt_handshake {
my ($vmode, $db) = @_; my ($vmode, $db) = @_;
print STDERR "PPROXY: Doing VeNCrypt Handshake\n"; print STDERR "\nPPROXY: Doing VeNCrypt Handshake\n";
my $psec = pack("C", $rfbSecTypeVencrypt); my $psec = pack("C", $rfbSecTypeVencrypt);
...@@ -1397,44 +1554,407 @@ sub vencrypt_dialog { ...@@ -1397,44 +1554,407 @@ sub vencrypt_dialog {
} }
} }
sub xfer { sub append_handshake {
my($in, $out) = @_; my $str = shift;
$RIN = $WIN = $EIN = ""; if ($handshake_file) {
$ROUT = ""; if (open(HSF, ">>$handshake_file")) {
vec($RIN, fileno($in), 1) = 1; print HSF $str;
vec($WIN, fileno($in), 1) = 1; close HSF;
$EIN = $RIN | $WIN; }
}
}
while (1) { sub do_vencrypt_viewer_bridge {
my $nf = 0; my ($listen, $connect) = @_;
while (! $nf) { print STDERR "\npproxy: starting vencrypt_viewer_bridge[$$]: $listen \-> $connect\n";
$nf = select($ROUT=$RIN, undef, undef, undef); my $db = 0;
my $backwards = 0;
if ($listen < 0) {
$backwards = 1;
$listen = -$listen;
} }
my $len = sysread($in, $buf, 8192); if ($handshake_file eq "") {
if (! defined($len)) { die "pproxy: vencrypt_viewer_bridge[$$]: no SSVNC_PREDIGESTED_HANDSHAKE\n";
next if $! =~ /^Interrupted/; }
print STDERR "pproxy\[$$]: $!\n"; my $listen_sock;
last; my $maxtry = 12;
} elsif ($len == 0) { my $sleep = 5;
print STDERR "pproxy\[$$]: Input is EOF.\n"; for (my $i=0; $i < $maxtry; $i++) {
$listen_sock = IO::Socket::INET->new(
Listen => 2,
LocalAddr => "127.0.0.1",
LocalPort => $listen,
Proto => "tcp"
);
if (! $listen_sock) {
if ($i < $maxtry - 1) {
warn "pproxy: vencrypt_viewer_bridge[$$]: $!\n";
warn "Could not listen on port $listen, retrying in $sleep seconds... (Ctrl-C to quit)\n";
sleep $sleep;
}
} else {
last; last;
} }
my $offset = 0; }
my $quit = 0; if (! $listen_sock) {
while ($len) { die "pproxy: vencrypt_viewer_bridge[$$]: $!\n";
my $written = syswrite($out, $buf, $len, $offset); }
if (! defined $written) { print STDERR "pproxy: vencrypt_viewer_bridge[$$]: listening on port $listen\n\n";
print STDERR "pproxy\[$$]: Output is EOF. $!\n"; my ($viewer_sock, $ip) = $listen_sock->accept();
$quit = 1; my $err = $!;
close $listen_sock;
if (! $viewer_sock) {
die "pproxy: vencrypt_viewer_bridge[$$]: $err\n";
}
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";
my $server_sock = IO::Socket::INET->new(
PeerAddr => "127.0.0.1",
PeerPort => $connect,
Proto => "tcp"
);
print STDERR "vencrypt_viewer_bridge[$$]: server_sock $server_sock\n" if $db;
if (! $server_sock) {
my $err = $!;
die "pproxy: vencrypt_viewer_bridge[$$]: $err\n";
}
if ($backwards) {
print STDERR "vencrypt_viewer_bridge[$$]: reversing roles of viewer and server.\n";
my $t = $viewer_sock;
$viewer_sock = $server_sock;
$server_sock = $t;
}
my %hs = ();
my $dt = 0.2;
my $slept = 0.0;
while ($slept < 20.0) {
select(undef, undef, undef, $dt);
$slept += $dt;
if (-f $handshake_file && open(HSF, "<$handshake_file")) {
my $done = 0;
%hs = ();
my $str = "";
while (<HSF>) {
print STDERR "vencrypt_viewer_bridge[$$]: $_" if $ENV{VENCRYPT_VIEWER_BRIDGE_DEBUG};
$str .= "vencrypt_viewer_bridge[$$]: $_";
chomp;
if ($_ eq "done") {
$done = 1;
} else {
my ($k, $v) = split(/=/, $_, 2);
if ($k ne "" && $v ne "") {
$hs{$k} = $v;
}
}
}
close HSF;
if ($done) {
print STDERR "\n" . $str;
last; last;
} }
$len -= $written;
$offset += $written;
} }
last if $quit;
} }
close($in); if (! exists $hs{server}) {
close($out); $hs{server} = "RFB 003.008";
}
if (! exists $hs{sectype}) {
unlink($handshake_file);
die "pproxy: vencrypt_viewer_bridge[$$]: no sectype.\n";
}
syswrite($viewer_sock, "$hs{server}\n", length($hs{server}) + 1);
my $viewer_rfb = "";
for (my $i = 0; $i < 12; $i++) {
my $c;
sysread($viewer_sock, $c, 1);
$viewer_rfb .= $c;
print STDERR $c;
}
my $viewer_major = 3;
my $viewer_minor = 8;
if ($viewer_rfb =~ /RFB (\d+)\.(\d+)/) {
$viewer_major = $1;
$viewer_minor = $2;
}
my $u0 = pack("C", 0);
my $u1 = pack("C", 1);
my $u2 = pack("C", 2);
if ($hs{sectype} == $rfbSecTypeAnonTls) {
unlink($handshake_file);
print STDERR "\npproxy: vencrypt_viewer_bridge[$$]: rfbSecTypeAnonTls\n";
if ($viewer_major > 3 || $viewer_minor >= 7) {
; # setup ok, proceed to xfer.
} else {
print STDERR "pproxy: vencrypt_viewer_bridge[$$]: faking RFB version 3.3 to viewer.\n";
my $n;
sysread($server_sock, $n, 1);
$n = unpack("C", $n);
if ($n == 0) {
die "pproxy: vencrypt_viewer_bridge[$$]: nsectypes == $n.\n";
}
my %types;
for (my $i = 0; $i < $n; $i++) {
my $t;
sysread($server_sock, $t, 1);
$t = unpack("C", $t);
$types{$t} = 1;
}
my $use = 1; # None
if (exists $types{1}) {
$use = 1; # None
} elsif (exists $types{2}) {
$use = 2; # VncAuth
} else {
die "pproxy: vencrypt_viewer_bridge[$$]: no valid sectypes" . join(",", keys %types) . "\n";
}
# send 4 bytes sectype to viewer:
# (note this should be MSB, network byte order...)
my $up = pack("C", $use);
syswrite($viewer_sock, $u0, 1);
syswrite($viewer_sock, $u0, 1);
syswrite($viewer_sock, $u0, 1);
syswrite($viewer_sock, $up, 1);
# and tell server the one we selected:
syswrite($server_sock, $up, 1);
if ($use == 1) {
# even None has security result, so read it here and discard it.
my $sr = "";
sysread($server_sock, $sr, 4);
}
}
} elsif ($hs{sectype} == $rfbSecTypeVencrypt) {
print STDERR "\npproxy: vencrypt_viewer_bridge[$$]: rfbSecTypeVencrypt\n";
if (! exists $hs{subtype}) {
unlink($handshake_file);
die "pproxy: vencrypt_viewer_bridge[$$]: no subtype.\n";
}
my $fake_type = "None";
my $plain = 0;
my $sub_type = $hs{subtype};
if ($sub_type == $rfbVencryptTlsNone) {
$fake_type = "None";
} elsif ($sub_type == $rfbVencryptTlsVnc) {
$fake_type = "VncAuth";
} elsif ($sub_type == $rfbVencryptTlsPlain) {
$fake_type = "None";
$plain = 1;
} elsif ($sub_type == $rfbVencryptX509None) {
$fake_type = "None";
} elsif ($sub_type == $rfbVencryptX509Vnc) {
$fake_type = "VncAuth";
} elsif ($sub_type == $rfbVencryptX509Plain) {
$fake_type = "None";
$plain = 1;
}
if ($plain) {
if (!open(W, ">$handshake_file")) {
unlink($handshake_file);
die "pproxy: vencrypt_viewer_bridge[$$]: $handshake_file $!\n";
}
print W <<"END";
proc print_out {} {
global user pass env
if [info exists env(SSVNC_UP_DEBUG)] {
toplevel .b
button .b.b -text "user=\$user pass=\$pass" -command {destroy .b}
pack .b.b
update
tkwait window .b
}
if [info exists env(SSVNC_UP_FILE)] {
set fh ""
catch {set fh [open \$env(SSVNC_UP_FILE) w]}
if {\$fh != ""} {
puts \$fh user=\$user\\npass=\$pass
flush \$fh
close \$fh
return
}
}
puts stdout user=\$user\\npass=\$pass
flush stdout
}
proc center_win {w} {
update
set W [winfo screenwidth \$w]
set W [expr \$W + 1]
wm geometry \$w +\$W+0
update
set x [expr [winfo screenwidth \$w]/2 - [winfo width \$w]/2]
set y [expr [winfo screenheight \$w]/2 - [winfo height \$w]/2]
wm geometry \$w +\$x+\$y
wm deiconify \$w
update
}
wm withdraw .
global env
set up {}
if [info exists env(SSVNC_UNIXPW)] {
set rm 0
set up \$env(SSVNC_UNIXPW)
if [regexp {^rm:} \$up] {
set rm 1
regsub {^rm:} \$up {} up
}
if [file exists \$up] {
set fh ""
set f \$up
catch {set fh [open \$up r]}
if {\$fh != ""} {
gets \$fh u
gets \$fh p
close \$fh
set up "\$u@\$p"
}
if {\$rm} {
catch {file delete \$f}
}
}
} elseif [info exists env(SSVNC_VENCRYPT_USERPASS)] {
set up \$env(SSVNC_VENCRYPT_USERPASS)
}
#puts stderr up=\$up
if {\$up != ""} {
if [regexp {@} \$up] {
global user pass
set user \$up
set pass \$up
regsub {@.*\$} \$user "" user
regsub {^[^@]*@} \$pass "" pass
print_out
exit
}
}
wm title . {VeNCrypt Viewer Bridge User/Pass}
set user {}
set pass {}
label .l -text {SSVNC VeNCrypt Viewer Bridge}
frame .f0
frame .f0.fL
label .f0.fL.la -text {Username: }
label .f0.fL.lb -text {Password: }
pack .f0.fL.la .f0.fL.lb -side top
frame .f0.fR
entry .f0.fR.ea -width 24 -textvariable user
entry .f0.fR.eb -width 24 -textvariable pass -show *
pack .f0.fR.ea .f0.fR.eb -side top -fill x
pack .f0.fL -side left
pack .f0.fR -side right -expand 1 -fill x
button .no -text Cancel -command {destroy .}
button .ok -text Done -command {print_out; destroy .}
center_win .
pack .l .f0 .no .ok -side top -fill x
update
wm deiconify .
bind .f0.fR.ea <Return> {focus .f0.fR.eb}
bind .f0.fR.eb <Return> {print_out; destroy .}
focus .f0.fR.ea
wm resizable . 1 0
wm minsize . [winfo reqwidth .] [winfo reqheight .]
END
close W;
#system("cat $handshake_file");
my $w = "wish";
if ($ENV{WISH}) {
$w = $ENV{WISH};
}
print STDERR "pproxy: vencrypt_viewer_bridge[$$]: prompt VencryptPlain user and passwd.\n";
my $res = "";
if (`uname` =~ /Darwin/) {
my $mtmp = `mktemp /tmp/hsup.XXXXXX`;
chomp $mtmp;
system("env SSVNC_UP_FILE=$mtmp $w $handshake_file");
$res = `cat $mtmp`;
unlink $mtmp;
} else {
$res = `$w $handshake_file`;
}
my $user = "";
my $pass = "";
if ($res =~ /user=(\S*)/) {
$user = $1;
}
if ($res =~ /pass=(\S*)/) {
$pass = $1;
}
print STDERR "pproxy: vencrypt_viewer_bridge[$$]: sending VencryptPlain user and passwd.\n";
my $ulen = pack("C", length($user));
my $plen = pack("C", length($pass));
# (note this should be MSB, network byte order...)
syswrite($server_sock, $u0, 1);
syswrite($server_sock, $u0, 1);
syswrite($server_sock, $u0, 1);
syswrite($server_sock, $ulen, 1);
syswrite($server_sock, $u0, 1);
syswrite($server_sock, $u0, 1);
syswrite($server_sock, $u0, 1);
syswrite($server_sock, $plen, 1);
syswrite($server_sock, $user, length($user));
syswrite($server_sock, $pass, length($pass));
}
unlink($handshake_file);
my $ft = 0;
if ($fake_type eq "None") {
$ft = 1;
} elsif ($fake_type eq "VncAuth") {
$ft = 2;
} else {
die "pproxy: vencrypt_viewer_bridge[$$]: unknown fake type: $fake_type\n";
}
my $fp = pack("C", $ft);
if ($viewer_major > 3 || $viewer_minor >= 7) {
syswrite($viewer_sock, $u1, 1);
syswrite($viewer_sock, $fp, 1);
my $cr;
sysread($viewer_sock, $cr, 1);
$cr = unpack("C", $cr);
if ($cr != $ft) {
die "pproxy: vencrypt_viewer_bridge[$$]: client selected wrong type: $cr / $ft\n";
}
} else {
print STDERR "pproxy: vencrypt_viewer_bridge[$$]: faking RFB version 3.3 to viewer.\n";
# send 4 bytes sect type to viewer:
# (note this should be MSB, network byte order...)
syswrite($viewer_sock, $u0, 1);
syswrite($viewer_sock, $u0, 1);
syswrite($viewer_sock, $u0, 1);
syswrite($viewer_sock, $fp, 1);
if ($ft == 1) {
# even None has security result, so read it here and discard it.
my $sr = "";
sysread($server_sock, $sr, 4);
}
}
}
$listen_handle = $viewer_sock;
$sock = $server_sock;
xfer_both();
} }
' '
# ' # '
...@@ -1520,11 +2040,33 @@ END ...@@ -1520,11 +2040,33 @@ END
} }
Kecho() { Kecho() {
if [ "X$USER" = "Xrunge" ]; then NO_KECHO=1
if [ "X$USER" = "Xrunge" -a "X$NO_KECHO" = "X" ]; then
echo "dbg: $*" echo "dbg: $*"
fi fi
} }
NHAFL_warning() {
echo ""
echo "** Warning: For the proxy: $proxy"
echo "** Warning: the ssh(1) option: $ssh_NHAFL"
echo "** Warning: will be used to avoid frequent 'ssh key has changed for localhost'"
echo "** Warning: dialogs and connection failures (for example, ssh will exit asking"
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: You can set the SSVNC_SSH_LOCALHOST_AUTH=1 env. var. to disable"
echo "** Warning: using the NoHostAuthenticationForLocalhost 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 ""
}
# handle ssh case:
#
if [ "X$use_ssh" = "X1" ]; then if [ "X$use_ssh" = "X1" ]; then
# #
# USING SSH # USING SSH
...@@ -1532,9 +2074,47 @@ if [ "X$use_ssh" = "X1" ]; then ...@@ -1532,9 +2074,47 @@ if [ "X$use_ssh" = "X1" ]; then
ssh_port="22" ssh_port="22"
ssh_host="$host" ssh_host="$host"
vnc_host="$localhost" vnc_host="$localhost"
ssh_UKHF=""
localhost_extra=""
# let user override ssh via $SSH # let user override ssh via $SSH
ssh=${SSH:-"ssh -x"} ssh=${SSH:-"ssh -x"}
sshword=`echo "$ssh" | awk '{print $1}'`
if [ "X$sshword" != "X" ]; then
if [ -x "$sshword" ]; then
:
elif type "$sshword" > /dev/null 2>&1; then
:
else
echo ""
echo "*********************************************************"
echo "** Problem finding the SSH command '$sshword': **"
echo ""
type "$sshword"
echo ""
echo "** Perhaps you need to install the SSH client package. **"
echo "*********************************************************"
echo ""
sleep 5
fi
fi
ssh_NHAFL="-o NoHostAuthenticationForLocalhost=yes"
if [ "X$SSVNC_SSH_LOCALHOST_AUTH" = "X1" ]; then
ssh_NHAFL=""
fi
if [ "X$SSVNC_KNOWN_HOSTS_FILE" != "X" ]; then
ssh_NHAFL=""
ssh_UKHF="-o UserKnownHostsFile=$SSVNC_KNOWN_HOSTS_FILE"
ssh_args="$ssh_args $ssh_UKHF"
if [ ! -f "$SSVNC_KNOWN_HOSTS_FILE" ]; then
touch "$SSVNC_KNOWN_HOSTS_FILE" >/dev/null 2>&1
fi
chmod 600 "$SSVNC_KNOWN_HOSTS_FILE" >/dev/null 2>&1
fi
did_ssh_NHAFL=""
if [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" ]; then if [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" ]; then
SSVNC_LIM_ACCEPT_PRELOAD="$SSVNC_BASEDIR/$SSVNC_UNAME/$SSVNC_LIM_ACCEPT_PRELOAD" SSVNC_LIM_ACCEPT_PRELOAD="$SSVNC_BASEDIR/$SSVNC_UNAME/$SSVNC_LIM_ACCEPT_PRELOAD"
fi fi
...@@ -1553,6 +2133,29 @@ if [ "X$use_ssh" = "X1" ]; then ...@@ -1553,6 +2133,29 @@ if [ "X$use_ssh" = "X1" ]; then
SSVNC_LIM_ACCEPT_PRELOAD="" SSVNC_LIM_ACCEPT_PRELOAD=""
fi fi
ssh_vencrypt_proxy=""
# We handle vencrypt for SSH+SSL mode.
if echo "$proxy" | grep 'vencrypt://' > /dev/null; then
proxynew=""
for part in `echo "$proxy" | tr ',' ' '`
do
if echo "$part" | egrep -i '^vencrypt://' > /dev/null; then
ssh_vencrypt_proxy=$part
else
if [ "X$proxynew" = "X" ]; then
proxynew="$part"
else
proxynew="$proxynew,$part"
fi
fi
done
proxy=$proxynew
fi
Kecho ssh_vencrypt_proxy=$ssh_vencrypt_proxy
# note that user must supply http:// for web proxy in SSH and SSH+SSL.
# No xxxx:// implies ssh server+port.
#
if echo "$proxy" | egrep '(http|https|socks|socks4|socks5)://' > /dev/null; then if echo "$proxy" | egrep '(http|https|socks|socks4|socks5)://' > /dev/null; then
# Handle Web or SOCKS proxy(ies) for the initial connect. # Handle Web or SOCKS proxy(ies) for the initial connect.
Kecho host=$host Kecho host=$host
...@@ -1638,11 +2241,16 @@ if [ "X$use_ssh" = "X1" ]; then ...@@ -1638,11 +2241,16 @@ if [ "X$use_ssh" = "X1" ]; then
port=$port_save port=$port_save
host=$host_save host=$host_save
nd=`findfree 6700` nd=`findfree 6600`
PPROXY_LISTEN=$nd; export PPROXY_LISTEN PPROXY_LISTEN=$nd; export PPROXY_LISTEN
$ptmp & $ptmp &
sleep 2 sleep 1
ssh_args="$ssh_args -o NoHostAuthenticationForLocalhost=yes" if [ "X$ssh_NHAFL" != "X" -a "X$did_ssh_NHAFL" != "X1" ]; then
NHAFL_warning
ssh_args="$ssh_args $ssh_NHAFL"
did_ssh_NHAFL=1
fi
sleep 1
if [ "X$sproxy1" = "X" ]; then if [ "X$sproxy1" = "X" ]; then
u="" u=""
if echo "$host" | grep '@' > /dev/null; then if echo "$host" | grep '@' > /dev/null; then
...@@ -1653,6 +2261,7 @@ if [ "X$use_ssh" = "X1" ]; then ...@@ -1653,6 +2261,7 @@ if [ "X$use_ssh" = "X1" ]; then
else else
proxy="${sproxy1_user}$localhost:$nd" proxy="${sproxy1_user}$localhost:$nd"
fi fi
localhost_extra=".2"
if [ "X$sproxy_rest" != "X" ]; then if [ "X$sproxy_rest" != "X" ]; then
proxy="$proxy,$sproxy_rest" proxy="$proxy,$sproxy_rest"
fi fi
...@@ -1684,12 +2293,21 @@ if [ "X$use_ssh" = "X1" ]; then ...@@ -1684,12 +2293,21 @@ if [ "X$use_ssh" = "X1" ]; then
ssh_port2="22" ssh_port2="22"
fi fi
proxport=`findfree 3500` proxport=`findfree 3500`
if [ "X$ssh_NHAFL" != "X" -a "X$did_ssh_NHAFL" != "X1" ]; then
NHAFL_warning
did_ssh_NHAFL=1
sleep 1
fi
echo echo
echo "Running 1st ssh proxy:" echo "Running 1st ssh proxy:"
echo "$ssh -f -x $ssh_port1 $targ -e none -o NoHostAuthenticationForLocalhost=yes -L $proxport:$ssh_host2:$ssh_port2 $ssh_host1 \"sleep 30\"" ukhf=""
if [ "X$ssh_UKHF" != "X" ]; then
ukhf="$ssh_UKHF$localhost_extra"
fi
echo "$ssh -f -x $ssh_port1 $targ -e none $ssh_NHAFL $ukhf -L $proxport:$ssh_host2:$ssh_port2 $ssh_host1 \"sleep 30\""
echo "" echo ""
$ssh -f -x $ssh_port1 $targ -e none -o NoHostAuthenticationForLocalhost=yes -L $proxport:$ssh_host2:$ssh_port2 $ssh_host1 "sleep 30" $ssh -f -x $ssh_port1 $targ -e none $ssh_NHAFL $ukhf -L $proxport:$ssh_host2:$ssh_port2 $ssh_host1 "sleep 30"
ssh_args="$ssh_args -o NoHostAuthenticationForLocalhost=yes" ssh_args="$ssh_args $ssh_NHAFL"
sleep 1 sleep 1
stty sane stty sane
proxy="${ssh_user2}$localhost:$proxport" proxy="${ssh_user2}$localhost:$proxport"
...@@ -1764,6 +2382,8 @@ if [ "X$use_ssh" = "X1" ]; then ...@@ -1764,6 +2382,8 @@ if [ "X$use_ssh" = "X1" ]; then
elif [ "X$getport" != "X" ]; then elif [ "X$getport" != "X" ]; then
tport=/tmp/ss_vncviewer_tport${RANDOM}.$$ tport=/tmp/ss_vncviewer_tport${RANDOM}.$$
tport=`mytmp "$tport"` tport=`mytmp "$tport"`
tport2=/tmp/ss_vncviewer_tport2${RANDOM}.$$
tport2=`mytmp "$tport2"`
if [ "X$rsh" != "X1" ]; then if [ "X$rsh" != "X1" ]; then
if echo "$ssh_cmd" | grep "sudo " > /dev/null; then if echo "$ssh_cmd" | grep "sudo " > /dev/null; then
...@@ -1777,10 +2397,12 @@ if [ "X$use_ssh" = "X1" ]; then ...@@ -1777,10 +2397,12 @@ if [ "X$use_ssh" = "X1" ]; then
fi fi
echo "$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host \"$info\"" echo "$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host \"$info\""
echo "" echo ""
$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host "$ssh_cmd" > $tport $ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host "$ssh_cmd" > $tport 2> $tport2
if [ "X$teeport" = "X1" ]; then if [ "X$teeport" = "X1" ]; then
tail -f $tport 1>&2 & tail -f $tport 1>&2 &
tail_pid=$! tail_pid=$!
tail -f $tport2 1>&2 &
tail_pid2=$!
fi fi
rc=$? rc=$?
else else
...@@ -1809,11 +2431,11 @@ if [ "X$use_ssh" = "X1" ]; then ...@@ -1809,11 +2431,11 @@ if [ "X$use_ssh" = "X1" ]; then
while [ $i -lt $imax ]; do while [ $i -lt $imax ]; do
#echo $sleepit #echo $sleepit
eval $sleepit eval $sleepit
PORT=`grep "^PORT=" $tport | head -n 1 | sed -e 's/PORT=//' -e 's/\r//g'` PORT=`grep "^PORT=" $tport | tr '\r' ' ' | head -n 1 | sed -e 's/PORT=//' -e 's/\r//g' -e 's/ *$//'`
if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then
break break
fi fi
vnss=`sed -e 's/\r//g' $tport | egrep -i '^(New.* desktop is|A VNC server is already running).*:[0-9[0-9]*$' | head -n 1 | awk '{print $NF}'` vnss=`sed -e 's/\r//g' $tport $tport2 | egrep -i '^(New.* desktop is|A VNC server is already running).*:[0-9[0-9]*$' | head -n 1 | awk '{print $NF}'`
if [ "X$vnss" != "X" ]; then if [ "X$vnss" != "X" ]; then
PORT=`echo "$vnss" | awk -F: '{print $2}'` PORT=`echo "$vnss" | awk -F: '{print $2}'`
if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then
...@@ -1822,14 +2444,16 @@ if [ "X$use_ssh" = "X1" ]; then ...@@ -1822,14 +2444,16 @@ if [ "X$use_ssh" = "X1" ]; then
fi fi
fi fi
if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then
vnss=`sed -e 's/\r//g' $tport | egrep -i '^(New.* desktop is|A VNC server is already running).*:[0-9[0-9]*$' | head -n 1`
echo "vncserver string: $vnss" 1>&2
break break
fi fi
fi fi
i=`expr $i + 1` i=`expr $i + 1`
done done
echo "PORT=$PORT" 1>&2 echo "found: PORT='$PORT'" 1>&2
rm -f $tport rm -f $tport $tport2
if [ "X$rsh" = "X1" ]; then if [ "X$rsh" = "X1" ]; then
rsh_viewer "$@" rsh_viewer "$@"
exit $? exit $?
...@@ -1955,6 +2579,33 @@ if [ "X$use_ssh" = "X1" ]; then ...@@ -1955,6 +2579,33 @@ if [ "X$use_ssh" = "X1" ]; then
else else
proxy="" proxy=""
fi fi
if [ "X$ssh_vencrypt_proxy" != "X" ]; then
ssh_vencrypt_proxy="vencrypt://$host:$port"
if [ "X$proxy" = "X" ]; then
proxy=$ssh_vencrypt_proxy
else
proxy="$proxy,$ssh_vencrypt_proxy"
fi
Kecho "proxy_now=$proxy"
unset PPROXY_LISTEN
fi
fi
fi
if [ "X$stunnel_set_here" = "X1" -a "X$showcert" = "X" ]; then
if type $STUNNEL > /dev/null 2>&1; then
:
else
echo ""
echo "***************************************************************"
echo "** Problem finding the Stunnel command '$STUNNEL': **"
echo ""
type $STUNNEL
echo ""
echo "** Perhaps you need to install the stunnel/stunnel4 package. **"
echo "***************************************************************"
echo ""
sleep 5
fi fi
fi fi
...@@ -1968,6 +2619,9 @@ if [ "X$verify" != "X" ]; then ...@@ -1968,6 +2619,9 @@ if [ "X$verify" != "X" ]; then
verify="$verify verify="$verify
verify = 2" verify = 2"
fi fi
if [ "X$SSVNC_STUNNEL_VERIFY3" != "X" ]; then
verify=`echo "$verify" | sed -e 's/verify = 2/verify = 3/'`
fi
if [ "X$mycert" != "X" ]; then if [ "X$mycert" != "X" ]; then
cert="cert = $mycert" cert="cert = $mycert"
fi fi
...@@ -1997,7 +2651,6 @@ if [ "X$proxy" != "X" ]; then ...@@ -1997,7 +2651,6 @@ if [ "X$proxy" != "X" ]; then
PPROXY_LISTEN=$nd PPROXY_LISTEN=$nd
export PPROXY_LISTEN export PPROXY_LISTEN
if [ "X$reverse" = "X" ]; then if [ "X$reverse" = "X" ]; then
#$ptmp 2>/dev/null &
$ptmp & $ptmp &
fi fi
sleep 2 sleep 2
...@@ -2016,6 +2669,8 @@ else ...@@ -2016,6 +2669,8 @@ else
connect="connect = $host:$port" connect="connect = $host:$port"
fi fi
# handle showcert case:
#
if [ "X$showcert" = "X1" ]; then if [ "X$showcert" = "X1" ]; then
if [ "X$proxy" != "X" ]; then if [ "X$proxy" != "X" ]; then
PPROXY_LISTEN=$use PPROXY_LISTEN=$use
...@@ -2026,6 +2681,23 @@ if [ "X$showcert" = "X1" ]; then ...@@ -2026,6 +2681,23 @@ if [ "X$showcert" = "X1" ]; then
$ptmp 2>/dev/null & $ptmp 2>/dev/null &
fi fi
sleep 1 sleep 1
more_sleep=1
if uname | grep Linux > /dev/null; then
if netstat -ant | grep LISTEN | grep "127.0.0.1:$use" > /dev/null; then
more_sleep=""
fi
elif uname | grep SunOS > /dev/null; then
if netstat -an -f inet -P tcp | grep LISTEN | grep "127.0.0.1.$use" > /dev/null; then
more_sleep=""
fi
elif uname | egrep -i 'bsd|darwin' > /dev/null; then
if netstat -ant -f inet | grep LISTEN | grep "127.0.0.1.$use" > /dev/null; then
more_sleep=""
fi
fi
if [ "X$more_sleep" = "X1" ]; then
sleep 1
fi
host="$localhost" host="$localhost"
port="$use" port="$use"
fi fi
...@@ -2033,8 +2705,30 @@ if [ "X$showcert" = "X1" ]; then ...@@ -2033,8 +2705,30 @@ if [ "X$showcert" = "X1" ]; then
if [ "X$ciphers" != "X" ]; then if [ "X$ciphers" != "X" ]; then
cipher_args=`echo "$ciphers" | sed -e 's/ciphers=/-cipher /'` cipher_args=`echo "$ciphers" | sed -e 's/ciphers=/-cipher /'`
fi fi
if type openssl > /dev/null 2>&1; then
:
else
echo ""
echo "********************************************************"
echo "** Problem finding the OpenSSL command 'openssl': **"
echo ""
type openssl 2>&1
echo ""
echo "** Perhaps you need to install the 'openssl' package. **"
echo "********************************************************"
echo ""
fi
#echo "openssl s_client $cipher_args -connect $host:$port" #echo "openssl s_client $cipher_args -connect $host:$port"
if [ "X$reverse" = "X" ]; then if [ "X$reverse" = "X" ]; then
host $host >/dev/null 2>&1
host $host >/dev/null 2>&1
timeout=15
if [ "X$SSVNC_FETCH_TIMEOUT" != "X" ]; then
timeout=$SSVNC_FETCH_TIMEOUT
fi
if type pkill >/dev/null 2>&1; then
(sleep $timeout; if kill -0 $$; then pkill -TERM -f "openssl.*s_client.*$host.*$port"; fi) >/dev/null 2>&1 &
fi
openssl s_client $cipher_args -prexit -connect $host:$port 2>&1 < /dev/null openssl s_client $cipher_args -prexit -connect $host:$port 2>&1 < /dev/null
rc=$? rc=$?
else else
...@@ -2052,6 +2746,9 @@ if [ "X$showcert" = "X1" ]; then ...@@ -2052,6 +2746,9 @@ if [ "X$showcert" = "X1" ]; then
#echo "openssl s_server $cipher_args $cert_args -accept $port -verify 2 > $tmp_out 2> $tmp_err" 1>&2 #echo "openssl s_server $cipher_args $cert_args -accept $port -verify 2 > $tmp_out 2> $tmp_err" 1>&2
# assume we have perl:
check_perl perl
perl -e " perl -e "
\$p = open(O, \"|openssl s_server $cipher_args $cert_args -accept $port -verify 2 1>$tmp_out 2> $tmp_err\"); \$p = open(O, \"|openssl s_server $cipher_args $cert_args -accept $port -verify 2 1>$tmp_out 2> $tmp_err\");
exit 1 unless \$p; exit 1 unless \$p;
...@@ -2094,9 +2791,15 @@ if [ "X$showcert" = "X1" ]; then ...@@ -2094,9 +2791,15 @@ if [ "X$showcert" = "X1" ]; then
if [ "X$SSVNC_PREDIGESTED_HANDSHAKE" != "X" ]; then if [ "X$SSVNC_PREDIGESTED_HANDSHAKE" != "X" ]; then
rm -f $SSVNC_PREDIGESTED_HANDSHAKE rm -f $SSVNC_PREDIGESTED_HANDSHAKE
fi fi
if [ "X$SSVNC_SHOWCERT_EXIT_0" = "X1" ]; then
exit 0
else
exit $rc exit $rc
fi
fi fi
# handle direct connect case:
#
if [ "X$direct_connect" != "X" ]; then if [ "X$direct_connect" != "X" ]; then
if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then
SSVNC_NO_ENC_WARN=1 SSVNC_NO_ENC_WARN=1
...@@ -2113,7 +2816,7 @@ if [ "X$direct_connect" != "X" ]; then ...@@ -2113,7 +2816,7 @@ if [ "X$direct_connect" != "X" ]; then
: :
else else
echo "" echo ""
echo "** NOTE: THERE WILL BE NO SSL OR SSH ENCRYPTION **" echo "** WARNING: THERE WILL BE NO SSL OR SSH ENCRYPTION **"
echo "" echo ""
fi fi
fi fi
...@@ -2334,6 +3037,14 @@ echo "Using this stunnel configuration:" ...@@ -2334,6 +3037,14 @@ echo "Using this stunnel configuration:"
echo "" echo ""
cat "$tmp_cfg" | uniq cat "$tmp_cfg" | uniq
echo "" echo ""
if egrep -i '^[ ]*(CApath|CAfile) =' "$tmp_cfg" > /dev/null ; then
:
else
echo "** WARNING: THE STUNNEL CONFIG HAS NO SERVER CERTIFICATE SPECIFIED **"
echo "** WARNING: (the CApath or CAfile stunnel option) THE VNC SERVER WILL **"
echo "** WARNING: NOT BE AUTHENTICATED. A MAN-IN-THE-MIDDLE ATTACK IS POSSIBLE **"
echo ""
fi
sleep 1 sleep 1
if [ "X$stunnel_exec" = "X" ]; then if [ "X$stunnel_exec" = "X" ]; then
...@@ -2376,8 +3087,16 @@ if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then ...@@ -2376,8 +3087,16 @@ if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then
echo "sleep $SSVNC_EXTRA_SLEEP" echo "sleep $SSVNC_EXTRA_SLEEP"
sleep $SSVNC_EXTRA_SLEEP sleep $SSVNC_EXTRA_SLEEP
fi fi
echo "Running viewer:"
if [ "X$reverse" = "X" ]; then if [ "X$reverse" = "X" ]; then
if [ "X$NEED_VENCRYPT_VIEWER_BRIDGE" = "X1" -a "X$ptmp" != "X" ] ; then
port1=`expr 5900 + $N` # stunnel port
port2=`findfree 5970` # bridge port (viewer connects to it.)
N=`expr $port2 - 5900`
env PPROXY_REMOVE=0 PPROXY_SLEEP=0 PPROXY_VENCRYPT_VIEWER_BRIDGE="$port2,$port1" $ptmp &
sleep 1
fi
echo "Running viewer:"
vnc_hp=$localhost:$N vnc_hp=$localhost:$N
if [ "X$stunnel_exec" != "X" ]; then if [ "X$stunnel_exec" != "X" ]; then
vnc_hp="exec=$STUNNEL $tmp_cfg" vnc_hp="exec=$STUNNEL $tmp_cfg"
...@@ -2394,19 +3113,16 @@ if [ "X$reverse" = "X" ]; then ...@@ -2394,19 +3113,16 @@ if [ "X$reverse" = "X" ]; then
fi fi
fi fi
else else
echo "Running viewer:"
echo "" echo ""
echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode." echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode."
echo "" echo ""
trap "final" 0 2 15
N2=$N N2=$N
if [ "X$VNCVIEWER_IS_REALVNC4" = "X1" ]; then N2_trim=`echo "$N2" | sed -e 's/://g'`
N2=`echo "$N2" | sed -e 's/://g'` if [ $N2_trim -le 200 ]; then
if [ $N2 -le 200 ]; then N2_trim=`expr $N2_trim + 5500`
N2=`expr $N2 + 5500`
fi fi
fi
echo "$VNCVIEWERCMD" "$@" -listen $N2
trap "final" 0 2 15
echo ""
if [ "X$proxy" != "X" ]; then if [ "X$proxy" != "X" ]; then
if echo "$proxy" | grep -i '^vencrypt:' > /dev/null; then if echo "$proxy" | grep -i '^vencrypt:' > /dev/null; then
pstunnel=`echo "$proxy" | awk -F: '{print $2}'` pstunnel=`echo "$proxy" | awk -F: '{print $2}'`
...@@ -2416,13 +3132,30 @@ else ...@@ -2416,13 +3132,30 @@ else
PPROXY_DEST="$localhost:$pstunnel"; export PPROXY_DEST PPROXY_DEST="$localhost:$pstunnel"; export PPROXY_DEST
STUNNEL_ONCE=1; export STUNNEL_ONCE STUNNEL_ONCE=1; export STUNNEL_ONCE
STUNNEL_MAX_CLIENTS=1; export STUNNEL_MAX_CLIENTS STUNNEL_MAX_CLIENTS=1; export STUNNEL_MAX_CLIENTS
if [ "X$NEED_VENCRYPT_VIEWER_BRIDGE" = "X1" -a "X$ptmp" != "X" ] ; then
port1=`expr 5500 + $N2`
port2=`findfree 5580`
N2=`expr $port2 - 5500`
N2_trim=`echo "$N2" | sed -e 's/://g'`
if [ $N2_trim -le 200 ]; then
N2_trim=`expr $N2_trim + 5500`
fi
env PPROXY_REMOVE=0 PPROXY_SLEEP=0 PPROXY_VENCRYPT_VIEWER_BRIDGE="-$port1,$port2" $ptmp &
sleep 1
fi
else else
PPROXY_REVERSE="$localhost:$port"; export PPROXY_REVERSE PPROXY_REVERSE="$localhost:$port"; export PPROXY_REVERSE
PPROXY_SLEEP=1; export PPROXY_SLEEP; PPROXY_SLEEP=1; export PPROXY_SLEEP;
fi fi
PPROXY_KILLPID=+1; export PPROXY_KILLPID; PPROXY_KILLPID=+1; export PPROXY_KILLPID;
$ptmp & $ptmp &
# Important to have no extra pids generated between here and VNCVIEWERCMD
fi
if [ "X$VNCVIEWER_IS_REALVNC4" = "X1" ]; then
N2=$N2_trim
fi fi
echo "$VNCVIEWERCMD" "$@" -listen $N2
echo ""
$VNCVIEWERCMD "$@" -listen $N2 $VNCVIEWERCMD "$@" -listen $N2
fi fi
......
...@@ -2644,8 +2644,8 @@ diff -Naur JavaViewer.orig/RfbProto.java JavaViewer/RfbProto.java ...@@ -2644,8 +2644,8 @@ diff -Naur JavaViewer.orig/RfbProto.java JavaViewer/RfbProto.java
// } // }
diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java
--- JavaViewer.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500 --- JavaViewer.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500
+++ JavaViewer/SSLSocketToMe.java 2009-06-19 10:23:50.000000000 -0400 +++ JavaViewer/SSLSocketToMe.java 2009-08-13 09:16:42.000000000 -0400
@@ -0,0 +1,1726 @@ @@ -0,0 +1,1727 @@
+/* +/*
+ * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer. + * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer.
+ * + *
...@@ -2654,7 +2654,8 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java ...@@ -2654,7 +2654,8 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java
+ * + *
+ * This is free software; you can redistribute it and/or modify + * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by + * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License. + * the Free Software Foundation; version 2 of the License, or
+ * (at your option) any later version.
+ * + *
+ * This software is distributed in the hope that it will be useful, + * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of + * but WITHOUT ANY WARRANTY; without even the implied warranty of
......
2009-12-04 Karl Runge <runge@karlrunge.com>
* classes/ssl: update binaries; new signing key; ss_vncviewer.
* x11vnc: add more wish possibilities for -gui. Declare crypt()
on all platforms (disable with -DDO_NOT_DECLARE_CRYPT.)
2009-12-02 Karl Runge <runge@karlrunge.com> 2009-12-02 Karl Runge <runge@karlrunge.com>
* x11vnc: -appshare mode for sharing an application windows intead * x11vnc: -appshare mode for sharing an application windows of the
of the entire desktop. map port + 5500 in reverse connect. entire desktop. map port + 5500 in reverse connect. Add id_cmd
Add id_cmd remote control functions for id (and other) windows. remote control functions for id (and other) windows. Allow zero
Allow zero port in SSL reverse connections. Adjust delays port in SSL reverse connections. Adjust delays between multiple
between multiple reverse connections; X11VNC_REVERSE_SLEEP_MAX reverse connections; X11VNC_REVERSE_SLEEP_MAX env var. Add some
env var. Add some missing mutex locks; add INPUT_LOCK and missing mutex locks; add INPUT_LOCK and threads_drop_input.
threads_drop_input. More safety in -threads mode for new More safety in -threads mode for new framebuffer change. Fix
framebuffer change. Fix some stderr leaking in -inetd mode. some stderr leaking in -inetd mode.
2009-11-18 Karl Runge <runge@karlrunge.com> 2009-11-18 Karl Runge <runge@karlrunge.com>
* x11vnc: use -timeout setting for reverse connections too. * x11vnc: use -timeout setting for reverse connections too.
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Copyright (C) 2002-2009 Karl J. Runge <runge@karlrunge.com> Copyright (C) 2002-2009 Karl J. Runge <runge@karlrunge.com>
All rights reserved. All rights reserved.
x11vnc README file Date: Wed Dec 2 22:03:06 EST 2009 x11vnc README file Date: Fri Dec 4 20:44:56 EST 2009
The following information is taken from these URLs: The following information is taken from these URLs:
...@@ -12894,7 +12894,7 @@ x11vnc: a VNC server for real X displays ...@@ -12894,7 +12894,7 @@ x11vnc: a VNC server for real X displays
Here are all of x11vnc command line options: Here are all of x11vnc command line options:
% x11vnc -opts (see below for -help long descriptions) % x11vnc -opts (see below for -help long descriptions)
x11vnc: allow VNC connections to real X11 displays. 0.9.9 lastmod: 2009-12-02 x11vnc: allow VNC connections to real X11 displays. 0.9.9 lastmod: 2009-12-04
x11vnc options: x11vnc options:
-display disp -auth file -N -display disp -auth file -N
...@@ -13021,7 +13021,7 @@ libvncserver-tight-extension options: ...@@ -13021,7 +13021,7 @@ libvncserver-tight-extension options:
% x11vnc -help % x11vnc -help
x11vnc: allow VNC connections to real X11 displays. 0.9.9 lastmod: 2009-12-02 x11vnc: allow VNC connections to real X11 displays. 0.9.9 lastmod: 2009-12-04
(type "x11vnc -opts" to just list the options.) (type "x11vnc -opts" to just list the options.)
......
...@@ -473,7 +473,7 @@ static void launch(Window win) { ...@@ -473,7 +473,7 @@ static void launch(Window win) {
char *q = strstr(cmd, "-connect_or_exit"); char *q = strstr(cmd, "-connect_or_exit");
if (q) q = strstr(q, "_or_exit"); if (q) q = strstr(q, "_or_exit");
if (q) { if (q) {
int i; unsigned int i;
for (i=0; i < strlen("_or_exit"); i++) { for (i=0; i < strlen("_or_exit"); i++) {
*q = ' '; *q = ' ';
q++; q++;
...@@ -907,7 +907,7 @@ static void recurse_search(int level, int level_max, Window top, Window app, int ...@@ -907,7 +907,7 @@ static void recurse_search(int level, int level_max, Window top, Window app, int
ok = XQueryTree(dpy, top, &r, &parent, &list, &nchild); ok = XQueryTree(dpy, top, &r, &parent, &list, &nchild);
if (ok) { if (ok) {
int i; int i;
for (i=0; i < nchild; i++) { for (i=0; i < (int) nchild; i++) {
w = list[i]; w = list[i];
if (w == None || find_win(w) >= 0) { if (w == None || find_win(w) >= 0) {
continue; continue;
...@@ -919,7 +919,7 @@ static void recurse_search(int level, int level_max, Window top, Window app, int ...@@ -919,7 +919,7 @@ static void recurse_search(int level, int level_max, Window top, Window app, int
(*nw)++; (*nw)++;
} }
} }
for (i=0; i < nchild; i++) { for (i=0; i < (int) nchild; i++) {
w = list[i]; w = list[i];
if (w == None || ours(w)) { if (w == None || ours(w)) {
continue; continue;
......
...@@ -261,9 +261,11 @@ static void sigusr1 (int sig) { ...@@ -261,9 +261,11 @@ static void sigusr1 (int sig) {
if (0) sig = 0; if (0) sig = 0;
} }
/* Most of the following mess is for wish on Solaris: */
static char *extra_path = ":/usr/local/bin:/usr/bin/X11:/usr/sfw/bin" static char *extra_path = ":/usr/local/bin:/usr/bin/X11:/usr/sfw/bin"
":/usr/X11R6/bin:/usr/openwin/bin:/usr/dt/bin"; ":/usr/X11R6/bin:/usr/openwin/bin:/usr/dt/bin:/opt/sfw/bin";
static char *wishes[] = {"wish8.4", "wish", "wish8.3", "wish8.5", "wish8.0", NULL}; static char *wishes[] = {"wish8.4", "wish", "wish8.3", "wish8.5", "wish8.6", "wish8.7", "wishx", "wish8.0", NULL};
static void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int start_x11vnc, static void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int start_x11vnc,
int simple_gui, pid_t parent, char *gui_opts) { int simple_gui, pid_t parent, char *gui_opts) {
...@@ -440,6 +442,15 @@ if (0) fprintf(stderr, "run_gui: %s -- %d %d\n", gui_xdisplay, connect_to_x11vnc ...@@ -440,6 +442,15 @@ if (0) fprintf(stderr, "run_gui: %s -- %d %d\n", gui_xdisplay, connect_to_x11vnc
if (!wish) { if (!wish) {
wish = strdup("wish"); wish = strdup("wish");
} }
if (getenv("WISH")) {
char *w = getenv("WISH");
if (strcmp(w, "")) {
wish = strdup(w);
}
}
if (getenv("DEBUG_WISH")) {
fprintf(stderr, "wish: %s\n", wish);
}
set_env("PATH", full_path); set_env("PATH", full_path);
set_env("DISPLAY", gui_xdisplay); set_env("DISPLAY", gui_xdisplay);
set_env("X11VNC_PROG", program_name); set_env("X11VNC_PROG", program_name);
......
...@@ -37,7 +37,9 @@ so, delete this exception statement from your version. ...@@ -37,7 +37,9 @@ so, delete this exception statement from your version.
extern int grantpt(int); extern int grantpt(int);
extern int unlockpt(int); extern int unlockpt(int);
extern char *ptsname(int); extern char *ptsname(int);
/* XXX remove need for this */ #endif
#ifndef DO_NOT_DECLARE_CRYPT
extern char *crypt(const char*, const char *); extern char *crypt(const char*, const char *);
#endif #endif
...@@ -800,7 +802,7 @@ int crypt_verify(char *user, char *pass) { ...@@ -800,7 +802,7 @@ int crypt_verify(char *user, char *pass) {
fprintf(stderr, "user='%s' pass='%s' realpw='%s' cr='%s'\n", fprintf(stderr, "user='%s' pass='%s' realpw='%s' cr='%s'\n",
user, pass, realpw, cr ? cr : "(null)"); user, pass, realpw, cr ? cr : "(null)");
} }
if (cr == NULL) { if (cr == NULL || cr[0] == '\0') {
return 0; return 0;
} }
if (!strcmp(cr, realpw)) { if (!strcmp(cr, realpw)) {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
.TH X11VNC "1" "December 2009" "x11vnc " "User Commands" .TH X11VNC "1" "December 2009" "x11vnc " "User Commands"
.SH NAME .SH NAME
x11vnc - allow VNC connections to real X11 displays x11vnc - allow VNC connections to real X11 displays
version: 0.9.9, lastmod: 2009-12-02 version: 0.9.9, lastmod: 2009-12-04
.SH SYNOPSIS .SH SYNOPSIS
.B x11vnc .B x11vnc
[OPTION]... [OPTION]...
......
...@@ -47,7 +47,7 @@ int xtrap_base_event_type = 0; ...@@ -47,7 +47,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0; int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */ /* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.9.9 lastmod: 2009-12-02"; char lastmod[] = "0.9.9 lastmod: 2009-12-04";
/* X display info */ /* X display info */
......
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