Java(tm) Secure Socket Extension for the JavaTM 2 Standard Edition, v5.0 Sample Code README ---------------------------------------------------------------------- CONTENTS ---------------------------------------------------------------------- - Introduction - Sample KeyStores - Code Examples - Troubleshooting ---------------------------------------------------------------------- Introduction ---------------------------------------------------------------------- This JSSE sample code bundle provides some simple examples of how the JSSE can be used to secure communications in the Java(tm) network environment. The samples do require some familiarity with Java and the JSSE API, so please consult the appropriate documentation for more information. JDK: http://java.sun.com/doc/ JSSE: Documentation for the JSSE API can be found in Sun's JDK implementation or documentation bundles, or at http://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html If you use a JSSE implementation from a vendor other than Sun, also consult that JSSE implementation's documentation. Follow any instructions given by the vendor as to how to configure the security provider, set the classpaths (if necessary), enable the https protocol handler, define HTTPS proxy servers, and so on. ---------------------------------------------------------------------- Sample Truststores ---------------------------------------------------------------------- This bundle includes sample KeyStore files that are used with the sample code. They are stored in the "JKS" KeyStore format, which is the default format used by Sun's JDK implementation. (If another KeyStore format is desired, the JDK will need to be configured to recognize the new default format.) JSSE uses the following certificate KeyStore files to authenticate the clients and servers. */testkeys These files are used by the code samples as the source of public/private key and certificate material. In the client program directories, the testkeys files contains the certificate entry for the Java mascot "Duke". In the server program directories (./sockets/server and rmi), the file contains a certificate entry for the server "localhost". The sample code expects the testkeys file to be in the current working directory. NOTE: These are very simple certificates and are not appropriate for a production environment, but they should be sufficient for running the samples here. The password for these keystores is: passphrase samplecacerts This truststore file is very similar to the stock JDK cacerts file, in that it contains trust certificates from several vendors. It also contains the trusted certificates from "Duke" and "localhost" above. The password for this keystore is the same as the JDK cacert's initial password: changeit Please see your provider's documentation for how to configure the location of your trusted cert file. NOTES FOR RUNNING WITH SUN's JDK: --------------------------------- Users of the Sun JDK can specify the location of the truststore by using one of the following methods (and are described more fully in the Sun JDK JSSE Reference Guide): 1. System properties: java -Djavax.net.ssl.trustStore=samplecacerts \ -Djavax.net.ssl.trustStorePassword=changeit Application 2. Install the file into: /lib/security/jssecacerts 3. Install the file into: /lib/security/cacerts If you choose 2) or 3), be sure to replace this file with a production cacerts file before deployment. The Sun JDK utility "keytool" can be used to generate alternate certificates and keystore files. ******************************************* IMPORTANT NOTE: Verify Your cacerts File Since you trust the CAs in the cacerts file as entities for signing and issuing certificates to other entities, you must manage the cacerts file carefully. The cacerts file should contain only certificates of the entities and CAs you trust. It is your responsibility to verify the trusted root CA certificates bundled in the cacerts file and make your own trust decisions. To remove an untrusted CA certificate from the cacerts file, use the delete option of the keytool command. You can find the cacerts file in the JRE installation directory. Contact your system administrator if you do not have permission to edit this file. ---------------------------------------------------------------------- Code Examples ---------------------------------------------------------------------- The sample code bundle is broken into several directories, based on the style of SSL connections. urls URLReader.java This example illustrates using a URL to access resources on a secure site. By default, this example connects to www.verisign.com, but it can be adapted to connect to the ClassFileServer below. To do so, the URL will need to be modified to point to the correct address. You may also need to update the server's certificate or provide a custom HostNameVerifier (see HttpsURLConnection) if the hostname in the server's certificate doesn't match the URL's hostname. SPECIAL NOTES: If you are behind a firewall, you may need to set the "https.proxyHost" and "https.proxyPort" System properties to correctly specify the proxy. USAGE: java URLReader URLReaderWithOptions.java This example is very similar to URLReader above, but allows you to set the system properties via arguments to the main method, rather than as -D options to the java runtime environment. USAGE: java URLReaderWithOptions [-h proxyhost] [-p proxyport] \ [-k protocolhandlerpkgs] [-c ciphersarray] proxyHost = secure proxy server hostname (https.proxyHost) proxyPort = secure proxy server port (https.proxyPort) protocolhandlerpkgs = a "|" separated list of protocol handlers (java.protocol.handler.pkgs) ciphersarray = enabled cipher suites as a comma separated list (https.cipherSuites) sockets server ClassServer.java ClassFileServer.java This sample demonstrates the implementation of a mini-webserver, which can service simple HTTP or HTTPS requests (only the GET method is supported). By default, the server does not use SSL/TLS. However, a command line option enables SSL/TLS. Requests must be of the form: GET / USAGE: java ClassFileServer port docroot [TLS [true]] port = the port on which the server resides docroot = the root of the local directory hierarchy TLS = an optional flag which enables SSL/TLS services true = an optional flag which requires that clients authenticate themselves. This option requires that SSL/TLS support be enabled. The secure server comes preinstalled with a certificate for "localhost". If server is on the same host as the client, URLs of the form "https://localhost:port/file" should pass hostname verification. If you choose to run on separate hosts, you should create a new host certificate for the https hostname being used, otherwise there will be hostname mismatch problems. (Note: in Java this can be corrected in the HttpsURLConnection class by providing a custom HostnameVerifier implementation, or in a browswer by "Accept"ing the dialog box that describes the hostname mismatch.) If you are using the TLS variant (HTTPS), remember to specify the https protocol: https://hostname:2001/dir1/file1 NOTE: If you use a browser such as Microsoft's Internet Explorer or Netscape's Navigator you will see a dialog popup with the message that the application doesn't recognize the "localhost" certificate. This is normal because the self-signed certificate being presented to the browser is not initially trusted. If desired, you could import the "localhost" certificate into the browser's truststore. client SSLSocketClient.java This example demonstrates how to use a SSLSocket as a client to send a HTTP request and get a response from an HTTPS server. By default, this example connects to www.verisign.com, but it can easily be adapted to connect to the ClassFileServer above. (Note: The GET request must be slightly modified, so that a file is specified.) This application assumes the client is not behind a firewall. USAGE: java SSLSocketClient SSLSocketClientWithClientAuth.java This example is similar to SSLSocketClient above, but this shows how to set up a key manager to do client authentication if required by server. This application also assumes the client is not behind a firewall. USAGE: java SSLSocketClientWithClientAuth host port requestedfilepath NOTE: If you are connecting to the ClassFileServer application above, be sure that it can find "duke"'s credentials. See the "Sample Key Stores" section above. SSLSocketClientWithTunneling.java This example illustrates how to do proxy Tunneling to access a secure web server from behind a firewall. The System properties "https.proxyHost" and "https.proxyPort" are used to make a socket connection to the proxy host, and then the SSLSocket is layered on top of that Socket. USAGE: java SSLSocketClientWithTunneling rmi Hello.java HelloImpl.java RMISSLClientSocketFactory.java RMISSLServerSocketFactory.java HelloClient.java This example illustrates how to use RMI over an SSL transport layer using JSSE. The server runs HelloImpl, which sets up an internal RMI registry (rather than using the rmiregistry command). The client runs HelloClient and communicates over a secured connection. Setting up this sample can be a little tricky, here are the necessary steps: % javac *.java % rmic HelloImpl % java \ -Djava.security.policy=policy \ HelloImpl (run in another window) % java HelloClient (run in another window) For the server, the RMI security manager will be installed, and the supplied policy file grants permission to accept connections from any host. Obviously, giving all permissions should not be done in a production environment. You will need to give it the appropriate restrictive network privileges, such as: permission java.net.SocketPermission \ "hostname:1024-", "accept,resolve"; In addition, this example can be easily updated to run with the new standard SSL/TLS-based RMI Socket Factories. To do this, modify the HelloImpl.java file to use: javax.rmi.ssl.SslRMIClientSocketFactory javax.rmi.ssl.SslRMIServerSocketFactory instead of: RMISSLClientSocketFactory RMISSLServerSocketFactory These new classes use SSLSocketFactory.getDefault() and SSLServerSocketFactory.getDefault(), so you will need to configure the system properly to locate your key and trust material. NOTES FOR RUNNING WITH SUN's JDK: --------------------------------- If you use the new classes mentioned above, you can specify the key stores using the System properties: -Djavax.net.ssl.keyStore=testkeys -Djavax.net.ssl.keyStorePassword=passphrase sslengine SSLEngineSimpleDemo.java This example demonstrates a very simple client/server application using SSLEngines. It demonstrates the APIs without taking into account I/O or compute issues. USAGE: java SSLEngineSimpleDemo NOTE: There is a much more extensive SSLEngine sample available. Please see the /sample/nio/server directory for a NIO/SSLEngine-based HTTP/HTTPS server. ---------------------------------------------------------------------- Troubleshooting ---------------------------------------------------------------------- One of the most common problems people have in using JSSE is when the JSSE receives a certificate that is unknown to the mechanism that makes trust decisions. If an unknown certificate is received, the trust mechanism will throw an exception saying that the certificate is untrusted. Make sure that the correct trust store is being used, and that the JSSE is installed and configured correctly. If you are using the "localhost" or "duke" credentials, be sure that you have correctly specified the location of the samplecacerts file, otherwise your application will not work. (See "Sample Key Stores" for more information.) The SSL debug mechanism can be used to investigate such trust problems. See the implementation documentation for more information about this subject.