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")) {