summaryrefslogtreecommitdiffstats
path: root/classes
diff options
context:
space:
mode:
authorrunge <runge@karlrunge.com>2009-06-18 22:32:16 -0400
committerrunge <runge@karlrunge.com>2009-06-18 22:32:16 -0400
commit61383c508e9a12c879bd94c77885e0ec0d7c47f8 (patch)
treeb4bf1b16037eca9110aaec6d5f92a57a2c00a80f /classes
parentd11b2abd8cf4d9afb1257695f8be1125d5625a65 (diff)
downloadlibtdevnc-61383c508e9a12c879bd94c77885e0ec0d7c47f8.tar.gz
libtdevnc-61383c508e9a12c879bd94c77885e0ec0d7c47f8.zip
classes/ssl: java viewer now handles auth-basic proxy logins.
misc/enhanced_tightvnc_viewer: update ssvnc.
Diffstat (limited to 'classes')
-rw-r--r--classes/ssl/SignedUltraViewerSSL.jarbin103589 -> 107370 bytes
-rw-r--r--classes/ssl/SignedVncViewer.jarbin79617 -> 83396 bytes
-rw-r--r--classes/ssl/UltraViewerSSL.jarbin100714 -> 104365 bytes
-rw-r--r--classes/ssl/VncViewer.jarbin76830 -> 80481 bytes
-rwxr-xr-xclasses/ssl/ss_vncviewer45
-rw-r--r--classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch343
-rw-r--r--classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch343
7 files changed, 644 insertions, 87 deletions
diff --git a/classes/ssl/SignedUltraViewerSSL.jar b/classes/ssl/SignedUltraViewerSSL.jar
index d8297b3..2ca5b78 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 06a2179..1498b4b 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 041e757..b012433 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 4d35cb3..b647da6 100644
--- a/classes/ssl/VncViewer.jar
+++ b/classes/ssl/VncViewer.jar
Binary files differ
diff --git a/classes/ssl/ss_vncviewer b/classes/ssl/ss_vncviewer
index 2231108..ec004c7 100755
--- a/classes/ssl/ss_vncviewer
+++ b/classes/ssl/ss_vncviewer
@@ -46,8 +46,8 @@
# -showcert Only fetch the certificate using the 'openssl s_client'
# command (openssl(1) must in installed).
#
-# See http://www.karlrunge.com/x11vnc/#faq-ssl-ca for details on SSL
-# certificates with VNC.
+# See http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-ca for details on
+# SSL certificates with VNC.
#
# A few other args (not related to SSL and certs):
#
@@ -115,6 +115,15 @@
#
VNCIPCMD=${VNCVIEWERCMD:-vncip}
VNCVIEWERCMD=${VNCVIEWERCMD:-vncviewer}
+if [ "X$SSVNC_TURBOVNC" != "X" ]; then
+ if echo "$VNCVIEWERCMD" | grep '\.turbovnc' > /dev/null; then
+ :
+ else
+ if type "$VNCVIEWERCMD.turbovnc" > /dev/null 2>/dev/null; then
+ VNCVIEWERCMD="$VNCVIEWERCMD.turbovnc"
+ fi
+ fi
+fi
#
# Same for STUNNEL, e.g. set it to /path/to/stunnel or stunnel4, etc.
#
@@ -268,6 +277,12 @@ do
;;
"-onelisten") SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE
;;
+ "-sendclipboard") VNCVIEWER_SEND_CLIPBOARD=1; export VNCVIEWER_SEND_CLIPBOARD
+ ;;
+ "-sendalways") VNCVIEWER_SEND_ALWAYS=1; export VNCVIEWER_SEND_ALWAYS
+ ;;
+ "-recvtext") shift; VNCVIEWER_RECV_TEXT="$1"; export VNCVIEWER_RECV_TEXT
+ ;;
"-escape") shift; VNCVIEWER_ESCAPE="$1"; export VNCVIEWER_ESCAPE
;;
"-ssvnc_encodings") shift; VNCVIEWER_ENCODINGS="$1"; export VNCVIEWER_ENCODINGS
@@ -751,6 +766,19 @@ if (exists $ENV{SSVNC_PREDIGESTED_HANDSHAKE}) {
$handshake_file = $ENV{SSVNC_PREDIGESTED_HANDSHAKE};
}
+my $have_gettimeofday = 0;
+eval "use Time::HiRes";
+if ($@ eq "") {
+ $have_gettimeofday = 1;
+}
+sub gettime {
+ my $t = "0.0";
+ if ($have_gettimeofday) {
+ $t = Time::HiRes::gettimeofday();
+ }
+ return $t;
+}
+
sub append_handshake {
my $str = shift;
if ($handshake_file) {
@@ -1324,12 +1352,19 @@ sub vencrypt_dialog {
} elsif ($minor == 7) {
$viewer_rfb = "RFB 003.007\n";
}
- syswrite($sock, $viewer_rfb, 12);
- append_handshake("viewer=$viewer_rfb");
-
my $nsec;
+ my $t1 = gettime();
+ my $t0 = gettime();
+ syswrite($sock, $viewer_rfb, 12);
sysread($sock, $nsec, 1);
+
+ $t1 = gettime();
+ $t1 = sprintf("%.6f", $t1 - $t0);
+
+ append_handshake("viewer=$viewer_rfb");
+ append_handshake("latency=$t1\n");
+
vdie if $nsec eq "";
$nsec = unpack("C", $nsec);
diff --git a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch b/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch
index 88185b7..1844eec 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 2008-04-15 12:54:51.000000000 -0400
-@@ -0,0 +1,1456 @@
++++ vnc_javasrc/SSLSocketToMe.java 2009-06-18 09:47:22.000000000 -0400
+@@ -0,0 +1,1717 @@
+/*
+ * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer.
+ *
@@ -130,6 +130,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ public DataInputStream is = null;
+ public OutputStream os = null;
+
++ String proxy_auth_string = null;
+ String proxy_dialog_host = null;
+ int proxy_dialog_port = 0;
+
@@ -648,9 +649,9 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ user_wants_to_see_cert = false;
+ } else {
+ bcd = new BrowserCertsDialog(serv, host + ":" + port);
-+ dbg("bcd START");
++ dbg("browser certs dialog START");
+ bcd.queryUser();
-+ dbg("bcd DONE");
++ dbg("browser certs dialog DONE");
+ if (bcd.showCertDialog) {
+ String msg = "user wants to see cert";
+ dbg(msg);
@@ -658,14 +659,17 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ throw new SSLHandshakeException(msg);
+ } else {
+ user_wants_to_see_cert = false;
-+ dbg("bcd: user said yes, accept it");
++ dbg("browser certs dialog: user said yes, accept it");
+ }
+ }
+
+ } catch (SSLHandshakeException eh) {
+ dbg("Could not automatically verify Server.");
+ dbg("msg: " + eh.getMessage());
++ 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();
+ socket = null;
+
@@ -701,6 +705,8 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ * close socket now, we will reopen after
+ * dialog if user agrees to use the cert.
+ */
++ os = socket.getOutputStream();
++ os.write(getoutstr.getBytes());
+ socket.close();
+ socket = null;
+
@@ -722,6 +728,15 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ throw new IOException(ehand2.getMessage());
+ }
+
++ if (socket != null) {
++ try {
++ socket.close();
++ } catch (Exception e) {
++ ;
++ }
++ socket = null;
++ }
++
+ /*
+ * Now connect a 3rd time, using the cert
+ * retrieved during connection 2 (that the user
@@ -806,6 +821,95 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ return n;
+ }
+
++ private void proxy_helper(String proxyHost, int proxyPort) {
++
++ boolean proxy_auth = false;
++ String proxy_auth_basic_realm = "";
++ String hp = host + ":" + port;
++ dbg("proxy_helper: " + proxyHost + ":" + proxyPort + " hp: " + hp);
++
++ for (int k=0; k < 2; k++) {
++ dbg("proxy_in_use psocket:");
++
++ if (proxySock != null) {
++ try {
++ proxySock.close();
++ } catch (Exception e) {
++ ;
++ }
++ }
++
++ proxySock = psocket(proxyHost, proxyPort);
++ if (proxySock == null) {
++ dbg("1-a sadly, returning a null socket");
++ return;
++ }
++
++ String req1 = "CONNECT " + hp + " HTTP/1.1\r\n"
++ + "Host: " + hp + "\r\n";
++
++ dbg("requesting: " + req1);
++
++ if (proxy_auth) {
++ if (proxy_auth_string == null) {
++ ProxyPasswdDialog pp = new ProxyPasswdDialog(proxyHost, proxyPort, proxy_auth_basic_realm);
++ pp.queryUser();
++ proxy_auth_string = pp.getAuth();
++ }
++ //dbg("auth1: " + proxy_auth_string);
++ String auth2 = Base64Coder.encodeString(proxy_auth_string);
++ //dbg("auth2: " + auth2);
++ req1 += "Proxy-Authorization: Basic " + auth2 + "\r\n";
++ //dbg("req1: " + req1);
++ dbg("added Proxy-Authorization: Basic ... to request");
++ }
++ req1 += "\r\n";
++
++ try {
++ proxy_os.write(req1.getBytes());
++ String reply = readline(proxy_is);
++
++ dbg("proxy replied: " + reply.trim());
++
++ if (reply.indexOf("HTTP/1.") == 0 && reply.indexOf(" 407 ") > 0) {
++ proxy_auth = true;
++ proxySock.close();
++ } else if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) {
++ proxySock.close();
++ proxySock = psocket(proxyHost, proxyPort);
++ if (proxySock == null) {
++ dbg("2-a sadly, returning a null socket");
++ return;
++ }
++ }
++ } catch(Exception e) {
++ dbg("sock prob: " + e.getMessage());
++ }
++
++ while (true) {
++ String line = readline(proxy_is);
++ dbg("proxy line: " + line.trim());
++ if (proxy_auth) {
++ String uc = line.toLowerCase();
++ if (uc.indexOf("proxy-authenticate:") == 0) {
++ if (uc.indexOf(" basic ") >= 0) {
++ int idx = uc.indexOf(" realm");
++ if (idx >= 0) {
++ proxy_auth_basic_realm = uc.substring(idx+1);
++ }
++ }
++ }
++ }
++ if (line.equals("\r\n") || line.equals("\n")) {
++ break;
++ }
++ }
++ if (!proxy_auth || proxy_auth_basic_realm.equals("")) {
++ break;
++ }
++ }
++ }
++
+ public SSLSocket proxy_socket(SSLSocketFactory factory) {
+ Properties props = null;
+ String proxyHost = null;
@@ -912,44 +1016,10 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ dbg("User said host: " + pd.getHost() + " port: " + pd.getPort());
+ }
+
-+ dbg("proxy_in_use psocket:");
-+ proxySock = psocket(proxyHost, proxyPort);
++ proxy_helper(proxyHost, proxyPort);
+ if (proxySock == null) {
-+ dbg("1-a sadly, returning a null socket");
+ return null;
+ }
-+ String hp = host + ":" + port;
-+
-+ String req1 = "CONNECT " + hp + " HTTP/1.1\r\n"
-+ + "Host: " + hp + "\r\n\r\n";
-+
-+ dbg("requesting1: " + req1);
-+
-+ try {
-+ proxy_os.write(req1.getBytes());
-+ String reply = readline(proxy_is);
-+
-+ dbg("proxy replied1: " + reply.trim());
-+
-+ if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) {
-+ proxySock.close();
-+ proxySock = psocket(proxyHost, proxyPort);
-+ if (proxySock == null) {
-+ dbg("2-a sadly, returning a null socket");
-+ return null;
-+ }
-+ }
-+ } catch(Exception e) {
-+ dbg("sock prob1: " + e.getMessage());
-+ }
-+
-+ while (true) {
-+ String line = readline(proxy_is);
-+ dbg("proxy line1: " + line.trim());
-+ if (line.equals("\r\n") || line.equals("\n")) {
-+ break;
-+ }
-+ }
+ } else if (viewer.CONNECT != null) {
+ dbg("viewer.CONNECT psocket:");
+ proxySock = psocket(host, port);
@@ -991,7 +1061,6 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ break;
+ }
+ }
-+
+ }
+
+ Socket sslsock = null;
@@ -1351,6 +1420,77 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ }
+}
+
++class ProxyPasswdDialog implements ActionListener {
++ String guessedHost = null;
++ String guessedPort = null;
++ String guessedUser = null;
++ String guessedPasswd = null;
++ String realm = null;
++ /*
++ * this is the gui to show the user the cert and info and ask
++ * them if they want to continue using this cert.
++ */
++
++ Button ok;
++ Dialog dialog;
++ TextField entry1;
++ TextField entry2;
++ String reply1 = "";
++ String reply2 = "";
++
++ ProxyPasswdDialog (String h, int p, String realm) {
++ guessedHost = h;
++ try {
++ guessedPort = Integer.toString(p);
++ } catch (Exception e) {
++ guessedPort = "8080";
++ }
++ this.realm = realm;
++ }
++
++ public void queryUser() {
++
++ /* create and display the dialog for unverified cert. */
++
++ Frame frame = new Frame("Proxy Requires Username and Password");
++
++ dialog = new Dialog(frame, true);
++
++ //Label label = new Label("Please Enter your Web Proxy Username in the top Entry and Password in the bottom Entry", Label.CENTER);
++ TextArea label = new TextArea("Please Enter your Web Proxy\nUsername in the Top Entry and\nPassword in the Bottom Entry,\nand then press OK.", 4, 20, TextArea.SCROLLBARS_NONE);
++ entry1 = new TextField(30);
++ entry2 = new TextField(30);
++ entry2.setEchoChar('*');
++ ok = new Button("OK");
++ ok.addActionListener(this);
++
++ dialog.setLayout(new BorderLayout());
++ dialog.add("North", label);
++ dialog.add("Center", entry1);
++ dialog.add("South", entry2);
++ dialog.add("East", ok);
++ dialog.pack();
++ dialog.resize(dialog.preferredSize());
++
++ dialog.show(); /* block here til OK or Cancel pressed. */
++ return;
++ }
++
++ public String getAuth() {
++ return reply1 + ":" + reply2;
++ }
++
++ public synchronized void actionPerformed(ActionEvent evt) {
++ System.out.println(evt.getActionCommand());
++ if (evt.getSource() == ok) {
++ reply1 = entry1.getText();
++ reply2 = entry2.getText();
++ //dialog.dispose();
++ dialog.hide();
++ }
++ }
++}
++
+class ClientCertDialog implements ActionListener {
+
+ Button ok;
@@ -1531,6 +1671,127 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL
+ }
+ }
+}
++
++class Base64Coder {
++
++ // Mapping table from 6-bit nibbles to Base64 characters.
++ private static char[] map1 = new char[64];
++ static {
++ int i=0;
++ for (char c='A'; c<='Z'; c++) map1[i++] = c;
++ for (char c='a'; c<='z'; c++) map1[i++] = c;
++ for (char c='0'; c<='9'; c++) map1[i++] = c;
++ map1[i++] = '+'; map1[i++] = '/'; }
++
++ // Mapping table from Base64 characters to 6-bit nibbles.
++ private static byte[] map2 = new byte[128];
++ static {
++ for (int i=0; i<map2.length; i++) map2[i] = -1;
++ for (int i=0; i<64; i++) map2[map1[i]] = (byte)i; }
++
++ /**
++ * Encodes a string into Base64 format.
++ * No blanks or line breaks are inserted.
++ * @param s a String to be encoded.
++ * @return A String with the Base64 encoded data.
++ */
++ public static String encodeString (String s) {
++ return new String(encode(s.getBytes())); }
++
++ /**
++ * Encodes a byte array into Base64 format.
++ * No blanks or line breaks are inserted.
++ * @param in an array containing the data bytes to be encoded.
++ * @return A character array with the Base64 encoded data.
++ */
++ public static char[] encode (byte[] in) {
++ return encode(in,in.length); }
++
++ /**
++ * Encodes a byte array into Base64 format.
++ * No blanks or line breaks are inserted.
++ * @param in an array containing the data bytes to be encoded.
++ * @param iLen number of bytes to process in <code>in</code>.
++ * @return A character array with the Base64 encoded data.
++ */
++ public static char[] encode (byte[] in, int iLen) {
++ int oDataLen = (iLen*4+2)/3; // output length without padding
++ int oLen = ((iLen+2)/3)*4; // output length including padding
++ char[] out = new char[oLen];
++ int ip = 0;
++ int op = 0;
++ while (ip < iLen) {
++ int i0 = in[ip++] & 0xff;
++ int i1 = ip < iLen ? in[ip++] & 0xff : 0;
++ int i2 = ip < iLen ? in[ip++] & 0xff : 0;
++ int o0 = i0 >>> 2;
++ int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
++ int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
++ int o3 = i2 & 0x3F;
++ out[op++] = map1[o0];
++ out[op++] = map1[o1];
++ out[op] = op < oDataLen ? map1[o2] : '='; op++;
++ out[op] = op < oDataLen ? map1[o3] : '='; op++; }
++ return out; }
++
++ /**
++ * Decodes a string from Base64 format.
++ * @param s a Base64 String to be decoded.
++ * @return A String containing the decoded data.
++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data.
++ */
++ public static String decodeString (String s) {
++ return new String(decode(s)); }
++
++ /**
++ * Decodes a byte array from Base64 format.
++ * @param s a Base64 String to be decoded.
++ * @return An array containing the decoded data bytes.
++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data.
++ */
++ public static byte[] decode (String s) {
++ return decode(s.toCharArray()); }
++
++ /**
++ * Decodes a byte array from Base64 format.
++ * No blanks or line breaks are allowed within the Base64 encoded data.
++ * @param in a character array containing the Base64 encoded data.
++ * @return An array containing the decoded data bytes.
++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data.
++ */
++ public static byte[] decode (char[] in) {
++ int iLen = in.length;
++ if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4.");
++ while (iLen > 0 && in[iLen-1] == '=') iLen--;
++ int oLen = (iLen*3) / 4;
++ byte[] out = new byte[oLen];
++ int ip = 0;
++ int op = 0;
++ while (ip < iLen) {
++ int i0 = in[ip++];
++ int i1 = in[ip++];
++ int i2 = ip < iLen ? in[ip++] : 'A';
++ int i3 = ip < iLen ? in[ip++] : 'A';
++ if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
++ throw new IllegalArgumentException ("Illegal character in Base64 encoded data.");
++ int b0 = map2[i0];
++ int b1 = map2[i1];
++ int b2 = map2[i2];
++ int b3 = map2[i3];
++ if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)
++ throw new IllegalArgumentException ("Illegal character in Base64 encoded data.");
++ int o0 = ( b0 <<2) | (b1>>>4);
++ int o1 = ((b1 & 0xf)<<4) | (b2>>>2);
++ int o2 = ((b2 & 3)<<6) | b3;
++ out[op++] = (byte)o0;
++ if (op<oLen) out[op++] = (byte)o1;
++ if (op<oLen) out[op++] = (byte)o2; }
++ return out; }
++
++ // Dummy constructor.
++ private Base64Coder() {}
++
++}
diff -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 2007-09-03 23:22:13.000000000 -0400
diff --git a/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch b/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch
index f92d3c6..4db84d3 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 2008-04-15 12:54:51.000000000 -0400
-@@ -0,0 +1,1456 @@
++++ JavaViewer/SSLSocketToMe.java 2009-06-18 09:47:22.000000000 -0400
+@@ -0,0 +1,1717 @@
+/*
+ * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer.
+ *
@@ -2701,6 +2701,7 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java
+ public DataInputStream is = null;
+ public OutputStream os = null;
+
++ String proxy_auth_string = null;
+ String proxy_dialog_host = null;
+ int proxy_dialog_port = 0;
+
@@ -3219,9 +3220,9 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java
+ user_wants_to_see_cert = false;
+ } else {
+ bcd = new BrowserCertsDialog(serv, host + ":" + port);
-+ dbg("bcd START");
++ dbg("browser certs dialog START");
+ bcd.queryUser();
-+ dbg("bcd DONE");
++ dbg("browser certs dialog DONE");
+ if (bcd.showCertDialog) {
+ String msg = "user wants to see cert";
+ dbg(msg);
@@ -3229,14 +3230,17 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java
+ throw new SSLHandshakeException(msg);
+ } else {
+ user_wants_to_see_cert = false;
-+ dbg("bcd: user said yes, accept it");
++ dbg("browser certs dialog: user said yes, accept it");
+ }
+ }
+
+ } catch (SSLHandshakeException eh) {
+ dbg("Could not automatically verify Server.");
+ dbg("msg: " + eh.getMessage());
++ 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();
+ socket = null;
+
@@ -3272,6 +3276,8 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java
+ * close socket now, we will reopen after
+ * dialog if user agrees to use the cert.
+ */
++ os = socket.getOutputStream();
++ os.write(getoutstr.getBytes());
+ socket.close();
+ socket = null;
+
@@ -3293,6 +3299,15 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java
+ throw new IOException(ehand2.getMessage());
+ }
+
++ if (socket != null) {
++ try {
++ socket.close();
++ } catch (Exception e) {
++ ;
++ }
++ socket = null;
++ }
++
+ /*
+ * Now connect a 3rd time, using the cert
+ * retrieved during connection 2 (that the user
@@ -3377,6 +3392,95 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java
+ return n;
+ }
+
++ private void proxy_helper(String proxyHost, int proxyPort) {
++
++ boolean proxy_auth = false;
++ String proxy_auth_basic_realm = "";
++ String hp = host + ":" + port;
++ dbg("proxy_helper: " + proxyHost + ":" + proxyPort + " hp: " + hp);
++
++ for (int k=0; k < 2; k++) {
++ dbg("proxy_in_use psocket:");
++
++ if (proxySock != null) {
++ try {
++ proxySock.close();
++ } catch (Exception e) {
++ ;
++ }
++ }
++
++ proxySock = psocket(proxyHost, proxyPort);
++ if (proxySock == null) {
++ dbg("1-a sadly, returning a null socket");
++ return;
++ }
++
++ String req1 = "CONNECT " + hp + " HTTP/1.1\r\n"
++ + "Host: " + hp + "\r\n";
++
++ dbg("requesting: " + req1);
++
++ if (proxy_auth) {
++ if (proxy_auth_string == null) {
++ ProxyPasswdDialog pp = new ProxyPasswdDialog(proxyHost, proxyPort, proxy_auth_basic_realm);
++ pp.queryUser();
++ proxy_auth_string = pp.getAuth();
++ }
++ //dbg("auth1: " + proxy_auth_string);
++ String auth2 = Base64Coder.encodeString(proxy_auth_string);
++ //dbg("auth2: " + auth2);
++ req1 += "Proxy-Authorization: Basic " + auth2 + "\r\n";
++ //dbg("req1: " + req1);
++ dbg("added Proxy-Authorization: Basic ... to request");
++ }
++ req1 += "\r\n";
++
++ try {
++ proxy_os.write(req1.getBytes());
++ String reply = readline(proxy_is);
++
++ dbg("proxy replied: " + reply.trim());
++
++ if (reply.indexOf("HTTP/1.") == 0 && reply.indexOf(" 407 ") > 0) {
++ proxy_auth = true;
++ proxySock.close();
++ } else if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) {
++ proxySock.close();
++ proxySock = psocket(proxyHost, proxyPort);
++ if (proxySock == null) {
++ dbg("2-a sadly, returning a null socket");
++ return;
++ }
++ }
++ } catch(Exception e) {
++ dbg("sock prob: " + e.getMessage());
++ }
++
++ while (true) {
++ String line = readline(proxy_is);
++ dbg("proxy line: " + line.trim());
++ if (proxy_auth) {
++ String uc = line.toLowerCase();
++ if (uc.indexOf("proxy-authenticate:") == 0) {
++ if (uc.indexOf(" basic ") >= 0) {
++ int idx = uc.indexOf(" realm");
++ if (idx >= 0) {
++ proxy_auth_basic_realm = uc.substring(idx+1);
++ }
++ }
++ }
++ }
++ if (line.equals("\r\n") || line.equals("\n")) {
++ break;
++ }
++ }
++ if (!proxy_auth || proxy_auth_basic_realm.equals("")) {
++ break;
++ }
++ }
++ }
++
+ public SSLSocket proxy_socket(SSLSocketFactory factory) {
+ Properties props = null;
+ String proxyHost = null;
@@ -3483,44 +3587,10 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java
+ dbg("User said host: " + pd.getHost() + " port: " + pd.getPort());
+ }
+
-+ dbg("proxy_in_use psocket:");
-+ proxySock = psocket(proxyHost, proxyPort);
++ proxy_helper(proxyHost, proxyPort);
+ if (proxySock == null) {
-+ dbg("1-a sadly, returning a null socket");
+ return null;
+ }
-+ String hp = host + ":" + port;
-+
-+ String req1 = "CONNECT " + hp + " HTTP/1.1\r\n"
-+ + "Host: " + hp + "\r\n\r\n";
-+
-+ dbg("requesting1: " + req1);
-+
-+ try {
-+ proxy_os.write(req1.getBytes());
-+ String reply = readline(proxy_is);
-+
-+ dbg("proxy replied1: " + reply.trim());
-+
-+ if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) {
-+ proxySock.close();
-+ proxySock = psocket(proxyHost, proxyPort);
-+ if (proxySock == null) {
-+ dbg("2-a sadly, returning a null socket");
-+ return null;
-+ }
-+ }
-+ } catch(Exception e) {
-+ dbg("sock prob1: " + e.getMessage());
-+ }
-+
-+ while (true) {
-+ String line = readline(proxy_is);
-+ dbg("proxy line1: " + line.trim());
-+ if (line.equals("\r\n") || line.equals("\n")) {
-+ break;
-+ }
-+ }
+ } else if (viewer.CONNECT != null) {
+ dbg("viewer.CONNECT psocket:");
+ proxySock = psocket(host, port);
@@ -3562,7 +3632,6 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java
+ break;
+ }
+ }
-+
+ }
+
+ Socket sslsock = null;
@@ -3922,6 +3991,77 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java
+ }
+}
+
++class ProxyPasswdDialog implements ActionListener {
++ String guessedHost = null;
++ String guessedPort = null;
++ String guessedUser = null;
++ String guessedPasswd = null;
++ String realm = null;
++ /*
++ * this is the gui to show the user the cert and info and ask
++ * them if they want to continue using this cert.
++ */
++
++ Button ok;
++ Dialog dialog;
++ TextField entry1;
++ TextField entry2;
++ String reply1 = "";
++ String reply2 = "";
++
++ ProxyPasswdDialog (String h, int p, String realm) {
++ guessedHost = h;
++ try {
++ guessedPort = Integer.toString(p);
++ } catch (Exception e) {
++ guessedPort = "8080";
++ }
++ this.realm = realm;
++ }
++
++ public void queryUser() {
++
++ /* create and display the dialog for unverified cert. */
++
++ Frame frame = new Frame("Proxy Requires Username and Password");
++
++ dialog = new Dialog(frame, true);
++
++ //Label label = new Label("Please Enter your Web Proxy Username in the top Entry and Password in the bottom Entry", Label.CENTER);
++ TextArea label = new TextArea("Please Enter your Web Proxy\nUsername in the Top Entry and\nPassword in the Bottom Entry,\nand then press OK.", 4, 20, TextArea.SCROLLBARS_NONE);
++ entry1 = new TextField(30);
++ entry2 = new TextField(30);
++ entry2.setEchoChar('*');
++ ok = new Button("OK");
++ ok.addActionListener(this);
++
++ dialog.setLayout(new BorderLayout());
++ dialog.add("North", label);
++ dialog.add("Center", entry1);
++ dialog.add("South", entry2);
++ dialog.add("East", ok);
++ dialog.pack();
++ dialog.resize(dialog.preferredSize());
++
++ dialog.show(); /* block here til OK or Cancel pressed. */
++ return;
++ }
++
++ public String getAuth() {
++ return reply1 + ":" + reply2;
++ }
++
++ public synchronized void actionPerformed(ActionEvent evt) {
++ System.out.println(evt.getActionCommand());
++ if (evt.getSource() == ok) {
++ reply1 = entry1.getText();
++ reply2 = entry2.getText();
++ //dialog.dispose();
++ dialog.hide();
++ }
++ }
++}
++
+class ClientCertDialog implements ActionListener {
+
+ Button ok;
@@ -4102,6 +4242,127 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java
+ }
+ }
+}
++
++class Base64Coder {
++
++ // Mapping table from 6-bit nibbles to Base64 characters.
++ private static char[] map1 = new char[64];
++ static {
++ int i=0;
++ for (char c='A'; c<='Z'; c++) map1[i++] = c;
++ for (char c='a'; c<='z'; c++) map1[i++] = c;
++ for (char c='0'; c<='9'; c++) map1[i++] = c;
++ map1[i++] = '+'; map1[i++] = '/'; }
++
++ // Mapping table from Base64 characters to 6-bit nibbles.
++ private static byte[] map2 = new byte[128];
++ static {
++ for (int i=0; i<map2.length; i++) map2[i] = -1;
++ for (int i=0; i<64; i++) map2[map1[i]] = (byte)i; }
++
++ /**
++ * Encodes a string into Base64 format.
++ * No blanks or line breaks are inserted.
++ * @param s a String to be encoded.
++ * @return A String with the Base64 encoded data.
++ */
++ public static String encodeString (String s) {
++ return new String(encode(s.getBytes())); }
++
++ /**
++ * Encodes a byte array into Base64 format.
++ * No blanks or line breaks are inserted.
++ * @param in an array containing the data bytes to be encoded.
++ * @return A character array with the Base64 encoded data.
++ */
++ public static char[] encode (byte[] in) {
++ return encode(in,in.length); }
++
++ /**
++ * Encodes a byte array into Base64 format.
++ * No blanks or line breaks are inserted.
++ * @param in an array containing the data bytes to be encoded.
++ * @param iLen number of bytes to process in <code>in</code>.
++ * @return A character array with the Base64 encoded data.
++ */
++ public static char[] encode (byte[] in, int iLen) {
++ int oDataLen = (iLen*4+2)/3; // output length without padding
++ int oLen = ((iLen+2)/3)*4; // output length including padding
++ char[] out = new char[oLen];
++ int ip = 0;
++ int op = 0;
++ while (ip < iLen) {
++ int i0 = in[ip++] & 0xff;
++ int i1 = ip < iLen ? in[ip++] & 0xff : 0;
++ int i2 = ip < iLen ? in[ip++] & 0xff : 0;
++ int o0 = i0 >>> 2;
++ int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
++ int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
++ int o3 = i2 & 0x3F;
++ out[op++] = map1[o0];
++ out[op++] = map1[o1];
++ out[op] = op < oDataLen ? map1[o2] : '='; op++;
++ out[op] = op < oDataLen ? map1[o3] : '='; op++; }
++ return out; }
++
++ /**
++ * Decodes a string from Base64 format.
++ * @param s a Base64 String to be decoded.
++ * @return A String containing the decoded data.
++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data.
++ */
++ public static String decodeString (String s) {
++ return new String(decode(s)); }
++
++ /**
++ * Decodes a byte array from Base64 format.
++ * @param s a Base64 String to be decoded.
++ * @return An array containing the decoded data bytes.
++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data.
++ */
++ public static byte[] decode (String s) {
++ return decode(s.toCharArray()); }
++
++ /**
++ * Decodes a byte array from Base64 format.
++ * No blanks or line breaks are allowed within the Base64 encoded data.
++ * @param in a character array containing the Base64 encoded data.
++ * @return An array containing the decoded data bytes.
++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data.
++ */
++ public static byte[] decode (char[] in) {
++ int iLen = in.length;
++ if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4.");
++ while (iLen > 0 && in[iLen-1] == '=') iLen--;
++ int oLen = (iLen*3) / 4;
++ byte[] out = new byte[oLen];
++ int ip = 0;
++ int op = 0;
++ while (ip < iLen) {
++ int i0 = in[ip++];
++ int i1 = in[ip++];
++ int i2 = ip < iLen ? in[ip++] : 'A';
++ int i3 = ip < iLen ? in[ip++] : 'A';
++ if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
++ throw new IllegalArgumentException ("Illegal character in Base64 encoded data.");
++ int b0 = map2[i0];
++ int b1 = map2[i1];
++ int b2 = map2[i2];
++ int b3 = map2[i3];
++ if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)
++ throw new IllegalArgumentException ("Illegal character in Base64 encoded data.");
++ int o0 = ( b0 <<2) | (b1>>>4);
++ int o1 = ((b1 & 0xf)<<4) | (b2>>>2);
++ int o2 = ((b2 & 3)<<6) | b3;
++ out[op++] = (byte)o0;
++ if (op<oLen) out[op++] = (byte)o1;
++ if (op<oLen) out[op++] = (byte)o2; }
++ return out; }
++
++ // Dummy constructor.
++ private Base64Coder() {}
++
++}
diff -Naur JavaViewer.orig/VncCanvas.java JavaViewer/VncCanvas.java
--- JavaViewer.orig/VncCanvas.java 2005-11-21 18:50:18.000000000 -0500
+++ JavaViewer/VncCanvas.java 2007-05-31 15:33:20.000000000 -0400