diff options
author | runge <runge@karlrunge.com> | 2010-03-21 00:05:51 -0400 |
---|---|---|
committer | runge <runge@karlrunge.com> | 2010-03-21 00:05:51 -0400 |
commit | 97540de56ca8a975ed31d86879d0e5c4cf169173 (patch) | |
tree | 6c8c0a28c3559a15c6a76bed92dc2a4c62630914 /classes/ssl | |
parent | edb79ae2b1d39bc12d489bcded74ab966e019994 (diff) | |
download | libtdevnc-97540de56ca8a975ed31d86879d0e5c4cf169173.tar.gz libtdevnc-97540de56ca8a975ed31d86879d0e5c4cf169173.zip |
classes/ssl: Many improvements to Java SSL applet, onetimekey
serverCert param, debugging printout, user dialogs, catch
socket exceptions, autodetect x11vnc for GET=1.
x11vnc: misc/scripts: desktop.cgi, inet6to4, panner.pl.
X11VNC_HTTPS_DOWNLOAD_WAIT_TIME, -unixpw %xxx documented, and
can run user cmd in UNIXPW_CMD. FD_XDMCP_IF for create script,
autodetect dm on udp6 only. Queries: pointer_x, pointer_y,
pointer_same, pointer_root. Switch on -xkd if keysyms per key >
4 in all cases. daemon mode improvements for connect_switch,
inet6to4, ultravnc_repeater.pl. Dynamic change of -clip do
not create new fb if WxH is unchanged.
Diffstat (limited to 'classes/ssl')
-rw-r--r-- | classes/ssl/README | 67 | ||||
-rw-r--r-- | classes/ssl/SignedUltraViewerSSL.jar | bin | 108090 -> 112002 bytes | |||
-rw-r--r-- | classes/ssl/SignedVncViewer.jar | bin | 84103 -> 88016 bytes | |||
-rw-r--r-- | classes/ssl/UltraViewerSSL.jar | bin | 105068 -> 108926 bytes | |||
-rw-r--r-- | classes/ssl/VncViewer.jar | bin | 81177 -> 85036 bytes | |||
-rwxr-xr-x | classes/ssl/onetimekey | 20 | ||||
-rw-r--r-- | classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch | 620 | ||||
-rw-r--r-- | classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch | 638 |
8 files changed, 1058 insertions, 287 deletions
diff --git a/classes/ssl/README b/classes/ssl/README index 0767ce9..b244cf1 100644 --- a/classes/ssl/README +++ b/classes/ssl/README @@ -137,6 +137,15 @@ Both TightVNC and UltraVNC Java viewers: 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 @@ -173,16 +182,47 @@ Both TightVNC and UltraVNC Java viewers: oneTimeKey string, default: none - set a special hex "key" to correspond to an SSL X.509 cert. - See the 'onetimekey' helper script. Can also be PROMPT to - prompt the user to paste the hex key string in. + 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 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. + 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 @@ -238,15 +278,8 @@ TightVNC Java viewer only: UltraVNC Java viewer only: - PASSWORD - string, default: none - VNC session password in plain text. + None. - 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 ftpDropDown diff --git a/classes/ssl/SignedUltraViewerSSL.jar b/classes/ssl/SignedUltraViewerSSL.jar Binary files differindex 5a562ff..e32079f 100644 --- a/classes/ssl/SignedUltraViewerSSL.jar +++ b/classes/ssl/SignedUltraViewerSSL.jar diff --git a/classes/ssl/SignedVncViewer.jar b/classes/ssl/SignedVncViewer.jar Binary files differindex a795e57..8e54308 100644 --- a/classes/ssl/SignedVncViewer.jar +++ b/classes/ssl/SignedVncViewer.jar diff --git a/classes/ssl/UltraViewerSSL.jar b/classes/ssl/UltraViewerSSL.jar Binary files differindex 15f6867..c037905 100644 --- a/classes/ssl/UltraViewerSSL.jar +++ b/classes/ssl/UltraViewerSSL.jar diff --git a/classes/ssl/VncViewer.jar b/classes/ssl/VncViewer.jar Binary files differindex a93d323..862bb20 100644 --- a/classes/ssl/VncViewer.jar +++ b/classes/ssl/VncViewer.jar diff --git a/classes/ssl/onetimekey b/classes/ssl/onetimekey index 5c0c26d..bf57c8f 100755 --- a/classes/ssl/onetimekey +++ b/classes/ssl/onetimekey @@ -1,6 +1,7 @@ #!/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. @@ -14,6 +15,19 @@ # 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 @@ -43,5 +57,9 @@ rm -f "$der" n=`grep -n 'BEGIN CERTIFICATE' $in | awk -F: '{print $1}' | head -1` str2=`tail +$n $in | $pbinhex` -echo "$str1,$str2" +if [ "X$certonly" = "X1" ]; then + echo "$str2" +else + echo "$str1,$str2" +fi rm -f $pbinhex diff --git a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch b/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch index f35a4e9..be5a22a 100644 --- a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch +++ b/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch @@ -73,8 +73,8 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0'); diff -x VncCanvas.java -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-02-22 20:03:11.000000000 -0500 -@@ -0,0 +1,1712 @@ ++++ vnc_javasrc/SSLSocketToMe.java 2010-03-19 12:52:08.000000000 -0400 +@@ -0,0 +1,2055 @@ +/* + * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer. + * @@ -118,7 +118,9 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + String host; + int port; + VncViewer viewer; ++ + boolean debug = true; ++ boolean debug_certs = false; + + /* sockets */ + SSLSocket socket = null; @@ -126,11 +128,11 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + + /* fallback for Proxy connection */ + boolean proxy_in_use = false; -+ boolean proxy_is_https = 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; @@ -142,21 +144,28 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + /* 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; + -+ boolean use_url_cert_for_auth = true; ++ /* client-side SSL auth key (oneTimeKey=...) */ ++ KeyManager[] mykey = null; ++ + boolean user_wants_to_see_cert = true; -+ boolean debug_certs = false; ++ String cert_fail = null; + -+ /* cert(s) we retrieve from VNC server */ ++ /* 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++) { @@ -189,11 +198,15 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + + dbg("SSL startup: " + host + " " + port); + -+ /* create trust managers used if initial handshake fails: */ ++ ++ /* create trust managers to be used if initial handshake fails: */ + + trustAllCerts = new TrustManager[] { + /* -+ * this one accepts everything. ++ * 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[] @@ -216,8 +229,9 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + + trustUrlCert = new TrustManager[] { + /* -+ * this one accepts only the retrieved server cert -+ * by SSLSocket by this applet. ++ * this one accepts only the retrieved server ++ * cert by SSLSocket by this applet and stored in ++ * trusturlCerts. + */ + new X509TrustManager() { + public java.security.cert.X509Certificate[] @@ -227,11 +241,12 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + public void checkClientTrusted( + java.security.cert.X509Certificate[] certs, + String authType) throws CertificateException { -+ throw new CertificateException("No Clients"); ++ 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."); @@ -259,6 +274,9 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + 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***********************************************"); @@ -277,10 +295,86 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + } + } + }; ++ ++ 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. ++ * 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[] @@ -290,11 +384,12 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + public void checkClientTrusted( + java.security.cert.X509Certificate[] certs, + String authType) throws CertificateException { -+ throw new CertificateException("No Clients"); ++ 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."); @@ -342,20 +437,20 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + }; + + /* -+ * They are used: ++ * The above TrustManagers are used: + * + * 1) to retrieve the server cert in case of failure to -+ * display it to the user. ++ * display it to the user in a dialog. + * 2) to subsequently connect to the server if user agrees. + */ + -+ KeyManager[] mykey = null; -+ ++ /* ++ * 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(","); + @@ -367,15 +462,18 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + KeyFactory kf = KeyFactory.getInstance("RSA"); + PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key ); + PrivateKey ff = kf.generatePrivate (keysp); -+ //dbg("ff " + ff); -+ String cert_str = new String(cert); ++ 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)); -+ //dbg("tmpcert" + tmpcert); ++ if (debug_certs) { ++ dbg("one time cert" + tmpcert); ++ } + certs[0] = tmpcert; + } else { + certs = (Certificate[]) c.toArray(); @@ -391,12 +489,54 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + 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(); ++ } ++ } + -+ /* trust loc certs: */ ++ /* the trust loc certs context: */ + try { + trustloc_ctx = SSLContext.getInstance("SSL"); -+ trustloc_ctx.init(mykey, null, new -+ java.security.SecureRandom()); ++ ++ /* ++ * 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."; @@ -404,7 +544,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + throw new Exception(msg); + } + -+ /* trust all certs: */ ++ /* the trust all certs context: */ + try { + trustall_ctx = SSLContext.getInstance("SSL"); + trustall_ctx.init(mykey, trustAllCerts, new @@ -416,7 +556,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + throw new Exception(msg); + } + -+ /* trust url certs: */ ++ /* the trust url certs context: */ + try { + trusturl_ctx = SSLContext.getInstance("SSL"); + trusturl_ctx.init(mykey, trustUrlCert, new @@ -428,99 +568,138 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + throw new Exception(msg); + } + -+ /* trust the one cert from server: */ ++ /* the trust srv certs context: */ + try { -+ trustone_ctx = SSLContext.getInstance("SSL"); -+ trustone_ctx.init(mykey, trustOneCert, new ++ trustsrv_ctx = SSLContext.getInstance("SSL"); ++ trustsrv_ctx.init(mykey, trustSrvCert, new + java.security.SecureRandom()); + + } catch (Exception e) { -+ String msg = "SSL trustone_ctx FAILED."; ++ String msg = "SSL trustsrv_ctx FAILED."; + dbg(msg); + throw new Exception(msg); + } -+ } -+ -+ boolean browser_cert_match() { -+ String msg = "Browser URL accept previously accepted cert"; + -+ if (user_wants_to_see_cert) { -+ return false; -+ } ++ /* the trust the one cert from server context: */ ++ try { ++ trustone_ctx = SSLContext.getInstance("SSL"); ++ trustone_ctx.init(mykey, trustOneCert, new ++ java.security.SecureRandom()); + -+ if (trustallCerts != null && trusturlCerts != null) { -+ if (trustallCerts.length == 1 && trusturlCerts.length == 1) { -+ if (trustallCerts[0].equals(trusturlCerts[0])) { -+ System.out.println(msg); -+ return true; -+ } -+ } ++ } catch (Exception e) { ++ String msg = "SSL trustone_ctx FAILED."; ++ dbg(msg); ++ throw new Exception(msg); + } -+ return false; + } + -+ public void check_for_proxy() { ++ /* ++ * 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() { + -+ boolean result = false; -+ + 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; // hmmm ++ 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(); ++ 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.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..."); ++ dbg("set trusturlCerts to null!"); + } else { + dbg("set trusturlCerts to non-null"); + } + + if (https.usingProxy()) { + proxy_in_use = true; -+ proxy_is_https = true; -+ dbg("HTTPS proxy in use. There may be connection problems."); ++ 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(); -+ result = true; ++ 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(); @@ -528,45 +707,64 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + http.setUseCaches(false); + http.setRequestMethod("GET"); + http.setRequestProperty("Pragma", "No-Cache"); -+ http.setRequestProperty("Proxy-Connection", -+ "Keep-Alive"); ++ http.setRequestProperty("Proxy-Connection", "Keep-Alive"); + http.setDoInput(true); + ++ dbg("trying http.connect()"); + http.connect(); + + if (http.usingProxy()) { + proxy_in_use = true; -+ proxy_is_https = false; -+ dbg("HTTP proxy in use. There may be connection problems."); ++ 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("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 -+ * also grab the VNC server cert. ++ * grab the VNC server cert at the same time: + */ -+ check_for_proxy(); ++ check_for_proxy_and_grab_vnc_server_cert(); ++ ++ boolean srv_cert = false; + -+ if (viewer.trustAllVncCerts) { ++ 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 (use_url_cert_for_auth && trusturlCerts != null) { ++ } 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)"); @@ -585,7 +783,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + } + + } catch (Exception esock) { -+ dbg("esock: " + esock.getMessage()); ++ dbg("socket error: " + esock.getMessage()); + if (proxy_in_use || viewer.CONNECT != null) { + proxy_failure = true; + if (proxy_in_use) { @@ -596,14 +794,17 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + try { + socket = proxy_socket(factory); + } catch (Exception e) { -+ dbg("err proxy_socket: " + e.getMessage()); ++ dbg("proxy_socket error: " + e.getMessage()); + } ++ } else { ++ /* n.b. socket is left in error state to cause ex. below. */ + } + } + + try { + socket.startHandshake(); -+ dbg("Server Connection Verified on 1st try."); ++ ++ dbg("The Server Connection Verified OK on 1st try."); + + java.security.cert.Certificate[] currentTrustedCerts; + BrowserCertsDialog bcd; @@ -612,9 +813,13 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + currentTrustedCerts = sess.getPeerCertificates(); + + if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-1"); ++ dbg("viewer.trustAllVncCerts-1 keeping socket."); + } else if (currentTrustedCerts == null || currentTrustedCerts.length < 1) { -+ socket.close(); ++ try { ++ socket.close(); ++ } catch (Exception e) { ++ dbg("socket is grumpy."); ++ } + socket = null; + throw new SSLHandshakeException("no current certs"); + } @@ -628,20 +833,28 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + } + + if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-2"); ++ 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"); ++ 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 START"); ++ dbg("browser certs dialog begin."); + bcd.queryUser(); -+ dbg("browser certs dialog DONE"); ++ 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; @@ -650,18 +863,37 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + } + + } catch (SSLHandshakeException eh) { -+ dbg("Could not automatically verify Server."); ++ 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"; + -+ OutputStream os = socket.getOutputStream(); -+ os.write(getoutstr.getBytes()); -+ socket.close(); ++ 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. The connection ++ * 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(); @@ -671,9 +903,18 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + 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("TrustAll Server Connection Verified."); ++ ++ dbg("The TrustAll Server Cert-grab Connection (trivially) Verified OK."); + + /* grab the cert: */ + try { @@ -683,17 +924,24 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + throw new Exception("Could not get " + + "Peer Certificate"); + } ++ if (debug_certs) { ++ dbg("trustallCerts: " + trustallCerts); ++ } + + if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-3"); ++ 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. + */ -+ os = socket.getOutputStream(); -+ os.write(getoutstr.getBytes()); -+ socket.close(); ++ 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: */ @@ -701,7 +949,27 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + TrustDialog td= new TrustDialog(host, port, + trustallCerts); + -+ if (! td.queryUser()) { ++ 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); @@ -709,24 +977,26 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + } + + } catch (Exception ehand2) { -+ dbg("** Could not TrustAll Verify Server."); ++ 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 (that the user -+ * likely blindly agreed to). ++ * retrieved during connection 2 (sadly, that ++ * the user likely blindly agreed to...) + */ + + factory = trustone_ctx.getSocketFactory(); @@ -738,15 +1008,18 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + + try { + socket.startHandshake(); -+ dbg("TrustAll Server Connection Verified #3."); ++ dbg("TrustAll/TrustOne Server Connection Verified #3."); + + } catch (Exception ehand3) { -+ dbg("** Could not TrustAll Verify Server #3."); ++ 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; @@ -754,9 +1027,11 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + str += " HTTP/1.0\r\n"; + str += "Pragma: No-Cache\r\n"; + str += "\r\n"; ++ + System.out.println("sending GET: " + str); + OutputStream os = socket.getOutputStream(); + String type = "os"; ++ + if (type == "os") { + os.write(str.getBytes()); + os.flush(); @@ -787,9 +1062,56 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + } + + 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); @@ -807,6 +1129,8 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + 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; @@ -814,14 +1138,15 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + 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:"); ++ dbg("proxy_in_use psocket: " + k); + + if (proxySock != null) { + try { + proxySock.close(); + } catch (Exception e) { -+ ; ++ dbg("proxy socket is grumpy."); + } + } + @@ -834,7 +1159,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + String req1 = "CONNECT " + hp + " HTTP/1.1\r\n" + + "Host: " + hp + "\r\n"; + -+ dbg("requesting: " + req1); ++ dbg("requesting via proxy: " + req1); + + if (proxy_auth) { + if (proxy_auth_string == null) { @@ -843,10 +1168,13 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + 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"; @@ -869,9 +1197,10 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + } + } + } catch(Exception e) { -+ dbg("sock prob: " + e.getMessage()); ++ 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()); @@ -891,6 +1220,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + } + } + if (!proxy_auth || proxy_auth_basic_realm.equals("")) { ++ /* we only try once for the non-password case: */ + break; + } + } @@ -908,6 +1238,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + 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) { @@ -924,6 +1255,8 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + 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); @@ -1046,7 +1379,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + } + } + } catch(Exception e) { -+ dbg("sock prob2: " + e.getMessage()); ++ dbg("proxy socket problem-2: " + e.getMessage()); + } + + while (true) { @@ -1130,7 +1463,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + msg = "VNC Server " + host + ":" + port + " Not Verified"; + } + -+ public boolean queryUser() { ++ public boolean queryUser(String reason) { + + /* create and display the dialog for unverified cert. */ + @@ -1143,6 +1476,9 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + 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" @@ -1153,28 +1489,38 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL ++ "\n" ++ "as a trusted VNC server.\n" ++ "\n" -++ "This may be due to:\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 using a Self-Signed Certificate.\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" -++ " - The VNC server using a Certificate Authority not recognized by your\n" -++ " Browser or Java Plugin runtime.\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 use of an Apache SSL portal employing CONNECT proxying and the\n" -++ " Apache web server has a certificate different from the VNC server's. \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 you wish\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\n" -++ "Certificate Authority certificate) you can configure your Web Browser or\n" -++ "Java Plugin to automatically authenticate this Server.\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" -++ "If you do so, then you will only have to click \"Yes\" when this VNC\n" -++ "Viewer applet asks you whether to trust your Browser/Java Plugin's\n" -++ "acceptance of the certificate. (except for the Apache portal case above.)\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: */ @@ -1210,7 +1556,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + label.setFont(new Font("Helvetica", Font.BOLD, 16)); + + /* textarea in the middle */ -+ textarea = new TextArea(text, 36, 64, ++ textarea = new TextArea(text, 38, 64, + TextArea.SCROLLBARS_VERTICAL_ONLY); + textarea.setEditable(false); + @@ -1562,22 +1908,19 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL +m += "\n"; +m += "on its own.\n"; +m += "\n"; -+m += "However, it has noticed that your Web Browser or Java VM Plugin\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"; + -+// String m = "\nShould this VNC Viewer applet use your Browser/JVM certs to\n"; -+// m += "authenticate the VNC Server:\n"; -+// m += "\n " + hostport + "\n\n " + vncServer + "\n\n"; -+// m += "(NOTE: this *includes* any certs you have Just Now accepted in a\n"; -+// m += "dialog box with your Web Browser or Java Applet Plugin)\n\n"; -+ -+ TextArea textarea = new TextArea(m, 20, 64, ++ TextArea textarea = new TextArea(m, 22, 64, + TextArea.SCROLLBARS_VERTICAL_ONLY); + textarea.setEditable(false); + yes = new Button("Yes"); @@ -1789,8 +2132,16 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL +} diff -x VncCanvas.java -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-02-22 19:25:19.000000000 -0500 -@@ -80,7 +80,7 @@ ++++ vnc_javasrc/VncViewer.java 2010-03-20 19:49:14.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; @@ -1799,7 +2150,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncView boolean showControls; boolean offerRelogin; boolean showOfflineDesktop; -@@ -88,6 +88,20 @@ +@@ -88,6 +89,21 @@ int deferCursorUpdates; int deferUpdateRequests; @@ -1809,6 +2160,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncView + String urlPrefix; + String httpsPort; + String oneTimeKey; ++ String serverCert; + String proxyHost; + String proxyPort; + boolean forceProxy; @@ -1820,9 +2172,12 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncView // Reference to this applet for inter-applet communication. public static java.applet.Applet refApplet; -@@ -591,8 +605,25 @@ +@@ -590,9 +606,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); @@ -1848,7 +2203,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncView if (inAnApplet) { str = readParameter("Open New Window", false); -@@ -626,6 +657,101 @@ +@@ -626,6 +661,106 @@ // SocketFactory. socketFactory = readParameter("SocketFactory", false); @@ -1891,7 +2246,12 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncView + + oneTimeKey = readParameter("oneTimeKey", false); + if (oneTimeKey != null) { -+ System.out.println("oneTimeKey: is set"); ++ System.out.println("oneTimeKey is set."); ++ } ++ ++ serverCert = readParameter("serverCert", false); ++ if (serverCert != null) { ++ System.out.println("serverCert is set."); + } + + forceProxy = false; diff --git a/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch b/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch index 369a221..8bb6f85 100644 --- a/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch +++ b/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch @@ -2644,8 +2644,8 @@ diff -Naur JavaViewer.orig/RfbProto.java JavaViewer/RfbProto.java // } 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-02-22 20:03:11.000000000 -0500 -@@ -0,0 +1,1712 @@ ++++ JavaViewer/SSLSocketToMe.java 2010-03-19 12:52:08.000000000 -0400 +@@ -0,0 +1,2055 @@ +/* + * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer. + * @@ -2689,7 +2689,9 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + String host; + int port; + VncViewer viewer; ++ + boolean debug = true; ++ boolean debug_certs = false; + + /* sockets */ + SSLSocket socket = null; @@ -2697,11 +2699,11 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + + /* fallback for Proxy connection */ + boolean proxy_in_use = false; -+ boolean proxy_is_https = 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; @@ -2713,21 +2715,28 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + /* 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; + -+ boolean use_url_cert_for_auth = true; ++ /* client-side SSL auth key (oneTimeKey=...) */ ++ KeyManager[] mykey = null; ++ + boolean user_wants_to_see_cert = true; -+ boolean debug_certs = false; ++ String cert_fail = null; + -+ /* cert(s) we retrieve from VNC server */ ++ /* 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++) { @@ -2760,11 +2769,15 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + + dbg("SSL startup: " + host + " " + port); + -+ /* create trust managers used if initial handshake fails: */ ++ ++ /* create trust managers to be used if initial handshake fails: */ + + trustAllCerts = new TrustManager[] { + /* -+ * this one accepts everything. ++ * 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[] @@ -2787,8 +2800,9 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + + trustUrlCert = new TrustManager[] { + /* -+ * this one accepts only the retrieved server cert -+ * by SSLSocket by this applet. ++ * this one accepts only the retrieved server ++ * cert by SSLSocket by this applet and stored in ++ * trusturlCerts. + */ + new X509TrustManager() { + public java.security.cert.X509Certificate[] @@ -2798,11 +2812,12 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + public void checkClientTrusted( + java.security.cert.X509Certificate[] certs, + String authType) throws CertificateException { -+ throw new CertificateException("No Clients"); ++ 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."); @@ -2830,6 +2845,9 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + 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***********************************************"); @@ -2848,10 +2866,86 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + } + } + }; ++ ++ 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. ++ * 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[] @@ -2861,11 +2955,12 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + public void checkClientTrusted( + java.security.cert.X509Certificate[] certs, + String authType) throws CertificateException { -+ throw new CertificateException("No Clients"); ++ 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."); @@ -2913,20 +3008,20 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + }; + + /* -+ * They are used: ++ * The above TrustManagers are used: + * + * 1) to retrieve the server cert in case of failure to -+ * display it to the user. ++ * display it to the user in a dialog. + * 2) to subsequently connect to the server if user agrees. + */ + -+ KeyManager[] mykey = null; -+ ++ /* ++ * 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(","); + @@ -2938,15 +3033,18 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + KeyFactory kf = KeyFactory.getInstance("RSA"); + PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key ); + PrivateKey ff = kf.generatePrivate (keysp); -+ //dbg("ff " + ff); -+ String cert_str = new String(cert); ++ 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)); -+ //dbg("tmpcert" + tmpcert); ++ if (debug_certs) { ++ dbg("one time cert" + tmpcert); ++ } + certs[0] = tmpcert; + } else { + certs = (Certificate[]) c.toArray(); @@ -2962,12 +3060,54 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + 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(); ++ } ++ } + -+ /* trust loc certs: */ ++ /* the trust loc certs context: */ + try { + trustloc_ctx = SSLContext.getInstance("SSL"); -+ trustloc_ctx.init(mykey, null, new -+ java.security.SecureRandom()); ++ ++ /* ++ * 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."; @@ -2975,7 +3115,7 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + throw new Exception(msg); + } + -+ /* trust all certs: */ ++ /* the trust all certs context: */ + try { + trustall_ctx = SSLContext.getInstance("SSL"); + trustall_ctx.init(mykey, trustAllCerts, new @@ -2987,7 +3127,7 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + throw new Exception(msg); + } + -+ /* trust url certs: */ ++ /* the trust url certs context: */ + try { + trusturl_ctx = SSLContext.getInstance("SSL"); + trusturl_ctx.init(mykey, trustUrlCert, new @@ -2999,99 +3139,138 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + throw new Exception(msg); + } + -+ /* trust the one cert from server: */ ++ /* the trust srv certs context: */ + try { -+ trustone_ctx = SSLContext.getInstance("SSL"); -+ trustone_ctx.init(mykey, trustOneCert, new ++ trustsrv_ctx = SSLContext.getInstance("SSL"); ++ trustsrv_ctx.init(mykey, trustSrvCert, new + java.security.SecureRandom()); + + } catch (Exception e) { -+ String msg = "SSL trustone_ctx FAILED."; ++ String msg = "SSL trustsrv_ctx FAILED."; + dbg(msg); + throw new Exception(msg); + } -+ } + -+ boolean browser_cert_match() { -+ String msg = "Browser URL accept previously accepted cert"; -+ -+ if (user_wants_to_see_cert) { -+ return false; -+ } ++ /* the trust the one cert from server context: */ ++ try { ++ trustone_ctx = SSLContext.getInstance("SSL"); ++ trustone_ctx.init(mykey, trustOneCert, new ++ java.security.SecureRandom()); + -+ if (trustallCerts != null && trusturlCerts != null) { -+ if (trustallCerts.length == 1 && trusturlCerts.length == 1) { -+ if (trustallCerts[0].equals(trusturlCerts[0])) { -+ System.out.println(msg); -+ return true; -+ } -+ } ++ } catch (Exception e) { ++ String msg = "SSL trustone_ctx FAILED."; ++ dbg(msg); ++ throw new Exception(msg); + } -+ return false; + } + -+ public void check_for_proxy() { ++ /* ++ * 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() { + -+ boolean result = false; -+ + 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; // hmmm ++ 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(); ++ 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.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..."); ++ dbg("set trusturlCerts to null!"); + } else { + dbg("set trusturlCerts to non-null"); + } + + if (https.usingProxy()) { + proxy_in_use = true; -+ proxy_is_https = true; -+ dbg("HTTPS proxy in use. There may be connection problems."); ++ 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(); -+ result = true; ++ 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(); @@ -3099,45 +3278,64 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + http.setUseCaches(false); + http.setRequestMethod("GET"); + http.setRequestProperty("Pragma", "No-Cache"); -+ http.setRequestProperty("Proxy-Connection", -+ "Keep-Alive"); ++ http.setRequestProperty("Proxy-Connection", "Keep-Alive"); + http.setDoInput(true); + ++ dbg("trying http.connect()"); + http.connect(); + + if (http.usingProxy()) { + proxy_in_use = true; -+ proxy_is_https = false; -+ dbg("HTTP proxy in use. There may be connection problems."); ++ 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("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 -+ * also grab the VNC server cert. ++ * grab the VNC server cert at the same time: + */ -+ check_for_proxy(); ++ check_for_proxy_and_grab_vnc_server_cert(); ++ ++ boolean srv_cert = false; + -+ if (viewer.trustAllVncCerts) { ++ 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 (use_url_cert_for_auth && trusturlCerts != null) { ++ } 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)"); @@ -3156,7 +3354,7 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + } + + } catch (Exception esock) { -+ dbg("esock: " + esock.getMessage()); ++ dbg("socket error: " + esock.getMessage()); + if (proxy_in_use || viewer.CONNECT != null) { + proxy_failure = true; + if (proxy_in_use) { @@ -3167,14 +3365,17 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + try { + socket = proxy_socket(factory); + } catch (Exception e) { -+ dbg("err proxy_socket: " + e.getMessage()); ++ dbg("proxy_socket error: " + e.getMessage()); + } ++ } else { ++ /* n.b. socket is left in error state to cause ex. below. */ + } + } + + try { + socket.startHandshake(); -+ dbg("Server Connection Verified on 1st try."); ++ ++ dbg("The Server Connection Verified OK on 1st try."); + + java.security.cert.Certificate[] currentTrustedCerts; + BrowserCertsDialog bcd; @@ -3183,9 +3384,13 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + currentTrustedCerts = sess.getPeerCertificates(); + + if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-1"); ++ dbg("viewer.trustAllVncCerts-1 keeping socket."); + } else if (currentTrustedCerts == null || currentTrustedCerts.length < 1) { -+ socket.close(); ++ try { ++ socket.close(); ++ } catch (Exception e) { ++ dbg("socket is grumpy."); ++ } + socket = null; + throw new SSLHandshakeException("no current certs"); + } @@ -3199,20 +3404,28 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + } + + if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-2"); ++ 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"); ++ 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 START"); ++ dbg("browser certs dialog begin."); + bcd.queryUser(); -+ dbg("browser certs dialog DONE"); ++ 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; @@ -3221,18 +3434,37 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + } + + } catch (SSLHandshakeException eh) { -+ dbg("Could not automatically verify Server."); ++ 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"; + -+ OutputStream os = socket.getOutputStream(); -+ os.write(getoutstr.getBytes()); -+ socket.close(); ++ 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. The connection ++ * 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(); @@ -3242,9 +3474,18 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + 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("TrustAll Server Connection Verified."); ++ ++ dbg("The TrustAll Server Cert-grab Connection (trivially) Verified OK."); + + /* grab the cert: */ + try { @@ -3254,17 +3495,24 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + throw new Exception("Could not get " + + "Peer Certificate"); + } ++ if (debug_certs) { ++ dbg("trustallCerts: " + trustallCerts); ++ } + + if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-3"); ++ 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. + */ -+ os = socket.getOutputStream(); -+ os.write(getoutstr.getBytes()); -+ socket.close(); ++ 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: */ @@ -3272,7 +3520,27 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + TrustDialog td= new TrustDialog(host, port, + trustallCerts); + -+ if (! td.queryUser()) { ++ 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); @@ -3280,24 +3548,26 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + } + + } catch (Exception ehand2) { -+ dbg("** Could not TrustAll Verify Server."); ++ 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 (that the user -+ * likely blindly agreed to). ++ * retrieved during connection 2 (sadly, that ++ * the user likely blindly agreed to...) + */ + + factory = trustone_ctx.getSocketFactory(); @@ -3309,15 +3579,18 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + + try { + socket.startHandshake(); -+ dbg("TrustAll Server Connection Verified #3."); ++ dbg("TrustAll/TrustOne Server Connection Verified #3."); + + } catch (Exception ehand3) { -+ dbg("** Could not TrustAll Verify Server #3."); ++ 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; @@ -3325,9 +3598,11 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + str += " HTTP/1.0\r\n"; + str += "Pragma: No-Cache\r\n"; + str += "\r\n"; ++ + System.out.println("sending GET: " + str); + OutputStream os = socket.getOutputStream(); + String type = "os"; ++ + if (type == "os") { + os.write(str.getBytes()); + os.flush(); @@ -3358,9 +3633,56 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + } + + 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); @@ -3378,6 +3700,8 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + 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; @@ -3385,14 +3709,15 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + 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:"); ++ dbg("proxy_in_use psocket: " + k); + + if (proxySock != null) { + try { + proxySock.close(); + } catch (Exception e) { -+ ; ++ dbg("proxy socket is grumpy."); + } + } + @@ -3405,7 +3730,7 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + String req1 = "CONNECT " + hp + " HTTP/1.1\r\n" + + "Host: " + hp + "\r\n"; + -+ dbg("requesting: " + req1); ++ dbg("requesting via proxy: " + req1); + + if (proxy_auth) { + if (proxy_auth_string == null) { @@ -3414,10 +3739,13 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + 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"; @@ -3440,9 +3768,10 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + } + } + } catch(Exception e) { -+ dbg("sock prob: " + e.getMessage()); ++ 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()); @@ -3462,6 +3791,7 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + } + } + if (!proxy_auth || proxy_auth_basic_realm.equals("")) { ++ /* we only try once for the non-password case: */ + break; + } + } @@ -3479,6 +3809,7 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + 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) { @@ -3495,6 +3826,8 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + 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); @@ -3617,7 +3950,7 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + } + } + } catch(Exception e) { -+ dbg("sock prob2: " + e.getMessage()); ++ dbg("proxy socket problem-2: " + e.getMessage()); + } + + while (true) { @@ -3701,7 +4034,7 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + msg = "VNC Server " + host + ":" + port + " Not Verified"; + } + -+ public boolean queryUser() { ++ public boolean queryUser(String reason) { + + /* create and display the dialog for unverified cert. */ + @@ -3714,6 +4047,9 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + 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" @@ -3724,28 +4060,38 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java ++ "\n" ++ "as a trusted VNC server.\n" ++ "\n" -++ "This may be due to:\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 using a Self-Signed Certificate.\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" -++ " - The VNC server using a Certificate Authority not recognized by your\n" -++ " Browser or Java Plugin runtime.\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 use of an Apache SSL portal employing CONNECT proxying and the\n" -++ " Apache web server has a certificate different from the VNC server's. \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 you wish\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\n" -++ "Certificate Authority certificate) you can configure your Web Browser or\n" -++ "Java Plugin to automatically authenticate this Server.\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\n" -++ "Viewer applet asks you whether to trust your Browser/Java Plugin's\n" -++ "acceptance of the certificate. (except for the Apache portal case above.)\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: */ @@ -3781,7 +4127,7 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + label.setFont(new Font("Helvetica", Font.BOLD, 16)); + + /* textarea in the middle */ -+ textarea = new TextArea(text, 36, 64, ++ textarea = new TextArea(text, 38, 64, + TextArea.SCROLLBARS_VERTICAL_ONLY); + textarea.setEditable(false); + @@ -4133,22 +4479,19 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java +m += "\n"; +m += "on its own.\n"; +m += "\n"; -+m += "However, it has noticed that your Web Browser or Java VM Plugin\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"; + -+// String m = "\nShould this VNC Viewer applet use your Browser/JVM certs to\n"; -+// m += "authenticate the VNC Server:\n"; -+// m += "\n " + hostport + "\n\n " + vncServer + "\n\n"; -+// m += "(NOTE: this *includes* any certs you have Just Now accepted in a\n"; -+// m += "dialog box with your Web Browser or Java Applet Plugin)\n\n"; -+ -+ TextArea textarea = new TextArea(m, 20, 64, ++ TextArea textarea = new TextArea(m, 22, 64, + TextArea.SCROLLBARS_VERTICAL_ONLY); + textarea.setEditable(false); + yes = new Button("Yes"); @@ -4483,8 +4826,16 @@ diff -Naur JavaViewer.orig/VncCanvas.java JavaViewer/VncCanvas.java 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-02-22 21:58:51.000000000 -0500 -@@ -80,11 +80,11 @@ ++++ JavaViewer/VncViewer.java 2010-03-20 19:50:16.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; @@ -4498,7 +4849,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java // Control session recording. Object recordingSync; -@@ -96,7 +96,7 @@ +@@ -96,7 +97,7 @@ // Variables read from parameter values. String host; @@ -4507,7 +4858,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java String passwordParam; String encPasswordParam; boolean showControls; -@@ -115,28 +115,71 @@ +@@ -115,28 +116,72 @@ int i; // mslogon support 2 end @@ -4518,6 +4869,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java +String urlPrefix; +String httpsPort; +String oneTimeKey; ++String serverCert; +String ftpDropDown; +String proxyHost; +String proxyPort; @@ -4585,7 +4937,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java // authenticator = new AuthPanel(false); // mslogon support : go to connectAndAuthenticate() if (RecordingFrame.checkSecurity()) rec = new RecordingFrame(this); -@@ -147,10 +190,11 @@ +@@ -147,10 +192,11 @@ cursorUpdatesDef = null; eightBitColorsDef = null; @@ -4599,7 +4951,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java rfbThread = new Thread(this); rfbThread.start(); } -@@ -186,6 +230,30 @@ +@@ -186,6 +232,30 @@ gbc.weightx = 1.0; gbc.weighty = 1.0; @@ -4630,7 +4982,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java // Add ScrollPanel to applet mode // Create a panel which itself is resizeable and can hold -@@ -286,6 +354,24 @@ +@@ -286,6 +356,24 @@ void connectAndAuthenticate() throws Exception { @@ -4655,7 +5007,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java // If "ENCPASSWORD" parameter is set, decrypt the password into // the passwordParam string. -@@ -336,7 +422,22 @@ +@@ -336,7 +424,22 @@ // @@ -4679,7 +5031,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java authenticator = new AuthPanel(mslogon); -@@ -390,6 +491,10 @@ +@@ -390,6 +493,10 @@ break; //mslogon support end @@ -4690,7 +5042,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java // Retry on authentication failure. authenticator.retry(); } -@@ -405,9 +510,11 @@ +@@ -405,9 +512,11 @@ void prologueDetectAuthProtocol() throws Exception { @@ -4704,7 +5056,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java System.out.println("RFB server supports protocol version " + rfb.serverMajor + "." + rfb.serverMinor); -@@ -431,16 +538,36 @@ +@@ -431,16 +540,36 @@ boolean tryAuthenticate(String us, String pw) throws Exception { @@ -4747,7 +5099,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java switch (authScheme) { -@@ -629,6 +756,10 @@ +@@ -629,6 +758,10 @@ void doProtocolInitialisation() throws IOException { @@ -4758,9 +5110,12 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java rfb.writeClientInit(); rfb.readServerInit(); -@@ -775,8 +906,25 @@ +@@ -774,9 +907,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); @@ -4786,7 +5141,7 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java if (inAnApplet) { str = readParameter("Open New Window", false); -@@ -804,6 +952,138 @@ +@@ -804,6 +956,143 @@ deferScreenUpdates = readIntParameter("Defer screen updates", 20); deferCursorUpdates = readIntParameter("Defer cursor updates", 10); deferUpdateRequests = readIntParameter("Defer update requests", 50); @@ -4840,7 +5195,12 @@ diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java + + oneTimeKey = readParameter("oneTimeKey", false); + if (oneTimeKey != null) { -+ System.out.println("oneTimeKey: is set"); ++ System.out.println("oneTimeKey is set."); ++ } ++ ++ serverCert = readParameter("serverCert", false); ++ if (serverCert != null) { ++ System.out.println("serverCert is set."); + } + + forceProxy = false; |