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