luehe       2003/07/10 18:04:54

  Modified:    util/java/org/apache/tomcat/util/net/jsse
                        JSSE14SocketFactory.java JSSESocketFactory.java
  Log:
  Added support for enabling subset of supported SSL cipher suites (based on earlier 
proposal)
  
  Revision  Changes    Path
  1.3       +29 -60    
jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/net/jsse/JSSE14SocketFactory.java
  
  Index: JSSE14SocketFactory.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/net/jsse/JSSE14SocketFactory.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- JSSE14SocketFactory.java  15 Mar 2003 07:00:07 -0000      1.2
  +++ JSSE14SocketFactory.java  11 Jul 2003 01:04:54 -0000      1.3
  @@ -60,10 +60,8 @@
   
   import java.io.*;
   import java.net.*;
  -
   import java.security.KeyStore;
  -
  -import java.security.Security;
  +import java.security.SecureRandom;
   import javax.net.ServerSocketFactory;
   import javax.net.ssl.SSLServerSocket;
   import javax.net.ssl.SSLSocket;
  @@ -99,82 +97,53 @@
           super();
       }
   
  -    // -------------------- Internal methods
  -    /** Read the keystore, init the SSL socket factory
  +    /**
  +     * Reads the keystore and initializes the SSL socket factory.
        */
  -    void initProxy() throws IOException {
  +    void init() throws IOException {
           try {
   
  -            // Please don't change the name of the attribute - other
  -            // software may depend on it ( j2ee for sure )
  -            String keystoreFile=(String)attributes.get("keystore");
  -            if( keystoreFile==null) keystoreFile=defaultKeystoreFile;
  -
  -            keystoreType=(String)attributes.get("keystoreType");
  -            if( keystoreType==null) keystoreType=defaultKeystoreType;
  -
  -            //determine whether we want client authentication
  -            // the presence of the attribute enables client auth
  -            String clientAuthStr=(String)attributes.get("clientauth");
  -            if(clientAuthStr != null){
  -                if(clientAuthStr.equals("true")){
  -                    clientAuth=true;
  -                } else if(clientAuthStr.equals("false")) {
  -                    clientAuth=false;
  -                } else {
  -                    throw new IOException("Invalid value '" +
  -                                          clientAuthStr + 
  -                                          "' for 'clientauth' parameter:");
  -                }
  -            }
  -
  -            String keyPass=(String)attributes.get("keypass");
  -            if( keyPass==null) keyPass=defaultKeyPass;
  +         String clientAuthStr = (String)attributes.get("clientauth");
  +         if (clientAuthStr != null){
  +             clientAuth = Boolean.valueOf(clientAuthStr).booleanValue();
  +         }
   
  -            String keystorePass=(String)attributes.get("keystorePass");
  -            if( keystorePass==null) keystorePass=keyPass;
  -
  -            //protocol for the SSL ie - TLS, SSL v3 etc.
  +         // SSL protocol variant (e.g., TLS, SSL v3, etc.)
               String protocol = (String)attributes.get("protocol");
  -            if(protocol == null) protocol = defaultProtocol;
  -            
  -            //Algorithm used to encode the certificate ie - SunX509
  +            if (protocol == null) protocol = defaultProtocol;
  +
  +         // Certificate encoding algorithm (e.g., SunX509)
               String algorithm = (String)attributes.get("algorithm");
  -            if(algorithm == null) algorithm = defaultAlgorithm;
  -            
  -            // You can't use ssl without a server certificate.
  -            // Create a KeyStore ( to get server certs )
  -            KeyStore kstore = initKeyStore( keystoreFile, keystorePass );
  -            
  -            SSLContext context = SSLContext.getInstance(protocol); //SSL
  +            if (algorithm == null) algorithm = defaultAlgorithm;
   
  -            // Key manager will extract the server key
  +            // Set up KeyManager, which will extract server key
               KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
  -            kmf.init( kstore, keyPass.toCharArray());
  +         String keystoreType = (String)attributes.get("keystoreType");
  +         if (keystoreType == null)
  +             keystoreType = defaultKeystoreType;
  +         String keystorePass = getKeystorePassword();
  +            kmf.init(getKeystore(keystoreType, keystorePass),
  +                  keystorePass.toCharArray());
   
  -            //  set up TrustManager
  +            // Set up TrustManager
               TrustManager[] tm = null;
  -            String trustStoreFile = System.getProperty("javax.net.ssl.trustStore");
  -            String trustStorePassword =
  -                System.getProperty("javax.net.ssl.trustStorePassword");
  -            if ( trustStoreFile != null && trustStorePassword != null ){
  -                KeyStore trustStore = 
  -                    initKeyStore( trustStoreFile, trustStorePassword);
  -            
  +         KeyStore trustStore = getTrustStore(keystoreType);
  +            if (trustStore != null) {
                   TrustManagerFactory tmf = 
TrustManagerFactory.getInstance("SunX509");
  -
                   tmf.init(trustStore);
                   tm = tmf.getTrustManagers();
               }
   
  -            // init context with the key managers
  -            context.init(kmf.getKeyManagers(), tm, 
  -                         new java.security.SecureRandom());
  +         // Create and init SSLContext
  +            SSLContext context = SSLContext.getInstance(protocol); 
  +            context.init(kmf.getKeyManagers(), tm, new SecureRandom());
   
               // create proxy
               sslProxy = context.getServerSocketFactory();
   
  -            return;
  +         // Determine which cipher suites to enable
  +         enabledCiphers = getEnabledCiphers(sslProxy.getSupportedCipherSuites());
  +
           } catch(Exception e) {
               if( e instanceof IOException )
                   throw (IOException)e;
  
  
  
  1.3       +212 -136  
jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
  
  Index: JSSESocketFactory.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- JSSESocketFactory.java    15 Mar 2003 06:55:21 -0000      1.2
  +++ JSSESocketFactory.java    11 Jul 2003 01:04:54 -0000      1.3
  @@ -60,10 +60,10 @@
   
   import java.io.*;
   import java.net.*;
  -
  +import java.util.Vector;
   import java.security.KeyStore;
  -
   import java.security.Security;
  +import java.security.SecureRandom;
   import javax.net.ServerSocketFactory;
   import javax.net.ssl.SSLServerSocket;
   import javax.net.ssl.SSLSocket;
  @@ -92,31 +92,29 @@
   public class JSSESocketFactory
       extends org.apache.tomcat.util.net.ServerSocketFactory
   {
  -    String keystoreType;
  -
  -    static String defaultKeystoreType = "JKS";
  +    // defaults
       static String defaultProtocol = "TLS";
       static String defaultAlgorithm = "SunX509";
       static boolean defaultClientAuth = false;
  +    static String defaultKeystoreType = "JKS";
  +    private static final String defaultKeystoreFile
  +        = System.getProperty("user.home") + "/.keystore";
  +    private static final String defaultKeyPass = "changeit";
  +
  +    protected boolean initialized;
  +    protected boolean clientAuth = false;
  +    protected SSLServerSocketFactory sslProxy = null;
  +    protected String[] enabledCiphers;
  +   
   
  -    boolean clientAuth = false;
  -    SSLServerSocketFactory sslProxy = null;
  -    
  -    // defaults
  -    static String defaultKeystoreFile=System.getProperty("user.home") +
  -     "/.keystore";
  -    static String defaultKeyPass="changeit";
  -
  -    
       public JSSESocketFactory () {
       }
   
       public ServerSocket createSocket (int port)
        throws IOException
       {
  -     if( sslProxy == null ) initProxy();
  -     ServerSocket socket = 
  -         sslProxy.createServerSocket(port);
  +     if (!initialized) init();
  +     ServerSocket socket = sslProxy.createServerSocket(port);
        initServerSocket(socket);
        return socket;
       }
  @@ -124,9 +122,8 @@
       public ServerSocket createSocket (int port, int backlog)
        throws IOException
       {
  -     if( sslProxy == null ) initProxy();
  -     ServerSocket socket = 
  -         sslProxy.createServerSocket(port, backlog);
  +     if (!initialized) init();
  +     ServerSocket socket = sslProxy.createServerSocket(port, backlog);
        initServerSocket(socket);
        return socket;
       }
  @@ -135,96 +132,216 @@
                                      InetAddress ifAddress)
        throws IOException
       {        
  -     if( sslProxy == null ) initProxy();
  -     ServerSocket socket = 
  -         sslProxy.createServerSocket(port, backlog, ifAddress);
  +     if (!initialized) init();
  +     ServerSocket socket = sslProxy.createServerSocket(port, backlog,
  +                                                       ifAddress);
        initServerSocket(socket);
        return socket;
       }
       
  -    
  -    // -------------------- Internal methods
  -    /** Read the keystore, init the SSL socket factory
  -     */
  -    void initProxy() throws IOException {
  +    public Socket acceptSocket(ServerSocket socket)
  +     throws IOException
  +    {
  +     SSLSocket asock = null;
        try {
  -         Security.addProvider (new sun.security.provider.Sun());
  -         Security.addProvider (new com.sun.net.ssl.internal.ssl.Provider());
  +          asock = (SSLSocket)socket.accept();
  +          asock.setNeedClientAuth(clientAuth);
  +     } catch (SSLException e){
  +       throw new SocketException("SSL handshake error" + e.toString());
  +     }
  +     return asock;
  +    }
  +
  +    public void handshake(Socket sock) throws IOException {
  +     ((SSLSocket)sock).startHandshake();
  +    }
  +     
  +    /*
  +     * Determines the SSL cipher suites to be enabled.
  +     *
  +     * @return Array of SSL cipher suites to be enabled, or null if the
  +     * cipherSuites property was not specified (meaning that all supported
  +     * cipher suites are to be enabled)
  +     */
  +    protected String[] getEnabledCiphers(String[] supportedCiphers) {
  +
  +     String[] enabledCiphers = null;
  +
  +     String attrValue = (String)attributes.get("ciphers");
  +     if (attrValue != null) {
  +         Vector vec = null;
  +         int fromIndex = 0;
  +         int index = attrValue.indexOf(',', fromIndex);
  +         while (index != -1) {
  +             String cipher = attrValue.substring(fromIndex, index).trim();
  +             /*
  +              * Check to see if the requested cipher is among the supported
  +              * ciphers, i.e., may be enabled
  +              */
  +             for (int i=0; supportedCiphers != null
  +                          && i<supportedCiphers.length; i++) {
  +                 if (supportedCiphers[i].equals(cipher)) {
  +                     if (vec == null) {
  +                         vec = new Vector();
  +                     }
  +                     vec.addElement(cipher);
  +                     break;
  +                 }
  +             }
  +             fromIndex = index+1;
  +             index = attrValue.indexOf(',', fromIndex);
  +         }
  +
  +         if (vec != null) {
  +             enabledCiphers = new String[vec.size()];
  +             vec.copyInto(enabledCiphers);
  +         }
  +     }
  +
  +     return enabledCiphers;
  +    }
  +
  +    /*
  +     * Gets the SSL server's keystore password.
  +     */
  +    protected String getKeystorePassword() {
  +     String keyPass = (String)attributes.get("keypass");
  +     if (keyPass == null) {
  +         keyPass = defaultKeyPass;
  +     }
  +     String keystorePass = (String)attributes.get("keystorePass");
  +     if (keystorePass == null) {
  +         keystorePass = keyPass;
  +     }
  +     return keystorePass;
  +    }
  +
  +    /*
  +     * Gets the SSL server's keystore.
  +     */
  +    protected KeyStore getKeystore(String type, String pass)
  +         throws IOException {
  +
  +     String keystoreFile = (String)attributes.get("keystore");
  +     if (keystoreFile == null)
  +         keystoreFile = defaultKeystoreFile;
  +
  +     return getStore(type, keystoreFile, pass);
  +    }
  +
  +    /*
  +     * Gets the SSL server's truststore.
  +     */
  +    protected KeyStore getTrustStore(String keystoreType) throws IOException {
  +     KeyStore trustStore = null;
  +
  +     String trustStoreFile = System.getProperty("javax.net.ssl.trustStore");
  +     String trustStorePassword =
  +         System.getProperty("javax.net.ssl.trustStorePassword");
  +     if (trustStoreFile != null && trustStorePassword != null){
  +         trustStore = getStore(keystoreType, trustStoreFile,
  +                               trustStorePassword);
  +     }
  +
  +     return trustStore;
  +    }
  +
  +    /*
  +     * Gets the key- or truststore with the specified type, path, and password.
  +     */
  +    private KeyStore getStore(String type, String path, String pass)
  +         throws IOException {
   
  -         // Please don't change the name of the attribute - other
  -         // software may depend on it ( j2ee for sure )
  -         String keystoreFile=(String)attributes.get("keystore");
  -         if( keystoreFile==null) keystoreFile=defaultKeystoreFile;
  -
  -         keystoreType=(String)attributes.get("keystoreType");
  -         if( keystoreType==null) keystoreType=defaultKeystoreType;
  -
  -         //determine whether we want client authentication
  -         // the presence of the attribute enables client auth
  -         String clientAuthStr=(String)attributes.get("clientauth");
  -         if(clientAuthStr != null){
  -             if(clientAuthStr.equals("true")){
  -                 clientAuth=true;
  -             } else if(clientAuthStr.equals("false")) {
  -                 clientAuth=false;
  -             } else {
  -                 throw new IOException("Invalid value '" +
  -                                       clientAuthStr + 
  -                                       "' for 'clientauth' parameter:");
  +     KeyStore ks = null;
  +     InputStream istream = null;
  +     try {
  +         ks = KeyStore.getInstance(type);
  +         istream = new FileInputStream(path);
  +         ks.load(istream, pass.toCharArray());
  +         istream.close();
  +         istream = null;
  +     } catch (FileNotFoundException fnfe) {
  +         throw fnfe;
  +     } catch (IOException ioe) {
  +         throw ioe;      
  +     } catch(Exception ex) {
  +         ex.printStackTrace();
  +         throw new IOException("Exception trying to load keystore " +
  +                               path + ": " + ex.getMessage() );
  +     } finally {
  +         if (istream != null) {
  +             try {
  +                 istream.close();
  +             } catch (IOException ioe) {
  +                 // Do nothing
                }
            }
  +     }
   
  -         String keyPass=(String)attributes.get("keypass");
  -         if( keyPass==null) keyPass=defaultKeyPass;
  +     return ks;
  +    }
   
  -         String keystorePass=(String)attributes.get("keystorePass");
  -         if( keystorePass==null) keystorePass=keyPass;
  +    /**
  +     * Reads the keystore and initializes the SSL socket factory.
  +     *
  +     * NOTE: This method is identical in functionality to the method of the
  +     * same name in JSSE14SocketFactory, except that this method is used with
  +     * JSSE 1.0.x (which is an extension to the 1.3 JVM), whereas the other is
  +     * used with JSSE 1.1.x (which ships with the 1.4 JVM). Therefore, this
  +     * method uses classes in com.sun.net.ssl, which have since moved to
  +     * javax.net.ssl, and explicitly registers the required security providers,
  +     * which come standard in a 1.4 JVM.
  +     */
  +    private void init() throws IOException {
  +     try {
  +         Security.addProvider (new sun.security.provider.Sun());
  +         Security.addProvider (new com.sun.net.ssl.internal.ssl.Provider());
   
  -         //protocol for the SSL ie - TLS, SSL v3 etc.
  +         String clientAuthStr = (String)attributes.get("clientauth");
  +         if (clientAuthStr != null){
  +             clientAuth = Boolean.valueOf(clientAuthStr).booleanValue();
  +         }
  +         
  +         // SSL protocol variant (e.g., TLS, SSL v3, etc.)
            String protocol = (String)attributes.get("protocol");
  -         if(protocol == null) protocol = defaultProtocol;
  +         if (protocol == null) protocol = defaultProtocol;
            
  -         //Algorithm used to encode the certificate ie - SunX509
  +         // Certificate encoding algorithm (e.g., SunX509)
            String algorithm = (String)attributes.get("algorithm");
  -         if(algorithm == null) algorithm = defaultAlgorithm;
  -         
  -         // You can't use ssl without a server certificate.
  -         // Create a KeyStore ( to get server certs )
  -         KeyStore kstore = initKeyStore( keystoreFile, keystorePass );
  -         
  -         // Create a SSLContext ( to create the ssl factory )
  -         // This is the only way to use server sockets with JSSE 1.0.1
  -         com.sun.net.ssl.SSLContext context = 
  -             com.sun.net.ssl.SSLContext.getInstance(protocol); //SSL
  +         if (algorithm == null) algorithm = defaultAlgorithm;
   
  -         // Key manager will extract the server key
  +            // Set up KeyManager, which will extract server key
            com.sun.net.ssl.KeyManagerFactory kmf = 
                com.sun.net.ssl.KeyManagerFactory.getInstance(algorithm);
  -         kmf.init( kstore, keyPass.toCharArray());
  +         String keystoreType = (String)attributes.get("keystoreType");
  +         if (keystoreType == null) {
  +             keystoreType = defaultKeystoreType;
  +         }
  +         String keystorePass = getKeystorePassword();
  +         kmf.init(getKeystore(keystoreType, keystorePass),
  +                  keystorePass.toCharArray());
   
  -         //  set up TrustManager
  +         // Set up TrustManager
            com.sun.net.ssl.TrustManager[] tm = null;
  -         String trustStoreFile = System.getProperty("javax.net.ssl.trustStore");
  -         String trustStorePassword =
  -             System.getProperty("javax.net.ssl.trustStorePassword");
  -         if ( trustStoreFile != null && trustStorePassword != null ){
  -            KeyStore trustStore = initKeyStore( trustStoreFile, trustStorePassword);
  -            
  -            com.sun.net.ssl.TrustManagerFactory tmf =
  -                com.sun.net.ssl.TrustManagerFactory.getInstance("SunX509");
  -
  -            tmf.init(trustStore);
  -            tm = tmf.getTrustManagers();
  -        }
  -
  -         // init context with the key managers
  -         context.init(kmf.getKeyManagers(), tm, 
  -                      new java.security.SecureRandom());
  +         KeyStore trustStore = getTrustStore(keystoreType);
  +            if (trustStore != null) {
  +             com.sun.net.ssl.TrustManagerFactory tmf =
  +                 com.sun.net.ssl.TrustManagerFactory.getInstance("SunX509");
  +             tmf.init(trustStore);
  +             tm = tmf.getTrustManagers();
  +         }
   
  -         // create proxy
  +         // Create and init SSLContext
  +         com.sun.net.ssl.SSLContext context = 
  +             com.sun.net.ssl.SSLContext.getInstance(protocol); 
  +         context.init(kmf.getKeyManagers(), tm, new SecureRandom());
  +
  +         // Create proxy
            sslProxy = context.getServerSocketFactory();
   
  -         return;
  +         // Determine which cipher suites to enable
  +         enabledCiphers = getEnabledCiphers(sslProxy.getSupportedCipherSuites());
  +
        } catch(Exception e) {
            if( e instanceof IOException )
                throw (IOException)e;
  @@ -232,61 +349,20 @@
        }
       }
   
  -    public Socket acceptSocket(ServerSocket socket)
  -     throws IOException
  -    {
  -     SSLSocket asock = null;
  -     try {
  -          asock = (SSLSocket)socket.accept();
  -          asock.setNeedClientAuth(clientAuth);
  -     } catch (SSLException e){
  -       throw new SocketException("SSL handshake error" + e.toString());
  -     }
  -     return asock;
  -    }
  -     
  -    /** Set server socket properties ( accepted cipher suites, etc)
  +    /**
  +     * Sets the SSL server socket properties (such as enabled cipher suites,
  +     * etc.)
        */
  -    void initServerSocket(ServerSocket ssocket) {
  +    private void initServerSocket(ServerSocket ssocket) {
        SSLServerSocket socket=(SSLServerSocket)ssocket;
   
  -     // We enable all cipher suites when the socket is
  -     // connected - XXX make this configurable 
  -     String cipherSuites[] = socket.getSupportedCipherSuites();
  -     socket.setEnabledCipherSuites(cipherSuites);
  +     if (enabledCiphers != null) {
  +         socket.setEnabledCipherSuites(enabledCiphers);
  +     }
   
        // we don't know if client auth is needed -
        // after parsing the request we may re-handshake
        socket.setNeedClientAuth(clientAuth);
       }
   
  -    KeyStore initKeyStore( String keystoreFile,
  -                                String keyPass)
  -     throws IOException
  -    {
  -     InputStream istream = null;
  -     try {
  -         KeyStore kstore=KeyStore.getInstance( keystoreType );
  -         istream = new FileInputStream(keystoreFile);
  -         kstore.load(istream, keyPass.toCharArray());
  -         return kstore;
  -     }
  -     catch (FileNotFoundException fnfe) {
  -         throw fnfe;
  -     }
  -     catch (IOException ioe) {
  -         throw ioe;      
  -     }
  -     catch(Exception ex) {
  -         ex.printStackTrace();
  -         throw new IOException( "Exception trying to load keystore " +
  -                                keystoreFile + ": " + ex.getMessage() );
  -     }
  -    }
  -
  -    public void handshake(Socket sock)
  -      throws IOException
  -    {
  -     ((SSLSocket)sock).startHandshake();
  -    }
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to