summaryrefslogtreecommitdiffstats
path: root/classes
diff options
context:
space:
mode:
authorrunge <runge@karlrunge.com>2010-03-21 00:05:51 -0400
committerrunge <runge@karlrunge.com>2010-03-21 00:05:51 -0400
commit97540de56ca8a975ed31d86879d0e5c4cf169173 (patch)
tree6c8c0a28c3559a15c6a76bed92dc2a4c62630914 /classes
parentedb79ae2b1d39bc12d489bcded74ab966e019994 (diff)
downloadlibtdevnc-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')
-rw-r--r--classes/ssl/README67
-rw-r--r--classes/ssl/SignedUltraViewerSSL.jarbin108090 -> 112002 bytes
-rw-r--r--classes/ssl/SignedVncViewer.jarbin84103 -> 88016 bytes
-rw-r--r--classes/ssl/UltraViewerSSL.jarbin105068 -> 108926 bytes
-rw-r--r--classes/ssl/VncViewer.jarbin81177 -> 85036 bytes
-rwxr-xr-xclasses/ssl/onetimekey20
-rw-r--r--classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch620
-rw-r--r--classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch638
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
index 5a562ff..e32079f 100644
--- a/classes/ssl/SignedUltraViewerSSL.jar
+++ b/classes/ssl/SignedUltraViewerSSL.jar
Binary files differ
diff --git a/classes/ssl/SignedVncViewer.jar b/classes/ssl/SignedVncViewer.jar
index a795e57..8e54308 100644
--- a/classes/ssl/SignedVncViewer.jar
+++ b/classes/ssl/SignedVncViewer.jar
Binary files differ
diff --git a/classes/ssl/UltraViewerSSL.jar b/classes/ssl/UltraViewerSSL.jar
index 15f6867..c037905 100644
--- a/classes/ssl/UltraViewerSSL.jar
+++ b/classes/ssl/UltraViewerSSL.jar
Binary files differ
diff --git a/classes/ssl/VncViewer.jar b/classes/ssl/VncViewer.jar
index a93d323..862bb20 100644
--- a/classes/ssl/VncViewer.jar
+++ b/classes/ssl/VncViewer.jar
Binary files differ
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;