Secure socket fun with VNC Applets.

Dave dwickford "at" yahoo.com
Mon Jul 12 20:39:01 2004


To preserve my virtue at the weekend I amended the VNC appletviewer to be able to use secure
sockets. I was surprized this hasn't been done already, that I could find, and really it should be
included as standard in the release.

These are the changes I made to CConn.java.  Note most of the changes are to support my self
signed certificate, which is OK for me as a home user.  If you are using certificate with a trail
to a good certification authority you should be able to get away with a 2 line change, using the
default SocketFactory.

// additional imports
import java.awt.*;
import java.awt.Event;
import java.io.*;
import javax.net.ssl.*;
import java.security.cert.*;
import java.security.*;

//a new class (in CConn.java)
class MyTrustManager implements X509TrustManager {

   MyTrustManager() { // constructor
      // create/load keystore
   }

   public void checkClientTrusted(X509Certificate chain[], String authType)
		 throws CertificateException {
   }

   public void checkServerTrusted(X509Certificate chain[], String authType) 
		throws CertificateException {
      // special handling such as poping dialog boxes
      X509Certificate first = chain[0];
      System.err.println("Serial Number "+first.getSerialNumber());
      java.math.BigInteger cert = new java.math.BigInteger("123456789");
      java.math.BigInteger  in = new java.math.BigInteger(first.getSerialNumber().toString());
      if (cert.equals(in)==false)
      {
	throw new CertificateException("not the same serial numbers!");
      }
	
   }

   public X509Certificate[] getAcceptedIssuers() {
	System.out.println("Caution getAcceptedIssuers called - not implemented properly!!");
	return null;	 
   }
}

//Note I'm checking the serial number of my certificate, but his isn't necessary
//getAcceptedIssuers() should return an array (maybe empty), but
//I don't know how to get the values.  Fix suggestions, please?

//In public class CConn the init() function has been changed:
public boolean init(java.net.Socket sock_, String vncServerName,
                      boolean alwaysShowServerDialog)
    throws java.io.IOException
  {
    sock = sock_;

    if (sock != null) {
      String name = sock.getInetAddress().getHostAddress()+"::"+sock.getPort();
      vlog.info("Accepted connection from "+name);
    } else {
      if (alwaysShowServerDialog || vncServerName == null) {
        ServerDialog dlg = new ServerDialog(options, about, vncServerName);
        if (!dlg.showDialog() || dlg.server.getText().equals(""))
          return false;
        vncServerName = dlg.server.getText();
      }
      serverHost = rfb.Hostname.getHost(vncServerName);
      serverPort = rfb.Hostname.getPort(vncServerName);

//      sock = new java.net.Socket(serverHost, serverPort);

// new secure code
	X509TrustManager xtm = new MyTrustManager();
	TrustManager mytm[] = {xtm};
	SSLContext ctx;
	try{
		ctx = SSLContext.getInstance("SSL");
	}
	catch (NoSuchAlgorithmException e)
	{
		System.err.println("No such Algorithm Exception");
		throw new IOException("Algorithm Exception SSL");
	}
	try{
		ctx.init(null,mytm, null );
	}
	catch (KeyManagementException e)
	{
		System.err.println("KeyManagementException e");
		throw new IOException ("Key Management after SSL");
	}
	SSLSocketFactory sf = ctx.getSocketFactory();

	/* too simplistic 
        SSLSocketFactory sslFact =
      		(SSLSocketFactory)SSLSocketFactory.getDefault();
         */
    	SSLSocket s =
      		(SSLSocket)sf.createSocket(serverHost, serverPort);
	String ciphers[] = s.getEnabledCipherSuites();
	int c=0;
	System.err.println("Ciphers");
	for (c=0;c<ciphers.length;c++)
	{
		System.err.println(ciphers[c]);
	}
	
	sock = s;
      vlog.info("connected to host "+serverHost+" port "+serverPort);
    }

    setServerName(sock.getInetAddress().getHostAddress()+"::"+sock.getPort());
    jis = new rdr.JavaInStream(sock.getInputStream());
    jos = new rdr.JavaOutStream(sock.getOutputStream());
    setStreams(jis, jos);
    initialiseProtocol();
    return true;
  }

//I've printed out some information to System.err.println(), but this really should be through
//vlog.


If this code could be tidied up, and improved, with e.g. certificate presentation for acceptance
that that would be a great improvement.  I did get this dialog once or twice, but pressing OK made
no difference, and I was still getting a "No trusted certificate found" exception.  It looks like
it needs Sun's Java 1.4 or later compiler because my Cygnus GNU gcj didn't work.

Regards,
Dave.







	
	
		
___________________________________________________________ALL-NEW Yahoo! Messenger - sooooo many all-new ways to express yourself http://uk.messenger.yahoo.com