Example: JSSE server servlet

/* 
 * 
 *  This material contains programming source code for your 
 *  consideration.  These examples have not been thoroughly 
 *  tested under all conditions.  IBM, therefore, cannot 
 *  guarantee or imply reliability, serviceability, or function 
 *  of these program.  All programs contained herein are 
 *  provided to you "AS IS".  THE IMPLIED WARRANTIES OF 
 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 *  ARE EXPRESSLY DISCLAIMED.  IBM provides no program services for 
 *  these programs and files. 
 * 
 */ 
import java.io.*; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.security.Security; 
import java.security.KeyStore; 
import javax.net.ssl.SSLServerSocketFactory; 
import javax.net.ssl.SSLServerSocket; 
import javax.net.ssl.SSLSocket; 
import javax.net.ssl.SSLSession; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import com.ibm.net.ssl.SSLContext; 
import com.ibm.net.ssl.TrustManagerFactory; 
import com.ibm.net.ssl.KeyManagerFactory; 

/* 
 * ServerJsse and ClientJsse 
 * 
 * Sample applications to demonstrate a simple client/server interaction using JSSE.
 * They will communicate using all enabled cipher suites. 
 * 
 * The ServerJsse and ClientJsse use different KeyStore files called
 * "clientAppKeys.jks" and "serverAppKeys.jks" protected by a password and assumed
 * to be in the current directory. In a real application, the client and server
 * should also have their own KeyStore files.
 * 
 * You can build these sample program classes by issuing the following command but
 * first make sure that the ibmjsse.jar file shipped in the
 * "WAS_PRODUCT_ROOT/java/ext" is in your CLASSPATH or extensions directory.
 * This is a servlet, so you also need "WAS_PRODUCT_ROOT/lib/j2ee.jar to compile. 
 * 
 *     javac ServerJsse.java 
 *     javac ClientJsse.java 
 * 
 * 
 * Running the client/server application requires that the Server is started first
 * and then the Client application. 
 * 
 * To start the ServerJsse, run the following command: 
 * 
 *     java ServerJsse  port 
 * 
 * The ServerJsse uses port 8050 by default. Once ServerJsse has started it waits
 * for the ClientJsse connection. 
 * 
 * To start the client, issue the following command: 
 * 
 *     java ClientJsse hostname:port 
 * 
 * where hostname:port is the name of the host:port running SeverJsse. 
 * The default is localhost:8050. 
 * 
 */ 

public class ServerJsse extends HttpServlet { 
  static int N = 50, L = 100, R = 2; 
  static PrintWriter out = new PrintWriter(System.out); 
  static SSLContext sslContext; 
  

  // Open up the KeyStore to obtain the Trusted Certificates. 
  // KeyStore is of type "JKS". Filename is "serverAppKeys.jks"
  // and password is "myKeys". 
  private static void initContext() throws Exception { 
    try { 
      Security.addProvider(new com.ibm.jsse.JSSEProvider()); 

      KeyStore ks = KeyStore.getInstance("JKS"); 
      ks.load(new FileInputStream("serverAppKeys.jks"), "myKeys".toCharArray()); 
      KeyManagerFactory kmf = KeyManagerFactory.getInstance("IbmX509"); 
      kmf.init(ks, "myKeys".toCharArray()); 
      TrustManagerFactory tmf = TrustManagerFactory.getInstance("IbmX509"); 
      tmf.init(ks); 
      sslContext = SSLContext.getInstance("SSL"); 
      sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 
    }
    catch (Exception e) { 
      out.println("Failed to read serverAppKeys.jks file."); 
      e.printStackTrace(); 
      throw e; 
    } 
  } 
  

  public void doGet(HttpServletRequest q, HttpServletResponse r) { 
    r.setContentType("text/html"); 

    String[] args = new String[1]; 
    args[0] = getInitParameter("port"); 

    // send result to the caller 
    try { 
      out = r.getWriter(); 
      out.println("<html>"); 
      out.println("<head><title>Server JSSE Session</title></head>"); 
      out.println("<body>"); 
      out.println("<h1>Server JSSE Session (starting) </h1>"); 
      out.flush(); 
      out.println("<pre>"); 
      main(args); 

      out.println("</pre>"); 
      out.println("</body></html>"); 
      out.flush(); 
      out.close(); 

    }
    catch (Exception e) { 
      out.println("Exception in ServerJsse Servlet: " + e.getMessage()); 
      e.printStackTrace(); 
    } 
  }//end  public void doGet(...) 
  

  /* Entry point for ServerJsse as stand alone application. 
   * @param args no parameters required 
   */ 
  public static void main(String args[]) throws Exception { 
    int i, j, len, portint; 
    String port = "8050"; 

    if ((args != null) && (args.length > 0)) { 
      port = args[0]; 
    } 

    portint = (new Integer(port)).intValue(); 

    if (args.length > 1) 
      N = Integer.parseInt(args[0]); 
    if (args.length > 2) 
      L = Integer.parseInt(args[1]); 

    byte buffer[] = new byte[L]; 

    out.println("SERVER: started."); 

    initContext(); 

    try { 

      out.println("ServerJsse: SSL server context created."); 

      SSLServerSocketFactory factory = sslContext.getServerSocketFactory(); 

      // Get and print the list of supported enabled cipher suites 
      String enabled[] = factory.getSupportedCipherSuites(); 
      out.println("ServerJsse: enabled cipher suites"); 
      for (i=0; i < enabled.length; i++) 
        out.println(enabled[i]); 
      out.flush(); 

      // Create an SSL session over port 8050 
      SSLServerSocket ssl_server_sock =
         (SSLServerSocket)factory.createServerSocket(portint); 
      SSLSocket ssl_sock; 
      InputStream istr; 
      OutputStream ostr; 
      long t; 
      while (buffer[0] != -1) { 
        for (int n=0; n<R; n++) { 
          try { 
            ssl_sock = (SSLSocket)(ssl_server_sock.accept()); 
            ssl_sock.setEnabledCipherSuites(enabled); 

            ssl_sock.startHandshake(); 
            SSLSession session = ssl_sock.getSession(); 
            out.println(" "); 
            out.println("\nServerJsse: SSL connection established"); 
            out.println("   cipher suite:       " + session.getCipherSuite()); 
          }
          catch (IOException se) { 
            out.println("ServerJsse: client connection refused\n" + se); 
            break; 
          } 

          if (L > 0) { 
            istr = ssl_sock.getInputStream(); 
            ostr = ssl_sock.getOutputStream(); 

            t = System.currentTimeMillis(); 
            for (j=0;j<N;j++) { 
              for (len = 0;;) { 
                try { 
                  if ((i = istr.read(buffer, len, L-len)) == -1) { 
                    out.println("ServerJsse: connection dropped by partner."); 
                    ssl_sock.close(); 
                    return; 
                  } 
                }
                catch (InterruptedIOException e) { 
                  out.println("waiting"); 
                  continue; 
                } 
                if ((len+=i) == L) break; 
              } 
              ostr.write(buffer, 0, L); 
            } 
            out.println("Messages = " + N*2 + "; Time = " + 
                       (System.currentTimeMillis() - t)); 
          } 
          ssl_sock.close(); 
        } 
      } 
      ssl_server_sock.close(); 
      out.println("ServerJsse: SSL connection closed."); 
      out.flush(); 
      Thread.sleep(1000); 

      // Example using plain sockets 
      if (L > 0) { 
        ServerSocket server_sock = new ServerSocket(portint); 
        Socket sock = server_sock.accept(); 
        out.println(" "); 
        out.println("\nServerJsse: Plain Socket connection accepted."); 
        istr = sock.getInputStream(); 
        ostr = sock.getOutputStream(); 

        t = System.currentTimeMillis(); 
        for (j=0;j<N;j++) { 
          for (len = 0;;) { 
            if ((i = istr.read(buffer, len, L-len)) == -1) { 
              out.println("ServerJsse: connection dropped by partner."); 
              return; 
            } 
            if ((len+=i) == L) break; 
          } 
          ostr.write(buffer, 0, L); 
        } 
        out.println("Messages = " + N*2 + "; Time = " + 
                   (System.currentTimeMillis() - t)); 
        sock.close(); 
        server_sock.close(); 
        out.println("ServerJsse: Plain Socket connection closed."); 
        Thread.sleep(1000); 
      } 
    }
    catch (IOException e) { 
      e.printStackTrace(); 
    }
    catch (InterruptedException f) { 
      f.printStackTrace(); 
    } 
    out.println(" "); 
    out.println("ServerJsse: terminated."); 
    out.flush(); 

  }//end main(...) 

}//end class