| #!/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 <[email protected]> |
| # |
| # 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 [email protected]:0 |
| # ss_vncviewer -ssh -sshcmd 'x11vnc -localhost' [email protected]:0 |
| # |
| # ss_vncviewer -ssh -proxy [email protected]:2022 mymachine:0 |
| # ss_vncviewer -ssh -proxy [email protected]: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 [email protected] 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}'` |
| |
| # [email protected]: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 |