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]