diff options
Diffstat (limited to 'classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch')
-rw-r--r-- | classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch | 2600 |
1 files changed, 0 insertions, 2600 deletions
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) { |