diff options
author | Christian Beier <dontmind@freeshell.org> | 2011-11-09 20:00:16 +0100 |
---|---|---|
committer | Christian Beier <dontmind@freeshell.org> | 2011-11-09 20:00:16 +0100 |
commit | faadd484489efddd182d6d0df43d8ecfdbff29ff (patch) | |
tree | 9c098fca3bd1280a2166259650695d172d049aee /classes/ssl | |
parent | 7cb0e4a9a95886300268e1bff1e72b4c18f1b762 (diff) | |
download | libtdevnc-faadd484489efddd182d6d0df43d8ecfdbff29ff.tar.gz libtdevnc-faadd484489efddd182d6d0df43d8ecfdbff29ff.zip |
Rename 'classes' dir to 'webclients'.
Diffstat (limited to 'classes/ssl')
-rw-r--r-- | classes/ssl/Makefile.am | 2 | ||||
-rw-r--r-- | classes/ssl/README | 338 | ||||
-rw-r--r-- | classes/ssl/SignedUltraViewerSSL.jar | bin | 113117 -> 0 bytes | |||
-rw-r--r-- | classes/ssl/SignedVncViewer.jar | bin | 89208 -> 0 bytes | |||
-rw-r--r-- | classes/ssl/UltraViewerSSL.jar | bin | 110040 -> 0 bytes | |||
-rw-r--r-- | classes/ssl/VncViewer.jar | bin | 86228 -> 0 bytes | |||
-rw-r--r-- | classes/ssl/index.vnc | 26 | ||||
-rwxr-xr-x | classes/ssl/onetimekey | 65 | ||||
-rw-r--r-- | classes/ssl/proxy.vnc | 73 | ||||
-rwxr-xr-x | classes/ssl/ss_vncviewer | 3676 | ||||
-rw-r--r-- | classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch | 111 | ||||
-rw-r--r-- | classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch | 2600 | ||||
-rw-r--r-- | classes/ssl/ultra.vnc | 28 | ||||
-rw-r--r-- | classes/ssl/ultraproxy.vnc | 28 | ||||
-rw-r--r-- | classes/ssl/ultrasigned.vnc | 28 | ||||
-rw-r--r-- | classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch | 5494 |
16 files changed, 0 insertions, 12469 deletions
diff --git a/classes/ssl/Makefile.am b/classes/ssl/Makefile.am deleted file mode 100644 index fd1c201..0000000 --- a/classes/ssl/Makefile.am +++ /dev/null @@ -1,2 +0,0 @@ -EXTRA_DIST=VncViewer.jar index.vnc SignedVncViewer.jar proxy.vnc README ss_vncviewer onetimekey UltraViewerSSL.jar SignedUltraViewerSSL.jar ultra.vnc ultrasigned.vnc ultraproxy.vnc - diff --git a/classes/ssl/README b/classes/ssl/README deleted file mode 100644 index b244cf1..0000000 --- a/classes/ssl/README +++ /dev/null @@ -1,338 +0,0 @@ -This directory contains a patched Java applet VNC viewer that is SSL -enabled. - -The patches in the *.patch files are relative to the source tarball: - - tightvnc-1.3dev7_javasrc.tar.gz - -currently (4/06) available here: - - http://prdownloads.sourceforge.net/vnc-tight/tightvnc-1.3dev7_javasrc.tar.gz?download - -It also includes some simple patches to: - - - fix richcursor colors - - - make the Java Applet cursor (not the cursor drawn to the canvas - framebuffer) invisible when it is inside the canvas. - - - allow Tab (and some other) keystrokes to be sent to the vnc - server instead of doing widget traversal. - - -This SSL applet should work with any VNC viewer that has an SSL tunnel in -front of it. It has been tested on x11vnc and using the stunnel tunnel -to other VNC servers. - -By default this Vnc Viewer will only do SSL. To do unencrypted traffic -see the "DisableSSL" applet parameter (e.g. set it to Yes in index.vnc). - -Proxies: they are a general problem with java socket applets (a socket -connection does not go through the proxy). See the info in the proxy.vnc -file for a workaround. It uses SignedVncViewer.jar which is simply -a signed version of VncViewer.jar. The basic idea is the user clicks -"Yes" to trust the applet and then it can connect directly to the proxy -and issue a CONNECT request. - -This applet has been tested on versions 1.4.2 and 1.5.0 of the Sun -Java plugin. It may not work on older releases or different vendor VM's. -Send full Java Console output for failures. - ---------------------------------------------------------------- -Tips: - -When doing single-port proxy connections (e.g. both VNC and HTTPS -thru port 5900) it helps to move through the 'do you trust this site' -dialogs quickly. x11vnc has to wait to see if the traffic is VNC or -HTTP and this can cause timeouts if you don't move thru them quickly. - -You may have to restart your browser completely if it gets into a -weird state. For one case we saw the JVM requesting VncViewer.class -even when no such file exists. - - ---------------------------------------------------------------- -Extras: - -ss_vncviewer (not Java): - - Wrapper script for native VNC viewer to connect to x11vnc in - SSL mode. Script launches stunnel(8) and then connects to it - via localhost which in turn is then redirected to x11vnc via an - SSL tunnel. stunnel(8) must be installed and available in PATH. - - -Running Java SSL VncViewer from the command line: - - From this directory: - - java -cp ./VncViewer.jar VncViewer HOST <thehost> PORT <theport> - - substitute <thehost> and <theport> with the actual values. - You can add any other parameters, e.g.: ignoreProxy yes - ---------------------------------------------------------------- -UltraVNC: - -The UltraVNC java viewer has also been patched to support SSL. Various -bugs in the UltraVNC java viewer were also fixed. This viewer can be -useful because is support UltraVNC filetransfer, and so it works on -Unix, etc. - -UltraViewerSSL.jar -SignedUltraViewerSSL.jar -ultra.vnc -ultraproxy.vnc -ultravnc-102-JavaViewer-ssl-etc.patch - ---------------------------------------------------------------- -Applet Parameters: - -Some additional applet parameters can be set via the URL, e.g. - - http://host:5800/?param=value - http://host:5800/ultra.vnc?param=value - https://host:5900/ultra.vnc?param=value - -etc. If running java from command line as show above, it comes -in as java ... VncViewer param value ... - -There is a limitation with libvncserver that param and value can -only be alphanumeric, underscore, "+" (for space), or "." - -We have added some applet parameters to the stock VNC java -viewers. Here are the applet parameters: - -Both TightVNC and UltraVNC Java viewers: - - HOST - string, default: none. - The Hostname to connect to. - - PORT - number, default: 0 - The VNC server port to connect to. - - Open New Window - yes/no, default: no - Run applet in separate frame. - - Show Controls - yes/no, default: yes - Show Controls button panel. - - Show Offline Desktop - yes/no, default: no - Do we continue showing desktop on remote disconnect? - - Defer screen updates - number, default: 20 - Milliseconds delay - - Defer cursor updates - number, default: 10 - Milliseconds delay - - Defer update requests - number, default: 50 - Milliseconds delay - - PASSWORD - string, default: none - VNC session password in plain text. - - ENCPASSWORD - string, default: none - VNC session password in encrypted in DES with KNOWN FIXED - key. It is a hex string. This is like the ~/.vnc/passwd format. - - - The following are added by x11vnc and/or ssvnc project - - VNCSERVERPORT - number, default: 0 - Like PORT, but if there is a firewall this is the Actual VNC - server port. PORT might be a redir port on the firewall. - - DisableSSL - yes/no, default: no - Do unencrypted connection, no SSL. - - httpsPort - number, default: none - When checking for proxy, use this at the url port number. - - CONNECT - string, default: none - Sets to host:port for the CONNECT line to a Web proxy. - The Web proxy should connect us to it. - - GET - yes/no, default: no - Set to do a special HTTP GET (/request.https.vnc.connection) - to the vnc server that will cause it to switch to VNC instead. - This is to speedup/make more robust, the single port HTTPS and VNC - mode of x11vnc (e.g. both services thru port 5900, etc) - - urlPrefix - string, default: none - set to a string that will be prefixed to all URL's when contacting - the VNC server. Idea is a special proxy will use this to indicate - internal hostname, etc. - - oneTimeKey - string, default: none - set a special hex "key" to correspond to an SSL X.509 cert+key. - See the 'onetimekey' helper script. Can also be PROMPT to prompt - the user to paste the hex key string in. - - This provides a Client-Side cert+key that the client will use to - authenticate itself by SSL To the VNC Server. - - This is to try to work around the problem that the Java applet - cannot keep an SSL keystore on disk, etc. E.g. if they log - into an HTTPS website via password they are authenticated and - encrypted, then the website can safely put oneTimeKey=... on the - URL. The Vncviewer authenticates the VNC server with this key. - - Note that there is currently a problem in that if x11vnc requires - Client Certificates the user cannot download the index.vnc HTML - and VncViewer.jar from the same x11vnc. Those need to come from - a different x11vnc or from a web server. - - Note that the HTTPS website can also put the VNC Password - (e.g. a temporary/one-time one) in the parameter PASSWORD. - The Java Applet will automatically supply this VNC password - instead of prompting. - - serverCert - string, default: none - set a special hex "cert" to correspond to an SSL X.509 cert - See the 'onetimekey -certonly' helper script. - - This provides a Server-Side cert that the client will authenticate - the VNC Server against by SSL. - - This is to try to work around the problem that the Java applet - cannot keep an SSL keystore on disk, etc. E.g. if they log - into an HTTPS website via password they are authenticated and - encrypted, then the website can safely put serverCert=... on the - URL. - - Of course the VNC Server is sending this string to the Java - Applet, so this is only reasonable security if the VNC Viewer - already trusts the HTTPS retrieval of the URL + serverCert param - that it gets. This should be done over HTTPS not HTTP. - - proxyHost - string, default: none - Do not try to guess the proxy's hostname, use the value in - proxyHost. Does not imply forceProxy (below.) - - proxyPort - string, default: none - Do not try to guess the proxy's port number, use the value in - proxyPort. Does not imply forceProxy (below.) - - forceProxy - yes/no, default: no - Assume there is a proxy and force its use. - - If a string other than "yes" or "no" is given, it implies "yes" - and uses the string for proxyHost and proxyPort (see above). - In this case the string must be of the form "hostname+port". - Note that it is "+" and not ":" before the port number. - - ignoreProxy - yes/no, default: no - Don't check for a proxy, assume there is none. - - trustAllVncCerts - yes/no, default: no - Automatically trust any cert received from the VNC server - (obviously this could be dangerous and lead to man in the - middle attack). Do not ask the user to verify any of these - certs from the VNC server. - - trustUrlVncCert - yes/no, default: no - Automatically trust any cert that the web browsers has accepted. - E.g. the user said "Yes" or "Continue" to a web browser dialog - regarding a certificate. If we get the same cert (chain) from - the VNC server we trust it without prompting the user. - - debugCerts - yes/no, default: no - Print out every cert in the Server, TrustUrl, TrustAll chains. - - -TightVNC Java viewer only: - - Offer Relogin - yes/no, default: yes - "Offer Relogin" set to "No" disables "Login again" - - SocketFactory - string, default: none - set Java Socket class factory. - -UltraVNC Java viewer only: - - None. - - The following are added by x11vnc and/or ssvnc project - - ftpDropDown - string, default: none - Sets the file transfer "drives" dropdown to the "." separated - list. Use "+" for space. The default is - - My+Documents.Desktop.Home - - for 3 entries in the dropdown in addition to the "drives" - (e.g. C:\) These items should be expanded properly by the VNC - Server. x11vnc will prepend $HOME to them, which is normally - what one wants. To include a "/" use "_2F_". Another example: - - Home.Desktop.bin_2F_linux - - If an item is prefixed with "TOP_" then the item is inserted at - the top of the drop down rather than being appended to the end. - E.g. to try to initially load the user homedir instead of /: - - TOP_Home.My+Documents.Desktop - - If ftpDropDown is set to the empty string, "", then no special - locations, [Desktop] etc., are placed in the drop down. Only the - ultravnc "drives" will appear. - - ftpOnly - yes/no, default: no - The VNC viewer only shows the filetransfer panel, no desktop - is displayed. - - graftFtp - yes/no, default: no - As ftpOnly, the VNC viewer only shows the filetransfer panel, - no desktop is displayed, however it is "grafted" onto an existing - SSVNC unix vncviewer. The special SSVNC vncviewer merges the two - channels. - - dsmActive - yes/no, default: no - Special usage mode with the SSVNC unix vncviewer. The UltraVNC - DSM encryption is active. Foolishly, UltraVNC DSM encryption - *MODIFIES* the VNC protocol when active (it is not a pure tunnel). - This option indicates to modify the VNC protocol to make this work. - Usually only used with graftFtp and SSVNC unix vncviewer. - - delayAuthPanel - yes/no, default: no - This is another special usage mode with the SSVNC unix vncviewer. - A login panel is delayed (not shown at startup.) Could be useful - for non SSVNC usage too. - - ignoreMSLogonCheck - yes/no, default: no - Similar to delayAuthPanel, do not put up a popup asking for - Windows username, etc. diff --git a/classes/ssl/SignedUltraViewerSSL.jar b/classes/ssl/SignedUltraViewerSSL.jar Binary files differdeleted file mode 100644 index 6c18737..0000000 --- a/classes/ssl/SignedUltraViewerSSL.jar +++ /dev/null diff --git a/classes/ssl/SignedVncViewer.jar b/classes/ssl/SignedVncViewer.jar Binary files differdeleted file mode 100644 index 95c0b0b..0000000 --- a/classes/ssl/SignedVncViewer.jar +++ /dev/null diff --git a/classes/ssl/UltraViewerSSL.jar b/classes/ssl/UltraViewerSSL.jar Binary files differdeleted file mode 100644 index 45259fd..0000000 --- a/classes/ssl/UltraViewerSSL.jar +++ /dev/null diff --git a/classes/ssl/VncViewer.jar b/classes/ssl/VncViewer.jar Binary files differdeleted file mode 100644 index 9453c6f..0000000 --- a/classes/ssl/VncViewer.jar +++ /dev/null diff --git a/classes/ssl/index.vnc b/classes/ssl/index.vnc deleted file mode 100644 index ec520dc..0000000 --- a/classes/ssl/index.vnc +++ /dev/null @@ -1,26 +0,0 @@ -<!-- - index.vnc - default HTML page for TightVNC Java viewer applet, to be - used with Xvnc. On any file ending in .vnc, the HTTP server embedded in - Xvnc will substitute the following variables when preceded by a dollar: - USER, DESKTOP, DISPLAY, APPLETWIDTH, APPLETHEIGHT, WIDTH, HEIGHT, PORT, - PARAMS. Use two dollar signs ($$) to get a dollar sign in the generated - HTML page. - - NOTE: the $PARAMS variable is not supported by the standard VNC, so - make sure you have TightVNC on the server side, if you're using this - variable. ---> - -<HTML> -<TITLE> -$USER's $DESKTOP desktop ($DISPLAY) -</TITLE> -<APPLET CODE=VncViewer.class ARCHIVE=VncViewer.jar - WIDTH=$APPLETWIDTH HEIGHT=$APPLETHEIGHT> -<param name=PORT value=$PORT> -<param name="Open New Window" value=yes> -$PARAMS -</APPLET> -<BR> -<A href="http://www.karlrunge.com/x11vnc">x11vnc site</A> -</HTML> diff --git a/classes/ssl/onetimekey b/classes/ssl/onetimekey deleted file mode 100755 index bf57c8f..0000000 --- a/classes/ssl/onetimekey +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/sh -# -# usage: onetimekey path/to/mycert.pem -# onetimekey -certonly path/to/mycert.pem -# -# Takes an openssl cert+key pem file and turns into a long string -# for the x11vnc SSL VNC Java Viewer. -# -# The Java applet URL parameter can be oneTimeKey=<str> where str is -# the output of this program, or can be oneTimeKey=PROMPT in which -# case the applet will ask you to paste in the string. -# -# The problem trying to be solved here is it is difficult to get -# the Java applet to have or use a keystore with the key saved -# in it. Also, as the name implies, an HTTPS server can create -# a one time key to send to the applet (the user has already -# logged in via password to the HTTPS server). -# -# Note oneTimeKey is to provide a CLIENT Certificate for the viewer -# to authenticate itself to the VNC Server. -# -# There is also the serverCert=<str> Applet parameter. This is -# a cert to authenticate the VNC server against. To create that -# string with this tool specify -certonly as the first argument. - -certonly="" -if [ "X$1" = "X-certonly" ]; then - shift - certonly=1 -fi - -in=$1 -der=/tmp/1time$$.der -touch $der -chmod 600 $der - -openssl pkcs8 -topk8 -nocrypt -in "$in" -out "$der" -outform der - -pbinhex=/tmp/pbinhex.$$ -cat > $pbinhex <<END -#!/usr/bin/perl - -\$str = ''; -while (1) { - \$c = getc(STDIN); - last if \$c eq ''; - \$str .= sprintf("%02x", unpack("C", \$c)); -} - -print "\$str\n"; -END - -chmod 700 $pbinhex - -str1=`$pbinhex < "$der"` -rm -f "$der" - -n=`grep -n 'BEGIN CERTIFICATE' $in | awk -F: '{print $1}' | head -1` -str2=`tail +$n $in | $pbinhex` -if [ "X$certonly" = "X1" ]; then - echo "$str2" -else - echo "$str1,$str2" -fi -rm -f $pbinhex diff --git a/classes/ssl/proxy.vnc b/classes/ssl/proxy.vnc deleted file mode 100644 index 6d3ab3d..0000000 --- a/classes/ssl/proxy.vnc +++ /dev/null @@ -1,73 +0,0 @@ -<!-- - index.vnc - default HTML page for TightVNC Java viewer applet, to be - used with Xvnc. On any file ending in .vnc, the HTTP server embedded in - Xvnc will substitute the following variables when preceded by a dollar: - USER, DESKTOP, DISPLAY, APPLETWIDTH, APPLETHEIGHT, WIDTH, HEIGHT, PORT, - PARAMS. Use two dollar signs ($$) to get a dollar sign in the generated - HTML page. - - NOTE: the $PARAMS variable is not supported by the standard VNC, so - make sure you have TightVNC on the server side, if you're using this - variable. ---> - -<!-- -The idea behind using the signed applet in SignedVncViewer.jar for -firewall proxies: - -Java socket applets and http proxies do not get along well. - -Java security allows the applet to connect back via a socket to the -originating host, but the browser/plugin Proxy settings are not used for -socket connections (only http and the like). So the socket connection -fails in the proxy environment. - -The applet is not allowed to open a socket connection to the proxy (since -that would let it connect to just about any host, e.g. CONNECT method). - -This is indpendent of SSL but of course fails for that socket connection -as well. I.e. this is a problem for non-SSL VNC Viewers as well. - -Solution? Sign the applet and have the user click on "Yes" that they -fully trust the applet. Then the applet can connect to any host via -sockets, in particular the proxy. It next issues the request - - CONNECT host:port HTTP/1.1 - Host: host:port - -and if the proxy supports the CONNECT method we are finally connected to -the VNC server. - -For SSL connections, SSL is layered on top of this socket. However note -this scheme will work for non-SSL applet proxy tunnelling as well. - -It should be able to get non-SSL VNC connections to work via GET -command but that has not been done yet. - -Note that some proxies only allow CONNECT to only these the ports 443 -(HTTPS) and 563 (SNEWS). So you would have to run the VNC server on -those ports. - -SignedVncViewer.jar is just a signed version of VncViewer.jar - -The URL to use for this file: https://host:port/proxy.vnc - -Note VNCSERVERPORT, we assume $PARAMS will have the correct PORT setting -(e.g. 563), not the one libvncserver puts in.... - ---> - - -<HTML> -<TITLE> -$USER's $DESKTOP desktop ($DISPLAY) -</TITLE> -<APPLET CODE=VncViewer.class ARCHIVE=SignedVncViewer.jar - WIDTH=$APPLETWIDTH HEIGHT=$APPLETHEIGHT> -<param name=VNCSERVERPORT value=$PORT> -<param name="Open New Window" value=yes> -$PARAMS -</APPLET> -<BR> -<A href="http://www.karlrunge.com/x11vnc">x11vnc site</A> -</HTML> diff --git a/classes/ssl/ss_vncviewer b/classes/ssl/ss_vncviewer deleted file mode 100755 index 7e793ff..0000000 --- a/classes/ssl/ss_vncviewer +++ /dev/null @@ -1,3676 +0,0 @@ -#!/bin/sh -# -# ss_vncviewer: wrapper for vncviewer to use an stunnel SSL tunnel -# or an SSH tunnel. -# -# Copyright (c) 2006-2009 by Karl J. Runge <runge@karlrunge.com> -# -# ss_vncviewer is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or (at -# your option) any later version. -# -# ss_vncviewer is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ss_vncviewer; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA -# or see <http://www.gnu.org/licenses/>. -# -# -# You must have stunnel(8) installed on the system and in your PATH -# (however, see the -ssh option below, in which case you will need ssh(1) -# installed) Note: stunnel is usually installed in an "sbin" subdirectory. -# -# You should have "x11vnc -ssl ..." or "x11vnc -stunnel ..." -# already running as the VNC server on the remote machine. -# (or use stunnel on the server side for any other VNC server) -# -# -# Usage: ss_vncviewer [cert-args] host:display <vncviewer-args> -# -# e.g.: ss_vncviewer snoopy:0 -# ss_vncviewer snoopy:0 -encodings "copyrect tight zrle hextile" -# -# [cert-args] can be: -# -# -verify /path/to/cacert.pem -# -mycert /path/to/mycert.pem -# -crl /path/to/my_crl.pem (or directory) -# -proxy host:port -# -# -verify specifies a CA cert PEM file (or a self-signed one) for -# authenticating the VNC server. -# -# -mycert specifies this client's cert+key PEM file for the VNC server to -# authenticate this client. -# -# -proxy try host:port as a Web proxy to use the CONNECT method -# to reach the VNC server (e.g. your firewall requires a proxy). -# -# For the "double proxy" case use -proxy host1:port1,host2:port2 -# (the first CONNECT is done through host1:port1 to host2:port2 -# and then a 2nd CONNECT to the destination VNC server.) -# -# Use socks://host:port, socks4://host:port, or socks5://host,port -# to force usage of a SOCKS proxy. Also repeater://host:port and -# sslrepeater://host:port. -# -# -showcert Only fetch the certificate using the 'openssl s_client' -# command (openssl(1) must in installed). On ssvnc 1.0.27 and -# later the bundled command 'ultravnc_dsm_helper' is used. -# -# See http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-ca for details on -# SSL certificates with VNC. -# -# A few other args (not related to SSL and certs): -# -# -2nd Run the vncviewer a 2nd time if the first connections fails. -# -# -ssh Use ssh instead of stunnel SSL. ssh(1) must be installed and you -# must be able to log into the remote machine via ssh. -# -# In this case "host:display" may be of the form "user@host:display" -# where "user@host" is used for the ssh login (see ssh(1) manpage). -# -# If -proxy is supplied it can be of the forms: "gwhost" "gwhost:port" -# "user@gwhost" or "user@gwhost:port". "gwhost" is an incoming ssh -# gateway machine (the VNC server is not running there), an ssh -L -# redir is used to "host" in "host:display" from "gwhost". Any "user@" -# part must be in the -proxy string (not in "host:display"). -# -# Under -proxy use "gwhost:port" if connecting to any ssh port -# other than the default (22). (even for the non-gateway case, -# -proxy must be used to specify a non-standard ssh port) -# -# A "double ssh" can be specified via a -proxy string with the two -# hosts separated by a comma: -# -# [user1@]host1[:port1],[user2@]host2[:port2] -# -# in which case a ssh to host1 and thru it via a -L redir a 2nd -# ssh is established to host2. -# -# Examples: -# -# ss_vncviewer -ssh bob@bobs-home.net:0 -# ss_vncviewer -ssh -sshcmd 'x11vnc -localhost' bob@bobs-home.net:0 -# -# ss_vncviewer -ssh -proxy fred@mygate.com:2022 mymachine:0 -# ss_vncviewer -ssh -proxy bob@bobs-home.net:2222 localhost:0 -# -# ss_vncviewer -ssh -proxy fred@gw-host,fred@peecee localhost:0 -# -# -sshcmd cmd Run "cmd" via ssh instead of the default "sleep 15" -# e.g. -sshcmd 'x11vnc -display :0 -localhost -rfbport 5900' -# -# -sshargs "args" pass "args" to the ssh process, e.g. -L/-R port redirs. -# -# -sshssl Tunnel the SSL connection thru a SSH connection. The tunnel as -# under -ssh is set up and the SSL connection goes thru it. Use -# this if you want to have and end-to-end SSL connection but must -# go thru a SSH gateway host (e.g. not the vnc server). Or use -# this if you need to tunnel additional services via -R and -L -# (see -sshargs above). -# -# ss_vncviewer -sshssl -proxy fred@mygate.com mymachine:0 -# -# -listen (or -reverse) set up a reverse connection. -# -# -alpha turn on cursor alphablending hack if you are using the -# enhanced tightvnc vncviewer. -# -# -grab turn on XGrabServer hack if you are using the enhanced tightvnc -# vncviewer (e.g. for fullscreen mode in some windowmanagers like -# fvwm that do not otherwise work in fullscreen mode) -# -# -# set VNCVIEWERCMD to whatever vncviewer command you want to use. -# -VNCIPCMD=${VNCVIEWERCMD:-vncip} -VNCVIEWERCMD=${VNCVIEWERCMD:-vncviewer} -if [ "X$SSVNC_TURBOVNC" != "X" ]; then - if echo "$VNCVIEWERCMD" | grep '\.turbovnc' > /dev/null; then - : - else - if type "$VNCVIEWERCMD.turbovnc" > /dev/null 2>/dev/null; then - VNCVIEWERCMD="$VNCVIEWERCMD.turbovnc" - fi - fi -fi -# -# Same for STUNNEL, e.g. set it to /path/to/stunnel or stunnel4, etc. -# - -# turn on verbose debugging output -if [ "X$SS_DEBUG" != "X" -a "X$SS_DEBUG" != "X0" ]; then - set -xv -fi - -PATH=$PATH:/usr/sbin:/usr/local/sbin:/dist/sbin; export PATH - -localhost="localhost" -if uname | grep Darwin >/dev/null; then - localhost="127.0.0.1" -fi - -# work out which stunnel to use (debian installs as stunnel4) -stunnel_set_here="" -if [ "X$STUNNEL" = "X" ]; then - check_stunnel=1 - if [ "X$SSVNC_BASEDIRNAME" != "X" ]; then - if [ -x "$SSVNC_BASEDIRNAME/stunnel" ]; then - type stunnel > /dev/null 2>&1 - if [ $? = 0 ]; then - # found ours - STUNNEL=stunnel - check_stunnel=0 - fi - fi - fi - if [ "X$check_stunnel" = "X1" ]; then - type stunnel4 > /dev/null 2>&1 - if [ $? = 0 ]; then - STUNNEL=stunnel4 - else - STUNNEL=stunnel - fi - fi - stunnel_set_here=1 -fi - -help() { - tail -n +2 "$0" | sed -e '/^$/ q' -} - -secondtry="" -gotalpha="" -use_ssh="" -use_sshssl="" -direct_connect="" -ssh_sleep=15 - -# sleep longer in -listen mode: -if echo "$*" | grep '.*-listen' > /dev/null; then - ssh_sleep=1800 -fi - - -ssh_cmd="" -# env override of ssh_cmd: -if [ "X$SS_VNCVIEWER_SSH_CMD" != "X" ]; then - ssh_cmd="$SS_VNCVIEWER_SSH_CMD" -fi - -ssh_args="" -showcert="" -reverse="" - -ciphers="" -anondh="ALL:RC4+RSA:+SSLv2:@STRENGTH" -anondh_set="" -stunnel_debug="6" -if [ "X$SS_DEBUG" != "X" -o "X$SSVNC_VENCRYPT_DEBUG" != "X" -o "X$SSVNC_STUNNEL_DEBUG" != "X" ]; then - stunnel_debug="7" -fi - -if [ "X$1" = "X-viewerflavor" ]; then - # special case, try to guess which viewer: - # - if echo "$VNCVIEWERCMD" | egrep -i '^(xmessage|sleep )' > /dev/null; then - echo "unknown" - exit 0 - fi - if echo "$VNCVIEWERCMD" | grep -i chicken.of > /dev/null; then - echo "cotvnc" - exit 0 - fi - if echo "$VNCVIEWERCMD" | grep -i ultra > /dev/null; then - echo "ultravnc" - exit 0 - fi - # OK, run it for help output... - str=`$VNCVIEWERCMD -h 2>&1 | head -n 5` - if echo "$str" | grep -i 'TightVNC.viewer' > /dev/null; then - echo "tightvnc" - elif echo "$str" | grep -i 'VNC viewer version 3' > /dev/null; then - echo "realvnc3" - elif echo "$str" | grep -i 'VNC viewer .*Edition 4' > /dev/null; then - echo "realvnc4" - elif echo "$str" | grep -i 'RealVNC.Ltd' > /dev/null; then - echo "realvnc4" - else - echo "unknown" - fi - exit 0 -fi -if [ "X$1" = "X-viewerhelp" ]; then - $VNCVIEWERCMD -h 2>&1 - exit 0 -fi - -# grab our cmdline options: -while [ "X$1" != "X" ] -do - case $1 in - "-verify") shift; verify="$1" - ;; - "-mycert") shift; mycert="$1" - ;; - "-crl") shift; crl="$1" - ;; - "-proxy") shift; proxy="$1" - ;; - "-ssh") use_ssh=1 - ;; - "-sshssl") use_ssh=1 - use_sshssl=1 - ;; - "-sshcmd") shift; ssh_cmd="$1" - ;; - "-sshargs") shift; ssh_args="$1" - ;; - "-anondh") ciphers="ciphers=$anondh" - ULTRAVNC_DSM_HELPER_SHOWCERT_ADH=1 - export ULTRAVNC_DSM_HELPER_SHOWCERT_ADH - anondh_set=1 - ;; - "-ciphers") shift; ciphers="ciphers=$1" - ;; - "-alpha") gotalpha=1 - ;; - "-showcert") showcert=1 - ;; - "-listen") reverse=1 - ;; - "-reverse") reverse=1 - ;; - "-2nd") secondtry=1 - ;; - "-grab") VNCVIEWER_GRAB_SERVER=1; export VNCVIEWER_GRAB_SERVER - ;; - "-x11cursor") VNCVIEWER_X11CURSOR=1; export VNCVIEWER_X11CURSOR - ;; - "-rawlocal") VNCVIEWER_RAWLOCAL=1; export VNCVIEWER_RAWLOCAL - ;; - "-scale") shift; SSVNC_SCALE="$1"; export SSVNC_SCALE - ;; - "-onelisten") SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE - ;; - "-sendclipboard") VNCVIEWER_SEND_CLIPBOARD=1; export VNCVIEWER_SEND_CLIPBOARD - ;; - "-sendalways") VNCVIEWER_SEND_ALWAYS=1; export VNCVIEWER_SEND_ALWAYS - ;; - "-recvtext") shift; VNCVIEWER_RECV_TEXT="$1"; export VNCVIEWER_RECV_TEXT - ;; - "-escape") shift; VNCVIEWER_ESCAPE="$1"; export VNCVIEWER_ESCAPE - ;; - "-ssvnc_encodings") shift; VNCVIEWER_ENCODINGS="$1"; export VNCVIEWER_ENCODINGS - ;; - "-ssvnc_extra_opts") shift; VNCVIEWERCMD_EXTRA_OPTS="$1"; export VNCVIEWERCMD_EXTRA_OPTS - ;; - "-rfbversion") shift; VNCVIEWER_RFBVERSION="$1"; export VNCVIEWER_RFBVERSION - ;; - "-nobell") VNCVIEWER_NOBELL=1; export VNCVIEWER_NOBELL - ;; - "-popupfix") VNCVIEWER_POPUP_FIX=1; export VNCVIEWER_POPUP_FIX - ;; - "-realvnc4") VNCVIEWER_IS_REALVNC4=1; export VNCVIEWER_IS_REALVNC4 - ;; - "-h"*) help; exit 0 - ;; - "--h"*) help; exit 0 - ;; - *) break - ;; - esac - shift -done - -# maxconn is something we added to stunnel, this disables it: -if [ "X$SS_VNCVIEWER_NO_MAXCONN" != "X" ]; then - STUNNEL_EXTRA_OPTS=`echo "$STUNNEL_EXTRA_OPTS" | sed -e 's/maxconn/#maxconn/'` -elif echo "$VNCVIEWERCMD" | egrep -i '^(xmessage|sleep )' > /dev/null; then - STUNNEL_EXTRA_OPTS=`echo "$STUNNEL_EXTRA_OPTS" | sed -e 's/maxconn/#maxconn/'` -elif [ "X$reverse" != "X" ]; then - STUNNEL_EXTRA_OPTS=`echo "$STUNNEL_EXTRA_OPTS" | sed -e 's/maxconn/#maxconn/'` -else - # new way (our patches). other than the above, we set these: - if [ "X$SKIP_STUNNEL_ONCE" = "X" ]; then - STUNNEL_ONCE=1; export STUNNEL_ONCE - fi - if [ "X$SKIP_STUNNEL_MAX_CLIENTS" = "X" ]; then - STUNNEL_MAX_CLIENTS=1; export STUNNEL_MAX_CLIENTS - fi -fi -# always set this one: -if [ "X$SKIP_STUNNEL_NO_SYSLOG" = "X" ]; then - STUNNEL_NO_SYSLOG=1; export STUNNEL_NO_SYSLOG -fi - -# this is the -t ssh option (gives better keyboard response thru SSH tunnel) -targ="-t" -if [ "X$SS_VNCVIEWER_NO_T" != "X" ]; then - targ="" -fi - -# set the alpha blending env. hack: -if [ "X$gotalpha" = "X1" ]; then - VNCVIEWER_ALPHABLEND=1 - export VNCVIEWER_ALPHABLEND -else - NO_ALPHABLEND=1 - export NO_ALPHABLEND -fi - -if [ "X$reverse" != "X" ]; then - ssh_sleep=1800 - if [ "X$proxy" != "X" ]; then - # check proxy usage under reverse connection: - if [ "X$use_ssh" = "X" -a "X$use_sshssl" = "X" ]; then - echo "" - if echo "$proxy" | egrep -i "(repeater|vencrypt)://" > /dev/null; then - : - else - echo "*Warning*: SSL -listen and a Web proxy does not make sense." - sleep 2 - fi - elif echo "$proxy" | grep "," > /dev/null; then - : - else - echo "" - echo "*Warning*: -listen and a single proxy/gateway does not make sense." - sleep 2 - fi - - # we now try to PPROXY_LOOP_THYSELF, set this var to disable that. - #SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE - fi -fi -if [ "X$ssh_cmd" = "X" ]; then - # if no remote ssh cmd, sleep a bit: - ssh_cmd="sleep $ssh_sleep" -fi - -# this should be a host:display: -# -orig="$1" -shift - -dL="-L" -if uname -sr | egrep 'SunOS 5\.[5-8]' > /dev/null; then - dL="-h" -fi - -have_uvnc_dsm_helper_showcert="" -if [ "X$showcert" = "X1" -a "X$SSVNC_USE_S_CLIENT" = "X" -a "X$reverse" = "X" ]; then - if type ultravnc_dsm_helper >/dev/null 2>&1; then - if ultravnc_dsm_helper -help 2>&1 | grep -w showcert >/dev/null; then - have_uvnc_dsm_helper_showcert=1 - fi - fi -fi -have_uvnc_dsm_helper_ipv6="" -if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then - if type ultravnc_dsm_helper >/dev/null 2>&1; then - if ultravnc_dsm_helper -help 2>&1 | grep -iw ipv6 >/dev/null; then - have_uvnc_dsm_helper_ipv6=1 - fi - fi -fi - -rchk() { - # a kludge to set $RANDOM if we are not bash: - if [ "X$BASH_VERSION" = "X" ]; then - RANDOM=`date +%S``sh -c 'echo $$'``ps -elf 2>&1 | sum 2>&1 | awk '{print $1}'` - fi -} -rchk - -# a portable, but not absolutely safe, tmp file creator -mytmp() { - tf=$1 - if type mktemp > /dev/null 2>&1; then - # if we have mktemp(1), use it: - tf2="$tf.XXXXXX" - tf2=`mktemp "$tf2"` - if [ "X$tf2" != "X" -a -f "$tf2" ]; then - if [ "X$DEBUG_MKTEMP" != "X" ]; then - echo "mytmp-mktemp: $tf2" 1>&2 - fi - echo "$tf2" - return - fi - fi - # fallback to multiple cmds: - rm -rf "$tf" || exit 1 - if [ -d "$tf" ]; then - echo "tmp file $tf still exists as a directory." - exit 1 - elif [ $dL "$tf" ]; then - echo "tmp file $tf still exists as a symlink." - exit 1 - elif [ -f "$tf" ]; then - echo "tmp file $tf still exists." - exit 1 - fi - touch "$tf" || exit 1 - chmod 600 "$tf" || exit 1 - rchk - if [ "X$DEBUG_MKTEMP" != "X" ]; then - echo "mytmp-touch: $tf" 1>&2 - fi - echo "$tf" -} - -# set up special case of ultravnc single click III mode: -if echo "$proxy" | egrep "^sslrepeater://" > /dev/null; then - pstr=`echo "$proxy" | sed -e 's,sslrepeater://,,'` - pstr1=`echo "$pstr" | sed -e 's/+.*$//'` - pstr2=`echo "$pstr" | sed -e 's/^[^+]*+//'` - SSVNC_REPEATER="SCIII=$pstr2"; export SSVNC_REPEATER - orig=$pstr1 - echo - echo "reset: SSVNC_REPEATER=$SSVNC_REPEATER orig=$orig proxy=''" - proxy="" -fi -if echo "$proxy" | egrep "vencrypt://" > /dev/null; then - vtmp="/tmp/ss_handshake${RANDOM}.$$.txt" - vtmp=`mytmp "$vtmp"` - SSVNC_PREDIGESTED_HANDSHAKE="$vtmp" - export SSVNC_PREDIGESTED_HANDSHAKE - if [ "X$SSVNC_USE_OURS" = "X" ]; then - NEED_VENCRYPT_VIEWER_BRIDGE=1 - fi -fi -if [ "X$SSVNC_USE_OURS" = "X" ]; then - VNCVIEWERCMD_EXTRA_OPTS="" -fi - - -# check -ssh and -mycert/-verify conflict: -if [ "X$use_ssh" = "X1" -a "X$use_sshssl" = "X" ]; then - if [ "X$mycert" != "X" -o "X$verify" != "X" ]; then - echo "-mycert and -verify cannot be used in -ssh mode" - exit 1 - fi -fi - -# direct mode Vnc:// means show no warnings. -# direct mode vnc:// will show warnings. -if echo "$orig" | grep '^V[Nn][Cc]://' > /dev/null; then - SSVNC_NO_ENC_WARN=1 - export SSVNC_NO_ENC_WARN - orig=`echo "$orig" | sed -e 's/^...:/vnc:/'` -fi - -# interprest the pseudo URL proto:// strings: -if echo "$orig" | grep '^vnc://' > /dev/null; then - orig=`echo "$orig" | sed -e 's,vnc://,,'` - verify="" - mycert="" - crl="" - use_ssh="" - use_sshssl="" - direct_connect=1 -elif echo "$orig" | grep '^vncs://' > /dev/null; then - orig=`echo "$orig" | sed -e 's,vncs://,,'` -elif echo "$orig" | grep '^vncssl://' > /dev/null; then - orig=`echo "$orig" | sed -e 's,vncssl://,,'` -elif echo "$orig" | grep '^vnc+ssl://' > /dev/null; then - orig=`echo "$orig" | sed -e 's,vnc.ssl://,,'` -elif echo "$orig" | grep '^vncssh://' > /dev/null; then - orig=`echo "$orig" | sed -e 's,vncssh://,,'` - use_ssh=1 -elif echo "$orig" | grep '^vnc+ssh://' > /dev/null; then - orig=`echo "$orig" | sed -e 's,vnc.ssh://,,'` - use_ssh=1 -fi - -if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then - verify="" - mycert="" - crl="" - use_ssh="" - use_sshssl="" - direct_connect=1 - if echo "$SSVNC_ULTRA_DSM" | grep 'noultra:' > /dev/null; then - SSVNC_NO_ULTRA_DSM=1; export SSVNC_NO_ULTRA_DSM - fi -fi - -# rsh mode is an internal/secret thing only I use. -rsh="" -if echo "$orig" | grep '^rsh://' > /dev/null; then - use_ssh=1 - rsh=1 - orig=`echo "$orig" | sed -e 's,rsh://,,'` -elif echo "$orig" | grep '^rsh:' > /dev/null; then - use_ssh=1 - rsh=1 - orig=`echo "$orig" | sed -e 's,rsh:,,'` -fi - -# play around with host:display port: -if echo "$orig" | grep ':[0-9][0-9]*$' > /dev/null; then - : -else - # add or assume :0 if no ':' - if [ "X$reverse" = "X" ]; then - orig="$orig:0" - elif [ "X$orig" = "X" ]; then - orig=":0" - fi -fi - -# extract host and disp number: - -# try to see if it is ipv6 address: -ipv6=0 -if echo "$orig" | grep '\[' > /dev/null; then - # ipv6 [fe80::219:dbff:fee5:3f92%eth1]:5900 - host=`echo "$orig" | sed -e 's/\].*$//' -e 's/\[//'` - disp=`echo "$orig" | sed -e 's/^.*\]://'` - ipv6=1 -elif echo "$orig" | grep ':..*:' > /dev/null; then - # ipv6 fe80::219:dbff:fee5:3f92%eth1:5900 - host=`echo "$orig" | sed -e 's/:[^:]*$//'` - disp=`echo "$orig" | sed -e 's/^.*://'` - ipv6=1 -else - # regular host:port - host=`echo "$orig" | awk -F: '{print $1}'` - disp=`echo "$orig" | awk -F: '{print $2}'` -fi - -if [ "X$reverse" != "X" -a "X$STUNNEL_LISTEN" = "X" -a "X$host" != "X" ]; then - STUNNEL_LISTEN=$host - echo "set STUNNEL_LISTEN=$STUNNEL_LISTEN" -fi - -if [ "X$host" = "X" ]; then - host=$localhost -fi - -if [ "X$SSVNC_IPV6" = "X0" ]; then - # disable checking for it. - ipv6=0 -#elif [ "X$reverse" != "X" -a "X$ipv6" = "X1" ]; then -# ipv6=0 -elif [ "X$ipv6" = "X1" ]; then - : -elif echo "$host" | grep '^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' > /dev/null; then - : -else - # regular hostname, can't be sure... - gout="" - if type getent > /dev/null 2>/dev/null; then - gout=`getent hosts "$host" 2>/dev/null` - fi - if echo "$gout" | grep ':.*:' > /dev/null; then - if echo "$gout" | grep '^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' > /dev/null; then - : - else - echo "ipv6: "`echo "$gout" | grep ':.*:' | head -n 1` - ipv6=1 - fi - fi - if [ "X$ipv6" = "X0" ]; then - hout="" - if type host > /dev/null 2>/dev/null; then - host "$host" >/dev/null 2>&1 - host "$host" >/dev/null 2>&1 - hout=`host "$host" 2>/dev/null` - fi - if echo "$hout" | grep -i 'has ipv6 address' > /dev/null; then - if echo "$hout" | grep -i 'has address' > /dev/null; then - : - else - echo "ipv6: "`echo "$hout" | grep -i 'has ipv6 address' | head -n 1` - ipv6=1 - fi - fi - fi - if [ "X$ipv6" = "X0" ]; then - dout="" - if type dig > /dev/null 2>/dev/null; then - dout=`dig -t any "$host" 2>/dev/null` - fi - if echo "$dout" | grep -i "^$host" | grep '[ ]AAAA[ ]' > /dev/null; then - if echo "$dout" | grep -i "^$host" | grep '[ ]A[ ]' > /dev/null; then - : - else - echo "ipv6: "`echo "$dout" | grep -i '[ ]AAAA[ ]' | head -n 1` - ipv6=1 - fi - fi - fi - if [ "X$ipv6" = "X0" ]; then - sout=`env LOOKUP="$host" \ - perl -e ' eval {use Socket}; exit 0 if $@; - eval {use Socket6}; exit 0 if $@; - @res = getaddrinfo($ENV{LOOKUP}, "daytime", AF_UNSPEC, SOCK_STREAM); - $ipv4 = 0; - $ipv6 = 0; - $ip6 = ""; - while (scalar(@res) >= 5) { - ($family, $socktype, $proto, $saddr, $canon, @res) = @res; - $ipv4 = 1 if $family == AF_INET; - $ipv6 = 1 if $family == AF_INET6; - if ($family == AF_INET6 && $ip6 eq "") { - my ($host, $port) = getnameinfo($saddr, NI_NUMERICHOST | NI_NUMERICSERV); - $ip6 = $host; - } - } - if (! $ipv4 && $ipv6) { - print "AF_INET6_ONLY: $ENV{LOOKUP}: $ip6\n"; - } - exit 0; - ' 2>/dev/null` - if echo "$sout" | grep AF_INET6_ONLY > /dev/null; then - echo "$sout" - ipv6=1 - fi - fi -fi -if [ "X$ipv6" = "X1" ]; then - echo "ipv6: addr=$host disp=$disp" -fi -if [ "X$disp" = "X" ]; then - port="" # probably -listen mode. -elif [ $disp -lt 0 ]; then - # negative means use |n| without question: - port=`expr 0 - $disp` -elif [ $disp -lt 200 ]; then - # less than 200 means 5900+n - if [ "X$reverse" = "X" ]; then - port=`expr $disp + 5900` - else - port=`expr $disp + 5500` - fi -else - # otherwise use the number directly, e.g. 443, 2345 - port=$disp -fi - -if [ "X$ipv6" = "X1" -a "X$direct_connect" = "X1" ]; then - if [ "X$proxy" = "X" -a "X$reverse" = "X" ]; then - if [ "X$SSVNC_ULTRA_DSM" != "X" -a "X$have_uvnc_dsm_helper_ipv6" = "X1" ]; then - : - elif [ "X$SSVNC_NO_IPV6_PROXY" != "X" ]; then - : - elif [ "X$SSVNC_NO_IPV6_PROXY_DIRECT" != "X" ]; then - : - elif [ "X$SSVNC_USE_OURS" = "X1" ]; then - # requires 1.0.27 and later ssvncviewer binary - : - else - proxy="ipv6://$host:$port" - echo "direct connect: set proxy=$proxy" - fi - fi -fi - -# (possibly) tell the vncviewer to only listen on lo: -if [ "X$reverse" != "X" ]; then - if [ "X$direct_connect" = "X" -o "X$proxy" != "X" -o "X$STUNNEL_LISTEN" != "X" ]; then - VNCVIEWER_LISTEN_LOCALHOST=1 - export VNCVIEWER_LISTEN_LOCALHOST - fi -fi - -# try to find an open listening port via netstat(1): -inuse="" -if uname | grep Linux > /dev/null; then - inuse=`netstat -ant | egrep 'LISTEN|WAIT|ESTABLISH|CLOSE' | awk '{print $4}' | sed 's/^.*://'` -elif uname | grep SunOS > /dev/null; then - inuse=`netstat -an -f inet -P tcp | egrep 'LISTEN|WAIT|ESTABLISH|CLOSE' | awk '{print $1}' | sed 's/^.*\.//'` -elif uname | egrep -i 'bsd|darwin' > /dev/null; then - inuse=`netstat -ant -f inet | egrep 'LISTEN|WAIT|ESTABLISH|CLOSE' | awk '{print $4}' | sed 's/^.*\.//'` -# add others... -fi - -# this is a crude attempt for unique ports tags, etc. -date_sec=`date +%S` - -# these are special cases of no vnc, e.g. sleep or xmessage. -# these are for using ssvnc as a general port redirector. -if echo "$VNCVIEWERCMD" | grep '^sleep[ ][ ]*[0-9][0-9]*' > /dev/null; then - if [ "X$SS_VNCVIEWER_LISTEN_PORT" = "X" ]; then - p=`echo "$VNCVIEWERCMD" | awk '{print $3}'` - if [ "X$p" != "X" ]; then - SS_VNCVIEWER_LISTEN_PORT=$p - fi - fi - p2=`echo "$VNCVIEWERCMD" | awk '{print $2}'` - VNCVIEWERCMD="eval sleep $p2; echo Local " -elif echo "$VNCVIEWERCMD" | grep '^xmessage[ ][ ]*[0-9][0-9]*' > /dev/null; then - if [ "X$SS_VNCVIEWER_LISTEN_PORT" = "X" ]; then - p=`echo "$VNCVIEWERCMD" | awk '{print $2}'` - SS_VNCVIEWER_LISTEN_PORT=$p - fi -fi - -# utility to find a free port to listen on. -findfree() { - try0=$1 - try=$try0 - use0="" - - if [ "X$SS_VNCVIEWER_LISTEN_PORT" != "X" ]; then - echo "$SS_VNCVIEWER_LISTEN_PORT" - return - fi - if [ $try -ge 6000 ]; then - fmax=`expr $try + 1000` - else - fmax=6000 - fi - - while [ $try -lt $fmax ] - do - if [ "X$inuse" = "X" ]; then - break - fi - if echo "$inuse" | grep -w $try > /dev/null; then - : - else - use0=$try - break - fi - try=`expr $try + 1` - done - if [ "X$use0" = "X" ]; then - use0=`expr $date_sec + $try0` - fi - - echo $use0 -} - -# utility for exiting; kills some helper processes, -# removes files, etc. -final() { - echo "" - if [ "X$tmp_cfg" != "X" ]; then - rm -f $tmp_cfg - fi - if [ "X$SS_VNCVIEWER_RM" != "X" ]; then - rm -f $SS_VNCVIEWER_RM 2>/dev/null - fi - if [ "X$tcert" != "X" ]; then - rm -f $tcert - fi - if [ "X$pssh" != "X" ]; then - echo "Terminating background ssh process" - echo kill -TERM "$pssh" - kill -TERM "$pssh" 2>/dev/null - sleep 1 - kill -KILL "$pssh" 2>/dev/null - pssh="" - fi - if [ "X$stunnel_pid" != "X" ]; then - echo "Terminating background stunnel process" - echo kill -TERM "$stunnel_pid" - kill -TERM "$stunnel_pid" 2>/dev/null - sleep 1 - kill -KILL "$stunnel_pid" 2>/dev/null - stunnel_pid="" - fi - if [ "X$dsm_pid" != "X" ]; then - echo "Terminating background ultravnc_dsm_helper process" - echo kill -TERM "$dsm_pid" - kill -TERM "$dsm_pid" 2>/dev/null - sleep 1 - kill -KILL "$dsm_pid" 2>/dev/null - stunnel_pid="" - fi - if [ "X$tail_pid" != "X" ]; then - kill -TERM $tail_pid - fi - if [ "X$tail_pid2" != "X" ]; then - kill -TERM $tail_pid2 - fi -} - -if [ "X$reverse" = "X" ]; then - # normal connections try 5930-5999: - if [ "X$showcert" = "X" ]; then - use=`findfree 5930` - else - # move away from normal place for (possibly many) -showcert - pstart=`date +%S` - pstart=`expr 6130 + $pstart + $pstart` - use=`findfree $pstart` - fi - if [ $use -ge 5900 ]; then - N=`expr $use - 5900` - else - N=$use - fi -else - # reverse connections: - p2=`expr $port + 30` - use=`findfree $p2` - if [ $use -ge 5500 ]; then - N=`expr $use - 5500` - else - N=$use - fi -fi - -# this is for my special use of ss_vncip -> vncip viewer. -if echo "$0" | grep vncip > /dev/null; then - VNCVIEWERCMD="$VNCIPCMD" -fi - -if echo "$VNCVIEWERCMD" | egrep -i '^(xmessage|sleep )' > /dev/null; then - : -elif [ "X$VNCVIEWERCMD_EXTRA_OPTS" != "X" ]; then - VNCVIEWERCMD="$VNCVIEWERCMD $VNCVIEWERCMD_EXTRA_OPTS" -fi - -# trick for the undocumented rsh://host:port method. -rsh_setup() { - if echo "$ssh_host" | grep '@' > /dev/null; then - ul=`echo "$ssh_host" | awk -F@ '{print $1}'` - ul="-l $ul" - ssh_host=`echo "$ssh_host" | awk -F@ '{print $2}'` - else - ul="" - fi - ssh_cmd=`echo "$ssh_cmd" | sed -e 's/ -localhost/ /g'` -} - -# trick for the undocumented rsh://host:port method. -rsh_viewer() { - trap "final" 0 2 15 - if [ "X$PORT" = "X" ]; then - exit 1 - elif [ $PORT -ge 5900 ]; then - vdpy=`expr $PORT - 5900` - else - vdpy=":$PORT" - fi - stty sane - echo "$VNCVIEWERCMD" "$@" $ssh_host:$vdpy - echo "" - $VNCVIEWERCMD "$@" $ssh_host:$vdpy - if [ $? != 0 ]; then - sleep 2 - $VNCVIEWERCMD "$@" $ssh_host:$vdpy - fi -} - -check_perl() { - if type "$1" > /dev/null 2>&1; then - : - elif [ ! -x "$1" ]; then - echo "" - echo "*******************************************************" - echo "** Problem finding the Perl command '$1': **" - echo "" - type "perl" - echo "" - echo "** Perhaps you need to install the Perl package. **" - echo "*******************************************************" - echo "" - sleep 5 - fi -} - -# this is the PPROXY tool. used only here for now... -pcode() { - tf=$1 - PPROXY_PROXY=$proxy; export PPROXY_PROXY - PPROXY_DEST="$host:$port"; export PPROXY_DEST - check_perl /usr/bin/perl - - cod='#!/usr/bin/perl - -# A hack to glue stunnel to a Web or SOCKS proxy, UltraVNC repeater for -# client connections. -# Also acts as a VeNCrypt bridge (by redirecting to stunnel.) - -use IO::Socket::INET; - -my $have_inet6 = ""; -eval "use IO::Socket::INET6;"; -$have_inet6 = 1 if $@ eq ""; - -#my $have_sock6 = ""; -#eval "use Socket; use Socket6;"; -#$have_sock6 = 1 if $@ eq ""; - -if (exists $ENV{PPROXY_LOOP_THYSELF}) { - # used for reverse vnc, run a repeating outer loop. - print STDERR "PPROXY_LOOP: $ENV{PPROXY_LOOP_THYSELF}\n"; - my $rm = $ENV{PPROXY_REMOVE}; - my $lp = $ENV{PPROXY_LOOP_THYSELF}; - delete $ENV{PPROXY_REMOVE}; - delete $ENV{PPROXY_LOOP_THYSELF}; - $ENV{PPROXY_LOOP_THYSELF_MASTER} = $$; - my $pid = $$; - my $dbg = 0; - my $c = 0; - use POSIX ":sys_wait_h"; - while (1) { - $pid = fork(); - last if ! defined $pid; - if ($pid eq "0") { - last; - } - $c++; - print STDERR "\nPPROXY_LOOP: pid=$$ child=$pid count=$c\n"; - while (1) { - waitpid(-1, WNOHANG); - fsleep(0.25); - if (! kill 0, $pid) { - print STDERR "PPROXY_LOOP: child=$pid gone.\n"; - last; - } - print STDERR "PPROXY_LOOP: child=$pid alive.\n" if $dbg; - if (! -f $lp) { - print STDERR "PPROXY_LOOP: flag file $lp gone, killing $pid\n"; - kill TERM, $pid; - fsleep(0.1); - wait; - last; - } - print STDERR "PPROXY_LOOP: file exists $lp\n" if $dbg; - } - last if ! -f $lp; - fsleep(0.25); - } - if ($pid ne "0") { - unlink($0) if $rm; - exit 0; - } -} - -if (exists $ENV{PPROXY_SLEEP} && $ENV{PPROXY_SLEEP} > 0) { - print STDERR "PPROXY_PID: $$\n"; - sleep $ENV{PPROXY_SLEEP}; -} - -foreach my $var (qw( - PPROXY_DEST - PPROXY_KILLPID - PPROXY_LISTEN - PPROXY_PROXY - PPROXY_REMOVE - PPROXY_REPEATER - PPROXY_REVERSE - PPROXY_SLEEP - PPROXY_SOCKS - PPROXY_VENCRYPT - PPROXY_VENCRYPT_VIEWER_BRIDGE - )) { - if (0 || $ENV{SS_DEBUG} || $ENV{SSVNC_VENCRYPT_DEBUG}) { - print STDERR "$var: $ENV{$var}\n"; - } -} - -if ($ENV{PPROXY_SOCKS} ne "" && $ENV{PPROXY_PROXY} !~ m,^socks5?://,i) { - if ($ENV{PPROXY_SOCKS} eq "5") { - $ENV{PPROXY_PROXY} = "socks5://$ENV{PPROXY_PROXY}"; - } else { - $ENV{PPROXY_PROXY} = "socks://$ENV{PPROXY_PROXY}"; - } -} - -my $rfbSecTypeAnonTls = 18; -my $rfbSecTypeVencrypt = 19; - -my $rfbVencryptPlain = 256; -my $rfbVencryptTlsNone = 257; -my $rfbVencryptTlsVnc = 258; -my $rfbVencryptTlsPlain = 259; -my $rfbVencryptX509None = 260; -my $rfbVencryptX509Vnc = 261; -my $rfbVencryptX509Plain = 262; - -my $handshake_file = ""; -if (exists $ENV{SSVNC_PREDIGESTED_HANDSHAKE}) { - $handshake_file = $ENV{SSVNC_PREDIGESTED_HANDSHAKE}; -} - -my $have_gettimeofday = 0; -eval "use Time::HiRes;"; -if ($@ eq "") { - $have_gettimeofday = 1; -} -sub gettime { - my $t = "0.0"; - if ($have_gettimeofday) { - $t = Time::HiRes::gettimeofday(); - } - return $t; -} - -my $listen_handle = ""; -my $sock = ""; -my $parent = $$; - -my $initial_data = ""; - -if ($ENV{PPROXY_VENCRYPT_VIEWER_BRIDGE}) { - my ($from, $to) = split(/,/, $ENV{PPROXY_VENCRYPT_VIEWER_BRIDGE}); - do_vencrypt_viewer_bridge($from, $to); - exit 0; -} - -my ($first, $second, $third) = split(/,/, $ENV{PPROXY_PROXY}, 3); -my ($mode_1st, $mode_2nd, $mode_3rd) = ("", "", ""); - -($first, $mode_1st) = url_parse($first); - -my ($proxy_host, $proxy_port) = ($first, ""); -if ($proxy_host =~ /^(.*):(\d+)$/) { - $proxy_host = $1; - $proxy_port = $2; -} -my $connect = $ENV{PPROXY_DEST}; - -if ($second ne "") { - ($second, $mode_2nd) = url_parse($second); -} - -if ($third ne "") { - ($third, $mode_3rd) = url_parse($third); -} - - -print STDERR "\n"; -print STDERR "PPROXY v0.4: a tool for Web, SOCKS, and UltraVNC proxies and for\n"; -print STDERR "PPROXY v0.4: IPv6 and VNC VeNCrypt bridging.\n"; -print STDERR "proxy_host: $proxy_host\n"; -print STDERR "proxy_port: $proxy_port\n"; -print STDERR "proxy_connect: $connect\n"; -print STDERR "pproxy_params: $ENV{PPROXY_PROXY}\n"; -print STDERR "pproxy_listen: $ENV{PPROXY_LISTEN}\n"; -print STDERR "pproxy_reverse: $ENV{PPROXY_REVERSE}\n"; -print STDERR "io_socket_inet6: $have_inet6\n"; -print STDERR "\n"; -if (! $have_inet6) { - print STDERR "PPROXY: To enable IPv6 connections, install the IO::Socket::INET6 perl module.\n\n"; -} - -if (1) { - print STDERR "pproxy 1st: $first\t- $mode_1st\n"; - print STDERR "pproxy 2nd: $second\t- $mode_2nd\n"; - print STDERR "pproxy 3rd: $third\t- $mode_3rd\n"; - print STDERR "\n"; -} - -sub pdie { - my $msg = shift; - kill_proxy_pids(); - die "$msg"; -} - -if ($ENV{PPROXY_REVERSE} ne "") { - my ($rhost, $rport) = ($ENV{PPROXY_REVERSE}, ""); - if ($rhost =~ /^(.*):(\d+)$/) { - $rhost = $1; - $rport = $2; - } - $rport = 5900 unless $rport; - my $emsg = ""; - $listen_handle = IO::Socket::INET->new( - PeerAddr => $rhost, - PeerPort => $rport, - Proto => "tcp" - ); - $emsg = $!; - if (! $listen_handle && $have_inet6) { - eval {$listen_handle = IO::Socket::INET6->new( - PeerAddr => $rhost, - PeerPort => $rport, - Proto => "tcp" - );}; - $emsg .= " / $!"; - } - if (! $listen_handle) { - pdie "pproxy: $emsg -- PPROXY_REVERSE\n"; - } - print STDERR "PPROXY_REVERSE: connected to $rhost $rport\n"; - -} elsif ($ENV{PPROXY_LISTEN} ne "") { - my $listen_sock = ""; - my $maxtry = 12; - my $sleep = 5; - my $p2 = ""; - my $emsg = ""; - for (my $i=0; $i < $maxtry; $i++) { - my ($if, $p) = ("", $ENV{PPROXY_LISTEN}); - if ($p =~ /^(.*):(\d+)$/) { - $if = $1; - $p = $2; - } - $p2 = "*:$p"; - if ($if eq "") { - $if = "localhost"; - } - print STDERR "pproxy interface: $if\n"; - - $emsg = ""; - if (($if eq "INADDR_ANY6" || $if eq "::") && $have_inet6) { - eval {$listen_sock = IO::Socket::INET6->new( - Listen => 2, - ReuseAddr => 1, - Domain => AF_INET6, - LocalAddr => "::", - LocalPort => $p, - Proto => "tcp" - );}; - $p2 = ":::$p"; - } elsif ($if =~ /^INADDR_ANY/) { - $listen_sock = IO::Socket::INET->new( - Listen => 2, - ReuseAddr => 1, - LocalPort => $p, - Proto => "tcp" - ); - } elsif (($if eq "INADDR_LOOPBACK6" || $if eq "::1") && $have_inet6) { - $p2 = "::1:$p"; - eval {$listen_sock = IO::Socket::INET6->new( - Listen => 2, - ReuseAddr => 1, - Domain => AF_INET6, - LocalAddr => "::1", - LocalPort => $p, - Proto => "tcp" - );}; - $p2 = "::1:$p"; - } else { - $p2 = "$if:$p"; - $listen_sock = IO::Socket::INET->new( - Listen => 2, - ReuseAddr => 1, - LocalAddr => $if, - LocalPort => $p, - Proto => "tcp" - ); - $emsg = $!; - - if (! $listen_sock && $have_inet6) { - print STDERR "PPROXY_LISTEN: retry with INET6\n"; - eval {$listen_sock = IO::Socket::INET6->new( - Listen => 2, - ReuseAddr => 1, - Domain => AF_INET6, - LocalAddr => $if, - LocalPort => $p, - Proto => "tcp" - );}; - $emsg .= " / $!"; - } - } - if (! $listen_sock) { - if ($i < $maxtry - 1) { - warn "pproxy: $emsg $!\n"; - warn "Could not listen on port $p2, retrying in $sleep seconds... (Ctrl-C to quit)\n"; - sleep $sleep; - } - } else { - last; - } - } - if (! $listen_sock) { - pdie "pproxy: $emsg -- PPROXY_LISTEN\n"; - } - print STDERR "pproxy: listening on $p2\n"; - my $ip; - ($listen_handle, $ip) = $listen_sock->accept(); - my $err = $!; - close $listen_sock; - if (! $listen_handle) { - pdie "pproxy: $err\n"; - } - - if ($ENV{PPROXY_LOOP_THYSELF_MASTER}) { - my $sml = $ENV{SSVNC_MULTIPLE_LISTEN}; - if ($sml ne "" && $sml ne "0") { - setpgrp(0, 0); - if (fork()) { - close $viewer_sock; - wait; - exit 0; - } - if (fork()) { - close $viewer_sock; - exit 0; - } - setpgrp(0, 0); - $parent = $$; - } - } -} - -$sock = IO::Socket::INET->new( - PeerAddr => $proxy_host, - PeerPort => $proxy_port, - Proto => "tcp" -); - -my $err = ""; - -if (! $sock && $have_inet6) { - $err = $!; - - print STDERR "pproxy: $!\n"; - - eval {$sock = IO::Socket::INET6->new( - PeerAddr => $proxy_host, - PeerPort => $proxy_port, - Proto => "tcp" - );}; - $err .= " / $!"; -} - -if (! $sock && ($proxy_host =~ /^::ffff:(\d+\.\d+\.\d+\.\d+)$/i || $proxy_host =~ /^::ffff:([\da-f]+:[\da-f]+)$/i)) { - print STDERR "pproxy: $!\n"; - my $ipv4_addr = $1; - if ($ipv4_addr =~ /:/) { - my ($a, $b) = split(/:/, $ipv4_addr); - $a = hex($a); - $b = hex($b); - $ipv4_addr = sprintf("%d.", ($a & 0xff00) >> 8); - $ipv4_addr .= sprintf("%d.", ($a & 0x00ff)); - $ipv4_addr .= sprintf("%d.", ($b & 0xff00) >> 8); - $ipv4_addr .= sprintf("%d", ($b & 0x00ff)); - } - - print STDERR "pproxy: re-trying with ipv4 addr: $ipv4_addr\n"; - - eval {$sock = IO::Socket::INET->new( - PeerAddr => $ipv4_addr, - PeerPort => $proxy_port, - Proto => "tcp" - );}; - $err .= " / $!"; -} - -if (! $sock) { - unlink($0) if $ENV{PPROXY_REMOVE}; - pdie "pproxy: $err\n"; -} - -unlink($0) if $ENV{PPROXY_REMOVE}; - -if ($ENV{PPROXY_PROXY} =~ /^vencrypt:/ && $ENV{PPROXY_VENCRYPT_REVERSE}) { - print STDERR "\nPPROXY: vencrypt+reverse: swapping listen socket with connect socket.\n"; - my $tmp_swap = $sock; - $sock = $listen_handle; - $listen_handle = $tmp_swap; -} - -$cur_proxy = $first; -setmode($mode_1st); - -if ($second ne "") { - connection($second, 1); - - setmode($mode_2nd); - $cur_proxy = $second; - - if ($third ne "") { - connection($third, 2); - setmode($mode_3rd); - $cur_proxy = $third; - connection($connect, 3); - } else { - connection($connect, 2); - } -} else { - connection($connect, 1); -} - -sub kill_proxy_pids() { - if ($ENV{PPROXY_VENCRYPT_VIEWER_BRIDGE}) { - return; - } - if ($ENV{PPROXY_KILLPID}) { - foreach my $p (split(/,/, $ENV{PPROXY_KILLPID})) { - if ($p =~ /^(\+|-)/) { - $p = $parent + $p; - } - print STDERR "kill TERM, $p (PPROXY_KILLPID)\n"; - kill "TERM", $p; - } - } -} - -sub xfer { - my($in, $out) = @_; - $RIN = $WIN = $EIN = ""; - $ROUT = ""; - vec($RIN, fileno($in), 1) = 1; - vec($WIN, fileno($in), 1) = 1; - $EIN = $RIN | $WIN; - - while (1) { - my $nf = 0; - while (! $nf) { - $nf = select($ROUT=$RIN, undef, undef, undef); - } - my $len = sysread($in, $buf, 8192); - if (! defined($len)) { - next if $! =~ /^Interrupted/; - print STDERR "pproxy[$$]: $!\n"; - last; - } elsif ($len == 0) { - print STDERR "pproxy[$$]: Input is EOF.\n"; - last; - } - my $offset = 0; - my $quit = 0; - while ($len) { - my $written = syswrite($out, $buf, $len, $offset); - if (! defined $written) { - print STDERR "pproxy[$$]: Output is EOF. $!\n"; - $quit = 1; - last; - } - $len -= $written; - $offset += $written; - } - last if $quit; - } - close($out); - close($in); - print STDERR "pproxy[$$]: finished xfer.\n"; -} - -sub handler { - print STDERR "pproxy[$$]: got SIGTERM.\n"; - close $listen_handle if $listen_handle; - close $sock if $sock; - exit; -} - -sub xfer_both { - $child = fork; - - if (! defined $child) { - kill_proxy_pids(); - exit 1; - } - - $SIG{TERM} = "handler"; - - if ($child) { - if ($listen_handle) { - print STDERR "pproxy parent[$$] listen_handle -> socket\n"; - xfer($listen_handle, $sock); - } else { - print STDERR "pproxy parent[$$] STDIN -> socket\n"; - xfer(STDIN, $sock); - } - select(undef, undef, undef, 0.25); - if (kill 0, $child) { - select(undef, undef, undef, 0.9); - if (kill 0, $child) { - print STDERR "pproxy[$$]: kill TERM child $child\n"; - kill "TERM", $child; - } else { - print STDERR "pproxy[$$]: child $child gone.\n"; - } - } - } else { - select(undef, undef, undef, 0.05); - if ($listen_handle) { - print STDERR "pproxy child [$$] socket -> listen_handle\n"; - if ($initial_data ne "") { - my $len = length $initial_data; - print STDERR "pproxy child [$$] sending initial_data, length $len\n\n"; - syswrite($listen_handle, $initial_data, $len); - } else { - print STDERR "\n"; - } - xfer($sock, $listen_handle); - } else { - print STDERR "pproxy child [$$] socket -> STDOUT\n"; - if ($initial_data ne "") { - my $len = length $initial_data; - print STDERR "pproxy child [$$] sending initial_data, length $len\n\n"; - syswrite(STDOUT, $initial_data, $len); - } else { - print STDERR "\n"; - } - xfer($sock, STDOUT); - } - select(undef, undef, undef, 0.25); - if (kill 0, $parent) { - select(undef, undef, undef, 0.8); - if (kill 0, $parent) { - print STDERR "pproxy[$$]: kill TERM parent $parent\n"; - kill "TERM", $parent; - } else { - print STDERR "pproxy[$$]: parent $parent gone.\n"; - } - } - } - - kill_proxy_pids(); -} - -xfer_both(); - -exit; - -sub fsleep { - select(undef, undef, undef, shift); -} - -sub url_parse { - my $hostport = shift; - my $mode = "http"; - if ($hostport =~ m,^socks4?://(\S*)$,i) { - $mode = "socks4"; - $hostport = $1; - } elsif ($hostport =~ m,^socks5://(\S*)$,i) { - $mode = "socks5"; - $hostport = $1; - } elsif ($hostport =~ m,^https?://(\S*)$,i) { - $mode = "http"; - $hostport = $1; - } elsif ($hostport =~ m,^ipv6://(\S*)$,i) { - $mode = "ipv6"; - $hostport = $1; - } elsif ($hostport =~ m,^repeater://(\S*)\+(\S*)$,i) { - # ultravnc repeater proxy. - $hostport = $1; - $mode = "repeater:$2"; - if ($hostport !~ /:\d+$/) { - $hostport .= ":5900"; - } - } elsif ($hostport =~ m,^vencrypt://(\S*)$,i) { - # vencrypt handshake. - $hostport = $1; - my $m = "connect"; - if ($hostpost =~ /^(\S+)\+(\S+)$/) { - $hostport = $1; - $mode = $2; - } - $mode = "vencrypt:$m"; - if ($hostport !~ /:\d+$/) { - $hostport .= ":5900"; - } - } - return ($hostport, $mode); -} - -sub setmode { - my $mode = shift; - $ENV{PPROXY_REPEATER} = ""; - $ENV{PPROXY_VENCRYPT} = ""; - if ($mode =~ /^socks/) { - if ($mode =~ /^socks5/) { - $ENV{PPROXY_SOCKS} = 5; - } else { - $ENV{PPROXY_SOCKS} = 1; - } - } elsif ($mode =~ /^ipv6/i) { - $ENV{PPROXY_SOCKS} = 0; - } elsif ($mode =~ /^repeater:(.*)/) { - $ENV{PPROXY_REPEATER} = $1; - $ENV{PPROXY_SOCKS} = ""; - } elsif ($mode =~ /^vencrypt:(.*)/) { - $ENV{PPROXY_VENCRYPT} = $1; - $ENV{PPROXY_SOCKS} = ""; - } else { - $ENV{PPROXY_SOCKS} = ""; - } -} - -sub connection { - my ($CONNECT, $w) = @_; - - my $con = ""; - my $msg = ""; - - if ($ENV{PPROXY_SOCKS} eq "5") { - # SOCKS5 - my ($h, $p) = ($CONNECT, ""); - if ($h =~ /^(.*):(\d+)$/) { - $h = $1; - $p = $2; - } - $con .= pack("C", 0x05); - $con .= pack("C", 0x01); - $con .= pack("C", 0x00); - - $msg = "SOCKS5 via $cur_proxy to $h:$p\n\n"; - print STDERR "proxy_request$w: $msg"; - - syswrite($sock, $con, length($con)); - - my ($n1, $n2, $n3, $n4, $n5, $n6); - my ($r1, $r2, $r3, $r4, $r5, $r6); - my ($s1, $s2, $s3, $s4, $s5, $s6); - - $n1 = sysread($sock, $r1, 1); - $n2 = sysread($sock, $r2, 1); - - $s1 = unpack("C", $r1); - $s2 = unpack("C", $r2); - if ($s1 != 0x05 || $s2 != 0x00) { - print STDERR "SOCKS5 fail s1=$s1 s2=$s2 n1=$n1 n2=$n2\n"; - close $sock; - exit(1); - } - - $con = ""; - $con .= pack("C", 0x05); - $con .= pack("C", 0x01); - $con .= pack("C", 0x00); - $con .= pack("C", 0x03); - $con .= pack("C", length($h)); - $con .= $h; - $con .= pack("C", $p >> 8); - $con .= pack("C", $p & 0xff); - - syswrite($sock, $con, length($con)); - - $n1 = sysread($sock, $r1, 1); - $n2 = sysread($sock, $r2, 1); - $n3 = sysread($sock, $r3, 1); - $n4 = sysread($sock, $r4, 1); - $s1 = unpack("C", $r1); - $s2 = unpack("C", $r2); - $s3 = unpack("C", $r3); - $s4 = unpack("C", $r4); - - if ($s4 == 0x1) { - sysread($sock, $r5, 4 + 2); - } elsif ($s4 == 0x3) { - sysread($sock, $r5, 1); - $s5 = unpack("C", $r5); - sysread($sock, $r6, $s5 + 2); - } elsif ($s4 == 0x4) { - sysread($sock, $r5, 16 + 2); - } - - if ($s1 != 0x5 || $s2 != 0x0 || $s3 != 0x0) { - print STDERR "SOCKS5 failed: s1=$s1 s2=$s2 s3=$s3 s4=$s4 n1=$n1 n2=$n2 n3=$n3 n4=$n4\n"; - close $sock; - exit(1); - } - - } elsif ($ENV{PPROXY_SOCKS} eq "1") { - # SOCKS4 SOCKS4a - my ($h, $p) = ($CONNECT, ""); - if ($h =~ /^(.*):(\d+)$/) { - $h = $1; - $p = $2; - } - $con .= pack("C", 0x04); - $con .= pack("C", 0x01); - $con .= pack("n", $p); - - my $SOCKS_4a = 0; - if ($h eq "localhost" || $h eq "127.0.0.1") { - $con .= pack("C", 127); - $con .= pack("C", 0); - $con .= pack("C", 0); - $con .= pack("C", 1); - } elsif ($h =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) { - $con .= pack("C", $1); - $con .= pack("C", $2); - $con .= pack("C", $3); - $con .= pack("C", $4); - } else { - $con .= pack("C", 0); - $con .= pack("C", 0); - $con .= pack("C", 0); - $con .= pack("C", 3); - $SOCKS_4a = 1; - } - - $con .= "nobody"; - $con .= pack("C", 0); - - $msg = "SOCKS4 via $cur_proxy to $h:$p\n\n"; - if ($SOCKS_4a) { - $con .= $h; - $con .= pack("C", 0); - $msg =~ s/SOCKS4/SOCKS4a/; - } - print STDERR "proxy_request$w: $msg"; - syswrite($sock, $con, length($con)); - - my $ok = 1; - for (my $i = 0; $i < 8; $i++) { - my $c; - sysread($sock, $c, 1); - my $s = unpack("C", $c); - if ($i == 0) { - $ok = 0 if $s != 0x0; - } elsif ($i == 1) { - $ok = 0 if $s != 0x5a; - } - } - if (! $ok) { - print STDERR "SOCKS4 failed.\n"; - close $sock; - exit(1); - } - } elsif ($ENV{PPROXY_SOCKS} eq "0") { - # hack for ipv6 "proxy", nothing to do, assume INET6 call worked. - ; - } elsif ($ENV{PPROXY_REPEATER} ne "") { - my $rep = $ENV{PPROXY_REPEATER}; - print STDERR "repeater: $rep\n"; - $rep .= pack("x") x 250; - syswrite($sock, $rep, 250); - - my $rfb = ""; - - my $ok = 1; - for (my $i = 0; $i < 12; $i++) { - my $c; - last if $ENV{PPROXY_GENERIC_REPEATER}; - sysread($sock, $c, 1); - print STDERR $c; - $rfb .= $c; - } - if ($rfb ne "" && $rfb !~ /^RFB 000\.000/) { - $initial_data = $rfb; - $rfb =~ s/\n//g; - print STDERR "detected non-UltraVNC repeater; forwarding \"$rfb\"\nlength: ", length($initial_data), "\n"; - } - } elsif ($ENV{PPROXY_VENCRYPT} ne "") { - my $vencrypt = $ENV{PPROXY_VENCRYPT}; - vencrypt_dialog($vencrypt); - - } else { - # Web Proxy: - $con = "CONNECT $CONNECT HTTP/1.1\r\n"; - $con .= "Host: $CONNECT\r\n"; - $con .= "Connection: close\r\n\r\n"; - $msg = $con; - - print STDERR "proxy_request$w: via $cur_proxy:\n$msg"; - syswrite($sock, $con, length($con)); - - my $rep = ""; - my $n = 0; - while ($rep !~ /\r\n\r\n/ && $n < 30000) { - my $c; - sysread($sock, $c, 1); - print STDERR $c; - $rep .= $c; - $n++; - } - if ($rep !~ m,HTTP/.* 200,) { - print STDERR "HTTP CONNECT failed.\n"; - close $sock; - exit(1); - } - } -} - -sub vdie { - append_handshake("done\n"); - close $sock; - kill_proxy_pids(); - exit(1); -} - -sub anontls_handshake { - my ($vmode, $db) = @_; - - print STDERR "\nPPROXY: Doing ANONTLS Handshake\n"; - - my $psec = pack("C", $rfbSecTypeAnonTls); - syswrite($sock, $psec, 1); - - append_handshake("done\n"); -} - -sub vencrypt_handshake { - - my ($vmode, $db) = @_; - - print STDERR "\nPPROXY: Doing VeNCrypt Handshake\n"; - - my $psec = pack("C", $rfbSecTypeVencrypt); - - if (exists $ENV{SSVNC_TEST_SEC_TYPE}) { - my $fake = $ENV{SSVNC_TEST_SEC_TYPE}; - print STDERR "PPROXY: sending sec-type: $fake\n"; - $psec = pack("C", $fake); - } - - syswrite($sock, $psec, 1); - - my $vmajor; - my $vminor; - sysread($sock, $vmajor, 1); - sysread($sock, $vminor, 1); - - vdie if $vmajor eq "" || $vminor eq ""; - - $vmajor = unpack("C", $vmajor); - $vminor = unpack("C", $vminor); - print STDERR "server vencrypt version $vmajor.$vminor\n" if $db; - - if (exists $ENV{SSVNC_TEST_SEC_TYPE}) { - print STDERR "PPROXY: continuing on in test mode.\n"; - } else { - vdie if $vmajor ne 0; - vdie if $vminor < 2; - } - - $vmajor = pack("C", 0); - $vminor = pack("C", 2); - append_handshake("subversion=0.2\n"); - - syswrite($sock, $vmajor, 1); - syswrite($sock, $vminor, 1); - - my $result; - sysread($sock, $result, 1); - print STDERR "result empty\n" if $db && $result eq ""; - - vdie if $result eq ""; - $result = unpack("C", $result); - print STDERR "result=$result\n" if $db; - - vdie if $result ne 0; - - my $nsubtypes; - sysread($sock, $nsubtypes, 1); - - vdie if $nsubtypes eq ""; - $nsubtypes = unpack("C", $nsubtypes); - print STDERR "nsubtypes=$nsubtypes\n" if $db; - - my %subtypes; - - for (my $i = 0; $i < $nsubtypes; $i++) { - my $subtype = ""; - sysread($sock, $subtype, 4); - vdie if length($subtype) != 4; - - # XXX fix 64bit. - $subtype = unpack("N", $subtype); - print STDERR "subtype: $subtype\n" if $db; - $subtypes{$subtype} = 1; - append_handshake("sst$i=$subtype\n"); - } - - my $subtype = 0; - if (exists $subtypes{$rfbVencryptX509None}) { - $subtype = $rfbVencryptX509None; - print STDERR "selected rfbVencryptX509None\n" if $db; - } elsif (exists $subtypes{$rfbVencryptX509Vnc}) { - $subtype = $rfbVencryptX509Vnc; - print STDERR "selected rfbVencryptX509Vnc\n" if $db; - } elsif (exists $subtypes{$rfbVencryptX509Plain}) { - $subtype = $rfbVencryptX509Plain; - print STDERR "selected rfbVencryptX509Plain\n" if $db; - } elsif (exists $subtypes{$rfbVencryptTlsNone}) { - $subtype = $rfbVencryptTlsNone; - print STDERR "selected rfbVencryptTlsNone\n" if $db; - } elsif (exists $subtypes{$rfbVencryptTlsVnc}) { - $subtype = $rfbVencryptTlsVnc; - print STDERR "selected rfbVencryptTlsVnc\n" if $db; - } elsif (exists $subtypes{$rfbVencryptTlsPlain}) { - $subtype = $rfbVencryptTlsPlain; - print STDERR "selected rfbVencryptTlsPlain\n" if $db; - } - - if (exists $ENV{SSVNC_TEST_SEC_SUBTYPE}) { - my $fake = $ENV{SSVNC_TEST_SEC_SUBTYPE}; - print STDERR "PPROXY: sending sec-subtype: $fake\n"; - $subtype = $fake; - } - - append_handshake("subtype=$subtype\n"); - - my $pst = pack("N", $subtype); - syswrite($sock, $pst, 4); - - if (exists $ENV{SSVNC_TEST_SEC_SUBTYPE}) { - print STDERR "PPROXY: continuing on in test mode.\n"; - } else { - vdie if $subtype == 0; - } - - my $ok; - sysread($sock, $ok, 1); - $ok = unpack("C", $ok); - print STDERR "ok=$ok\n" if $db; - - append_handshake("done\n"); - - vdie if $ok == 0; -} - -sub vencrypt_dialog { - my $vmode = shift; - my $db = 0; - - $db = 1 if exists $ENV{SS_DEBUG}; - $db = 1 if exists $ENV{SSVNC_VENCRYPT_DEBUG}; - - append_handshake("mode=$vmode\n"); - - my $server_rfb = ""; - #syswrite($sock, $rep, 250); - for (my $i = 0; $i < 12; $i++) { - my $c; - sysread($sock, $c, 1); - $server_rfb .= $c; - print STDERR $c; - } - print STDERR "server_rfb: $server_rfb\n" if $db; - append_handshake("server=$server_rfb"); - - my $minor = ""; - if ($server_rfb =~ /^RFB 003\.(\d+)/) { - $minor = $1; - } else { - vdie; - } - my $viewer_rfb = "RFB 003.008\n"; - if ($minor < 7) { - vdie; - } elsif ($minor == 7) { - $viewer_rfb = "RFB 003.007\n"; - } - my $nsec; - my $t1 = gettime(); - my $t0 = gettime(); - - syswrite($sock, $viewer_rfb, 12); - sysread($sock, $nsec, 1); - - $t1 = gettime(); - $t1 = sprintf("%.6f", $t1 - $t0); - - append_handshake("viewer=$viewer_rfb"); - append_handshake("latency=$t1\n"); - - vdie if $nsec eq ""; - - $nsec = unpack("C", $nsec); - - print STDERR "nsec: $nsec\n" if $db; - vdie if $nsec eq 0 || $nsec > 100; - - my %sectypes = (); - - for (my $i = 0; $i < $nsec; $i++) { - my $sec; - sysread($sock, $sec, 1); - vdie if $sec eq ""; - $sec = unpack("C", $sec); - print STDERR "sec: $sec\n" if $db; - $sectypes{$sec} = 1; - } - - if (exists $sectypes{$rfbSecTypeVencrypt}) { - print STDERR "found rfbSecTypeVencrypt\n" if $db; - append_handshake("sectype=$rfbSecTypeVencrypt\n"); - vencrypt_handshake($vmode, $db); - } elsif (exists $sectypes{$rfbSecTypeAnonTls}) { - print STDERR "found rfbSecTypeAnonTls\n" if $db; - append_handshake("sectype=$rfbSecTypeAnonTls\n"); - anontls_handshake($vmode, $db); - } else { - print STDERR "No supported sec-type found\n" if $db; - vdie; - } -} - -sub append_handshake { - my $str = shift; - if ($handshake_file) { - if (open(HSF, ">>$handshake_file")) { - print HSF $str; - close HSF; - } - } -} - -sub do_vencrypt_viewer_bridge { - my ($listen, $connect) = @_; - print STDERR "\npproxy: starting vencrypt_viewer_bridge[$$]: $listen \-> $connect\n"; - my $db = 0; - my $backwards = 0; - if ($listen < 0) { - $backwards = 1; - $listen = -$listen; - } - if ($handshake_file eq "") { - die "pproxy: vencrypt_viewer_bridge[$$]: no SSVNC_PREDIGESTED_HANDSHAKE\n"; - } - my $listen_sock; - my $maxtry = 12; - my $sleep = 5; - for (my $i=0; $i < $maxtry; $i++) { - $listen_sock = IO::Socket::INET->new( - Listen => 2, - ReuseAddr => 1, - LocalAddr => "127.0.0.1", - LocalPort => $listen, - Proto => "tcp" - ); - if (! $listen_sock) { - if ($i < $maxtry - 1) { - warn "pproxy: vencrypt_viewer_bridge[$$]: $!\n"; - warn "Could not listen on port $listen, retrying in $sleep seconds... (Ctrl-C to quit)\n"; - sleep $sleep; - } - } else { - last; - } - } - if (! $listen_sock) { - die "pproxy: vencrypt_viewer_bridge[$$]: $!\n"; - } - print STDERR "pproxy: vencrypt_viewer_bridge[$$]: listening on port $listen\n\n"; - my ($viewer_sock, $ip) = $listen_sock->accept(); - my $err = $!; - close $listen_sock; - if (! $viewer_sock) { - die "pproxy: vencrypt_viewer_bridge[$$]: $err\n"; - } - if ($ENV{PPROXY_LOOP_THYSELF_MASTER}) { - my $sml = $ENV{SSVNC_MULTIPLE_LISTEN}; - if ($sml ne "" && $sml ne "0") { - setpgrp(0, 0); - if (fork()) { - close $viewer_sock; - wait; - exit 0; - } - if (fork()) { - close $viewer_sock; - exit 0; - } - setpgrp(0, 0); - $parent = $$; - } - } - print STDERR "vencrypt_viewer_bridge[$$]: viewer_sock $viewer_sock\n" if $db; - - print STDERR "pproxy: vencrypt_viewer_bridge[$$]: connecting to 127.0.0.1:$connect\n"; - my $server_sock = IO::Socket::INET->new( - PeerAddr => "127.0.0.1", - PeerPort => $connect, - Proto => "tcp" - ); - print STDERR "vencrypt_viewer_bridge[$$]: server_sock $server_sock\n" if $db; - if (! $server_sock) { - my $err = $!; - die "pproxy: vencrypt_viewer_bridge[$$]: $err\n"; - } - - if ($backwards) { - print STDERR "vencrypt_viewer_bridge[$$]: reversing roles of viewer and server.\n"; - my $t = $viewer_sock; - $viewer_sock = $server_sock; - $server_sock = $t; - } - - my %hs = (); - my $dt = 0.2; - my $slept = 0.0; - while ($slept < 20.0) { - select(undef, undef, undef, $dt); - $slept += $dt; - if (-f $handshake_file && open(HSF, "<$handshake_file")) { - my $done = 0; - %hs = (); - my $str = ""; - while (<HSF>) { - print STDERR "vencrypt_viewer_bridge[$$]: $_" if $ENV{VENCRYPT_VIEWER_BRIDGE_DEBUG}; - $str .= "vencrypt_viewer_bridge[$$]: $_"; - chomp; - if ($_ eq "done") { - $done = 1; - } else { - my ($k, $v) = split(/=/, $_, 2); - if ($k ne "" && $v ne "") { - $hs{$k} = $v; - } - } - } - close HSF; - if ($done) { - print STDERR "\n" . $str; - last; - } - } - } - if (! exists $hs{server}) { - $hs{server} = "RFB 003.008"; - } - if (! exists $hs{sectype}) { - unlink($handshake_file); - die "pproxy: vencrypt_viewer_bridge[$$]: no sectype.\n"; - } - syswrite($viewer_sock, "$hs{server}\n", length($hs{server}) + 1); - my $viewer_rfb = ""; - for (my $i = 0; $i < 12; $i++) { - my $c; - sysread($viewer_sock, $c, 1); - $viewer_rfb .= $c; - print STDERR $c; - } - my $viewer_major = 3; - my $viewer_minor = 8; - if ($viewer_rfb =~ /RFB (\d+)\.(\d+)/) { - $viewer_major = $1; - $viewer_minor = $2; - } - my $u0 = pack("C", 0); - my $u1 = pack("C", 1); - my $u2 = pack("C", 2); - if ($hs{sectype} == $rfbSecTypeAnonTls) { - unlink($handshake_file); - print STDERR "\npproxy: vencrypt_viewer_bridge[$$]: rfbSecTypeAnonTls\n"; - if ($viewer_major > 3 || $viewer_minor >= 7) { - ; # setup ok, proceed to xfer. - } else { - print STDERR "pproxy: vencrypt_viewer_bridge[$$]: faking RFB version 3.3 to viewer.\n"; - my $n; - sysread($server_sock, $n, 1); - $n = unpack("C", $n); - if ($n == 0) { - die "pproxy: vencrypt_viewer_bridge[$$]: nsectypes == $n.\n"; - } - my %types; - for (my $i = 0; $i < $n; $i++) { - my $t; - sysread($server_sock, $t, 1); - $t = unpack("C", $t); - $types{$t} = 1; - } - my $use = 1; # None - if (exists $types{1}) { - $use = 1; # None - } elsif (exists $types{2}) { - $use = 2; # VncAuth - } else { - die "pproxy: vencrypt_viewer_bridge[$$]: no valid sectypes" . join(",", keys %types) . "\n"; - } - - # send 4 bytes sectype to viewer: - # (note this should be MSB, network byte order...) - my $up = pack("C", $use); - syswrite($viewer_sock, $u0, 1); - syswrite($viewer_sock, $u0, 1); - syswrite($viewer_sock, $u0, 1); - syswrite($viewer_sock, $up, 1); - # and tell server the one we selected: - syswrite($server_sock, $up, 1); - if ($use == 1) { - # even None has security result, so read it here and discard it. - my $sr = ""; - sysread($server_sock, $sr, 4); - } - } - } elsif ($hs{sectype} == $rfbSecTypeVencrypt) { - print STDERR "\npproxy: vencrypt_viewer_bridge[$$]: rfbSecTypeVencrypt\n"; - if (! exists $hs{subtype}) { - unlink($handshake_file); - die "pproxy: vencrypt_viewer_bridge[$$]: no subtype.\n"; - } - my $fake_type = "None"; - my $plain = 0; - my $sub_type = $hs{subtype}; - if ($sub_type == $rfbVencryptTlsNone) { - $fake_type = "None"; - } elsif ($sub_type == $rfbVencryptTlsVnc) { - $fake_type = "VncAuth"; - } elsif ($sub_type == $rfbVencryptTlsPlain) { - $fake_type = "None"; - $plain = 1; - } elsif ($sub_type == $rfbVencryptX509None) { - $fake_type = "None"; - } elsif ($sub_type == $rfbVencryptX509Vnc) { - $fake_type = "VncAuth"; - } elsif ($sub_type == $rfbVencryptX509Plain) { - $fake_type = "None"; - $plain = 1; - } - if ($plain) { - if (!open(W, ">$handshake_file")) { - unlink($handshake_file); - die "pproxy: vencrypt_viewer_bridge[$$]: $handshake_file $!\n"; - } - print W <<"END"; - - proc print_out {} { - global user pass env - - if [info exists env(SSVNC_UP_DEBUG)] { - toplevel .b - button .b.b -text "user=\$user pass=\$pass" -command {destroy .b} - pack .b.b - update - tkwait window .b - } - - if [info exists env(SSVNC_UP_FILE)] { - set fh "" - catch {set fh [open \$env(SSVNC_UP_FILE) w]} - if {\$fh != ""} { - puts \$fh user=\$user\\npass=\$pass - flush \$fh - close \$fh - return - } - } - puts stdout user=\$user\\npass=\$pass - flush stdout - } - - proc center_win {w} { - update - set W [winfo screenwidth \$w] - set W [expr \$W + 1] - wm geometry \$w +\$W+0 - update - set x [expr [winfo screenwidth \$w]/2 - [winfo width \$w]/2] - set y [expr [winfo screenheight \$w]/2 - [winfo height \$w]/2] - - wm geometry \$w +\$x+\$y - wm deiconify \$w - update - } - - wm withdraw . - - global env - set up {} - if [info exists env(SSVNC_UNIXPW)] { - set rm 0 - set up \$env(SSVNC_UNIXPW) - if [regexp {^rm:} \$up] { - set rm 1 - regsub {^rm:} \$up {} up - } - if [file exists \$up] { - set fh "" - set f \$up - catch {set fh [open \$up r]} - if {\$fh != ""} { - gets \$fh u - gets \$fh p - close \$fh - set up "\$u@\$p" - } - if {\$rm} { - catch {file delete \$f} - } - } - } elseif [info exists env(SSVNC_VENCRYPT_USERPASS)] { - set up \$env(SSVNC_VENCRYPT_USERPASS) - } - #puts stderr up=\$up - if {\$up != ""} { - if [regexp {@} \$up] { - global user pass - set user \$up - set pass \$up - regsub {@.*\$} \$user "" user - regsub {^[^@]*@} \$pass "" pass - print_out - exit - } - } - - wm title . {VeNCrypt Viewer Bridge User/Pass} - - set user {} - set pass {} - - label .l -text {SSVNC VeNCrypt Viewer Bridge} - - frame .f0 - frame .f0.fL - label .f0.fL.la -text {Username: } - label .f0.fL.lb -text {Password: } - - pack .f0.fL.la .f0.fL.lb -side top - - frame .f0.fR - entry .f0.fR.ea -width 24 -textvariable user - entry .f0.fR.eb -width 24 -textvariable pass -show * - - pack .f0.fR.ea .f0.fR.eb -side top -fill x - - pack .f0.fL -side left - pack .f0.fR -side right -expand 1 -fill x - - button .no -text Cancel -command {destroy .} - button .ok -text Done -command {print_out; destroy .} - - center_win . - pack .l .f0 .no .ok -side top -fill x - update - wm deiconify . - - bind .f0.fR.ea <Return> {focus .f0.fR.eb} - bind .f0.fR.eb <Return> {print_out; destroy .} - focus .f0.fR.ea - - wm resizable . 1 0 - wm minsize . [winfo reqwidth .] [winfo reqheight .] -END - close W; - - #system("cat $handshake_file"); - my $w = "wish"; - if ($ENV{WISH}) { - $w = $ENV{WISH}; - } - print STDERR "pproxy: vencrypt_viewer_bridge[$$]: prompt VencryptPlain user and passwd.\n"; - my $res = ""; - if (`uname` =~ /Darwin/) { - my $mtmp = `mktemp /tmp/hsup.XXXXXX`; - chomp $mtmp; - system("env SSVNC_UP_FILE=$mtmp $w $handshake_file"); - $res = `cat $mtmp`; - unlink $mtmp; - } else { - $res = `$w $handshake_file`; - } - my $user = ""; - my $pass = ""; - if ($res =~ /user=(\S*)/) { - $user = $1; - } - if ($res =~ /pass=(\S*)/) { - $pass = $1; - } - print STDERR "pproxy: vencrypt_viewer_bridge[$$]: sending VencryptPlain user and passwd.\n"; - my $ulen = pack("C", length($user)); - my $plen = pack("C", length($pass)); - # (note this should be MSB, network byte order...) - syswrite($server_sock, $u0, 1); - syswrite($server_sock, $u0, 1); - syswrite($server_sock, $u0, 1); - syswrite($server_sock, $ulen, 1); - syswrite($server_sock, $u0, 1); - syswrite($server_sock, $u0, 1); - syswrite($server_sock, $u0, 1); - syswrite($server_sock, $plen, 1); - syswrite($server_sock, $user, length($user)); - syswrite($server_sock, $pass, length($pass)); - } - unlink($handshake_file); - - my $ft = 0; - if ($fake_type eq "None") { - $ft = 1; - } elsif ($fake_type eq "VncAuth") { - $ft = 2; - } else { - die "pproxy: vencrypt_viewer_bridge[$$]: unknown fake type: $fake_type\n"; - } - my $fp = pack("C", $ft); - if ($viewer_major > 3 || $viewer_minor >= 7) { - syswrite($viewer_sock, $u1, 1); - syswrite($viewer_sock, $fp, 1); - my $cr; - sysread($viewer_sock, $cr, 1); - $cr = unpack("C", $cr); - if ($cr != $ft) { - die "pproxy: vencrypt_viewer_bridge[$$]: client selected wrong type: $cr / $ft\n"; - } - } else { - print STDERR "pproxy: vencrypt_viewer_bridge[$$]: faking RFB version 3.3 to viewer.\n"; - # send 4 bytes sect type to viewer: - # (note this should be MSB, network byte order...) - syswrite($viewer_sock, $u0, 1); - syswrite($viewer_sock, $u0, 1); - syswrite($viewer_sock, $u0, 1); - syswrite($viewer_sock, $fp, 1); - if ($ft == 1) { - # even None has security result, so read it here and discard it. - my $sr = ""; - sysread($server_sock, $sr, 4); - } - } - } - - $listen_handle = $viewer_sock; - $sock = $server_sock; - - xfer_both(); -} -' - # ' - # xpg_echo will expand \n \r, etc. - # try to unset and then test for it. - if type shopt > /dev/null 2>&1; then - shopt -u xpg_echo >/dev/null 2>&1 - fi - v='print STDOUT "abc\n";' - echo "$v" > $tf - chmod 700 $tf - - lc=`wc -l $tf | awk '{print $1}'` - if [ "X$lc" = "X1" ]; then - echo "$cod" > $tf - else - printf "%s" "$cod" > $tf - echo "" >> $tf - fi - # prime perl - perl -e 'use IO::Socket::INET; select(undef, undef, undef, 0.01)' >/dev/null 2>&1 -} - -# make_tcert is no longer invoked via the ssvnc gui (Listen mode). -# make_tcert is for testing only now via -mycert BUILTIN -make_tcert() { - tcert="/tmp/ss_vnc_viewer_tcert${RANDOM}.$$" - tcert=`mytmp "$tcert"` - cat > $tcert <<END ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAvkfXxb0wcxgrjV2ziFikjII+ze8iKcTBt47L0GM/c21efelN -+zZpJUUXLu4zz8Ryq8Q+sQgfNy7uTOpN9bUUaOk1TnD7gaDQnQWiNHmqbW2kL+DS -OKngJVPo9dETAS8hf7+D1e1DBZxjTc1a4RQqWJixwpYj99ixWzu8VC2m/xXsjvOs -jp4+DLBB490nbkwvstmhmiWm1CmI5O5xOkgioVNQqHvQMdVKOSz9PpbjvZiRX1Uo -qoMrk+2NOqwP90TB35yPASXb9zXKpO7DLhkube+yYGf+yk46aD707L07Eb7cosFP -S84vNZ9gX7rQ0UOwm5rYA/oZTBskgaqhtIzkLwIDAQABAoIBAD4ot/sXt5kRn0Ca -CIkU9AQWlC+v28grR2EQW9JiaZrqcoDNUzUqbCTJsi4ZkIFh2lf0TsqELbZYNW6Y -6AjJM7al4E0UqYSKJTv2WCuuRxdiRs2BMwthqyBmjeanev7bB6V0ybt7u3Y8xU/o -MrTuYnr4vrEjXPKdLirwk7AoDbKsRXHSIiHEIBOq1+dUQ32t36ukdnnza4wKDLZc -PKHiCdCk/wOGhuDlxD6RspqUAlRnJ8/aEhrgWxadFXw1hRhRsf/v1shtB0T3DmTe -Jchjwyiw9mryb9JZAcKxW+fUc4EVvj6VdQGqYInQJY5Yxm5JAlVQUJicuuJEvn6A -rj5osQECgYEA552CaHpUiFlB4HGkjaH00kL+f0+gRF4PANCPk6X3UPDVYzKnzmuu -yDvIdEETGFWBwoztUrOOKqVvPEQ+kBa2+DWWYaERZLtg2cI5byfDJxQ3ldzilS3J -1S3WgCojqcsG/hlxoQJ1dZFanUy/QhUZ0B+wlC+Zp1Q8AyuGQvhHp68CgYEA0lBI -eqq2GGCdJuNHMPFbi8Q0BnX55LW5C1hWjhuYiEkb3hOaIJuJrqvayBlhcQa2cGqp -uP34e9UCfoeLgmoCQ0b4KpL2NGov/mL4i8bMgog4hcoYuIi3qxN18vVR14VKEh4U -RLk0igAYPU+IK2QByaQlBo9OSaKkcfm7U1/pK4ECgYAxr6VpGk0GDvfF2Tsusv6d -GIgV8ZP09qSLTTJvvxvF/lQYeqZq7sjI5aJD5i3de4JhpO/IXQJzfZfWOuGc8XKA -3qYK/Y2IqXXGYRcHFGWV/Y1LFd55mCADHlk0l1WdOBOg8P5iRu/Br9PbiLpCx9oI -vrOXpnp03eod1/luZmqguwKBgQCWFRSj9Q7ddpSvG6HCG3ro0qsNsUMTI1tZ7UBX -SPogx4tLf1GN03D9ZUZLZVFUByZKMtPLX/Hi7K9K/A9ikaPrvsl6GEX6QYzeTGJx -3Pw0amFrmDzr8ySewNR6/PXahxPEuhJcuI31rPufRRI3ZLah3rFNbRbBFX+klkJH -zTnoAQKBgDbUK/aQFGduSy7WUT7LlM3UlGxJ2sA90TQh4JRQwzur0ACN5GdYZkqM -YBts4sBJVwwJoxD9OpbvKu3uKCt41BSj0/KyoBzjT44S2io2tj1syujtlVUsyyBy -/ca0A7WBB8lD1D7QMIhYUm2O9kYtSCLlUTHt5leqGaRG38DqlX36 ------END RSA PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIDzDCCArQCCQDSzxzxqhyqLzANBgkqhkiG9w0BAQQFADCBpzELMAkGA1UEBhMC -VVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxDzANBgNVBAcTBkJvc3RvbjETMBEG -A1UEChMKTXkgQ29tcGFueTEcMBoGA1UECxMTUHJvZHVjdCBEZXZlbG9wbWVudDEZ -MBcGA1UEAxMQd3d3Lm5vd2hlcmUubm9uZTEhMB8GCSqGSIb3DQEJARYSYWRtaW5A -bm93aGVyZS5ub25lMB4XDTA3MDMyMzE4MDc0NVoXDTI2MDUyMjE4MDc0NVowgacx -CzAJBgNVBAYTAlVTMRYwFAYDVQQIEw1NYXNzYWNodXNldHRzMQ8wDQYDVQQHEwZC -b3N0b24xEzARBgNVBAoTCk15IENvbXBhbnkxHDAaBgNVBAsTE1Byb2R1Y3QgRGV2 -ZWxvcG1lbnQxGTAXBgNVBAMTEHd3dy5ub3doZXJlLm5vbmUxITAfBgkqhkiG9w0B -CQEWEmFkbWluQG5vd2hlcmUubm9uZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBAL5H18W9MHMYK41ds4hYpIyCPs3vIinEwbeOy9BjP3NtXn3pTfs2aSVF -Fy7uM8/EcqvEPrEIHzcu7kzqTfW1FGjpNU5w+4Gg0J0FojR5qm1tpC/g0jip4CVT -6PXREwEvIX+/g9XtQwWcY03NWuEUKliYscKWI/fYsVs7vFQtpv8V7I7zrI6ePgyw -QePdJ25ML7LZoZolptQpiOTucTpIIqFTUKh70DHVSjks/T6W472YkV9VKKqDK5Pt -jTqsD/dEwd+cjwEl2/c1yqTuwy4ZLm3vsmBn/spOOmg+9Oy9OxG+3KLBT0vOLzWf -YF+60NFDsJua2AP6GUwbJIGqobSM5C8CAwEAATANBgkqhkiG9w0BAQQFAAOCAQEA -vGomHEp6TVU83X2EBUgnbOhzKJ9u3fOI/Uf5L7p//Vxqow7OR1cguzh/YEzmXOIL -ilMVnzX9nj/bvcLAuqEP7MR1A8f4+E807p/L/Sf49BiCcwQq5I966sGKYXjkve+T -2GTBNwMSq+5kLSf6QY8VZI+qnrAudEQMeJByQhTZZ0dH8Njeq8EGl9KUio+VWaiW -CQK6xJuAvAHqa06OjLmwu1fYD4GLGSrOIiRVkSXV8qLIUmzxdJaIRznkFWsrCEKR -wAH966SAOvd2s6yOHMvyDRIL7WHxfESB6rDHsdIW/yny1fBePjv473KrxyXtbz7I -dMw1yW09l+eEo4A7GzwOdw== ------END CERTIFICATE----- -END - chmod 600 $tcert - echo "$tcert" -} - -Kecho() { - NO_KECHO=1 - if [ "X$USER" = "Xrunge" -a "X$NO_KECHO" = "X" ]; then - echo "dbg: $*" - fi -} - -NHAFL_warning() { - echo "" - echo "** Warning: For the proxy: $proxy" - echo "** Warning: the ssh(1) option: $ssh_NHAFL" - echo "** Warning: will be used to avoid frequent 'ssh key has changed for localhost'" - echo "** Warning: dialogs and connection failures (for example, ssh will exit asking" - echo "** Warning: you to manually remove a key from ~/.ssh/known_hosts.)" - echo "** Warning: " - echo "** Warning: This decreases security: a Man-In-The-Middle attack is possible." - echo "** Warning: For chained ssh connections the first ssh leg is secure but the" - echo "** Warning: 2nd ssh leg is vulnerable. For an ssh connection going through" - echo "** Warning: a HTTP or SOCKS proxy the ssh connection is vulnerable." - echo "** Warning: " - echo "** Warning: You can set the SSVNC_SSH_LOCALHOST_AUTH=1 env. var. to disable" - echo "** Warning: using the NoHostAuthenticationForLocalhost=yes ssh option." - echo "** Warning: " - echo "** Warning: A better solution is to configure (in the SSVNC GUI) the setting:" - echo "** Warning: 'Options -> Advanced -> Private SSH KnownHosts file' (or set" - echo "** Warning: SSVNC_KNOWN_HOSTS_FILE directly) to a per-connection known hosts" - echo "** Warning: file. That file holds the 'localhost' cert for this specific" - echo "** Warning: connection. This yields a both secure and convenient solution." - echo "" -} - -space_expand() { - str=`echo "$1" | sed -e 's/%SPACE/ /g' -e 's/%TAB/\t/g'` - echo "$str" -} - -# handle ssh case: -# -if [ "X$use_ssh" = "X1" ]; then - # - # USING SSH - # - ssh_port="22" - ssh_host="$host" - vnc_host="$localhost" - ssh_UKHF="" - localhost_extra="" - # let user override ssh via $SSH - ssh=${SSH:-"ssh -x"} - - sshword=`echo "$ssh" | awk '{print $1}'` - if [ "X$sshword" != "X" ]; then - if [ -x "$sshword" ]; then - : - elif type "$sshword" > /dev/null 2>&1; then - : - else - echo "" - echo "*********************************************************" - echo "** Problem finding the SSH command '$sshword': **" - echo "" - type "$sshword" - echo "" - echo "** Perhaps you need to install the SSH client package. **" - echo "*********************************************************" - echo "" - sleep 5 - fi - fi - - ssh_NHAFL="-o NoHostAuthenticationForLocalhost=yes" - if [ "X$SSVNC_SSH_LOCALHOST_AUTH" = "X1" ]; then - ssh_NHAFL="" - fi - if [ "X$SSVNC_KNOWN_HOSTS_FILE" != "X" ]; then - ssh_NHAFL="" - - ssh_UKHF="-o UserKnownHostsFile=$SSVNC_KNOWN_HOSTS_FILE" - ssh_args="$ssh_args $ssh_UKHF" - if [ ! -f "$SSVNC_KNOWN_HOSTS_FILE" ]; then - touch "$SSVNC_KNOWN_HOSTS_FILE" >/dev/null 2>&1 - fi - chmod 600 "$SSVNC_KNOWN_HOSTS_FILE" >/dev/null 2>&1 - fi - did_ssh_NHAFL="" - - if [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" ]; then - SSVNC_LIM_ACCEPT_PRELOAD="$SSVNC_BASEDIR/$SSVNC_UNAME/$SSVNC_LIM_ACCEPT_PRELOAD" - fi - if [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" ]; then - echo "" - echo "SSVNC_LIM_ACCEPT_PRELOAD=$SSVNC_LIM_ACCEPT_PRELOAD" - fi - - if [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" -a -f "$SSVNC_LIM_ACCEPT_PRELOAD" ]; then - plvar=LD_PRELOAD - if uname | grep Darwin >/dev/null; then - plvar="DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES" - fi - ssh="env $plvar=$SSVNC_LIM_ACCEPT_PRELOAD $ssh" - else - SSVNC_LIM_ACCEPT_PRELOAD="" - fi - - ssh_vencrypt_proxy="" - # We handle vencrypt for SSH+SSL mode. - if echo "$proxy" | grep 'vencrypt://' > /dev/null; then - proxynew="" - for part in `echo "$proxy" | tr ',' ' '` - do - if echo "$part" | egrep -i '^vencrypt://' > /dev/null; then - ssh_vencrypt_proxy=$part - else - if [ "X$proxynew" = "X" ]; then - proxynew="$part" - else - proxynew="$proxynew,$part" - fi - fi - done - proxy=$proxynew - fi - Kecho ssh_vencrypt_proxy=$ssh_vencrypt_proxy - - # note that user must supply http:// for web proxy in SSH and SSH+SSL. - # No xxxx:// implies ssh server+port. - # - if echo "$proxy" | egrep '(http|https|socks|socks4|socks5)://' > /dev/null; then - # Handle Web or SOCKS proxy(ies) for the initial connect. - Kecho host=$host - Kecho port=$port - pproxy="" - sproxy1="" - sproxy_rest="" - for part in `echo "$proxy" | tr ',' ' '` - do - Kecho proxy_part=$part - if [ "X$part" = "X" ]; then - continue - elif echo "$part" | egrep -i '^(http|https|socks|socks4|socks5)://' > /dev/null; then - pproxy="$pproxy,$part" - else - if [ "X$sproxy1" = "X" ]; then - sproxy1="$part" - else - sproxy_rest="$sproxy_rest,$part" - fi - fi - done - pproxy=`echo "$pproxy" | sed -e 's/^,,*//' -e 's/,,*/,/g'` - sproxy_rest=`echo "$sproxy_rest" | sed -e 's/^,,*//' -e 's/,,*/,/g'` - - Kecho pproxy=$pproxy - Kecho sproxy1=$sproxy1 - Kecho sproxy_rest=$sproxy_rest - - sproxy1_host="" - sproxy1_port="" - sproxy1_user="" - - if [ "X$sproxy1" != "X" ]; then - # XXX fix ipv6 ip adder here and below. - sproxy1_host=`echo "$sproxy1" | awk -F: '{print $1}'` - sproxy1_user=`echo "$sproxy1_host" | awk -F@ '{print $1}'` - sproxy1_host=`echo "$sproxy1_host" | awk -F@ '{print $2}'` - if [ "X$sproxy1_host" = "X" ]; then - sproxy1_host=$sproxy1_user - sproxy1_user="" - else - sproxy1_user="${sproxy1_user}@" - fi - sproxy1_port=`echo "$sproxy1" | awk -F: '{print $2}'` - if [ "X$sproxy1_port" = "X" ]; then - sproxy1_port="22" - fi - else - sproxy1_host=`echo "$host" | awk -F: '{print $1}'` - sproxy1_user=`echo "$sproxy1_host" | awk -F@ '{print $1}'` - sproxy1_host=`echo "$sproxy1_host" | awk -F@ '{print $2}'` - if [ "X$sproxy1_host" = "X" ]; then - sproxy1_host=$sproxy1_user - sproxy1_user="" - else - sproxy1_user="${sproxy1_user}@" - fi - sproxy1_port=`echo "$host" | awk -F: '{print $2}'` - if [ "X$sproxy1_port" = "X" ]; then - sproxy1_port="22" - fi - fi - - Kecho sproxy1_host=$sproxy1_host - Kecho sproxy1_port=$sproxy1_port - Kecho sproxy1_user=$sproxy1_user - - ptmp="/tmp/ss_vncviewer_ssh${RANDOM}.$$.pl" - ptmp=`mytmp "$ptmp"` - PPROXY_REMOVE=1; export PPROXY_REMOVE - proxy=$pproxy - port_save=$port - host_save=$host - if [ "X$sproxy1_host" != "X" ]; then - host=$sproxy1_host - fi - if [ "X$sproxy1_port" != "X" ]; then - port=$sproxy1_port - fi - host=`echo "$host" | sed -e 's/^.*@//'` - port=`echo "$port" | sed -e 's/^.*://'` - pcode "$ptmp" - port=$port_save - host=$host_save - - nd=`findfree 6600` - PPROXY_LISTEN=$nd; export PPROXY_LISTEN - # XXX no reverse forever PPROXY_LOOP_THYSELF ... - $ptmp & - sleep 1 - if [ "X$ssh_NHAFL" != "X" -a "X$did_ssh_NHAFL" != "X1" ]; then - NHAFL_warning - ssh_args="$ssh_args $ssh_NHAFL" - did_ssh_NHAFL=1 - fi - sleep 1 - if [ "X$sproxy1" = "X" ]; then - u="" - if echo "$host" | grep '@' > /dev/null; then - u=`echo "$host" | sed -e 's/@.*$/@/'` - fi - - proxy="${u}$localhost:$nd" - else - proxy="${sproxy1_user}$localhost:$nd" - fi - localhost_extra=".2" - if [ "X$sproxy_rest" != "X" ]; then - proxy="$proxy,$sproxy_rest" - fi - Kecho proxy=$proxy - fi - - if echo "$proxy" | grep "," > /dev/null; then - - proxy1=`echo "$proxy" | awk -F, '{print $1}'` - proxy2=`echo "$proxy" | awk -F, '{print $2}'` - - # user1@gw1.com:port1,user2@ws2:port2 - ssh_host1=`echo "$proxy1" | awk -F: '{print $1}'` - ssh_port1=`echo "$proxy1" | awk -F: '{print $2}'` - if [ "X$ssh_port1" != "X" ]; then - ssh_port1="-p $ssh_port1" - fi - ssh_host2=`echo "$proxy2" | awk -F: '{print $1}'` - ssh_user2=`echo "$ssh_host2" | awk -F@ '{print $1}'` - ssh_host2=`echo "$ssh_host2" | awk -F@ '{print $2}'` - if [ "X$ssh_host2" = "X" ]; then - ssh_host2=$ssh_user2 - ssh_user2="" - else - ssh_user2="${ssh_user2}@" - fi - ssh_port2=`echo "$proxy2" | awk -F: '{print $2}'` - if [ "X$ssh_port2" = "X" ]; then - ssh_port2="22" - fi - proxport=`findfree 3500` - if [ "X$ssh_NHAFL" != "X" -a "X$did_ssh_NHAFL" != "X1" ]; then - NHAFL_warning - did_ssh_NHAFL=1 - sleep 1 - fi - echo - echo "Running 1st ssh proxy:" - ukhf="" - if [ "X$ssh_UKHF" != "X" ]; then - ukhf="$ssh_UKHF$localhost_extra" - fi - if echo "$ssh_host1" | grep '%' > /dev/null; then - uath=`space_expand "$ssh_host1"` - else - uath="$ssh_host1" - fi - echo "$ssh -f -x $ssh_port1 $targ -e none $ssh_NHAFL $ukhf -L $proxport:$ssh_host2:$ssh_port2 \"$uath\" \"sleep 30\"" - echo "" - $ssh -f -x $ssh_port1 $targ -e none $ssh_NHAFL $ukhf -L $proxport:$ssh_host2:$ssh_port2 "$uath" "sleep 30" - ssh_args="$ssh_args $ssh_NHAFL" - sleep 1 - stty sane - proxy="${ssh_user2}$localhost:$proxport" - fi - - if [ "X$proxy" != "X" ]; then - ssh_port=`echo "$proxy" | awk -F: '{print $2}'` - if [ "X$ssh_port" = "X" ]; then - ssh_port="22" - fi - ssh_host=`echo "$proxy" | awk -F: '{print $1}'` - vnc_host="$host" - fi - - echo "" - echo "Running ssh:" - sz=`echo "$ssh_cmd" | wc -c` - if [ "$sz" -gt 300 ]; then - info="..." - else - info="$ssh_cmd" - fi - - C="" - if [ "X$SS_VNCVIEWER_USE_C" != "X" ]; then - C="-C" - fi - - getport="" - teeport="" - if echo "$ssh_cmd" | egrep "(PORT=|P=) " > /dev/null; then - getport=1 - if echo "$ssh_cmd" | egrep "P= " > /dev/null; then - teeport=1 - fi - - PORT="" - ssh_cmd=`echo "$ssh_cmd" | sed -e 's/PORT=[ ]*//' -e 's/P=//'` - SSVNC_NO_ENC_WARN=1 - if [ "X$use_sshssl" = "X" ]; then - direct_connect=1 - fi - fi - if [ "X$getport" != "X" ]; then - ssh_redir="-D ${use}" - elif [ "X$reverse" = "X" ]; then - ssh_redir="-L ${use}:${vnc_host}:${port}" - else - ssh_redir="-R ${port}:${vnc_host}:${use}" - fi - pmark=`sh -c 'echo $$'` - - # the -t option actually speeds up typing response via VNC!! - if [ "X$ssh_port" = "X22" ]; then - ssh_port="" - else - ssh_port="-p $ssh_port" - fi - - if echo "$ssh_host" | grep '%' > /dev/null; then - uath=`space_expand "$ssh_host"` - else - uath="$ssh_host" - fi - if [ "X$SS_VNCVIEWER_SSH_ONLY" != "X" ]; then - echo "$ssh -x $ssh_port $targ $C $ssh_args \"$uath\" \"$info\"" - echo "" - $ssh -x $ssh_port $targ $C $ssh_args "$uath" "$ssh_cmd" - exit $? - - elif [ "X$SS_VNCVIEWER_NO_F" != "X" ]; then - echo "$ssh -x $ssh_port $targ $C $ssh_redir $ssh_args \"$uath\" \"$info\"" - echo "" - $ssh -x $ssh_port $targ $C $ssh_redir $ssh_args "$uath" "$ssh_cmd" - rc=$? - - elif [ "X$getport" != "X" ]; then - tport=/tmp/ss_vncviewer_tport${RANDOM}.$$ - tport=`mytmp "$tport"` - tport2=/tmp/ss_vncviewer_tport2${RANDOM}.$$ - tport2=`mytmp "$tport2"` - - if [ "X$rsh" != "X1" ]; then - if echo "$ssh_cmd" | grep "sudo " > /dev/null; then - echo "" - echo "Initial ssh with 'sudo id' to prime sudo so hopefully the next one" - echo "will require no password..." - echo "" - targ="-t" - $ssh -x $ssh_port $targ $ssh_args "$uath" "sudo id; tty" - echo "" - fi - echo "$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args \"$uath\" \"$info\"" - echo "" - $ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args "$uath" "$ssh_cmd" > $tport 2> $tport2 - if [ "X$teeport" = "X1" ]; then - tail -f $tport 1>&2 & - tail_pid=$! - tail -f $tport2 1>&2 & - tail_pid2=$! - fi - rc=$? - else - rsh_setup - echo "rsh $ul \"$ssh_host\" \"$ssh_cmd\"" - echo "" - rsh $ul "$ssh_host" "$ssh_cmd" > $tport & - sleep 1 - rc=0 - fi - - if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then - echo "sleep $SSVNC_EXTRA_SLEEP" - sleep $SSVNC_EXTRA_SLEEP - fi - - stty sane - i=0 - if type perl > /dev/null 2>&1; then - imax=50 - sleepit="perl -e 'select(undef, undef, undef, 0.20)'" - else - imax=10 - sleepit="sleep 1" - fi - while [ $i -lt $imax ]; do - #echo $sleepit - eval $sleepit - PORT=`grep "^PORT=" $tport | tr '\r' ' ' | head -n 1 | sed -e 's/PORT=//' -e 's/\r//g' -e 's/ *$//'` - if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then - break - fi - vnss=`sed -e 's/\r//g' $tport $tport2 | egrep -i '^(New.* desktop is|A VNC server is already running).*:[0-9[0-9]*$' | head -n 1 | awk '{print $NF}'` - if [ "X$vnss" != "X" ]; then - PORT=`echo "$vnss" | awk -F: '{print $2}'` - if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then - if [ $PORT -lt 100 ]; then - PORT=`expr $PORT + 5900` - fi - fi - if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then - vnss=`sed -e 's/\r//g' $tport | egrep -i '^(New.* desktop is|A VNC server is already running).*:[0-9[0-9]*$' | head -n 1` - echo "vncserver string: $vnss" 1>&2 - break - fi - fi - i=`expr $i + 1` - done - - echo "found: PORT='$PORT'" 1>&2 - lh6="" - if [ "X$SSVNC_PORT_IPV6" != "X" ]; then - lh6=1 - elif egrep 'Info: listening on IPv6 only|Info: listening only on IPv6' $tport > /dev/null; then - lh6=1 - fi - if [ "X$lh6" = "X1" ]; then - echo "set SOCKS5 localhost to ::1" 1>&2 - fi - rm -f $tport $tport2 - if [ "X$rsh" = "X1" ]; then - rsh_viewer "$@" - exit $? - fi - PPROXY_SOCKS=5 - if [ "X$SSVNC_SOCKS5" != "X" ]; then - PPROXY_SOCKS=5 - elif [ "X$SSVNC_SOCKS4" != "X" ]; then - PPROXY_SOCKS=1 - fi - export PPROXY_SOCKS - if [ "X$lh6" = "X" ]; then - host="$localhost" - else - host="::1" - fi - port="$PORT" - proxy="$localhost:$use" - - else - if [ "X$rsh" != "X1" ]; then - echo "$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args \"$uath\" \"$info\"" - echo "" - $ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args "$uath" "$ssh_cmd" - rc=$? - else - rsh_setup - echo "rsh $ul \"$ssh_host\" \"$ssh_cmd\"" - echo "" - rsh $ul "$ssh_host" "$ssh_cmd" & - sleep 1 - PORT=$port - rsh_viewer "$@" - exit $? - fi - fi - - if [ "$rc" != "0" ]; then - echo "" - echo "ssh to \"$uath\" failed." - exit 1 - fi - stty sane - - c=0 - pssh="" - while [ $c -lt 40 ] - do - p=`expr $pmark + $c` - pout=`ps -p "$p" 2>/dev/null | grep -v '^[ ]*PID' | sed -e 's/-L.*$//' -e 's/-x .*$//'` - if echo "$pout" | grep "ssh" > /dev/null; then - if echo "$pout" | egrep -i 'ssh.*(-add|-agent|-ask|-keygen|-argv0|vnc)' >/dev/null; then - : - elif echo "$pout" | egrep -i 'scp|sshd' >/dev/null; then - : - else - pssh=$p - break - fi - fi - c=`expr $c + 1` - done - if [ "X$getport" != "X" ]; then - : - elif [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" ] ; then - sleep 2 - elif [ "X$ssh_cmd" = "Xsleep $ssh_sleep" ] ; then - #echo T sleep 1 - sleep 1 - elif echo "$ssh_cmd" | grep '^sleep ' >/dev/null; then - #echo T sleep 2 - sleep 2 - else - # let any command get started a bit. - #echo T sleep 5 - sleep 5 - fi - echo "" - #reset - stty sane - if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then - echo "sleep $SSVNC_EXTRA_SLEEP" - sleep $SSVNC_EXTRA_SLEEP - fi - echo "ssh_pid='$pssh'"; echo - if [ "X$use_sshssl" = "X" -a "X$getport" = "X" ]; then - if [ "X$SSVNC_EXTRA_COMMAND" != "X" ]; then - (sh -c "$SSVNC_EXTRA_COMMAND") & - echo "($SSVNC_EXTRA_COMMAND) &"; echo - fi - echo "Running viewer:" - - trap "final" 0 2 15 - if [ "X$reverse" = "X" ]; then - echo "$VNCVIEWERCMD" "$@" $localhost:$N - echo "" - $VNCVIEWERCMD "$@" $localhost:$N - if [ $? != 0 ]; then - echo "vncviewer command failed: $?" - if [ "X$secondtry" = "X1" ]; then - sleep 2 - $VNCVIEWERCMD "$@" $localhost:$N - fi - fi - else - echo "" - echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode." - echo "" - N2=$N - if [ "X$VNCVIEWER_IS_REALVNC4" = "X1" ]; then - N2=`echo "$N2" | sed -e 's/://g'` - if [ $N2 -le 200 ]; then - N2=`expr $N2 + 5500` - fi - fi - echo "$VNCVIEWERCMD" "$@" -listen $N2 - echo "" - $VNCVIEWERCMD "$@" -listen $N2 - fi - - exit $? - else - use2=`findfree 5960` - host0=$host - port0=$port - host=$localhost - port=$use - use=$use2 - N=`expr $use - 5900` - if [ "X$getport" != "X" ]; then - host="$host0" - port="$port0" - else - proxy="" - fi - if [ "X$ssh_vencrypt_proxy" != "X" ]; then - ssh_vencrypt_proxy="vencrypt://$host:$port" - if [ "X$proxy" = "X" ]; then - proxy=$ssh_vencrypt_proxy - else - proxy="$proxy,$ssh_vencrypt_proxy" - fi - Kecho "proxy_now=$proxy" - unset PPROXY_LISTEN - fi - fi -fi - -if [ "X$stunnel_set_here" = "X1" -a "X$showcert" = "X" ]; then - if type $STUNNEL > /dev/null 2>&1; then - : - else - echo "" - echo "***************************************************************" - echo "** Problem finding the Stunnel command '$STUNNEL': **" - echo "" - type $STUNNEL - echo "" - echo "** Perhaps you need to install the stunnel/stunnel4 package. **" - echo "***************************************************************" - echo "" - sleep 5 - fi -fi - -# create the stunnel config file: -if [ "X$verify" != "X" ]; then - if [ -d $verify ]; then - verify="CApath = $verify" - else - verify="CAfile = $verify" - fi - verify="$verify -verify = 2" -fi -if [ "X$SSVNC_STUNNEL_VERIFY3" != "X" ]; then - verify=`echo "$verify" | sed -e 's/verify = 2/verify = 3/'` -fi -if [ "X$mycert" != "X" ]; then - cert="cert = $mycert" -fi -if [ "X$crl" != "X" ]; then - if [ -d $crl ]; then - crl="CRLpath = $crl" - else - crl="CRLfile = $crl" - fi -fi - -if [ "X$showcert" = "X1" ]; then - if [ "X$have_uvnc_dsm_helper_showcert" = "X1" ]; then - : - elif [ "X$SSVNC_NO_IPV6_PROXY" != "X" ]; then - : - elif [ "X$ipv6" = "X1" -a "X$proxy" = "X" ]; then - proxy="ipv6://$host:$port" - fi -fi - -if [ "X$direct_connect" != "X" -a "X$STUNNEL_LISTEN" != "X" ]; then - proxy=reverse_direct -fi - -ptmp="" -if [ "X$proxy" != "X" ]; then - ptmp="/tmp/ss_vncviewer${RANDOM}.$$.pl" - ptmp=`mytmp "$ptmp"` - PPROXY_REMOVE=1; export PPROXY_REMOVE - pcode "$ptmp" - if [ "X$showcert" != "X1" -a "X$direct_connect" = "X" ]; then - if uname | egrep 'Darwin|SunOS' >/dev/null; then - vout=`echo "$proxy" | grep -i vencrypt` - if [ "X$vout" != "X" -a "X$reverse" = "X1" ]; then - # need to exec for reverse vencrypt - connect="exec = $ptmp" - else - # on mac and solaris we need to listen on socket instead of stdio: - nd=`findfree 6700` - PPROXY_LISTEN=$nd - export PPROXY_LISTEN - if [ "X$reverse" = "X" ]; then - $ptmp & - fi - sleep 2 - host="$localhost" - port="$nd" - connect="connect = $localhost:$nd" - fi - else - # otherwise on unix we can exec it: - connect="exec = $ptmp" - fi - else - connect="exec = $ptmp" - fi -else - connect="connect = $host:$port" -fi - -# handle showcert case: -# -if [ "X$showcert" = "X1" ]; then - if [ "X$proxy" != "X" ]; then - PPROXY_LISTEN=$use - export PPROXY_LISTEN - if [ "X$SS_DEBUG" != "X" ]; then - $ptmp & - else - $ptmp 2>/dev/null & - fi - sleep 1 - more_sleep=1 - if uname | grep Linux > /dev/null; then - if netstat -ant | grep LISTEN | grep "127.0.0.1:$use" > /dev/null; then - more_sleep="" - fi - elif uname | grep SunOS > /dev/null; then - if netstat -an -f inet -P tcp | grep LISTEN | grep "127.0.0.1.$use" > /dev/null; then - more_sleep="" - fi - elif uname | egrep -i 'bsd|darwin' > /dev/null; then - if netstat -ant -f inet | grep LISTEN | grep "127.0.0.1.$use" > /dev/null; then - more_sleep="" - fi - fi - if [ "X$more_sleep" = "X1" ]; then - sleep 1 - fi - host="$localhost" - port="$use" - fi - cipher_args="" - if [ "X$ciphers" != "X" ]; then - cipher_args=`echo "$ciphers" | sed -e 's/ciphers=/-cipher /'` - fi - if [ "X$have_uvnc_dsm_helper_showcert" = "X1" ]; then - : - elif type openssl > /dev/null 2>&1; then - : - else - echo "" - echo "********************************************************" - echo "** Problem finding the OpenSSL command 'openssl': **" - echo "" - type openssl 2>&1 - echo "" - echo "** Perhaps you need to install the 'openssl' package. **" - echo "********************************************************" - echo "" - fi - #echo "openssl s_client $cipher_args -connect $host:$port" - if [ "X$reverse" = "X" ]; then - if type host > /dev/null 2>/dev/null; then - host $host >/dev/null 2>&1 - host $host >/dev/null 2>&1 - fi - timeout=15 - if [ "X$SSVNC_FETCH_TIMEOUT" != "X" ]; then - timeout=$SSVNC_FETCH_TIMEOUT - fi - if [ "X$have_uvnc_dsm_helper_showcert" = "X1" ]; then - if type pkill >/dev/null 2>&1; then - (sleep $timeout; if kill -0 $$; then pkill -TERM -f "ultravnc_dsm_helper.*$host.*$port"; fi) >/dev/null 2>&1 & - fi - ultravnc_dsm_helper showcert $host:$port 2>&1 - else - if type pkill >/dev/null 2>&1; then - (sleep $timeout; if kill -0 $$; then pkill -TERM -f "openssl.*s_client.*$host.*$port"; fi) >/dev/null 2>&1 & - fi - openssl s_client $cipher_args -prexit -connect $host:$port 2>&1 < /dev/null - fi - rc=$? - else - tcert="" - if [ "X$mycert" = "X" ]; then - tcert=`make_tcert` - cert_args="-cert $tcert -CAfile $tcert" - else - cert_args="-cert $mycert -CAfile $mycert" - fi - tmp_out=/tmp/showcert_out${RANDOM}.$$ - tmp_out=`mytmp "$tmp_out"` - tmp_err=/tmp/showcert_err${RANDOM}.$$ - tmp_err=`mytmp "$tmp_err"` - - #echo "openssl s_server $cipher_args $cert_args -accept $port -verify 2 > $tmp_out 2> $tmp_err" 1>&2 - - # assume we have perl: - check_perl perl - - perl -e " - \$p = open(O, \"|openssl s_server $cipher_args $cert_args -accept $port -verify 2 1>$tmp_out 2> $tmp_err\"); - exit 1 unless \$p; - while (1) { - sleep 1; - if (!open(F, \"<$tmp_out\")) { - kill \$p; - exit 1; - } - while (<F>) { - if (/RFB 00/) { - fsleep(0.25); - print O \"RFB 000.000\\n\"; - fsleep(1.00); - kill \$p; - fsleep(0.25); - exit 0; - } - } - close F; - } - sub fsleep { - select(undef, undef, undef, shift); - } - "; - - echo "" - cat $tmp_out - echo "" - echo "----2----" - cat $tmp_err - if grep BEGIN.CERTIFICATE $tmp_out >/dev/null; then - rc=0 - else - rc=1 - fi - - rm -f $tmp_out $tmp_err - fi - if [ "X$SSVNC_PREDIGESTED_HANDSHAKE" != "X" ]; then - rm -f $SSVNC_PREDIGESTED_HANDSHAKE - fi - if [ "X$SSVNC_SHOWCERT_EXIT_0" = "X1" ]; then - exit 0 - else - exit $rc - fi -fi - -# handle direct connect case: -# -if [ "X$direct_connect" != "X" ]; then - if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then - SSVNC_NO_ENC_WARN=1 - echo "" - echo "Using UltraVNC DSM Plugin key for encryption:" - echo "" - ustr=`echo "$SSVNC_ULTRA_DSM" | sed -e 's/pw=[^ ]*/pw=******/g'` - echo " $ustr PORT HOST:PORT" - echo "" - elif [ "X$getport" = "X" ]; then - echo "" - echo "Running viewer for direct connection:" - if echo X"$@" | grep chatonly > /dev/null; then - : - else - echo "" - echo "** WARNING: THERE WILL BE NO SSL OR SSH ENCRYPTION **" - echo "" - fi - fi - x="" - if [ "X$SSVNC_NO_ENC_WARN" != "X" ]; then - if [ "X$getport" = "X" ]; then - sleep 1 - fi - elif type printf > /dev/null 2>&1; then - printf "Are you sure you want to continue? [y]/n " - read x - else - echo -n "Are you sure you want to continue? [y]/n " - read x - fi - if [ "X$x" = "Xn" ]; then - exit 1 - fi - echo "" - if [ "X$ptmp" != "X" ]; then - if [ "X$reverse" = "X" ]; then - PPROXY_LISTEN=$use - export PPROXY_LISTEN - else - if [ "X$proxy" = "Xreverse_direct" ]; then - PPROXY_LISTEN="$STUNNEL_LISTEN:`expr 5500 + $disp`" - PPROXY_DEST="$localhost:$use" - PPROXY_PROXY="ipv6://$localhost:$use" # not always ipv6.. - export PPROXY_LISTEN PPROXY_DEST PPROXY_PROXY - pps=1 - else - PPROXY_REVERSE="$localhost:$use" - export PPROXY_LISTEN - pps=3 - fi - if [ "X$SSVNC_LISTEN_ONCE" != "X1" ]; then - PPROXY_LOOP_THYSELF=`mytmp "/tmp/pproxy_loop_thyself.${RANDOM}.$$"` - export PPROXY_LOOP_THYSELF - pps=2 - fi - if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then - pps=`expr $pps + $SSVNC_EXTRA_SLEEP` - fi - PPROXY_SLEEP=$pps; export PPROXY_SLEEP; - PPROXY_KILLPID=+1; export PPROXY_KILLPID; - fi - - $ptmp & - - if [ "X$reverse" = "X" ]; then - #sleep 2 - #echo T sleep 1 - sleep 1 - fi - host="$localhost" - disp="$N" - port=`expr $disp + 5900` - fi - if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then - echo "T sleep $SSVNC_EXTRA_SLEEP" - sleep $SSVNC_EXTRA_SLEEP - fi - if [ "X$SSVNC_EXTRA_COMMAND" != "X" ]; then - (sh -c "$SSVNC_EXTRA_COMMAND") & - echo "($SSVNC_EXTRA_COMMAND) &"; echo - fi - if [ "X$reverse" = "X" ]; then - hostdisp="$host:$disp" - if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then - if [ "X$SSVNC_USE_OURS" = "X1" ]; then - hostdisp="exec=$SSVNC_ULTRA_DSM 0 $host:$port" - else - pf=`findfree 5970` - cmd="$SSVNC_ULTRA_DSM -$pf $host:$port" - pf=`expr $pf - 5900` - hostdisp="$localhost:$pf" - ustr=`echo "$cmd" | sed -e 's/pw=[^ ]*/pw=******/g'` - echo "Running:" - echo - echo "$ustr &" - echo - $cmd & - dsm_pid=$! - sleep 2 - fi - fi - hostdisp2=`echo "$hostdisp" | sed -e 's/pw=[^ ]*/pw=******/g'` - echo "$VNCVIEWERCMD" "$@" "$hostdisp2" - trap "final" 0 2 15 - echo "" - $VNCVIEWERCMD "$@" "$hostdisp" - if [ $? != 0 ]; then - echo "vncviewer command failed: $?" - if [ "X$secondtry" = "X1" ]; then - sleep 2 - $VNCVIEWERCMD "$@" "$hostdisp" - fi - fi - else - echo "" - echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode." - echo "" - trap "final" 0 2 15 - if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then - if [ "X$SSVNC_LISTEN_ONCE" = "X1" ]; then - echo "NOTE: The ultravnc_dsm_helper only runs once. So after the first LISTEN" - echo " ends you must restart the Listening mode. You may also need to" - echo " Press Ctrl-C to stop the viewer and restart for another connection." - echo "" - fi - #SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE - VNCVIEWER_LISTEN_LOCALHOST=1 - export VNCVIEWER_LISTEN_LOCALHOST - dport=`expr 5500 + $disp` - cmd="$SSVNC_ULTRA_DSM $dport $localhost:$use" - ustr=`echo "$cmd" | sed -e 's/pw=[^ ]*/pw=******/g'` - echo "Running:" - echo - echo "$ustr &" - echo - if [ "X$SSVNC_LISTEN_ONCE" = "X1" ]; then - $cmd & - dsm_pid=$! - else - while [ 1 ]; do $cmd; sleep 1; done & - dsm_pid=$! - fi - sleep 2 - disp=$use - if [ $disp -ge 5500 ]; then - disp=`expr $disp - 5500` - fi - fi - disp2=$disp - if [ "X$VNCVIEWER_IS_REALVNC4" = "X1" ]; then - disp2=`echo "$disp2" | sed -e 's/://g'` - if [ $disp2 -le 200 ]; then - disp2=`expr $disp2 + 5500` - fi - fi - echo "$VNCVIEWERCMD" "$@" -listen $disp2 - echo "" - $VNCVIEWERCMD "$@" -listen $disp2 - if [ "X$PPROXY_LOOP_THYSELF" != "X" ]; then - rm -f $PPROXY_LOOP_THYSELF - fi - fi - exit $? -fi - -tmp_cfg=/tmp/ss_vncviewer${RANDOM}.$$ -tmp_cfg=`mytmp "$tmp_cfg"` - -stunnel_exec="" -if [ "X$SSVNC_USE_OURS" != "X1" ]; then - : -elif echo $STUNNEL_EXTRA_SVC_OPTS | grep '#stunnel-exec' > /dev/null; then - stunnel_exec="#" -fi - -if [ "X$reverse" = "X" ]; then - - if echo "$proxy" | grep "^repeater://" > /dev/null; then - if [ "X$cert" = "XBUILTIN" ]; then - ttcert=`make_tcert` - cert="cert = $ttcert" - fi - # Note for listen mode, an empty cert will cause stunnel to fail. - # The ssvnc gui will have already taken care of this. - fi - - cat > "$tmp_cfg" <<END -foreground = yes -pid = -client = yes -debug = $stunnel_debug -$ciphers -$STUNNEL_EXTRA_OPTS -$STUNNEL_EXTRA_OPTS_USER -$cert -$crl -$verify - -${stunnel_exec}[vnc_stunnel] -${stunnel_exec}accept = $localhost:$use -$connect -$STUNNEL_EXTRA_SVC_OPTS -$STUNNEL_EXTRA_SVC_OPTS_USER - -END - -else - # REVERSE case: - - stunnel_exec="" # doesn't work for listening. - - p2=`expr 5500 + $N` - connect="connect = $localhost:$p2" - if [ "X$cert" = "XBUILTIN" ]; then - ttcert=`make_tcert` - cert="cert = $ttcert" - fi - # Note for listen mode, an empty cert will cause stunnel to fail. - # The ssvnc gui will have already taken care of this. - - - hloc="" - if [ "X$use_ssh" = "X1" ]; then - hloc="$localhost:" - elif [ "X$STUNNEL_LISTEN" != "X" ]; then - hloc="$STUNNEL_LISTEN:" - fi - if echo "$proxy" | grep -i '^vencrypt:' > /dev/null; then - hloc="$localhost:" - pv=`findfree 5570` - proxy="vencrypt:$pv:$port" - port=$pv - if [ "X$anondh_set" = "X1" ]; then - # not needed for ANONDH in this mode - #ciphers="ciphers = ADH:@STRENGTH" - : - fi - fi - cat > "$tmp_cfg" <<END -foreground = yes -pid = -client = no -debug = $stunnel_debug -$ciphers -$STUNNEL_EXTRA_OPTS -$STUNNEL_EXTRA_OPTS_USER -$cert -$crl -$verify - -[vnc_stunnel] -accept = $hloc$port -$connect -$STUNNEL_EXTRA_SVC_OPTS -$STUNNEL_EXTRA_SVC_OPTS_USER - -END - -fi - -echo "" -echo "Using this stunnel configuration:" -echo "" -cat "$tmp_cfg" | uniq -echo "" -if egrep -i '^[ ]*(CApath|CAfile) =' "$tmp_cfg" > /dev/null ; then - : -else - echo "** WARNING: THE STUNNEL CONFIG HAS NO SERVER CERTIFICATE SPECIFIED **" - echo "** WARNING: (the CApath or CAfile stunnel option) THE VNC SERVER WILL **" - echo "** WARNING: NOT BE AUTHENTICATED. A MAN-IN-THE-MIDDLE ATTACK IS POSSIBLE **" - echo "" -fi -sleep 1 - -if [ "X$stunnel_exec" = "X" ]; then - echo "" - echo "Running stunnel:" - echo "$STUNNEL $tmp_cfg" - st=`echo "$STUNNEL" | awk '{print $1}'` - $st -help > /dev/null 2>&1 - $STUNNEL "$tmp_cfg" < /dev/tty > /dev/tty & - stunnel_pid=$! - echo "" - - # pause here to let the user supply a possible passphrase for the - # mycert key: - if [ "X$mycert" != "X" ]; then - nsl=10 - dsl=0 - if [ ! -f $mycert ]; then - dsl=0 - elif grep -i 'Proc-Type.*ENCRYPTED' "$mycert" > /dev/null 2>/dev/null; then - dsl=1 - fi - if [ "X$dsl" = "X1" ]; then - echo "" - echo "(** pausing $nsl secs for possible certificate passphrase dialog **)" - echo "" - sleep $nsl - echo "(** done pausing for passphrase **)" - echo "" - fi - fi - #echo T sleep 1 - sleep 1 - rm -f "$tmp_cfg" -fi - - -echo "" -if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then - echo "sleep $SSVNC_EXTRA_SLEEP" - sleep $SSVNC_EXTRA_SLEEP -fi -if [ "X$SSVNC_EXTRA_COMMAND" != "X" ]; then - (sh -c "$SSVNC_EXTRA_COMMAND") & - echo "($SSVNC_EXTRA_COMMAND) &"; echo -fi - -if [ "X$reverse" = "X" ]; then - if [ "X$NEED_VENCRYPT_VIEWER_BRIDGE" = "X1" -a "X$ptmp" != "X" ] ; then - port1=`expr 5900 + $N` # stunnel port - port2=`findfree 5970` # bridge port (viewer connects to it.) - N=`expr $port2 - 5900` - env PPROXY_REMOVE=0 PPROXY_SLEEP=0 PPROXY_VENCRYPT_VIEWER_BRIDGE="$port2,$port1" $ptmp & - sleep 1 - fi - echo "Running viewer:" - vnc_hp=$localhost:$N - if [ "X$stunnel_exec" != "X" ]; then - vnc_hp="exec=$STUNNEL $tmp_cfg" - fi - echo "$VNCVIEWERCMD" "$@" "$vnc_hp" - trap "final" 0 2 15 - echo "" - $VNCVIEWERCMD "$@" "$vnc_hp" - if [ $? != 0 ]; then - echo "vncviewer command failed: $?" - if [ "X$secondtry" = "X1" ]; then - sleep 2 - $VNCVIEWERCMD "$@" "$vnc_hp" - fi - fi -else - echo "Running viewer:" - echo "" - echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode." - echo "" - trap "final" 0 2 15 - N2=$N - N2_trim=`echo "$N2" | sed -e 's/://g'` - if [ $N2_trim -le 200 ]; then - N2_trim=`expr $N2_trim + 5500` - fi - if [ "X$proxy" != "X" ]; then - if echo "$proxy" | grep -i '^vencrypt:' > /dev/null; then - pstunnel=`echo "$proxy" | awk -F: '{print $2}'` - plisten=`echo "$proxy" | awk -F: '{print $3}'` - IF=INADDR_ANY - if [ "X$STUNNEL_LISTEN" != "X" ]; then - IF=$STUNNEL_LISTEN - fi - PPROXY_VENCRYPT_REVERSE=1; export PPROXY_VENCRYPT_REVERSE - PPROXY_LISTEN="$IF:$plisten"; export PPROXY_LISTEN - PPROXY_PROXY="vencrypt://$localhost:$pstunnel"; export PPROXY_PROXY - PPROXY_DEST="$localhost:$pstunnel"; export PPROXY_DEST - STUNNEL_ONCE=1; export STUNNEL_ONCE - STUNNEL_MAX_CLIENTS=1; export STUNNEL_MAX_CLIENTS - if [ "X$NEED_VENCRYPT_VIEWER_BRIDGE" = "X1" -a "X$ptmp" != "X" ] ; then - port1=`expr 5500 + $N2` - port2=`findfree 5580` - N2=`expr $port2 - 5500` - N2_trim=`echo "$N2" | sed -e 's/://g'` - if [ $N2_trim -le 200 ]; then - N2_trim=`expr $N2_trim + 5500` - fi - if [ "X$SSVNC_LISTEN_ONCE" != "X1" ]; then - PPROXY_LOOP_THYSELF=`mytmp "/tmp/pproxy_loop_thyself1.${RANDOM}.$$"` - export PPROXY_LOOP_THYSELF - PPROXY_LOOP_THYSELF0=$PPROXY_LOOP_THYSELF - fi - env PPROXY_REMOVE=0 PPROXY_SLEEP=0 PPROXY_VENCRYPT_VIEWER_BRIDGE="-$port1,$port2" $ptmp & - sleep 1 - fi - else - PPROXY_REVERSE="$localhost:$port"; export PPROXY_REVERSE - PPROXY_SLEEP=1; export PPROXY_SLEEP; - fi - PPROXY_KILLPID=+1; export PPROXY_KILLPID; - if [ "X$SSVNC_LISTEN_ONCE" != "X1" ]; then - PPROXY_LOOP_THYSELF=`mytmp "/tmp/pproxy_loop_thyself2.${RANDOM}.$$"` - export PPROXY_LOOP_THYSELF - fi - $ptmp & - # Important to have no extra pids generated between here and VNCVIEWERCMD - fi - if [ "X$VNCVIEWER_IS_REALVNC4" = "X1" ]; then - N2=$N2_trim - fi - echo "$VNCVIEWERCMD" "$@" -listen $N2 - echo "" - $VNCVIEWERCMD "$@" -listen $N2 - - if [ "X$PPROXY_LOOP_THYSELF" != "X" ]; then - rm -f $PPROXY_LOOP_THYSELF - fi - if [ "X$PPROXY_LOOP_THYSELF0" != "X" ]; then - rm -f $PPROXY_LOOP_THYSELF0 - fi -fi - -sleep 1 diff --git a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch b/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch deleted file mode 100644 index bc10f3c..0000000 --- a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch +++ /dev/null @@ -1,111 +0,0 @@ ---- vnc_javasrc.orig/VncCanvas.java 2004-10-10 02:15:54.000000000 -0400 -+++ vnc_javasrc/VncCanvas.java 2010-11-30 21:01:15.000000000 -0500 -@@ -28,13 +28,14 @@ - import java.lang.*; - import java.util.zip.*; - -+import java.util.Collections; - - // - // VncCanvas is a subclass of Canvas which draws a VNC desktop on it. - // - - class VncCanvas extends Canvas -- implements KeyListener, MouseListener, MouseMotionListener { -+ implements KeyListener, MouseListener, MouseMotionListener, MouseWheelListener { - - VncViewer viewer; - RfbProto rfb; -@@ -81,6 +82,20 @@ - cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6)); - cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF); - -+ // kludge to not show any Java cursor in the canvas since we are -+ // showing the soft cursor (should be a user setting...) -+ Cursor dot = Toolkit.getDefaultToolkit().createCustomCursor( -+ Toolkit.getDefaultToolkit().createImage(new byte[4]), new Point(0,0), -+ "dot"); -+ this.setCursor(dot); -+ -+ // while we are at it... get rid of the keyboard traversals that -+ // make it so we can't type a Tab character: -+ this.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, -+ Collections.EMPTY_SET); -+ this.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, -+ Collections.EMPTY_SET); -+ - colors = new Color[256]; - for (int i = 0; i < 256; i++) - colors[i] = new Color(cm8.getRGB(i)); -@@ -169,6 +184,7 @@ - inputEnabled = true; - addMouseListener(this); - addMouseMotionListener(this); -+ addMouseWheelListener(this); - if (viewer.showControls) { - viewer.buttonPanel.enableRemoteAccessControls(true); - } -@@ -177,6 +193,7 @@ - inputEnabled = false; - removeMouseListener(this); - removeMouseMotionListener(this); -+ removeMouseWheelListener(this); - if (viewer.showControls) { - viewer.buttonPanel.enableRemoteAccessControls(false); - } -@@ -1190,6 +1207,9 @@ - public void mouseDragged(MouseEvent evt) { - processLocalMouseEvent(evt, true); - } -+ public void mouseWheelMoved(MouseWheelEvent evt) { -+ processLocalMouseWheelEvent(evt); -+ } - - public void processLocalKeyEvent(KeyEvent evt) { - if (viewer.rfb != null && rfb.inNormalProtocol) { -@@ -1221,6 +1241,19 @@ - evt.consume(); - } - -+ public void processLocalMouseWheelEvent(MouseWheelEvent evt) { -+ if (viewer.rfb != null && rfb.inNormalProtocol) { -+ synchronized(rfb) { -+ try { -+ rfb.writeWheelEvent(evt); -+ } catch (Exception e) { -+ e.printStackTrace(); -+ } -+ rfb.notify(); -+ } -+ } -+ } -+ - public void processLocalMouseEvent(MouseEvent evt, boolean moved) { - if (viewer.rfb != null && rfb.inNormalProtocol) { - if (moved) { -@@ -1387,9 +1420,9 @@ - result = cm8.getRGB(pixBuf[i]); - } else { - result = 0xFF000000 | -- (pixBuf[i * 4 + 1] & 0xFF) << 16 | -- (pixBuf[i * 4 + 2] & 0xFF) << 8 | -- (pixBuf[i * 4 + 3] & 0xFF); -+ (pixBuf[i * 4 + 2] & 0xFF) << 16 | -+ (pixBuf[i * 4 + 1] & 0xFF) << 8 | -+ (pixBuf[i * 4 + 0] & 0xFF); - } - } else { - result = 0; // Transparent pixel -@@ -1403,9 +1436,9 @@ - result = cm8.getRGB(pixBuf[i]); - } else { - result = 0xFF000000 | -- (pixBuf[i * 4 + 1] & 0xFF) << 16 | -- (pixBuf[i * 4 + 2] & 0xFF) << 8 | -- (pixBuf[i * 4 + 3] & 0xFF); -+ (pixBuf[i * 4 + 2] & 0xFF) << 16 | -+ (pixBuf[i * 4 + 1] & 0xFF) << 8 | -+ (pixBuf[i * 4 + 0] & 0xFF); - } - } else { - result = 0; // Transparent pixel diff --git a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch b/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch deleted file mode 100644 index 801234a..0000000 --- a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch +++ /dev/null @@ -1,2600 +0,0 @@ -diff -Naur vnc_javasrc.orig/Makefile vnc_javasrc/Makefile ---- vnc_javasrc.orig/Makefile 2004-03-04 08:34:25.000000000 -0500 -+++ vnc_javasrc/Makefile 2010-05-18 20:56:26.000000000 -0400 -@@ -4,6 +4,7 @@ - - CP = cp - JC = javac -+JC_ARGS = -target 1.4 -source 1.4 - JAR = jar - ARCHIVE = VncViewer.jar - MANIFEST = MANIFEST.MF -@@ -15,25 +16,29 @@ - DesCipher.class CapabilityInfo.class CapsContainer.class \ - RecordingFrame.class SessionRecorder.class AuthUnixLoginPanel.class \ - SocketFactory.class HTTPConnectSocketFactory.class \ -- HTTPConnectSocket.class ReloginPanel.class -+ HTTPConnectSocket.class ReloginPanel.class \ -+ SSLSocketToMe.class -+ -+SSL_CLASSES = SSLSocketToMe*.class TrustDialog.class - - SOURCES = VncViewer.java RfbProto.java AuthPanel.java VncCanvas.java \ - OptionsFrame.java ClipboardFrame.java ButtonPanel.java \ - DesCipher.java CapabilityInfo.java CapsContainer.java \ - RecordingFrame.java SessionRecorder.java AuthUnixLoginPanel.java \ - SocketFactory.java HTTPConnectSocketFactory.java \ -- HTTPConnectSocket.java ReloginPanel.java -+ HTTPConnectSocket.java ReloginPanel.java \ -+ SSLSocketToMe.java - - all: $(CLASSES) $(ARCHIVE) - - $(CLASSES): $(SOURCES) -- $(JC) -target 1.1 -O $(SOURCES) -+ $(JC) $(JC_ARGS) -O $(SOURCES) - - $(ARCHIVE): $(CLASSES) $(MANIFEST) -- $(JAR) cfm $(ARCHIVE) $(MANIFEST) $(CLASSES) -+ $(JAR) cfm $(ARCHIVE) $(MANIFEST) $(CLASSES) $(SSL_CLASSES) - - install: $(CLASSES) $(ARCHIVE) -- $(CP) $(CLASSES) $(ARCHIVE) $(PAGES) $(INSTALL_DIR) -+ $(CP) $(CLASSES) $(SSL_CLASSES) $(ARCHIVE) $(PAGES) $(INSTALL_DIR) - - export:: $(CLASSES) $(ARCHIVE) $(PAGES) - @$(ExportJavaClasses) -diff -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto.java ---- vnc_javasrc.orig/RfbProto.java 2004-03-04 08:34:25.000000000 -0500 -+++ vnc_javasrc/RfbProto.java 2010-11-30 22:05:12.000000000 -0500 -@@ -199,7 +199,21 @@ - host = h; - port = p; - -- if (viewer.socketFactory == null) { -+ if (! viewer.disableSSL) { -+ System.out.println("new SSLSocketToMe"); -+ SSLSocketToMe ssl; -+ try { -+ ssl = new SSLSocketToMe(host, port, v); -+ } catch (Exception e) { -+ throw new IOException(e.getMessage()); -+ } -+ -+ try { -+ sock = ssl.connectSock(); -+ } catch (Exception es) { -+ throw new IOException(es.getMessage()); -+ } -+ } else if (viewer.socketFactory == null) { - sock = new Socket(host, port); - } else { - try { -@@ -255,7 +269,7 @@ - || (b[10] < '0') || (b[10] > '9') || (b[11] != '\n')) - { - throw new Exception("Host " + host + " port " + port + -- " is not an RFB server"); -+ " is not an RFB server: " + b); - } - - serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0'); -@@ -892,6 +906,38 @@ - final static int ALT_MASK = InputEvent.ALT_MASK; - - -+ void writeWheelEvent(MouseWheelEvent evt) throws IOException { -+ -+ eventBufLen = 0; -+ -+ int x = evt.getX(); -+ int y = evt.getY(); -+ -+ if (x < 0) x = 0; -+ if (y < 0) y = 0; -+ -+ int ptrmask; -+ -+ int clicks = evt.getWheelRotation(); -+ System.out.println("writeWheelEvent: clicks: " + clicks); -+ if (clicks > 0) { -+ ptrmask = 16; -+ } else if (clicks < 0) { -+ ptrmask = 8; -+ } else { -+ return; -+ } -+ -+ eventBuf[eventBufLen++] = (byte) PointerEvent; -+ eventBuf[eventBufLen++] = (byte) ptrmask; -+ eventBuf[eventBufLen++] = (byte) ((x >> 8) & 0xff); -+ eventBuf[eventBufLen++] = (byte) (x & 0xff); -+ eventBuf[eventBufLen++] = (byte) ((y >> 8) & 0xff); -+ eventBuf[eventBufLen++] = (byte) (y & 0xff); -+ -+ os.write(eventBuf, 0, eventBufLen); -+ } -+ - // - // Write a pointer event message. We may need to send modifier key events - // around it to set the correct modifier state. -@@ -992,6 +1038,19 @@ - boolean down = (evt.getID() == KeyEvent.KEY_PRESSED); - - int key; -+ if (viewer.debugKeyboard) { -+ System.out.println("----------------------------------------"); -+ System.out.println("evt.getKeyChar: " + evt.getKeyChar()); -+ System.out.println("getKeyText: " + KeyEvent.getKeyText(evt.getKeyCode())); -+ System.out.println("evt.getKeyCode: " + evt.getKeyCode()); -+ System.out.println("evt.getID: " + evt.getID()); -+ System.out.println("evt.getKeyLocation: " + evt.getKeyLocation()); -+ System.out.println("evt.isActionKey: " + evt.isActionKey()); -+ System.out.println("evt.isControlDown: " + evt.isControlDown()); -+ System.out.println("evt.getModifiers: " + evt.getModifiers()); -+ System.out.println("getKeyModifiersText: " + KeyEvent.getKeyModifiersText(evt.getModifiers())); -+ System.out.println("evt.paramString: " + evt.paramString()); -+ } - if (evt.isActionKey()) { - - // -@@ -1025,6 +1084,13 @@ - return; - } - -+ if(key == 0xffc2 && viewer.mapF5_to_atsign) { -+ if (viewer.debugKeyboard) { -+ System.out.println("Mapping: F5 -> AT "); -+ } -+ key = 0x40; -+ } -+ - } else { - - // -@@ -1036,6 +1102,7 @@ - - key = keyChar; - -+ - if (key < 0x20) { - if (evt.isControlDown()) { - key += 0x60; -@@ -1121,6 +1188,16 @@ - int oldModifiers = 0; - - void writeModifierKeyEvents(int newModifiers) { -+ if(viewer.forbid_Ctrl_Alt) { -+ if ((newModifiers & CTRL_MASK) != 0 && (newModifiers & ALT_MASK) != 0) { -+ int orig = newModifiers; -+ newModifiers &= ~ALT_MASK; -+ newModifiers &= ~CTRL_MASK; -+ if (viewer.debugKeyboard) { -+ System.out.println("Ctrl+Alt modifiers: " + orig + " -> " + newModifiers); -+ } -+ } -+ } - if ((newModifiers & CTRL_MASK) != (oldModifiers & CTRL_MASK)) - writeKeyEvent(0xffe3, (newModifiers & CTRL_MASK) != 0); - -diff -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSLSocketToMe.java ---- vnc_javasrc.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_javasrc/SSLSocketToMe.java 2010-07-10 19:18:06.000000000 -0400 -@@ -0,0 +1,2067 @@ -+/* -+ * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer. -+ * -+ * Copyright (c) 2006 Karl J. Runge <runge@karlrunge.com> -+ * All rights reserved. -+ * -+ * This 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; version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software 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 this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ * -+ */ -+ -+import java.net.*; -+import java.io.*; -+import javax.net.ssl.*; -+import java.util.*; -+ -+import java.security.*; -+import java.security.cert.*; -+import java.security.spec.*; -+import java.security.cert.Certificate; -+import java.security.cert.CertificateFactory; -+ -+import java.awt.*; -+import java.awt.event.*; -+ -+public class SSLSocketToMe { -+ -+ /* basic member data: */ -+ String host; -+ int port; -+ VncViewer viewer; -+ -+ boolean debug = true; -+ boolean debug_certs = false; -+ -+ /* sockets */ -+ SSLSocket socket = null; -+ SSLSocketFactory factory; -+ -+ /* fallback for Proxy connection */ -+ boolean proxy_in_use = false; -+ boolean proxy_failure = false; -+ public DataInputStream is = null; -+ public OutputStream os = null; -+ -+ /* strings from user WRT proxy: */ -+ String proxy_auth_string = null; -+ String proxy_dialog_host = null; -+ int proxy_dialog_port = 0; -+ -+ Socket proxySock; -+ DataInputStream proxy_is; -+ OutputStream proxy_os; -+ -+ /* trust contexts */ -+ SSLContext trustloc_ctx; -+ SSLContext trustall_ctx; -+ SSLContext trustsrv_ctx; -+ SSLContext trusturl_ctx; -+ SSLContext trustone_ctx; -+ -+ /* corresponding trust managers */ -+ TrustManager[] trustAllCerts; -+ TrustManager[] trustSrvCert; -+ TrustManager[] trustUrlCert; -+ TrustManager[] trustOneCert; -+ -+ /* client-side SSL auth key (oneTimeKey=...) */ -+ KeyManager[] mykey = null; -+ -+ boolean user_wants_to_see_cert = true; -+ String cert_fail = null; -+ -+ /* cert(s) we retrieve from Web server, VNC server, or serverCert param: */ -+ java.security.cert.Certificate[] trustallCerts = null; -+ java.security.cert.Certificate[] trustsrvCerts = null; -+ java.security.cert.Certificate[] trusturlCerts = null; -+ -+ /* utility to decode hex oneTimeKey=... and serverCert=... */ -+ byte[] hex2bytes(String s) { -+ byte[] bytes = new byte[s.length()/2]; -+ for (int i=0; i<s.length()/2; i++) { -+ int j = 2*i; -+ try { -+ int val = Integer.parseInt(s.substring(j, j+2), 16); -+ if (val > 127) { -+ val -= 256; -+ } -+ Integer I = new Integer(val); -+ bytes[i] = Byte.decode(I.toString()).byteValue(); -+ -+ } catch (Exception e) { -+ ; -+ } -+ } -+ return bytes; -+ } -+ -+ SSLSocketToMe(String h, int p, VncViewer v) throws Exception { -+ host = h; -+ port = p; -+ viewer = v; -+ -+ debug_certs = v.debugCerts; -+ -+ /* we will first try default factory for certification: */ -+ -+ factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); -+ -+ dbg("SSL startup: " + host + " " + port); -+ -+ -+ /* create trust managers to be used if initial handshake fails: */ -+ -+ trustAllCerts = new TrustManager[] { -+ /* -+ * this one accepts everything. Only used if user -+ * has disabled checking (trustAllVncCerts=yes) -+ * or when we grab the cert to show it to them in -+ * a dialog and ask them to manually verify/accept it. -+ */ -+ new X509TrustManager() { -+ public java.security.cert.X509Certificate[] -+ getAcceptedIssuers() { -+ return null; -+ } -+ public void checkClientTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) { -+ /* empty */ -+ } -+ public void checkServerTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) { -+ /* empty */ -+ dbg("ALL: an untrusted connect to grab cert."); -+ } -+ } -+ }; -+ -+ trustUrlCert = new TrustManager[] { -+ /* -+ * this one accepts only the retrieved server -+ * cert by SSLSocket by this applet and stored in -+ * trusturlCerts. -+ */ -+ new X509TrustManager() { -+ public java.security.cert.X509Certificate[] -+ getAcceptedIssuers() { -+ return null; -+ } -+ public void checkClientTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ throw new CertificateException("No Clients (URL)"); -+ } -+ public void checkServerTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ /* we want to check 'certs' against 'trusturlCerts' */ -+ if (trusturlCerts == null) { -+ throw new CertificateException( -+ "No Trust url Certs array."); -+ } -+ if (trusturlCerts.length < 1) { -+ throw new CertificateException( -+ "No Trust url Certs."); -+ } -+ if (certs == null) { -+ throw new CertificateException( -+ "No this-certs array."); -+ } -+ if (certs.length < 1) { -+ throw new CertificateException( -+ "No this-certs Certs."); -+ } -+ if (certs.length != trusturlCerts.length) { -+ throw new CertificateException( -+ "certs.length != trusturlCerts.length " + certs.length + " " + trusturlCerts.length); -+ } -+ boolean ok = true; -+ for (int i = 0; i < certs.length; i++) { -+ if (! trusturlCerts[i].equals(certs[i])) { -+ ok = false; -+ dbg("URL: cert mismatch at i=" + i); -+ dbg("URL: cert mismatch cert" + certs[i]); -+ dbg("URL: cert mismatch url" + trusturlCerts[i]); -+ if (cert_fail == null) { -+ cert_fail = "cert-mismatch"; -+ } -+ } -+ if (debug_certs) { -+ dbg("\n***********************************************"); -+ dbg("URL: cert info at i=" + i); -+ dbg("URL: cert info cert" + certs[i]); -+ dbg("==============================================="); -+ dbg("URL: cert info url" + trusturlCerts[i]); -+ dbg("***********************************************"); -+ } -+ } -+ if (!ok) { -+ throw new CertificateException( -+ "Server Cert Chain != URL Cert Chain."); -+ } -+ dbg("URL: trusturlCerts[i] matches certs[i] i=0:" + (certs.length-1)); -+ } -+ } -+ }; -+ -+ trustSrvCert = new TrustManager[] { -+ /* -+ * this one accepts cert given to us in the serverCert -+ * Applet Parameter we were started with. It is -+ * currently a fatal error if the VNC Server's cert -+ * doesn't match it. -+ */ -+ new X509TrustManager() { -+ public java.security.cert.X509Certificate[] -+ getAcceptedIssuers() { -+ return null; -+ } -+ public void checkClientTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ throw new CertificateException("No Clients (SRV)"); -+ } -+ public void checkServerTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ /* we want to check 'certs' against 'trustsrvCerts' */ -+ if (trustsrvCerts == null) { -+ throw new CertificateException( -+ "No Trust srv Certs array."); -+ } -+ if (trustsrvCerts.length < 1) { -+ throw new CertificateException( -+ "No Trust srv Certs."); -+ } -+ if (certs == null) { -+ throw new CertificateException( -+ "No this-certs array."); -+ } -+ if (certs.length < 1) { -+ throw new CertificateException( -+ "No this-certs Certs."); -+ } -+ if (certs.length != trustsrvCerts.length) { -+ throw new CertificateException( -+ "certs.length != trustsrvCerts.length " + certs.length + " " + trustsrvCerts.length); -+ } -+ boolean ok = true; -+ for (int i = 0; i < certs.length; i++) { -+ if (! trustsrvCerts[i].equals(certs[i])) { -+ ok = false; -+ dbg("SRV: cert mismatch at i=" + i); -+ dbg("SRV: cert mismatch cert" + certs[i]); -+ dbg("SRV: cert mismatch srv" + trustsrvCerts[i]); -+ if (cert_fail == null) { -+ cert_fail = "server-cert-mismatch"; -+ } -+ } -+ if (debug_certs) { -+ dbg("\n***********************************************"); -+ dbg("SRV: cert info at i=" + i); -+ dbg("SRV: cert info cert" + certs[i]); -+ dbg("==============================================="); -+ dbg("SRV: cert info srv" + trustsrvCerts[i]); -+ dbg("***********************************************"); -+ } -+ } -+ if (!ok) { -+ throw new CertificateException( -+ "Server Cert Chain != serverCert Applet Parameter Cert Chain."); -+ } -+ dbg("SRV: trustsrvCerts[i] matches certs[i] i=0:" + (certs.length-1)); -+ } -+ } -+ }; -+ -+ trustOneCert = new TrustManager[] { -+ /* -+ * this one accepts only the retrieved server -+ * cert by SSLSocket by this applet we stored in -+ * trustallCerts that user has accepted or applet -+ * parameter trustAllVncCerts=yes is set. This is -+ * for when we reconnect after the user has manually -+ * accepted the trustall cert in the dialog (or set -+ * trustAllVncCerts=yes applet param.) -+ */ -+ new X509TrustManager() { -+ public java.security.cert.X509Certificate[] -+ getAcceptedIssuers() { -+ return null; -+ } -+ public void checkClientTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ throw new CertificateException("No Clients (ONE)"); -+ } -+ public void checkServerTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ /* we want to check 'certs' against 'trustallCerts' */ -+ if (trustallCerts == null) { -+ throw new CertificateException( -+ "No Trust All Server Certs array."); -+ } -+ if (trustallCerts.length < 1) { -+ throw new CertificateException( -+ "No Trust All Server Certs."); -+ } -+ if (certs == null) { -+ throw new CertificateException( -+ "No this-certs array."); -+ } -+ if (certs.length < 1) { -+ throw new CertificateException( -+ "No this-certs Certs."); -+ } -+ if (certs.length != trustallCerts.length) { -+ throw new CertificateException( -+ "certs.length != trustallCerts.length " + certs.length + " " + trustallCerts.length); -+ } -+ boolean ok = true; -+ for (int i = 0; i < certs.length; i++) { -+ if (! trustallCerts[i].equals(certs[i])) { -+ ok = false; -+ dbg("ONE: cert mismatch at i=" + i); -+ dbg("ONE: cert mismatch cert" + certs[i]); -+ dbg("ONE: cert mismatch all" + trustallCerts[i]); -+ } -+ if (debug_certs) { -+ dbg("\n***********************************************"); -+ dbg("ONE: cert info at i=" + i); -+ dbg("ONE: cert info cert" + certs[i]); -+ dbg("==============================================="); -+ dbg("ONE: cert info all" + trustallCerts[i]); -+ dbg("***********************************************"); -+ } -+ } -+ if (!ok) { -+ throw new CertificateException( -+ "Server Cert Chain != TRUSTALL Cert Chain."); -+ } -+ dbg("ONE: trustallCerts[i] matches certs[i] i=0:" + (certs.length-1)); -+ } -+ } -+ }; -+ -+ /* -+ * The above TrustManagers are used: -+ * -+ * 1) to retrieve the server cert in case of failure to -+ * display it to the user in a dialog. -+ * 2) to subsequently connect to the server if user agrees. -+ */ -+ -+ /* -+ * build oneTimeKey cert+key if supplied in applet parameter: -+ */ -+ if (viewer.oneTimeKey != null && viewer.oneTimeKey.equals("PROMPT")) { -+ ClientCertDialog d = new ClientCertDialog(); -+ viewer.oneTimeKey = d.queryUser(); -+ } -+ if (viewer.oneTimeKey != null && viewer.oneTimeKey.indexOf(",") > 0) { -+ int idx = viewer.oneTimeKey.indexOf(","); -+ -+ String onetimekey = viewer.oneTimeKey.substring(0, idx); -+ byte[] key = hex2bytes(onetimekey); -+ String onetimecert = viewer.oneTimeKey.substring(idx+1); -+ byte[] cert = hex2bytes(onetimecert); -+ -+ KeyFactory kf = KeyFactory.getInstance("RSA"); -+ PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key ); -+ PrivateKey ff = kf.generatePrivate (keysp); -+ if (debug_certs) { -+ dbg("one time key " + ff); -+ } -+ -+ CertificateFactory cf = CertificateFactory.getInstance("X.509"); -+ Collection c = cf.generateCertificates(new ByteArrayInputStream(cert)); -+ Certificate[] certs = new Certificate[c.toArray().length]; -+ if (c.size() == 1) { -+ Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert)); -+ if (debug_certs) { -+ dbg("one time cert" + tmpcert); -+ } -+ certs[0] = tmpcert; -+ } else { -+ certs = (Certificate[]) c.toArray(); -+ } -+ -+ KeyStore ks = KeyStore.getInstance("JKS"); -+ ks.load(null, null); -+ ks.setKeyEntry("onetimekey", ff, "".toCharArray(), certs); -+ String da = KeyManagerFactory.getDefaultAlgorithm(); -+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(da); -+ kmf.init(ks, "".toCharArray()); -+ -+ mykey = kmf.getKeyManagers(); -+ } -+ -+ /* -+ * build serverCert cert if supplied in applet parameter: -+ */ -+ if (viewer.serverCert != null) { -+ CertificateFactory cf = CertificateFactory.getInstance("X.509"); -+ byte[] cert = hex2bytes(viewer.serverCert); -+ Collection c = cf.generateCertificates(new ByteArrayInputStream(cert)); -+ trustsrvCerts = new Certificate[c.toArray().length]; -+ if (c.size() == 1) { -+ Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert)); -+ trustsrvCerts[0] = tmpcert; -+ } else { -+ trustsrvCerts = (Certificate[]) c.toArray(); -+ } -+ } -+ -+ /* the trust loc certs context: */ -+ try { -+ trustloc_ctx = SSLContext.getInstance("SSL"); -+ -+ /* -+ * below is a failed attempt to get jvm's default -+ * trust manager using null (below) makes it so -+ * for HttpsURLConnection the server cannot be -+ * verified (no prompting.) -+ */ -+ if (false) { -+ boolean didit = false; -+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); -+ tmf.init((KeyStore) null); -+ TrustManager [] tml = tmf.getTrustManagers(); -+ for (int i = 0; i < tml.length; i++) { -+ TrustManager tm = tml[i]; -+ if (tm instanceof X509TrustManager) { -+ TrustManager tm1[] = new TrustManager[1]; -+ tm1[0] = tm; -+ trustloc_ctx.init(mykey, tm1, null); -+ didit = true; -+ break; -+ } -+ } -+ if (!didit) { -+ trustloc_ctx.init(mykey, null, null); -+ } -+ } else { -+ /* we have to set trust manager to null */ -+ trustloc_ctx.init(mykey, null, null); -+ } -+ -+ } catch (Exception e) { -+ String msg = "SSL trustloc_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ -+ /* the trust all certs context: */ -+ try { -+ trustall_ctx = SSLContext.getInstance("SSL"); -+ trustall_ctx.init(mykey, trustAllCerts, new -+ java.security.SecureRandom()); -+ -+ } catch (Exception e) { -+ String msg = "SSL trustall_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ -+ /* the trust url certs context: */ -+ try { -+ trusturl_ctx = SSLContext.getInstance("SSL"); -+ trusturl_ctx.init(mykey, trustUrlCert, new -+ java.security.SecureRandom()); -+ -+ } catch (Exception e) { -+ String msg = "SSL trusturl_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ -+ /* the trust srv certs context: */ -+ try { -+ trustsrv_ctx = SSLContext.getInstance("SSL"); -+ trustsrv_ctx.init(mykey, trustSrvCert, new -+ java.security.SecureRandom()); -+ -+ } catch (Exception e) { -+ String msg = "SSL trustsrv_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ -+ /* the trust the one cert from server context: */ -+ try { -+ trustone_ctx = SSLContext.getInstance("SSL"); -+ trustone_ctx.init(mykey, trustOneCert, new -+ java.security.SecureRandom()); -+ -+ } catch (Exception e) { -+ String msg = "SSL trustone_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ } -+ -+ /* -+ * we call this early on to 1) check for a proxy, 2) grab -+ * Browser/JVM accepted HTTPS cert. -+ */ -+ public void check_for_proxy_and_grab_vnc_server_cert() { -+ -+ trusturlCerts = null; -+ proxy_in_use = false; -+ -+ if (viewer.ignoreProxy) { -+ /* applet param says skip it. */ -+ /* the downside is we do not set trusturlCerts for comparison later... */ -+ /* nor do we autodetect x11vnc for GET=1. */ -+ return; -+ } -+ -+ dbg("------------------------------------------------"); -+ dbg("Into check_for_proxy_and_grab_vnc_server_cert():"); -+ -+ dbg("TRYING HTTPS:"); -+ String ustr = "https://" + host + ":"; -+ if (viewer.httpsPort != null) { -+ ustr += viewer.httpsPort; -+ } else { -+ ustr += port; -+ } -+ ustr += viewer.urlPrefix + "/check.https.proxy.connection"; -+ dbg("ustr is: " + ustr); -+ -+ try { -+ /* prepare for an HTTPS URL connection to host:port */ -+ URL url = new URL(ustr); -+ HttpsURLConnection https = (HttpsURLConnection) url.openConnection(); -+ -+ if (mykey != null) { -+ /* with oneTimeKey (mykey) we can't use the default SSL context */ -+ if (trustsrvCerts != null) { -+ dbg("passing trustsrv_ctx to HttpsURLConnection to provide client cert."); -+ https.setSSLSocketFactory(trustsrv_ctx.getSocketFactory()); -+ } else if (trustloc_ctx != null) { -+ dbg("passing trustloc_ctx to HttpsURLConnection to provide client cert."); -+ https.setSSLSocketFactory(trustloc_ctx.getSocketFactory()); -+ } -+ } -+ -+ https.setUseCaches(false); -+ https.setRequestMethod("GET"); -+ https.setRequestProperty("Pragma", "No-Cache"); -+ https.setRequestProperty("Proxy-Connection", "Keep-Alive"); -+ https.setDoInput(true); -+ -+ dbg("trying https.connect()"); -+ https.connect(); -+ -+ dbg("trying https.getServerCertificates()"); -+ trusturlCerts = https.getServerCertificates(); -+ -+ if (trusturlCerts == null) { -+ dbg("set trusturlCerts to null!"); -+ } else { -+ dbg("set trusturlCerts to non-null"); -+ } -+ -+ if (https.usingProxy()) { -+ proxy_in_use = true; -+ dbg("An HTTPS proxy is in use. There may be connection problems."); -+ } -+ -+ dbg("trying https.getContent()"); -+ Object output = https.getContent(); -+ dbg("trying https.disconnect()"); -+ https.disconnect(); -+ if (! viewer.GET) { -+ String header = https.getHeaderField("VNC-Server"); -+ if (header != null && header.startsWith("x11vnc")) { -+ dbg("detected x11vnc server (1), setting GET=1"); -+ viewer.GET = true; -+ } -+ } -+ -+ } catch(Exception e) { -+ dbg("HttpsURLConnection: " + e.getMessage()); -+ } -+ -+ if (proxy_in_use) { -+ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); -+ dbg("------------------------------------------------"); -+ return; -+ } else if (trusturlCerts != null && !viewer.forceProxy) { -+ /* Allow user to require HTTP check? use forceProxy for now. */ -+ dbg("SKIPPING HTTP PROXY CHECK: got trusturlCerts, assuming proxy info is correct."); -+ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); -+ dbg("------------------------------------------------"); -+ return; -+ } -+ -+ /* -+ * XXX need to remember scenario where this extra check -+ * gives useful info. User's Browser proxy settings? -+ */ -+ dbg("TRYING HTTP:"); -+ ustr = "http://" + host + ":" + port; -+ ustr += viewer.urlPrefix + "/index.vnc"; -+ dbg("ustr is: " + ustr); -+ -+ try { -+ /* prepare for an HTTP URL connection to the same host:port (but not httpsPort) */ -+ URL url = new URL(ustr); -+ HttpURLConnection http = (HttpURLConnection) -+ url.openConnection(); -+ -+ http.setUseCaches(false); -+ http.setRequestMethod("GET"); -+ http.setRequestProperty("Pragma", "No-Cache"); -+ http.setRequestProperty("Proxy-Connection", "Keep-Alive"); -+ http.setDoInput(true); -+ -+ dbg("trying http.connect()"); -+ http.connect(); -+ -+ if (http.usingProxy()) { -+ proxy_in_use = true; -+ dbg("An HTTP proxy is in use. There may be connection problems."); -+ } -+ dbg("trying http.getContent()"); -+ Object output = http.getContent(); -+ dbg("trying http.disconnect()"); -+ http.disconnect(); -+ if (! viewer.GET) { -+ String header = http.getHeaderField("VNC-Server"); -+ if (header != null && header.startsWith("x11vnc")) { -+ dbg("detected x11vnc server (2), setting GET=1"); -+ viewer.GET = true; -+ } -+ } -+ } catch(Exception e) { -+ dbg("HttpURLConnection: " + e.getMessage()); -+ } -+ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); -+ dbg("------------------------------------------------"); -+ } -+ -+ public Socket connectSock() throws IOException { -+ /* -+ * first try a https connection to detect a proxy, and -+ * grab the VNC server cert at the same time: -+ */ -+ check_for_proxy_and_grab_vnc_server_cert(); -+ -+ boolean srv_cert = false; -+ -+ if (trustsrvCerts != null) { -+ /* applet parameter suppled serverCert */ -+ dbg("viewer.trustSrvCert-0 using trustsrv_ctx"); -+ factory = trustsrv_ctx.getSocketFactory(); -+ srv_cert = true; -+ } else if (viewer.trustAllVncCerts) { -+ /* trust all certs (no checking) */ -+ dbg("viewer.trustAllVncCerts-0 using trustall_ctx"); -+ factory = trustall_ctx.getSocketFactory(); -+ } else if (trusturlCerts != null) { -+ /* trust certs the Browser/JVM accepted in check_for_proxy... */ -+ dbg("using trusturl_ctx"); -+ factory = trusturl_ctx.getSocketFactory(); -+ } else { -+ /* trust the local defaults */ -+ dbg("using trustloc_ctx"); -+ factory = trustloc_ctx.getSocketFactory(); -+ } -+ -+ socket = null; -+ -+ try { -+ if (proxy_in_use && viewer.forceProxy) { -+ throw new Exception("forcing proxy (forceProxy)"); -+ } else if (viewer.CONNECT != null) { -+ throw new Exception("forcing CONNECT"); -+ } -+ -+ int timeout = 6; -+ if (timeout > 0) { -+ socket = (SSLSocket) factory.createSocket(); -+ InetSocketAddress inetaddr = new InetSocketAddress(host, port); -+ dbg("Using timeout of " + timeout + " secs to: " + host + ":" + port); -+ socket.connect(inetaddr, timeout * 1000); -+ } else { -+ socket = (SSLSocket) factory.createSocket(host, port); -+ } -+ -+ } catch (Exception esock) { -+ dbg("socket error: " + esock.getMessage()); -+ if (proxy_in_use || viewer.CONNECT != null) { -+ proxy_failure = true; -+ if (proxy_in_use) { -+ dbg("HTTPS proxy in use. Trying to go with it."); -+ } else { -+ dbg("viewer.CONNECT reverse proxy in use. Trying to go with it."); -+ } -+ try { -+ socket = proxy_socket(factory); -+ } catch (Exception e) { -+ dbg("proxy_socket error: " + e.getMessage()); -+ } -+ } else { -+ /* n.b. socket is left in error state to cause ex. below. */ -+ } -+ } -+ -+ try { -+ socket.startHandshake(); -+ -+ dbg("The Server Connection Verified OK on 1st try."); -+ -+ java.security.cert.Certificate[] currentTrustedCerts; -+ BrowserCertsDialog bcd; -+ -+ SSLSession sess = socket.getSession(); -+ currentTrustedCerts = sess.getPeerCertificates(); -+ -+ if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-1 keeping socket."); -+ } else if (currentTrustedCerts == null || currentTrustedCerts.length < 1) { -+ try { -+ socket.close(); -+ } catch (Exception e) { -+ dbg("socket is grumpy."); -+ } -+ socket = null; -+ throw new SSLHandshakeException("no current certs"); -+ } -+ -+ String serv = ""; -+ try { -+ CertInfo ci = new CertInfo(currentTrustedCerts[0]); -+ serv = ci.get_certinfo("CN"); -+ } catch (Exception e) { -+ ; -+ } -+ -+ if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-2 skipping browser certs dialog"); -+ user_wants_to_see_cert = false; -+ } else if (viewer.serverCert != null && trustsrvCerts != null) { -+ dbg("viewer.serverCert-1 skipping browser certs dialog"); -+ user_wants_to_see_cert = false; -+ } else if (viewer.trustUrlVncCert) { -+ dbg("viewer.trustUrlVncCert-1 skipping browser certs dialog"); -+ user_wants_to_see_cert = false; -+ } else { -+ /* have a dialog with the user: */ -+ bcd = new BrowserCertsDialog(serv, host + ":" + port); -+ dbg("browser certs dialog begin."); -+ bcd.queryUser(); -+ dbg("browser certs dialog finished."); -+ -+ if (bcd.showCertDialog) { -+ String msg = "user wants to see cert"; -+ dbg(msg); -+ user_wants_to_see_cert = true; -+ if (cert_fail == null) { -+ cert_fail = "user-view"; -+ } -+ throw new SSLHandshakeException(msg); -+ } else { -+ user_wants_to_see_cert = false; -+ dbg("browser certs dialog: user said yes, accept it"); -+ } -+ } -+ -+ } catch (SSLHandshakeException eh) { -+ dbg("SSLHandshakeException: could not automatically verify Server."); -+ dbg("msg: " + eh.getMessage()); -+ -+ -+ /* send a cleanup string just in case: */ -+ String getoutstr = "GET /index.vnc HTTP/1.0\r\nConnection: close\r\n\r\n"; -+ -+ try { -+ OutputStream os = socket.getOutputStream(); -+ os.write(getoutstr.getBytes()); -+ socket.close(); -+ } catch (Exception e) { -+ dbg("socket is grumpy!"); -+ } -+ -+ /* reload */ -+ -+ socket = null; -+ -+ String reason = null; -+ -+ if (srv_cert) { -+ /* for serverCert usage we make this a fatal error. */ -+ throw new IOException("Fatal: VNC Server's Cert does not match Applet Parameter 'serverCert=...'"); -+ /* see below in TrustDialog were we describe this case to user anyway */ -+ } -+ -+ /* -+ * Reconnect, trusting any cert, so we can grab -+ * the cert to show it to the user in a dialog -+ * for him to manually accept. This connection -+ * is not used for anything else. -+ */ -+ factory = trustall_ctx.getSocketFactory(); -+ if (proxy_failure) { -+ socket = proxy_socket(factory); -+ } else { -+ socket = (SSLSocket) factory.createSocket(host, port); -+ } -+ -+ if (debug_certs) { -+ dbg("trusturlCerts: " + trusturlCerts); -+ dbg("trustsrvCerts: " + trustsrvCerts); -+ } -+ if (trusturlCerts == null && cert_fail == null) { -+ cert_fail = "missing-certs"; -+ } -+ -+ try { -+ socket.startHandshake(); -+ -+ dbg("The TrustAll Server Cert-grab Connection (trivially) Verified OK."); -+ -+ /* grab the cert: */ -+ try { -+ SSLSession sess = socket.getSession(); -+ trustallCerts = sess.getPeerCertificates(); -+ } catch (Exception e) { -+ throw new Exception("Could not get " + -+ "Peer Certificate"); -+ } -+ if (debug_certs) { -+ dbg("trustallCerts: " + trustallCerts); -+ } -+ -+ if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-3. skipping dialog, trusting everything."); -+ } else if (! browser_cert_match()) { -+ /* -+ * close socket now, we will reopen after -+ * dialog if user agrees to use the cert. -+ */ -+ try { -+ OutputStream os = socket.getOutputStream(); -+ os.write(getoutstr.getBytes()); -+ socket.close(); -+ } catch (Exception e) { -+ dbg("socket is grumpy!!"); -+ } -+ socket = null; -+ -+ /* dialog with user to accept cert or not: */ -+ -+ TrustDialog td= new TrustDialog(host, port, -+ trustallCerts); -+ -+ if (cert_fail == null) { -+ ; -+ } else if (cert_fail.equals("user-view")) { -+ reason = "Reason for this Dialog:\n\n" -+ + " You Asked to View the Certificate."; -+ } else if (cert_fail.equals("server-cert-mismatch")) { -+ /* this is now fatal error, see above. */ -+ reason = "Reason for this Dialog:\n\n" -+ + " The VNC Server's Certificate does not match the Certificate\n" -+ + " specified in the supplied 'serverCert' Applet Parameter."; -+ } else if (cert_fail.equals("cert-mismatch")) { -+ reason = "Reason for this Dialog:\n\n" -+ + " The VNC Server's Certificate does not match the Website's\n" -+ + " HTTPS Certificate (that you previously accepted; either\n" -+ + " manually or automatically via Certificate Authority.)"; -+ } else if (cert_fail.equals("missing-certs")) { -+ reason = "Reason for this Dialog:\n\n" -+ + " Not all Certificates could be obtained to check."; -+ } -+ -+ if (! td.queryUser(reason)) { -+ String msg = "User decided against it."; -+ dbg(msg); -+ throw new IOException(msg); -+ } -+ } -+ -+ } catch (Exception ehand2) { -+ dbg("** Could not TrustAll Verify Server!"); -+ -+ throw new IOException(ehand2.getMessage()); -+ } -+ -+ /* reload again: */ -+ -+ if (socket != null) { -+ try { -+ socket.close(); -+ } catch (Exception e) { -+ dbg("socket is grumpy!!!"); -+ } -+ socket = null; -+ } -+ -+ /* -+ * Now connect a 3rd time, using the cert -+ * retrieved during connection 2 (sadly, that -+ * the user likely blindly agreed to...) -+ */ -+ -+ factory = trustone_ctx.getSocketFactory(); -+ if (proxy_failure) { -+ socket = proxy_socket(factory); -+ } else { -+ socket = (SSLSocket) factory.createSocket(host, port); -+ } -+ -+ try { -+ socket.startHandshake(); -+ dbg("TrustAll/TrustOne Server Connection Verified #3."); -+ -+ } catch (Exception ehand3) { -+ dbg("** Could not TrustAll/TrustOne Verify Server #3."); -+ -+ throw new IOException(ehand3.getMessage()); -+ } -+ } -+ -+ /* we have socket (possibly null) at this point, so proceed: */ -+ -+ /* handle x11vnc GET=1, if applicable: */ -+ if (socket != null && viewer.GET) { -+ String str = "GET "; -+ str += viewer.urlPrefix; -+ str += "/request.https.vnc.connection"; -+ str += " HTTP/1.0\r\n"; -+ str += "Pragma: No-Cache\r\n"; -+ str += "\r\n"; -+ -+ System.out.println("sending: " + str); -+ OutputStream os = socket.getOutputStream(); -+ String type = "os"; -+ -+ if (type == "os") { -+ os.write(str.getBytes()); -+ os.flush(); -+ System.out.println("used OutputStream"); -+ } else if (type == "bs") { -+ BufferedOutputStream bs = new BufferedOutputStream(os); -+ bs.write(str.getBytes()); -+ bs.flush(); -+ System.out.println("used BufferedOutputStream"); -+ } else if (type == "ds") { -+ DataOutputStream ds = new DataOutputStream(os); -+ ds.write(str.getBytes()); -+ ds.flush(); -+ System.out.println("used DataOutputStream"); -+ } -+ if (false) { -+ String rep = ""; -+ DataInputStream is = new DataInputStream( -+ new BufferedInputStream(socket.getInputStream(), 16384)); -+ while (true) { -+ rep += readline(is); -+ if (rep.indexOf("\r\n\r\n") >= 0) { -+ break; -+ } -+ } -+ System.out.println("rep: " + rep); -+ } -+ } -+ -+ dbg("SSL returning socket to caller."); -+ dbg(""); -+ -+ /* could be null, let caller handle that. */ -+ return (Socket) socket; -+ } -+ -+ boolean browser_cert_match() { -+ String msg = "Browser URL accept previously accepted cert"; -+ -+ if (user_wants_to_see_cert) { -+ return false; -+ } -+ -+ if (viewer.serverCert != null || trustsrvCerts != null) { -+ if (cert_fail == null) { -+ cert_fail = "server-cert-mismatch"; -+ } -+ } -+ if (trustallCerts != null && trusturlCerts != null) { -+ if (trustallCerts.length == trusturlCerts.length) { -+ boolean ok = true; -+ /* check toath trustallCerts (socket) equals trusturlCerts (browser) */ -+ for (int i = 0; i < trusturlCerts.length; i++) { -+ if (! trustallCerts[i].equals(trusturlCerts[i])) { -+ dbg("BCM: cert mismatch at i=" + i); -+ dbg("BCM: cert mismatch url" + trusturlCerts[i]); -+ dbg("BCM: cert mismatch all" + trustallCerts[i]); -+ ok = false; -+ } -+ } -+ if (ok) { -+ System.out.println(msg); -+ if (cert_fail == null) { -+ cert_fail = "did-not-fail"; -+ } -+ return true; -+ } else { -+ if (cert_fail == null) { -+ cert_fail = "cert-mismatch"; -+ } -+ return false; -+ } -+ } -+ } -+ if (cert_fail == null) { -+ cert_fail = "missing-certs"; -+ } -+ return false; -+ } -+ -+ private void dbg(String s) { -+ if (debug) { -+ System.out.println(s); -+ } -+ } -+ -+ private int gint(String s) { -+ int n = -1; -+ try { -+ Integer I = new Integer(s); -+ n = I.intValue(); -+ } catch (Exception ex) { -+ return -1; -+ } -+ return n; -+ } -+ -+ /* this will do the proxy CONNECT negotiation and hook us up. */ -+ -+ private void proxy_helper(String proxyHost, int proxyPort) { -+ -+ boolean proxy_auth = false; -+ String proxy_auth_basic_realm = ""; -+ String hp = host + ":" + port; -+ dbg("proxy_helper: " + proxyHost + ":" + proxyPort + " hp: " + hp); -+ -+ /* we loop here a few times trying for the password case */ -+ for (int k=0; k < 2; k++) { -+ dbg("proxy_in_use psocket: " + k); -+ -+ if (proxySock != null) { -+ try { -+ proxySock.close(); -+ } catch (Exception e) { -+ dbg("proxy socket is grumpy."); -+ } -+ } -+ -+ proxySock = psocket(proxyHost, proxyPort); -+ if (proxySock == null) { -+ dbg("1-a sadly, returning a null socket"); -+ return; -+ } -+ -+ String req1 = "CONNECT " + hp + " HTTP/1.1\r\n" -+ + "Host: " + hp + "\r\n"; -+ -+ dbg("requesting via proxy: " + req1); -+ -+ if (proxy_auth) { -+ if (proxy_auth_string == null) { -+ ProxyPasswdDialog pp = new ProxyPasswdDialog(proxyHost, proxyPort, proxy_auth_basic_realm); -+ pp.queryUser(); -+ proxy_auth_string = pp.getAuth(); -+ } -+ //dbg("auth1: " + proxy_auth_string); -+ -+ String auth2 = Base64Coder.encodeString(proxy_auth_string); -+ //dbg("auth2: " + auth2); -+ -+ req1 += "Proxy-Authorization: Basic " + auth2 + "\r\n"; -+ //dbg("req1: " + req1); -+ -+ dbg("added Proxy-Authorization: Basic ... to request"); -+ } -+ req1 += "\r\n"; -+ -+ try { -+ proxy_os.write(req1.getBytes()); -+ String reply = readline(proxy_is); -+ -+ dbg("proxy replied: " + reply.trim()); -+ -+ if (reply.indexOf("HTTP/1.") == 0 && reply.indexOf(" 407 ") > 0) { -+ proxy_auth = true; -+ proxySock.close(); -+ } else if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { -+ proxySock.close(); -+ proxySock = psocket(proxyHost, proxyPort); -+ if (proxySock == null) { -+ dbg("2-a sadly, returning a null socket"); -+ return; -+ } -+ } -+ } catch(Exception e) { -+ dbg("some proxy socket problem: " + e.getMessage()); -+ } -+ -+ /* read the rest of the HTTP headers */ -+ while (true) { -+ String line = readline(proxy_is); -+ dbg("proxy line: " + line.trim()); -+ if (proxy_auth) { -+ String uc = line.toLowerCase(); -+ if (uc.indexOf("proxy-authenticate:") == 0) { -+ if (uc.indexOf(" basic ") >= 0) { -+ int idx = uc.indexOf(" realm"); -+ if (idx >= 0) { -+ proxy_auth_basic_realm = uc.substring(idx+1); -+ } -+ } -+ } -+ } -+ if (line.equals("\r\n") || line.equals("\n")) { -+ break; -+ } -+ } -+ if (!proxy_auth || proxy_auth_basic_realm.equals("")) { -+ /* we only try once for the non-password case: */ -+ break; -+ } -+ } -+ } -+ -+ public SSLSocket proxy_socket(SSLSocketFactory factory) { -+ Properties props = null; -+ String proxyHost = null; -+ int proxyPort = 0; -+ String proxyHost_nossl = null; -+ int proxyPort_nossl = 0; -+ String str; -+ -+ /* see if we can guess the proxy info from Properties: */ -+ try { -+ props = System.getProperties(); -+ } catch (Exception e) { -+ /* sandboxed applet might not be able to read it. */ -+ dbg("props failed: " + e.getMessage()); -+ } -+ if (viewer.proxyHost != null) { -+ dbg("Using supplied proxy " + viewer.proxyHost + " " + viewer.proxyPort + " applet parameters."); -+ proxyHost = viewer.proxyHost; -+ if (viewer.proxyPort != null) { -+ proxyPort = gint(viewer.proxyPort); -+ } else { -+ proxyPort = 8080; -+ } -+ -+ } else if (props != null) { -+ dbg("\n---------------\nAll props:"); -+ props.list(System.out); -+ dbg("\n---------------\n\n"); -+ -+ /* scrape throught properties looking for proxy info: */ -+ -+ for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { -+ String s = (String) e.nextElement(); -+ String v = System.getProperty(s); -+ String s2 = s.toLowerCase(); -+ String v2 = v.toLowerCase(); -+ -+ if (s2.indexOf("proxy.https.host") >= 0) { -+ proxyHost = v2; -+ continue; -+ } -+ if (s2.indexOf("proxy.https.port") >= 0) { -+ proxyPort = gint(v2); -+ continue; -+ } -+ if (s2.indexOf("proxy.http.host") >= 0) { -+ proxyHost_nossl = v2; -+ continue; -+ } -+ if (s2.indexOf("proxy.http.port") >= 0) { -+ proxyPort_nossl = gint(v2); -+ continue; -+ } -+ } -+ -+ for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { -+ String s = (String) e.nextElement(); -+ String v = System.getProperty(s); -+ String s2 = s.toLowerCase(); -+ String v2 = v.toLowerCase(); -+ -+ if (proxyHost != null && proxyPort > 0) { -+ break; -+ } -+ -+ // look for something like: javaplugin.proxy.config.list = http=10.0.2.1:8082 -+ if (s2.indexOf("proxy") < 0 && v2.indexOf("proxy") < 0) { -+ continue; -+ } -+ if (v2.indexOf("http") < 0) { -+ continue; -+ } -+ -+ String[] pieces = v.split("[,;]"); -+ for (int i = 0; i < pieces.length; i++) { -+ String p = pieces[i]; -+ int j = p.indexOf("https"); -+ if (j < 0) { -+ j = p.indexOf("http"); -+ if (j < 0) { -+ continue; -+ } -+ } -+ j = p.indexOf("=", j); -+ if (j < 0) { -+ continue; -+ } -+ p = p.substring(j+1); -+ String [] hp = p.split(":"); -+ if (hp.length != 2) { -+ continue; -+ } -+ if (hp[0].length() > 1 && hp[1].length() > 1) { -+ -+ proxyPort = gint(hp[1]); -+ if (proxyPort < 0) { -+ continue; -+ } -+ proxyHost = new String(hp[0]); -+ break; -+ } -+ } -+ } -+ } -+ if (proxyHost != null) { -+ if (proxyHost_nossl != null && proxyPort_nossl > 0) { -+ dbg("Using http proxy info instead of https."); -+ proxyHost = proxyHost_nossl; -+ proxyPort = proxyPort_nossl; -+ } -+ } -+ -+ if (proxy_in_use) { -+ if (proxy_dialog_host != null && proxy_dialog_port > 0) { -+ proxyHost = proxy_dialog_host; -+ proxyPort = proxy_dialog_port; -+ } -+ if (proxyHost != null) { -+ dbg("Lucky us! we figured out the Proxy parameters: " + proxyHost + " " + proxyPort); -+ } else { -+ /* ask user to help us: */ -+ ProxyDialog pd = new ProxyDialog(proxyHost, proxyPort); -+ pd.queryUser(); -+ proxyHost = pd.getHost(); -+ proxyPort = pd.getPort(); -+ proxy_dialog_host = new String(proxyHost); -+ proxy_dialog_port = proxyPort; -+ dbg("User said host: " + pd.getHost() + " port: " + pd.getPort()); -+ } -+ -+ proxy_helper(proxyHost, proxyPort); -+ if (proxySock == null) { -+ return null; -+ } -+ } else if (viewer.CONNECT != null) { -+ dbg("viewer.CONNECT psocket:"); -+ proxySock = psocket(host, port); -+ if (proxySock == null) { -+ dbg("1-b sadly, returning a null socket"); -+ return null; -+ } -+ } -+ -+ if (viewer.CONNECT != null) { -+ String hp = viewer.CONNECT; -+ String req2 = "CONNECT " + hp + " HTTP/1.1\r\n" -+ + "Host: " + hp + "\r\n\r\n"; -+ -+ dbg("requesting2: " + req2); -+ -+ try { -+ proxy_os.write(req2.getBytes()); -+ String reply = readline(proxy_is); -+ -+ dbg("proxy replied2: " + reply.trim()); -+ -+ if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { -+ proxySock.close(); -+ proxySock = psocket(proxyHost, proxyPort); -+ if (proxySock == null) { -+ dbg("2-b sadly, returning a null socket"); -+ return null; -+ } -+ } -+ } catch(Exception e) { -+ dbg("proxy socket problem-2: " + e.getMessage()); -+ } -+ -+ while (true) { -+ String line = readline(proxy_is); -+ dbg("proxy line2: " + line.trim()); -+ if (line.equals("\r\n") || line.equals("\n")) { -+ break; -+ } -+ } -+ } -+ -+ Socket sslsock = null; -+ try { -+ sslsock = factory.createSocket(proxySock, host, port, true); -+ } catch(Exception e) { -+ dbg("sslsock prob: " + e.getMessage()); -+ dbg("3 sadly, returning a null socket"); -+ } -+ -+ return (SSLSocket) sslsock; -+ } -+ -+ Socket psocket(String h, int p) { -+ Socket psock = null; -+ try { -+ psock = new Socket(h, p); -+ proxy_is = new DataInputStream(new BufferedInputStream( -+ psock.getInputStream(), 16384)); -+ proxy_os = psock.getOutputStream(); -+ } catch(Exception e) { -+ dbg("psocket prob: " + e.getMessage()); -+ return null; -+ } -+ -+ return psock; -+ } -+ -+ String readline(DataInputStream i) { -+ byte[] ba = new byte[1]; -+ String s = new String(""); -+ ba[0] = 0; -+ try { -+ while (ba[0] != 0xa) { -+ ba[0] = (byte) i.readUnsignedByte(); -+ s += new String(ba); -+ } -+ } catch (Exception e) { -+ ; -+ } -+ return s; -+ } -+} -+ -+class TrustDialog implements ActionListener { -+ String msg, host, text; -+ int port; -+ java.security.cert.Certificate[] trustallCerts = null; -+ boolean viewing_cert = false; -+ boolean trust_this_session = false; -+ -+ /* -+ * this is the gui to show the user the cert and info and ask -+ * them if they want to continue using this cert. -+ */ -+ -+ Button ok, cancel, viewcert; -+ TextArea textarea; -+ Checkbox accept, deny; -+ Dialog dialog; -+ -+ String s1 = "Accept this certificate temporarily for this session"; -+ String s2 = "Do not accept this certificate and do not connect to" -+ + " this VNC server"; -+ String ln = "\n---------------------------------------------------\n\n"; -+ -+ TrustDialog (String h, int p, java.security.cert.Certificate[] s) { -+ host = h; -+ port = p; -+ trustallCerts = s; -+ -+ msg = "VNC Server " + host + ":" + port + " Not Verified"; -+ } -+ -+ public boolean queryUser(String reason) { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame(msg); -+ -+ dialog = new Dialog(frame, true); -+ -+ String infostr = ""; -+ if (trustallCerts.length == 1) { -+ CertInfo ci = new CertInfo(trustallCerts[0]); -+ infostr = ci.get_certinfo("all"); -+ } -+ if (reason != null) { -+ reason += "\n\n"; -+ } -+ -+ text = "\n" -++ "Unable to verify the identity of\n" -++ "\n" -++ " " + host + ":" + port + "\n" -++ "\n" -++ infostr -++ "\n" -++ "as a trusted VNC server.\n" -++ "\n" -++ reason -++ "In General not being able to verify the VNC Server and/or your seeing this Dialog\n" -++ "is due to one of the following:\n" -++ "\n" -++ " - Your requesting to View the Certificate before accepting.\n" -++ "\n" -++ " - The VNC server is using a Self-Signed Certificate or a Certificate\n" -++ " Authority not recognized by your Web Browser or Java Plugin runtime.\n" -++ "\n" -++ " - The use of an Apache SSL portal scheme employing CONNECT proxying AND\n" -++ " the Apache Web server has a certificate *different* from the VNC server's.\n" -++ "\n" -++ " - No previously accepted Certificate (via Web Broswer/Java Plugin) could be\n" -++ " obtained by this applet to compare the VNC Server Certificate against.\n" -++ "\n" -++ " - The VNC Server's Certificate does not match the one specified in the\n" -++ " supplied 'serverCert' Java Applet Parameter.\n" -++ "\n" -++ " - A Man-In-The-Middle attack impersonating as the VNC server that you wish\n" -++ " to connect to. (Wouldn't that be exciting!!)\n" -++ "\n" -++ "By safely copying the VNC server's Certificate (or using a common Certificate\n" -++ "Authority certificate) you can configure your Web Browser and Java Plugin to\n" -++ "automatically authenticate this VNC Server.\n" -++ "\n" -++ "If you do so, then you will only have to click \"Yes\" when this VNC Viewer\n" -++ "applet asks you whether to trust your Browser/Java Plugin's acceptance of the\n" -++ "certificate (except for the Apache portal case above where they don't match.)\n" -++ "\n" -++ "You can also set the applet parameter 'trustUrlVncCert=yes' to automatically\n" -++ "accept certificates already accepted/trusted by your Web Browser/Java Plugin,\n" -++ "and thereby see no dialog from this VNC Viewer applet.\n" -+; -+ -+ /* the accept / do-not-accept radio buttons: */ -+ CheckboxGroup checkbox = new CheckboxGroup(); -+ accept = new Checkbox(s1, true, checkbox); -+ deny = new Checkbox(s2, false, checkbox); -+ -+ /* put the checkboxes in a panel: */ -+ Panel check = new Panel(); -+ check.setLayout(new GridLayout(2, 1)); -+ -+ check.add(accept); -+ check.add(deny); -+ -+ /* make the 3 buttons: */ -+ ok = new Button("OK"); -+ cancel = new Button("Cancel"); -+ viewcert = new Button("View Certificate"); -+ -+ ok.addActionListener(this); -+ cancel.addActionListener(this); -+ viewcert.addActionListener(this); -+ -+ /* put the buttons in their own panel: */ -+ Panel buttonrow = new Panel(); -+ buttonrow.setLayout(new FlowLayout(FlowLayout.LEFT)); -+ buttonrow.add(viewcert); -+ buttonrow.add(ok); -+ buttonrow.add(cancel); -+ -+ /* label at the top: */ -+ Label label = new Label(msg, Label.CENTER); -+ label.setFont(new Font("Helvetica", Font.BOLD, 16)); -+ -+ /* textarea in the middle */ -+ textarea = new TextArea(text, 38, 64, -+ TextArea.SCROLLBARS_VERTICAL_ONLY); -+ textarea.setEditable(false); -+ -+ /* put the two panels in their own panel at bottom: */ -+ Panel bot = new Panel(); -+ bot.setLayout(new GridLayout(2, 1)); -+ bot.add(check); -+ bot.add(buttonrow); -+ -+ /* now arrange things inside the dialog: */ -+ dialog.setLayout(new BorderLayout()); -+ -+ dialog.add("North", label); -+ dialog.add("South", bot); -+ dialog.add("Center", textarea); -+ -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til OK or Cancel pressed. */ -+ -+ return trust_this_session; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ -+ if (evt.getSource() == viewcert) { -+ /* View Certificate button clicked */ -+ if (viewing_cert) { -+ /* show the original info text: */ -+ textarea.setText(text); -+ viewcert.setLabel("View Certificate"); -+ viewing_cert = false; -+ } else { -+ int i; -+ /* show all (likely just one) certs: */ -+ textarea.setText(""); -+ for (i=0; i < trustallCerts.length; i++) { -+ int j = i + 1; -+ textarea.append("Certificate[" + -+ j + "]\n\n"); -+ textarea.append( -+ trustallCerts[i].toString()); -+ textarea.append(ln); -+ } -+ viewcert.setLabel("View Info"); -+ viewing_cert = true; -+ -+ textarea.setCaretPosition(0); -+ } -+ -+ } else if (evt.getSource() == ok) { -+ /* OK button clicked */ -+ if (accept.getState()) { -+ trust_this_session = true; -+ } else { -+ trust_this_session = false; -+ } -+ //dialog.dispose(); -+ dialog.hide(); -+ -+ } else if (evt.getSource() == cancel) { -+ /* Cancel button clicked */ -+ trust_this_session = false; -+ -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ } -+ -+ String get_certinfo() { -+ String all = ""; -+ String fields[] = {"CN", "OU", "O", "L", "C"}; -+ int i; -+ if (trustallCerts.length < 1) { -+ all = ""; -+ return all; -+ } -+ String cert = trustallCerts[0].toString(); -+ -+ /* -+ * For now we simply scrape the cert string, there must -+ * be an API for this... perhaps optionValue? -+ */ -+ -+ for (i=0; i < fields.length; i++) { -+ int f, t, t1, t2; -+ String sub, mat = fields[i] + "="; -+ -+ f = cert.indexOf(mat, 0); -+ if (f > 0) { -+ t1 = cert.indexOf(", ", f); -+ t2 = cert.indexOf("\n", f); -+ if (t1 < 0 && t2 < 0) { -+ continue; -+ } else if (t1 < 0) { -+ t = t2; -+ } else if (t2 < 0) { -+ t = t1; -+ } else if (t1 < t2) { -+ t = t1; -+ } else { -+ t = t2; -+ } -+ if (t > f) { -+ sub = cert.substring(f, t); -+ all = all + " " + sub + "\n"; -+ } -+ } -+ } -+ return all; -+ } -+} -+ -+class ProxyDialog implements ActionListener { -+ String guessedHost = null; -+ String guessedPort = null; -+ /* -+ * this is the gui to show the user the cert and info and ask -+ * them if they want to continue using this cert. -+ */ -+ -+ Button ok; -+ Dialog dialog; -+ TextField entry; -+ String reply = ""; -+ -+ ProxyDialog (String h, int p) { -+ guessedHost = h; -+ try { -+ guessedPort = Integer.toString(p); -+ } catch (Exception e) { -+ guessedPort = "8080"; -+ } -+ } -+ -+ public void queryUser() { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame("Need Proxy host:port"); -+ -+ dialog = new Dialog(frame, true); -+ -+ -+ Label label = new Label("Please Enter your https Proxy info as host:port", Label.CENTER); -+ //label.setFont(new Font("Helvetica", Font.BOLD, 16)); -+ entry = new TextField(30); -+ ok = new Button("OK"); -+ ok.addActionListener(this); -+ -+ String guess = ""; -+ if (guessedHost != null) { -+ guess = guessedHost + ":" + guessedPort; -+ } -+ entry.setText(guess); -+ -+ dialog.setLayout(new BorderLayout()); -+ dialog.add("North", label); -+ dialog.add("Center", entry); -+ dialog.add("South", ok); -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til OK or Cancel pressed. */ -+ return; -+ } -+ -+ public String getHost() { -+ int i = reply.indexOf(":"); -+ if (i < 0) { -+ return "unknown"; -+ } -+ String h = reply.substring(0, i); -+ return h; -+ } -+ -+ public int getPort() { -+ int i = reply.indexOf(":"); -+ int p = 8080; -+ if (i < 0) { -+ return p; -+ } -+ i++; -+ String ps = reply.substring(i); -+ try { -+ Integer I = new Integer(ps); -+ p = I.intValue(); -+ } catch (Exception e) { -+ ; -+ } -+ return p; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ System.out.println(evt.getActionCommand()); -+ if (evt.getSource() == ok) { -+ reply = entry.getText(); -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ } -+} -+ -+class ProxyPasswdDialog implements ActionListener { -+ String guessedHost = null; -+ String guessedPort = null; -+ String guessedUser = null; -+ String guessedPasswd = null; -+ String realm = null; -+ /* -+ * this is the gui to show the user the cert and info and ask -+ * them if they want to continue using this cert. -+ */ -+ -+ Button ok; -+ Dialog dialog; -+ TextField entry1; -+ TextField entry2; -+ String reply1 = ""; -+ String reply2 = ""; -+ -+ ProxyPasswdDialog (String h, int p, String realm) { -+ guessedHost = h; -+ try { -+ guessedPort = Integer.toString(p); -+ } catch (Exception e) { -+ guessedPort = "8080"; -+ } -+ this.realm = realm; -+ } -+ -+ public void queryUser() { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame("Proxy Requires Username and Password"); -+ -+ dialog = new Dialog(frame, true); -+ -+ //Label label = new Label("Please Enter your Web Proxy Username in the top Entry and Password in the bottom Entry", Label.CENTER); -+ TextArea label = new TextArea("Please Enter your Web Proxy\nUsername in the Top Entry and\nPassword in the Bottom Entry,\nand then press OK.", 4, 20, TextArea.SCROLLBARS_NONE); -+ entry1 = new TextField(30); -+ entry2 = new TextField(30); -+ entry2.setEchoChar('*'); -+ ok = new Button("OK"); -+ ok.addActionListener(this); -+ -+ dialog.setLayout(new BorderLayout()); -+ dialog.add("North", label); -+ dialog.add("Center", entry1); -+ dialog.add("South", entry2); -+ dialog.add("East", ok); -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til OK or Cancel pressed. */ -+ return; -+ } -+ -+ public String getAuth() { -+ return reply1 + ":" + reply2; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ System.out.println(evt.getActionCommand()); -+ if (evt.getSource() == ok) { -+ reply1 = entry1.getText(); -+ reply2 = entry2.getText(); -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ } -+} -+ -+class ClientCertDialog implements ActionListener { -+ -+ Button ok; -+ Dialog dialog; -+ TextField entry; -+ String reply = ""; -+ -+ ClientCertDialog() { -+ ; -+ } -+ -+ public String queryUser() { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame("Enter SSL Client Cert+Key String"); -+ -+ dialog = new Dialog(frame, true); -+ -+ -+ Label label = new Label("Please Enter the SSL Client Cert+Key String 308204c0...,...522d2d0a", Label.CENTER); -+ entry = new TextField(30); -+ ok = new Button("OK"); -+ ok.addActionListener(this); -+ -+ dialog.setLayout(new BorderLayout()); -+ dialog.add("North", label); -+ dialog.add("Center", entry); -+ dialog.add("South", ok); -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til OK or Cancel pressed. */ -+ return reply; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ System.out.println(evt.getActionCommand()); -+ if (evt.getSource() == ok) { -+ reply = entry.getText(); -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ } -+} -+ -+class BrowserCertsDialog implements ActionListener { -+ Button yes, no; -+ Dialog dialog; -+ String vncServer; -+ String hostport; -+ public boolean showCertDialog = true; -+ -+ BrowserCertsDialog(String serv, String hp) { -+ vncServer = serv; -+ hostport = hp; -+ } -+ -+ public void queryUser() { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame("Use Browser/JVM Certs?"); -+ -+ dialog = new Dialog(frame, true); -+ -+ String m = ""; -+m += "\n"; -+m += "This VNC Viewer applet does not have its own keystore to track\n"; -+m += "SSL certificates, and so cannot authenticate the certificate\n"; -+m += "of the VNC Server:\n"; -+m += "\n"; -+m += " " + hostport + "\n\n " + vncServer + "\n"; -+m += "\n"; -+m += "on its own.\n"; -+m += "\n"; -+m += "However, it has noticed that your Web Browser and/or Java VM Plugin\n"; -+m += "has previously accepted the same certificate. You may have set\n"; -+m += "this up permanently or just for this session, or the server\n"; -+m += "certificate was signed by a CA cert that your Web Browser or\n"; -+m += "Java VM Plugin has.\n"; -+m += "\n"; -+m += "If the VNC Server connection times out while you are reading this\n"; -+m += "dialog, then restart the connection and try again.\n"; -+m += "\n"; -+m += "Should this VNC Viewer applet now connect to the above VNC server?\n"; -+m += "\n"; -+ -+ TextArea textarea = new TextArea(m, 22, 64, -+ TextArea.SCROLLBARS_VERTICAL_ONLY); -+ textarea.setEditable(false); -+ yes = new Button("Yes"); -+ yes.addActionListener(this); -+ no = new Button("No, Let Me See the Certificate."); -+ no.addActionListener(this); -+ -+ dialog.setLayout(new BorderLayout()); -+ dialog.add("North", textarea); -+ dialog.add("Center", yes); -+ dialog.add("South", no); -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til Yes or No pressed. */ -+ System.out.println("done show()"); -+ return; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ System.out.println(evt.getActionCommand()); -+ if (evt.getSource() == yes) { -+ showCertDialog = false; -+ //dialog.dispose(); -+ dialog.hide(); -+ } else if (evt.getSource() == no) { -+ showCertDialog = true; -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ System.out.println("done actionPerformed()"); -+ } -+} -+ -+class CertInfo { -+ String fields[] = {"CN", "OU", "O", "L", "C"}; -+ java.security.cert.Certificate cert; -+ String certString = ""; -+ -+ CertInfo(java.security.cert.Certificate c) { -+ cert = c; -+ certString = cert.toString(); -+ } -+ -+ String get_certinfo(String which) { -+ int i; -+ String cs = new String(certString); -+ String all = ""; -+ -+ /* -+ * For now we simply scrape the cert string, there must -+ * be an API for this... perhaps optionValue? -+ */ -+ for (i=0; i < fields.length; i++) { -+ int f, t, t1, t2; -+ String sub, mat = fields[i] + "="; -+ -+ f = cs.indexOf(mat, 0); -+ if (f > 0) { -+ t1 = cs.indexOf(", ", f); -+ t2 = cs.indexOf("\n", f); -+ if (t1 < 0 && t2 < 0) { -+ continue; -+ } else if (t1 < 0) { -+ t = t2; -+ } else if (t2 < 0) { -+ t = t1; -+ } else if (t1 < t2) { -+ t = t1; -+ } else { -+ t = t2; -+ } -+ if (t > f) { -+ sub = cs.substring(f, t); -+ all = all + " " + sub + "\n"; -+ if (which.equals(fields[i])) { -+ return sub; -+ } -+ } -+ } -+ } -+ if (which.equals("all")) { -+ return all; -+ } else { -+ return ""; -+ } -+ } -+} -+ -+class Base64Coder { -+ -+ // Mapping table from 6-bit nibbles to Base64 characters. -+ private static char[] map1 = new char[64]; -+ static { -+ int i=0; -+ for (char c='A'; c<='Z'; c++) map1[i++] = c; -+ for (char c='a'; c<='z'; c++) map1[i++] = c; -+ for (char c='0'; c<='9'; c++) map1[i++] = c; -+ map1[i++] = '+'; map1[i++] = '/'; } -+ -+ // Mapping table from Base64 characters to 6-bit nibbles. -+ private static byte[] map2 = new byte[128]; -+ static { -+ for (int i=0; i<map2.length; i++) map2[i] = -1; -+ for (int i=0; i<64; i++) map2[map1[i]] = (byte)i; } -+ -+ /** -+ * Encodes a string into Base64 format. -+ * No blanks or line breaks are inserted. -+ * @param s a String to be encoded. -+ * @return A String with the Base64 encoded data. -+ */ -+ public static String encodeString (String s) { -+ return new String(encode(s.getBytes())); } -+ -+ /** -+ * Encodes a byte array into Base64 format. -+ * No blanks or line breaks are inserted. -+ * @param in an array containing the data bytes to be encoded. -+ * @return A character array with the Base64 encoded data. -+ */ -+ public static char[] encode (byte[] in) { -+ return encode(in,in.length); } -+ -+ /** -+ * Encodes a byte array into Base64 format. -+ * No blanks or line breaks are inserted. -+ * @param in an array containing the data bytes to be encoded. -+ * @param iLen number of bytes to process in <code>in</code>. -+ * @return A character array with the Base64 encoded data. -+ */ -+ public static char[] encode (byte[] in, int iLen) { -+ int oDataLen = (iLen*4+2)/3; // output length without padding -+ int oLen = ((iLen+2)/3)*4; // output length including padding -+ char[] out = new char[oLen]; -+ int ip = 0; -+ int op = 0; -+ while (ip < iLen) { -+ int i0 = in[ip++] & 0xff; -+ int i1 = ip < iLen ? in[ip++] & 0xff : 0; -+ int i2 = ip < iLen ? in[ip++] & 0xff : 0; -+ int o0 = i0 >>> 2; -+ int o1 = ((i0 & 3) << 4) | (i1 >>> 4); -+ int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); -+ int o3 = i2 & 0x3F; -+ out[op++] = map1[o0]; -+ out[op++] = map1[o1]; -+ out[op] = op < oDataLen ? map1[o2] : '='; op++; -+ out[op] = op < oDataLen ? map1[o3] : '='; op++; } -+ return out; } -+ -+ /** -+ * Decodes a string from Base64 format. -+ * @param s a Base64 String to be decoded. -+ * @return A String containing the decoded data. -+ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. -+ */ -+ public static String decodeString (String s) { -+ return new String(decode(s)); } -+ -+ /** -+ * Decodes a byte array from Base64 format. -+ * @param s a Base64 String to be decoded. -+ * @return An array containing the decoded data bytes. -+ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. -+ */ -+ public static byte[] decode (String s) { -+ return decode(s.toCharArray()); } -+ -+ /** -+ * Decodes a byte array from Base64 format. -+ * No blanks or line breaks are allowed within the Base64 encoded data. -+ * @param in a character array containing the Base64 encoded data. -+ * @return An array containing the decoded data bytes. -+ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. -+ */ -+ public static byte[] decode (char[] in) { -+ int iLen = in.length; -+ if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4."); -+ while (iLen > 0 && in[iLen-1] == '=') iLen--; -+ int oLen = (iLen*3) / 4; -+ byte[] out = new byte[oLen]; -+ int ip = 0; -+ int op = 0; -+ while (ip < iLen) { -+ int i0 = in[ip++]; -+ int i1 = in[ip++]; -+ int i2 = ip < iLen ? in[ip++] : 'A'; -+ int i3 = ip < iLen ? in[ip++] : 'A'; -+ if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) -+ throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); -+ int b0 = map2[i0]; -+ int b1 = map2[i1]; -+ int b2 = map2[i2]; -+ int b3 = map2[i3]; -+ if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) -+ throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); -+ int o0 = ( b0 <<2) | (b1>>>4); -+ int o1 = ((b1 & 0xf)<<4) | (b2>>>2); -+ int o2 = ((b2 & 3)<<6) | b3; -+ out[op++] = (byte)o0; -+ if (op<oLen) out[op++] = (byte)o1; -+ if (op<oLen) out[op++] = (byte)o2; } -+ return out; } -+ -+ // Dummy constructor. -+ private Base64Coder() {} -+ -+} -diff -Naur vnc_javasrc.orig/VncCanvas.java vnc_javasrc/VncCanvas.java ---- vnc_javasrc.orig/VncCanvas.java 2004-10-10 02:15:54.000000000 -0400 -+++ vnc_javasrc/VncCanvas.java 2010-11-30 21:01:15.000000000 -0500 -@@ -28,13 +28,14 @@ - import java.lang.*; - import java.util.zip.*; - -+import java.util.Collections; - - // - // VncCanvas is a subclass of Canvas which draws a VNC desktop on it. - // - - class VncCanvas extends Canvas -- implements KeyListener, MouseListener, MouseMotionListener { -+ implements KeyListener, MouseListener, MouseMotionListener, MouseWheelListener { - - VncViewer viewer; - RfbProto rfb; -@@ -81,6 +82,20 @@ - cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6)); - cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF); - -+ // kludge to not show any Java cursor in the canvas since we are -+ // showing the soft cursor (should be a user setting...) -+ Cursor dot = Toolkit.getDefaultToolkit().createCustomCursor( -+ Toolkit.getDefaultToolkit().createImage(new byte[4]), new Point(0,0), -+ "dot"); -+ this.setCursor(dot); -+ -+ // while we are at it... get rid of the keyboard traversals that -+ // make it so we can't type a Tab character: -+ this.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, -+ Collections.EMPTY_SET); -+ this.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, -+ Collections.EMPTY_SET); -+ - colors = new Color[256]; - for (int i = 0; i < 256; i++) - colors[i] = new Color(cm8.getRGB(i)); -@@ -169,6 +184,7 @@ - inputEnabled = true; - addMouseListener(this); - addMouseMotionListener(this); -+ addMouseWheelListener(this); - if (viewer.showControls) { - viewer.buttonPanel.enableRemoteAccessControls(true); - } -@@ -177,6 +193,7 @@ - inputEnabled = false; - removeMouseListener(this); - removeMouseMotionListener(this); -+ removeMouseWheelListener(this); - if (viewer.showControls) { - viewer.buttonPanel.enableRemoteAccessControls(false); - } -@@ -1190,6 +1207,9 @@ - public void mouseDragged(MouseEvent evt) { - processLocalMouseEvent(evt, true); - } -+ public void mouseWheelMoved(MouseWheelEvent evt) { -+ processLocalMouseWheelEvent(evt); -+ } - - public void processLocalKeyEvent(KeyEvent evt) { - if (viewer.rfb != null && rfb.inNormalProtocol) { -@@ -1221,6 +1241,19 @@ - evt.consume(); - } - -+ public void processLocalMouseWheelEvent(MouseWheelEvent evt) { -+ if (viewer.rfb != null && rfb.inNormalProtocol) { -+ synchronized(rfb) { -+ try { -+ rfb.writeWheelEvent(evt); -+ } catch (Exception e) { -+ e.printStackTrace(); -+ } -+ rfb.notify(); -+ } -+ } -+ } -+ - public void processLocalMouseEvent(MouseEvent evt, boolean moved) { - if (viewer.rfb != null && rfb.inNormalProtocol) { - if (moved) { -@@ -1387,9 +1420,9 @@ - result = cm8.getRGB(pixBuf[i]); - } else { - result = 0xFF000000 | -- (pixBuf[i * 4 + 1] & 0xFF) << 16 | -- (pixBuf[i * 4 + 2] & 0xFF) << 8 | -- (pixBuf[i * 4 + 3] & 0xFF); -+ (pixBuf[i * 4 + 2] & 0xFF) << 16 | -+ (pixBuf[i * 4 + 1] & 0xFF) << 8 | -+ (pixBuf[i * 4 + 0] & 0xFF); - } - } else { - result = 0; // Transparent pixel -@@ -1403,9 +1436,9 @@ - result = cm8.getRGB(pixBuf[i]); - } else { - result = 0xFF000000 | -- (pixBuf[i * 4 + 1] & 0xFF) << 16 | -- (pixBuf[i * 4 + 2] & 0xFF) << 8 | -- (pixBuf[i * 4 + 3] & 0xFF); -+ (pixBuf[i * 4 + 2] & 0xFF) << 16 | -+ (pixBuf[i * 4 + 1] & 0xFF) << 8 | -+ (pixBuf[i * 4 + 0] & 0xFF); - } - } else { - result = 0; // Transparent pixel -diff -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncViewer.java ---- vnc_javasrc.orig/VncViewer.java 2004-03-04 08:34:25.000000000 -0500 -+++ vnc_javasrc/VncViewer.java 2010-03-27 17:57:04.000000000 -0400 -@@ -29,6 +29,7 @@ - import java.awt.event.*; - import java.io.*; - import java.net.*; -+import java.util.*; - - public class VncViewer extends java.applet.Applet - implements java.lang.Runnable, WindowListener { -@@ -80,7 +81,7 @@ - // Variables read from parameter values. - String socketFactory; - String host; -- int port; -+ int port, vncserverport; - boolean showControls; - boolean offerRelogin; - boolean showOfflineDesktop; -@@ -88,6 +89,24 @@ - int deferCursorUpdates; - int deferUpdateRequests; - -+ boolean disableSSL; -+ boolean GET; -+ String CONNECT; -+ String urlPrefix; -+ String httpsPort; -+ String oneTimeKey; -+ String serverCert; -+ String proxyHost; -+ String proxyPort; -+ boolean forceProxy; -+ boolean ignoreProxy; -+ boolean trustAllVncCerts; -+ boolean trustUrlVncCert; -+ boolean debugCerts; -+ boolean debugKeyboard; -+ boolean mapF5_to_atsign; -+ boolean forbid_Ctrl_Alt; -+ - // Reference to this applet for inter-applet communication. - public static java.applet.Applet refApplet; - -@@ -282,10 +301,24 @@ - validate(); - } - -- while (!tryAuthenticate()) { -- authenticator.retry(); -- authenticatorUnixLogin.retry(); -- } -+ if (false) { -+ /* a bug on retries: 'Error: bad position: 8' sun.awt.X11.XTextFieldPeer.setCaretPosition(XTextFieldPeer.java:215) */ -+ while (!tryAuthenticate()) { -+ authenticator.retry(); -+ authenticatorUnixLogin.retry(); -+ } -+ } else { -+ /* just try once and not forever... */ -+ if (!tryAuthenticate()) { -+ showConnectionStatus("Authentication Failed."); -+ showMessage("Authentication Failed."); -+ if (!offerRelogin) { -+ fatalError("auth failed."); -+ } -+ } else { -+ //showConnectionStatus("Authentication OK."); -+ } -+ } - } - - -@@ -428,7 +461,10 @@ - gbc.ipadx = 100; - gbc.ipady = 50; - gridbag.setConstraints(authPanel, gbc); -+ try { - vncContainer.add(authPanel); -+ } catch (Exception e) { -+ } - - if (inSeparateFrame) { - vncFrame.pack(); -@@ -590,9 +626,28 @@ - fatalError("HOST parameter not specified"); - } - } -+ Date d = new Date(); -+ System.out.println("-\nSSL VNC Java Applet starting. " + d); - -- String str = readParameter("PORT", true); -- port = Integer.parseInt(str); -+ port = 0; -+ String str = readParameter("PORT", false); -+ if (str != null) { -+ port = Integer.parseInt(str); -+ } -+ // When there is a proxy VNCSERVERPORT may be inaccessible (inside firewall). -+ vncserverport = 0; -+ str = readParameter("VNCSERVERPORT", false); -+ if (str != null) { -+ vncserverport = Integer.parseInt(str); -+ } -+ if (port == 0 && vncserverport == 0) { -+ fatalError("Neither PORT nor VNCSERVERPORT parameters specified"); -+ } -+ if (port == 0) { -+ // Nevertheless, fall back to vncserverport if we have to. -+ System.out.println("using vncserverport: '" + vncserverport + "' for PORT."); -+ port = vncserverport; -+ } - - if (inAnApplet) { - str = readParameter("Open New Window", false); -@@ -626,6 +681,121 @@ - - // SocketFactory. - socketFactory = readParameter("SocketFactory", false); -+ -+ // SSL -+ disableSSL = false; -+ str = readParameter("DisableSSL", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) -+ disableSSL = true; -+ -+ httpsPort = readParameter("httpsPort", false); -+ -+ // Extra GET, CONNECT string: -+ CONNECT = readParameter("CONNECT", false); -+ if (CONNECT != null) { -+ CONNECT = CONNECT.replaceAll(" ", ":"); -+ } -+ -+ GET = false; -+ str = readParameter("GET", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ GET = true; -+ } -+ if (str != null && str.equalsIgnoreCase("1")) { -+ GET = true; -+ } -+ -+ urlPrefix = readParameter("urlPrefix", false); -+ if (urlPrefix != null) { -+ urlPrefix = urlPrefix.replaceAll("%2F", "/"); -+ urlPrefix = urlPrefix.replaceAll("%2f", "/"); -+ urlPrefix = urlPrefix.replaceAll("_2F_", "/"); -+ if (urlPrefix.indexOf("/") != 0) { -+ urlPrefix = "/" + urlPrefix; -+ } -+ } else { -+ urlPrefix = ""; -+ } -+ System.out.println("urlPrefix: '" + urlPrefix + "'"); -+ -+ oneTimeKey = readParameter("oneTimeKey", false); -+ if (oneTimeKey != null) { -+ System.out.println("oneTimeKey is set."); -+ } -+ -+ serverCert = readParameter("serverCert", false); -+ if (serverCert != null) { -+ System.out.println("serverCert is set."); -+ } -+ -+ forceProxy = false; -+ proxyHost = null; -+ proxyPort = null; -+ str = readParameter("forceProxy", false); -+ if (str != null) { -+ if (str.equalsIgnoreCase("Yes")) { -+ forceProxy = true; -+ } else if (str.equalsIgnoreCase("No")) { -+ forceProxy = false; -+ } else { -+ forceProxy = true; -+ String[] pieces = str.split(" "); -+ proxyHost = new String(pieces[0]); -+ if (pieces.length >= 2) { -+ proxyPort = new String(pieces[1]); -+ } else { -+ proxyPort = new String("8080"); -+ } -+ } -+ } -+ str = readParameter("proxyHost", false); -+ if (str != null) { -+ proxyHost = new String(str); -+ } -+ str = readParameter("proxyPort", false); -+ if (str != null) { -+ proxyPort = new String(str); -+ } -+ if (proxyHost != null && proxyPort == null) { -+ proxyPort = new String("8080"); -+ } -+ -+ ignoreProxy = false; -+ str = readParameter("ignoreProxy", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ ignoreProxy = true; -+ } -+ -+ trustAllVncCerts = false; -+ str = readParameter("trustAllVncCerts", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ trustAllVncCerts = true; -+ } -+ trustUrlVncCert = false; -+ str = readParameter("trustUrlVncCert", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ trustUrlVncCert = true; -+ } -+ debugCerts = false; -+ str = readParameter("debugCerts", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ debugCerts = true; -+ } -+ debugKeyboard = false; -+ str = readParameter("debugKeyboard", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ debugKeyboard = true; -+ } -+ mapF5_to_atsign = false; -+ str = readParameter("mapF5_to_atsign", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ mapF5_to_atsign = true; -+ } -+ forbid_Ctrl_Alt = false; -+ str = readParameter("forbid_Ctrl_Alt", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ forbid_Ctrl_Alt = true; -+ } - } - - public String readParameter(String name, boolean required) { diff --git a/classes/ssl/ultra.vnc b/classes/ssl/ultra.vnc deleted file mode 100644 index 3c57445..0000000 --- a/classes/ssl/ultra.vnc +++ /dev/null @@ -1,28 +0,0 @@ -<!-- - index.vnc - default HTML page for TightVNC Java viewer applet, to be - used with Xvnc. On any file ending in .vnc, the HTTP server embedded in - Xvnc will substitute the following variables when preceded by a dollar: - USER, DESKTOP, DISPLAY, APPLETWIDTH, APPLETHEIGHT, WIDTH, HEIGHT, PORT, - PARAMS. Use two dollar signs ($$) to get a dollar sign in the generated - HTML page. - - NOTE: the $PARAMS variable is not supported by the standard VNC, so - make sure you have TightVNC on the server side, if you're using this - variable. ---> - -<HTML> -<TITLE> -$USER's $DESKTOP desktop ($DISPLAY) -</TITLE> -<APPLET CODE=VncViewer.class ARCHIVE=UltraViewerSSL.jar - WIDTH=$APPLETWIDTH HEIGHT=$APPLETHEIGHT> -<param name=PORT value=$PORT> -<param name="Open New Window" value=yes> -<param name="ignoreMSLogonCheck" value=yes> -<param name="delayAuthPanel" value=yes> -$PARAMS -</APPLET> -<BR> -<A href="http://www.karlrunge.com/x11vnc">x11vnc site</A> -</HTML> diff --git a/classes/ssl/ultraproxy.vnc b/classes/ssl/ultraproxy.vnc deleted file mode 100644 index fd842c4..0000000 --- a/classes/ssl/ultraproxy.vnc +++ /dev/null @@ -1,28 +0,0 @@ -<!-- - index.vnc - default HTML page for TightVNC Java viewer applet, to be - used with Xvnc. On any file ending in .vnc, the HTTP server embedded in - Xvnc will substitute the following variables when preceded by a dollar: - USER, DESKTOP, DISPLAY, APPLETWIDTH, APPLETHEIGHT, WIDTH, HEIGHT, PORT, - PARAMS. Use two dollar signs ($$) to get a dollar sign in the generated - HTML page. - - NOTE: the $PARAMS variable is not supported by the standard VNC, so - make sure you have TightVNC on the server side, if you're using this - variable. ---> - -<HTML> -<TITLE> -$USER's $DESKTOP desktop ($DISPLAY) -</TITLE> -<APPLET CODE=VncViewer.class ARCHIVE=SignedUltraViewerSSL.jar - WIDTH=$APPLETWIDTH HEIGHT=$APPLETHEIGHT> -<param name="Open New Window" value=yes> -<param name="ignoreMSLogonCheck" value=yes> -<param name="delayAuthPanel" value=yes> -<param name=VNCSERVERPORT value=$PORT> -$PARAMS -</APPLET> -<BR> -<A href="http://www.karlrunge.com/x11vnc">x11vnc site</A> -</HTML> diff --git a/classes/ssl/ultrasigned.vnc b/classes/ssl/ultrasigned.vnc deleted file mode 100644 index a711655..0000000 --- a/classes/ssl/ultrasigned.vnc +++ /dev/null @@ -1,28 +0,0 @@ -<!-- - index.vnc - default HTML page for TightVNC Java viewer applet, to be - used with Xvnc. On any file ending in .vnc, the HTTP server embedded in - Xvnc will substitute the following variables when preceded by a dollar: - USER, DESKTOP, DISPLAY, APPLETWIDTH, APPLETHEIGHT, WIDTH, HEIGHT, PORT, - PARAMS. Use two dollar signs ($$) to get a dollar sign in the generated - HTML page. - - NOTE: the $PARAMS variable is not supported by the standard VNC, so - make sure you have TightVNC on the server side, if you're using this - variable. ---> - -<HTML> -<TITLE> -$USER's $DESKTOP desktop ($DISPLAY) -</TITLE> -<APPLET CODE=VncViewer.class ARCHIVE=SignedUltraViewerSSL.jar - WIDTH=$APPLETWIDTH HEIGHT=$APPLETHEIGHT> -<param name=PORT value=$PORT> -<param name="Open New Window" value=yes> -<param name="ignoreMSLogonCheck" value=yes> -<param name="delayAuthPanel" value=yes> -$PARAMS -</APPLET> -<BR> -<A href="http://www.karlrunge.com/x11vnc">x11vnc site</A> -</HTML> diff --git a/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch b/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch deleted file mode 100644 index 3309860..0000000 --- a/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch +++ /dev/null @@ -1,5494 +0,0 @@ -diff -Naur JavaViewer.orig/ButtonPanel.java JavaViewer/ButtonPanel.java ---- JavaViewer.orig/ButtonPanel.java 2004-12-12 20:51:02.000000000 -0500 -+++ JavaViewer/ButtonPanel.java 2007-05-31 15:40:45.000000000 -0400 -@@ -43,30 +43,36 @@ - viewer = v; - - setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); -- disconnectButton = new Button("Disconnect"); -+ if (v.ftpOnly) { -+ disconnectButton = new Button("Quit"); -+ } else { -+ disconnectButton = new Button("Close"); -+ } - disconnectButton.setEnabled(false); - add(disconnectButton); - disconnectButton.addActionListener(this); -- optionsButton = new Button("Options"); -- add(optionsButton); -- optionsButton.addActionListener(this); -- clipboardButton = new Button("Clipboard"); -- clipboardButton.setEnabled(false); -- add(clipboardButton); -- clipboardButton.addActionListener(this); -- if (viewer.rec != null) { -- recordButton = new Button("Record"); -- add(recordButton); -- recordButton.addActionListener(this); -- } -- ctrlAltDelButton = new Button("Send Ctrl-Alt-Del"); -- ctrlAltDelButton.setEnabled(false); -- add(ctrlAltDelButton); -- ctrlAltDelButton.addActionListener(this); -- refreshButton = new Button("Refresh"); -- refreshButton.setEnabled(false); -- add(refreshButton); -- refreshButton.addActionListener(this); -+ if (!v.ftpOnly) { -+ optionsButton = new Button("Options"); -+ add(optionsButton); -+ optionsButton.addActionListener(this); -+ clipboardButton = new Button("Clipboard"); -+ clipboardButton.setEnabled(false); -+ add(clipboardButton); -+ clipboardButton.addActionListener(this); -+ if (viewer.rec != null) { -+ recordButton = new Button("Record"); -+ add(recordButton); -+ recordButton.addActionListener(this); -+ } -+ ctrlAltDelButton = new Button("Send Ctrl-Alt-Del"); -+ ctrlAltDelButton.setEnabled(false); -+ add(ctrlAltDelButton); -+ ctrlAltDelButton.addActionListener(this); -+ refreshButton = new Button("Refresh"); -+ refreshButton.setEnabled(false); -+ add(refreshButton); -+ refreshButton.addActionListener(this); -+ } - ftpButton = new Button("File Transfer"); - ftpButton.setEnabled(false); - add(ftpButton); -@@ -79,9 +85,10 @@ - - public void enableButtons() { - disconnectButton.setEnabled(true); -+ ftpButton.setEnabled(true); -+ if (viewer.ftpOnly) {return;} - clipboardButton.setEnabled(true); - refreshButton.setEnabled(true); -- ftpButton.setEnabled(true); - } - - // -@@ -89,6 +96,9 @@ - // - - public void disableButtonsOnDisconnect() { -+ ftpButton.setEnabled(false); -+ if (viewer.ftpOnly) {return;} -+ - remove(disconnectButton); - disconnectButton = new Button("Hide desktop"); - disconnectButton.setEnabled(true); -@@ -99,7 +109,6 @@ - clipboardButton.setEnabled(false); - ctrlAltDelButton.setEnabled(false); - refreshButton.setEnabled(false); -- ftpButton.setEnabled(false); - - validate(); - } -@@ -110,6 +119,7 @@ - // - - public void enableRemoteAccessControls(boolean enable) { -+ if (viewer.ftpOnly) {return;} - ctrlAltDelButton.setEnabled(enable); - } - -@@ -163,9 +173,19 @@ - } - else if (evt.getSource() == ftpButton) - { -- viewer.ftp.setVisible(!viewer.ftp.isVisible()); -+// begin runge/x11vnc -+ if (viewer.ftpOnly) { -+ viewer.vncFrame.setVisible(false); -+ } -+ viewer.ftp.setSavedLocations(); -+ if (viewer.ftp.isVisible()) { -+ viewer.ftp.doClose(); -+ } else { -+ viewer.ftp.doOpen(); -+ } -+// end runge/x11vnc - viewer.rfb.readServerDriveList(); -- -+ - } - } - } -diff -Naur JavaViewer.orig/FTPFrame.java JavaViewer/FTPFrame.java ---- JavaViewer.orig/FTPFrame.java 2005-03-15 23:53:14.000000000 -0500 -+++ JavaViewer/FTPFrame.java 2009-01-13 09:48:30.000000000 -0500 -@@ -24,8 +24,17 @@ - import java.io.*; - import java.util.ArrayList; - import java.util.Vector; -+import java.util.Date; - import javax.swing.*; - -+import java.nio.ByteBuffer; -+import java.nio.CharBuffer; -+import java.nio.charset.*; -+ -+// begin runge/x11vnc -+import java.util.Arrays; -+// end runge/x11vnc -+ - - /* - * Created on Feb 25, 2004 -@@ -74,12 +83,31 @@ - public javax.swing.JTextField connectionStatus = null; - public boolean updateDriveList; - private Vector remoteList = null; -+ private Vector remoteListInfo = null; - private Vector localList = null; -+ private Vector localListInfo = null; - private File currentLocalDirectory = null; // Holds the current local Directory - private File currentRemoteDirectory = null; // Holds the current remote Directory - private File localSelection = null; // Holds the currently selected local file - private String remoteSelection = null; // Holds the currently selected remote file - public String selectedTable = null; -+ -+// begin runge/x11vnc -+ private javax.swing.JButton viewButton = null; -+ private javax.swing.JButton refreshButton = null; -+ public File saveLocalDirectory = null; -+ public long saveLocalDirectoryTime = 0; -+ public int saveLocalDirectoryCount = 0; -+ public String saveRemoteDirectory = null; -+ public long saveRemoteDirectoryTime = 0; -+ public int saveRemoteDirectoryCount = 0; -+ private boolean localCurrentIsDir = true; -+ private int lastRemoteIndex = -1; -+ private int lastLocalIndex = -1; -+ private boolean doingShortcutDir = false; -+ private boolean gotShortcutDir = false; -+ private boolean ignore_events = false; -+// end runge/x11vnc - - // sf@2004 - Separate directories and files for better lisibility - private ArrayList DirsList; -@@ -125,11 +153,61 @@ - - void refreshRemoteLocation() - { -+ -+//System.out.println("refreshRemoteLocation1"); - remoteList.clear(); -+ remoteListInfo.clear(); - remoteFileTable.setListData(remoteList); -+System.out.println("refreshRemoteLocation '" + remoteLocation.getText() + "'"); // runge/x11vnc - viewer.rfb.readServerDirectory(remoteLocation.getText()); - } - -+// begin runge/x11vnc -+ public void setSavedLocations() { -+ saveLocalDirectory = currentLocalDirectory; -+ saveLocalDirectoryTime = System.currentTimeMillis(); -+ saveLocalDirectoryCount = 0; -+ -+ if (remoteLocation != null) { -+ saveRemoteDirectory = remoteLocation.getText(); -+System.out.println("RemoteSave '" + saveRemoteDirectory + "'"); -+ } -+ saveRemoteDirectoryTime = System.currentTimeMillis(); -+ saveRemoteDirectoryCount = 0; -+ } -+ -+ private File saveLocalHack(File dir) { -+ saveLocalDirectoryCount++; -+//System.out.println("L " + saveLocalDirectoryCount + " dt: " + (System.currentTimeMillis() - saveLocalDirectoryTime) + " - " + saveLocalDirectory); -+ if (System.currentTimeMillis() > saveLocalDirectoryTime + 2000 || saveLocalDirectoryCount > 2) { -+ saveLocalDirectory = null; -+ } -+ if (saveLocalDirectory != null) { -+ currentLocalDirectory = saveLocalDirectory; -+ localLocation.setText(saveLocalDirectory.toString()); -+ return saveLocalDirectory; -+ } else { -+ return dir; -+ } -+ } -+ -+ private String saveRemoteHack(String indrive) { -+ saveRemoteDirectoryCount++; -+//System.out.println("R " + saveRemoteDirectoryCount + " - " + saveRemoteDirectory); -+ if (saveRemoteDirectory != null && saveRemoteDirectoryCount > 1) { -+ saveRemoteDirectory = null; -+ } -+ if (saveRemoteDirectory != null) { -+ if (! saveRemoteDirectory.equals("")) { -+System.out.println("saveRemoteHack setText + refreshRemoteLocation '" + saveRemoteDirectory + "'"); -+ return saveRemoteDirectory; -+ } -+ } -+ return indrive; -+ } -+// end runge/x11vnc -+ -+ - /* - * Prints the list of drives on the remote directory and returns a String[]. - * str takes as string like A:fC:lD:lE:lF:lG:cH:c -@@ -143,6 +221,9 @@ - int size = str.length(); - String driveType = null; - String[] drive = new String[str.length() / 3]; -+ int idx = 0, C_drive = -1, O_drive = -1; -+ -+System.out.println("ComboBox: Str '" + str + "'"); - - // Loop through the string to create a String[] - for (int i = 0; i < size; i = i + 3) { -@@ -150,26 +231,68 @@ - driveType = str.substring(i + 2, i + 3); - if (driveType.compareTo("f") == 0) - drive[i / 3] += "\\ Floppy"; -- if (driveType.compareTo("l") == 0) -+ if (driveType.compareTo("l") == 0) { - drive[i / 3] += "\\ Local Disk"; -+ if (drive[i/3].substring(0,1).toUpperCase().equals("C")) { -+ C_drive = idx; -+ } else if (O_drive < 0) { -+ O_drive = idx; -+ } -+ } - if (driveType.compareTo("c") == 0) - drive[i / 3] += "\\ CD-ROM"; - if (driveType.compareTo("n") == 0) - drive[i / 3] += "\\ Network"; - - remoteDrivesComboBox.addItem(drive[i / 3]); -+System.out.println("ComboBox: Add " + idx + " '" + drive[i/3] + "'"); -+ idx++; -+ } -+ -+ // runge -+ if (viewer.ftpDropDown != null) { -+ String[] dd = viewer.ftpDropDown.split("\\."); -+ for (int i=0; i < dd.length; i++) { -+ if (!dd[i].equals("")) { -+ String s = dd[i]; -+ if (s.startsWith("TOP_")) { -+ s = s.substring(4); -+ remoteDrivesComboBox.insertItemAt(" [" + s + "]", 0); -+ } else { -+ remoteDrivesComboBox.addItem(" [" + s + "]"); -+ } -+ } -+ } -+ } else { -+ remoteDrivesComboBox.addItem(" [My Documents]"); -+ remoteDrivesComboBox.addItem(" [Desktop]"); -+ remoteDrivesComboBox.addItem(" [Home]"); - } -+ - //sf@ - Select Drive C:as default if possible - boolean bFound = false; -- for(int i = 0; i < remoteDrivesComboBox.getItemCount() ; i++) -- { -- if(remoteDrivesComboBox.getItemAt(i).toString().substring(0,1).toUpperCase().equals("C")) -- { -- remoteDrivesComboBox.setSelectedIndex(i); -+ -+ if (false) { -+ for(int i = 0; i < remoteDrivesComboBox.getItemCount() ; i++) { -+ if(remoteDrivesComboBox.getItemAt(i).toString().substring(0,1).toUpperCase().equals("C")) { -+ remoteDrivesComboBox.setSelectedIndex(i); -+ bFound = true; -+ } -+ } -+ } else { -+ if (C_drive >= 0) { -+ remoteDrivesComboBox.setSelectedIndex(C_drive); -+ bFound = true; -+System.out.println("ComboBox: C_drive index: " + C_drive); -+ } else if (O_drive >= 0) { -+ remoteDrivesComboBox.setSelectedIndex(O_drive); - bFound = true; -+System.out.println("ComboBox: Other_drive index: " + O_drive); - } - } -+ - if (!bFound) remoteDrivesComboBox.setSelectedIndex(0); -+ - updateDriveList = false; - return drive; - } -@@ -185,6 +308,8 @@ - stopButton.setVisible(true); - stopButton.setEnabled(true); - receiveButton.setEnabled(false); -+ viewButton.setEnabled(false); // runge/x11vnc -+ refreshButton.setEnabled(false); - remoteTopButton.setEnabled(false); - sendButton.setEnabled(false); - remoteFileTable.setEnabled(false); -@@ -207,6 +332,8 @@ - stopButton.setVisible(false); - stopButton.setEnabled(false); - receiveButton.setEnabled(true); -+ viewButton.setEnabled(true); // runge/x11vnc -+ refreshButton.setEnabled(true); - remoteTopButton.setEnabled(true); - sendButton.setEnabled(true); - remoteFileTable.setEnabled(true); -@@ -221,10 +348,11 @@ - /* - * Print Directory prints out all the contents of a directory - */ -- void printDirectory(ArrayList a) { -+ void printDirectory(ArrayList a, ArrayList b) { - - for (int i = 0; i < a.size(); i++) { - remoteList.addElement(a.get(i)); -+ remoteListInfo.addElement(b.get(i)); - } - remoteFileTable.setListData(remoteList); - } -@@ -235,10 +363,12 @@ - * @return void - */ - private void initialize() { -+ ignore_events = true; - this.setSize(794, 500); - this.setContentPane(getJContentPane()); -+ ignore_events = false; - updateDriveList = true; -- } -+ } - /** - * This method initializes jContentPane. This is the main content pane - * -@@ -253,6 +383,33 @@ - jContentPane.add(getRemotePanel(), java.awt.BorderLayout.EAST); - jContentPane.add(getLocalPanel(), java.awt.BorderLayout.WEST); - jContentPane.add(getButtonPanel(), java.awt.BorderLayout.CENTER); -+ -+ KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); -+ AbstractAction escapeAction = new AbstractAction() { -+ public void actionPerformed(ActionEvent actionEvent) { -+ System.out.println("Escape Pressed"); -+ if (viewer.ftpOnly) { -+ System.out.println("exiting..."); -+ System.exit(0); -+ } else { -+ doClose(); -+ } -+ } -+ }; -+ jContentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(stroke, "escapeAction"); -+ jContentPane.getInputMap().put(stroke, "escapeAction"); -+ jContentPane.getActionMap().put("escapeAction", escapeAction); -+ -+ stroke = KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_MASK); -+ AbstractAction resetAction = new AbstractAction() { -+ public void actionPerformed(ActionEvent actionEvent) { -+ System.out.println("Ctrl-R Pressed"); -+ doReset(); -+ } -+ }; -+ jContentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(stroke, "resetAction"); -+ jContentPane.getInputMap().put(stroke, "resetAction"); -+ jContentPane.getActionMap().put("resetAction", resetAction); - } - return jContentPane; - } -@@ -270,6 +427,7 @@ - topPanelLocal.add(getLocalMachineLabel(), java.awt.BorderLayout.CENTER); - topPanelLocal.add(getLocalTopButton(), java.awt.BorderLayout.EAST); - topPanelLocal.setBackground(java.awt.Color.lightGray); -+//System.out.println("getTopPanelLocal"); - } - return topPanelLocal; - } -@@ -288,6 +446,7 @@ - topPanelRemote.add(getRemoteMachineLabel(), java.awt.BorderLayout.CENTER); - topPanelRemote.add(getRemoteTopButton(), java.awt.BorderLayout.EAST); - topPanelRemote.setBackground(java.awt.Color.lightGray); -+//System.out.println("getTopPanelRemote"); - } - return topPanelRemote; - } -@@ -301,6 +460,7 @@ - if (topPanelCenter == null) { - topPanelCenter = new javax.swing.JPanel(); - topPanelCenter.add(getDummyButton(), null); -+//System.out.println("getTopPanelCenter"); - } - return topPanelCenter; - } -@@ -328,6 +488,7 @@ - topPanel.add(getRemoteTopButton(), null); - topPanel.setBackground(java.awt.Color.lightGray); - */ -+//System.out.println("getTopPanel"); - } - return topPanel; - } -@@ -348,6 +509,7 @@ - statusPanel.add(getJProgressBar(), null); - statusPanel.add(getConnectionStatus(), null); - statusPanel.setBackground(java.awt.Color.lightGray); -+//System.out.println("getStatusPanel"); - - } - return statusPanel; -@@ -368,6 +530,7 @@ - remotePanel.add(getRemoteScrollPane(), null); - remotePanel.add(getRemoteStatus(), null); - remotePanel.setBackground(java.awt.Color.lightGray); -+//System.out.println("getRemotePanel"); - } - return remotePanel; - } -@@ -390,6 +553,7 @@ - localPanel.setComponentOrientation( - java.awt.ComponentOrientation.UNKNOWN); - localPanel.setName("localPanel"); -+//System.out.println("getLocalPanel"); - } - return localPanel; - } -@@ -405,12 +569,15 @@ - buttonPanel = new javax.swing.JPanel(); - buttonPanel.setLayout(null); - buttonPanel.add(getReceiveButton(), null); -+ buttonPanel.add(getRefreshButton(), null); // runge/x11vnc -+ buttonPanel.add(getViewButton(), null); // runge/x11vnc - buttonPanel.add(getNewFolderButton(), null); - buttonPanel.add(getCloseButton(), null); - buttonPanel.add(getDeleteButton(), null); - buttonPanel.add(getSendButton(), null); - buttonPanel.add(getStopButton(), null); - buttonPanel.setBackground(java.awt.Color.lightGray); -+//System.out.println("getButtonPanel"); - } - return buttonPanel; - } -@@ -422,10 +589,11 @@ - private javax.swing.JButton getSendButton() { - if (sendButton == null) { - sendButton = new javax.swing.JButton(); -- sendButton.setBounds(20, 30, 97, 25); -+ sendButton.setBounds(15, 30, 107, 25); // runge/x11vnc - sendButton.setText("Send >>"); - sendButton.setName("sendButton"); - sendButton.addActionListener(this); -+//System.out.println("getSendButton"); - - } - return sendButton; -@@ -438,7 +606,7 @@ - private javax.swing.JButton getReceiveButton() { - if (receiveButton == null) { - receiveButton = new javax.swing.JButton(); -- receiveButton.setBounds(20, 60, 97, 25); -+ receiveButton.setBounds(15, 60, 107, 25); // runge/x11vnc - receiveButton.setText("<< Receive"); - receiveButton.setName("receiveButton"); - receiveButton.addActionListener(this); -@@ -453,7 +621,7 @@ - private javax.swing.JButton getDeleteButton() { - if (deleteButton == null) { - deleteButton = new javax.swing.JButton(); -- deleteButton.setBounds(20, 110, 97, 25); -+ deleteButton.setBounds(15, 110, 107, 25); // runge/x11vnc - deleteButton.setText("Delete File"); - deleteButton.setName("deleteButton"); - deleteButton.addActionListener(this); -@@ -468,7 +636,7 @@ - private javax.swing.JButton getNewFolderButton() { - if (newFolderButton == null) { - newFolderButton = new javax.swing.JButton(); -- newFolderButton.setBounds(20, 140, 97, 25); -+ newFolderButton.setBounds(15, 140, 107, 25); // runge/x11vnc - newFolderButton.setText("New Folder"); - newFolderButton.setName("newFolderButton"); - newFolderButton.addActionListener(this); -@@ -476,6 +644,39 @@ - return newFolderButton; - } - -+// begin runge/x11vnc -+ /** -+ * This method initializes refreshButton -+ * -+ * @return javax.swing.JButton -+ */ -+ private javax.swing.JButton getRefreshButton() { -+ if (refreshButton == null) { -+ refreshButton = new javax.swing.JButton(); -+ refreshButton.setBounds(15, 170, 107, 25); -+ refreshButton.setText("Refresh"); -+ refreshButton.setName("refreshButton"); -+ refreshButton.addActionListener(this); -+ } -+ return refreshButton; -+ } -+ /** -+ * This method initializes viewButton -+ * -+ * @return javax.swing.JButton -+ */ -+ private javax.swing.JButton getViewButton() { -+ if (viewButton == null) { -+ viewButton = new javax.swing.JButton(); -+ viewButton.setBounds(15, 200, 107, 25); -+ viewButton.setText("View File"); -+ viewButton.setName("viewButton"); -+ viewButton.addActionListener(this); -+ } -+ return viewButton; -+ } -+// end runge/x11vnc -+ - /** - * This method initializes stopButton - * -@@ -486,7 +687,7 @@ - if (stopButton == null) - { - stopButton = new javax.swing.JButton(); -- stopButton.setBounds(20, 200, 97, 25); -+ stopButton.setBounds(15, 230, 107, 25); // runge/x11vnc - stopButton.setText("Stop"); - stopButton.setName("stopButton"); - stopButton.addActionListener(this); -@@ -503,8 +704,12 @@ - private javax.swing.JButton getCloseButton() { - if (closeButton == null) { - closeButton = new javax.swing.JButton(); -- closeButton.setBounds(20, 325, 97, 25); -- closeButton.setText("Close"); -+ closeButton.setBounds(15, 325, 107, 25); // runge/x11vnc -+ if (viewer.ftpOnly) { -+ closeButton.setText("Quit"); -+ } else { -+ closeButton.setText("Close"); -+ } - closeButton.setName("closeButton"); - closeButton.addActionListener(this); - } -@@ -551,6 +756,7 @@ - //Select the second entry (e.g. C:\) - // localDrivesComboBox.setSelectedIndex(1); - localDrivesComboBox.addActionListener(this); -+//System.out.println("getLocalDrivesComboBox"); - } - updateDriveList = false; - return localDrivesComboBox; -@@ -567,6 +773,7 @@ - remoteDrivesComboBox.setFont( - new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); - remoteDrivesComboBox.addActionListener(this); -+//System.out.println("getRemoteDrivesComboBox"); - - } - return remoteDrivesComboBox; -@@ -587,6 +794,7 @@ - localMachineLabel.setFont( - new java.awt.Font("Dialog", java.awt.Font.BOLD, 11)); - localMachineLabel.setEditable(false); -+//System.out.println("getLocalMachineLabel"); - } - return localMachineLabel; - } -@@ -622,6 +830,7 @@ - localTopButton.setFont( - new java.awt.Font("Dialog", java.awt.Font.BOLD, 10)); - localTopButton.addActionListener(this); -+//System.out.println("getLocalTopButton"); - } - return localTopButton; - } -@@ -638,6 +847,7 @@ - remoteTopButton.setFont( - new java.awt.Font("Dialog", java.awt.Font.BOLD, 10)); - remoteTopButton.addActionListener(this); -+//System.out.println("getRemoteTopButton"); - } - return remoteTopButton; - } -@@ -650,9 +860,24 @@ - private javax.swing.JList getLocalFileTable() { - if (localFileTable == null) { - localList = new Vector(0); -+ localListInfo = new Vector(0); - localFileTable = new JList(localList); -+ MouseMotionListener mlisten = new MouseMotionAdapter() { -+ public void mouseMoved(MouseEvent e) { -+ int index = localFileTable.locationToIndex(e.getPoint()); -+ if (index == lastLocalIndex) { -+ return; -+ } else if (index < 0) { -+ return; -+ } -+ lastLocalIndex = index; -+ connectionStatus.setText((String) localListInfo.get(index)); -+ } -+ }; - localFileTable.addMouseListener(this); -+ localFileTable.addMouseMotionListener(mlisten); - localFileTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); -+//System.out.println("getLocalFileTable"); - } - return localFileTable; - } -@@ -669,6 +894,7 @@ - localScrollPane.setFont( - new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); - localScrollPane.setName("localFileList"); -+//System.out.println("getLocalScrollPane"); - } - return localScrollPane; - } -@@ -680,10 +906,25 @@ - private javax.swing.JList getRemoteFileTable() { - if (remoteFileTable == null) { - remoteList = new Vector(0); -+ remoteListInfo = new Vector(0); - remoteFileTable = new JList(remoteList); -+ MouseMotionListener mlisten = new MouseMotionAdapter() { -+ public void mouseMoved(MouseEvent e) { -+ int index = remoteFileTable.locationToIndex(e.getPoint()); -+ if (index == lastRemoteIndex) { -+ return; -+ } else if (index < 0) { -+ return; -+ } -+ lastRemoteIndex = index; -+ connectionStatus.setText((String) remoteListInfo.get(index)); -+ } -+ }; - remoteFileTable.addMouseListener(this); -+ remoteFileTable.addMouseMotionListener(mlisten); - remoteFileTable.setSelectedValue("C:\\", false); - remoteFileTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); -+//System.out.println("getRemoteFileTable"); - - } - return remoteFileTable; -@@ -698,6 +939,7 @@ - remoteScrollPane = new javax.swing.JScrollPane(); - remoteScrollPane.setViewportView(getRemoteFileTable()); - remoteScrollPane.setPreferredSize(new java.awt.Dimension(325, 418)); -+//System.out.println("getRemoteScrollPane"); - } - return remoteScrollPane; - } -@@ -716,6 +958,7 @@ - remoteLocation.setBackground(new Color(255,255,238)); - remoteLocation.setFont( - new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); -+//System.out.println("getRemoteLocation"); - } - return remoteLocation; - } -@@ -732,6 +975,7 @@ - localLocation.setBackground( new Color(255,255,238)); - localLocation.setFont( - new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); -+//System.out.println("getLocalLocation"); - } - return localLocation; - } -@@ -748,6 +992,7 @@ - localStatus.setFont( - new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); - localStatus.setEditable(false); -+//System.out.println("getLocalStatus"); - } - return localStatus; - } -@@ -764,6 +1009,7 @@ - remoteStatus.setFont( - new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); - remoteStatus.setEditable(false); -+//System.out.println("getRemoteStatus"); - } - return remoteStatus; - } -@@ -777,9 +1023,10 @@ - historyComboBox = new javax.swing.JComboBox(); - historyComboBox.setFont( - new java.awt.Font("Dialog", java.awt.Font.BOLD, 10)); -- historyComboBox.insertItemAt(new String("Pulldown to view history ..."),0); -+ historyComboBox.insertItemAt(new String("Pulldown to view history; Press Escape to Close/Quit; Press Ctrl-R to Reset Panel."),0); - historyComboBox.setSelectedIndex(0); - historyComboBox.addActionListener(this); -+//System.out.println("getHistoryComboBox"); - } - return historyComboBox; - } -@@ -791,6 +1038,7 @@ - private javax.swing.JProgressBar getJProgressBar() { - if (jProgressBar == null) { - jProgressBar = new javax.swing.JProgressBar(); -+//System.out.println("getJProgressBar"); - } - return jProgressBar; - } -@@ -806,6 +1054,7 @@ - connectionStatus.setBackground(java.awt.Color.lightGray); - connectionStatus.setFont( - new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); -+//System.out.println("getConnectionStatus"); - } - connectionStatus.setEditable(false); - return connectionStatus; -@@ -815,7 +1064,12 @@ - * Implements Action listener. - */ - public void actionPerformed(ActionEvent evt) { -- System.out.println(evt.getSource()); -+// System.out.println(evt.getSource()); -+ -+ if (ignore_events) { -+ System.out.println("ignore_events: " + evt.getSource()); -+ return; -+ } - - if (evt.getSource() == closeButton) - { // Close Button -@@ -829,15 +1083,27 @@ - { - doReceive(); - } -+// begin runge/x11vnc -+ else if (evt.getSource() == viewButton) -+ { -+ doView(); -+ } -+// end runge/x11vnc - else if (evt.getSource() == localDrivesComboBox) - { - changeLocalDrive(); - } - else if (evt.getSource() == remoteDrivesComboBox) - { -+//System.out.println("remoteDrivesComboBox"); // runge/x11vnc - changeRemoteDrive(); -- remoteList.clear(); -- remoteFileTable.setListData(remoteList); -+ -+ // are these really needed? changeRemoteDrive() does them at the end. -+ if (false) { -+ remoteList.clear(); -+ remoteListInfo.clear(); -+ remoteFileTable.setListData(remoteList); -+ } - } - else if (evt.getSource() == localTopButton) - { -@@ -845,12 +1111,17 @@ - } - else if (evt.getSource() == remoteTopButton) - { -+//System.out.println("remoteTopButton"); // runge/x11vnc - changeRemoteDrive(); - } - else if(evt.getSource() == deleteButton) - { - doDelete(); - } -+ else if(evt.getSource() == refreshButton) -+ { -+ doRefresh(); -+ } - else if(evt.getSource()==newFolderButton) - { - doNewFolder(); -@@ -864,7 +1135,7 @@ - - private void doNewFolder() - { -- String name = JOptionPane.showInputDialog(null,"Enter new directory name", "Create New Directory", JOptionPane.QUESTION_MESSAGE); -+ String name = JOptionPane.showInputDialog(jContentPane,"Enter new directory name", "Create New Directory", JOptionPane.QUESTION_MESSAGE); - if(selectedTable.equals("remote")) - { - name = remoteLocation.getText()+name; -@@ -880,34 +1151,106 @@ - historyComboBox.setSelectedIndex(0); - } - } -- private void doClose() -+ public void doClose() - { -+ if (viewer.ftpOnly) { -+ viewer.disconnect(); -+ return; -+ } - try { - this.setVisible(false); -- viewer.rfb.writeFramebufferUpdateRequest( -- 0, -- 0, -- viewer.rfb.framebufferWidth, -- viewer.rfb.framebufferHeight, -- true); -+ viewer.rfb.writeFramebufferUpdateRequest(0, 0, viewer.rfb.framebufferWidth, -+ viewer.rfb.framebufferHeight, true); -+ -+ if (false) { -+ this.dispose(); -+ jContentPane = null; -+ } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } -+ private void unSwing() { -+ jContentPane = null; -+ topPanel = null; -+ topPanelLocal = null; -+ topPanelRemote = null; -+ topPanelCenter = null; -+ statusPanel = null; -+ remotePanel = null; -+ localPanel = null; -+ buttonPanel = null; -+ sendButton = null; -+ receiveButton = null; -+ deleteButton = null; -+ newFolderButton = null; -+ stopButton = null; -+ closeButton = null; -+ dummyButton = null; -+ localDrivesComboBox = null; -+ remoteDrivesComboBox = null; -+ localMachineLabel = null; -+ remoteMachineLabel = null; -+ localTopButton = null; -+ remoteTopButton = null; -+ localScrollPane = null; -+ localFileTable = null; -+ remoteScrollPane = null; -+ remoteFileTable = null; -+ remoteLocation = null; -+ localLocation = null; -+ localStatus = null; -+ remoteStatus = null; -+ historyComboBox = null; -+ jProgressBar = null; -+ connectionStatus = null; -+ viewButton = null; -+ refreshButton = null; -+ } -+ -+ public void doReset() -+ { -+ try { -+ this.setVisible(false); -+ this.dispose(); -+ jContentPane = null; -+ try {Thread.sleep(500);} catch (InterruptedException e) {} -+ viewer.ftp_init(); -+ } catch (Exception e) { -+ // TODO Auto-generated catch block -+ e.printStackTrace(); -+ } -+ } - -+ public void doOpen() -+ { -+ try { -+ this.setVisible(true); -+ if (false) { -+ this.initialize(); -+ } -+ } catch (Exception e) { -+ // TODO Auto-generated catch block -+ e.printStackTrace(); -+ } -+ } - private void doDelete() - { -- System.out.println("Delete Button Pressed"); -+// System.out.println("Delete Button Pressed"); - //Call this method to delete a file at server - if(selectedTable.equals("remote")) - { -- String sFileName = ((String) this.remoteFileTable.getSelectedValue()); -+ Object selected = this.remoteFileTable.getSelectedValue(); -+ if (selected == null) { -+ return; -+ } -+ String sFileName = ((String) selected); - - // sf@2004 - Directory can't be deleted - if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) - { -- JOptionPane.showMessageDialog(null, (String)"Directory Deletion is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); -+ JOptionPane.showMessageDialog(jContentPane, (String)"Directory Deletion is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); - return; - } - -@@ -916,7 +1259,7 @@ - // sf@2004 - Delete prompt - if (remoteList.contains(sFileName)) - { -- int r = JOptionPane.showConfirmDialog(null, "Are you sure you want to delete the file \n< " + sFileName + " >\n on Remote Machine ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); -+ int r = JOptionPane.showConfirmDialog(jContentPane, "Are you sure you want to delete the file \n< " + sFileName + " >\n on Remote Machine ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); - if (r == JOptionPane.NO_OPTION) - return; - } -@@ -926,18 +1269,22 @@ - } - else - { -- String sFileName = ((String) this.localFileTable.getSelectedValue()); -+ Object selected = this.localFileTable.getSelectedValue(); -+ if (selected == null) { -+ return; -+ } -+ String sFileName = ((String) selected); - - // sf@2004 - Directory can't be deleted - if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) - { -- JOptionPane.showMessageDialog(null, (String)"Directory Deletion is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); -+ JOptionPane.showMessageDialog(jContentPane, (String)"Directory Deletion is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); - return; - } - // sf@2004 - Delete prompt - if (localList.contains(sFileName)) - { -- int r = JOptionPane.showConfirmDialog(null, "Are you sure you want to delete the file \n< " + sFileName + " >\n on Local Machine ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); -+ int r = JOptionPane.showConfirmDialog(jContentPane, "Are you sure you want to delete the file \n< " + sFileName + " >\n on Local Machine ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); - if (r == JOptionPane.NO_OPTION) - return; - } -@@ -952,21 +1299,25 @@ - - private void doReceive() - { -- System.out.println("Received Button Pressed"); -+// System.out.println("Received Button Pressed"); - -- String sFileName = ((String) this.remoteFileTable.getSelectedValue()); -+ Object selected = this.remoteFileTable.getSelectedValue(); -+ if (selected == null) { -+ return; -+ } -+ String sFileName = ((String) selected); - - // sf@2004 - Directory can't be transfered - if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) - { -- JOptionPane.showMessageDialog(null, (String)"Directory Transfer is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); -+ JOptionPane.showMessageDialog(jContentPane, (String)"Directory Transfer is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); - return; - } - - // sf@2004 - Overwrite prompt - if (localList.contains(sFileName)) - { -- int r = JOptionPane.showConfirmDialog(null, "The file < " + sFileName + " >\n already exists on Local Machine\n Are you sure you want to overwrite it ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); -+ int r = JOptionPane.showConfirmDialog(jContentPane, "The file < " + sFileName + " >\n already exists on Local Machine\n Are you sure you want to overwrite it ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); - if (r == JOptionPane.NO_OPTION) - return; - } -@@ -979,23 +1330,101 @@ - viewer.rfb.requestRemoteFile(remoteFileName,localDestinationPath); - } - -+// begin runge/x11vnc -+ private void doRefresh() -+ { -+ System.out.println("Refreshing Local and Remote."); -+ refreshLocalLocation(); -+ refreshRemoteLocation(); -+ } -+ -+ private void doView() -+ { -+// System.out.println("View Button Pressed"); -+ -+ if (selectedTable == null) { -+ return; -+ } -+ if (selectedTable.equals("remote")) { -+ viewRemote(); -+ } else if (selectedTable.equals("local")) { -+ viewLocal(); -+ } -+ } -+ -+ private File doReceiveTmp() -+ { -+ -+ if (remoteFileTable == null) { -+ return null; -+ } -+ Object selected = this.remoteFileTable.getSelectedValue(); -+ if (selected == null) { -+ return null; -+ } -+ String sFileName = ((String) selected); -+ -+ if (sFileName == null) { -+ return null; -+ } -+ -+ // sf@2004 - Directory can't be transfered -+ if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) -+ { -+ return null; -+ } -+ -+ File tmp = null; -+ try { -+ tmp = File.createTempFile("ULTRAFTP", ".txt"); -+ } catch (Exception e) { -+ return null; -+ } -+ -+ //updateHistory("Downloaded " + localSelection.toString()); -+ String remoteFileName = this.remoteLocation.getText(); -+ remoteFileName+= ((String) this.remoteFileTable.getSelectedValue()).substring(1); -+ System.out.println("remoteFileName: " + remoteFileName); -+if (false) { -+ char[] b = remoteFileName.toCharArray(); -+ for (int n = 0; n < b.length; n++) { -+ System.out.print(Integer.toHexString(b[n]) + " "); -+ } -+ System.out.println(""); -+ for (int n = 0; n < b.length; n++) { -+ System.out.print(b[n]); -+ } -+ System.out.println(""); -+} -+ -+ String localDestinationPath = tmp.getAbsolutePath(); -+ viewer.rfb.requestRemoteFile(remoteFileName,localDestinationPath); -+ System.out.println("ReceiveTmp: " + localDestinationPath); -+ return tmp; -+ } -+// end runge/x11vnc -+ - private void doSend() - { -- System.out.println("Send Button Pressed"); -+// System.out.println("Send Button Pressed"); - -- String sFileName = ((String) this.localFileTable.getSelectedValue()); -+ Object selected = this.localFileTable.getSelectedValue(); -+ if (selected == null) { -+ return; -+ } -+ String sFileName = ((String) selected); - - // sf@2004 - Directory can't be transfered - if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) - { -- JOptionPane.showMessageDialog(null, (String)"Directory Transfer is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); -+ JOptionPane.showMessageDialog(jContentPane, (String)"Directory Transfer is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); - return; - } - - // sf@2004 - Overwrite prompt - if (remoteList.contains(sFileName)) - { -- int r = JOptionPane.showConfirmDialog(null, "The file < " + sFileName + " >\n already exists on Remote Machine\n Are you sure you want to overwrite it ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); -+ int r = JOptionPane.showConfirmDialog(jContentPane, "The file < " + sFileName + " >\n already exists on Remote Machine\n Are you sure you want to overwrite it ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); - if (r == JOptionPane.NO_OPTION) - return; - } -@@ -1013,6 +1442,7 @@ - // - private void doStop() - { -+ System.out.println("** Current Transfer Aborted **"); - viewer.rfb.fAbort = true; - } - /** -@@ -1024,6 +1454,14 @@ - System.out.println("History: " + message); - historyComboBox.insertItemAt(new String(message), 0); - } -+ -+ public void receivedRemoteDirectoryName(String str) { -+ if (doingShortcutDir) { -+ if (str.length() > 1) { -+ remoteLocation.setText(str); -+ } -+ } -+ } - - /** - * This method updates the file table to the current selection of the remoteComboBox -@@ -1034,11 +1472,44 @@ - remoteSelection = null; - - if (!updateDriveList) { -- String drive = remoteDrivesComboBox.getSelectedItem().toString().substring(0,1)+ ":\\"; -- viewer.rfb.readServerDirectory(drive); -- remoteLocation.setText(drive); -+//System.out.println("changeRemoteDrive-A " + drive); // begin runge/x11vnc -+ Object selected = remoteDrivesComboBox.getSelectedItem(); -+ if (selected != null) { -+ String instr = selected.toString(); -+ if (instr != null) { -+System.out.println("changeRemoteDrive: instr='" + instr + "'"); -+ String drive = instr.substring(0,1)+ ":\\"; -+ if (instr.startsWith(" [")) { -+ int idx = instr.lastIndexOf(']'); -+ if (idx > 2) { -+ drive = instr.substring(2, idx); -+ } else { -+ drive = instr.substring(2); -+ } -+ if (drive.equals("Home")) { -+ drive = ""; -+ } -+ drive += "\\"; -+ doingShortcutDir = true; -+ } else { -+ doingShortcutDir = false; -+ drive = saveRemoteHack(drive); -+ } -+ gotShortcutDir = false; -+ viewer.rfb.readServerDirectory(drive); -+ if (!gotShortcutDir) { -+ remoteLocation.setText(drive); -+ } -+ } else { -+System.out.println("changeRemoteDrive: instr null"); -+ } -+ } else { -+System.out.println("changeRemoteDrive: selection null"); -+ } -+//System.out.println("changeRemoteDrive-B " + drive); // end runge/x11vnc - } - remoteList.clear(); -+ remoteListInfo.clear(); - remoteFileTable.setListData(remoteList); - } - /** -@@ -1048,6 +1519,7 @@ - private void changeLocalDrive() - { - File currentDrive = new File(localDrivesComboBox.getSelectedItem().toString()); -+System.out.println("changeLocalDrive " + currentDrive.toString()); // runge/x11vnc - if(currentDrive.canRead()) - { - localSelection = null; -@@ -1057,9 +1529,11 @@ - else - { - localList.clear(); -+ localListInfo.clear(); - localStatus.setText("WARNING: Drive " + localDrivesComboBox.getSelectedItem().toString()); - connectionStatus.setText(" > WARNING - Local Drive unavailable (possibly restricted access or media not present)"); - } -+ - } - /** - * Determines which FileTable was double-clicked and updates the table -@@ -1098,10 +1572,18 @@ - selectedTable = "remote"; - localFileTable.setBackground(new Color(238, 238, 238)); - remoteFileTable.setBackground(new Color(255, 255, 255)); -- String name = (remoteFileTable.getSelectedValue().toString()).substring(1); -+ Object selected = remoteFileTable.getSelectedValue(); -+ if (selected == null) { -+ return; -+ } -+ String selstr = selected.toString(); -+ if (selstr == null) { -+ return; -+ } -+ String name = selstr.substring(1); - if( !name.substring(0, 2).equals(" [")) - remoteSelection = remoteLocation.getText() + name.substring(0, name.length()); -- -+ - } - - /* -@@ -1115,10 +1597,38 @@ - localFileTable.setBackground(new Color(255, 255, 255)); - File currentSelection = new File(currentLocalDirectory, getTrimmedSelection()); - -- if(currentSelection.isFile()) -+// begin runge/x11vnc -+ // localSelection = currentSelection.getAbsoluteFile(); -+ if(currentSelection.isFile()) { - localSelection = currentSelection.getAbsoluteFile(); -+ localCurrentIsDir = false; -+ } else { -+ localCurrentIsDir = true; -+ } -+// end runge/x11vnc - - } -+ -+// begin runge/x11vnc -+ private void viewRemote() { -+ File tmp = doReceiveTmp(); -+ if (tmp == null) { -+ return; -+ } -+ TextViewer tv = new TextViewer("Remote: " + remoteSelection, tmp, true); -+ } -+ private void viewLocal() { -+ if (localSelection == null) { -+ return; -+ } -+ if (localCurrentIsDir) { -+ return; -+ } -+ File loc = new File(localSelection.toString()); -+ TextViewer tv = new TextViewer("Local: " + localSelection.toString(), loc, false); -+ } -+// end runge/x11vnc -+ - /** - * Updates the Remote File Table based on selection. Called from mouseClicked handler - */ -@@ -1126,20 +1636,29 @@ - String name = null; - String action = null; - String drive = null; -- name = (remoteFileTable.getSelectedValue().toString()).substring(1); -+ Object selected = remoteFileTable.getSelectedValue(); -+ if (selected == null) { -+ return; -+ } -+ String sname = selected.toString(); -+ if (sname == null) { -+ return; -+ } -+ name = sname.substring(1); - - if (name.equals("[..]")) - { - action = "up"; - remoteSelection = null; - drive = remoteLocation.getText().substring(0, remoteLocation.getText().length() - 1); -- // JOptionPane.showMessageDialog(null, (String)drive, "FileTransfer DEBUG", JOptionPane.INFORMATION_MESSAGE); -+ // JOptionPane.showMessageDialog(jContentPane, (String)drive, "FileTransfer DEBUG", JOptionPane.INFORMATION_MESSAGE); - int index = drive.lastIndexOf("\\"); - drive = drive.substring(0, index + 1); - - remoteLocation.setText(drive); - viewer.rfb.readServerDirectory(drive); - remoteList.clear(); -+ remoteListInfo.clear(); - remoteFileTable.setListData(remoteList); - } - else if (!name.substring(0, 2).equals(" [") && !name.substring((name.length() - 1), name.length()).equals("]")) -@@ -1149,6 +1668,7 @@ - remoteSelection = remoteLocation.getText() + name.substring(0, name.length()); - drive = remoteLocation.getText(); - // ?? -+ viewRemote(); // runge/x11vnc - } - else - { -@@ -1159,10 +1679,12 @@ - remoteLocation.setText(drive); - viewer.rfb.readServerDirectory(drive); - remoteList.clear(); -+ remoteListInfo.clear(); - remoteFileTable.setListData(remoteList); - } - //remoteLocation.setText(drive); - } -+ - /** - * Updates the Local File Table based on selection. Called from MouseClicked handler - */ -@@ -1188,6 +1710,7 @@ - else if (currentSelection.isFile()) - { - localSelection = currentSelection.getAbsoluteFile(); -+ viewLocal(); // runge/x11vnc - } - else if (currentSelection.isDirectory()) - { -@@ -1201,13 +1724,22 @@ - * - */ - private String getTrimmedSelection(){ -- String currentSelection = (localFileTable.getSelectedValue().toString()).substring(1); -- if(currentSelection.substring(0,1).equals("[") && -- currentSelection.substring(currentSelection.length()-1,currentSelection.length()).equals("]")){ -- return currentSelection.substring(1,currentSelection.length()-1); -- } else { -- return currentSelection; -- } -+ String currentSelection = ""; -+ Object selected = localFileTable.getSelectedValue(); -+ if (selected == null) { -+ return currentSelection; -+ } -+ String selstr = selected.toString(); -+ if (selstr == null) { -+ return currentSelection; -+ } -+ currentSelection = selstr.substring(1); -+ if(currentSelection.substring(0,1).equals("[") && -+ currentSelection.substring(currentSelection.length()-1,currentSelection.length()).equals("]")){ -+ return currentSelection.substring(1,currentSelection.length()-1); -+ } else { -+ return currentSelection; -+ } - } - - /* -@@ -1241,36 +1773,148 @@ - return null; - } - -+ String timeStr(long t) { -+ Date date = new Date(t); -+ return date.toString(); -+ } -+ String dotPast(double f, int n) { -+ String fs = "" + f; -+ int i = fs.lastIndexOf(".") + n; -+ if (i >= 0) { -+ int len = fs.length(); -+ if (i >= len) { -+ i = len-1; -+ } -+ fs = fs.substring(0, i); -+ } -+ return fs; -+ } -+ String sizeStr(int s) { -+ if (s < 0) { -+ return s + "? B"; -+ } else if (s < 1024) { -+ return s + " B"; -+ } else if (s < 1024 * 1024) { -+ double k = s / 1024.0; -+ String ks = dotPast(k, 3); -+ -+ return s + " (" + ks + " KB)"; -+ } else { -+ double m = s / (1024.0*1024.0); -+ String ms = dotPast(m, 3); -+ return s + " (" + ms + " MB)"; -+ } -+ } -+ -+ int max_char(String text) { -+ int maxc = 0; -+ char chars[] = text.toCharArray(); -+ for (int n = 0; n < chars.length; n++) { -+ if ((int) chars[n] > maxc) { -+ maxc = (int) chars[n]; -+ } -+ } -+ return maxc; -+ } - - /* - * Navigates the local file structure up or down one directory - */ - public void changeLocalDirectory(File dir) - { -- currentLocalDirectory = dir; // Updates Global -+ dir = saveLocalHack(dir); // runge/x11vnc -+ -+ if (dir == null) { -+ connectionStatus.setText("Error changing local directory."); -+ historyComboBox.insertItemAt(new String("> Error changing local directory."), 0); -+ historyComboBox.setSelectedIndex(0); -+ return; -+ } -+ - File allFiles[] = dir.listFiles(); // Reads files - String[] contents = dir.list(); - -+ if (contents == null || allFiles == null) { -+ connectionStatus.setText("Error changing local directory."); -+ historyComboBox.insertItemAt(new String("> Error changing local directory."), 0); -+ historyComboBox.setSelectedIndex(0); -+ return; -+ } -+ -+ currentLocalDirectory = dir; // Updates Global -+// begin runge/x11vnc -+System.out.println("changeLocalDirectory: " + dir.toString()); -+ if (contents != null) { -+ java.util.Arrays.sort(contents, String.CASE_INSENSITIVE_ORDER); -+ for (int i = 0; i < contents.length; i++) { -+ allFiles[i] = new File(dir, contents[i]); -+ } -+ } else { -+ return; -+ } -+// end runge/x11vnc -+ - localList.clear(); -+ localListInfo.clear(); - localList.addElement(" [..]"); -+ localListInfo.addElement(" [..]"); -+ -+ ArrayList DirInfo = new ArrayList(); -+ ArrayList FilInfo = new ArrayList(); -+ -+ Charset charset = Charset.forName("ISO-8859-1"); -+ CharsetDecoder decoder = charset.newDecoder(); -+ CharsetEncoder encoder = charset.newEncoder(); - - // Populate the Lists - for (int i = 0; i < contents.length; i++) - { -- if (allFiles[i].isDirectory()) -+ String f1 = contents[i]; -+ -+if (false) { -+ -+System.out.println("max_char: " + max_char(f1) + " " + f1); -+ if (max_char(f1) > 255) { -+ try { -+System.out.println("bbuf1"); -+ ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(f1.toCharArray())); -+System.out.println("bbuf2"); -+ CharBuffer cbuf = decoder.decode(bbuf); -+System.out.println("bbuf3"); -+ f1 = cbuf.toString(); -+System.out.println("did bbuf: " + f1); -+ } catch (Exception e) { -+ ; -+ } -+ } -+} -+ -+ String f2 = f1; -+ if (f2.length() < 24) { -+ for (int ik = f2.length(); ik < 24; ik++) { -+ f2 = f2 + " "; -+ } -+ } -+ String s = f2 + " \tLastmod: " + timeStr(allFiles[i].lastModified()) + " \t\tSize: " + sizeStr((int) allFiles[i].length()); -+ if (allFiles[i].isDirectory()) { - // localList.addElement("[" + contents[i] + "]"); -- DirsList.add(" [" + contents[i] + "]"); // sf@2004 -- else -- { -+ DirsList.add(" [" + f1 + "]"); // sf@2004 -+ DirInfo.add(s); -+ } else { - // localList.addElement(contents[i]); -- FilesList.add(" " + contents[i]); // sf@2004 -+ FilesList.add(" " + f1); // sf@2004 -+ FilInfo.add(s); - } - } - // sf@2004 -- for (int i = 0; i < DirsList.size(); i++) -+ for (int i = 0; i < DirsList.size(); i++) { - localList.addElement(DirsList.get(i)); -- for (int i = 0; i < FilesList.size(); i++) -+ localListInfo.addElement(DirInfo.get(i)); -+ } -+ for (int i = 0; i < FilesList.size(); i++) { - localList.addElement(FilesList.get(i)); -+ localListInfo.addElement(FilInfo.get(i)); -+ } - - FilesList.clear(); - DirsList.clear(); -@@ -1296,3 +1940,147 @@ - } - - } // @jve:visual-info decl-index=0 visual-constraint="10,10" -+ -+// begin runge/x11vnc -+class TextViewer extends JFrame implements ActionListener { -+ -+ JTextArea textArea = new JTextArea(35, 80); -+ File file = null; -+ JButton refreshButton; -+ JButton dismissButton; -+ Timer tim = null; -+ int rcnt = 0; -+ int tms = 250; -+ boolean delete_it = false; -+ TextViewer me; -+ -+ public TextViewer(String s, File f, boolean d) { -+ -+ delete_it = d; -+ file = f; -+ me = this; -+ -+ JScrollPane scrollPane = new JScrollPane(textArea, -+ JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, -+ JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); -+ -+ textArea.setEditable(false); -+ textArea.setFont(new Font("Monospaced", Font.PLAIN, 12)); -+ -+ KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, InputEvent.SHIFT_MASK); -+ AbstractAction escapeAction = new AbstractAction() { -+ public void actionPerformed(ActionEvent actionEvent) { -+ cleanse(); -+ me.dispose(); -+ } -+ }; -+ textArea.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(stroke, "escapeAction"); -+ textArea.getInputMap().put(stroke, "escapeAction"); -+ textArea.getActionMap().put("escapeAction", escapeAction); -+ -+ refreshButton = new JButton(); -+ refreshButton.setText("Reload"); -+ refreshButton.setName("refreshButton"); -+ refreshButton.addActionListener(this); -+ -+ dismissButton = new JButton(); -+ dismissButton.setText("Dismiss"); -+ dismissButton.setName("dismissButton"); -+ dismissButton.addActionListener(this); -+ -+ JPanel buttons = new JPanel(); -+ buttons.setLayout(new BorderLayout()); -+ buttons.add(refreshButton, BorderLayout.WEST); -+ buttons.add(dismissButton, BorderLayout.EAST); -+ -+ JPanel content = new JPanel(); -+ content.setLayout(new BorderLayout()); -+ content.add(scrollPane, BorderLayout.CENTER); -+ content.add(buttons, BorderLayout.SOUTH); -+ -+ ActionListener tsk = new ActionListener() { -+ public void actionPerformed(ActionEvent evt) { -+ // System.out.println("tsk"); -+ refresh(); -+ } -+ }; -+ tim = new Timer(tms, tsk); -+ tim.start(); -+ -+ this.setContentPane(content); -+ this.setTitle("TextViewer - " + s); -+ this.pack(); -+ this.setVisible(true); -+ } -+ -+ private void refresh() { -+ -+ rcnt++; -+ if (rcnt * tms > 3000 && tim != null) { -+ tim.stop(); -+ tim = null; -+ } -+ BufferedReader input = null; -+ StringBuffer contents = new StringBuffer(); -+ try { -+ if (input == null) { -+ input = new BufferedReader(new FileReader(file)); -+ } -+ String line = null; -+ int i = 0; -+ while (( line = input.readLine()) != null) { -+ if (i == 0) { -+ // System.out.println("read"); -+ } -+ i++; -+ contents.append(line); -+ contents.append(System.getProperty("line.separator")); -+ } -+ } catch (Exception e) { -+ ; -+ } finally { -+ try { -+ if (input != null) { -+ input.close(); -+ input = null; -+ } -+ } catch (Exception e) { -+ ; -+ } -+ } -+ -+ textArea.setText(contents.toString()); -+ textArea.setCaretPosition(0); -+ } -+ -+ public void actionPerformed(ActionEvent evt) { -+ -+ if (evt.getSource() == refreshButton) { -+ refresh(); -+ } -+ if (evt.getSource() == dismissButton) { -+ cleanse(); -+ this.dispose(); -+ } -+ } -+ -+ private void cleanse() { -+ if (delete_it && file != null) { -+ try { -+ file.delete(); -+ file = null; -+ } catch (Exception e) { -+ ; -+ } -+ } -+ } -+ -+ protected void finalize() throws Throwable { -+ try { -+ cleanse(); -+ } finally { -+ super.finalize(); -+ } -+ } -+} -+// end runge/x11vnc -diff -Naur JavaViewer.orig/Makefile JavaViewer/Makefile ---- JavaViewer.orig/Makefile 2006-05-29 09:06:32.000000000 -0400 -+++ JavaViewer/Makefile 2010-05-18 20:53:32.000000000 -0400 -@@ -4,6 +4,7 @@ - - CP = cp - JC = javac -+JC_ARGS = -target 1.4 -source 1.4 - JAR = jar - ARCHIVE = VncViewer.jar - PAGES = index.vnc shared.vnc noshared.vnc hextile.vnc zlib.vnc tight.vnc -@@ -20,7 +21,7 @@ - all: $(CLASSES) $(ARCHIVE) - - $(CLASSES): $(SOURCES) -- $(JC) -O $(SOURCES) -+ $(JC) $(JC_ARGS) -O $(SOURCES) - - $(ARCHIVE): $(CLASSES) - $(JAR) cf $(ARCHIVE) $(CLASSES) -diff -Naur JavaViewer.orig/OptionsFrame.java JavaViewer/OptionsFrame.java ---- JavaViewer.orig/OptionsFrame.java 2005-11-21 18:50:16.000000000 -0500 -+++ JavaViewer/OptionsFrame.java 2007-05-13 22:18:30.000000000 -0400 -@@ -144,7 +144,10 @@ - choices[jpegQualityIndex].select("6"); - choices[cursorUpdatesIndex].select("Enable"); - choices[useCopyRectIndex].select("Yes"); -- choices[eightBitColorsIndex].select("64"); -+// begin runge/x11vnc -+// choices[eightBitColorsIndex].select("64"); -+ choices[eightBitColorsIndex].select("Full"); -+// end runge/x11vnc - choices[mouseButtonIndex].select("Normal"); - choices[viewOnlyIndex].select("No"); - choices[shareDesktopIndex].select("Yes"); -diff -Naur JavaViewer.orig/RfbProto.java JavaViewer/RfbProto.java ---- JavaViewer.orig/RfbProto.java 2006-05-24 15:14:40.000000000 -0400 -+++ JavaViewer/RfbProto.java 2010-11-30 22:13:58.000000000 -0500 -@@ -31,6 +31,7 @@ - import java.net.Socket; - import java.util.*; - import java.util.zip.*; -+import java.text.DateFormat; - - - class RfbProto { -@@ -86,8 +87,11 @@ - - // sf@2004 - FileTransfer part - ArrayList remoteDirsList; -+ ArrayList remoteDirsListInfo; - ArrayList remoteFilesList; -+ ArrayList remoteFilesListInfo; - ArrayList a; -+ ArrayList b; - boolean fFTInit = true; // sf@2004 - boolean fFTAllowed = true; - boolean fAbort = false; -@@ -199,6 +203,10 @@ - // playback. - int numUpdatesInSession; - -+// begin runge/x11vnc -+ int readServerDriveListCnt = -1; -+ long readServerDriveListTime = 0; -+// end runge/x11vnc - // - // Constructor. Make TCP connection to RFB server. - // -@@ -207,7 +215,27 @@ - viewer = v; - host = h; - port = p; -- sock = new Socket(host, port); -+// begin runge/x11vnc -+// sock = new Socket(host, port); -+ if (! viewer.disableSSL) { -+ System.out.println("new SSLSocketToMe"); -+ SSLSocketToMe ssl; -+ try { -+ ssl = new SSLSocketToMe(host, port, v); -+ } catch (Exception e) { -+ throw new IOException(e.getMessage()); -+ } -+ -+ try { -+ sock = ssl.connectSock(); -+ } catch (Exception es) { -+ throw new IOException(es.getMessage()); -+ } -+ } else { -+ sock = new Socket(host, port); -+ } -+// end runge/x11vnc -+ - is = - new DataInputStream( - new BufferedInputStream(sock.getInputStream(), 16384)); -@@ -215,9 +243,12 @@ - osw = new OutputStreamWriter(sock.getOutputStream()); - inDirectory2 = false; - a = new ArrayList(); -+ b = new ArrayList(); - // sf@2004 - remoteDirsList = new ArrayList(); -+ remoteDirsListInfo = new ArrayList(); - remoteFilesList = new ArrayList(); -+ remoteFilesListInfo = new ArrayList(); - - sendFileSource = ""; - } -@@ -420,7 +451,13 @@ - // - - int readServerMessageType() throws IOException { -- int msgType = is.readUnsignedByte(); -+ int msgType; -+ try { -+ msgType = is.readUnsignedByte(); -+ } catch (Exception e) { -+ viewer.disconnect(); -+ return -1; -+ } - - // If the session is being recorded: - if (rec != null) { -@@ -600,6 +637,7 @@ - contentParamT = is.readUnsignedByte(); - contentParamT = contentParamT << 8; - contentParam = contentParam | contentParamT; -+//System.out.println("FTM: contentType " + contentType + " contentParam " + contentParam); - if (contentType == rfbRDrivesList || contentType == rfbDirPacket) - { - readDriveOrDirectory(contentParam); -@@ -610,7 +648,7 @@ - } - else if (contentType == rfbFilePacket) - { -- receiveFileChunk(); -+ receiveFileChunk(); - } - else if (contentType == rfbEndOfFile) - { -@@ -618,6 +656,10 @@ - } - else if (contentType == rfbAbortFileTransfer) - { -+ System.out.println("rfbAbortFileTransfer: fFileReceptionRunning=" -+ + fFileReceptionRunning + " fAbort=" -+ + fAbort + " fFileReceptionError=" -+ + fFileReceptionError); - if (fFileReceptionRunning) - { - endOfReceiveFile(false); // Error -@@ -626,6 +668,11 @@ - { - // sf@2004 - Todo: Add TestPermission - // System.out.println("File Transfer Aborted!"); -+ -+ // runge: seems like we must at least read the remaining -+ // 8 bytes of the header, right? -+ int size = is.readInt(); -+ int length = is.readInt(); - } - - } -@@ -645,6 +692,7 @@ - { - System.out.println("ContentType: " + contentType); - } -+//System.out.println("FTM: done"); - } - - //Refactored from readRfbFileTransferMsg() -@@ -662,6 +710,7 @@ - - //Refactored from readRfbFileTransferMsg() - public void readDriveOrDirectory(int contentParam) throws IOException { -+//System.out.println("RDOD: " + contentParam + " " + inDirectory2); - if (contentParam == rfbADrivesList) - { - readFTPMsgDriveList(); -@@ -688,13 +737,21 @@ - - // Internally used. Write an Rfb message to the server - void writeRfbFileTransferMsg( -- int contentType, -- int contentParam, -- long size, // 0 : compression not supported - 1 : compression supported -- long length, -- String text) throws IOException -+ int contentType, -+ int contentParam, -+ long size, // 0 : compression not supported - 1 : compression supported -+ long length, -+ String text) throws IOException - { - byte b[] = new byte[12]; -+ byte byteArray[]; -+ -+ if (viewer.dsmActive) { -+ // need to send the rfbFileTransfer msg type twice for the plugin... -+ byte b2[] = new byte[1]; -+ b2[0] = (byte) rfbFileTransfer; -+ os.write(b2); -+ } - - b[0] = (byte) rfbFileTransfer; - b[1] = (byte) contentType; -@@ -702,7 +759,7 @@ - - byte by = 0; - long c = 0; -- length++; -+ - c = size & 0xFF000000; - by = (byte) (c >>> 24); - b[4] = by; -@@ -716,6 +773,32 @@ - by = (byte) c; - b[7] = by; - -+ if (text != null) { -+ byte byteArray0[] = text.getBytes(); -+ int maxc = max_char(text); -+ if (maxc > 255) { -+ System.out.println("writeRfbFileTransferMsg: using getBytes(\"UTF-8\")"); -+ byteArray0 = text.getBytes("UTF-8"); -+ } else if (maxc > 127) { -+ System.out.println("writeRfbFileTransferMsg: using getBytes(\"ISO-8859-1\")"); -+ byteArray0 = text.getBytes("ISO-8859-1"); -+ } -+ byteArray = new byte[byteArray0.length + 1]; -+ for (int i = 0; i < byteArray0.length; i++) { -+ byteArray[i] = byteArray0[i]; -+ } -+ byteArray[byteArray.length - 1] = 0; -+System.out.println("writeRfbFileTransferMsg: length: " + length + " -> byteArray.length: " + byteArray.length); -+ -+ // will equal length for ascii, ISO-8859-1, more for UTF-8 -+ length = byteArray.length; -+ -+ //length++; // used to not include null byte at end. -+ } else { -+ String moo = "moo"; -+ byteArray = moo.getBytes(); -+ } -+ - c = length & 0xFF000000; - by = (byte) (c >>> 24); - b[8] = by; -@@ -729,29 +812,91 @@ - by = (byte) c; - b[11] = by; - os.write(b); -+ -+//System.out.println("size: " + size + " length: " + length + " text: " + text); - - - if (text != null) - { -- byte byteArray[] = text.getBytes(); -- byte byteArray2[] = new byte[byteArray.length + 1]; -- for (int i = 0; i < byteArray.length; i++) { -- byteArray2[i] = byteArray[i]; -+ os.write(byteArray); -+ } -+ } -+ -+ int max_char(String text) { -+ int maxc = 0; -+ char chars[] = text.toCharArray(); -+ for (int n = 0; n < chars.length; n++) { -+ if ((int) chars[n] > maxc) { -+ maxc = (int) chars[n]; - } -- byteArray2[byteArray2.length - 1] = 0; -- os.write(byteArray2); - } -- -+ return maxc; - } - -+ String guess_encoding(char[] chars) { -+ boolean saw_high_char = false; -+ -+ for (int i = 0; i < chars.length; i++) { -+ if (chars[i] == '\0') { -+ break; -+ } -+ if (chars[i] >= 128) { -+ saw_high_char = true; -+ break; -+ } -+ } -+ if (!saw_high_char) { -+ return "ASCII"; -+ } -+ char prev = 1; -+ boolean valid_utf8 = true; -+ int n = 0; -+ for (int i = 0; i < chars.length; i++) { -+ if (chars[i] == '\0') { -+ break; -+ } -+ char c = chars[i]; -+ if (prev < 128 && c >= 128) { -+ if (c >> 5 == 0x6) { -+ n = 1; -+ } else if (c >> 4 == 0xe) { -+ n = 2; -+ } else if (c >> 3 == 0x1e) { -+ n = 3; -+ } else if (c >> 2 == 0x3e) { -+ n = 4; -+ } else { -+ valid_utf8 = false; -+ break; -+ } -+ } else { -+ if (n > 0) { -+ if (c < 128) { -+ valid_utf8 = false; -+ break; -+ } -+ n--; -+ } -+ } -+ -+ prev = c; -+ } -+ if (valid_utf8) { -+ return "UTF-8"; -+ } else { -+ return "ISO-8859-1"; -+ } -+ } -+ -+ - //Internally used. Write an rfb message to the server for sending files ONLY - int writeRfbFileTransferMsgForSendFile( -- int contentType, -- int contentParam, -- long size, -- long length, -- String source -- ) throws IOException -+ int contentType, -+ int contentParam, -+ long size, -+ long length, -+ String source -+ ) throws IOException - { - File f = new File(source); - fis = new FileInputStream(f); -@@ -768,50 +913,47 @@ - - while (bytesRead!=-1) - { -- counter += bytesRead; -- myDeflater.setInput(byteBuffer, 0, bytesRead); -- myDeflater.finish(); -- compressedSize = myDeflater.deflate(CompressionBuffer); -- myDeflater.reset(); -- // If the compressed data is larger than the original one, we're dealing with -- // already compressed data -- if (compressedSize > bytesRead) -- fCompress = false; -- this.writeRfbFileTransferMsg( -- contentType, -- contentParam, -- (fCompress ? 1 : 0), -- (fCompress ? compressedSize-1 : bytesRead-1), -- null -- ); -- // Todo: Test write error ! -- os.write( -- fCompress ? CompressionBuffer : byteBuffer, -- 0, -- fCompress ? compressedSize : bytesRead -- ); -- -- // Todo: test read error ! -- bytesRead = fis.read(byteBuffer); -- -- // viewer.ftp.connectionStatus.setText("Sent: "+ counter + " bytes of "+ f.length() + " bytes"); -- viewer.ftp.jProgressBar.setValue((int)((counter * 100) / f.length())); -- viewer.ftp.connectionStatus.setText(">>> Sending File: " + source + " - Size: " + f.length() + " bytes - Progress: " + ((counter * 100) / f.length()) + "%"); -- -- if (fAbort == true) -- { -- fAbort = false; -- fError = true; -- break; -- } -- try -- { -- Thread.sleep(5); -- } -- catch(InterruptedException e) -- { -- System.err.println("Interrupted"); -- } -+ counter += bytesRead; -+ myDeflater.setInput(byteBuffer, 0, bytesRead); -+ myDeflater.finish(); -+ compressedSize = myDeflater.deflate(CompressionBuffer); -+ myDeflater.reset(); -+ // If the compressed data is larger than the original one, we're dealing with -+ // already compressed data -+ if (compressedSize > bytesRead) -+ fCompress = false; -+ this.writeRfbFileTransferMsg( -+ contentType, -+ contentParam, -+ (fCompress ? 1 : 0), -+// RUNGE (fCompress ? compressedSize-1 : bytesRead-1), -+ (fCompress ? compressedSize : bytesRead), -+ null -+ ); -+ // Todo: Test write error ! -+ os.write(fCompress ? CompressionBuffer : byteBuffer, 0, fCompress ? compressedSize : bytesRead); -+ -+ // Todo: test read error ! -+ bytesRead = fis.read(byteBuffer); -+ -+ // viewer.ftp.connectionStatus.setText("Sent: "+ counter + " bytes of "+ f.length() + " bytes"); -+ viewer.ftp.jProgressBar.setValue((int)((counter * 100) / f.length())); -+ viewer.ftp.connectionStatus.setText(">>> Sending File: " + source + " - Size: " + f.length() + " bytes - Progress: " + ((counter * 100) / f.length()) + "%"); -+ -+ if (fAbort == true) -+ { -+ fAbort = false; -+ fError = true; -+ break; -+ } -+ try -+ { -+ Thread.sleep(5); -+ } -+ catch(InterruptedException e) -+ { -+ System.err.println("Interrupted"); -+ } - } - - writeRfbFileTransferMsg(fError ? rfbAbortFileTransfer : rfbEndOfFile, 0, 0, 0, null); -@@ -831,24 +973,30 @@ - { - System.out.print((char) is.readUnsignedByte()); - } -+ System.out.println(""); -+ -+ if (size == rfbRErrorCmd || size == -1) { -+ viewer.ftp.enableButtons(); -+ viewer.ftp.connectionStatus.setText("Remote file not available for writing."); -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - Remote file not available for writing."), 0); -+ viewer.ftp.historyComboBox.setSelectedIndex(0); -+ return; -+ } - -- int ret = writeRfbFileTransferMsgForSendFile( -- rfbFilePacket, -- 0, -- 0, -- 0, -- sendFileSource); -+ int ret = writeRfbFileTransferMsgForSendFile(rfbFilePacket, 0, 0, 0, sendFileSource); - - viewer.ftp.refreshRemoteLocation(); - if (ret != 1) - { - viewer.ftp.connectionStatus.setText(" > Error - File NOT sent"); -- viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - File: <" + sendFileSource) + "> was not correctly sent (aborted by user or error)",0); -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - File: <" + sendFileSource) -+ + "> was not correctly sent (aborted or error). Data may still be buffered/in transit. Wait for remote listing...",0); - } - else - { - viewer.ftp.connectionStatus.setText(" > File sent"); -- viewer.ftp.historyComboBox.insertItemAt(new String(" > File: <" + sendFileSource) + "> was sent to Remote Machine",0); -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > File: <" + sendFileSource) -+ + "> was sent to Remote Machine. Note: data may still be buffered/in transit. Wait for remote listing...",0); - } - viewer.ftp.historyComboBox.setSelectedIndex(0); - viewer.ftp.enableButtons(); -@@ -907,7 +1055,7 @@ - //Handles acknowledgement that the file has been deleted on the server - void deleteRemoteFileFeedback() throws IOException - { -- is.readInt(); -+ int ret = is.readInt(); - int length = is.readInt(); - String f = ""; - for (int i = 0; i < length; i++) -@@ -916,7 +1064,11 @@ - } - - viewer.ftp.refreshRemoteLocation(); -- viewer.ftp.historyComboBox.insertItemAt(new String(" > Deleted File On Remote Machine: " + f.substring(0, f.length()-1)),0); -+ if (ret == -1) { -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > ERROR Could not Delete File On Remote Machine: "),0); -+ } else { -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > Deleted File On Remote Machine: " + f.substring(0, f.length()-1)),0); -+ } - viewer.ftp.historyComboBox.setSelectedIndex(0); - } - -@@ -926,12 +1078,7 @@ - try - { - String temp = text; -- writeRfbFileTransferMsg( -- rfbCommand, -- rfbCFileDelete, -- 0, -- temp.length(), -- temp); -+ writeRfbFileTransferMsg(rfbCommand, rfbCFileDelete, 0, temp.length(), temp); - } - catch (IOException e) - { -@@ -943,7 +1090,7 @@ - // Handles acknowledgement that the directory has been created on the server - void createRemoteDirectoryFeedback() throws IOException - { -- is.readInt(); -+ int ret = is.readInt(); - int length = is.readInt(); - String f=""; - for (int i = 0; i < length; i++) -@@ -951,7 +1098,11 @@ - f += (char)is.readUnsignedByte(); - } - viewer.ftp.refreshRemoteLocation(); -- viewer.ftp.historyComboBox.insertItemAt(new String(" > Created Directory on Remote Machine: " + f.substring(0, f.length()-1)),0); -+ if (ret == -1) { -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > ERROR Could not Create Directory on Remote Machine."),0); -+ } else { -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > Created Directory on Remote Machine: " + f.substring(0, f.length()-1)),0); -+ } - viewer.ftp.historyComboBox.setSelectedIndex(0); - } - -@@ -961,12 +1112,7 @@ - try - { - String temp = text; -- writeRfbFileTransferMsg( -- rfbCommand, -- rfbCDirCreate, -- 0, -- temp.length(), -- temp); -+ writeRfbFileTransferMsg(rfbCommand, rfbCDirCreate, 0, temp.length(), temp); - } - catch (IOException e) - { -@@ -979,15 +1125,13 @@ - { - try - { -+//System.out.println("requestRemoteFile text: " + text); -+//System.out.println("requestRemoteFile leng: " + text.length()); - String temp = text; - receivePath = localPath; - -- writeRfbFileTransferMsg( -- rfbFileTransferRequest, -- 0, -- 1, // 0 : compression not supported - 1 : compression supported -- temp.length(), -- temp); -+ // 0 : compression not supported - 1 : compression supported -+ writeRfbFileTransferMsg(rfbFileTransferRequest, 0, 1, temp.length(), temp); - } - catch (IOException e) - { -@@ -1004,6 +1148,9 @@ - viewer.ftp.disableButtons(); - int size = is.readInt(); - int length = is.readInt(); -+ -+//System.out.println("receiveFileHeader size: " + size); -+//System.out.println("receiveFileHeader leng: " + length); - - String tempName = ""; - for (int i = 0; i < length; i++) -@@ -1011,6 +1158,15 @@ - tempName += (char) is.readUnsignedByte(); - } - -+ if (size == rfbRErrorCmd || size == -1) { -+ fFileReceptionRunning = false; -+ viewer.ftp.enableButtons(); -+ viewer.ftp.connectionStatus.setText("Remote file not available for reading."); -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - Remote file not available for reading."), 0); -+ viewer.ftp.historyComboBox.setSelectedIndex(0); -+ return; -+ } -+ - // sf@2004 - Read the high part of file size (not yet in rfbFileTransferMsg for - // backward compatibility reasons...) - int sizeH = is.readInt(); -@@ -1021,7 +1177,16 @@ - fileSize=0; - fileChunkCounter = 0; - String fileName = receivePath; -- fos = new FileOutputStream(fileName); -+ try { -+ fos = new FileOutputStream(fileName); -+ } catch (Exception e) { -+ fFileReceptionRunning = false; -+ writeRfbFileTransferMsg(rfbAbortFileTransfer, 0, 0, 0, null); -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > ERROR opening Local File: <" + fileName ),0); -+ viewer.ftp.historyComboBox.setSelectedIndex(0); -+ viewer.ftp.enableButtons(); -+ return; -+ } - writeRfbFileTransferMsg(rfbFileHeader, 0, 0, 0, null); - } - -@@ -1085,7 +1250,13 @@ - fAbort = false; - fFileReceptionError = true; - writeRfbFileTransferMsg(rfbAbortFileTransfer, 0, 0, 0, null); -- -+ -+ //runge for use with x11vnc/libvncserver, no rfbAbortFileTransfer reply sent. -+ try {Thread.sleep(500);} catch (InterruptedException e) {} -+ viewer.ftp.enableButtons(); -+ viewer.ftp.refreshLocalLocation(); -+ viewer.ftp.connectionStatus.setText(" > Error - File NOT received"); -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - File: <" + receivePath + "> not correctly received from Remote Machine (aborted by user or error)") ,0); - } - // sf@2004 - For old FT protocole only - /* -@@ -1104,7 +1275,7 @@ - int length = is.readInt(); - fileSize=0; - fos.close(); -- -+ - viewer.ftp.refreshLocalLocation(); - if (fReceptionOk && !fFileReceptionError) - { -@@ -1132,12 +1303,7 @@ - try - { - String temp = text; -- writeRfbFileTransferMsg( -- rfbDirContentRequest, -- rfbRDirContent, -- 0, -- temp.length(), -- temp); -+ writeRfbFileTransferMsg(rfbDirContentRequest, rfbRDirContent, 0, temp.length(), temp); - } - catch (IOException e) - { -@@ -1197,11 +1363,80 @@ - str += temp; - } - } -+ // runge -+ viewer.ftp.receivedRemoteDirectoryName(str); - // viewer.ftp.changeRemoteDirectory(str); - - } - } - -+ int zogswap(int n) { -+ long l = n; -+ if (l < 0) { -+ l += 0x100000000L; -+ } -+ l = l & 0xFFFFFFFF; -+ l = (l >> 24) | ((l & 0x00ff0000) >> 8) | ((l & 0x0000ff00) << 8) | (l << 24); -+ return (int) l; -+ } -+ -+ int windozeToUnix(int L, int H) { -+ long L2 = zogswap(L); -+ long H2 = zogswap(H); -+ long unix = (H2 << 32) + L2; -+ unix -= 11644473600L * 10000000L; -+ unix /= 10000000L; -+ //System.out.println("unix time: " + unix + " H2: " + H2 + " L2: " + L2); -+ return (int) unix; -+ } -+ -+ String timeStr(int t, int h) { -+ if (h == 0) { -+ // x11vnc/libvncserver unix -+ t = zogswap(t); -+ } else { -+ // ultra (except if h==0 by chance) -+ t = windozeToUnix(t, h); -+ } -+ long tl = (long) t; -+ Date date = new Date(tl * 1000); -+ if (true) { -+ return date.toString(); -+ } else { -+ return DateFormat.getDateTimeInstance().format(date); -+ } -+ } -+ -+ String dotPast(double f, int n) { -+ String fs = "" + f; -+ int i = fs.lastIndexOf(".") + n; -+ if (i >= 0) { -+ int len = fs.length(); -+ if (i >= len) { -+ i = len-1; -+ } -+ fs = fs.substring(0, i); -+ } -+ return fs; -+ } -+ String sizeStr(int s) { -+ s = zogswap(s); -+ if (s < 0) { -+ return s + "? B"; -+ } else if (s < 1024) { -+ return s + " B"; -+ } else if (s < 1024 * 1024) { -+ double k = s / 1024.0; -+ String ks = dotPast(k, 3); -+ -+ return s + " (" + ks + " KB)"; -+ } else { -+ double m = s / (1024.0*1024.0); -+ String ms = dotPast(m, 3); -+ return s + " (" + ms + " MB)"; -+ } -+ } -+ - //Internally used to receive directory content from server - //Here, the server sends one file/directory with it's attributes - void readFTPMsgDirectoryListContent() throws IOException -@@ -1217,17 +1452,32 @@ - dwReserved0, - dwReserved1; - long ftCreationTime, ftLastAccessTime, ftLastWriteTime; -+ int ftCreationTimeL, ftLastAccessTimeL, ftLastWriteTimeL; -+ int ftCreationTimeH, ftLastAccessTimeH, ftLastWriteTimeH; - char cFileName, cAlternateFileName; - int length = 0; - is.readInt(); - length = is.readInt(); -+ -+ char[] chars = new char[4*length]; -+ int char_cnt = 0; -+ for (int i = 0; i < chars.length; i++) { -+ chars[i] = '\0'; -+ } -+ - dwFileAttributes = is.readInt(); - length -= 4; -- ftCreationTime = is.readLong(); -+ //ftCreationTime = is.readLong(); -+ ftCreationTimeL = is.readInt(); -+ ftCreationTimeH = is.readInt(); - length -= 8; -- ftLastAccessTime = is.readLong(); -+ //ftLastAccessTime = is.readLong(); -+ ftLastAccessTimeL = is.readInt(); -+ ftLastAccessTimeH = is.readInt(); - length -= 8; -- ftLastWriteTime = is.readLong(); -+ //ftLastWriteTime = is.readLong(); -+ ftLastWriteTimeL = is.readInt(); -+ ftLastWriteTimeH = is.readInt(); - length -= 8; - nFileSizeHigh = is.readInt(); - length -= 4; -@@ -1239,10 +1489,12 @@ - length -= 4; - cFileName = (char) is.readUnsignedByte(); - length--; -+ chars[char_cnt++] = cFileName; - while (cFileName != '\0') - { - fileName += cFileName; - cFileName = (char) is.readUnsignedByte(); -+ chars[char_cnt++] = cFileName; - length--; - } - cAlternateFileName = (char) is.readByte(); -@@ -1253,7 +1505,28 @@ - cAlternateFileName = (char) is.readUnsignedByte(); - length--; - } -- if (dwFileAttributes == 268435456 -+ String guessed = guess_encoding(chars); -+ if (!guessed.equals("ASCII")) { -+ System.out.println("guess: " + guessed + "\t" + fileName); -+ } -+ if (guessed.equals("UTF-8")) { -+ try { -+ byte[] bytes = new byte[char_cnt-1]; -+ for (int i=0; i < char_cnt-1; i++) { -+ bytes[i] = (byte) chars[i]; -+ } -+ String newstr = new String(bytes, "UTF-8"); -+ fileName = newstr; -+ } catch (Exception e) { -+ System.out.println("failed to convert bytes to UTF-8 based string"); -+ } -+ } -+ for (int i = 0; i < char_cnt; i++) { -+ //System.out.println("char[" + i + "]\t" + (int) chars[i]); -+ } -+ if (fileName.length() <= 0) { -+ ; -+ } else if (dwFileAttributes == 268435456 - || dwFileAttributes == 369098752 - || dwFileAttributes == 285212672 - || dwFileAttributes == 271056896 -@@ -1263,11 +1536,74 @@ - || dwFileAttributes == 369623040) - { - fileName = " [" + fileName + "]"; -- remoteDirsList.add(fileName); // sf@2004 -- } -- else -- { -- remoteFilesList.add(" " + fileName); // sf@2004 -+// begin runge/x11vnc -+// remoteDirsList.add(fileName); // sf@2004 -+ int i = -1; -+ String t1 = fileName.toLowerCase(); -+ for (int j = 0; j < remoteDirsList.size(); j++) { -+ String t = (String) remoteDirsList.get(j); -+ String t2 = t.toLowerCase(); -+ if (t1.compareTo(t2) < 0) { -+ i = j; -+ break; -+ } -+ } -+ //String s = "Lastmod: " + timeStr(ftLastWriteTimeL, ftLastWriteTimeH) + " " + fileName; -+ String f2 = fileName; -+ if (f2.length() < 24) { -+ for (int ik = f2.length(); ik < 24; ik++) { -+ f2 = f2 + " "; -+ } -+ } -+ String s = f2 + " \tLastmod: " + timeStr(ftLastWriteTimeL, ftLastWriteTimeH) + " \t\tSize: " + sizeStr(nFileSizeLow); -+ //s = fileName + " Lastmod: " + zogswap(ftLastWriteTimeL); -+ if (i >= 0) { -+ remoteDirsList.add(i, fileName); -+ remoteDirsListInfo.add(i, s); -+ } else { -+ remoteDirsList.add(fileName); -+ remoteDirsListInfo.add(s); -+ } -+// end runge/x11vnc -+ } else { -+// begin runge/x11vnc -+// remoteFilesList.add(" " + fileName); // sf@2004 -+ -+ fileName = " " + fileName; -+ int i = -1; -+ String t1 = fileName.toLowerCase(); -+ for (int j = 0; j < remoteFilesList.size(); j++) { -+ String t = (String) remoteFilesList.get(j); -+ String t2 = t.toLowerCase(); -+ if (t1.compareTo(t2) < 0) { -+ i = j; -+ break; -+ } -+ } -+ String f2 = fileName; -+ if (f2.length() < 24) { -+ for (int ik = f2.length(); ik < 24; ik++) { -+ f2 = f2 + " "; -+ } -+ } -+ -+if (false) { -+System.out.println("fileName: " + f2); -+System.out.println("ftLastWriteTimeL: " + ftLastWriteTimeL); -+System.out.println("ftLastWriteTimeH: " + ftLastWriteTimeH); -+System.out.println("nFileSizeLow: " + nFileSizeLow); -+} -+ -+ String s = f2 + " \tLastmod: " + timeStr(ftLastWriteTimeL, ftLastWriteTimeH) + " \t\tSize: " + sizeStr(nFileSizeLow); -+ //s = fileName + " Lastmod: " + ftLastWriteTimeL + "/" + zogswap(ftLastWriteTimeL) + " Size: " + nFileSizeLow + "/" + zogswap(nFileSizeLow); -+ if (i >= 0) { -+ remoteFilesList.add(i, fileName); -+ remoteFilesListInfo.add(i, s); -+ } else { -+ remoteFilesList.add(fileName); -+ remoteFilesListInfo.add(s); -+ } -+// end runge/x11vnc - } - - // a.add(fileName); -@@ -1282,14 +1618,32 @@ - - // sf@2004 - a.clear(); -- for (int i = 0; i < remoteDirsList.size(); i++) -+ b.clear(); -+ for (int i = 0; i < remoteDirsList.size(); i++) { - a.add(remoteDirsList.get(i)); -- for (int i = 0; i < remoteFilesList.size(); i++) -+ b.add(remoteDirsListInfo.get(i)); -+ } -+ for (int i = 0; i < remoteFilesList.size(); i++) { - a.add(remoteFilesList.get(i)); -+ -+ b.add(remoteFilesListInfo.get(i)); -+ } - remoteDirsList.clear(); -+ remoteDirsListInfo.clear(); - remoteFilesList.clear(); -+ remoteFilesListInfo.clear(); - -- viewer.ftp.printDirectory(a); -+// begin runge/x11vnc -+ // Hack for double listing at startup... probably libvncserver bug.. -+ readServerDriveListCnt++; -+ if (readServerDriveListCnt == 2) { -+ if (System.currentTimeMillis() - readServerDriveListTime < 2000) { -+//System.out.println("readServerDriveListCnt skip " + readServerDriveListCnt); -+ return; -+ } -+ } -+// end runge/x11vnc -+ viewer.ftp.printDirectory(a, b); - } - - //Internally used to signify the drive requested is not ready -@@ -1299,6 +1653,8 @@ - System.out.println("Remote Drive unavailable"); - viewer.ftp.connectionStatus.setText(" > WARNING - Remote Drive unavailable (possibly restricted access or media not present)"); - viewer.ftp.remoteStatus.setText("WARNING: Remote Drive unavailable"); -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > WARNING: Remote Drive unavailable."), 0); -+ viewer.ftp.historyComboBox.setSelectedIndex(0); - } - - //Call this method to request the list of drives on the server. -@@ -1306,12 +1662,11 @@ - { - try - { -- viewer.rfb.writeRfbFileTransferMsg( -- RfbProto.rfbDirContentRequest, -- RfbProto.rfbRDrivesList, -- 0, -- 0, -- null); -+ viewer.rfb.writeRfbFileTransferMsg(RfbProto.rfbDirContentRequest, RfbProto.rfbRDrivesList, 0, 0, null); -+// begin runge/x11vnc -+ readServerDriveListCnt = 0; -+ readServerDriveListTime = System.currentTimeMillis(); -+// end runge/x11vnc - } - catch (IOException e) - { -@@ -1355,21 +1710,21 @@ - int h, - boolean incremental) - throws IOException { -- if (!viewer.ftp.isVisible()) { -- byte[] b = new byte[10]; -+ if (!viewer.ftp.isVisible()) { -+ byte[] b = new byte[10]; - -- b[0] = (byte) FramebufferUpdateRequest; -- b[1] = (byte) (incremental ? 1 : 0); -- b[2] = (byte) ((x >> 8) & 0xff); -- b[3] = (byte) (x & 0xff); -- b[4] = (byte) ((y >> 8) & 0xff); -- b[5] = (byte) (y & 0xff); -- b[6] = (byte) ((w >> 8) & 0xff); -- b[7] = (byte) (w & 0xff); -- b[8] = (byte) ((h >> 8) & 0xff); -- b[9] = (byte) (h & 0xff); -+ b[0] = (byte) FramebufferUpdateRequest; -+ b[1] = (byte) (incremental ? 1 : 0); -+ b[2] = (byte) ((x >> 8) & 0xff); -+ b[3] = (byte) (x & 0xff); -+ b[4] = (byte) ((y >> 8) & 0xff); -+ b[5] = (byte) (y & 0xff); -+ b[6] = (byte) ((w >> 8) & 0xff); -+ b[7] = (byte) (w & 0xff); -+ b[8] = (byte) ((h >> 8) & 0xff); -+ b[9] = (byte) (h & 0xff); - -- os.write(b); -+ os.write(b); - } - } - -@@ -1482,7 +1837,13 @@ - b[6] = (byte) ((text.length() >> 8) & 0xff); - b[7] = (byte) (text.length() & 0xff); - -- System.arraycopy(text.getBytes(), 0, b, 8, text.length()); -+ if (false && max_char(text) > 255) { -+ System.arraycopy(text.getBytes("UTF-8"), 0, b, 8, text.length()); -+ } else if (max_char(text) > 127) { -+ System.arraycopy(text.getBytes("ISO-8859-1"), 0, b, 8, text.length()); -+ } else { -+ System.arraycopy(text.getBytes(), 0, b, 8, text.length()); -+ } - - os.write(b); - // } -@@ -1506,6 +1867,37 @@ - final static int META_MASK = InputEvent.META_MASK; - final static int ALT_MASK = InputEvent.ALT_MASK; - -+ void writeWheelEvent(MouseWheelEvent evt) throws IOException { -+ eventBufLen = 0; -+ -+ int x = evt.getX(); -+ int y = evt.getY(); -+ -+ if (x < 0) x = 0; -+ if (y < 0) y = 0; -+ -+ int ptrmask; -+ -+ int clicks = evt.getWheelRotation(); -+ System.out.println("writeWheelEvent: clicks: " + clicks); -+ if (clicks > 0) { -+ ptrmask = 16; -+ } else if (clicks < 0) { -+ ptrmask = 8; -+ } else { -+ return; -+ } -+ -+ eventBuf[eventBufLen++] = (byte) PointerEvent; -+ eventBuf[eventBufLen++] = (byte) ptrmask; -+ eventBuf[eventBufLen++] = (byte) ((x >> 8) & 0xff); -+ eventBuf[eventBufLen++] = (byte) (x & 0xff); -+ eventBuf[eventBufLen++] = (byte) ((y >> 8) & 0xff); -+ eventBuf[eventBufLen++] = (byte) (y & 0xff); -+ -+ os.write(eventBuf, 0, eventBufLen); -+ } -+ - // - // Write a pointer event message. We may need to send modifier key events - // around it to set the correct modifier state. -@@ -1610,6 +2002,21 @@ - - boolean down = (evt.getID() == KeyEvent.KEY_PRESSED); - -+ if (viewer.debugKeyboard) { -+ System.out.println("----------------------------------------"); -+ System.out.println("evt.getKeyChar: " + evt.getKeyChar()); -+ System.out.println("getKeyText: " + KeyEvent.getKeyText(evt.getKeyCode())); -+ System.out.println("evt.getKeyCode: " + evt.getKeyCode()); -+ System.out.println("evt.getID: " + evt.getID()); -+ System.out.println("evt.getKeyLocation: " + evt.getKeyLocation()); -+ System.out.println("evt.isActionKey: " + evt.isActionKey()); -+ System.out.println("evt.isControlDown: " + evt.isControlDown()); -+ System.out.println("evt.getModifiers: " + evt.getModifiers()); -+ System.out.println("getKeyModifiersText: " + KeyEvent.getKeyModifiersText(evt.getModifiers())); -+ System.out.println("evt.paramString: " + evt.paramString()); -+ } -+ -+ - int key; - if (evt.isActionKey()) { - -@@ -1685,6 +2092,9 @@ - default : - return; - } -+ if (key == 0xffc2 && viewer.mapF5_to_atsign) { -+ key = 0x40; -+ } - - } else { - -@@ -1794,6 +2204,16 @@ - int oldModifiers = 0; - - void writeModifierKeyEvents(int newModifiers) { -+ if(viewer.forbid_Ctrl_Alt) { -+ if ((newModifiers & CTRL_MASK) != 0 && (newModifiers & ALT_MASK) != 0) { -+ int orig = newModifiers; -+ newModifiers &= ~ALT_MASK; -+ newModifiers &= ~CTRL_MASK; -+ if (viewer.debugKeyboard) { -+ System.out.println("Ctrl+Alt modifiers: " + orig + " -> " + newModifiers); -+ } -+ } -+ } - if ((newModifiers & CTRL_MASK) != (oldModifiers & CTRL_MASK)) - writeKeyEvent(0xffe3, (newModifiers & CTRL_MASK) != 0); - -diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java ---- JavaViewer.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500 -+++ JavaViewer/SSLSocketToMe.java 2010-07-10 19:18:06.000000000 -0400 -@@ -0,0 +1,2067 @@ -+/* -+ * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer. -+ * -+ * Copyright (c) 2006 Karl J. Runge <runge@karlrunge.com> -+ * All rights reserved. -+ * -+ * This 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; version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software 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 this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ * -+ */ -+ -+import java.net.*; -+import java.io.*; -+import javax.net.ssl.*; -+import java.util.*; -+ -+import java.security.*; -+import java.security.cert.*; -+import java.security.spec.*; -+import java.security.cert.Certificate; -+import java.security.cert.CertificateFactory; -+ -+import java.awt.*; -+import java.awt.event.*; -+ -+public class SSLSocketToMe { -+ -+ /* basic member data: */ -+ String host; -+ int port; -+ VncViewer viewer; -+ -+ boolean debug = true; -+ boolean debug_certs = false; -+ -+ /* sockets */ -+ SSLSocket socket = null; -+ SSLSocketFactory factory; -+ -+ /* fallback for Proxy connection */ -+ boolean proxy_in_use = false; -+ boolean proxy_failure = false; -+ public DataInputStream is = null; -+ public OutputStream os = null; -+ -+ /* strings from user WRT proxy: */ -+ String proxy_auth_string = null; -+ String proxy_dialog_host = null; -+ int proxy_dialog_port = 0; -+ -+ Socket proxySock; -+ DataInputStream proxy_is; -+ OutputStream proxy_os; -+ -+ /* trust contexts */ -+ SSLContext trustloc_ctx; -+ SSLContext trustall_ctx; -+ SSLContext trustsrv_ctx; -+ SSLContext trusturl_ctx; -+ SSLContext trustone_ctx; -+ -+ /* corresponding trust managers */ -+ TrustManager[] trustAllCerts; -+ TrustManager[] trustSrvCert; -+ TrustManager[] trustUrlCert; -+ TrustManager[] trustOneCert; -+ -+ /* client-side SSL auth key (oneTimeKey=...) */ -+ KeyManager[] mykey = null; -+ -+ boolean user_wants_to_see_cert = true; -+ String cert_fail = null; -+ -+ /* cert(s) we retrieve from Web server, VNC server, or serverCert param: */ -+ java.security.cert.Certificate[] trustallCerts = null; -+ java.security.cert.Certificate[] trustsrvCerts = null; -+ java.security.cert.Certificate[] trusturlCerts = null; -+ -+ /* utility to decode hex oneTimeKey=... and serverCert=... */ -+ byte[] hex2bytes(String s) { -+ byte[] bytes = new byte[s.length()/2]; -+ for (int i=0; i<s.length()/2; i++) { -+ int j = 2*i; -+ try { -+ int val = Integer.parseInt(s.substring(j, j+2), 16); -+ if (val > 127) { -+ val -= 256; -+ } -+ Integer I = new Integer(val); -+ bytes[i] = Byte.decode(I.toString()).byteValue(); -+ -+ } catch (Exception e) { -+ ; -+ } -+ } -+ return bytes; -+ } -+ -+ SSLSocketToMe(String h, int p, VncViewer v) throws Exception { -+ host = h; -+ port = p; -+ viewer = v; -+ -+ debug_certs = v.debugCerts; -+ -+ /* we will first try default factory for certification: */ -+ -+ factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); -+ -+ dbg("SSL startup: " + host + " " + port); -+ -+ -+ /* create trust managers to be used if initial handshake fails: */ -+ -+ trustAllCerts = new TrustManager[] { -+ /* -+ * this one accepts everything. Only used if user -+ * has disabled checking (trustAllVncCerts=yes) -+ * or when we grab the cert to show it to them in -+ * a dialog and ask them to manually verify/accept it. -+ */ -+ new X509TrustManager() { -+ public java.security.cert.X509Certificate[] -+ getAcceptedIssuers() { -+ return null; -+ } -+ public void checkClientTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) { -+ /* empty */ -+ } -+ public void checkServerTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) { -+ /* empty */ -+ dbg("ALL: an untrusted connect to grab cert."); -+ } -+ } -+ }; -+ -+ trustUrlCert = new TrustManager[] { -+ /* -+ * this one accepts only the retrieved server -+ * cert by SSLSocket by this applet and stored in -+ * trusturlCerts. -+ */ -+ new X509TrustManager() { -+ public java.security.cert.X509Certificate[] -+ getAcceptedIssuers() { -+ return null; -+ } -+ public void checkClientTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ throw new CertificateException("No Clients (URL)"); -+ } -+ public void checkServerTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ /* we want to check 'certs' against 'trusturlCerts' */ -+ if (trusturlCerts == null) { -+ throw new CertificateException( -+ "No Trust url Certs array."); -+ } -+ if (trusturlCerts.length < 1) { -+ throw new CertificateException( -+ "No Trust url Certs."); -+ } -+ if (certs == null) { -+ throw new CertificateException( -+ "No this-certs array."); -+ } -+ if (certs.length < 1) { -+ throw new CertificateException( -+ "No this-certs Certs."); -+ } -+ if (certs.length != trusturlCerts.length) { -+ throw new CertificateException( -+ "certs.length != trusturlCerts.length " + certs.length + " " + trusturlCerts.length); -+ } -+ boolean ok = true; -+ for (int i = 0; i < certs.length; i++) { -+ if (! trusturlCerts[i].equals(certs[i])) { -+ ok = false; -+ dbg("URL: cert mismatch at i=" + i); -+ dbg("URL: cert mismatch cert" + certs[i]); -+ dbg("URL: cert mismatch url" + trusturlCerts[i]); -+ if (cert_fail == null) { -+ cert_fail = "cert-mismatch"; -+ } -+ } -+ if (debug_certs) { -+ dbg("\n***********************************************"); -+ dbg("URL: cert info at i=" + i); -+ dbg("URL: cert info cert" + certs[i]); -+ dbg("==============================================="); -+ dbg("URL: cert info url" + trusturlCerts[i]); -+ dbg("***********************************************"); -+ } -+ } -+ if (!ok) { -+ throw new CertificateException( -+ "Server Cert Chain != URL Cert Chain."); -+ } -+ dbg("URL: trusturlCerts[i] matches certs[i] i=0:" + (certs.length-1)); -+ } -+ } -+ }; -+ -+ trustSrvCert = new TrustManager[] { -+ /* -+ * this one accepts cert given to us in the serverCert -+ * Applet Parameter we were started with. It is -+ * currently a fatal error if the VNC Server's cert -+ * doesn't match it. -+ */ -+ new X509TrustManager() { -+ public java.security.cert.X509Certificate[] -+ getAcceptedIssuers() { -+ return null; -+ } -+ public void checkClientTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ throw new CertificateException("No Clients (SRV)"); -+ } -+ public void checkServerTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ /* we want to check 'certs' against 'trustsrvCerts' */ -+ if (trustsrvCerts == null) { -+ throw new CertificateException( -+ "No Trust srv Certs array."); -+ } -+ if (trustsrvCerts.length < 1) { -+ throw new CertificateException( -+ "No Trust srv Certs."); -+ } -+ if (certs == null) { -+ throw new CertificateException( -+ "No this-certs array."); -+ } -+ if (certs.length < 1) { -+ throw new CertificateException( -+ "No this-certs Certs."); -+ } -+ if (certs.length != trustsrvCerts.length) { -+ throw new CertificateException( -+ "certs.length != trustsrvCerts.length " + certs.length + " " + trustsrvCerts.length); -+ } -+ boolean ok = true; -+ for (int i = 0; i < certs.length; i++) { -+ if (! trustsrvCerts[i].equals(certs[i])) { -+ ok = false; -+ dbg("SRV: cert mismatch at i=" + i); -+ dbg("SRV: cert mismatch cert" + certs[i]); -+ dbg("SRV: cert mismatch srv" + trustsrvCerts[i]); -+ if (cert_fail == null) { -+ cert_fail = "server-cert-mismatch"; -+ } -+ } -+ if (debug_certs) { -+ dbg("\n***********************************************"); -+ dbg("SRV: cert info at i=" + i); -+ dbg("SRV: cert info cert" + certs[i]); -+ dbg("==============================================="); -+ dbg("SRV: cert info srv" + trustsrvCerts[i]); -+ dbg("***********************************************"); -+ } -+ } -+ if (!ok) { -+ throw new CertificateException( -+ "Server Cert Chain != serverCert Applet Parameter Cert Chain."); -+ } -+ dbg("SRV: trustsrvCerts[i] matches certs[i] i=0:" + (certs.length-1)); -+ } -+ } -+ }; -+ -+ trustOneCert = new TrustManager[] { -+ /* -+ * this one accepts only the retrieved server -+ * cert by SSLSocket by this applet we stored in -+ * trustallCerts that user has accepted or applet -+ * parameter trustAllVncCerts=yes is set. This is -+ * for when we reconnect after the user has manually -+ * accepted the trustall cert in the dialog (or set -+ * trustAllVncCerts=yes applet param.) -+ */ -+ new X509TrustManager() { -+ public java.security.cert.X509Certificate[] -+ getAcceptedIssuers() { -+ return null; -+ } -+ public void checkClientTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ throw new CertificateException("No Clients (ONE)"); -+ } -+ public void checkServerTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ /* we want to check 'certs' against 'trustallCerts' */ -+ if (trustallCerts == null) { -+ throw new CertificateException( -+ "No Trust All Server Certs array."); -+ } -+ if (trustallCerts.length < 1) { -+ throw new CertificateException( -+ "No Trust All Server Certs."); -+ } -+ if (certs == null) { -+ throw new CertificateException( -+ "No this-certs array."); -+ } -+ if (certs.length < 1) { -+ throw new CertificateException( -+ "No this-certs Certs."); -+ } -+ if (certs.length != trustallCerts.length) { -+ throw new CertificateException( -+ "certs.length != trustallCerts.length " + certs.length + " " + trustallCerts.length); -+ } -+ boolean ok = true; -+ for (int i = 0; i < certs.length; i++) { -+ if (! trustallCerts[i].equals(certs[i])) { -+ ok = false; -+ dbg("ONE: cert mismatch at i=" + i); -+ dbg("ONE: cert mismatch cert" + certs[i]); -+ dbg("ONE: cert mismatch all" + trustallCerts[i]); -+ } -+ if (debug_certs) { -+ dbg("\n***********************************************"); -+ dbg("ONE: cert info at i=" + i); -+ dbg("ONE: cert info cert" + certs[i]); -+ dbg("==============================================="); -+ dbg("ONE: cert info all" + trustallCerts[i]); -+ dbg("***********************************************"); -+ } -+ } -+ if (!ok) { -+ throw new CertificateException( -+ "Server Cert Chain != TRUSTALL Cert Chain."); -+ } -+ dbg("ONE: trustallCerts[i] matches certs[i] i=0:" + (certs.length-1)); -+ } -+ } -+ }; -+ -+ /* -+ * The above TrustManagers are used: -+ * -+ * 1) to retrieve the server cert in case of failure to -+ * display it to the user in a dialog. -+ * 2) to subsequently connect to the server if user agrees. -+ */ -+ -+ /* -+ * build oneTimeKey cert+key if supplied in applet parameter: -+ */ -+ if (viewer.oneTimeKey != null && viewer.oneTimeKey.equals("PROMPT")) { -+ ClientCertDialog d = new ClientCertDialog(); -+ viewer.oneTimeKey = d.queryUser(); -+ } -+ if (viewer.oneTimeKey != null && viewer.oneTimeKey.indexOf(",") > 0) { -+ int idx = viewer.oneTimeKey.indexOf(","); -+ -+ String onetimekey = viewer.oneTimeKey.substring(0, idx); -+ byte[] key = hex2bytes(onetimekey); -+ String onetimecert = viewer.oneTimeKey.substring(idx+1); -+ byte[] cert = hex2bytes(onetimecert); -+ -+ KeyFactory kf = KeyFactory.getInstance("RSA"); -+ PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key ); -+ PrivateKey ff = kf.generatePrivate (keysp); -+ if (debug_certs) { -+ dbg("one time key " + ff); -+ } -+ -+ CertificateFactory cf = CertificateFactory.getInstance("X.509"); -+ Collection c = cf.generateCertificates(new ByteArrayInputStream(cert)); -+ Certificate[] certs = new Certificate[c.toArray().length]; -+ if (c.size() == 1) { -+ Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert)); -+ if (debug_certs) { -+ dbg("one time cert" + tmpcert); -+ } -+ certs[0] = tmpcert; -+ } else { -+ certs = (Certificate[]) c.toArray(); -+ } -+ -+ KeyStore ks = KeyStore.getInstance("JKS"); -+ ks.load(null, null); -+ ks.setKeyEntry("onetimekey", ff, "".toCharArray(), certs); -+ String da = KeyManagerFactory.getDefaultAlgorithm(); -+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(da); -+ kmf.init(ks, "".toCharArray()); -+ -+ mykey = kmf.getKeyManagers(); -+ } -+ -+ /* -+ * build serverCert cert if supplied in applet parameter: -+ */ -+ if (viewer.serverCert != null) { -+ CertificateFactory cf = CertificateFactory.getInstance("X.509"); -+ byte[] cert = hex2bytes(viewer.serverCert); -+ Collection c = cf.generateCertificates(new ByteArrayInputStream(cert)); -+ trustsrvCerts = new Certificate[c.toArray().length]; -+ if (c.size() == 1) { -+ Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert)); -+ trustsrvCerts[0] = tmpcert; -+ } else { -+ trustsrvCerts = (Certificate[]) c.toArray(); -+ } -+ } -+ -+ /* the trust loc certs context: */ -+ try { -+ trustloc_ctx = SSLContext.getInstance("SSL"); -+ -+ /* -+ * below is a failed attempt to get jvm's default -+ * trust manager using null (below) makes it so -+ * for HttpsURLConnection the server cannot be -+ * verified (no prompting.) -+ */ -+ if (false) { -+ boolean didit = false; -+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); -+ tmf.init((KeyStore) null); -+ TrustManager [] tml = tmf.getTrustManagers(); -+ for (int i = 0; i < tml.length; i++) { -+ TrustManager tm = tml[i]; -+ if (tm instanceof X509TrustManager) { -+ TrustManager tm1[] = new TrustManager[1]; -+ tm1[0] = tm; -+ trustloc_ctx.init(mykey, tm1, null); -+ didit = true; -+ break; -+ } -+ } -+ if (!didit) { -+ trustloc_ctx.init(mykey, null, null); -+ } -+ } else { -+ /* we have to set trust manager to null */ -+ trustloc_ctx.init(mykey, null, null); -+ } -+ -+ } catch (Exception e) { -+ String msg = "SSL trustloc_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ -+ /* the trust all certs context: */ -+ try { -+ trustall_ctx = SSLContext.getInstance("SSL"); -+ trustall_ctx.init(mykey, trustAllCerts, new -+ java.security.SecureRandom()); -+ -+ } catch (Exception e) { -+ String msg = "SSL trustall_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ -+ /* the trust url certs context: */ -+ try { -+ trusturl_ctx = SSLContext.getInstance("SSL"); -+ trusturl_ctx.init(mykey, trustUrlCert, new -+ java.security.SecureRandom()); -+ -+ } catch (Exception e) { -+ String msg = "SSL trusturl_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ -+ /* the trust srv certs context: */ -+ try { -+ trustsrv_ctx = SSLContext.getInstance("SSL"); -+ trustsrv_ctx.init(mykey, trustSrvCert, new -+ java.security.SecureRandom()); -+ -+ } catch (Exception e) { -+ String msg = "SSL trustsrv_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ -+ /* the trust the one cert from server context: */ -+ try { -+ trustone_ctx = SSLContext.getInstance("SSL"); -+ trustone_ctx.init(mykey, trustOneCert, new -+ java.security.SecureRandom()); -+ -+ } catch (Exception e) { -+ String msg = "SSL trustone_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ } -+ -+ /* -+ * we call this early on to 1) check for a proxy, 2) grab -+ * Browser/JVM accepted HTTPS cert. -+ */ -+ public void check_for_proxy_and_grab_vnc_server_cert() { -+ -+ trusturlCerts = null; -+ proxy_in_use = false; -+ -+ if (viewer.ignoreProxy) { -+ /* applet param says skip it. */ -+ /* the downside is we do not set trusturlCerts for comparison later... */ -+ /* nor do we autodetect x11vnc for GET=1. */ -+ return; -+ } -+ -+ dbg("------------------------------------------------"); -+ dbg("Into check_for_proxy_and_grab_vnc_server_cert():"); -+ -+ dbg("TRYING HTTPS:"); -+ String ustr = "https://" + host + ":"; -+ if (viewer.httpsPort != null) { -+ ustr += viewer.httpsPort; -+ } else { -+ ustr += port; -+ } -+ ustr += viewer.urlPrefix + "/check.https.proxy.connection"; -+ dbg("ustr is: " + ustr); -+ -+ try { -+ /* prepare for an HTTPS URL connection to host:port */ -+ URL url = new URL(ustr); -+ HttpsURLConnection https = (HttpsURLConnection) url.openConnection(); -+ -+ if (mykey != null) { -+ /* with oneTimeKey (mykey) we can't use the default SSL context */ -+ if (trustsrvCerts != null) { -+ dbg("passing trustsrv_ctx to HttpsURLConnection to provide client cert."); -+ https.setSSLSocketFactory(trustsrv_ctx.getSocketFactory()); -+ } else if (trustloc_ctx != null) { -+ dbg("passing trustloc_ctx to HttpsURLConnection to provide client cert."); -+ https.setSSLSocketFactory(trustloc_ctx.getSocketFactory()); -+ } -+ } -+ -+ https.setUseCaches(false); -+ https.setRequestMethod("GET"); -+ https.setRequestProperty("Pragma", "No-Cache"); -+ https.setRequestProperty("Proxy-Connection", "Keep-Alive"); -+ https.setDoInput(true); -+ -+ dbg("trying https.connect()"); -+ https.connect(); -+ -+ dbg("trying https.getServerCertificates()"); -+ trusturlCerts = https.getServerCertificates(); -+ -+ if (trusturlCerts == null) { -+ dbg("set trusturlCerts to null!"); -+ } else { -+ dbg("set trusturlCerts to non-null"); -+ } -+ -+ if (https.usingProxy()) { -+ proxy_in_use = true; -+ dbg("An HTTPS proxy is in use. There may be connection problems."); -+ } -+ -+ dbg("trying https.getContent()"); -+ Object output = https.getContent(); -+ dbg("trying https.disconnect()"); -+ https.disconnect(); -+ if (! viewer.GET) { -+ String header = https.getHeaderField("VNC-Server"); -+ if (header != null && header.startsWith("x11vnc")) { -+ dbg("detected x11vnc server (1), setting GET=1"); -+ viewer.GET = true; -+ } -+ } -+ -+ } catch(Exception e) { -+ dbg("HttpsURLConnection: " + e.getMessage()); -+ } -+ -+ if (proxy_in_use) { -+ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); -+ dbg("------------------------------------------------"); -+ return; -+ } else if (trusturlCerts != null && !viewer.forceProxy) { -+ /* Allow user to require HTTP check? use forceProxy for now. */ -+ dbg("SKIPPING HTTP PROXY CHECK: got trusturlCerts, assuming proxy info is correct."); -+ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); -+ dbg("------------------------------------------------"); -+ return; -+ } -+ -+ /* -+ * XXX need to remember scenario where this extra check -+ * gives useful info. User's Browser proxy settings? -+ */ -+ dbg("TRYING HTTP:"); -+ ustr = "http://" + host + ":" + port; -+ ustr += viewer.urlPrefix + "/index.vnc"; -+ dbg("ustr is: " + ustr); -+ -+ try { -+ /* prepare for an HTTP URL connection to the same host:port (but not httpsPort) */ -+ URL url = new URL(ustr); -+ HttpURLConnection http = (HttpURLConnection) -+ url.openConnection(); -+ -+ http.setUseCaches(false); -+ http.setRequestMethod("GET"); -+ http.setRequestProperty("Pragma", "No-Cache"); -+ http.setRequestProperty("Proxy-Connection", "Keep-Alive"); -+ http.setDoInput(true); -+ -+ dbg("trying http.connect()"); -+ http.connect(); -+ -+ if (http.usingProxy()) { -+ proxy_in_use = true; -+ dbg("An HTTP proxy is in use. There may be connection problems."); -+ } -+ dbg("trying http.getContent()"); -+ Object output = http.getContent(); -+ dbg("trying http.disconnect()"); -+ http.disconnect(); -+ if (! viewer.GET) { -+ String header = http.getHeaderField("VNC-Server"); -+ if (header != null && header.startsWith("x11vnc")) { -+ dbg("detected x11vnc server (2), setting GET=1"); -+ viewer.GET = true; -+ } -+ } -+ } catch(Exception e) { -+ dbg("HttpURLConnection: " + e.getMessage()); -+ } -+ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); -+ dbg("------------------------------------------------"); -+ } -+ -+ public Socket connectSock() throws IOException { -+ /* -+ * first try a https connection to detect a proxy, and -+ * grab the VNC server cert at the same time: -+ */ -+ check_for_proxy_and_grab_vnc_server_cert(); -+ -+ boolean srv_cert = false; -+ -+ if (trustsrvCerts != null) { -+ /* applet parameter suppled serverCert */ -+ dbg("viewer.trustSrvCert-0 using trustsrv_ctx"); -+ factory = trustsrv_ctx.getSocketFactory(); -+ srv_cert = true; -+ } else if (viewer.trustAllVncCerts) { -+ /* trust all certs (no checking) */ -+ dbg("viewer.trustAllVncCerts-0 using trustall_ctx"); -+ factory = trustall_ctx.getSocketFactory(); -+ } else if (trusturlCerts != null) { -+ /* trust certs the Browser/JVM accepted in check_for_proxy... */ -+ dbg("using trusturl_ctx"); -+ factory = trusturl_ctx.getSocketFactory(); -+ } else { -+ /* trust the local defaults */ -+ dbg("using trustloc_ctx"); -+ factory = trustloc_ctx.getSocketFactory(); -+ } -+ -+ socket = null; -+ -+ try { -+ if (proxy_in_use && viewer.forceProxy) { -+ throw new Exception("forcing proxy (forceProxy)"); -+ } else if (viewer.CONNECT != null) { -+ throw new Exception("forcing CONNECT"); -+ } -+ -+ int timeout = 6; -+ if (timeout > 0) { -+ socket = (SSLSocket) factory.createSocket(); -+ InetSocketAddress inetaddr = new InetSocketAddress(host, port); -+ dbg("Using timeout of " + timeout + " secs to: " + host + ":" + port); -+ socket.connect(inetaddr, timeout * 1000); -+ } else { -+ socket = (SSLSocket) factory.createSocket(host, port); -+ } -+ -+ } catch (Exception esock) { -+ dbg("socket error: " + esock.getMessage()); -+ if (proxy_in_use || viewer.CONNECT != null) { -+ proxy_failure = true; -+ if (proxy_in_use) { -+ dbg("HTTPS proxy in use. Trying to go with it."); -+ } else { -+ dbg("viewer.CONNECT reverse proxy in use. Trying to go with it."); -+ } -+ try { -+ socket = proxy_socket(factory); -+ } catch (Exception e) { -+ dbg("proxy_socket error: " + e.getMessage()); -+ } -+ } else { -+ /* n.b. socket is left in error state to cause ex. below. */ -+ } -+ } -+ -+ try { -+ socket.startHandshake(); -+ -+ dbg("The Server Connection Verified OK on 1st try."); -+ -+ java.security.cert.Certificate[] currentTrustedCerts; -+ BrowserCertsDialog bcd; -+ -+ SSLSession sess = socket.getSession(); -+ currentTrustedCerts = sess.getPeerCertificates(); -+ -+ if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-1 keeping socket."); -+ } else if (currentTrustedCerts == null || currentTrustedCerts.length < 1) { -+ try { -+ socket.close(); -+ } catch (Exception e) { -+ dbg("socket is grumpy."); -+ } -+ socket = null; -+ throw new SSLHandshakeException("no current certs"); -+ } -+ -+ String serv = ""; -+ try { -+ CertInfo ci = new CertInfo(currentTrustedCerts[0]); -+ serv = ci.get_certinfo("CN"); -+ } catch (Exception e) { -+ ; -+ } -+ -+ if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-2 skipping browser certs dialog"); -+ user_wants_to_see_cert = false; -+ } else if (viewer.serverCert != null && trustsrvCerts != null) { -+ dbg("viewer.serverCert-1 skipping browser certs dialog"); -+ user_wants_to_see_cert = false; -+ } else if (viewer.trustUrlVncCert) { -+ dbg("viewer.trustUrlVncCert-1 skipping browser certs dialog"); -+ user_wants_to_see_cert = false; -+ } else { -+ /* have a dialog with the user: */ -+ bcd = new BrowserCertsDialog(serv, host + ":" + port); -+ dbg("browser certs dialog begin."); -+ bcd.queryUser(); -+ dbg("browser certs dialog finished."); -+ -+ if (bcd.showCertDialog) { -+ String msg = "user wants to see cert"; -+ dbg(msg); -+ user_wants_to_see_cert = true; -+ if (cert_fail == null) { -+ cert_fail = "user-view"; -+ } -+ throw new SSLHandshakeException(msg); -+ } else { -+ user_wants_to_see_cert = false; -+ dbg("browser certs dialog: user said yes, accept it"); -+ } -+ } -+ -+ } catch (SSLHandshakeException eh) { -+ dbg("SSLHandshakeException: could not automatically verify Server."); -+ dbg("msg: " + eh.getMessage()); -+ -+ -+ /* send a cleanup string just in case: */ -+ String getoutstr = "GET /index.vnc HTTP/1.0\r\nConnection: close\r\n\r\n"; -+ -+ try { -+ OutputStream os = socket.getOutputStream(); -+ os.write(getoutstr.getBytes()); -+ socket.close(); -+ } catch (Exception e) { -+ dbg("socket is grumpy!"); -+ } -+ -+ /* reload */ -+ -+ socket = null; -+ -+ String reason = null; -+ -+ if (srv_cert) { -+ /* for serverCert usage we make this a fatal error. */ -+ throw new IOException("Fatal: VNC Server's Cert does not match Applet Parameter 'serverCert=...'"); -+ /* see below in TrustDialog were we describe this case to user anyway */ -+ } -+ -+ /* -+ * Reconnect, trusting any cert, so we can grab -+ * the cert to show it to the user in a dialog -+ * for him to manually accept. This connection -+ * is not used for anything else. -+ */ -+ factory = trustall_ctx.getSocketFactory(); -+ if (proxy_failure) { -+ socket = proxy_socket(factory); -+ } else { -+ socket = (SSLSocket) factory.createSocket(host, port); -+ } -+ -+ if (debug_certs) { -+ dbg("trusturlCerts: " + trusturlCerts); -+ dbg("trustsrvCerts: " + trustsrvCerts); -+ } -+ if (trusturlCerts == null && cert_fail == null) { -+ cert_fail = "missing-certs"; -+ } -+ -+ try { -+ socket.startHandshake(); -+ -+ dbg("The TrustAll Server Cert-grab Connection (trivially) Verified OK."); -+ -+ /* grab the cert: */ -+ try { -+ SSLSession sess = socket.getSession(); -+ trustallCerts = sess.getPeerCertificates(); -+ } catch (Exception e) { -+ throw new Exception("Could not get " + -+ "Peer Certificate"); -+ } -+ if (debug_certs) { -+ dbg("trustallCerts: " + trustallCerts); -+ } -+ -+ if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-3. skipping dialog, trusting everything."); -+ } else if (! browser_cert_match()) { -+ /* -+ * close socket now, we will reopen after -+ * dialog if user agrees to use the cert. -+ */ -+ try { -+ OutputStream os = socket.getOutputStream(); -+ os.write(getoutstr.getBytes()); -+ socket.close(); -+ } catch (Exception e) { -+ dbg("socket is grumpy!!"); -+ } -+ socket = null; -+ -+ /* dialog with user to accept cert or not: */ -+ -+ TrustDialog td= new TrustDialog(host, port, -+ trustallCerts); -+ -+ if (cert_fail == null) { -+ ; -+ } else if (cert_fail.equals("user-view")) { -+ reason = "Reason for this Dialog:\n\n" -+ + " You Asked to View the Certificate."; -+ } else if (cert_fail.equals("server-cert-mismatch")) { -+ /* this is now fatal error, see above. */ -+ reason = "Reason for this Dialog:\n\n" -+ + " The VNC Server's Certificate does not match the Certificate\n" -+ + " specified in the supplied 'serverCert' Applet Parameter."; -+ } else if (cert_fail.equals("cert-mismatch")) { -+ reason = "Reason for this Dialog:\n\n" -+ + " The VNC Server's Certificate does not match the Website's\n" -+ + " HTTPS Certificate (that you previously accepted; either\n" -+ + " manually or automatically via Certificate Authority.)"; -+ } else if (cert_fail.equals("missing-certs")) { -+ reason = "Reason for this Dialog:\n\n" -+ + " Not all Certificates could be obtained to check."; -+ } -+ -+ if (! td.queryUser(reason)) { -+ String msg = "User decided against it."; -+ dbg(msg); -+ throw new IOException(msg); -+ } -+ } -+ -+ } catch (Exception ehand2) { -+ dbg("** Could not TrustAll Verify Server!"); -+ -+ throw new IOException(ehand2.getMessage()); -+ } -+ -+ /* reload again: */ -+ -+ if (socket != null) { -+ try { -+ socket.close(); -+ } catch (Exception e) { -+ dbg("socket is grumpy!!!"); -+ } -+ socket = null; -+ } -+ -+ /* -+ * Now connect a 3rd time, using the cert -+ * retrieved during connection 2 (sadly, that -+ * the user likely blindly agreed to...) -+ */ -+ -+ factory = trustone_ctx.getSocketFactory(); -+ if (proxy_failure) { -+ socket = proxy_socket(factory); -+ } else { -+ socket = (SSLSocket) factory.createSocket(host, port); -+ } -+ -+ try { -+ socket.startHandshake(); -+ dbg("TrustAll/TrustOne Server Connection Verified #3."); -+ -+ } catch (Exception ehand3) { -+ dbg("** Could not TrustAll/TrustOne Verify Server #3."); -+ -+ throw new IOException(ehand3.getMessage()); -+ } -+ } -+ -+ /* we have socket (possibly null) at this point, so proceed: */ -+ -+ /* handle x11vnc GET=1, if applicable: */ -+ if (socket != null && viewer.GET) { -+ String str = "GET "; -+ str += viewer.urlPrefix; -+ str += "/request.https.vnc.connection"; -+ str += " HTTP/1.0\r\n"; -+ str += "Pragma: No-Cache\r\n"; -+ str += "\r\n"; -+ -+ System.out.println("sending: " + str); -+ OutputStream os = socket.getOutputStream(); -+ String type = "os"; -+ -+ if (type == "os") { -+ os.write(str.getBytes()); -+ os.flush(); -+ System.out.println("used OutputStream"); -+ } else if (type == "bs") { -+ BufferedOutputStream bs = new BufferedOutputStream(os); -+ bs.write(str.getBytes()); -+ bs.flush(); -+ System.out.println("used BufferedOutputStream"); -+ } else if (type == "ds") { -+ DataOutputStream ds = new DataOutputStream(os); -+ ds.write(str.getBytes()); -+ ds.flush(); -+ System.out.println("used DataOutputStream"); -+ } -+ if (false) { -+ String rep = ""; -+ DataInputStream is = new DataInputStream( -+ new BufferedInputStream(socket.getInputStream(), 16384)); -+ while (true) { -+ rep += readline(is); -+ if (rep.indexOf("\r\n\r\n") >= 0) { -+ break; -+ } -+ } -+ System.out.println("rep: " + rep); -+ } -+ } -+ -+ dbg("SSL returning socket to caller."); -+ dbg(""); -+ -+ /* could be null, let caller handle that. */ -+ return (Socket) socket; -+ } -+ -+ boolean browser_cert_match() { -+ String msg = "Browser URL accept previously accepted cert"; -+ -+ if (user_wants_to_see_cert) { -+ return false; -+ } -+ -+ if (viewer.serverCert != null || trustsrvCerts != null) { -+ if (cert_fail == null) { -+ cert_fail = "server-cert-mismatch"; -+ } -+ } -+ if (trustallCerts != null && trusturlCerts != null) { -+ if (trustallCerts.length == trusturlCerts.length) { -+ boolean ok = true; -+ /* check toath trustallCerts (socket) equals trusturlCerts (browser) */ -+ for (int i = 0; i < trusturlCerts.length; i++) { -+ if (! trustallCerts[i].equals(trusturlCerts[i])) { -+ dbg("BCM: cert mismatch at i=" + i); -+ dbg("BCM: cert mismatch url" + trusturlCerts[i]); -+ dbg("BCM: cert mismatch all" + trustallCerts[i]); -+ ok = false; -+ } -+ } -+ if (ok) { -+ System.out.println(msg); -+ if (cert_fail == null) { -+ cert_fail = "did-not-fail"; -+ } -+ return true; -+ } else { -+ if (cert_fail == null) { -+ cert_fail = "cert-mismatch"; -+ } -+ return false; -+ } -+ } -+ } -+ if (cert_fail == null) { -+ cert_fail = "missing-certs"; -+ } -+ return false; -+ } -+ -+ private void dbg(String s) { -+ if (debug) { -+ System.out.println(s); -+ } -+ } -+ -+ private int gint(String s) { -+ int n = -1; -+ try { -+ Integer I = new Integer(s); -+ n = I.intValue(); -+ } catch (Exception ex) { -+ return -1; -+ } -+ return n; -+ } -+ -+ /* this will do the proxy CONNECT negotiation and hook us up. */ -+ -+ private void proxy_helper(String proxyHost, int proxyPort) { -+ -+ boolean proxy_auth = false; -+ String proxy_auth_basic_realm = ""; -+ String hp = host + ":" + port; -+ dbg("proxy_helper: " + proxyHost + ":" + proxyPort + " hp: " + hp); -+ -+ /* we loop here a few times trying for the password case */ -+ for (int k=0; k < 2; k++) { -+ dbg("proxy_in_use psocket: " + k); -+ -+ if (proxySock != null) { -+ try { -+ proxySock.close(); -+ } catch (Exception e) { -+ dbg("proxy socket is grumpy."); -+ } -+ } -+ -+ proxySock = psocket(proxyHost, proxyPort); -+ if (proxySock == null) { -+ dbg("1-a sadly, returning a null socket"); -+ return; -+ } -+ -+ String req1 = "CONNECT " + hp + " HTTP/1.1\r\n" -+ + "Host: " + hp + "\r\n"; -+ -+ dbg("requesting via proxy: " + req1); -+ -+ if (proxy_auth) { -+ if (proxy_auth_string == null) { -+ ProxyPasswdDialog pp = new ProxyPasswdDialog(proxyHost, proxyPort, proxy_auth_basic_realm); -+ pp.queryUser(); -+ proxy_auth_string = pp.getAuth(); -+ } -+ //dbg("auth1: " + proxy_auth_string); -+ -+ String auth2 = Base64Coder.encodeString(proxy_auth_string); -+ //dbg("auth2: " + auth2); -+ -+ req1 += "Proxy-Authorization: Basic " + auth2 + "\r\n"; -+ //dbg("req1: " + req1); -+ -+ dbg("added Proxy-Authorization: Basic ... to request"); -+ } -+ req1 += "\r\n"; -+ -+ try { -+ proxy_os.write(req1.getBytes()); -+ String reply = readline(proxy_is); -+ -+ dbg("proxy replied: " + reply.trim()); -+ -+ if (reply.indexOf("HTTP/1.") == 0 && reply.indexOf(" 407 ") > 0) { -+ proxy_auth = true; -+ proxySock.close(); -+ } else if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { -+ proxySock.close(); -+ proxySock = psocket(proxyHost, proxyPort); -+ if (proxySock == null) { -+ dbg("2-a sadly, returning a null socket"); -+ return; -+ } -+ } -+ } catch(Exception e) { -+ dbg("some proxy socket problem: " + e.getMessage()); -+ } -+ -+ /* read the rest of the HTTP headers */ -+ while (true) { -+ String line = readline(proxy_is); -+ dbg("proxy line: " + line.trim()); -+ if (proxy_auth) { -+ String uc = line.toLowerCase(); -+ if (uc.indexOf("proxy-authenticate:") == 0) { -+ if (uc.indexOf(" basic ") >= 0) { -+ int idx = uc.indexOf(" realm"); -+ if (idx >= 0) { -+ proxy_auth_basic_realm = uc.substring(idx+1); -+ } -+ } -+ } -+ } -+ if (line.equals("\r\n") || line.equals("\n")) { -+ break; -+ } -+ } -+ if (!proxy_auth || proxy_auth_basic_realm.equals("")) { -+ /* we only try once for the non-password case: */ -+ break; -+ } -+ } -+ } -+ -+ public SSLSocket proxy_socket(SSLSocketFactory factory) { -+ Properties props = null; -+ String proxyHost = null; -+ int proxyPort = 0; -+ String proxyHost_nossl = null; -+ int proxyPort_nossl = 0; -+ String str; -+ -+ /* see if we can guess the proxy info from Properties: */ -+ try { -+ props = System.getProperties(); -+ } catch (Exception e) { -+ /* sandboxed applet might not be able to read it. */ -+ dbg("props failed: " + e.getMessage()); -+ } -+ if (viewer.proxyHost != null) { -+ dbg("Using supplied proxy " + viewer.proxyHost + " " + viewer.proxyPort + " applet parameters."); -+ proxyHost = viewer.proxyHost; -+ if (viewer.proxyPort != null) { -+ proxyPort = gint(viewer.proxyPort); -+ } else { -+ proxyPort = 8080; -+ } -+ -+ } else if (props != null) { -+ dbg("\n---------------\nAll props:"); -+ props.list(System.out); -+ dbg("\n---------------\n\n"); -+ -+ /* scrape throught properties looking for proxy info: */ -+ -+ for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { -+ String s = (String) e.nextElement(); -+ String v = System.getProperty(s); -+ String s2 = s.toLowerCase(); -+ String v2 = v.toLowerCase(); -+ -+ if (s2.indexOf("proxy.https.host") >= 0) { -+ proxyHost = v2; -+ continue; -+ } -+ if (s2.indexOf("proxy.https.port") >= 0) { -+ proxyPort = gint(v2); -+ continue; -+ } -+ if (s2.indexOf("proxy.http.host") >= 0) { -+ proxyHost_nossl = v2; -+ continue; -+ } -+ if (s2.indexOf("proxy.http.port") >= 0) { -+ proxyPort_nossl = gint(v2); -+ continue; -+ } -+ } -+ -+ for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { -+ String s = (String) e.nextElement(); -+ String v = System.getProperty(s); -+ String s2 = s.toLowerCase(); -+ String v2 = v.toLowerCase(); -+ -+ if (proxyHost != null && proxyPort > 0) { -+ break; -+ } -+ -+ // look for something like: javaplugin.proxy.config.list = http=10.0.2.1:8082 -+ if (s2.indexOf("proxy") < 0 && v2.indexOf("proxy") < 0) { -+ continue; -+ } -+ if (v2.indexOf("http") < 0) { -+ continue; -+ } -+ -+ String[] pieces = v.split("[,;]"); -+ for (int i = 0; i < pieces.length; i++) { -+ String p = pieces[i]; -+ int j = p.indexOf("https"); -+ if (j < 0) { -+ j = p.indexOf("http"); -+ if (j < 0) { -+ continue; -+ } -+ } -+ j = p.indexOf("=", j); -+ if (j < 0) { -+ continue; -+ } -+ p = p.substring(j+1); -+ String [] hp = p.split(":"); -+ if (hp.length != 2) { -+ continue; -+ } -+ if (hp[0].length() > 1 && hp[1].length() > 1) { -+ -+ proxyPort = gint(hp[1]); -+ if (proxyPort < 0) { -+ continue; -+ } -+ proxyHost = new String(hp[0]); -+ break; -+ } -+ } -+ } -+ } -+ if (proxyHost != null) { -+ if (proxyHost_nossl != null && proxyPort_nossl > 0) { -+ dbg("Using http proxy info instead of https."); -+ proxyHost = proxyHost_nossl; -+ proxyPort = proxyPort_nossl; -+ } -+ } -+ -+ if (proxy_in_use) { -+ if (proxy_dialog_host != null && proxy_dialog_port > 0) { -+ proxyHost = proxy_dialog_host; -+ proxyPort = proxy_dialog_port; -+ } -+ if (proxyHost != null) { -+ dbg("Lucky us! we figured out the Proxy parameters: " + proxyHost + " " + proxyPort); -+ } else { -+ /* ask user to help us: */ -+ ProxyDialog pd = new ProxyDialog(proxyHost, proxyPort); -+ pd.queryUser(); -+ proxyHost = pd.getHost(); -+ proxyPort = pd.getPort(); -+ proxy_dialog_host = new String(proxyHost); -+ proxy_dialog_port = proxyPort; -+ dbg("User said host: " + pd.getHost() + " port: " + pd.getPort()); -+ } -+ -+ proxy_helper(proxyHost, proxyPort); -+ if (proxySock == null) { -+ return null; -+ } -+ } else if (viewer.CONNECT != null) { -+ dbg("viewer.CONNECT psocket:"); -+ proxySock = psocket(host, port); -+ if (proxySock == null) { -+ dbg("1-b sadly, returning a null socket"); -+ return null; -+ } -+ } -+ -+ if (viewer.CONNECT != null) { -+ String hp = viewer.CONNECT; -+ String req2 = "CONNECT " + hp + " HTTP/1.1\r\n" -+ + "Host: " + hp + "\r\n\r\n"; -+ -+ dbg("requesting2: " + req2); -+ -+ try { -+ proxy_os.write(req2.getBytes()); -+ String reply = readline(proxy_is); -+ -+ dbg("proxy replied2: " + reply.trim()); -+ -+ if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { -+ proxySock.close(); -+ proxySock = psocket(proxyHost, proxyPort); -+ if (proxySock == null) { -+ dbg("2-b sadly, returning a null socket"); -+ return null; -+ } -+ } -+ } catch(Exception e) { -+ dbg("proxy socket problem-2: " + e.getMessage()); -+ } -+ -+ while (true) { -+ String line = readline(proxy_is); -+ dbg("proxy line2: " + line.trim()); -+ if (line.equals("\r\n") || line.equals("\n")) { -+ break; -+ } -+ } -+ } -+ -+ Socket sslsock = null; -+ try { -+ sslsock = factory.createSocket(proxySock, host, port, true); -+ } catch(Exception e) { -+ dbg("sslsock prob: " + e.getMessage()); -+ dbg("3 sadly, returning a null socket"); -+ } -+ -+ return (SSLSocket) sslsock; -+ } -+ -+ Socket psocket(String h, int p) { -+ Socket psock = null; -+ try { -+ psock = new Socket(h, p); -+ proxy_is = new DataInputStream(new BufferedInputStream( -+ psock.getInputStream(), 16384)); -+ proxy_os = psock.getOutputStream(); -+ } catch(Exception e) { -+ dbg("psocket prob: " + e.getMessage()); -+ return null; -+ } -+ -+ return psock; -+ } -+ -+ String readline(DataInputStream i) { -+ byte[] ba = new byte[1]; -+ String s = new String(""); -+ ba[0] = 0; -+ try { -+ while (ba[0] != 0xa) { -+ ba[0] = (byte) i.readUnsignedByte(); -+ s += new String(ba); -+ } -+ } catch (Exception e) { -+ ; -+ } -+ return s; -+ } -+} -+ -+class TrustDialog implements ActionListener { -+ String msg, host, text; -+ int port; -+ java.security.cert.Certificate[] trustallCerts = null; -+ boolean viewing_cert = false; -+ boolean trust_this_session = false; -+ -+ /* -+ * this is the gui to show the user the cert and info and ask -+ * them if they want to continue using this cert. -+ */ -+ -+ Button ok, cancel, viewcert; -+ TextArea textarea; -+ Checkbox accept, deny; -+ Dialog dialog; -+ -+ String s1 = "Accept this certificate temporarily for this session"; -+ String s2 = "Do not accept this certificate and do not connect to" -+ + " this VNC server"; -+ String ln = "\n---------------------------------------------------\n\n"; -+ -+ TrustDialog (String h, int p, java.security.cert.Certificate[] s) { -+ host = h; -+ port = p; -+ trustallCerts = s; -+ -+ msg = "VNC Server " + host + ":" + port + " Not Verified"; -+ } -+ -+ public boolean queryUser(String reason) { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame(msg); -+ -+ dialog = new Dialog(frame, true); -+ -+ String infostr = ""; -+ if (trustallCerts.length == 1) { -+ CertInfo ci = new CertInfo(trustallCerts[0]); -+ infostr = ci.get_certinfo("all"); -+ } -+ if (reason != null) { -+ reason += "\n\n"; -+ } -+ -+ text = "\n" -++ "Unable to verify the identity of\n" -++ "\n" -++ " " + host + ":" + port + "\n" -++ "\n" -++ infostr -++ "\n" -++ "as a trusted VNC server.\n" -++ "\n" -++ reason -++ "In General not being able to verify the VNC Server and/or your seeing this Dialog\n" -++ "is due to one of the following:\n" -++ "\n" -++ " - Your requesting to View the Certificate before accepting.\n" -++ "\n" -++ " - The VNC server is using a Self-Signed Certificate or a Certificate\n" -++ " Authority not recognized by your Web Browser or Java Plugin runtime.\n" -++ "\n" -++ " - The use of an Apache SSL portal scheme employing CONNECT proxying AND\n" -++ " the Apache Web server has a certificate *different* from the VNC server's.\n" -++ "\n" -++ " - No previously accepted Certificate (via Web Broswer/Java Plugin) could be\n" -++ " obtained by this applet to compare the VNC Server Certificate against.\n" -++ "\n" -++ " - The VNC Server's Certificate does not match the one specified in the\n" -++ " supplied 'serverCert' Java Applet Parameter.\n" -++ "\n" -++ " - A Man-In-The-Middle attack impersonating as the VNC server that you wish\n" -++ " to connect to. (Wouldn't that be exciting!!)\n" -++ "\n" -++ "By safely copying the VNC server's Certificate (or using a common Certificate\n" -++ "Authority certificate) you can configure your Web Browser and Java Plugin to\n" -++ "automatically authenticate this VNC Server.\n" -++ "\n" -++ "If you do so, then you will only have to click \"Yes\" when this VNC Viewer\n" -++ "applet asks you whether to trust your Browser/Java Plugin's acceptance of the\n" -++ "certificate (except for the Apache portal case above where they don't match.)\n" -++ "\n" -++ "You can also set the applet parameter 'trustUrlVncCert=yes' to automatically\n" -++ "accept certificates already accepted/trusted by your Web Browser/Java Plugin,\n" -++ "and thereby see no dialog from this VNC Viewer applet.\n" -+; -+ -+ /* the accept / do-not-accept radio buttons: */ -+ CheckboxGroup checkbox = new CheckboxGroup(); -+ accept = new Checkbox(s1, true, checkbox); -+ deny = new Checkbox(s2, false, checkbox); -+ -+ /* put the checkboxes in a panel: */ -+ Panel check = new Panel(); -+ check.setLayout(new GridLayout(2, 1)); -+ -+ check.add(accept); -+ check.add(deny); -+ -+ /* make the 3 buttons: */ -+ ok = new Button("OK"); -+ cancel = new Button("Cancel"); -+ viewcert = new Button("View Certificate"); -+ -+ ok.addActionListener(this); -+ cancel.addActionListener(this); -+ viewcert.addActionListener(this); -+ -+ /* put the buttons in their own panel: */ -+ Panel buttonrow = new Panel(); -+ buttonrow.setLayout(new FlowLayout(FlowLayout.LEFT)); -+ buttonrow.add(viewcert); -+ buttonrow.add(ok); -+ buttonrow.add(cancel); -+ -+ /* label at the top: */ -+ Label label = new Label(msg, Label.CENTER); -+ label.setFont(new Font("Helvetica", Font.BOLD, 16)); -+ -+ /* textarea in the middle */ -+ textarea = new TextArea(text, 38, 64, -+ TextArea.SCROLLBARS_VERTICAL_ONLY); -+ textarea.setEditable(false); -+ -+ /* put the two panels in their own panel at bottom: */ -+ Panel bot = new Panel(); -+ bot.setLayout(new GridLayout(2, 1)); -+ bot.add(check); -+ bot.add(buttonrow); -+ -+ /* now arrange things inside the dialog: */ -+ dialog.setLayout(new BorderLayout()); -+ -+ dialog.add("North", label); -+ dialog.add("South", bot); -+ dialog.add("Center", textarea); -+ -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til OK or Cancel pressed. */ -+ -+ return trust_this_session; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ -+ if (evt.getSource() == viewcert) { -+ /* View Certificate button clicked */ -+ if (viewing_cert) { -+ /* show the original info text: */ -+ textarea.setText(text); -+ viewcert.setLabel("View Certificate"); -+ viewing_cert = false; -+ } else { -+ int i; -+ /* show all (likely just one) certs: */ -+ textarea.setText(""); -+ for (i=0; i < trustallCerts.length; i++) { -+ int j = i + 1; -+ textarea.append("Certificate[" + -+ j + "]\n\n"); -+ textarea.append( -+ trustallCerts[i].toString()); -+ textarea.append(ln); -+ } -+ viewcert.setLabel("View Info"); -+ viewing_cert = true; -+ -+ textarea.setCaretPosition(0); -+ } -+ -+ } else if (evt.getSource() == ok) { -+ /* OK button clicked */ -+ if (accept.getState()) { -+ trust_this_session = true; -+ } else { -+ trust_this_session = false; -+ } -+ //dialog.dispose(); -+ dialog.hide(); -+ -+ } else if (evt.getSource() == cancel) { -+ /* Cancel button clicked */ -+ trust_this_session = false; -+ -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ } -+ -+ String get_certinfo() { -+ String all = ""; -+ String fields[] = {"CN", "OU", "O", "L", "C"}; -+ int i; -+ if (trustallCerts.length < 1) { -+ all = ""; -+ return all; -+ } -+ String cert = trustallCerts[0].toString(); -+ -+ /* -+ * For now we simply scrape the cert string, there must -+ * be an API for this... perhaps optionValue? -+ */ -+ -+ for (i=0; i < fields.length; i++) { -+ int f, t, t1, t2; -+ String sub, mat = fields[i] + "="; -+ -+ f = cert.indexOf(mat, 0); -+ if (f > 0) { -+ t1 = cert.indexOf(", ", f); -+ t2 = cert.indexOf("\n", f); -+ if (t1 < 0 && t2 < 0) { -+ continue; -+ } else if (t1 < 0) { -+ t = t2; -+ } else if (t2 < 0) { -+ t = t1; -+ } else if (t1 < t2) { -+ t = t1; -+ } else { -+ t = t2; -+ } -+ if (t > f) { -+ sub = cert.substring(f, t); -+ all = all + " " + sub + "\n"; -+ } -+ } -+ } -+ return all; -+ } -+} -+ -+class ProxyDialog implements ActionListener { -+ String guessedHost = null; -+ String guessedPort = null; -+ /* -+ * this is the gui to show the user the cert and info and ask -+ * them if they want to continue using this cert. -+ */ -+ -+ Button ok; -+ Dialog dialog; -+ TextField entry; -+ String reply = ""; -+ -+ ProxyDialog (String h, int p) { -+ guessedHost = h; -+ try { -+ guessedPort = Integer.toString(p); -+ } catch (Exception e) { -+ guessedPort = "8080"; -+ } -+ } -+ -+ public void queryUser() { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame("Need Proxy host:port"); -+ -+ dialog = new Dialog(frame, true); -+ -+ -+ Label label = new Label("Please Enter your https Proxy info as host:port", Label.CENTER); -+ //label.setFont(new Font("Helvetica", Font.BOLD, 16)); -+ entry = new TextField(30); -+ ok = new Button("OK"); -+ ok.addActionListener(this); -+ -+ String guess = ""; -+ if (guessedHost != null) { -+ guess = guessedHost + ":" + guessedPort; -+ } -+ entry.setText(guess); -+ -+ dialog.setLayout(new BorderLayout()); -+ dialog.add("North", label); -+ dialog.add("Center", entry); -+ dialog.add("South", ok); -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til OK or Cancel pressed. */ -+ return; -+ } -+ -+ public String getHost() { -+ int i = reply.indexOf(":"); -+ if (i < 0) { -+ return "unknown"; -+ } -+ String h = reply.substring(0, i); -+ return h; -+ } -+ -+ public int getPort() { -+ int i = reply.indexOf(":"); -+ int p = 8080; -+ if (i < 0) { -+ return p; -+ } -+ i++; -+ String ps = reply.substring(i); -+ try { -+ Integer I = new Integer(ps); -+ p = I.intValue(); -+ } catch (Exception e) { -+ ; -+ } -+ return p; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ System.out.println(evt.getActionCommand()); -+ if (evt.getSource() == ok) { -+ reply = entry.getText(); -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ } -+} -+ -+class ProxyPasswdDialog implements ActionListener { -+ String guessedHost = null; -+ String guessedPort = null; -+ String guessedUser = null; -+ String guessedPasswd = null; -+ String realm = null; -+ /* -+ * this is the gui to show the user the cert and info and ask -+ * them if they want to continue using this cert. -+ */ -+ -+ Button ok; -+ Dialog dialog; -+ TextField entry1; -+ TextField entry2; -+ String reply1 = ""; -+ String reply2 = ""; -+ -+ ProxyPasswdDialog (String h, int p, String realm) { -+ guessedHost = h; -+ try { -+ guessedPort = Integer.toString(p); -+ } catch (Exception e) { -+ guessedPort = "8080"; -+ } -+ this.realm = realm; -+ } -+ -+ public void queryUser() { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame("Proxy Requires Username and Password"); -+ -+ dialog = new Dialog(frame, true); -+ -+ //Label label = new Label("Please Enter your Web Proxy Username in the top Entry and Password in the bottom Entry", Label.CENTER); -+ TextArea label = new TextArea("Please Enter your Web Proxy\nUsername in the Top Entry and\nPassword in the Bottom Entry,\nand then press OK.", 4, 20, TextArea.SCROLLBARS_NONE); -+ entry1 = new TextField(30); -+ entry2 = new TextField(30); -+ entry2.setEchoChar('*'); -+ ok = new Button("OK"); -+ ok.addActionListener(this); -+ -+ dialog.setLayout(new BorderLayout()); -+ dialog.add("North", label); -+ dialog.add("Center", entry1); -+ dialog.add("South", entry2); -+ dialog.add("East", ok); -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til OK or Cancel pressed. */ -+ return; -+ } -+ -+ public String getAuth() { -+ return reply1 + ":" + reply2; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ System.out.println(evt.getActionCommand()); -+ if (evt.getSource() == ok) { -+ reply1 = entry1.getText(); -+ reply2 = entry2.getText(); -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ } -+} -+ -+class ClientCertDialog implements ActionListener { -+ -+ Button ok; -+ Dialog dialog; -+ TextField entry; -+ String reply = ""; -+ -+ ClientCertDialog() { -+ ; -+ } -+ -+ public String queryUser() { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame("Enter SSL Client Cert+Key String"); -+ -+ dialog = new Dialog(frame, true); -+ -+ -+ Label label = new Label("Please Enter the SSL Client Cert+Key String 308204c0...,...522d2d0a", Label.CENTER); -+ entry = new TextField(30); -+ ok = new Button("OK"); -+ ok.addActionListener(this); -+ -+ dialog.setLayout(new BorderLayout()); -+ dialog.add("North", label); -+ dialog.add("Center", entry); -+ dialog.add("South", ok); -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til OK or Cancel pressed. */ -+ return reply; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ System.out.println(evt.getActionCommand()); -+ if (evt.getSource() == ok) { -+ reply = entry.getText(); -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ } -+} -+ -+class BrowserCertsDialog implements ActionListener { -+ Button yes, no; -+ Dialog dialog; -+ String vncServer; -+ String hostport; -+ public boolean showCertDialog = true; -+ -+ BrowserCertsDialog(String serv, String hp) { -+ vncServer = serv; -+ hostport = hp; -+ } -+ -+ public void queryUser() { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame("Use Browser/JVM Certs?"); -+ -+ dialog = new Dialog(frame, true); -+ -+ String m = ""; -+m += "\n"; -+m += "This VNC Viewer applet does not have its own keystore to track\n"; -+m += "SSL certificates, and so cannot authenticate the certificate\n"; -+m += "of the VNC Server:\n"; -+m += "\n"; -+m += " " + hostport + "\n\n " + vncServer + "\n"; -+m += "\n"; -+m += "on its own.\n"; -+m += "\n"; -+m += "However, it has noticed that your Web Browser and/or Java VM Plugin\n"; -+m += "has previously accepted the same certificate. You may have set\n"; -+m += "this up permanently or just for this session, or the server\n"; -+m += "certificate was signed by a CA cert that your Web Browser or\n"; -+m += "Java VM Plugin has.\n"; -+m += "\n"; -+m += "If the VNC Server connection times out while you are reading this\n"; -+m += "dialog, then restart the connection and try again.\n"; -+m += "\n"; -+m += "Should this VNC Viewer applet now connect to the above VNC server?\n"; -+m += "\n"; -+ -+ TextArea textarea = new TextArea(m, 22, 64, -+ TextArea.SCROLLBARS_VERTICAL_ONLY); -+ textarea.setEditable(false); -+ yes = new Button("Yes"); -+ yes.addActionListener(this); -+ no = new Button("No, Let Me See the Certificate."); -+ no.addActionListener(this); -+ -+ dialog.setLayout(new BorderLayout()); -+ dialog.add("North", textarea); -+ dialog.add("Center", yes); -+ dialog.add("South", no); -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til Yes or No pressed. */ -+ System.out.println("done show()"); -+ return; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ System.out.println(evt.getActionCommand()); -+ if (evt.getSource() == yes) { -+ showCertDialog = false; -+ //dialog.dispose(); -+ dialog.hide(); -+ } else if (evt.getSource() == no) { -+ showCertDialog = true; -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ System.out.println("done actionPerformed()"); -+ } -+} -+ -+class CertInfo { -+ String fields[] = {"CN", "OU", "O", "L", "C"}; -+ java.security.cert.Certificate cert; -+ String certString = ""; -+ -+ CertInfo(java.security.cert.Certificate c) { -+ cert = c; -+ certString = cert.toString(); -+ } -+ -+ String get_certinfo(String which) { -+ int i; -+ String cs = new String(certString); -+ String all = ""; -+ -+ /* -+ * For now we simply scrape the cert string, there must -+ * be an API for this... perhaps optionValue? -+ */ -+ for (i=0; i < fields.length; i++) { -+ int f, t, t1, t2; -+ String sub, mat = fields[i] + "="; -+ -+ f = cs.indexOf(mat, 0); -+ if (f > 0) { -+ t1 = cs.indexOf(", ", f); -+ t2 = cs.indexOf("\n", f); -+ if (t1 < 0 && t2 < 0) { -+ continue; -+ } else if (t1 < 0) { -+ t = t2; -+ } else if (t2 < 0) { -+ t = t1; -+ } else if (t1 < t2) { -+ t = t1; -+ } else { -+ t = t2; -+ } -+ if (t > f) { -+ sub = cs.substring(f, t); -+ all = all + " " + sub + "\n"; -+ if (which.equals(fields[i])) { -+ return sub; -+ } -+ } -+ } -+ } -+ if (which.equals("all")) { -+ return all; -+ } else { -+ return ""; -+ } -+ } -+} -+ -+class Base64Coder { -+ -+ // Mapping table from 6-bit nibbles to Base64 characters. -+ private static char[] map1 = new char[64]; -+ static { -+ int i=0; -+ for (char c='A'; c<='Z'; c++) map1[i++] = c; -+ for (char c='a'; c<='z'; c++) map1[i++] = c; -+ for (char c='0'; c<='9'; c++) map1[i++] = c; -+ map1[i++] = '+'; map1[i++] = '/'; } -+ -+ // Mapping table from Base64 characters to 6-bit nibbles. -+ private static byte[] map2 = new byte[128]; -+ static { -+ for (int i=0; i<map2.length; i++) map2[i] = -1; -+ for (int i=0; i<64; i++) map2[map1[i]] = (byte)i; } -+ -+ /** -+ * Encodes a string into Base64 format. -+ * No blanks or line breaks are inserted. -+ * @param s a String to be encoded. -+ * @return A String with the Base64 encoded data. -+ */ -+ public static String encodeString (String s) { -+ return new String(encode(s.getBytes())); } -+ -+ /** -+ * Encodes a byte array into Base64 format. -+ * No blanks or line breaks are inserted. -+ * @param in an array containing the data bytes to be encoded. -+ * @return A character array with the Base64 encoded data. -+ */ -+ public static char[] encode (byte[] in) { -+ return encode(in,in.length); } -+ -+ /** -+ * Encodes a byte array into Base64 format. -+ * No blanks or line breaks are inserted. -+ * @param in an array containing the data bytes to be encoded. -+ * @param iLen number of bytes to process in <code>in</code>. -+ * @return A character array with the Base64 encoded data. -+ */ -+ public static char[] encode (byte[] in, int iLen) { -+ int oDataLen = (iLen*4+2)/3; // output length without padding -+ int oLen = ((iLen+2)/3)*4; // output length including padding -+ char[] out = new char[oLen]; -+ int ip = 0; -+ int op = 0; -+ while (ip < iLen) { -+ int i0 = in[ip++] & 0xff; -+ int i1 = ip < iLen ? in[ip++] & 0xff : 0; -+ int i2 = ip < iLen ? in[ip++] & 0xff : 0; -+ int o0 = i0 >>> 2; -+ int o1 = ((i0 & 3) << 4) | (i1 >>> 4); -+ int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); -+ int o3 = i2 & 0x3F; -+ out[op++] = map1[o0]; -+ out[op++] = map1[o1]; -+ out[op] = op < oDataLen ? map1[o2] : '='; op++; -+ out[op] = op < oDataLen ? map1[o3] : '='; op++; } -+ return out; } -+ -+ /** -+ * Decodes a string from Base64 format. -+ * @param s a Base64 String to be decoded. -+ * @return A String containing the decoded data. -+ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. -+ */ -+ public static String decodeString (String s) { -+ return new String(decode(s)); } -+ -+ /** -+ * Decodes a byte array from Base64 format. -+ * @param s a Base64 String to be decoded. -+ * @return An array containing the decoded data bytes. -+ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. -+ */ -+ public static byte[] decode (String s) { -+ return decode(s.toCharArray()); } -+ -+ /** -+ * Decodes a byte array from Base64 format. -+ * No blanks or line breaks are allowed within the Base64 encoded data. -+ * @param in a character array containing the Base64 encoded data. -+ * @return An array containing the decoded data bytes. -+ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. -+ */ -+ public static byte[] decode (char[] in) { -+ int iLen = in.length; -+ if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4."); -+ while (iLen > 0 && in[iLen-1] == '=') iLen--; -+ int oLen = (iLen*3) / 4; -+ byte[] out = new byte[oLen]; -+ int ip = 0; -+ int op = 0; -+ while (ip < iLen) { -+ int i0 = in[ip++]; -+ int i1 = in[ip++]; -+ int i2 = ip < iLen ? in[ip++] : 'A'; -+ int i3 = ip < iLen ? in[ip++] : 'A'; -+ if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) -+ throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); -+ int b0 = map2[i0]; -+ int b1 = map2[i1]; -+ int b2 = map2[i2]; -+ int b3 = map2[i3]; -+ if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) -+ throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); -+ int o0 = ( b0 <<2) | (b1>>>4); -+ int o1 = ((b1 & 0xf)<<4) | (b2>>>2); -+ int o2 = ((b2 & 3)<<6) | b3; -+ out[op++] = (byte)o0; -+ if (op<oLen) out[op++] = (byte)o1; -+ if (op<oLen) out[op++] = (byte)o2; } -+ return out; } -+ -+ // Dummy constructor. -+ private Base64Coder() {} -+ -+} -diff -Naur JavaViewer.orig/VncCanvas.java JavaViewer/VncCanvas.java ---- JavaViewer.orig/VncCanvas.java 2005-11-21 18:50:18.000000000 -0500 -+++ JavaViewer/VncCanvas.java 2010-11-30 22:57:50.000000000 -0500 -@@ -27,6 +27,13 @@ - import java.lang.*; - import java.util.zip.*; - -+// begin runge/x11vnc -+import java.util.Collections; -+// end runge/x11vnc -+ -+// begin runge/x11vnc -+// all the MouseWheel stuff below. -+// end runge/x11vnc - - // - // VncCanvas is a subclass of Canvas which draws a VNC desktop on it. -@@ -34,7 +41,7 @@ - - class VncCanvas - extends Canvas -- implements KeyListener, MouseListener, MouseMotionListener { -+ implements KeyListener, MouseListener, MouseMotionListener, MouseWheelListener { - - VncViewer viewer; - RfbProto rfb; -@@ -85,6 +92,22 @@ - - cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF); - -+// begin runge/x11vnc -+// kludge to not show any Java cursor in the canvas since we are -+// showing the soft cursor (should be a user setting...) -+Cursor dot = Toolkit.getDefaultToolkit().createCustomCursor( -+ Toolkit.getDefaultToolkit().createImage(new byte[4]), new Point(0,0), -+ "dot"); -+this.setCursor(dot); -+ -+// while we are at it... get rid of the keyboard traversals that -+// make it so we can't type a Tab character: -+this.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, -+ Collections.EMPTY_SET); -+this.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, -+ Collections.EMPTY_SET); -+// end runge/x11vnc -+ - colors = new Color[256]; - // sf@2005 - Now Default - for (int i = 0; i < 256; i++) -@@ -186,6 +209,7 @@ - inputEnabled = true; - addMouseListener(this); - addMouseMotionListener(this); -+ addMouseWheelListener(this); - if (viewer.showControls) { - viewer.buttonPanel.enableRemoteAccessControls(true); - } -@@ -193,6 +217,7 @@ - inputEnabled = false; - removeMouseListener(this); - removeMouseMotionListener(this); -+ removeMouseWheelListener(this); - if (viewer.showControls) { - viewer.buttonPanel.enableRemoteAccessControls(false); - } -@@ -202,6 +227,9 @@ - - public void setPixelFormat() throws IOException { - // sf@2005 - Adding more color modes -+ if (viewer.graftFtp) { -+ return; -+ } - if (viewer.options.eightBitColors > 0) - { - viewer.options.oldEightBitColors = viewer.options.eightBitColors; -@@ -237,6 +265,9 @@ - } - else - { -+// begin runge/x11vnc -+ viewer.options.oldEightBitColors = viewer.options.eightBitColors; -+// end runge/x11vnc - rfb.writeSetPixelFormat( - 32, - 24, -@@ -376,12 +407,14 @@ - // Start/stop session recording if necessary. - viewer.checkRecordingStatus(); - -- rfb.writeFramebufferUpdateRequest( -- 0, -- 0, -- rfb.framebufferWidth, -- rfb.framebufferHeight, -- false); -+ if (!viewer.graftFtp) { -+ rfb.writeFramebufferUpdateRequest( -+ 0, -+ 0, -+ rfb.framebufferWidth, -+ rfb.framebufferHeight, -+ false); -+ } - - // - // main dispatch loop -@@ -390,6 +423,9 @@ - while (true) { - // Read message type from the server. - int msgType = rfb.readServerMessageType(); -+ if (viewer.ftpOnly && msgType != RfbProto.rfbFileTransfer) { -+ System.out.println("msgType:" + msgType); -+ } - - // Process the message depending on its type. - switch (msgType) { -@@ -1332,6 +1368,9 @@ - public void mouseDragged(MouseEvent evt) { - processLocalMouseEvent(evt, true); - } -+ public void mouseWheelMoved(MouseWheelEvent evt) { -+ processLocalMouseWheelEvent(evt); -+ } - - public void processLocalKeyEvent(KeyEvent evt) { - if (viewer.rfb != null && rfb.inNormalProtocol) { -@@ -1367,6 +1406,19 @@ - evt.consume(); - } - -+ public void processLocalMouseWheelEvent(MouseWheelEvent evt) { -+ if (viewer.rfb != null && rfb.inNormalProtocol) { -+ synchronized(rfb) { -+ try { -+ rfb.writeWheelEvent(evt); -+ } catch (Exception e) { -+ e.printStackTrace(); -+ } -+ rfb.notify(); -+ } -+ } -+ } -+ - public void processLocalMouseEvent(MouseEvent evt, boolean moved) { - if (viewer.rfb != null && rfb.inNormalProtocol) { - if (moved) { -@@ -1532,9 +1584,14 @@ - else - { - result = -- 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF) -- << 16 | (pixBuf[i * 4 + 2] & 0xFF) -- << 8 | (pixBuf[i * 4 + 3] & 0xFF); -+// begin runge/x11vnc -+// 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF) -+// << 16 | (pixBuf[i * 4 + 2] & 0xFF) -+// << 8 | (pixBuf[i * 4 + 3] & 0xFF); -+ 0xFF000000 | (pixBuf[i * 4 + 2] & 0xFF) -+ << 16 | (pixBuf[i * 4 + 1] & 0xFF) -+ << 8 | (pixBuf[i * 4 + 0] & 0xFF); -+// end runge/x11vnc - } - } else { - result = 0; // Transparent pixel -@@ -1565,9 +1622,14 @@ - else - { - result = -- 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF) -- << 16 | (pixBuf[i * 4 + 2] & 0xFF) -- << 8 | (pixBuf[i * 4 + 3] & 0xFF); -+// begin runge/x11vnc -+// 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF) -+// << 16 | (pixBuf[i * 4 + 2] & 0xFF) -+// << 8 | (pixBuf[i * 4 + 3] & 0xFF); -+ 0xFF000000 | (pixBuf[i * 4 + 2] & 0xFF) -+ << 16 | (pixBuf[i * 4 + 1] & 0xFF) -+ << 8 | (pixBuf[i * 4 + 0] & 0xFF); -+// end runge/x11vnc - } - } else { - result = 0; // Transparent pixel -diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java ---- JavaViewer.orig/VncViewer.java 2006-05-24 15:14:40.000000000 -0400 -+++ JavaViewer/VncViewer.java 2010-03-27 18:00:28.000000000 -0400 -@@ -41,6 +41,7 @@ - import java.io.*; - import java.net.*; - import javax.swing.*; -+import java.util.Date; - - public class VncViewer extends java.applet.Applet - implements java.lang.Runnable, WindowListener { -@@ -80,11 +81,11 @@ - GridBagLayout gridbag; - ButtonPanel buttonPanel; - AuthPanel authenticator; -- VncCanvas vc; -+ VncCanvas vc = null; - OptionsFrame options; - ClipboardFrame clipboard; - RecordingFrame rec; -- FTPFrame ftp; // KMC: FTP Frame declaration -+ FTPFrame ftp = null; // KMC: FTP Frame declaration - - // Control session recording. - Object recordingSync; -@@ -96,7 +97,7 @@ - - // Variables read from parameter values. - String host; -- int port; -+ int port, vncserverport; - String passwordParam; - String encPasswordParam; - boolean showControls; -@@ -115,28 +116,75 @@ - int i; - // mslogon support 2 end - -+// begin runge/x11vnc -+boolean disableSSL; -+boolean GET; -+String CONNECT; -+String urlPrefix; -+String httpsPort; -+String oneTimeKey; -+String serverCert; -+String ftpDropDown; -+String proxyHost; -+String proxyPort; -+boolean forceProxy; -+boolean ignoreProxy; -+boolean trustAllVncCerts; -+boolean trustUrlVncCert; -+boolean debugCerts; -+boolean debugKeyboard; -+boolean mapF5_to_atsign; -+boolean forbid_Ctrl_Alt; -+ -+boolean ignoreMSLogonCheck; -+boolean delayAuthPanel; -+boolean ftpOnly; -+boolean graftFtp; -+boolean dsmActive; -+ -+boolean gotAuth; -+int authGot; -+// end runge/x11vnc -+ -+ - // - // init() - // - -+public void ftp_init() { -+ boolean show = false; -+ if (ftp != null) { -+ show = true; -+ } -+ ftp = null; -+ -+ ftp = new FTPFrame(this); // KMC: FTPFrame creation -+ -+ if (show) { -+ ftp.doOpen(); -+ rfb.readServerDriveList(); -+ } -+} -+ - public void init() { - - readParameters(); - - if (inSeparateFrame) { -- vncFrame = new Frame("Ultr@VNC"); -- if (!inAnApplet) { -- vncFrame.add("Center", this); -- } -- vncContainer = vncFrame; -+ vncFrame = new Frame("Ultr@VNC"); -+ if (!inAnApplet) { -+ vncFrame.add("Center", this); -+ } -+ vncContainer = vncFrame; - } else { -- vncContainer = this; -+ vncContainer = this; - } - - recordingSync = new Object(); - - options = new OptionsFrame(this); - clipboard = new ClipboardFrame(this); -+ - // authenticator = new AuthPanel(false); // mslogon support : go to connectAndAuthenticate() - if (RecordingFrame.checkSecurity()) - rec = new RecordingFrame(this); -@@ -147,10 +195,11 @@ - cursorUpdatesDef = null; - eightBitColorsDef = null; - -- if (inSeparateFrame) -+ if (inSeparateFrame && vncFrame != null) - vncFrame.addWindowListener(this); - -- ftp = new FTPFrame(this); // KMC: FTPFrame creation -+ ftp_init(); -+ - rfbThread = new Thread(this); - rfbThread.start(); - } -@@ -186,6 +235,30 @@ - gbc.weightx = 1.0; - gbc.weighty = 1.0; - -+ if (ftpOnly) { -+ if (showControls) { -+ buttonPanel.enableButtons(); -+ } -+ ActionListener taskPerformer = new ActionListener() { -+ public void actionPerformed(ActionEvent evt) { -+ vncFrame.setVisible(false); -+ ftp.setSavedLocations(); -+ if (ftp.isVisible()) { -+ ftp.doClose(); -+ } else { -+ ftp.doOpen(); -+ } -+ rfb.readServerDriveList(); -+ } -+ }; -+ Timer t = new Timer(300, taskPerformer); -+ t.setRepeats(false); -+ t.start(); -+ -+ vc.processNormalProtocol(); -+ return; -+ } -+ - // Add ScrollPanel to applet mode - - // Create a panel which itself is resizeable and can hold -@@ -286,6 +359,24 @@ - - void connectAndAuthenticate() throws Exception { - -+ if (graftFtp) { -+ rfb = new RfbProto(host, port, this); -+ rfb.desktopName = "ftponly"; -+ rfb.framebufferWidth = 12; -+ rfb.framebufferHeight = 12; -+ rfb.bitsPerPixel = 32; -+ rfb.depth = 24; -+ rfb.trueColour = true; -+ rfb.redMax = 255; -+ rfb.greenMax = 255; -+ rfb.blueMax = 255; -+ rfb.redShift = 16; -+ rfb.greenShift = 8; -+ rfb.blueShift = 0; -+ rfb.inNormalProtocol = true; -+ return; -+ } -+ - // If "ENCPASSWORD" parameter is set, decrypt the password into - // the passwordParam string. - -@@ -336,7 +427,22 @@ - // - - -- prologueDetectAuthProtocol() ; -+// begin runge/x11vnc -+ gotAuth = false; -+ if (delayAuthPanel) { -+ if (tryAuthenticate(null, null)) { -+ if (inSeparateFrame) { -+ vncFrame.pack(); -+ vncFrame.show(); -+ } -+ return; -+ } -+ } -+// prologueDetectAuthProtocol() ; -+ if (ignoreMSLogonCheck == false) { -+ prologueDetectAuthProtocol() ; -+ } -+// end runge/x11vnc - - authenticator = new AuthPanel(mslogon); - -@@ -371,6 +477,7 @@ - //mslogon support end - } - -+ int tries = 0; - while (true) { - // Wait for user entering a password, or a username and a password - synchronized(authenticator) { -@@ -390,6 +497,13 @@ - break; - //mslogon support end - -+// begin runge/x11vnc -+ gotAuth = false; -+ if (++tries > 2) { -+ throw new Exception("Incorrect password entered " + tries + " times."); -+ } -+// end runge/x11vnc -+ - // Retry on authentication failure. - authenticator.retry(); - } -@@ -405,9 +519,11 @@ - - void prologueDetectAuthProtocol() throws Exception { - -- rfb = new RfbProto(host, port, this); -+ if (!gotAuth) { -+ rfb = new RfbProto(host, port, this); - -- rfb.readVersionMsg(); -+ rfb.readVersionMsg(); -+ } - - System.out.println("RFB server supports protocol version " + - rfb.serverMajor + "." + rfb.serverMinor); -@@ -431,16 +547,36 @@ - - boolean tryAuthenticate(String us, String pw) throws Exception { - -- rfb = new RfbProto(host, port, this); -+ int authScheme; - -- rfb.readVersionMsg(); -+ if (!gotAuth) { -+ rfb = new RfbProto(host, port, this); - -- System.out.println("RFB server supports protocol version " + -- rfb.serverMajor + "." + rfb.serverMinor); -+ rfb.readVersionMsg(); - -- rfb.writeVersionMsg(); -+ System.out.println("RFB server supports protocol version: " + -+ rfb.serverMajor + "." + rfb.serverMinor); - -- int authScheme = rfb.readAuthScheme(); -+ rfb.writeVersionMsg(); -+ -+ authScheme = rfb.readAuthScheme(); -+ -+ gotAuth = true; -+ authGot = authScheme; -+ } else { -+ authScheme = authGot; -+ } -+// begin runge/x11vnc -+ if (delayAuthPanel && pw == null) { -+ if (authScheme == RfbProto.NoAuth) { -+ System.out.println("No authentication needed"); -+ return true; -+ } else { -+ return false; -+ } -+ } -+System.out.println("as: " + authScheme); -+// end runge/x11vnc - - switch (authScheme) { - -@@ -629,6 +765,10 @@ - - void doProtocolInitialisation() throws IOException { - -+ if (graftFtp) { -+ return; -+ } -+ - rfb.writeClientInit(); - - rfb.readServerInit(); -@@ -774,9 +914,28 @@ - fatalError("HOST parameter not specified"); - } - } -+ Date d = new Date(); -+ System.out.println("-\nSSL VNC Java Applet starting. " + d); - -- String str = readParameter("PORT", true); -- port = Integer.parseInt(str); -+ port = 0; -+ String str = readParameter("PORT", false); -+ if (str != null) { -+ port = Integer.parseInt(str); -+ } -+ // When there is a proxy VNCSERVERPORT may be inaccessible (inside firewall). -+ vncserverport = 0; -+ str = readParameter("VNCSERVERPORT", false); -+ if (str != null) { -+ vncserverport = Integer.parseInt(str); -+ } -+ if (port == 0 && vncserverport == 0) { -+ fatalError("Neither PORT nor VNCSERVERPORT parameters specified"); -+ } -+ if (port == 0) { -+ // Nevertheless, fall back to vncserverport if we have to. -+ System.out.println("using vncserverport: '" + vncserverport + "' for PORT."); -+ port = vncserverport; -+ } - - if (inAnApplet) { - str = readParameter("Open New Window", false); -@@ -804,6 +963,158 @@ - deferScreenUpdates = readIntParameter("Defer screen updates", 20); - deferCursorUpdates = readIntParameter("Defer cursor updates", 10); - deferUpdateRequests = readIntParameter("Defer update requests", 50); -+ -+// begin runge/x11vnc -+ // SSL -+ disableSSL = false; -+ str = readParameter("DisableSSL", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) -+ disableSSL = true; -+ -+ httpsPort = readParameter("httpsPort", false); -+ -+ // Extra GET, CONNECT string: -+ CONNECT = readParameter("CONNECT", false); -+ if (CONNECT != null) { -+ CONNECT = CONNECT.replaceAll(" ", ":"); -+ } -+ -+ GET = false; -+ str = readParameter("GET", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ GET = true; -+ } -+ if (str != null && str.equalsIgnoreCase("1")) { -+ GET = true; -+ } -+ -+ urlPrefix = readParameter("urlPrefix", false); -+ if (urlPrefix != null) { -+ urlPrefix = urlPrefix.replaceAll("%2F", "/"); -+ urlPrefix = urlPrefix.replaceAll("%2f", "/"); -+ urlPrefix = urlPrefix.replaceAll("_2F_", "/"); -+ if (urlPrefix.indexOf("/") != 0) { -+ urlPrefix = "/" + urlPrefix; -+ } -+ } else { -+ urlPrefix = ""; -+ } -+ System.out.println("urlPrefix: '" + urlPrefix + "'"); -+ -+ ftpDropDown = readParameter("ftpDropDown", false); -+ if (ftpDropDown != null) { -+ ftpDropDown = ftpDropDown.replaceAll("%2F", "/"); -+ ftpDropDown = ftpDropDown.replaceAll("%2f", "/"); -+ ftpDropDown = ftpDropDown.replaceAll("_2F_", "/"); -+ ftpDropDown = ftpDropDown.replaceAll("%20", " "); -+ System.out.println("ftpDropDown: '" + ftpDropDown + "'"); -+ } -+ -+ -+ oneTimeKey = readParameter("oneTimeKey", false); -+ if (oneTimeKey != null) { -+ System.out.println("oneTimeKey is set."); -+ } -+ -+ serverCert = readParameter("serverCert", false); -+ if (serverCert != null) { -+ System.out.println("serverCert is set."); -+ } -+ -+ forceProxy = false; -+ proxyHost = null; -+ proxyPort = null; -+ str = readParameter("forceProxy", false); -+ if (str != null) { -+ if (str.equalsIgnoreCase("Yes")) { -+ forceProxy = true; -+ } else if (str.equalsIgnoreCase("No")) { -+ forceProxy = false; -+ } else { -+ forceProxy = true; -+ String[] pieces = str.split(" "); -+ proxyHost = new String(pieces[0]); -+ if (pieces.length >= 2) { -+ proxyPort = new String(pieces[1]); -+ } else { -+ proxyPort = new String("8080"); -+ } -+ } -+ } -+ str = readParameter("proxyHost", false); -+ if (str != null) { -+ proxyHost = new String(str); -+ } -+ str = readParameter("proxyPort", false); -+ if (str != null) { -+ proxyPort = new String(str); -+ } -+ if (proxyHost != null && proxyPort == null) { -+ proxyPort = new String("8080"); -+ } -+ -+ ignoreProxy = false; -+ str = readParameter("ignoreProxy", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ ignoreProxy = true; -+ } -+ -+ trustAllVncCerts = false; -+ str = readParameter("trustAllVncCerts", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ trustAllVncCerts = true; -+ } -+ trustUrlVncCert = false; -+ str = readParameter("trustUrlVncCert", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ trustUrlVncCert = true; -+ } -+ debugCerts = false; -+ str = readParameter("debugCerts", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ debugCerts = true; -+ } -+ debugKeyboard = false; -+ str = readParameter("debugKeyboard", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ debugKeyboard = true; -+ } -+ mapF5_to_atsign = false; -+ str = readParameter("mapF5_to_atsign", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ mapF5_to_atsign = true; -+ } -+ forbid_Ctrl_Alt = false; -+ str = readParameter("forbid_Ctrl_Alt", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ forbid_Ctrl_Alt = true; -+ } -+ ignoreMSLogonCheck = false; -+ str = readParameter("ignoreMSLogonCheck", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ ignoreMSLogonCheck = true; -+ } -+ ftpOnly = false; -+ str = readParameter("ftpOnly", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ ftpOnly = true; -+ } -+ graftFtp = false; -+ str = readParameter("graftFtp", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ graftFtp = true; -+ } -+ dsmActive = false; -+ str = readParameter("dsmActive", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ dsmActive = true; -+ } -+ delayAuthPanel = false; -+ str = readParameter("delayAuthPanel", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ delayAuthPanel = true; -+ } -+// end runge/x11vnc - } - - public String readParameter(String name, boolean required) { |