diff options
Diffstat (limited to 'webclients/java-applet/ssl/ss_vncviewer')
| -rwxr-xr-x | webclients/java-applet/ssl/ss_vncviewer | 3676 | 
1 files changed, 3676 insertions, 0 deletions
| diff --git a/webclients/java-applet/ssl/ss_vncviewer b/webclients/java-applet/ssl/ss_vncviewer new file mode 100755 index 0000000..7e793ff --- /dev/null +++ b/webclients/java-applet/ssl/ss_vncviewer @@ -0,0 +1,3676 @@ +#!/bin/sh +# +# ss_vncviewer:  wrapper for vncviewer to use an stunnel SSL tunnel +#                or an SSH tunnel. +# +# Copyright (c) 2006-2009 by Karl J. Runge <runge@karlrunge.com> +# +# ss_vncviewer is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or (at +# your option) any later version. +#  +# ss_vncviewer is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +#  +# You should have received a copy of the GNU General Public License +# along with ss_vncviewer; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +# or see <http://www.gnu.org/licenses/>. +#  +#  +# You must have stunnel(8) installed on the system and in your PATH +# (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).  On ssvnc 1.0.27 and +#            later the bundled command 'ultravnc_dsm_helper' is used. +# +#    See http://www.karlrunge.com/x11vnc/faq.html#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} +if [ "X$SSVNC_TURBOVNC" != "X" ]; then +	if echo "$VNCVIEWERCMD" | grep '\.turbovnc' > /dev/null; then +		: +	else +		if type "$VNCVIEWERCMD.turbovnc" > /dev/null 2>/dev/null; then +			VNCVIEWERCMD="$VNCVIEWERCMD.turbovnc" +		fi +	fi +fi +# +# Same for STUNNEL, e.g. set it to /path/to/stunnel or stunnel4, etc. +# + +# turn on verbose debugging output +if [ "X$SS_DEBUG" != "X" -a "X$SS_DEBUG" != "X0" ]; 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) +stunnel_set_here="" +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 +	stunnel_set_here=1 +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 'VNC viewer version 3' > /dev/null; then +		echo "realvnc3" +	elif echo "$str" | grep -i 'VNC viewer .*Edition 4' > /dev/null; then +		echo "realvnc4" +	elif echo "$str" | grep -i 'RealVNC.Ltd' > /dev/null; then +		echo "realvnc4" +	else +		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" +			ULTRAVNC_DSM_HELPER_SHOWCERT_ADH=1 +			export ULTRAVNC_DSM_HELPER_SHOWCERT_ADH +			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 +                ;; +	"-sendclipboard")	VNCVIEWER_SEND_CLIPBOARD=1; export VNCVIEWER_SEND_CLIPBOARD +                ;; +	"-sendalways")	VNCVIEWER_SEND_ALWAYS=1; export VNCVIEWER_SEND_ALWAYS +                ;; +	"-recvtext")	shift; VNCVIEWER_RECV_TEXT="$1"; export VNCVIEWER_RECV_TEXT +                ;; +	"-escape")	shift; VNCVIEWER_ESCAPE="$1"; export VNCVIEWER_ESCAPE +                ;; +	"-ssvnc_encodings")	shift; VNCVIEWER_ENCODINGS="$1"; export VNCVIEWER_ENCODINGS +                ;; +	"-ssvnc_extra_opts")	shift; VNCVIEWERCMD_EXTRA_OPTS="$1"; export VNCVIEWERCMD_EXTRA_OPTS +                ;; +	"-rfbversion")	shift; VNCVIEWER_RFBVERSION="$1"; export VNCVIEWER_RFBVERSION +                ;; +	"-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 + +		# 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 +	# 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 + +have_uvnc_dsm_helper_showcert="" +if [ "X$showcert" = "X1" -a "X$SSVNC_USE_S_CLIENT" = "X" -a "X$reverse" = "X" ]; then +	if type ultravnc_dsm_helper >/dev/null 2>&1; then +		if ultravnc_dsm_helper -help 2>&1 | grep -w showcert >/dev/null; then +			have_uvnc_dsm_helper_showcert=1 +		fi +	fi +fi +have_uvnc_dsm_helper_ipv6="" +if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then +	if type ultravnc_dsm_helper >/dev/null 2>&1; then +		if ultravnc_dsm_helper -help 2>&1 | grep -iw ipv6 >/dev/null; then +			have_uvnc_dsm_helper_ipv6=1 +		fi +	fi +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 +	if [ "X$SSVNC_USE_OURS" = "X" ]; then +		NEED_VENCRYPT_VIEWER_BRIDGE=1 +	fi +fi +if [ "X$SSVNC_USE_OURS" = "X" ]; then +	VNCVIEWERCMD_EXTRA_OPTS="" +fi + + +# 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 + +# 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 ':[0-9][0-9]*$' > /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: + +# 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... +	gout="" +	if type getent > /dev/null 2>/dev/null; then +		gout=`getent hosts "$host" 2>/dev/null` +	fi +	if echo "$gout" | grep ':.*:' > /dev/null; then +		if echo "$gout" | grep '^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' > /dev/null; then +			: +		else +			echo "ipv6: "`echo "$gout" | grep ':.*:' | head -n 1` +			ipv6=1 +		fi +	fi +	if [ "X$ipv6" = "X0" ]; then +		hout="" +		if type host > /dev/null 2>/dev/null; then +			host "$host" >/dev/null 2>&1 +			host "$host" >/dev/null 2>&1 +			hout=`host "$host" 2>/dev/null` +		fi +		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 +	fi +	if [ "X$ipv6" = "X0" ]; then +		dout="" +		if type dig > /dev/null 2>/dev/null; then +		dout=`dig -t any "$host" 2>/dev/null` +		fi +		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 +	# 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 + +if [ "X$ipv6" = "X1" -a "X$direct_connect" = "X1" ]; then +	if [ "X$proxy" = "X" -a "X$reverse" = "X" ]; then +		if [ "X$SSVNC_ULTRA_DSM" != "X" -a "X$have_uvnc_dsm_helper_ipv6" = "X1" ]; then +			: +		elif [ "X$SSVNC_NO_IPV6_PROXY" != "X" ]; then +			: +		elif [ "X$SSVNC_NO_IPV6_PROXY_DIRECT" != "X" ]; then +			: +		elif [ "X$SSVNC_USE_OURS" = "X1" ]; then +			# requires 1.0.27 and later ssvncviewer binary +			: +		else +			proxy="ipv6://$host:$port" +			echo "direct connect: set proxy=$proxy" +		fi +	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 +	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$tail_pid2" != "X" ]; then +		kill -TERM $tail_pid2 +	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 + +if echo "$VNCVIEWERCMD" | egrep -i '^(xmessage|sleep )' > /dev/null; then +	: +elif [ "X$VNCVIEWERCMD_EXTRA_OPTS" != "X" ]; then +	VNCVIEWERCMD="$VNCVIEWERCMD $VNCVIEWERCMD_EXTRA_OPTS" +fi + +# trick for the undocumented rsh://host:port method. +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 +} + +check_perl() { +	if type "$1" > /dev/null 2>&1; then +		: +	elif [ ! -x "$1" ]; then +		echo "" +		echo "*******************************************************" +		echo "** Problem finding the Perl command '$1': **" +		echo "" +		type "perl" +		echo "" +		echo "** Perhaps you need to install the Perl package. **" +		echo "*******************************************************" +		echo "" +		sleep 5 +	fi +} + +# this is the PPROXY tool.  used only here for now...  +pcode() { +	tf=$1 +	PPROXY_PROXY=$proxy; export PPROXY_PROXY +	PPROXY_DEST="$host:$port"; export PPROXY_DEST +	check_perl /usr/bin/perl + +	cod='#!/usr/bin/perl + +# A hack to glue stunnel to a Web or SOCKS proxy, UltraVNC repeater for +# client connections. +# Also acts as a VeNCrypt bridge (by redirecting to stunnel.) + +use IO::Socket::INET; + +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}; +} + +foreach my $var (qw( +		PPROXY_DEST +		PPROXY_KILLPID +		PPROXY_LISTEN +		PPROXY_PROXY +		PPROXY_REMOVE +		PPROXY_REPEATER +		PPROXY_REVERSE +		PPROXY_SLEEP +		PPROXY_SOCKS +		PPROXY_VENCRYPT +		PPROXY_VENCRYPT_VIEWER_BRIDGE +    )) { +	if (0 || $ENV{SS_DEBUG} || $ENV{SSVNC_VENCRYPT_DEBUG}) { +		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}; +} + +my $have_gettimeofday = 0; +eval "use Time::HiRes;"; +if ($@ eq "") { +	$have_gettimeofday = 1; +} +sub gettime { +	my $t = "0.0"; +	if ($have_gettimeofday) { +		$t = Time::HiRes::gettimeofday(); +	} +	return $t; +} + +my $listen_handle = ""; +my $sock = ""; +my $parent = $$; + +my $initial_data = ""; + +if ($ENV{PPROXY_VENCRYPT_VIEWER_BRIDGE}) { +	my ($from, $to) = split(/,/, $ENV{PPROXY_VENCRYPT_VIEWER_BRIDGE}); +	do_vencrypt_viewer_bridge($from, $to); +	exit 0; +} + +my ($first, $second, $third) = split(/,/, $ENV{PPROXY_PROXY}, 3); +my ($mode_1st, $mode_2nd, $mode_3rd) = ("", "", ""); + +($first, $mode_1st) = url_parse($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 "") { +	($second, $mode_2nd) = url_parse($second); +} + +if ($third ne "") { +	($third, $mode_3rd) = url_parse($third); +} + + +print STDERR "\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 (! $have_inet6) { +	print STDERR "PPROXY: To enable IPv6 connections, install the IO::Socket::INET6 perl module.\n\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"; +} + +sub pdie { +	my $msg = shift; +	kill_proxy_pids(); +	die "$msg"; +} + +if ($ENV{PPROXY_REVERSE} ne "") { +	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: $emsg -- PPROXY_REVERSE\n"; +	} +	print STDERR "PPROXY_REVERSE: connected to $rhost $rport\n"; + +} elsif ($ENV{PPROXY_LISTEN} ne "") { +	my $listen_sock = ""; +	my $maxtry = 12; +	my $sleep = 5; +	my $p2 = ""; +	my $emsg = ""; +	for (my $i=0; $i < $maxtry; $i++)  { +		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 = "$if:$p"; +			$listen_sock = IO::Socket::INET->new( +				Listen    => 2, +				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: $emsg $!\n"; +				warn "Could not listen on port $p2, retrying in $sleep seconds... (Ctrl-C to quit)\n"; +				sleep $sleep; +			} +		} else { +			last; +		} +	} +	if (! $listen_sock) { +		pdie "pproxy: $emsg -- PPROXY_LISTEN\n"; +	} +	print STDERR "pproxy: listening on $p2\n"; +	my $ip; +	($listen_handle, $ip) = $listen_sock->accept(); +	my $err = $!; +	close $listen_sock; +	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( +	PeerAddr => $proxy_host, +	PeerPort => $proxy_port, +	Proto => "tcp" +); + +my $err = ""; + +if (! $sock && $have_inet6) { +	$err = $!; + +	print STDERR "pproxy: $!\n"; + +	eval {$sock = IO::Socket::INET6->new( +		PeerAddr => $proxy_host, +		PeerPort => $proxy_port, +		Proto => "tcp" +	);}; +	$err .= " / $!"; +} + +if (! $sock && ($proxy_host =~ /^::ffff:(\d+\.\d+\.\d+\.\d+)$/i || $proxy_host =~ /^::ffff:([\da-f]+:[\da-f]+)$/i)) { +	print STDERR "pproxy: $!\n"; +	my $ipv4_addr = $1; +	if ($ipv4_addr =~ /:/) { +		my ($a, $b) = split(/:/, $ipv4_addr); +		$a = hex($a); +		$b = hex($b); +		$ipv4_addr  = sprintf("%d.", ($a & 0xff00) >> 8); +		$ipv4_addr .= sprintf("%d.", ($a & 0x00ff)); +		$ipv4_addr .= sprintf("%d.", ($b & 0xff00) >> 8); +		$ipv4_addr .= sprintf("%d",  ($b & 0x00ff)); +	} + +	print STDERR "pproxy: re-trying with ipv4 addr: $ipv4_addr\n"; + +	eval {$sock = IO::Socket::INET->new( +		PeerAddr => $ipv4_addr, +		PeerPort => $proxy_port, +		Proto => "tcp" +	);}; +	$err .= " / $!"; +} + +if (! $sock) { +	unlink($0) if $ENV{PPROXY_REMOVE}; +	pdie "pproxy: $err\n"; +} + +unlink($0) if $ENV{PPROXY_REMOVE}; + +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; +	$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); +} + +sub kill_proxy_pids() { +	if ($ENV{PPROXY_VENCRYPT_VIEWER_BRIDGE}) { +		return; +	} +	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; +		} +	} +} + +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($out); +	close($in); +	print STDERR "pproxy[$$]: finished xfer.\n"; +} + +sub handler { +	print STDERR "pproxy[$$]: got SIGTERM.\n"; +	close $listen_handle if $listen_handle; +	close $sock if $sock; +	exit; +} + +sub xfer_both { +	$child = fork; + +	if (! defined $child) { +		kill_proxy_pids(); +		exit 1; +	} + +	$SIG{TERM} = "handler"; + +	if ($child) { +		if ($listen_handle) { +			print STDERR "pproxy parent[$$]  listen_handle -> socket\n"; +			xfer($listen_handle, $sock); +		} else { +			print STDERR "pproxy parent[$$]  STDIN -> socket\n"; +			xfer(STDIN, $sock); +		} +		select(undef, undef, undef, 0.25); +		if (kill 0, $child) { +			select(undef, undef, undef, 0.9); +			if (kill 0, $child) { +				print STDERR "pproxy[$$]: kill TERM child $child\n"; +				kill "TERM", $child; +			} else { +				print STDERR "pproxy[$$]: child  $child gone.\n"; +			} +		} +	} else { +		select(undef, undef, undef, 0.05); +		if ($listen_handle) { +			print STDERR "pproxy child [$$]  socket -> listen_handle\n"; +			if ($initial_data ne "") { +				my $len = length $initial_data; +				print STDERR "pproxy child [$$]  sending initial_data, length $len\n\n"; +				syswrite($listen_handle, $initial_data, $len); +			} else { +				print STDERR "\n"; +			} +			xfer($sock, $listen_handle); +		} else { +			print STDERR "pproxy child [$$]  socket -> STDOUT\n"; +			if ($initial_data ne "") { +				my $len = length $initial_data; +				print STDERR "pproxy child [$$]  sending initial_data, length $len\n\n"; +				syswrite(STDOUT, $initial_data, $len); +			} else { +				print STDERR "\n"; +			} +			xfer($sock, STDOUT); +		} +		select(undef, undef, undef, 0.25); +		if (kill 0, $parent) { +			select(undef, undef, undef, 0.8); +			if (kill 0, $parent) { +				print STDERR "pproxy[$$]: kill TERM parent $parent\n"; +				kill "TERM", $parent; +			} else { +				print STDERR "pproxy[$$]: parent $parent gone.\n"; +			} +		} +	} + +	kill_proxy_pids(); +} + +xfer_both(); + +exit; + +sub fsleep { +	select(undef, undef, undef, shift); +} + +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,^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+$/) { +			$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 =~ /^ipv6/i) { +		$ENV{PPROXY_SOCKS} = 0; +	} 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) = ($CONNECT, ""); +		if ($h =~ /^(.*):(\d+)$/) { +			$h = $1; +			$p = $2; +		} +		$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} eq "1") { +		# SOCKS4 SOCKS4a +		my ($h, $p) = ($CONNECT, ""); +		if ($h =~ /^(.*):(\d+)$/) { +			$h = $1; +			$p = $2; +		} +		$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_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"; +		$rep .= pack("x") x 250; +		syswrite($sock, $rep, 250); + +		my $rfb = ""; + +		my $ok = 1; +		for (my $i = 0; $i < 12; $i++) { +			my $c; +			last if $ENV{PPROXY_GENERIC_REPEATER}; +			sysread($sock, $c, 1); +			print STDERR $c; +			$rfb .= $c; +		} +		if ($rfb ne "" && $rfb !~ /^RFB 000\.000/) { +			$initial_data = $rfb; +			$rfb =~ s/\n//g; +			print STDERR "detected non-UltraVNC repeater; forwarding \"$rfb\"\nlength: ", length($initial_data), "\n"; +		} +	} 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; +	kill_proxy_pids(); +	exit(1); +} + +sub anontls_handshake { +	my ($vmode, $db) = @_; + +	print STDERR "\nPPROXY: 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 "\nPPROXY: 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"; +	} +	my $nsec; +	my $t1 = gettime(); +	my $t0 = gettime(); + +	syswrite($sock, $viewer_rfb, 12); +	sysread($sock, $nsec, 1); + +	$t1 = gettime(); +	$t1 = sprintf("%.6f", $t1 - $t0); + +	append_handshake("viewer=$viewer_rfb"); +	append_handshake("latency=$t1\n"); + +	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 append_handshake { +	my $str = shift; +	if ($handshake_file) { +		if (open(HSF, ">>$handshake_file")) { +			print HSF $str; +			close HSF; +		} +	} +} + +sub do_vencrypt_viewer_bridge { +	my ($listen, $connect) = @_; +	print STDERR "\npproxy: starting vencrypt_viewer_bridge[$$]: $listen \-> $connect\n"; +	my $db = 0; +	my $backwards = 0; +	if ($listen < 0) { +		$backwards = 1; +		$listen = -$listen; +	} +	if ($handshake_file eq "") { +		die "pproxy: vencrypt_viewer_bridge[$$]: no SSVNC_PREDIGESTED_HANDSHAKE\n"; +	} +	my $listen_sock; +	my $maxtry = 12; +	my $sleep = 5; +	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" +		); +		if (! $listen_sock) { +			if ($i < $maxtry - 1) { +				warn "pproxy: vencrypt_viewer_bridge[$$]: $!\n"; +				warn "Could not listen on port $listen, retrying in $sleep seconds... (Ctrl-C to quit)\n"; +				sleep $sleep; +			} +		} else { +			last; +		} +	} +	if (! $listen_sock) { +		die "pproxy: vencrypt_viewer_bridge[$$]: $!\n"; +	} +	print STDERR "pproxy: vencrypt_viewer_bridge[$$]: listening on port $listen\n\n"; +	my ($viewer_sock, $ip) = $listen_sock->accept(); +	my $err = $!; +	close $listen_sock; +	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"; +	my $server_sock = IO::Socket::INET->new( +		PeerAddr => "127.0.0.1", +		PeerPort => $connect, +		Proto => "tcp" +	); +	print STDERR "vencrypt_viewer_bridge[$$]: server_sock $server_sock\n" if $db; +	if (! $server_sock) { +		my $err = $!; +		die "pproxy: vencrypt_viewer_bridge[$$]: $err\n"; +	} + +	if ($backwards) { +		print STDERR "vencrypt_viewer_bridge[$$]: reversing roles of viewer and server.\n"; +		my $t = $viewer_sock; +		$viewer_sock = $server_sock; +		$server_sock = $t; +	} + +	my %hs = (); +	my $dt = 0.2; +	my $slept = 0.0; +	while ($slept < 20.0) { +		select(undef, undef, undef, $dt); +		$slept += $dt; +		if (-f $handshake_file && open(HSF, "<$handshake_file")) { +			my $done = 0; +			%hs = (); +			my $str = ""; +			while (<HSF>) { +				print STDERR "vencrypt_viewer_bridge[$$]: $_" if $ENV{VENCRYPT_VIEWER_BRIDGE_DEBUG}; +				$str .= "vencrypt_viewer_bridge[$$]: $_"; +				chomp; +				if ($_ eq "done") { +					$done = 1; +				} else { +					my ($k, $v) = split(/=/, $_, 2); +					if ($k ne "" && $v ne "") { +						$hs{$k} = $v; +					} +				} +			} +			close HSF; +			if ($done) { +				print STDERR "\n" . $str; +				last; +			} +		} +	} +	if (! exists $hs{server}) { +		$hs{server} = "RFB 003.008"; +	} +	if (! exists $hs{sectype}) { +		unlink($handshake_file); +		die "pproxy: vencrypt_viewer_bridge[$$]: no sectype.\n"; +	} +	syswrite($viewer_sock, "$hs{server}\n", length($hs{server}) + 1); +	my $viewer_rfb = ""; +	for (my $i = 0; $i < 12; $i++) { +		my $c; +		sysread($viewer_sock, $c, 1); +		$viewer_rfb .= $c; +		print STDERR $c; +	} +	my $viewer_major = 3; +	my $viewer_minor = 8; +	if ($viewer_rfb =~ /RFB (\d+)\.(\d+)/) { +		$viewer_major = $1;	 +		$viewer_minor = $2;	 +	} +	my $u0 = pack("C", 0); +	my $u1 = pack("C", 1); +	my $u2 = pack("C", 2); +	if ($hs{sectype} == $rfbSecTypeAnonTls) { +		unlink($handshake_file); +		print STDERR "\npproxy: vencrypt_viewer_bridge[$$]: rfbSecTypeAnonTls\n"; +		if ($viewer_major > 3 || $viewer_minor >= 7) { +			;	# setup ok, proceed to xfer. +		} else { +			print STDERR "pproxy: vencrypt_viewer_bridge[$$]: faking RFB version 3.3 to viewer.\n"; +			my $n; +			sysread($server_sock, $n, 1); +			$n = unpack("C", $n); +			if ($n == 0) { +				die "pproxy: vencrypt_viewer_bridge[$$]: nsectypes == $n.\n"; +			} +			my %types; +			for (my $i = 0; $i < $n; $i++) { +				my $t; +				sysread($server_sock, $t, 1); +				$t = unpack("C", $t); +				$types{$t} = 1; +			} +			my $use = 1;	# None +			if (exists $types{1}) { +				$use = 1;	# None +			} elsif (exists $types{2}) { +				$use = 2;	# VncAuth +			} else { +				die "pproxy: vencrypt_viewer_bridge[$$]: no valid sectypes" . join(",", keys %types) . "\n"; +			} +				 +			# send 4 bytes sectype to viewer:  +			# (note this should be MSB, network byte order...) +			my $up = pack("C", $use); +			syswrite($viewer_sock, $u0, 1); +			syswrite($viewer_sock, $u0, 1); +			syswrite($viewer_sock, $u0, 1); +			syswrite($viewer_sock, $up, 1); +			# and tell server the one we selected: +			syswrite($server_sock, $up, 1); +			if ($use == 1) { +				# even None has security result, so read it here and discard it. +				my $sr = ""; +				sysread($server_sock, $sr, 4); +			} +		} +	} elsif ($hs{sectype} == $rfbSecTypeVencrypt) { +		print STDERR "\npproxy: vencrypt_viewer_bridge[$$]: rfbSecTypeVencrypt\n"; +		if (! exists $hs{subtype}) { +			unlink($handshake_file); +			die "pproxy: vencrypt_viewer_bridge[$$]: no subtype.\n"; +		} +		my $fake_type = "None"; +		my $plain = 0; +		my $sub_type = $hs{subtype}; +		if ($sub_type == $rfbVencryptTlsNone) { +			$fake_type = "None"; +		} elsif ($sub_type == $rfbVencryptTlsVnc) { +			$fake_type = "VncAuth"; +		} elsif ($sub_type == $rfbVencryptTlsPlain) { +			$fake_type = "None"; +			$plain = 1; +		} elsif ($sub_type == $rfbVencryptX509None) { +			$fake_type = "None"; +		} elsif ($sub_type == $rfbVencryptX509Vnc) { +			$fake_type = "VncAuth"; +		} elsif ($sub_type == $rfbVencryptX509Plain) { +			$fake_type = "None"; +			$plain = 1; +		} +		if ($plain) { +			if (!open(W, ">$handshake_file")) { +				unlink($handshake_file); +				die "pproxy: vencrypt_viewer_bridge[$$]: $handshake_file $!\n"; +			} +			print W <<"END"; + +			proc print_out {} { +				global user pass env + +				if [info exists env(SSVNC_UP_DEBUG)] { +					toplevel .b +					button .b.b -text "user=\$user pass=\$pass" -command {destroy .b} +					pack .b.b +					update +					tkwait window .b +				} +				 +				if [info exists env(SSVNC_UP_FILE)] { +					set fh ""  +					catch {set fh [open \$env(SSVNC_UP_FILE) w]} +					if {\$fh != ""} { +						puts \$fh user=\$user\\npass=\$pass +						flush \$fh +						close \$fh +						return +					} +				} +				puts stdout user=\$user\\npass=\$pass +				flush stdout +			} + +			proc center_win {w} { +				update +				set W [winfo screenwidth  \$w] +				set W [expr \$W + 1] +				wm geometry \$w +\$W+0 +				update +				set x [expr [winfo screenwidth  \$w]/2 - [winfo width  \$w]/2] +				set y [expr [winfo screenheight \$w]/2 - [winfo height \$w]/2] + +				wm geometry \$w +\$x+\$y +				wm deiconify \$w +				update +			} + +			wm withdraw . + +			global env +			set up {} +			if [info exists env(SSVNC_UNIXPW)] { +				set rm 0 +				set up \$env(SSVNC_UNIXPW) +				if [regexp {^rm:} \$up]  { +					set rm 1 +					regsub {^rm:} \$up {} up +				} +				if [file exists \$up] { +					set fh "" +					set f \$up +					catch {set fh [open \$up r]} +					if {\$fh != ""} { +						gets \$fh u	 +						gets \$fh p	 +						close \$fh +						set up "\$u@\$p" +					} +					if {\$rm} { +						catch {file delete \$f} +					} +				} +			} elseif [info exists env(SSVNC_VENCRYPT_USERPASS)] { +				set up \$env(SSVNC_VENCRYPT_USERPASS) +			} +			#puts stderr up=\$up +			if {\$up != ""} { +				if [regexp {@} \$up] { +					global user pass +					set user \$up +					set pass \$up +					regsub {@.*\$}  \$user "" user +					regsub {^[^@]*@} \$pass "" pass +					print_out +					exit +				} +			} + +			wm title . {VeNCrypt Viewer Bridge User/Pass} + +			set user {} +			set pass {} + +			label .l -text {SSVNC VeNCrypt Viewer Bridge} + +			frame .f0 +			frame .f0.fL +			label .f0.fL.la -text {Username: } +			label .f0.fL.lb -text {Password: } + +			pack .f0.fL.la .f0.fL.lb -side top + +			frame .f0.fR +			entry .f0.fR.ea -width 24 -textvariable user +			entry .f0.fR.eb -width 24 -textvariable pass -show * + +			pack .f0.fR.ea .f0.fR.eb -side top -fill x + +			pack .f0.fL -side left +			pack .f0.fR -side right -expand 1 -fill x + +			button .no -text Cancel -command {destroy .} +			button .ok -text Done   -command {print_out; destroy .} + +			center_win . +			pack .l .f0 .no .ok -side top -fill x +			update +			wm deiconify . + +			bind .f0.fR.ea <Return> {focus .f0.fR.eb} +			bind .f0.fR.eb <Return> {print_out; destroy .} +			focus .f0.fR.ea + +			wm resizable . 1 0 +			wm minsize . [winfo reqwidth .] [winfo reqheight .] +END +			close W; + +			#system("cat $handshake_file"); +			my $w = "wish"; +			if ($ENV{WISH}) { +				$w = $ENV{WISH};	 +			} +			print STDERR "pproxy: vencrypt_viewer_bridge[$$]: prompt  VencryptPlain user and passwd.\n"; +			my $res = ""; +			if (`uname` =~ /Darwin/) { +				my $mtmp = `mktemp /tmp/hsup.XXXXXX`; +				chomp $mtmp; +				system("env SSVNC_UP_FILE=$mtmp $w $handshake_file"); +				$res = `cat $mtmp`; +				unlink $mtmp; +			} else { +				$res = `$w $handshake_file`; +			} +			my $user = ""; +			my $pass = ""; +			if ($res =~ /user=(\S*)/) { +				$user = $1; +			} +			if ($res =~ /pass=(\S*)/) { +				$pass = $1; +			} +			print STDERR "pproxy: vencrypt_viewer_bridge[$$]: sending VencryptPlain user and passwd.\n"; +			my $ulen = pack("C", length($user)); +			my $plen = pack("C", length($pass)); +			# (note this should be MSB, network byte order...) +			syswrite($server_sock, $u0, 1); +			syswrite($server_sock, $u0, 1); +			syswrite($server_sock, $u0, 1); +			syswrite($server_sock, $ulen, 1); +			syswrite($server_sock, $u0, 1); +			syswrite($server_sock, $u0, 1); +			syswrite($server_sock, $u0, 1); +			syswrite($server_sock, $plen, 1); +			syswrite($server_sock, $user, length($user)); +			syswrite($server_sock, $pass, length($pass)); +		} +		unlink($handshake_file); + +		my $ft = 0; +		if ($fake_type eq "None") { +			$ft = 1; +		} elsif ($fake_type eq "VncAuth") { +			$ft = 2; +		} else { +			die "pproxy: vencrypt_viewer_bridge[$$]: unknown fake type: $fake_type\n"; +		} +		my $fp = pack("C", $ft); +		if ($viewer_major > 3 || $viewer_minor >= 7) { +			syswrite($viewer_sock, $u1, 1); +			syswrite($viewer_sock, $fp, 1); +			my $cr; +			sysread($viewer_sock, $cr, 1); +			$cr = unpack("C", $cr); +			if ($cr != $ft) { +				die "pproxy: vencrypt_viewer_bridge[$$]: client selected wrong type: $cr / $ft\n"; +			} +		} else { +			print STDERR "pproxy: vencrypt_viewer_bridge[$$]: faking RFB version 3.3 to viewer.\n"; +			# send 4 bytes sect type to viewer:  +			# (note this should be MSB, network byte order...) +			syswrite($viewer_sock, $u0, 1); +			syswrite($viewer_sock, $u0, 1); +			syswrite($viewer_sock, $u0, 1); +			syswrite($viewer_sock, $fp, 1); +			if ($ft == 1) { +				# even None has security result, so read it here and discard it. +				my $sr = ""; +				sysread($server_sock, $sr, 4); +			} +		} +	} + +	$listen_handle = $viewer_sock; +	$sock = $server_sock; + +	xfer_both(); +} +' +	# ' +	# 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() { +	NO_KECHO=1 +	if [ "X$USER" = "Xrunge" -a "X$NO_KECHO" = "X" ]; then +		echo "dbg: $*" +	fi +} + +NHAFL_warning() { +	echo ""  +	echo "** Warning: For the proxy: $proxy"  +	echo "** Warning: the ssh(1) option: $ssh_NHAFL"  +	echo "** Warning: will be used to avoid frequent 'ssh key has changed for localhost'" +	echo "** Warning: dialogs and connection failures (for example, ssh will exit asking" +	echo "** Warning: you to manually remove a key from ~/.ssh/known_hosts.)" +	echo "** Warning: " +	echo "** Warning: This decreases security: a Man-In-The-Middle attack is possible." +	echo "** Warning: 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=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.  That file holds the 'localhost' cert for this specific"  +	echo "** Warning: connection.  This yields a both secure and convenient solution."  +	echo ""  +} + +space_expand() { +	str=`echo "$1" | sed -e 's/%SPACE/ /g' -e 's/%TAB/\t/g'` +	echo "$str" +} + +# handle ssh case: +# +if [ "X$use_ssh" = "X1" ]; then +	# +	# USING SSH +	# +	ssh_port="22" +	ssh_host="$host" +	vnc_host="$localhost" +	ssh_UKHF="" +	localhost_extra="" +	# let user override ssh via $SSH +	ssh=${SSH:-"ssh -x"} + +	sshword=`echo "$ssh" | awk '{print $1}'` +	if [ "X$sshword" != "X" ]; then +		if [ -x "$sshword" ]; then +			: +		elif type "$sshword" > /dev/null 2>&1; then +			: +		else +			echo "" +			echo "*********************************************************" +			echo "** Problem finding the SSH command '$sshword': **" +			echo "" +			type "$sshword" +			echo "" +			echo "** Perhaps you need to install the SSH client package. **" +			echo "*********************************************************" +			echo "" +			sleep 5 +		fi +	fi + +	ssh_NHAFL="-o NoHostAuthenticationForLocalhost=yes" +	if [ "X$SSVNC_SSH_LOCALHOST_AUTH" = "X1" ]; then +		ssh_NHAFL="" +	fi +	if [ "X$SSVNC_KNOWN_HOSTS_FILE" != "X" ]; then +		ssh_NHAFL="" +	 +		ssh_UKHF="-o UserKnownHostsFile=$SSVNC_KNOWN_HOSTS_FILE" +		ssh_args="$ssh_args $ssh_UKHF" +		if [ ! -f "$SSVNC_KNOWN_HOSTS_FILE" ]; then +			touch "$SSVNC_KNOWN_HOSTS_FILE" >/dev/null 2>&1 +		fi +		chmod 600 "$SSVNC_KNOWN_HOSTS_FILE" >/dev/null 2>&1 +	fi +	did_ssh_NHAFL="" + +	if [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" ]; then +		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 + +	ssh_vencrypt_proxy="" +	# We handle vencrypt for SSH+SSL mode. +	if echo "$proxy" | grep 'vencrypt://' > /dev/null; then +		proxynew="" +		for part in `echo "$proxy" | tr ',' ' '` +		do +			if echo "$part" | egrep -i '^vencrypt://' > /dev/null; then +				ssh_vencrypt_proxy=$part +			else +				if [ "X$proxynew" = "X" ]; then +					proxynew="$part" +				else +					proxynew="$proxynew,$part" +				fi +			fi +		done +		proxy=$proxynew +	fi  +	Kecho ssh_vencrypt_proxy=$ssh_vencrypt_proxy + +	# note that user must supply http:// for web proxy in SSH and SSH+SSL. +	# No xxxx:// implies ssh server+port. +	# +	if echo "$proxy" | egrep '(http|https|socks|socks4|socks5)://' > /dev/null; then +		# 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 +			# XXX fix ipv6 ip adder here and below. +			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 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 +			NHAFL_warning +			ssh_args="$ssh_args $ssh_NHAFL" +			did_ssh_NHAFL=1 +		fi +		sleep 1 +		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 +		localhost_extra=".2" +		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` +		if [ "X$ssh_NHAFL" != "X" -a "X$did_ssh_NHAFL" != "X1" ]; then +			NHAFL_warning +			did_ssh_NHAFL=1 +			sleep 1 +		fi +		echo +		echo "Running 1st ssh proxy:" +		ukhf="" +		if [ "X$ssh_UKHF" != "X" ]; then  +			ukhf="$ssh_UKHF$localhost_extra" +		fi +		if echo "$ssh_host1" | grep '%' > /dev/null; then +			uath=`space_expand "$ssh_host1"` +		else +			uath="$ssh_host1" +		fi +		echo "$ssh -f -x $ssh_port1 $targ -e none $ssh_NHAFL $ukhf -L $proxport:$ssh_host2:$ssh_port2 \"$uath\" \"sleep 30\"" +		echo "" +		      $ssh -f -x $ssh_port1 $targ -e none $ssh_NHAFL $ukhf -L $proxport:$ssh_host2:$ssh_port2 "$uath" "sleep 30" +		ssh_args="$ssh_args $ssh_NHAFL" +		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 echo "$ssh_host" | grep '%' > /dev/null; then +		uath=`space_expand "$ssh_host"` +	else +		uath="$ssh_host" +	fi +	if [ "X$SS_VNCVIEWER_SSH_ONLY" != "X" ]; then +		echo "$ssh -x $ssh_port $targ $C $ssh_args \"$uath\" \"$info\"" +		echo "" +		$ssh -x $ssh_port $targ $C $ssh_args "$uath" "$ssh_cmd" +		exit $? + +	elif [ "X$SS_VNCVIEWER_NO_F" != "X" ]; then +		echo "$ssh -x $ssh_port $targ $C $ssh_redir $ssh_args \"$uath\" \"$info\"" +		echo "" +		$ssh -x $ssh_port $targ $C $ssh_redir $ssh_args "$uath" "$ssh_cmd" +		rc=$? + +	elif [ "X$getport" != "X" ]; then +		tport=/tmp/ss_vncviewer_tport${RANDOM}.$$ +		tport=`mytmp "$tport"` +		tport2=/tmp/ss_vncviewer_tport2${RANDOM}.$$ +		tport2=`mytmp "$tport2"` + +		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 "$uath" "sudo id; tty" +				echo "" +			fi +			echo "$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args \"$uath\" \"$info\"" +			echo "" +			$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args "$uath" "$ssh_cmd" > $tport 2> $tport2 +			if [ "X$teeport" = "X1" ]; then +				tail -f $tport  1>&2 & +				tail_pid=$! +				tail -f $tport2 1>&2 & +				tail_pid2=$! +			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 | tr '\r' ' ' | head -n 1 | sed -e 's/PORT=//' -e 's/\r//g' -e 's/ *$//'` +			if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then +				break +			fi +			vnss=`sed -e 's/\r//g' $tport $tport2 | egrep -i '^(New.* desktop is|A VNC server is already running).*:[0-9[0-9]*$' | head -n 1 | awk '{print $NF}'` +			if [ "X$vnss" != "X" ]; then +				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 +					vnss=`sed -e 's/\r//g' $tport | egrep -i '^(New.* desktop is|A VNC server is already running).*:[0-9[0-9]*$' | head -n 1` +					echo "vncserver string: $vnss" 1>&2 +					break +				fi +			fi +			i=`expr $i + 1` +		done + +		echo "found: PORT='$PORT'" 1>&2 +		lh6="" +		if [ "X$SSVNC_PORT_IPV6" != "X" ]; then +			lh6=1 +		elif egrep 'Info: listening on IPv6 only|Info: listening only on IPv6' $tport > /dev/null; then +			lh6=1 +		fi +		if [ "X$lh6" = "X1" ]; then +			echo "set SOCKS5 localhost to ::1" 1>&2 +		fi +		rm -f $tport $tport2 +		if [ "X$rsh" = "X1" ]; then +			rsh_viewer "$@" +			exit $? +		fi +		PPROXY_SOCKS=5 +		if [ "X$SSVNC_SOCKS5" != "X" ]; then +			PPROXY_SOCKS=5 +		elif [ "X$SSVNC_SOCKS4" != "X" ]; then +			PPROXY_SOCKS=1 +		fi +		export PPROXY_SOCKS +		if [ "X$lh6" = "X" ]; then +			host="$localhost" +		else +			host="::1" +		fi +		port="$PORT" +		proxy="$localhost:$use" + +	else +		if [ "X$rsh" != "X1" ]; then +			echo "$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args \"$uath\" \"$info\"" +			echo "" +			$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args "$uath" "$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 \"$uath\" 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 +		if [ "X$SSVNC_EXTRA_COMMAND" != "X" ]; then +			(sh -c "$SSVNC_EXTRA_COMMAND") & +			echo "($SSVNC_EXTRA_COMMAND) &"; echo +		fi +		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 +		if [ "X$ssh_vencrypt_proxy" != "X" ]; then +			ssh_vencrypt_proxy="vencrypt://$host:$port" +			if [ "X$proxy" = "X" ]; then +				proxy=$ssh_vencrypt_proxy +			else +				proxy="$proxy,$ssh_vencrypt_proxy" +			fi +			Kecho "proxy_now=$proxy" +			unset PPROXY_LISTEN +		fi +	fi +fi + +if [ "X$stunnel_set_here" = "X1" -a "X$showcert" = "X" ]; then +	if type $STUNNEL > /dev/null 2>&1; then +		: +	else +		echo "" +		echo "***************************************************************" +		echo "** Problem finding the Stunnel command '$STUNNEL': **" +		echo "" +		type $STUNNEL +		echo "" +		echo "** Perhaps you need to install the stunnel/stunnel4 package. **" +		echo "***************************************************************" +		echo "" +		sleep 5 +	fi +fi + +# 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$SSVNC_STUNNEL_VERIFY3" != "X" ]; then +	verify=`echo "$verify" | sed -e 's/verify = 2/verify = 3/'` +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 + +if [ "X$showcert" = "X1" ]; then +	if [ "X$have_uvnc_dsm_helper_showcert" = "X1" ]; then +		: +	elif [ "X$SSVNC_NO_IPV6_PROXY" != "X" ]; then +		: +	elif [ "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" +	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 & +				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 + +# handle showcert case: +# +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 +		more_sleep=1 +		if uname | grep Linux > /dev/null; then +			if netstat -ant | grep LISTEN | grep "127.0.0.1:$use" > /dev/null; then +				more_sleep="" +			fi +		elif uname | grep SunOS > /dev/null; then +			if netstat -an -f inet -P tcp | grep LISTEN | grep "127.0.0.1.$use" > /dev/null; then +				more_sleep="" +			fi +		elif uname | egrep -i 'bsd|darwin' > /dev/null; then +			if netstat -ant -f inet | grep LISTEN | grep "127.0.0.1.$use" > /dev/null; then +				more_sleep="" +			fi +		fi +		if [ "X$more_sleep" = "X1" ]; then +			sleep 1 +		fi +		host="$localhost" +		port="$use" +	fi +	cipher_args="" +	if [ "X$ciphers" != "X" ]; then +		cipher_args=`echo "$ciphers" | sed -e 's/ciphers=/-cipher /'` +	fi +	if [ "X$have_uvnc_dsm_helper_showcert" = "X1" ]; then +		: +	elif type openssl > /dev/null 2>&1; then +		: +	else +		echo "" +		echo "********************************************************" +		echo "** Problem finding the OpenSSL command 'openssl': **"  +		echo "" +		type openssl 2>&1 +		echo "" +		echo "** Perhaps you need to install the 'openssl' package. **" +		echo "********************************************************" +		echo "" +	fi +	#echo "openssl s_client $cipher_args -connect $host:$port"  +	if [ "X$reverse" = "X" ]; then +		if type host > /dev/null 2>/dev/null; then +			host $host >/dev/null 2>&1 +			host $host >/dev/null 2>&1 +		fi +		timeout=15 +		if [ "X$SSVNC_FETCH_TIMEOUT" != "X" ]; then +			timeout=$SSVNC_FETCH_TIMEOUT +		fi +		if [ "X$have_uvnc_dsm_helper_showcert" = "X1" ]; then +			if type pkill >/dev/null 2>&1; then +				(sleep $timeout; if kill -0 $$; then pkill -TERM -f "ultravnc_dsm_helper.*$host.*$port"; fi) >/dev/null 2>&1 & +			fi +			ultravnc_dsm_helper showcert $host:$port 2>&1 +		else +			if type pkill >/dev/null 2>&1; then +				(sleep $timeout; if kill -0 $$; then pkill -TERM -f "openssl.*s_client.*$host.*$port"; fi) >/dev/null 2>&1 & +			fi +			openssl s_client $cipher_args -prexit -connect $host:$port 2>&1 < /dev/null +		fi +		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 + +		# assume we have perl: +		check_perl perl + +		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 +	if [ "X$SSVNC_SHOWCERT_EXIT_0" = "X1" ]; then +		exit 0 +	else +		exit $rc +	fi +fi + +# handle direct connect case: +# +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 "** WARNING: 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 +			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 +			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$SSVNC_EXTRA_COMMAND" != "X" ]; then +		(sh -c "$SSVNC_EXTRA_COMMAND") & +		echo "($SSVNC_EXTRA_COMMAND) &"; echo +	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 +			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` +			cmd="$SSVNC_ULTRA_DSM $dport $localhost:$use" +			ustr=`echo "$cmd" | sed -e 's/pw=[^ ]*/pw=******/g'` +			echo "Running:" +			echo +			echo "$ustr &" +			echo +			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 +				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 +		if [ "X$PPROXY_LOOP_THYSELF" != "X" ]; then +			rm -f $PPROXY_LOOP_THYSELF +		fi +	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:" +	elif [ "X$STUNNEL_LISTEN" != "X" ]; then +		hloc="$STUNNEL_LISTEN:" +	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 "" +if egrep -i '^[ 	]*(CApath|CAfile) =' "$tmp_cfg" > /dev/null ; then +	: +else +	echo "** WARNING: THE STUNNEL CONFIG HAS NO SERVER CERTIFICATE SPECIFIED       **" +	echo "** WARNING: (the CApath or CAfile stunnel option) THE VNC SERVER WILL    **" +	echo "** WARNING: NOT BE AUTHENTICATED. A MAN-IN-THE-MIDDLE ATTACK IS POSSIBLE **" +	echo "" +fi +sleep 1 + +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 +if [ "X$SSVNC_EXTRA_COMMAND" != "X" ]; then +	(sh -c "$SSVNC_EXTRA_COMMAND") & +	echo "($SSVNC_EXTRA_COMMAND) &"; echo +fi + +if [ "X$reverse" = "X" ]; then +	if [ "X$NEED_VENCRYPT_VIEWER_BRIDGE" = "X1" -a "X$ptmp" != "X" ] ; then +		port1=`expr 5900 + $N`		# stunnel port +		port2=`findfree 5970`		# bridge port (viewer connects to it.) +		N=`expr $port2 - 5900` +		env PPROXY_REMOVE=0 PPROXY_SLEEP=0 PPROXY_VENCRYPT_VIEWER_BRIDGE="$port2,$port1" $ptmp & +		sleep 1 +	fi +	echo "Running viewer:" +	vnc_hp=$localhost:$N +	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 "Running viewer:" +	echo "" +	echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode." +	echo "" +	trap "final" 0 2 15 +	N2=$N +	N2_trim=`echo "$N2" | sed -e 's/://g'` +	if [ $N2_trim -le 200 ]; then +		N2_trim=`expr $N2_trim + 5500` +	fi +	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}'` +			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 +			STUNNEL_MAX_CLIENTS=1; export STUNNEL_MAX_CLIENTS +			if [ "X$NEED_VENCRYPT_VIEWER_BRIDGE" = "X1" -a "X$ptmp" != "X" ] ; then +				port1=`expr 5500 + $N2` +				port2=`findfree 5580` +				N2=`expr $port2 - 5500` +				N2_trim=`echo "$N2" | sed -e 's/://g'` +				if [ $N2_trim -le 200 ]; then +					N2_trim=`expr $N2_trim + 5500` +				fi +				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 +		else +			PPROXY_REVERSE="$localhost:$port"; export PPROXY_REVERSE +			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 +	if [ "X$VNCVIEWER_IS_REALVNC4" = "X1" ]; then +		N2=$N2_trim +	fi +	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 | 
