You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by lu...@apache.org on 2003/07/11 03:04:55 UTC

cvs commit: jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/net/jsse JSSE14SocketFactory.java JSSESocketFactory.java

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: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org