diff options
-rwxr-xr-x | classes/ssl/ss_vncviewer | 370 |
1 files changed, 317 insertions, 53 deletions
diff --git a/classes/ssl/ss_vncviewer b/classes/ssl/ss_vncviewer index 75020df..12fe6b2 100755 --- a/classes/ssl/ss_vncviewer +++ b/classes/ssl/ss_vncviewer @@ -162,6 +162,9 @@ ssh_args="" showcert="" reverse="" +ciphers="" +anondh="ALL:RC4+RSA:+SSLv2:@STRENGTH" + if [ "X$1" = "X-viewerflavor" ]; then # special case, try to guess which viewer: # @@ -196,6 +199,10 @@ if [ "X$SS_VNCVIEWER_NO_MAXCONN" != "X" ]; then STUNNEL_EXTRA_OPTS=`echo "$STUNNEL_EXTRA_OPTS" | sed -e 's/maxconn/#maxconn/'` elif echo "$VNCVIEWERCMD" | egrep -i '^(xmessage|sleep )' > /dev/null; then STUNNEL_EXTRA_OPTS=`echo "$STUNNEL_EXTRA_OPTS" | sed -e 's/maxconn/#maxconn/'` +else + STUNNEL_ONCE=1; export STUNNEL_ONCE + STUNNEL_MAX_CLIENTS=1; export STUNNEL_MAX_CLIENTS + STUNNEL_NO_SYSLOG=1; export STUNNEL_NO_SYSLOG fi # grab our cmdline options: @@ -217,6 +224,10 @@ do ;; "-sshargs") shift; ssh_args="$1" ;; + "-anondh") ciphers="ciphers=$anondh" + ;; + "-ciphers") shift; ciphers="ciphers=$1" + ;; "-alpha") gotalpha=1 ;; "-showcert") showcert=1 @@ -235,6 +246,8 @@ do ;; "-scale") shift; SSVNC_SCALE="$1"; export SSVNC_SCALE ;; + "-escape") shift; VNCVIEWER_ESCAPE="$1"; export VNCVIEWER_ESCAPE + ;; "-ssvnc_encodings") shift; VNCVIEWER_ENCODINGS="$1"; export VNCVIEWER_ENCODINGS ;; "-rfbversion") shift; VNCVIEWER_RFBVERSION="$1"; export VNCVIEWER_RFBVERSION @@ -302,6 +315,47 @@ fi orig="$1" shift +dL="-L" +if uname -sr | egrep 'SunOS 5\.[5-8]' > /dev/null; then + dL="-h" +fi + +# a portable, but not absolutely safe, tmp file creator +mytmp() { + tf=$1 + if type mktemp > /dev/null 2>&1; then + # if we have mktemp(1), use it: + tf2="$tf.XXXXXX" + tf2=`mktemp "$tf2"` + if [ "X$tf2" != "X" -a -f "$tf2" ]; then + if [ "X$DEBUG_MKTEMP" != "X" ]; then + echo "mytmp-mktemp: $tf2" 1>&2 + fi + echo "$tf2" + return + fi + fi + # fallback to multiple cmds: + rm -rf "$tf" || exit 1 + if [ -d "$tf" ]; then + echo "tmp file $tf still exists as a directory." + exit 1 + elif [ $dL "$tf" ]; then + echo "tmp file $tf still exists as a symlink." + exit 1 + elif [ -f "$tf" ]; then + echo "tmp file $tf still exists." + exit 1 + fi + touch "$tf" || exit 1 + chmod 600 "$tf" || exit 1 + rchk + if [ "X$DEBUG_MKTEMP" != "X" ]; then + echo "mytmp-touch: $tf" 1>&2 + fi + echo "$tf" +} + # set up special case of ultravnc single click III mode: if echo "$proxy" | egrep "^sslrepeater://" > /dev/null; then pstr=`echo "$proxy" | sed -e 's,sslrepeater://,,'` @@ -313,6 +367,13 @@ if echo "$proxy" | egrep "^sslrepeater://" > /dev/null; then echo "reset: SSVNC_REPEATER=$SSVNC_REPEATER orig=$orig proxy=''" proxy="" fi +if echo "$proxy" | egrep "vencrypt://" > /dev/null; then + vtmp="/tmp/ss_handshake${RANDOM}.$$.txt" + vtmp=`mytmp "$vtmp"` + SSVNC_PREDIGESTED_HANDSHAKE="$vtmp" + export SSVNC_PREDIGESTED_HANDSHAKE + #echo "SSVNC_PREDIGESTED_HANDSHAKE=$SSVNC_PREDIGESTED_HANDSHAKE" +fi # check -ssh and -mycert/-verify conflict: @@ -559,47 +620,6 @@ rchk() { } rchk -dL="-L" -if uname -sr | egrep 'SunOS 5\.[5-8]' > /dev/null; then - dL="-h" -fi - -# a portable, but not absolutely safe, tmp file creator -mytmp() { - tf=$1 - if type mktemp > /dev/null 2>&1; then - # if we have mktemp(1), use it: - tf2="$tf.XXXXXX" - tf2=`mktemp "$tf2"` - if [ "X$tf2" != "X" -a -f "$tf2" ]; then - if [ "X$DEBUG_MKTEMP" != "X" ]; then - echo "mytmp-mktemp: $tf2" 1>&2 - fi - echo "$tf2" - return - fi - fi - # fallback to multiple cmds: - rm -rf "$tf" || exit 1 - if [ -d "$tf" ]; then - echo "tmp file $tf still exists as a directory." - exit 1 - elif [ $dL "$tf" ]; then - echo "tmp file $tf still exists as a symlink." - exit 1 - elif [ -f "$tf" ]; then - echo "tmp file $tf still exists." - exit 1 - fi - touch "$tf" || exit 1 - chmod 600 "$tf" || exit 1 - rchk - if [ "X$DEBUG_MKTEMP" != "X" ]; then - echo "mytmp-touch: $tf" 1>&2 - fi - echo "$tf" -} - # trick for the undocumented rsh://host:port method. rsh_setup() { if echo "$ssh_host" | grep '@' > /dev/null; then @@ -663,6 +683,32 @@ if ($ENV{PPROXY_SOCKS} ne "" && $ENV{PPROXY_PROXY} !~ m,^socks5?://,i) { } } +my $rfbSecTypeTlsVnc = 18; +my $rfbSecTypeVencrypt = 19; + +my $rfbVencryptPlain = 256; +my $rfbVencryptTlsNone = 257; +my $rfbVencryptTlsVnc = 258; +my $rfbVencryptTlsPlain = 259; +my $rfbVencryptX509None = 260; +my $rfbVencryptX509Vnc = 261; +my $rfbVencryptX509Plain = 262; + +my $handshake_file = ""; +if (exists $ENV{SSVNC_PREDIGESTED_HANDSHAKE}) { + $handshake_file = $ENV{SSVNC_PREDIGESTED_HANDSHAKE}; +} + +sub append_handshake { + my $str = shift; + if ($handshake_file) { + if (open(HSF, ">>$handshake_file")) { + print HSF $str; + close HSF; + } + } +} + my ($first, $second, $third) = split(/,/, $ENV{PPROXY_PROXY}, 3); my ($mode_1st, $mode_2nd, $mode_3rd) = ("", "", ""); @@ -823,6 +869,18 @@ sub url_parse { if ($hostport !~ /:\d+/) { $hostport .= ":5900"; } + } elsif ($hostport =~ m,^vencrypt://(\S*)$,i) { + # vencrypt handshake. + $hostport = $1; + my $m = "connect"; + if ($hostpost =~ /^(\S+)\+(\S+)$/) { + $hostport = $1; + $mode = $2; + } + $mode = "vencrypt:$m"; + if ($hostport !~ /:\d+/) { + $hostport .= ":5900"; + } } return ($hostport, $mode); } @@ -830,6 +888,7 @@ sub url_parse { sub setmode { my $mode = shift; $ENV{PPROXY_REPEATER} = ""; + $ENV{PPROXY_VENCRYPT} = ""; if ($mode =~ /^socks/) { if ($mode =~ /^socks5/) { $ENV{PPROXY_SOCKS} = 5; @@ -839,6 +898,9 @@ sub setmode { } elsif ($mode =~ /^repeater:(.*)/) { $ENV{PPROXY_REPEATER} = $1; $ENV{PPROXY_SOCKS} = ""; + } elsif ($mode =~ /^vencrypt:(.*)/) { + $ENV{PPROXY_VENCRYPT} = $1; + $ENV{PPROXY_SOCKS} = ""; } else { $ENV{PPROXY_SOCKS} = ""; } @@ -980,6 +1042,9 @@ sub connection { sysread($sock, $c, 1); print STDERR $c; } + } elsif ($ENV{PPROXY_VENCRYPT} ne "") { + my $vencrypt = $ENV{PPROXY_VENCRYPT}; + vencrypt_dialog($vencrypt); } else { # Web Proxy: @@ -1008,6 +1073,189 @@ sub connection { } } +sub vdie { + append_handshake("done\n"); + close $sock; + exit(1); +} + +sub tlsvnc_handshake { + my ($vmode, $db) = @_; + + print STDERR "PPROXY: Doing TLSVNC Handshake\n"; + + my $psec = pack("C", $rfbSecTypeTlsVnc); + syswrite($sock, $psec, 1); + + append_handshake("done\n"); +} + +sub vencrypt_handshake { + + my ($vmode, $db) = @_; + + print STDERR "PPROXY: Doing VeNCrypt Handshake\n"; + + my $psec = pack("C", $rfbSecTypeVencrypt); + syswrite($sock, $psec, 1); + + my $vmajor; + my $vminor; + sysread($sock, $vmajor, 1); + sysread($sock, $vminor, 1); + + vdie if $vmajor eq "" || $vminor eq ""; + + $vmajor = unpack("C", $vmajor); + $vminor = unpack("C", $vminor); + print STDERR "$vmajor.$vminor\n" if $db; + + vdie if $vmajor ne 0; + vdie if $vminor < 2; + + $vmajor = pack("C", 0); + $vminor = pack("C", 2); + append_handshake("subversion=0.2\n"); + + syswrite($sock, $vmajor, 1); + syswrite($sock, $vminor, 1); + + my $result; + sysread($sock, $result, 1); + + vdie if $result eq ""; + $result = unpack("C", $result); + print STDERR "result=$result\n" if $db; + + vdie if $result ne 0; + + my $nsubtypes; + sysread($sock, $nsubtypes, 1); + + vdie if $nsubtypes eq ""; + $nsubtypes = unpack("C", $nsubtypes); + print STDERR "nsubtypes=$nsubtypes\n" if $db; + + my %subtypes; + + for (my $i = 0; $i < $nsubtypes; $i++) { + my $subtype = ""; + sysread($sock, $subtype, 4); + vdie if length($subtype) != 4; + + # XXX fix 64bit. + $subtype = unpack("N", $subtype); + print STDERR "subtype: $subtype\n" if $db; + $subtypes{$subtype} = 1; + append_handshake("sst$i=$subtype\n"); + } + + my $subtype = 0; + if (exists $subtypes{$rfbVencryptX509None}) { + $subtype = $rfbVencryptX509None; + print STDERR "selected rfbVencryptX509None\n" if $db; + } elsif (exists $subtypes{$rfbVencryptX509Vnc}) { + $subtype = $rfbVencryptX509Vnc; + print STDERR "selected rfbVencryptX509Vnc\n" if $db; + } elsif (exists $subtypes{$rfbVencryptX509Plain}) { + $subtype = $rfbVencryptX509Plain; + print STDERR "selected rfbVencryptX509Plain\n" if $db; + } elsif (exists $subtypes{$rfbVencryptTlsNone}) { + $subtype = $rfbVencryptTlsNone; + print STDERR "selected rfbVencryptTlsNone\n" if $db; + } elsif (exists $subtypes{$rfbVencryptTlsVnc}) { + $subtype = $rfbVencryptTlsVnc; + print STDERR "selected rfbVencryptTlsVnc\n" if $db; + } elsif (exists $subtypes{$rfbVencryptTlsPlain}) { + $subtype = $rfbVencryptTlsPlain; + print STDERR "selected rfbVencryptTlsPlain\n" if $db; + } + append_handshake("subtype=$subtype\n"); + + my $pst = pack("N", $subtype); + syswrite($sock, $pst, 4); + + vdie if $subtype == 0; + + my $ok; + sysread($sock, $ok, 1); + $ok = unpack("C", $ok); + print STDERR "ok=$ok\n" if $db; + + append_handshake("done\n"); + + vdie if $ok == 0; +} + +sub vencrypt_dialog { + my $vmode = shift; + my $db = 0; + + $db = 1 if exists $ENV{SS_DEBUG}; + + append_handshake("mode=$vmode\n"); + + my $server_rfb = ""; + syswrite($sock, $rep, 250); + for (my $i = 0; $i < 12; $i++) { + my $c; + sysread($sock, $c, 1); + $server_rfb .= $c; + print STDERR $c; + } + print STDERR "server_rfb: $server_rfb\n" if $db; + append_handshake("server=$server_rfb"); + + my $minor = ""; + if ($server_rfb =~ /^RFB 003\.(\d+)/) { + $minor = $1; + } else { + vdie; + } + my $viewer_rfb = "RFB 003.008\n"; + if ($minor < 7) { + vdie; + } elsif ($minor == 7) { + $viewer_rfb = "RFB 003.007\n"; + } + syswrite($sock, $viewer_rfb, 12); + append_handshake("viewer=$viewer_rfb"); + + my $nsec; + + sysread($sock, $nsec, 1); + vdie if $nsec eq ""; + + $nsec = unpack("C", $nsec); + + print STDERR "nsec: $nsec\n" if $db; + vdie if $nsec eq 0 || $nsec > 100; + + my %sectypes = (); + + for (my $i = 0; $i < $nsec; $i++) { + my $sec; + sysread($sock, $sec, 1); + vdie if $sec eq ""; + $sec = unpack("C", $sec); + print STDERR "sec: $sec\n" if $db; + $sectypes{$sec} = 1; + } + + if (exists $sectypes{$rfbSecTypeVencrypt}) { + print STDERR "found rfbSecTypeVencrypt\n" if $db; + append_handshake("sectype=$rfbSecTypeVencrypt\n"); + vencrypt_handshake($vmode, $db); + } elsif (exists $sectypes{$rfbSecTypeTlsVnc}) { + print STDERR "found rfbSecTypeTlsVnc\n" if $db; + append_handshake("sectype=$rfbSecTypeTlsVnc\n"); + tlsvnc_handshake($vmode, $db); + } else { + print STDERR "No supported sec-type found\n" if $db; + vdie; + } +} + sub xfer { my($in, $out) = @_; $RIN = $WIN = $EIN = ""; @@ -1102,8 +1350,8 @@ if [ "X$use_ssh" = "X1" ]; then if echo "$proxy" | egrep '(http|https|socks|socks4|socks5)://' > /dev/null; then # Handle Web or SOCKS proxy(ies) for the initial connect. -Kecho host=$host -Kecho port=$port + Kecho host=$host + Kecho port=$port pproxy="" sproxy1="" sproxy_rest="" @@ -1124,9 +1372,10 @@ Kecho port=$port done pproxy=`echo "$pproxy" | sed -e 's/^,,*//' -e 's/,,*/,/g'` sproxy_rest=`echo "$sproxy_rest" | sed -e 's/^,,*//' -e 's/,,*/,/g'` -Kecho pproxy=$pproxy -Kecho sproxy1=$sproxy1 -Kecho sproxy_rest=$sproxy_rest + + Kecho pproxy=$pproxy + Kecho sproxy1=$sproxy1 + Kecho sproxy_rest=$sproxy_rest sproxy1_host="" sproxy1_port="" @@ -1162,9 +1411,9 @@ Kecho sproxy_rest=$sproxy_rest fi fi -Kecho sproxy1_host=$sproxy1_host -Kecho sproxy1_port=$sproxy1_port -Kecho sproxy1_user=$sproxy1_user + Kecho sproxy1_host=$sproxy1_host + Kecho sproxy1_port=$sproxy1_port + Kecho sproxy1_user=$sproxy1_user ptmp="/tmp/ss_vncviewer_ssh${RANDOM}.$$.pl" ptmp=`mytmp "$ptmp"` @@ -1202,7 +1451,7 @@ Kecho sproxy1_user=$sproxy1_user if [ "X$sproxy_rest" != "X" ]; then proxy="$proxy,$sproxy_rest" fi -Kecho proxy=$proxy + Kecho proxy=$proxy fi if echo "$proxy" | grep "," > /dev/null; then @@ -1548,13 +1797,26 @@ if [ "X$showcert" = "X1" ]; then if [ "X$proxy" != "X" ]; then PPROXY_LISTEN=$use export PPROXY_LISTEN - $ptmp 2>/dev/null & + if [ "X$SS_DEBUG" != "X" ]; then + $ptmp & + else + $ptmp 2>/dev/null & + fi sleep 1 host="localhost" port="$use" fi - openssl s_client -connect $host:$port 2>&1 < /dev/null - exit $? + cipher_args="" + if [ "X$ciphers" != "X" ]; then + cipher_args=`echo "$ciphers" | sed -e 's/ciphers=/-cipher /'` + fi + #echo "openssl s_client $cipher_args -connect $host:$port" + openssl s_client $cipher_args -prexit -connect $host:$port 2>&1 < /dev/null + rc=$? + if [ "X$SSVNC_PREDIGESTED_HANDSHAKE" != "X" ]; then + rm -f $SSVNC_PREDIGESTED_HANDSHAKE + fi + exit $rc fi if [ "X$direct_connect" != "X" ]; then @@ -1781,6 +2043,7 @@ foreground = yes pid = client = yes debug = 6 +$ciphers $STUNNEL_EXTRA_OPTS $STUNNEL_EXTRA_OPTS_USER $verify @@ -1816,6 +2079,7 @@ foreground = yes pid = client = no debug = 6 +$ciphers $STUNNEL_EXTRA_OPTS $STUNNEL_EXTRA_OPTS_USER $verify |