--- /dev/null
+#!/bin/sh
+#
+# ss_vncviewer: wrapper for vncviewer to use an stunnel SSL tunnel
+# or an SSH tunnel.
+#
+# Copyright (c) 2006-2008 by Karl J. Runge <runge@karlrunge.com>
+#
+# 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)
+# installed) Note: stunnel is usually installed in an "sbin" subdirectory.
+#
+# You should have "x11vnc -ssl ..." or "x11vnc -stunnel ..."
+# already running as the VNC server on the remote machine.
+# (or use stunnel on the server side for any other VNC server)
+#
+#
+# Usage: ss_vncviewer [cert-args] host:display <vncviewer-args>
+#
+# e.g.: ss_vncviewer snoopy:0
+# ss_vncviewer snoopy:0 -encodings "copyrect tight zrle hextile"
+#
+# [cert-args] can be:
+#
+# -verify /path/to/cacert.pem
+# -mycert /path/to/mycert.pem
+# -crl /path/to/my_crl.pem (or directory)
+# -proxy host:port
+#
+# -verify specifies a CA cert PEM file (or a self-signed one) for
+# authenticating the VNC server.
+#
+# -mycert specifies this client's cert+key PEM file for the VNC server to
+# authenticate this client.
+#
+# -proxy try host:port as a Web proxy to use the CONNECT method
+# to reach the VNC server (e.g. your firewall requires a proxy).
+#
+# For the "double proxy" case use -proxy host1:port1,host2:port2
+# (the first CONNECT is done through host1:port1 to host2:port2
+# and then a 2nd CONNECT to the destination VNC server.)
+#
+# Use socks://host:port, socks4://host:port, or socks5://host,port
+# to force usage of a SOCKS proxy. Also repeater://host:port and
+# sslrepeater://host:port.
+#
+# -showcert Only fetch the certificate using the 'openssl s_client'
+# command (openssl(1) must in installed).
+#
+# See http://www.karlrunge.com/x11vnc/#faq-ssl-ca for details on SSL
+# certificates with VNC.
+#
+# A few other args (not related to SSL and certs):
+#
+# -2nd Run the vncviewer a 2nd time if the first connections fails.
+#
+# -ssh Use ssh instead of stunnel SSL. ssh(1) must be installed and you
+# must be able to log into the remote machine via ssh.
+#
+# In this case "host:display" may be of the form "user@host:display"
+# where "user@host" is used for the ssh login (see ssh(1) manpage).
+#
+# If -proxy is supplied it can be of the forms: "gwhost" "gwhost:port"
+# "user@gwhost" or "user@gwhost:port". "gwhost" is an incoming ssh
+# gateway machine (the VNC server is not running there), an ssh -L
+# redir is used to "host" in "host:display" from "gwhost". Any "user@"
+# part must be in the -proxy string (not in "host:display").
+#
+# Under -proxy use "gwhost:port" if connecting to any ssh port
+# other than the default (22). (even for the non-gateway case,
+# -proxy must be used to specify a non-standard ssh port)
+#
+# A "double ssh" can be specified via a -proxy string with the two
+# hosts separated by a comma:
+#
+# [user1@]host1[:port1],[user2@]host2[:port2]
+#
+# in which case a ssh to host1 and thru it via a -L redir a 2nd
+# ssh is established to host2.
+#
+# Examples:
+#
+# ss_vncviewer -ssh bob@bobs-home.net:0
+# ss_vncviewer -ssh -sshcmd 'x11vnc -localhost' bob@bobs-home.net:0
+#
+# ss_vncviewer -ssh -proxy fred@mygate.com:2022 mymachine:0
+# ss_vncviewer -ssh -proxy bob@bobs-home.net:2222 localhost:0
+#
+# ss_vncviewer -ssh -proxy fred@gw-host,fred@peecee localhost:0
+#
+# -sshcmd cmd Run "cmd" via ssh instead of the default "sleep 15"
+# e.g. -sshcmd 'x11vnc -display :0 -localhost -rfbport 5900'
+#
+# -sshargs "args" pass "args" to the ssh process, e.g. -L/-R port redirs.
+#
+# -sshssl Tunnel the SSL connection thru a SSH connection. The tunnel as
+# under -ssh is set up and the SSL connection goes thru it. Use
+# this if you want to have and end-to-end SSL connection but must
+# go thru a SSH gateway host (e.g. not the vnc server). Or use
+# this if you need to tunnel additional services via -R and -L
+# (see -sshargs above).
+#
+# ss_vncviewer -sshssl -proxy fred@mygate.com mymachine:0
+#
+# -listen (or -reverse) set up a reverse connection.
+#
+# -alpha turn on cursor alphablending hack if you are using the
+# enhanced tightvnc vncviewer.
+#
+# -grab turn on XGrabServer hack if you are using the enhanced tightvnc
+# vncviewer (e.g. for fullscreen mode in some windowmanagers like
+# fvwm that do not otherwise work in fullscreen mode)
+#
+#
+# set VNCVIEWERCMD to whatever vncviewer command you want to use.
+#
+VNCIPCMD=${VNCVIEWERCMD:-vncip}
+VNCVIEWERCMD=${VNCVIEWERCMD:-vncviewer}
+#
+# Same for STUNNEL, e.g. set it to /path/to/stunnel or stunnel4, etc.
+#
+
+# turn on verbose debugging output
+if [ "X$SS_DEBUG" != "X" ]; then
+ set -xv
+fi
+
+PATH=$PATH:/usr/sbin:/usr/local/sbin:/dist/sbin; export PATH
+
+localhost="localhost"
+if uname | grep Darwin >/dev/null; then
+ localhost="127.0.0.1"
+fi
+
+# work out which stunnel to use (debian installs as stunnel4)
+if [ "X$STUNNEL" = "X" ]; then
+ check_stunnel=1
+ if [ "X$SSVNC_BASEDIRNAME" != "X" ]; then
+ if [ -x "$SSVNC_BASEDIRNAME/stunnel" ]; then
+ type stunnel > /dev/null 2>&1
+ if [ $? = 0 ]; then
+ # found ours
+ STUNNEL=stunnel
+ check_stunnel=0
+ fi
+ fi
+ fi
+ if [ "X$check_stunnel" = "X1" ]; then
+ type stunnel4 > /dev/null 2>&1
+ if [ $? = 0 ]; then
+ STUNNEL=stunnel4
+ else
+ STUNNEL=stunnel
+ fi
+ fi
+fi
+
+help() {
+ tail -n +2 "$0" | sed -e '/^$/ q'
+}
+
+secondtry=""
+gotalpha=""
+use_ssh=""
+use_sshssl=""
+direct_connect=""
+ssh_sleep=15
+
+# sleep longer in -listen mode:
+if echo "$*" | grep '.*-listen' > /dev/null; then
+ ssh_sleep=1800
+fi
+
+
+ssh_cmd=""
+# env override of ssh_cmd:
+if [ "X$SS_VNCVIEWER_SSH_CMD" != "X" ]; then
+ ssh_cmd="$SS_VNCVIEWER_SSH_CMD"
+fi
+
+ssh_args=""
+showcert=""
+reverse=""
+
+ciphers=""
+anondh="ALL:RC4+RSA:+SSLv2:@STRENGTH"
+anondh_set=""
+stunnel_debug="6"
+if [ "X$SS_DEBUG" != "X" -o "X$SSVNC_VENCRYPT_DEBUG" != "X" -o "X$SSVNC_STUNNEL_DEBUG" != "X" ]; then
+ stunnel_debug="7"
+fi
+
+if [ "X$1" = "X-viewerflavor" ]; then
+ # special case, try to guess which viewer:
+ #
+ if echo "$VNCVIEWERCMD" | egrep -i '^(xmessage|sleep )' > /dev/null; then
+ echo "unknown"
+ exit 0
+ fi
+ if echo "$VNCVIEWERCMD" | grep -i chicken.of > /dev/null; then
+ echo "cotvnc"
+ exit 0
+ fi
+ if echo "$VNCVIEWERCMD" | grep -i ultra > /dev/null; then
+ echo "ultravnc"
+ exit 0
+ fi
+ # OK, run it for help output...
+ str=`$VNCVIEWERCMD -h 2>&1 | head -n 5`
+ if echo "$str" | grep -i 'TightVNC.viewer' > /dev/null; then
+ 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
+ echo "realvnc3"
+ else
+ echo "unknown"
+ fi
+ exit 0
+fi
+if [ "X$1" = "X-viewerhelp" ]; then
+ $VNCVIEWERCMD -h 2>&1
+ exit 0
+fi
+
+# grab our cmdline options:
+while [ "X$1" != "X" ]
+do
+ case $1 in
+ "-verify") shift; verify="$1"
+ ;;
+ "-mycert") shift; mycert="$1"
+ ;;
+ "-crl") shift; crl="$1"
+ ;;
+ "-proxy") shift; proxy="$1"
+ ;;
+ "-ssh") use_ssh=1
+ ;;
+ "-sshssl") use_ssh=1
+ use_sshssl=1
+ ;;
+ "-sshcmd") shift; ssh_cmd="$1"
+ ;;
+ "-sshargs") shift; ssh_args="$1"
+ ;;
+ "-anondh") ciphers="ciphers=$anondh"
+ anondh_set=1
+ ;;
+ "-ciphers") shift; ciphers="ciphers=$1"
+ ;;
+ "-alpha") gotalpha=1
+ ;;
+ "-showcert") showcert=1
+ ;;
+ "-listen") reverse=1
+ ;;
+ "-reverse") reverse=1
+ ;;
+ "-2nd") secondtry=1
+ ;;
+ "-grab") VNCVIEWER_GRAB_SERVER=1; export VNCVIEWER_GRAB_SERVER
+ ;;
+ "-x11cursor") VNCVIEWER_X11CURSOR=1; export VNCVIEWER_X11CURSOR
+ ;;
+ "-rawlocal") VNCVIEWER_RAWLOCAL=1; export VNCVIEWER_RAWLOCAL
+ ;;
+ "-scale") shift; SSVNC_SCALE="$1"; export SSVNC_SCALE
+ ;;
+ "-onelisten") SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE
+ ;;
+ "-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
+ ;;
+ "-nobell") VNCVIEWER_NOBELL=1; export VNCVIEWER_NOBELL
+ ;;
+ "-popupfix") VNCVIEWER_POPUP_FIX=1; export VNCVIEWER_POPUP_FIX
+ ;;
+ "-realvnc4") VNCVIEWER_IS_REALVNC4=1; export VNCVIEWER_IS_REALVNC4
+ ;;
+ "-h"*) help; exit 0
+ ;;
+ "--h"*) help; exit 0
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+done
+
+# maxconn is something we added to stunnel, this disables it:
+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/'`
+elif [ "X$reverse" != "X" ]; then
+ STUNNEL_EXTRA_OPTS=`echo "$STUNNEL_EXTRA_OPTS" | sed -e 's/maxconn/#maxconn/'`
+else
+ # new way (our patches). other than the above, we set these:
+ if [ "X$SKIP_STUNNEL_ONCE" = "X" ]; then
+ STUNNEL_ONCE=1; export STUNNEL_ONCE
+ fi
+ if [ "X$SKIP_STUNNEL_MAX_CLIENTS" = "X" ]; then
+ STUNNEL_MAX_CLIENTS=1; export STUNNEL_MAX_CLIENTS
+ fi
+fi
+# always set this one:
+if [ "X$SKIP_STUNNEL_NO_SYSLOG" = "X" ]; then
+ STUNNEL_NO_SYSLOG=1; export STUNNEL_NO_SYSLOG
+fi
+
+# this is the -t ssh option (gives better keyboard response thru SSH tunnel)
+targ="-t"
+if [ "X$SS_VNCVIEWER_NO_T" != "X" ]; then
+ targ=""
+fi
+
+# set the alpha blending env. hack:
+if [ "X$gotalpha" = "X1" ]; then
+ VNCVIEWER_ALPHABLEND=1
+ export VNCVIEWER_ALPHABLEND
+else
+ NO_ALPHABLEND=1
+ export NO_ALPHABLEND
+fi
+
+if [ "X$reverse" != "X" ]; then
+ ssh_sleep=1800
+ if [ "X$proxy" != "X" ]; then
+ # check proxy usage under reverse connection:
+ if [ "X$use_ssh" = "X" -a "X$use_sshssl" = "X" ]; then
+ echo ""
+ if echo "$proxy" | egrep -i "(repeater|vencrypt)://" > /dev/null; then
+ :
+ else
+ echo "*Warning*: SSL -listen and a Web proxy does not make sense."
+ sleep 2
+ fi
+ elif echo "$proxy" | grep "," > /dev/null; then
+ :
+ else
+ echo ""
+ echo "*Warning*: -listen and a single proxy/gateway does not make sense."
+ sleep 2
+ fi
+ SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE
+ fi
+fi
+if [ "X$ssh_cmd" = "X" ]; then
+ # if no remote ssh cmd, sleep a bit:
+ ssh_cmd="sleep $ssh_sleep"
+fi
+
+# this should be a host:display:
+#
+orig="$1"
+shift
+
+dL="-L"
+if uname -sr | egrep 'SunOS 5\.[5-8]' > /dev/null; then
+ dL="-h"
+fi
+
+rchk() {
+ # a kludge to set $RANDOM if we are not bash:
+ if [ "X$BASH_VERSION" = "X" ]; then
+ RANDOM=`date +%S``sh -c 'echo $$'``ps -elf 2>&1 | sum 2>&1 | awk '{print $1}'`
+ fi
+}
+rchk
+
+# 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://,,'`
+ pstr1=`echo "$pstr" | sed -e 's/+.*$//'`
+ pstr2=`echo "$pstr" | sed -e 's/^[^+]*+//'`
+ SSVNC_REPEATER="SCIII=$pstr2"; export SSVNC_REPEATER
+ orig=$pstr1
+ echo
+ 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:
+if [ "X$use_ssh" = "X1" -a "X$use_sshssl" = "X" ]; then
+ if [ "X$mycert" != "X" -o "X$verify" != "X" ]; then
+ echo "-mycert and -verify cannot be used in -ssh mode"
+ exit 1
+ fi
+fi
+
+# direct mode Vnc:// means show no warnings.
+# direct mode vnc:// will show warnings.
+if echo "$orig" | grep '^V[Nn][Cc]://' > /dev/null; then
+ SSVNC_NO_ENC_WARN=1
+ export SSVNC_NO_ENC_WARN
+ orig=`echo "$orig" | sed -e 's/^...:/vnc:/'`
+fi
+
+# interprest the pseudo URL proto:// strings:
+if echo "$orig" | grep '^vnc://' > /dev/null; then
+ orig=`echo "$orig" | sed -e 's,vnc://,,'`
+ verify=""
+ mycert=""
+ crl=""
+ use_ssh=""
+ use_sshssl=""
+ direct_connect=1
+elif echo "$orig" | grep '^vncs://' > /dev/null; then
+ orig=`echo "$orig" | sed -e 's,vncs://,,'`
+elif echo "$orig" | grep '^vncssl://' > /dev/null; then
+ orig=`echo "$orig" | sed -e 's,vncssl://,,'`
+elif echo "$orig" | grep '^vnc+ssl://' > /dev/null; then
+ orig=`echo "$orig" | sed -e 's,vnc.ssl://,,'`
+elif echo "$orig" | grep '^vncssh://' > /dev/null; then
+ orig=`echo "$orig" | sed -e 's,vncssh://,,'`
+ use_ssh=1
+elif echo "$orig" | grep '^vnc+ssh://' > /dev/null; then
+ orig=`echo "$orig" | sed -e 's,vnc.ssh://,,'`
+ use_ssh=1
+fi
+
+if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then
+ verify=""
+ mycert=""
+ crl=""
+ use_ssh=""
+ use_sshssl=""
+ direct_connect=1
+ if echo "$SSVNC_ULTRA_DSM" | grep 'noultra:' > /dev/null; then
+ SSVNC_NO_ULTRA_DSM=1; export SSVNC_NO_ULTRA_DSM
+ 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
+ use_ssh=1
+ rsh=1
+ orig=`echo "$orig" | sed -e 's,rsh://,,'`
+elif echo "$orig" | grep '^rsh:' > /dev/null; then
+ use_ssh=1
+ rsh=1
+ orig=`echo "$orig" | sed -e 's,rsh:,,'`
+fi
+
+# play around with host:display port:
+if echo "$orig" | grep ':' > /dev/null; then
+ :
+else
+ # add or assume :0 if no ':'
+ if [ "X$reverse" = "X" ]; then
+ orig="$orig:0"
+ elif [ "X$orig" = "X" ]; then
+ orig=":0"
+ fi
+fi
+
+# extract host and disp number:
+host=`echo "$orig" | awk -F: '{print $1}'`
+disp=`echo "$orig" | awk -F: '{print $2}'`
+if [ "X$host" = "X" ]; then
+ host=$localhost
+fi
+if [ "X$disp" = "X" ]; then
+ port="" # probably -listen mode.
+elif [ $disp -lt 0 ]; then
+ # negative means use |n| without question:
+ port=`expr 0 - $disp`
+elif [ $disp -lt 200 ]; then
+ # less than 200 means 5900+n
+ if [ "X$reverse" = "X" ]; then
+ port=`expr $disp + 5900`
+ else
+ port=`expr $disp + 5500`
+ fi
+else
+ # otherwise use the number directly, e.g. 443, 2345
+ port=$disp
+fi
+
+# try to find an open listening port via netstat(1):
+inuse=""
+if uname | grep Linux > /dev/null; then
+ inuse=`netstat -ant | egrep 'LISTEN|WAIT|ESTABLISH|CLOSE' | awk '{print $4}' | sed 's/^.*://'`
+elif uname | grep SunOS > /dev/null; then
+ inuse=`netstat -an -f inet -P tcp | egrep 'LISTEN|WAIT|ESTABLISH|CLOSE' | awk '{print $1}' | sed 's/^.*\.//'`
+elif uname | egrep -i 'bsd|darwin' > /dev/null; then
+ inuse=`netstat -ant -f inet | egrep 'LISTEN|WAIT|ESTABLISH|CLOSE' | awk '{print $4}' | sed 's/^.*\.//'`
+# add others...
+fi
+
+# this is a crude attempt for unique ports tags, etc.
+date_sec=`date +%S`
+
+# these are special cases of no vnc, e.g. sleep or xmessage.
+# these are for using ssvnc as a general port redirector.
+if echo "$VNCVIEWERCMD" | grep '^sleep[ ][ ]*[0-9][0-9]*' > /dev/null; then
+ if [ "X$SS_VNCVIEWER_LISTEN_PORT" = "X" ]; then
+ p=`echo "$VNCVIEWERCMD" | awk '{print $3}'`
+ if [ "X$p" != "X" ]; then
+ SS_VNCVIEWER_LISTEN_PORT=$p
+ fi
+ fi
+ p2=`echo "$VNCVIEWERCMD" | awk '{print $2}'`
+ VNCVIEWERCMD="eval sleep $p2; echo Local "
+elif echo "$VNCVIEWERCMD" | grep '^xmessage[ ][ ]*[0-9][0-9]*' > /dev/null; then
+ if [ "X$SS_VNCVIEWER_LISTEN_PORT" = "X" ]; then
+ p=`echo "$VNCVIEWERCMD" | awk '{print $2}'`
+ SS_VNCVIEWER_LISTEN_PORT=$p
+ fi
+fi
+
+# utility to find a free port to listen on.
+findfree() {
+ try0=$1
+ try=$try0
+ use0=""
+
+ if [ "X$SS_VNCVIEWER_LISTEN_PORT" != "X" ]; then
+ echo "$SS_VNCVIEWER_LISTEN_PORT"
+ return
+ fi
+ if [ $try -ge 6000 ]; then
+ fmax=`expr $try + 1000`
+ else
+ fmax=6000
+ fi
+
+ while [ $try -lt $fmax ]
+ do
+ if [ "X$inuse" = "X" ]; then
+ break
+ fi
+ if echo "$inuse" | grep -w $try > /dev/null; then
+ :
+ else
+ use0=$try
+ break
+ fi
+ try=`expr $try + 1`
+ done
+ if [ "X$use0" = "X" ]; then
+ use0=`expr $date_sec + $try0`
+ fi
+
+ echo $use0
+}
+
+# utility for exiting; kills some helper processes,
+# removes files, etc.
+final() {
+ echo ""
+ if [ "X$tmp_cfg" != "X" ]; then
+ rm -f $tmp_cfg
+ fi
+ if [ "X$SS_VNCVIEWER_RM" != "X" ]; then
+ rm -f $SS_VNCVIEWER_RM 2>/dev/null
+ fi
+ if [ "X$tcert" != "X" ]; then
+ rm -f $tcert
+ fi
+ if [ "X$pssh" != "X" ]; then
+ echo "Terminating background ssh process"
+ echo kill -TERM "$pssh"
+ kill -TERM "$pssh" 2>/dev/null
+ sleep 1
+ kill -KILL "$pssh" 2>/dev/null
+ pssh=""
+ fi
+ if [ "X$stunnel_pid" != "X" ]; then
+ echo "Terminating background stunnel process"
+ echo kill -TERM "$stunnel_pid"
+ kill -TERM "$stunnel_pid" 2>/dev/null
+ sleep 1
+ kill -KILL "$stunnel_pid" 2>/dev/null
+ stunnel_pid=""
+ fi
+ if [ "X$dsm_pid" != "X" ]; then
+ echo "Terminating background ultravnc_dsm_helper process"
+ echo kill -TERM "$dsm_pid"
+ kill -TERM "$dsm_pid" 2>/dev/null
+ sleep 1
+ kill -KILL "$dsm_pid" 2>/dev/null
+ stunnel_pid=""
+ fi
+ if [ "X$tail_pid" != "X" ]; then
+ kill -TERM $tail_pid
+ fi
+}
+
+if [ "X$reverse" = "X" ]; then
+ # normal connections try 5930-5999:
+ if [ "X$showcert" = "X" ]; then
+ use=`findfree 5930`
+ else
+ # move away from normal place for (possibly many) -showcert
+ pstart=`date +%S`
+ pstart=`expr 6130 + $pstart + $pstart`
+ use=`findfree $pstart`
+ fi
+ if [ $use -ge 5900 ]; then
+ N=`expr $use - 5900`
+ else
+ N=$use
+ fi
+else
+ # reverse connections:
+ p2=`expr $port + 30`
+ use=`findfree $p2`
+ if [ $use -ge 5500 ]; then
+ N=`expr $use - 5500`
+ else
+ N=$use
+ fi
+fi
+
+# this is for my special use of ss_vncip -> vncip viewer.
+if echo "$0" | grep vncip > /dev/null; then
+ VNCVIEWERCMD="$VNCIPCMD"
+fi
+
+# trick for the undocumented rsh://host:port method.
+rsh_setup() {
+ if echo "$ssh_host" | grep '@' > /dev/null; then
+ ul=`echo "$ssh_host" | awk -F@ '{print $1}'`
+ ul="-l $ul"
+ ssh_host=`echo "$ssh_host" | awk -F@ '{print $2}'`
+ else
+ ul=""
+ fi
+ ssh_cmd=`echo "$ssh_cmd" | sed -e 's/ -localhost/ /g'`
+}
+
+# trick for the undocumented rsh://host:port method.
+rsh_viewer() {
+ trap "final" 0 2 15
+ if [ "X$PORT" = "X" ]; then
+ exit 1
+ elif [ $PORT -ge 5900 ]; then
+ vdpy=`expr $PORT - 5900`
+ else
+ vdpy=":$PORT"
+ fi
+ stty sane
+ echo "$VNCVIEWERCMD" "$@" $ssh_host:$vdpy
+ echo ""
+ $VNCVIEWERCMD "$@" $ssh_host:$vdpy
+ if [ $? != 0 ]; then
+ sleep 2
+ $VNCVIEWERCMD "$@" $ssh_host:$vdpy
+ fi
+}
+
+# this is the PPROXY tool. used only here for now...
+pcode() {
+ tf=$1
+ PPROXY_PROXY=$proxy; export PPROXY_PROXY
+ PPROXY_DEST="$host:$port"; export PPROXY_DEST
+ cod='#!/usr/bin/perl
+
+# A hack to glue stunnel to a Web proxy or SOCKS for client connections.
+
+use IO::Socket::INET;
+
+if (exists $ENV{PPROXY_SLEEP}) {
+ print STDERR "PPROXY_PID: $$\n";
+ sleep $ENV{PPROXY_SLEEP};
+}
+
+foreach my $var (qw(PPROXY_PROXY PPROXY_SOCKS PPROXY_DEST PPROXY_LISTEN
+ PPROXY_REVERSE PPROXY_REPEATER PPROXY_REMOVE PPROXY_KILLPID PPROXY_SLEEP)) {
+ if (0 || $ENV{SS_DEBUG} || $ENV{SSVNC_VENCRYPT_DEBUG}) {
+ print STDERR "$var: $ENV{$var}\n";
+ }
+}
+
+if ($ENV{PPROXY_SOCKS} ne "" && $ENV{PPROXY_PROXY} !~ m,^socks5?://,i) {
+ if ($ENV{PPROXY_SOCKS} eq "5") {
+ $ENV{PPROXY_PROXY} = "socks5://$ENV{PPROXY_PROXY}";
+ } else {
+ $ENV{PPROXY_PROXY} = "socks://$ENV{PPROXY_PROXY}";
+ }
+}
+
+my $rfbSecTypeAnonTls = 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) = ("", "", "");
+
+($first, $mode_1st) = url_parse($first);
+
+my ($proxy_host, $proxy_port) = split(/:/, $first);
+my $connect = $ENV{PPROXY_DEST};
+
+if ($second ne "") {
+ ($second, $mode_2nd) = url_parse($second);
+}
+
+if ($third ne "") {
+ ($third, $mode_3rd) = url_parse($third);
+}
+
+
+print STDERR "\n";
+print STDERR "PPROXY v0.2: a tool for Web proxies and SOCKS connections.\n";
+print STDERR "proxy_host: $proxy_host\n";
+print STDERR "proxy_port: $proxy_port\n";
+print STDERR "proxy_connect: $connect\n";
+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 "\n";
+if (1) {
+ print STDERR "pproxy 1st: $first\t- $mode_1st\n";
+ print STDERR "pproxy 2nd: $second\t- $mode_2nd\n";
+ print STDERR "pproxy 3rd: $third\t- $mode_3rd\n";
+ print STDERR "\n";
+}
+
+my $listen_handle = "";
+if ($ENV{PPROXY_REVERSE} ne "") {
+ my ($rhost, $rport) = split(/:/, $ENV{PPROXY_REVERSE});
+ $rport = 5900 unless $rport;
+ $listen_handle = IO::Socket::INET->new(
+ PeerAddr => $rhost,
+ PeerPort => $rport,
+ Proto => "tcp"
+ );
+ if (! $listen_handle) {
+ die "pproxy: $! -- PPROXY_REVERSE\n";
+ }
+ print STDERR "PPROXY_REVERSE: connected to $rhost $rport\n";
+
+} elsif ($ENV{PPROXY_LISTEN} ne "") {
+ my $listen_sock = "";
+ if ($ENV{PPROXY_LISTEN} =~ /^INADDR_ANY:(.*)/) {
+ my $p = $1;
+ $listen_sock = IO::Socket::INET->new(
+ Listen => 2,
+ LocalPort => $p,
+ Proto => "tcp"
+ );
+ } else {
+ $listen_sock = IO::Socket::INET->new(
+ Listen => 2,
+ LocalAddr => "127.0.0.1",
+ LocalPort => $ENV{PPROXY_LISTEN},
+ Proto => "tcp"
+ );
+ }
+ if (! $listen_sock) {
+ die "pproxy: $! -- PPROXY_LISTEN\n";
+ }
+ my $ip;
+ ($listen_handle, $ip) = $listen_sock->accept();
+ if (! $listen_handle) {
+ die "pproxy: $!\n";
+ }
+ close $listen_sock;
+}
+
+my $sock = IO::Socket::INET->new(
+ PeerAddr => $proxy_host,
+ PeerPort => $proxy_port,
+ Proto => "tcp"
+);
+
+if (! $sock) {
+ my $err = $!;
+ unlink($0) if $ENV{PPROXY_REMOVE};
+ die "pproxy: $err\n";
+}
+
+unlink($0) if $ENV{PPROXY_REMOVE};
+
+if ($ENV{PPROXY_PROXY} =~ /^vencrypt:/ && $ENV{PPROXY_LISTEN} =~ /^INADDR_ANY:/) {
+ print STDERR "PPROXY: vencrypt+reverse: swapping listen socket with connect socket.\n";
+ my $tmp_swap = $sock;
+ $sock = $listen_handle;
+ $listen_handle = $tmp_swap;
+}
+
+$cur_proxy = $first;
+setmode($mode_1st);
+
+if ($second ne "") {
+ connection($second, 1);
+
+ setmode($mode_2nd);
+ $cur_proxy = $second;
+
+ if ($third ne "") {
+ connection($third, 2);
+ setmode($mode_3rd);
+ $cur_proxy = $third;
+ connection($connect, 3);
+ } else {
+ connection($connect, 2);
+ }
+} else {
+ connection($connect, 1);
+}
+
+$parent = $$;
+$child = fork;
+if (! defined $child) {
+ if ($ENV{PPROXY_KILLPID}) {
+ foreach my $p (split(/,/, $ENV{PPROXY_KILLPID})) {
+ if ($p =~ /^(\+|-)/) {
+ $p = $parent + $p;
+ }
+ kill "TERM", $p;
+ }
+ }
+ exit 1;
+}
+
+if ($child) {
+ print STDERR "pproxy parent\[$$] STDIN -> socket\n";
+ if ($listen_handle) {
+ xfer($listen_handle, $sock);
+ } else {
+ xfer(STDIN, $sock);
+ }
+ select(undef, undef, undef, 0.25);
+ if (kill 0, $child) {
+ select(undef, undef, undef, 1.5);
+ print STDERR "pproxy\[$$]: kill TERM $child\n";
+ kill "TERM", $child;
+ }
+} else {
+ print STDERR "pproxy child \[$$] socket -> STDOUT\n";
+ if ($listen_handle) {
+ xfer($sock, $listen_handle);
+ } else {
+ xfer($sock, STDOUT);
+ }
+ select(undef, undef, undef, 0.25);
+ if (kill 0, $parent) {
+ select(undef, undef, undef, 1.5);
+ print STDERR "pproxy\[$$]: kill TERM $parent\n";
+ kill "TERM", $parent;
+ }
+}
+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;
+ }
+ }
+}
+exit;
+
+sub url_parse {
+ my $hostport = shift;
+ my $mode = "http";
+ if ($hostport =~ m,^socks4?://(\S*)$,i) {
+ $mode = "socks4";
+ $hostport = $1;
+ } elsif ($hostport =~ m,^socks5://(\S*)$,i) {
+ $mode = "socks5";
+ $hostport = $1;
+ } elsif ($hostport =~ m,^https?://(\S*)$,i) {
+ $mode = "http";
+ $hostport = $1;
+ } elsif ($hostport =~ m,^repeater://(\S*)\+(\S*)$,i) {
+ # ultravnc repeater proxy.
+ $hostport = $1;
+ $mode = "repeater:$2";
+ 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);
+}
+
+sub setmode {
+ my $mode = shift;
+ $ENV{PPROXY_REPEATER} = "";
+ $ENV{PPROXY_VENCRYPT} = "";
+ if ($mode =~ /^socks/) {
+ if ($mode =~ /^socks5/) {
+ $ENV{PPROXY_SOCKS} = 5;
+ } else {
+ $ENV{PPROXY_SOCKS} = 1;
+ }
+ } elsif ($mode =~ /^repeater:(.*)/) {
+ $ENV{PPROXY_REPEATER} = $1;
+ $ENV{PPROXY_SOCKS} = "";
+ } elsif ($mode =~ /^vencrypt:(.*)/) {
+ $ENV{PPROXY_VENCRYPT} = $1;
+ $ENV{PPROXY_SOCKS} = "";
+ } else {
+ $ENV{PPROXY_SOCKS} = "";
+ }
+}
+
+sub connection {
+ my ($CONNECT, $w) = @_;
+
+ my $con = "";
+ my $msg = "";
+
+ if ($ENV{PPROXY_SOCKS} eq "5") {
+ # SOCKS5
+ my ($h, $p) = split(/:/, $CONNECT);
+ $con .= pack("C", 0x05);
+ $con .= pack("C", 0x01);
+ $con .= pack("C", 0x00);
+
+ $msg = "SOCKS5 via $cur_proxy to $h:$p\n\n";
+ print STDERR "proxy_request$w: $msg";
+
+ syswrite($sock, $con, length($con));
+
+ my ($n1, $n2, $n3, $n4, $n5, $n6);
+ my ($r1, $r2, $r3, $r4, $r5, $r6);
+ my ($s1, $s2, $s3, $s4, $s5, $s6);
+
+ $n1 = sysread($sock, $r1, 1);
+ $n2 = sysread($sock, $r2, 1);
+
+ $s1 = unpack("C", $r1);
+ $s2 = unpack("C", $r2);
+ if ($s1 != 0x05 || $s2 != 0x00) {
+ print STDERR "SOCKS5 fail s1=$s1 s2=$s2 n1=$n1 n2=$n2\n";
+ close $sock;
+ exit(1);
+ }
+
+ $con = "";
+ $con .= pack("C", 0x05);
+ $con .= pack("C", 0x01);
+ $con .= pack("C", 0x00);
+ $con .= pack("C", 0x03);
+ $con .= pack("C", length($h));
+ $con .= $h;
+ $con .= pack("C", $p >> 8);
+ $con .= pack("C", $p & 0xff);
+
+ syswrite($sock, $con, length($con));
+
+ $n1 = sysread($sock, $r1, 1);
+ $n2 = sysread($sock, $r2, 1);
+ $n3 = sysread($sock, $r3, 1);
+ $n4 = sysread($sock, $r4, 1);
+ $s1 = unpack("C", $r1);
+ $s2 = unpack("C", $r2);
+ $s3 = unpack("C", $r3);
+ $s4 = unpack("C", $r4);
+
+ if ($s4 == 0x1) {
+ sysread($sock, $r5, 4 + 2);
+ } elsif ($s4 == 0x3) {
+ sysread($sock, $r5, 1);
+ $s5 = unpack("C", $r5);
+ sysread($sock, $r6, $s5 + 2);
+ } elsif ($s4 == 0x4) {
+ sysread($sock, $r5, 16 + 2);
+ }
+
+ if ($s1 != 0x5 || $s2 != 0x0 || $s3 != 0x0) {
+ print STDERR "SOCKS5 failed: s1=$s1 s2=$s2 s3=$s3 s4=$s4 n1=$n1 n2=$n2 n3=$n3 n4=$n4\n";
+ close $sock;
+ exit(1);
+ }
+
+ } elsif ($ENV{PPROXY_SOCKS} ne "") {
+ # SOCKS4 SOCKS4a
+ my ($h, $p) = split(/:/, $CONNECT);
+ $con .= pack("C", 0x04);
+ $con .= pack("C", 0x01);
+ $con .= pack("n", $p);
+
+ my $SOCKS_4a = 0;
+ if ($h eq "localhost" || $h eq "127.0.0.1") {
+ $con .= pack("C", 127);
+ $con .= pack("C", 0);
+ $con .= pack("C", 0);
+ $con .= pack("C", 1);
+ } elsif ($h =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) {
+ $con .= pack("C", $1);
+ $con .= pack("C", $2);
+ $con .= pack("C", $3);
+ $con .= pack("C", $4);
+ } else {
+ $con .= pack("C", 0);
+ $con .= pack("C", 0);
+ $con .= pack("C", 0);
+ $con .= pack("C", 3);
+ $SOCKS_4a = 1;
+ }
+
+ $con .= "nobody";
+ $con .= pack("C", 0);
+
+ $msg = "SOCKS4 via $cur_proxy to $h:$p\n\n";
+ if ($SOCKS_4a) {
+ $con .= $h;
+ $con .= pack("C", 0);
+ $msg =~ s/SOCKS4/SOCKS4a/;
+ }
+ print STDERR "proxy_request$w: $msg";
+ syswrite($sock, $con, length($con));
+
+ my $ok = 1;
+ for (my $i = 0; $i < 8; $i++) {
+ my $c;
+ sysread($sock, $c, 1);
+ my $s = unpack("C", $c);
+ if ($i == 0) {
+ $ok = 0 if $s != 0x0;
+ } elsif ($i == 1) {
+ $ok = 0 if $s != 0x5a;
+ }
+ }
+ if (! $ok) {
+ print STDERR "SOCKS4 failed.\n";
+ close $sock;
+ exit(1);
+ }
+ } elsif ($ENV{PPROXY_REPEATER} ne "") {
+ my $rep = $ENV{PPROXY_REPEATER};
+ print STDERR "repeater: $rep\n";
+ $rep .= pack("x") x 250;
+ syswrite($sock, $rep, 250);
+
+ my $ok = 1;
+ for (my $i = 0; $i < 12; $i++) {
+ my $c;
+ sysread($sock, $c, 1);
+ print STDERR $c;
+ }
+ } elsif ($ENV{PPROXY_VENCRYPT} ne "") {
+ my $vencrypt = $ENV{PPROXY_VENCRYPT};
+ vencrypt_dialog($vencrypt);
+
+ } else {
+ # Web Proxy:
+ $con = "CONNECT $CONNECT HTTP/1.1\r\n";
+ $con .= "Host: $CONNECT\r\n";
+ $con .= "Connection: close\r\n\r\n";
+ $msg = $con;
+
+ print STDERR "proxy_request$w: via $cur_proxy:\n$msg";
+ syswrite($sock, $con, length($con));
+
+ my $rep = "";
+ my $n = 0;
+ while ($rep !~ /\r\n\r\n/ && $n < 30000) {
+ my $c;
+ sysread($sock, $c, 1);
+ print STDERR $c;
+ $rep .= $c;
+ $n++;
+ }
+ if ($rep !~ m,HTTP/.* 200,) {
+ print STDERR "HTTP CONNECT failed.\n";
+ close $sock;
+ exit(1);
+ }
+ }
+}
+
+sub vdie {
+ append_handshake("done\n");
+ close $sock;
+ exit(1);
+}
+
+sub anontls_handshake {
+ my ($vmode, $db) = @_;
+
+ print STDERR "PPROXY: Doing ANONTLS Handshake\n";
+
+ my $psec = pack("C", $rfbSecTypeAnonTls);
+ 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);
+
+ if (exists $ENV{SSVNC_TEST_SEC_TYPE}) {
+ my $fake = $ENV{SSVNC_TEST_SEC_TYPE};
+ print STDERR "PPROXY: sending sec-type: $fake\n";
+ $psec = pack("C", $fake);
+ }
+
+ 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 "server vencrypt version $vmajor.$vminor\n" if $db;
+
+ if (exists $ENV{SSVNC_TEST_SEC_TYPE}) {
+ print STDERR "PPROXY: continuing on in test mode.\n";
+ } else {
+ 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);
+ print STDERR "result empty\n" if $db && $result eq "";
+
+ 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;
+ }
+
+ if (exists $ENV{SSVNC_TEST_SEC_SUBTYPE}) {
+ my $fake = $ENV{SSVNC_TEST_SEC_SUBTYPE};
+ print STDERR "PPROXY: sending sec-subtype: $fake\n";
+ $subtype = $fake;
+ }
+
+ append_handshake("subtype=$subtype\n");
+
+ my $pst = pack("N", $subtype);
+ syswrite($sock, $pst, 4);
+
+ if (exists $ENV{SSVNC_TEST_SEC_SUBTYPE}) {
+ print STDERR "PPROXY: continuing on in test mode.\n";
+ } else {
+ 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};
+ $db = 1 if exists $ENV{SSVNC_VENCRYPT_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{$rfbSecTypeAnonTls}) {
+ print STDERR "found rfbSecTypeAnonTls\n" if $db;
+ append_handshake("sectype=$rfbSecTypeAnonTls\n");
+ anontls_handshake($vmode, $db);
+ } else {
+ print STDERR "No supported sec-type found\n" if $db;
+ vdie;
+ }
+}
+
+sub xfer {
+ 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($in);
+ close($out);
+}
+'
+ # '
+ # xpg_echo will expand \n \r, etc.
+ # try to unset and then test for it.
+ if type shopt > /dev/null 2>&1; then
+ shopt -u xpg_echo >/dev/null 2>&1
+ fi
+ v='print STDOUT "abc\n";'
+ echo "$v" > $tf
+ chmod 700 $tf
+
+ lc=`wc -l $tf | awk '{print $1}'`
+ if [ "X$lc" = "X1" ]; then
+ echo "$cod" > $tf
+ else
+ printf "%s" "$cod" > $tf
+ echo "" >> $tf
+ fi
+ # prime perl
+ perl -e 'use IO::Socket::INET; select(undef, undef, undef, 0.01)' >/dev/null 2>&1
+}
+
+# make_tcert is no longer invoked via the ssvnc gui (Listen mode).
+# make_tcert is for testing only now via -mycert BUILTIN
+make_tcert() {
+ tcert="/tmp/ss_vnc_viewer_tcert${RANDOM}.$$"
+ tcert=`mytmp "$tcert"`
+ cat > $tcert <<END
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAvkfXxb0wcxgrjV2ziFikjII+ze8iKcTBt47L0GM/c21efelN
++zZpJUUXLu4zz8Ryq8Q+sQgfNy7uTOpN9bUUaOk1TnD7gaDQnQWiNHmqbW2kL+DS
+OKngJVPo9dETAS8hf7+D1e1DBZxjTc1a4RQqWJixwpYj99ixWzu8VC2m/xXsjvOs
+jp4+DLBB490nbkwvstmhmiWm1CmI5O5xOkgioVNQqHvQMdVKOSz9PpbjvZiRX1Uo
+qoMrk+2NOqwP90TB35yPASXb9zXKpO7DLhkube+yYGf+yk46aD707L07Eb7cosFP
+S84vNZ9gX7rQ0UOwm5rYA/oZTBskgaqhtIzkLwIDAQABAoIBAD4ot/sXt5kRn0Ca
+CIkU9AQWlC+v28grR2EQW9JiaZrqcoDNUzUqbCTJsi4ZkIFh2lf0TsqELbZYNW6Y
+6AjJM7al4E0UqYSKJTv2WCuuRxdiRs2BMwthqyBmjeanev7bB6V0ybt7u3Y8xU/o
+MrTuYnr4vrEjXPKdLirwk7AoDbKsRXHSIiHEIBOq1+dUQ32t36ukdnnza4wKDLZc
+PKHiCdCk/wOGhuDlxD6RspqUAlRnJ8/aEhrgWxadFXw1hRhRsf/v1shtB0T3DmTe
+Jchjwyiw9mryb9JZAcKxW+fUc4EVvj6VdQGqYInQJY5Yxm5JAlVQUJicuuJEvn6A
+rj5osQECgYEA552CaHpUiFlB4HGkjaH00kL+f0+gRF4PANCPk6X3UPDVYzKnzmuu
+yDvIdEETGFWBwoztUrOOKqVvPEQ+kBa2+DWWYaERZLtg2cI5byfDJxQ3ldzilS3J
+1S3WgCojqcsG/hlxoQJ1dZFanUy/QhUZ0B+wlC+Zp1Q8AyuGQvhHp68CgYEA0lBI
+eqq2GGCdJuNHMPFbi8Q0BnX55LW5C1hWjhuYiEkb3hOaIJuJrqvayBlhcQa2cGqp
+uP34e9UCfoeLgmoCQ0b4KpL2NGov/mL4i8bMgog4hcoYuIi3qxN18vVR14VKEh4U
+RLk0igAYPU+IK2QByaQlBo9OSaKkcfm7U1/pK4ECgYAxr6VpGk0GDvfF2Tsusv6d
+GIgV8ZP09qSLTTJvvxvF/lQYeqZq7sjI5aJD5i3de4JhpO/IXQJzfZfWOuGc8XKA
+3qYK/Y2IqXXGYRcHFGWV/Y1LFd55mCADHlk0l1WdOBOg8P5iRu/Br9PbiLpCx9oI
+vrOXpnp03eod1/luZmqguwKBgQCWFRSj9Q7ddpSvG6HCG3ro0qsNsUMTI1tZ7UBX
+SPogx4tLf1GN03D9ZUZLZVFUByZKMtPLX/Hi7K9K/A9ikaPrvsl6GEX6QYzeTGJx
+3Pw0amFrmDzr8ySewNR6/PXahxPEuhJcuI31rPufRRI3ZLah3rFNbRbBFX+klkJH
+zTnoAQKBgDbUK/aQFGduSy7WUT7LlM3UlGxJ2sA90TQh4JRQwzur0ACN5GdYZkqM
+YBts4sBJVwwJoxD9OpbvKu3uKCt41BSj0/KyoBzjT44S2io2tj1syujtlVUsyyBy
+/ca0A7WBB8lD1D7QMIhYUm2O9kYtSCLlUTHt5leqGaRG38DqlX36
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIDzDCCArQCCQDSzxzxqhyqLzANBgkqhkiG9w0BAQQFADCBpzELMAkGA1UEBhMC
+VVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxDzANBgNVBAcTBkJvc3RvbjETMBEG
+A1UEChMKTXkgQ29tcGFueTEcMBoGA1UECxMTUHJvZHVjdCBEZXZlbG9wbWVudDEZ
+MBcGA1UEAxMQd3d3Lm5vd2hlcmUubm9uZTEhMB8GCSqGSIb3DQEJARYSYWRtaW5A
+bm93aGVyZS5ub25lMB4XDTA3MDMyMzE4MDc0NVoXDTI2MDUyMjE4MDc0NVowgacx
+CzAJBgNVBAYTAlVTMRYwFAYDVQQIEw1NYXNzYWNodXNldHRzMQ8wDQYDVQQHEwZC
+b3N0b24xEzARBgNVBAoTCk15IENvbXBhbnkxHDAaBgNVBAsTE1Byb2R1Y3QgRGV2
+ZWxvcG1lbnQxGTAXBgNVBAMTEHd3dy5ub3doZXJlLm5vbmUxITAfBgkqhkiG9w0B
+CQEWEmFkbWluQG5vd2hlcmUubm9uZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAL5H18W9MHMYK41ds4hYpIyCPs3vIinEwbeOy9BjP3NtXn3pTfs2aSVF
+Fy7uM8/EcqvEPrEIHzcu7kzqTfW1FGjpNU5w+4Gg0J0FojR5qm1tpC/g0jip4CVT
+6PXREwEvIX+/g9XtQwWcY03NWuEUKliYscKWI/fYsVs7vFQtpv8V7I7zrI6ePgyw
+QePdJ25ML7LZoZolptQpiOTucTpIIqFTUKh70DHVSjks/T6W472YkV9VKKqDK5Pt
+jTqsD/dEwd+cjwEl2/c1yqTuwy4ZLm3vsmBn/spOOmg+9Oy9OxG+3KLBT0vOLzWf
+YF+60NFDsJua2AP6GUwbJIGqobSM5C8CAwEAATANBgkqhkiG9w0BAQQFAAOCAQEA
+vGomHEp6TVU83X2EBUgnbOhzKJ9u3fOI/Uf5L7p//Vxqow7OR1cguzh/YEzmXOIL
+ilMVnzX9nj/bvcLAuqEP7MR1A8f4+E807p/L/Sf49BiCcwQq5I966sGKYXjkve+T
+2GTBNwMSq+5kLSf6QY8VZI+qnrAudEQMeJByQhTZZ0dH8Njeq8EGl9KUio+VWaiW
+CQK6xJuAvAHqa06OjLmwu1fYD4GLGSrOIiRVkSXV8qLIUmzxdJaIRznkFWsrCEKR
+wAH966SAOvd2s6yOHMvyDRIL7WHxfESB6rDHsdIW/yny1fBePjv473KrxyXtbz7I
+dMw1yW09l+eEo4A7GzwOdw==
+-----END CERTIFICATE-----
+END
+ chmod 600 $tcert
+ echo "$tcert"
+}
+
+Kecho() {
+ if [ "X$USER" = "Xrunge" ]; then
+ echo "dbg: $*"
+ fi
+}
+
+if [ "X$use_ssh" = "X1" ]; then
+ #
+ # USING SSH
+ #
+ ssh_port="22"
+ ssh_host="$host"
+ vnc_host="$localhost"
+ # let user override ssh via $SSH
+ ssh=${SSH:-"ssh -x"}
+
+ if [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" ]; then
+ SSVNC_LIM_ACCEPT_PRELOAD="$SSVNC_BASEDIR/$SSVNC_UNAME/$SSVNC_LIM_ACCEPT_PRELOAD"
+ fi
+ if [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" ]; then
+ echo ""
+ echo "SSVNC_LIM_ACCEPT_PRELOAD=$SSVNC_LIM_ACCEPT_PRELOAD"
+ fi
+
+ if [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" -a -f "$SSVNC_LIM_ACCEPT_PRELOAD" ]; then
+ plvar=LD_PRELOAD
+ if uname | grep Darwin >/dev/null; then
+ plvar="DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES"
+ fi
+ ssh="env $plvar=$SSVNC_LIM_ACCEPT_PRELOAD $ssh"
+ else
+ SSVNC_LIM_ACCEPT_PRELOAD=""
+ fi
+
+ 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
+ pproxy=""
+ sproxy1=""
+ sproxy_rest=""
+ for part in `echo "$proxy" | tr ',' ' '`
+ do
+ Kecho proxy_part=$part
+ if [ "X$part" = "X" ]; then
+ continue
+ elif echo "$part" | egrep -i '^(http|https|socks|socks4|socks5)://' > /dev/null; then
+ pproxy="$pproxy,$part"
+ else
+ if [ "X$sproxy1" = "X" ]; then
+ sproxy1="$part"
+ else
+ sproxy_rest="$sproxy_rest,$part"
+ fi
+ fi
+ 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
+
+ sproxy1_host=""
+ sproxy1_port=""
+ sproxy1_user=""
+
+ if [ "X$sproxy1" != "X" ]; then
+ sproxy1_host=`echo "$sproxy1" | awk -F: '{print $1}'`
+ sproxy1_user=`echo "$sproxy1_host" | awk -F@ '{print $1}'`
+ sproxy1_host=`echo "$sproxy1_host" | awk -F@ '{print $2}'`
+ if [ "X$sproxy1_host" = "X" ]; then
+ sproxy1_host=$sproxy1_user
+ sproxy1_user=""
+ else
+ sproxy1_user="${sproxy1_user}@"
+ fi
+ sproxy1_port=`echo "$sproxy1" | awk -F: '{print $2}'`
+ if [ "X$sproxy1_port" = "X" ]; then
+ sproxy1_port="22"
+ fi
+ else
+ sproxy1_host=`echo "$host" | awk -F: '{print $1}'`
+ sproxy1_user=`echo "$sproxy1_host" | awk -F@ '{print $1}'`
+ sproxy1_host=`echo "$sproxy1_host" | awk -F@ '{print $2}'`
+ if [ "X$sproxy1_host" = "X" ]; then
+ sproxy1_host=$sproxy1_user
+ sproxy1_user=""
+ else
+ sproxy1_user="${sproxy1_user}@"
+ fi
+ sproxy1_port=`echo "$host" | awk -F: '{print $2}'`
+ if [ "X$sproxy1_port" = "X" ]; then
+ sproxy1_port="22"
+ fi
+ fi
+
+ 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"`
+ PPROXY_REMOVE=1; export PPROXY_REMOVE
+ proxy=$pproxy
+ port_save=$port
+ host_save=$host
+ if [ "X$sproxy1_host" != "X" ]; then
+ host=$sproxy1_host
+ fi
+ if [ "X$sproxy1_port" != "X" ]; then
+ port=$sproxy1_port
+ fi
+ host=`echo "$host" | sed -e 's/^.*@//'`
+ port=`echo "$port" | sed -e 's/^.*://'`
+ pcode "$ptmp"
+ port=$port_save
+ host=$host_save
+
+ nd=`findfree 6700`
+ PPROXY_LISTEN=$nd; export PPROXY_LISTEN
+ $ptmp &
+ sleep 2
+ ssh_args="$ssh_args -o NoHostAuthenticationForLocalhost=yes"
+ if [ "X$sproxy1" = "X" ]; then
+ u=""
+ if echo "$host" | grep '@' > /dev/null; then
+ u=`echo "$host" | sed -e 's/@.*$/@/'`
+ fi
+
+ proxy="${u}$localhost:$nd"
+ else
+ proxy="${sproxy1_user}$localhost:$nd"
+ fi
+ if [ "X$sproxy_rest" != "X" ]; then
+ proxy="$proxy,$sproxy_rest"
+ fi
+ Kecho proxy=$proxy
+ fi
+
+ if echo "$proxy" | grep "," > /dev/null; then
+
+ proxy1=`echo "$proxy" | awk -F, '{print $1}'`
+ proxy2=`echo "$proxy" | awk -F, '{print $2}'`
+
+ # user1@gw1.com:port1,user2@ws2:port2
+ ssh_host1=`echo "$proxy1" | awk -F: '{print $1}'`
+ ssh_port1=`echo "$proxy1" | awk -F: '{print $2}'`
+ if [ "X$ssh_port1" != "X" ]; then
+ ssh_port1="-p $ssh_port1"
+ fi
+ ssh_host2=`echo "$proxy2" | awk -F: '{print $1}'`
+ ssh_user2=`echo "$ssh_host2" | awk -F@ '{print $1}'`
+ ssh_host2=`echo "$ssh_host2" | awk -F@ '{print $2}'`
+ if [ "X$ssh_host2" = "X" ]; then
+ ssh_host2=$ssh_user2
+ ssh_user2=""
+ else
+ ssh_user2="${ssh_user2}@"
+ fi
+ ssh_port2=`echo "$proxy2" | awk -F: '{print $2}'`
+ if [ "X$ssh_port2" = "X" ]; then
+ ssh_port2="22"
+ fi
+ proxport=`findfree 3500`
+ echo
+ 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\""
+ echo ""
+ $ssh -f -x $ssh_port1 $targ -e none -o NoHostAuthenticationForLocalhost=yes -L $proxport:$ssh_host2:$ssh_port2 $ssh_host1 "sleep 30"
+ ssh_args="$ssh_args -o NoHostAuthenticationForLocalhost=yes"
+ sleep 1
+ stty sane
+ proxy="${ssh_user2}$localhost:$proxport"
+ fi
+
+ if [ "X$proxy" != "X" ]; then
+ ssh_port=`echo "$proxy" | awk -F: '{print $2}'`
+ if [ "X$ssh_port" = "X" ]; then
+ ssh_port="22"
+ fi
+ ssh_host=`echo "$proxy" | awk -F: '{print $1}'`
+ vnc_host="$host"
+ fi
+
+ echo ""
+ echo "Running ssh:"
+ sz=`echo "$ssh_cmd" | wc -c`
+ if [ "$sz" -gt 300 ]; then
+ info="..."
+ else
+ info="$ssh_cmd"
+ fi
+
+ C=""
+ if [ "X$SS_VNCVIEWER_USE_C" != "X" ]; then
+ C="-C"
+ fi
+
+ getport=""
+ teeport=""
+ if echo "$ssh_cmd" | egrep "(PORT=|P=) " > /dev/null; then
+ getport=1
+ if echo "$ssh_cmd" | egrep "P= " > /dev/null; then
+ teeport=1
+ fi
+
+ PORT=""
+ ssh_cmd=`echo "$ssh_cmd" | sed -e 's/PORT=[ ]*//' -e 's/P=//'`
+ SSVNC_NO_ENC_WARN=1
+ if [ "X$use_sshssl" = "X" ]; then
+ direct_connect=1
+ fi
+ fi
+ if [ "X$getport" != "X" ]; then
+ ssh_redir="-D ${use}"
+ elif [ "X$reverse" = "X" ]; then
+ ssh_redir="-L ${use}:${vnc_host}:${port}"
+ else
+ ssh_redir="-R ${port}:${vnc_host}:${use}"
+ fi
+ pmark=`sh -c 'echo $$'`
+
+ # the -t option actually speeds up typing response via VNC!!
+ if [ "X$ssh_port" = "X22" ]; then
+ ssh_port=""
+ else
+ ssh_port="-p $ssh_port"
+ fi
+
+ if [ "X$SS_VNCVIEWER_SSH_ONLY" != "X" ]; then
+ echo "$ssh -x $ssh_port $targ $C $ssh_args $ssh_host \"$info\""
+ echo ""
+ $ssh -x $ssh_port $targ $C $ssh_args $ssh_host "$ssh_cmd"
+ exit $?
+
+ elif [ "X$SS_VNCVIEWER_NO_F" != "X" ]; then
+ echo "$ssh -x $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host \"$info\""
+ echo ""
+ $ssh -x $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host "$ssh_cmd"
+ rc=$?
+
+ elif [ "X$getport" != "X" ]; then
+ tport=/tmp/ss_vncviewer_tport${RANDOM}.$$
+ tport=`mytmp "$tport"`
+
+ if [ "X$rsh" != "X1" ]; then
+ if echo "$ssh_cmd" | grep "sudo " > /dev/null; then
+ echo ""
+ echo "Initial ssh with 'sudo id' to prime sudo so hopefully the next one"
+ echo "will require no password..."
+ echo ""
+ targ="-t"
+ $ssh -x $ssh_port $targ $ssh_args $ssh_host "sudo id; tty"
+ echo ""
+ 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 "$ssh_cmd" > $tport
+ if [ "X$teeport" = "X1" ]; then
+ tail -f $tport 1>&2 &
+ tail_pid=$!
+ fi
+ rc=$?
+ else
+ rsh_setup
+ echo "rsh $ul $ssh_host \"$ssh_cmd\""
+ echo ""
+ rsh $ul $ssh_host "$ssh_cmd" > $tport &
+ sleep 1
+ rc=0
+ fi
+
+ if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then
+ echo "sleep $SSVNC_EXTRA_SLEEP"
+ sleep $SSVNC_EXTRA_SLEEP
+ fi
+
+ stty sane
+ i=0
+ if type perl > /dev/null 2>&1; then
+ imax=50
+ sleepit="perl -e 'select(undef, undef, undef, 0.20)'"
+ else
+ imax=10
+ sleepit="sleep 1"
+ fi
+ while [ $i -lt $imax ]; do
+ #echo $sleepit
+ eval $sleepit
+ PORT=`grep "^PORT=" $tport | head -n 1 | sed -e 's/PORT=//' -e 's/\r//g'`
+ if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then
+ break
+ fi
+ vnss=`sed -e 's/\r//g' $tport | egrep -i '^(New.* desktop is|A VNC server is already running).*:[0-9[0-9]*$' | head -n 1 | awk '{print $NF}'`
+ if [ "X$vnss" != "X" ]; then
+ PORT=`echo "$vnss" | awk -F: '{print $2}'`
+ if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then
+ if [ $PORT -lt 100 ]; then
+ PORT=`expr $PORT + 5900`
+ fi
+ fi
+ if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then
+ break
+ fi
+ fi
+ i=`expr $i + 1`
+ done
+
+ echo "PORT=$PORT" 1>&2
+ rm -f $tport
+ if [ "X$rsh" = "X1" ]; then
+ rsh_viewer "$@"
+ exit $?
+ fi
+ PPROXY_SOCKS=1
+ if [ "X$SSVNC_SOCKS5" != "X" ]; then
+ PPROXY_SOCKS=5
+ fi
+ export PPROXY_SOCKS
+ host="$localhost"
+ port="$PORT"
+ proxy="$localhost:$use"
+
+ else
+ if [ "X$rsh" != "X1" ]; then
+ 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 "$ssh_cmd"
+ rc=$?
+ else
+ rsh_setup
+ echo "rsh $ul $ssh_host \"$ssh_cmd\""
+ echo ""
+ rsh $ul $ssh_host "$ssh_cmd" &
+ sleep 1
+ PORT=$port
+ rsh_viewer "$@"
+ exit $?
+ fi
+ fi
+
+ if [ "$rc" != "0" ]; then
+ echo ""
+ echo "ssh to $ssh_host failed."
+ exit 1
+ fi
+ stty sane
+
+ c=0
+ pssh=""
+ while [ $c -lt 40 ]
+ do
+ p=`expr $pmark + $c`
+ pout=`ps -p "$p" 2>/dev/null | grep -v '^[ ]*PID' | sed -e 's/-L.*$//' -e 's/-x .*$//'`
+ if echo "$pout" | grep "ssh" > /dev/null; then
+ if echo "$pout" | egrep -i 'ssh.*(-add|-agent|-ask|-keygen|-argv0|vnc)' >/dev/null; then
+ :
+ elif echo "$pout" | egrep -i 'scp|sshd' >/dev/null; then
+ :
+ else
+ pssh=$p
+ break
+ fi
+ fi
+ c=`expr $c + 1`
+ done
+ if [ "X$getport" != "X" ]; then
+ :
+ elif [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" ] ; then
+ sleep 2
+ elif [ "X$ssh_cmd" = "Xsleep $ssh_sleep" ] ; then
+ #echo T sleep 1
+ sleep 1
+ elif echo "$ssh_cmd" | grep '^sleep ' >/dev/null; then
+ #echo T sleep 2
+ sleep 2
+ else
+ # let any command get started a bit.
+ #echo T sleep 5
+ sleep 5
+ fi
+ echo ""
+ #reset
+ stty sane
+ if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then
+ echo "sleep $SSVNC_EXTRA_SLEEP"
+ sleep $SSVNC_EXTRA_SLEEP
+ fi
+ echo "ssh_pid='$pssh'"; echo
+ if [ "X$use_sshssl" = "X" -a "X$getport" = "X" ]; then
+ echo "Running viewer:"
+
+ trap "final" 0 2 15
+ if [ "X$reverse" = "X" ]; then
+ echo "$VNCVIEWERCMD" "$@" $localhost:$N
+ echo ""
+ $VNCVIEWERCMD "$@" $localhost:$N
+ if [ $? != 0 ]; then
+ echo "vncviewer command failed: $?"
+ if [ "X$secondtry" = "X1" ]; then
+ sleep 2
+ $VNCVIEWERCMD "$@" $localhost:$N
+ fi
+ fi
+ else
+ echo ""
+ echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode."
+ echo ""
+ N2=$N
+ if [ "X$VNCVIEWER_IS_REALVNC4" = "X1" ]; then
+ N2=`echo "$N2" | sed -e 's/://g'`
+ if [ $N2 -le 200 ]; then
+ N2=`expr $N2 + 5500`
+ fi
+ fi
+ echo "$VNCVIEWERCMD" "$@" -listen $N2
+ echo ""
+ $VNCVIEWERCMD "$@" -listen $N2
+ fi
+
+ exit $?
+ else
+ use2=`findfree 5960`
+ host0=$host
+ port0=$port
+ host=$localhost
+ port=$use
+ use=$use2
+ N=`expr $use - 5900`
+ if [ "X$getport" != "X" ]; then
+ host="$host0"
+ port="$port0"
+ else
+ proxy=""
+ fi
+ fi
+fi
+
+# create the stunnel config file:
+if [ "X$verify" != "X" ]; then
+ if [ -d $verify ]; then
+ verify="CApath = $verify"
+ else
+ verify="CAfile = $verify"
+ fi
+ verify="$verify
+verify = 2"
+fi
+if [ "X$mycert" != "X" ]; then
+ cert="cert = $mycert"
+fi
+if [ "X$crl" != "X" ]; then
+ if [ -d $crl ]; then
+ crl="CRLpath = $crl"
+ else
+ crl="CRLfile = $crl"
+ fi
+fi
+
+ptmp=""
+if [ "X$proxy" != "X" ]; then
+ ptmp="/tmp/ss_vncviewer${RANDOM}.$$.pl"
+ ptmp=`mytmp "$ptmp"`
+ PPROXY_REMOVE=1; export PPROXY_REMOVE
+ pcode "$ptmp"
+ if [ "X$showcert" != "X1" -a "X$direct_connect" = "X" ]; then
+ if uname | egrep 'Darwin|SunOS' >/dev/null; then
+ vout=`echo "$proxy" | grep -i vencrypt`
+ if [ "X$vout" != "X" -a "X$reverse" = "X1" ]; then
+ # need to exec for reverse vencrypt
+ connect="exec = $ptmp"
+ else
+ # on mac and solaris we need to listen on socket instead of stdio:
+ nd=`findfree 6700`
+ PPROXY_LISTEN=$nd
+ export PPROXY_LISTEN
+ if [ "X$reverse" = "X" ]; then
+ #$ptmp 2>/dev/null &
+ $ptmp &
+ fi
+ sleep 2
+ host="$localhost"
+ port="$nd"
+ connect="connect = $localhost:$nd"
+ fi
+ else
+ # otherwise on unix we can exec it:
+ connect="exec = $ptmp"
+ fi
+ else
+ connect="exec = $ptmp"
+ fi
+else
+ connect="connect = $host:$port"
+fi
+
+if [ "X$showcert" = "X1" ]; then
+ if [ "X$proxy" != "X" ]; then
+ PPROXY_LISTEN=$use
+ export PPROXY_LISTEN
+ if [ "X$SS_DEBUG" != "X" ]; then
+ $ptmp &
+ else
+ $ptmp 2>/dev/null &
+ fi
+ sleep 1
+ host="$localhost"
+ port="$use"
+ fi
+ 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"
+ if [ "X$reverse" = "X" ]; then
+ openssl s_client $cipher_args -prexit -connect $host:$port 2>&1 < /dev/null
+ rc=$?
+ else
+ tcert=""
+ if [ "X$mycert" = "X" ]; then
+ tcert=`make_tcert`
+ cert_args="-cert $tcert -CAfile $tcert"
+ else
+ cert_args="-cert $mycert -CAfile $mycert"
+ fi
+ tmp_out=/tmp/showcert_out${RANDOM}.$$
+ tmp_out=`mytmp "$tmp_out"`
+ tmp_err=/tmp/showcert_err${RANDOM}.$$
+ tmp_err=`mytmp "$tmp_err"`
+
+ #echo "openssl s_server $cipher_args $cert_args -accept $port -verify 2 > $tmp_out 2> $tmp_err" 1>&2
+
+ perl -e "
+ \$p = open(O, \"|openssl s_server $cipher_args $cert_args -accept $port -verify 2 1>$tmp_out 2> $tmp_err\");
+ exit 1 unless \$p;
+ while (1) {
+ sleep 1;
+ if (!open(F, \"<$tmp_out\")) {
+ kill \$p;
+ exit 1;
+ }
+ while (<F>) {
+ if (/RFB 00/) {
+ fsleep(0.25);
+ print O \"RFB 000.000\\n\";
+ fsleep(1.00);
+ kill \$p;
+ fsleep(0.25);
+ exit 0;
+ }
+ }
+ close F;
+ }
+ sub fsleep {
+ select(undef, undef, undef, shift);
+ }
+ ";
+
+ echo ""
+ cat $tmp_out
+ echo ""
+ echo "----2----"
+ cat $tmp_err
+ if grep BEGIN.CERTIFICATE $tmp_out >/dev/null; then
+ rc=0
+ else
+ rc=1
+ fi
+
+ rm -f $tmp_out $tmp_err
+ fi
+ if [ "X$SSVNC_PREDIGESTED_HANDSHAKE" != "X" ]; then
+ rm -f $SSVNC_PREDIGESTED_HANDSHAKE
+ fi
+ exit $rc
+fi
+
+if [ "X$direct_connect" != "X" ]; then
+ if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then
+ SSVNC_NO_ENC_WARN=1
+ echo ""
+ echo "Using UltraVNC DSM Plugin key for encryption:"
+ echo ""
+ ustr=`echo "$SSVNC_ULTRA_DSM" | sed -e 's/pw=[^ ]*/pw=******/g'`
+ echo " $ustr PORT HOST:PORT"
+ echo ""
+ elif [ "X$getport" = "X" ]; then
+ echo ""
+ echo "Running viewer for direct connection:"
+ if echo X"$@" | grep chatonly > /dev/null; then
+ :
+ else
+ echo ""
+ echo "** NOTE: THERE WILL BE NO SSL OR SSH ENCRYPTION **"
+ echo ""
+ fi
+ fi
+ x=""
+ if [ "X$SSVNC_NO_ENC_WARN" != "X" ]; then
+ if [ "X$getport" = "X" ]; then
+ sleep 1
+ fi
+ elif type printf > /dev/null 2>&1; then
+ printf "Are you sure you want to continue? [y]/n "
+ read x
+ else
+ echo -n "Are you sure you want to continue? [y]/n "
+ read x
+ fi
+ if [ "X$x" = "Xn" ]; then
+ exit 1
+ fi
+ echo ""
+ if [ "X$ptmp" != "X" ]; then
+ if [ "X$reverse" = "X" ]; then
+ PPROXY_LISTEN=$use
+ export PPROXY_LISTEN
+ else
+ PPROXY_REVERSE="$localhost:$use"
+ export PPROXY_REVERSE
+ pps=3
+ if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then
+ pps=`expr $pps + $SSVNC_EXTRA_SLEEP`
+ fi
+ PPROXY_SLEEP=$pps; export PPROXY_SLEEP;
+ PPROXY_KILLPID=+1; export PPROXY_KILLPID;
+ fi
+
+ $ptmp &
+
+ if [ "X$reverse" = "X" ]; then
+ #sleep 2
+ #echo T sleep 1
+ sleep 1
+ fi
+ host="$localhost"
+ disp="$N"
+ port=`expr $disp + 5900`
+ fi
+ if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then
+ echo "T sleep $SSVNC_EXTRA_SLEEP"
+ sleep $SSVNC_EXTRA_SLEEP
+ fi
+ if [ "X$reverse" = "X" ]; then
+ hostdisp="$host:$disp"
+ if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then
+ if [ "X$SSVNC_USE_OURS" = "X1" ]; then
+ hostdisp="exec=$SSVNC_ULTRA_DSM 0 $host:$port"
+ else
+ pf=`findfree 5970`
+ cmd="$SSVNC_ULTRA_DSM -$pf $host:$port"
+ pf=`expr $pf - 5900`
+ hostdisp="$localhost:$pf"
+ ustr=`echo "$cmd" | sed -e 's/pw=[^ ]*/pw=******/g'`
+ echo "Running:"
+ echo
+ echo "$ustr &"
+ echo
+ $cmd &
+ dsm_pid=$!
+ sleep 2
+ fi
+ fi
+ hostdisp2=`echo "$hostdisp" | sed -e 's/pw=[^ ]*/pw=******/g'`
+ echo "$VNCVIEWERCMD" "$@" "$hostdisp2"
+ trap "final" 0 2 15
+ echo ""
+ $VNCVIEWERCMD "$@" "$hostdisp"
+ if [ $? != 0 ]; then
+ echo "vncviewer command failed: $?"
+ if [ "X$secondtry" = "X1" ]; then
+ sleep 2
+ $VNCVIEWERCMD "$@" "$hostdisp"
+ fi
+ fi
+ else
+ echo ""
+ echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode."
+ 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
+ VNCVIEWER_LISTEN_LOCALHOST=1
+ export VNCVIEWER_LISTEN_LOCALHOST
+ dport=`expr 5500 + $disp`
+ cmd="$SSVNC_ULTRA_DSM $dport $localhost:$use"
+ ustr=`echo "$cmd" | sed -e 's/pw=[^ ]*/pw=******/g'`
+ echo "Running:"
+ echo
+ echo "$ustr &"
+ echo
+ $cmd &
+ dsm_pid=$!
+ sleep 2
+ disp=$use
+ if [ $disp -ge 5500 ]; then
+ disp=`expr $disp - 5500`
+ fi
+ fi
+ disp2=$disp
+ if [ "X$VNCVIEWER_IS_REALVNC4" = "X1" ]; then
+ disp2=`echo "$disp2" | sed -e 's/://g'`
+ if [ $disp2 -le 200 ]; then
+ disp2=`expr $disp2 + 5500`
+ fi
+ fi
+ echo "$VNCVIEWERCMD" "$@" -listen $disp2
+ echo ""
+ $VNCVIEWERCMD "$@" -listen $disp2
+ fi
+ exit $?
+fi
+
+tmp_cfg=/tmp/ss_vncviewer${RANDOM}.$$
+tmp_cfg=`mytmp "$tmp_cfg"`
+
+stunnel_exec=""
+if [ "X$SSVNC_USE_OURS" != "X1" ]; then
+ :
+elif echo $STUNNEL_EXTRA_SVC_OPTS | grep '#stunnel-exec' > /dev/null; then
+ stunnel_exec="#"
+fi
+
+if [ "X$reverse" = "X" ]; then
+
+ if echo "$proxy" | grep "^repeater://" > /dev/null; then
+ if [ "X$cert" = "XBUILTIN" ]; then
+ ttcert=`make_tcert`
+ cert="cert = $ttcert"
+ fi
+ # Note for listen mode, an empty cert will cause stunnel to fail.
+ # The ssvnc gui will have already taken care of this.
+ fi
+
+ cat > "$tmp_cfg" <<END
+foreground = yes
+pid =
+client = yes
+debug = $stunnel_debug
+$ciphers
+$STUNNEL_EXTRA_OPTS
+$STUNNEL_EXTRA_OPTS_USER
+$cert
+$crl
+$verify
+
+${stunnel_exec}[vnc_stunnel]
+${stunnel_exec}accept = $localhost:$use
+$connect
+$STUNNEL_EXTRA_SVC_OPTS
+$STUNNEL_EXTRA_SVC_OPTS_USER
+
+END
+
+else
+ # REVERSE case:
+
+ stunnel_exec="" # doesn't work for listening.
+
+ p2=`expr 5500 + $N`
+ connect="connect = $localhost:$p2"
+ if [ "X$cert" = "XBUILTIN" ]; then
+ ttcert=`make_tcert`
+ cert="cert = $ttcert"
+ fi
+ # Note for listen mode, an empty cert will cause stunnel to fail.
+ # The ssvnc gui will have already taken care of this.
+
+
+ hloc=""
+ if [ "X$use_ssh" = "X1" ]; then
+ hloc="$localhost:"
+ fi
+ if echo "$proxy" | grep -i '^vencrypt:' > /dev/null; then
+ hloc="$localhost:"
+ pv=`findfree 5570`
+ proxy="vencrypt:$pv:$port"
+ port=$pv
+ if [ "X$anondh_set" = "X1" ]; then
+ # not needed for ANONDH in this mode
+ #ciphers="ciphers = ADH:@STRENGTH"
+ :
+ fi
+ fi
+ cat > "$tmp_cfg" <<END
+foreground = yes
+pid =
+client = no
+debug = $stunnel_debug
+$ciphers
+$STUNNEL_EXTRA_OPTS
+$STUNNEL_EXTRA_OPTS_USER
+$cert
+$crl
+$verify
+
+[vnc_stunnel]
+accept = $hloc$port
+$connect
+$STUNNEL_EXTRA_SVC_OPTS
+$STUNNEL_EXTRA_SVC_OPTS_USER
+
+END
+
+fi
+
+echo ""
+echo "Using this stunnel configuration:"
+echo ""
+cat "$tmp_cfg" | uniq
+echo ""
+sleep 1
+
+if [ "X$stunnel_exec" = "X" ]; then
+ echo ""
+ echo "Running stunnel:"
+ echo "$STUNNEL $tmp_cfg"
+ st=`echo "$STUNNEL" | awk '{print $1}'`
+ $st -help > /dev/null 2>&1
+ $STUNNEL "$tmp_cfg" < /dev/tty > /dev/tty &
+ stunnel_pid=$!
+ echo ""
+
+ # pause here to let the user supply a possible passphrase for the
+ # mycert key:
+ if [ "X$mycert" != "X" ]; then
+ nsl=10
+ dsl=0
+ if [ ! -f $mycert ]; then
+ dsl=0
+ elif grep -i 'Proc-Type.*ENCRYPTED' "$mycert" > /dev/null 2>/dev/null; then
+ dsl=1
+ fi
+ if [ "X$dsl" = "X1" ]; then
+ echo ""
+ echo "(** pausing $nsl secs for possible certificate passphrase dialog **)"
+ echo ""
+ sleep $nsl
+ echo "(** done pausing for passphrase **)"
+ echo ""
+ fi
+ fi
+ #echo T sleep 1
+ sleep 1
+ rm -f "$tmp_cfg"
+fi
+
+
+echo ""
+if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then
+ echo "sleep $SSVNC_EXTRA_SLEEP"
+ sleep $SSVNC_EXTRA_SLEEP
+fi
+echo "Running viewer:"
+if [ "X$reverse" = "X" ]; then
+ vnc_hp=$localhost:$N
+ if [ "X$stunnel_exec" != "X" ]; then
+ vnc_hp="exec=$STUNNEL $tmp_cfg"
+ fi
+ echo "$VNCVIEWERCMD" "$@" "$vnc_hp"
+ trap "final" 0 2 15
+ echo ""
+ $VNCVIEWERCMD "$@" "$vnc_hp"
+ if [ $? != 0 ]; then
+ echo "vncviewer command failed: $?"
+ if [ "X$secondtry" = "X1" ]; then
+ sleep 2
+ $VNCVIEWERCMD "$@" "$vnc_hp"
+ fi
+ fi
+else
+ echo ""
+ echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode."
+ echo ""
+ N2=$N
+ if [ "X$VNCVIEWER_IS_REALVNC4" = "X1" ]; then
+ N2=`echo "$N2" | sed -e 's/://g'`
+ if [ $N2 -le 200 ]; then
+ N2=`expr $N2 + 5500`
+ fi
+ fi
+ echo "$VNCVIEWERCMD" "$@" -listen $N2
+ trap "final" 0 2 15
+ echo ""
+ if [ "X$proxy" != "X" ]; then
+ 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
+ PPROXY_PROXY="vencrypt://$localhost:$pstunnel"; export PPROXY_PROXY
+ PPROXY_DEST="$localhost:$pstunnel"; export PPROXY_DEST
+ STUNNEL_ONCE=1; export STUNNEL_ONCE
+ STUNNEL_MAX_CLIENTS=1; export STUNNEL_MAX_CLIENTS
+ else
+ PPROXY_REVERSE="$localhost:$port"; export PPROXY_REVERSE
+ PPROXY_SLEEP=1; export PPROXY_SLEEP;
+ fi
+ PPROXY_KILLPID=+1; export PPROXY_KILLPID;
+ $ptmp &
+ fi
+ $VNCVIEWERCMD "$@" -listen $N2
+fi
+
+sleep 1