From: markt Date: Thu, 9 Dec 2010 18:10:38 +0000 (+0000) Subject: Re-factoring in support of https://issues.apache.org/bugzilla/show_bug.cgi?id=50360 X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=61bd392033c358a6011022dc4b9ea8233549e80b;p=tomcat7.0 Re-factoring in support of https://issues.apache.org/bugzilla/show_bug.cgi?id=50360 Move ad-hoc attribute handling from the ProtocolHandler to the Endpoint and expose the Endpoint to ServerSocketFactory objects so they can retrieve additional configuration if required. All default components now use explicit configuration rather than relying on the ad-hoc mechanism. Ensure the hooks for alternative SSL implementations are in place (were partially removed). Remove the hooks for alternative ServerSocketFactory implementations (had been hard-coded / half implemented for some time). Make the sslEnabledProtocols attribute work with BIO as well. git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1044058 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/java/org/apache/catalina/connector/Connector.java b/java/org/apache/catalina/connector/Connector.java index 4b8185bc3..619b28c00 100644 --- a/java/org/apache/catalina/connector/Connector.java +++ b/java/org/apache/catalina/connector/Connector.java @@ -249,7 +249,6 @@ public class Connector extends LifecycleMBeanBase { replacements.put("connectionTimeout", "soTimeout"); replacements.put("randomFile", "randomfile"); replacements.put("rootFile", "rootfile"); - replacements.put("sslProtocols", "protocols"); } diff --git a/java/org/apache/coyote/AbstractProtocolHandler.java b/java/org/apache/coyote/AbstractProtocolHandler.java index a8040eb96..b7a00c49f 100644 --- a/java/org/apache/coyote/AbstractProtocolHandler.java +++ b/java/org/apache/coyote/AbstractProtocolHandler.java @@ -17,8 +17,6 @@ package org.apache.coyote; import java.net.InetAddress; -import java.util.HashMap; -import java.util.Iterator; import java.util.concurrent.Executor; import javax.management.MBeanRegistration; @@ -65,55 +63,6 @@ public abstract class AbstractProtocolHandler implements ProtocolHandler, // ----------------------------------------------- Generic property handling /** - * Attributes provide a way for configuration to be passed to sub-components - * without the {@link ProtocolHandler} being aware of the properties - * available on those sub-components. One example of such a sub-component is - * the {@link org.apache.tomcat.util.net.ServerSocketFactory}. - */ - protected HashMap attributes = - new HashMap(); - - - /** - * Generic property setter called when a property for which a specific - * setter already exists within the {@link ProtocolHandler} needs to be - * made available to sub-components. The specific setter will call this - * method to populate the attributes. - */ - @Override - public void setAttribute(String name, Object value) { - if (getLog().isTraceEnabled()) { - getLog().trace(sm.getString("abstractProtocolHandler.setAttribute", - name, value)); - } - attributes.put(name, value); - } - - - /** - * Used by sub-components to retrieve configuration information. - */ - @Override - public Object getAttribute(String key) { - Object value = attributes.get(key); - if (getLog().isTraceEnabled()) { - getLog().trace(sm.getString("abstractProtocolHandler.getAttribute", - key, value)); - } - return value; - } - - - /** - * Used by sub-components to retrieve configuration information. - */ - @Override - public Iterator getAttributeNames() { - return attributes.keySet().iterator(); - } - - - /** * Generic property setter used by the digester. Other code should not need * to use this. The digester will only use this method if it can't find a * more specific setter. That means the property belongs to the Endpoint, @@ -121,7 +70,6 @@ public abstract class AbstractProtocolHandler implements ProtocolHandler, * ensures that it is visible to both. */ public boolean setProperty(String name, String value) { - setAttribute(name, value); return endpoint.setProperty(name, value); } @@ -131,9 +79,7 @@ public abstract class AbstractProtocolHandler implements ProtocolHandler, * to use this. */ public String getProperty(String name) { - // Since all calls to setProperty() will place the property in the - // attributes list, just retrieve it from there. - return (String)getAttribute(name); + return endpoint.getProperty(name); } @@ -217,14 +163,12 @@ public abstract class AbstractProtocolHandler implements ProtocolHandler, public InetAddress getAddress() { return endpoint.getAddress(); } public void setAddress(InetAddress ia) { endpoint.setAddress(ia); - setAttribute("address", ia.toString()); } public int getPort() { return endpoint.getPort(); } public void setPort(int port) { endpoint.setPort(port); - setAttribute("port", Integer.toString(port)); } @@ -239,10 +183,6 @@ public abstract class AbstractProtocolHandler implements ProtocolHandler, public void setConnectionTimeout(int timeout) { // Note that the endpoint uses the alternative name endpoint.setSoTimeout(timeout); - String str = Integer.toString(timeout); - setAttribute("connectionTimeout", str); - // Also set the attribute for the alternative name - setAttribute("soTimeout", str); } /* diff --git a/java/org/apache/coyote/ProtocolHandler.java b/java/org/apache/coyote/ProtocolHandler.java index 8b2f608f0..b1594c8d6 100644 --- a/java/org/apache/coyote/ProtocolHandler.java +++ b/java/org/apache/coyote/ProtocolHandler.java @@ -17,7 +17,6 @@ package org.apache.coyote; -import java.util.Iterator; import java.util.concurrent.Executor; @@ -37,14 +36,6 @@ import java.util.concurrent.Executor; public interface ProtocolHandler { /** - * Pass config info. - */ - public void setAttribute(String name, Object value); - public Object getAttribute(String name); - public Iterator getAttributeNames(); - - - /** * The adapter, used to call the connector. */ public void setAdapter(Adapter adapter); diff --git a/java/org/apache/coyote/ajp/AjpProtocol.java b/java/org/apache/coyote/ajp/AjpProtocol.java index 5ec65ca89..3a4ea2c6b 100644 --- a/java/org/apache/coyote/ajp/AjpProtocol.java +++ b/java/org/apache/coyote/ajp/AjpProtocol.java @@ -34,6 +34,7 @@ import org.apache.tomcat.util.modeler.Registry; import org.apache.tomcat.util.net.AbstractEndpoint; import org.apache.tomcat.util.net.JIoEndpoint; import org.apache.tomcat.util.net.JIoEndpoint.Handler; +import org.apache.tomcat.util.net.SSLImplementation; import org.apache.tomcat.util.net.SocketStatus; import org.apache.tomcat.util.net.SocketWrapper; @@ -145,6 +146,12 @@ public class AjpProtocol extends AbstractAjpProtocol { } @Override + public SSLImplementation getSslImplementation() { + // AJP does not support SSL + return null; + } + + @Override public void recycle() { recycledProcessors.clear(); } @@ -251,7 +258,6 @@ public class AjpProtocol extends AbstractAjpProtocol { } } } - } } diff --git a/java/org/apache/coyote/http11/AbstractHttp11JsseProtocol.java b/java/org/apache/coyote/http11/AbstractHttp11JsseProtocol.java index 8786fb434..2f797565b 100644 --- a/java/org/apache/coyote/http11/AbstractHttp11JsseProtocol.java +++ b/java/org/apache/coyote/http11/AbstractHttp11JsseProtocol.java @@ -17,7 +17,6 @@ package org.apache.coyote.http11; import org.apache.tomcat.util.net.SSLImplementation; -import org.apache.tomcat.util.net.jsse.JSSEImplementation; public abstract class AbstractHttp11JsseProtocol extends AbstractHttp11Protocol { @@ -104,12 +103,19 @@ public abstract class AbstractHttp11JsseProtocol return endpoint.getAllowUnsafeLegacyRenegotiation(); } + private String sslImplemenationName = null; + public String getSslImplemenationName() { return sslImplemenationName; } + public void setSslImplemenationName(String s) { + this.sslImplemenationName = s; + } // ------------------------------------------------------- Lifecycle methods @Override public void init() throws Exception { + // SSL implementation needs to be in place before end point is + // initialized + sslImplementation = SSLImplementation.getInstance(sslImplemenationName); super.init(); - sslImplementation = new JSSEImplementation(); } } diff --git a/java/org/apache/coyote/http11/AbstractHttp11Protocol.java b/java/org/apache/coyote/http11/AbstractHttp11Protocol.java index 3b9748de0..648409b86 100644 --- a/java/org/apache/coyote/http11/AbstractHttp11Protocol.java +++ b/java/org/apache/coyote/http11/AbstractHttp11Protocol.java @@ -166,7 +166,6 @@ public abstract class AbstractHttp11Protocol extends AbstractProtocolHandler { public boolean getSecure() { return secure; } public void setSecure(boolean b) { secure = b; - setAttribute("secure", "" + b); } @@ -179,7 +178,6 @@ public abstract class AbstractHttp11Protocol extends AbstractProtocolHandler { } public void setMaxKeepAliveRequests(int mkar) { endpoint.setMaxKeepAliveRequests(mkar); - setAttribute("maxKeepAliveRequests", "" + mkar); } diff --git a/java/org/apache/coyote/http11/Http11NioProtocol.java b/java/org/apache/coyote/http11/Http11NioProtocol.java index a0f401735..8460ae4d1 100644 --- a/java/org/apache/coyote/http11/Http11NioProtocol.java +++ b/java/org/apache/coyote/http11/Http11NioProtocol.java @@ -37,6 +37,7 @@ import org.apache.tomcat.util.net.AbstractEndpoint; import org.apache.tomcat.util.net.NioChannel; import org.apache.tomcat.util.net.NioEndpoint; import org.apache.tomcat.util.net.NioEndpoint.Handler; +import org.apache.tomcat.util.net.SSLImplementation; import org.apache.tomcat.util.net.SecureNioChannel; import org.apache.tomcat.util.net.SocketStatus; @@ -110,12 +111,10 @@ public class Http11NioProtocol extends AbstractHttp11JsseProtocol { public void setAcceptorThreadPriority(int threadPriority) { ((NioEndpoint)endpoint).setAcceptorThreadPriority(threadPriority); - setAttribute("acceptorThreadPriority", "" + threadPriority); } public void setPollerThreadPriority(int threadPriority) { ((NioEndpoint)endpoint).setPollerThreadPriority(threadPriority); - setAttribute("pollerThreadPriority", "" + threadPriority); } public int getAcceptorThreadPriority() { @@ -142,12 +141,10 @@ public class Http11NioProtocol extends AbstractHttp11JsseProtocol { public void setSocketCloseDelay( int d ) { socketCloseDelay=d; - setAttribute("socketCloseDelay", "" + d); } public void setOomParachute(int oomParachute) { ((NioEndpoint)endpoint).setOomParachute(oomParachute); - setAttribute("oomParachute", Integer.valueOf(oomParachute)); } // -------------------- SSL related properties -------------------- @@ -217,6 +214,10 @@ public class Http11NioProtocol extends AbstractHttp11JsseProtocol { recycledProcessors.clear(); } + public SSLImplementation getSslImplementation() { + return proto.sslImplementation; + } + @Override public void release(SocketChannel socket) { if (log.isDebugEnabled()) diff --git a/java/org/apache/coyote/http11/Http11Protocol.java b/java/org/apache/coyote/http11/Http11Protocol.java index 00a61cf44..11b5a913e 100644 --- a/java/org/apache/coyote/http11/Http11Protocol.java +++ b/java/org/apache/coyote/http11/Http11Protocol.java @@ -35,6 +35,7 @@ import org.apache.tomcat.util.modeler.Registry; import org.apache.tomcat.util.net.AbstractEndpoint; import org.apache.tomcat.util.net.JIoEndpoint; import org.apache.tomcat.util.net.JIoEndpoint.Handler; +import org.apache.tomcat.util.net.SSLImplementation; import org.apache.tomcat.util.net.SocketStatus; import org.apache.tomcat.util.net.SocketWrapper; @@ -142,6 +143,10 @@ public class Http11Protocol extends AbstractHttp11JsseProtocol { return global; } + public SSLImplementation getSslImplementation() { + return proto.sslImplementation; + } + @Override public void recycle() { recycledProcessors.clear(); diff --git a/java/org/apache/tomcat/util/net/AbstractEndpoint.java b/java/org/apache/tomcat/util/net/AbstractEndpoint.java index 070ae7dc1..074489133 100644 --- a/java/org/apache/tomcat/util/net/AbstractEndpoint.java +++ b/java/org/apache/tomcat/util/net/AbstractEndpoint.java @@ -20,6 +20,8 @@ import java.io.File; import java.io.OutputStreamWriter; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.HashMap; import java.util.StringTokenizer; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; @@ -320,10 +322,44 @@ public abstract class AbstractEndpoint { protected abstract boolean getDeferAccept(); + + /** + * Attributes provide a way for configuration to be passed to sub-components + * without the {@link ProtocolHandler} being aware of the properties + * available on those sub-components. One example of such a sub-component is + * the {@link org.apache.tomcat.util.net.ServerSocketFactory}. + */ + protected HashMap attributes = + new HashMap(); + /** + * Generic property setter called when a property for which a specific + * setter already exists within the {@link ProtocolHandler} needs to be + * made available to sub-components. The specific setter will call this + * method to populate the attributes. + */ + public void setAttribute(String name, Object value) { + if (getLog().isTraceEnabled()) { + getLog().trace(sm.getString("abstractProtocolHandler.setAttribute", + name, value)); + } + attributes.put(name, value); + } /** - * Generic properties, introspected + * Used by sub-components to retrieve configuration information. */ + public Object getAttribute(String key) { + Object value = attributes.get(key); + if (getLog().isTraceEnabled()) { + getLog().trace(sm.getString("abstractProtocolHandler.getAttribute", + key, value)); + } + return value; + } + + + public boolean setProperty(String name, String value) { + setAttribute(name, value); final String socketName = "socket."; try { if (name.startsWith(socketName)) { @@ -336,7 +372,10 @@ public abstract class AbstractEndpoint { return false; } } - + public String getProperty(String name) { + return (String) getAttribute(name); + } + /** * Return the amount of threads that are managed by the pool. * @@ -632,11 +671,24 @@ public abstract class AbstractEndpoint { private String[] sslEnabledProtocolsarr = new String[0]; - public String[] getSslEnabledProtocolsArray() { return this.sslEnabledProtocolsarr;} + public String[] getSslEnabledProtocolsArray() { + return this.sslEnabledProtocolsarr; + } public void setSslEnabledProtocols(String s) { - StringTokenizer t = new StringTokenizer(s,","); - sslEnabledProtocolsarr = new String[t.countTokens()]; - for (int i=0; i sslEnabledProtocols = new ArrayList(); + StringTokenizer t = new StringTokenizer(s,","); + while (t.hasMoreTokens()) { + String p = t.nextToken().trim(); + if (p.length() > 0) { + sslEnabledProtocols.add(p); + } + } + sslEnabledProtocolsarr = sslEnabledProtocols.toArray( + new String[sslEnabledProtocols.size()]); + } } } diff --git a/java/org/apache/tomcat/util/net/DefaultServerSocketFactory.java b/java/org/apache/tomcat/util/net/DefaultServerSocketFactory.java index 1b4c7f04c..4ee222d73 100644 --- a/java/org/apache/tomcat/util/net/DefaultServerSocketFactory.java +++ b/java/org/apache/tomcat/util/net/DefaultServerSocketFactory.java @@ -29,48 +29,38 @@ import java.net.Socket; * @author db@eng.sun.com * @author Harish Prabandham */ +public class DefaultServerSocketFactory implements ServerSocketFactory { -// Default implementation of server sockets. + private AbstractEndpoint endpoint; -// -// WARNING: Some of the APIs in this class are used by J2EE. -// Please talk to harishp@eng.sun.com before making any changes. -// -class DefaultServerSocketFactory extends ServerSocketFactory { - - DefaultServerSocketFactory () { - /* NOTHING */ + public DefaultServerSocketFactory(AbstractEndpoint endpoint) { + this.endpoint = endpoint; } @Override - public ServerSocket createSocket (int port) - throws IOException { + public ServerSocket createSocket (int port) throws IOException { return new ServerSocket (port); } @Override public ServerSocket createSocket (int port, int backlog) - throws IOException { + throws IOException { return new ServerSocket (port, backlog); } @Override public ServerSocket createSocket (int port, int backlog, - InetAddress ifAddress) - throws IOException { + InetAddress ifAddress) throws IOException { return new ServerSocket (port, backlog, ifAddress); } - + @Override - public Socket acceptSocket(ServerSocket socket) - throws IOException { + public Socket acceptSocket(ServerSocket socket) throws IOException { return socket.accept(); } - + @Override - public void handshake(Socket sock) - throws IOException { + public void handshake(Socket sock) throws IOException { // NOOP } - } diff --git a/java/org/apache/tomcat/util/net/JIoEndpoint.java b/java/org/apache/tomcat/util/net/JIoEndpoint.java index 24c5e181f..1ca3c923b 100644 --- a/java/org/apache/tomcat/util/net/JIoEndpoint.java +++ b/java/org/apache/tomcat/util/net/JIoEndpoint.java @@ -119,7 +119,9 @@ public class JIoEndpoint extends AbstractEndpoint { */ public interface Handler extends AbstractEndpoint.Handler { public SocketState process(SocketWrapper socket); - public SocketState process(SocketWrapper socket, SocketStatus status); + public SocketState process(SocketWrapper socket, + SocketStatus status); + public SSLImplementation getSslImplementation(); } @@ -333,57 +335,22 @@ public class JIoEndpoint extends AbstractEndpoint { acceptorThreadCount = 1; } if (serverSocketFactory == null) { - serverSocketFactory = ServerSocketFactory.getDefault(); - } - if (isSSLEnabled()) { - serverSocketFactory.setAttribute(SSL_ATTR_ALGORITHM, - getAlgorithm()); - serverSocketFactory.setAttribute(SSL_ATTR_CLIENT_AUTH, - getClientAuth()); - serverSocketFactory.setAttribute(SSL_ATTR_KEYSTORE_FILE, - getKeystoreFile()); - serverSocketFactory.setAttribute(SSL_ATTR_KEYSTORE_PASS, - getKeystorePass()); - serverSocketFactory.setAttribute(SSL_ATTR_KEYSTORE_TYPE, - getKeystoreType()); - serverSocketFactory.setAttribute(SSL_ATTR_KEYSTORE_PROVIDER, - getKeystoreProvider()); - serverSocketFactory.setAttribute(SSL_ATTR_SSL_PROTOCOL, - getSslProtocol()); - serverSocketFactory.setAttribute(SSL_ATTR_CIPHERS, - getCiphers()); - serverSocketFactory.setAttribute(SSL_ATTR_KEY_ALIAS, - getKeyAlias()); - serverSocketFactory.setAttribute(SSL_ATTR_KEY_PASS, - getKeyPass()); - serverSocketFactory.setAttribute(SSL_ATTR_TRUSTSTORE_FILE, - getTruststoreFile()); - serverSocketFactory.setAttribute(SSL_ATTR_TRUSTSTORE_PASS, - getTruststorePass()); - serverSocketFactory.setAttribute(SSL_ATTR_TRUSTSTORE_TYPE, - getTruststoreType()); - serverSocketFactory.setAttribute(SSL_ATTR_TRUSTSTORE_PROVIDER, - getTruststoreProvider()); - serverSocketFactory.setAttribute(SSL_ATTR_TRUSTSTORE_ALGORITHM, - getTruststoreAlgorithm()); - serverSocketFactory.setAttribute(SSL_ATTR_CRL_FILE, - getCrlFile()); - serverSocketFactory.setAttribute(SSL_ATTR_TRUST_MAX_CERT_LENGTH, - getTrustMaxCertLength()); - serverSocketFactory.setAttribute(SSL_ATTR_SESSION_CACHE_SIZE, - getSessionCacheSize()); - serverSocketFactory.setAttribute(SSL_ATTR_SESSION_TIMEOUT, - getSessionTimeout()); - serverSocketFactory.setAttribute(SSL_ATTR_ALLOW_UNSAFE_RENEG, - getAllowUnsafeLegacyRenegotiation()); + if (isSSLEnabled()) { + serverSocketFactory = + handler.getSslImplementation().getServerSocketFactory(this); + } else { + serverSocketFactory = new DefaultServerSocketFactory(this); + } } if (serverSocket == null) { try { if (getAddress() == null) { - serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog()); + serverSocket = serverSocketFactory.createSocket(getPort(), + getBacklog()); } else { - serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog(), getAddress()); + serverSocket = serverSocketFactory.createSocket(getPort(), + getBacklog(), getAddress()); } } catch (BindException orig) { String msg; @@ -397,11 +364,8 @@ public class JIoEndpoint extends AbstractEndpoint { throw be; } } - //if( serverTimeout >= 0 ) - // serverSocket.setSoTimeout( serverTimeout ); initialized = true; - } @Override @@ -475,8 +439,6 @@ public class JIoEndpoint extends AbstractEndpoint { * Configure the socket. */ protected boolean setSocketOptions(Socket socket) { - serverSocketFactory.initSocket(socket); - try { // 1: Set socket options: timeout, linger, etc socketProperties.setProperties(socket); diff --git a/java/org/apache/tomcat/util/net/NioEndpoint.java b/java/org/apache/tomcat/util/net/NioEndpoint.java index 2df3759a8..11d557ae8 100644 --- a/java/org/apache/tomcat/util/net/NioEndpoint.java +++ b/java/org/apache/tomcat/util/net/NioEndpoint.java @@ -1500,6 +1500,7 @@ public class NioEndpoint extends AbstractEndpoint { public SocketState event(NioChannel socket, SocketStatus status); public void release(NioChannel socket); public void release(SocketChannel socket); + public SSLImplementation getSslImplementation(); } diff --git a/java/org/apache/tomcat/util/net/SSLImplementation.java b/java/org/apache/tomcat/util/net/SSLImplementation.java index f9a661331..a194af9a7 100644 --- a/java/org/apache/tomcat/util/net/SSLImplementation.java +++ b/java/org/apache/tomcat/util/net/SSLImplementation.java @@ -80,7 +80,8 @@ public abstract class SSLImplementation { public abstract String getImplementationName(); - public abstract ServerSocketFactory getServerSocketFactory(); + public abstract ServerSocketFactory getServerSocketFactory( + AbstractEndpoint endpoint); public abstract SSLSupport getSSLSupport(Socket sock); diff --git a/java/org/apache/tomcat/util/net/ServerSocketFactory.java b/java/org/apache/tomcat/util/net/ServerSocketFactory.java index d87223cd3..5d7792555 100644 --- a/java/org/apache/tomcat/util/net/ServerSocketFactory.java +++ b/java/org/apache/tomcat/util/net/ServerSocketFactory.java @@ -14,91 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.apache.tomcat.util.net; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; -import java.util.Hashtable; /** - * This class creates server sockets. It may be subclassed by other factories, - * which create particular types of server sockets. This provides a general - * framework for the addition of public socket-level functionality. It it is the - * server side analogue of a socket factory, and similarly provides a way to - * capture a variety of policies related to the sockets being constructed. - *

- * Like socket factories, Server Socket factory instances have two categories of - * methods. First are methods used to create sockets. Second are methods which - * set properties used in the production of sockets, such as networking options. - * There is also an environment specific default server socket factory; - * frameworks will often use their own customized factory. - *

- *


- * It may be desirable to move this interface into the - * java.net package, so that is not an extension but the preferred - * interface. Should this be serializable, making it a JavaBean which can - * be saved along with its networking configuration? - * - * - * @author db@eng.sun.com - * @author Harish Prabandham + * The common interface through which the {@link JIoEndpoint} interacts with + * both non-SSL and SSL sockets. */ -public abstract class ServerSocketFactory implements Cloneable { - - // - // NOTE: JDK 1.1 bug in class GC, this can get collected - // even though it's always accessible via getDefault(). - // - - private static ServerSocketFactory theFactory; - protected Hashtable attributes = new Hashtable(); - - /** - * Constructor is used only by subclasses. - */ - protected ServerSocketFactory() { - /* NOTHING */ - } - - /** - * General mechanism to pass attributes from the ServerConnector to the - * socket factory. Note that the "preferred" mechanism is to use bean - * setters and explicit methods, but this allows easy configuration via - * server.xml or simple Properties - */ - public void setAttribute(String name, Object value) { - if (name != null && value != null) - attributes.put(name, value); - } - - /** - * Returns a copy of the environment's default socket factory. - */ - public static synchronized ServerSocketFactory getDefault() { - // - // optimize typical case: no synch needed - // - - if (theFactory == null) { - // - // Different implementations of this method could - // work rather differently. For example, driving - // this from a system property, or using a different - // implementation than JavaSoft's. - // - - theFactory = new DefaultServerSocketFactory(); - } - - try { - return (ServerSocketFactory) theFactory.clone(); - } catch (CloneNotSupportedException e) { - throw new RuntimeException(e.getMessage()); - } - } +public interface ServerSocketFactory { /** * Returns a server socket which uses all network interfaces on the host, @@ -112,7 +39,7 @@ public abstract class ServerSocketFactory implements Cloneable { * @exception InstantiationException * for construction errors */ - public abstract ServerSocket createSocket(int port) throws IOException, + ServerSocket createSocket(int port) throws IOException, InstantiationException; /** @@ -130,8 +57,8 @@ public abstract class ServerSocketFactory implements Cloneable { * @exception InstantiationException * for construction errors */ - public abstract ServerSocket createSocket(int port, int backlog) - throws IOException, InstantiationException; + ServerSocket createSocket(int port, int backlog) throws IOException, + InstantiationException; /** * Returns a server socket which uses only the specified network interface @@ -150,26 +77,21 @@ public abstract class ServerSocketFactory implements Cloneable { * @exception InstantiationException * for construction errors */ - public abstract ServerSocket createSocket(int port, int backlog, - InetAddress ifAddress) throws IOException, InstantiationException; - - public void initSocket(Socket s) { - } + ServerSocket createSocket(int port, int backlog, InetAddress ifAddress) + throws IOException, InstantiationException; /** * Wrapper function for accept(). This allows us to trap and translate - * exceptions if necessary + * exceptions if necessary. * * @exception IOException - * ; */ - public abstract Socket acceptSocket(ServerSocket socket) throws IOException; + Socket acceptSocket(ServerSocket socket) throws IOException; /** - * Extra function to initiate the handshake. Sometimes necessary for SSL + * Triggers the SSL handshake. This will be a no-op for non-SSL sockets. * * @exception IOException - * ; */ - public abstract void handshake(Socket sock) throws IOException; + void handshake(Socket sock) throws IOException; } diff --git a/java/org/apache/tomcat/util/net/jsse/JSSEFactory.java b/java/org/apache/tomcat/util/net/jsse/JSSEFactory.java index 774574846..dcb0354d9 100644 --- a/java/org/apache/tomcat/util/net/jsse/JSSEFactory.java +++ b/java/org/apache/tomcat/util/net/jsse/JSSEFactory.java @@ -22,6 +22,7 @@ import java.net.Socket; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; +import org.apache.tomcat.util.net.AbstractEndpoint; import org.apache.tomcat.util.net.SSLSupport; import org.apache.tomcat.util.net.ServerSocketFactory; @@ -38,8 +39,8 @@ public class JSSEFactory { /** * Returns the ServerSocketFactory to use. */ - public ServerSocketFactory getSocketFactory() { - return new JSSESocketFactory(); + public ServerSocketFactory getSocketFactory(AbstractEndpoint endpoint) { + return new JSSESocketFactory(endpoint); } /** diff --git a/java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java b/java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java index 45d3e0df6..671423d2e 100644 --- a/java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java +++ b/java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java @@ -21,6 +21,7 @@ import java.net.Socket; import javax.net.ssl.SSLSession; +import org.apache.tomcat.util.net.AbstractEndpoint; import org.apache.tomcat.util.net.SSLImplementation; import org.apache.tomcat.util.net.SSLSupport; import org.apache.tomcat.util.net.ServerSocketFactory; @@ -47,8 +48,8 @@ public class JSSEImplementation extends SSLImplementation { } @Override - public ServerSocketFactory getServerSocketFactory() { - ServerSocketFactory ssf = factory.getSocketFactory(); + public ServerSocketFactory getServerSocketFactory(AbstractEndpoint endpoint) { + ServerSocketFactory ssf = factory.getSocketFactory(endpoint); return ssf; } diff --git a/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java b/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java index bf9540c65..7e8ca6fe2 100644 --- a/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java +++ b/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java @@ -60,6 +60,7 @@ import javax.net.ssl.X509KeyManager; import org.apache.catalina.Globals; import org.apache.tomcat.util.net.AbstractEndpoint; +import org.apache.tomcat.util.net.ServerSocketFactory; import org.apache.tomcat.util.res.StringManager; /** @@ -75,8 +76,7 @@ import org.apache.tomcat.util.res.StringManager; * @author Jan Luehe * @author Bill Barker */ -public class JSSESocketFactory - extends org.apache.tomcat.util.net.ServerSocketFactory { +public class JSSESocketFactory implements ServerSocketFactory { private static final StringManager sm = StringManager.getManager("org.apache.tomcat.util.net.jsse.res"); @@ -94,6 +94,8 @@ public class JSSESocketFactory static final org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory.getLog(JSSESocketFactory.class); + private AbstractEndpoint endpoint; + protected boolean initialized; protected SSLServerSocketFactory sslProxy = null; protected String[] enabledCiphers; @@ -110,8 +112,8 @@ public class JSSESocketFactory protected boolean wantClientAuth = false; - public JSSESocketFactory () { - // NOOP + public JSSESocketFactory (AbstractEndpoint endpoint) { + this.endpoint = endpoint; } @Override @@ -256,13 +258,11 @@ public class JSSESocketFactory * Gets the SSL server's keystore password. */ protected String getKeystorePassword() { - String keyPass = (String)attributes.get( - AbstractEndpoint.SSL_ATTR_KEY_PASS); + String keyPass = endpoint.getKeyPass(); if (keyPass == null) { keyPass = DEFAULT_KEY_PASS; } - String keystorePass = (String)attributes.get( - AbstractEndpoint.SSL_ATTR_KEYSTORE_PASS); + String keystorePass = endpoint.getKeystorePass(); if (keystorePass == null) { keystorePass = keyPass; } @@ -275,8 +275,7 @@ public class JSSESocketFactory protected KeyStore getKeystore(String type, String provider, String pass) throws IOException { - String keystoreFile = (String)attributes.get( - AbstractEndpoint.SSL_ATTR_KEYSTORE_FILE); + String keystoreFile = endpoint.getKeystoreFile(); if (keystoreFile == null) keystoreFile = defaultKeystoreFile; @@ -290,8 +289,7 @@ public class JSSESocketFactory String keystoreProvider) throws IOException { KeyStore trustStore = null; - String truststoreFile = (String)attributes.get( - AbstractEndpoint.SSL_ATTR_TRUSTSTORE_FILE); + String truststoreFile = endpoint.getTruststoreFile(); if(truststoreFile == null) { truststoreFile = System.getProperty("javax.net.ssl.trustStore"); } @@ -299,8 +297,7 @@ public class JSSESocketFactory log.debug("Truststore = " + truststoreFile); } - String truststorePassword = (String)attributes.get( - AbstractEndpoint.SSL_ATTR_TRUSTSTORE_PASS); + String truststorePassword = endpoint.getTruststorePass(); if( truststorePassword == null) { truststorePassword = System.getProperty("javax.net.ssl.trustStorePassword"); @@ -309,8 +306,7 @@ public class JSSESocketFactory log.debug("TrustPass = " + truststorePassword); } - String truststoreType = (String)attributes.get( - AbstractEndpoint.SSL_ATTR_TRUSTSTORE_TYPE); + String truststoreType = endpoint.getTruststoreType(); if( truststoreType == null) { truststoreType = System.getProperty("javax.net.ssl.trustStoreType"); } @@ -321,9 +317,7 @@ public class JSSESocketFactory log.debug("trustType = " + truststoreType); } - String truststoreProvider = - (String)attributes.get( - AbstractEndpoint.SSL_ATTR_TRUSTSTORE_PROVIDER); + String truststoreProvider = endpoint.getTruststoreProvider(); if( truststoreProvider == null) { truststoreProvider = System.getProperty("javax.net.ssl.trustStoreProvider"); @@ -419,8 +413,7 @@ public class JSSESocketFactory void init() throws IOException { try { - String clientAuthStr = (String) attributes.get( - AbstractEndpoint.SSL_ATTR_CLIENT_AUTH); + String clientAuthStr = endpoint.getClientAuth(); if("true".equalsIgnoreCase(clientAuthStr) || "yes".equalsIgnoreCase(clientAuthStr)) { requireClientAuth = true; @@ -429,32 +422,25 @@ public class JSSESocketFactory } // SSL protocol variant (e.g., TLS, SSL v3, etc.) - String protocol = (String) attributes.get( - AbstractEndpoint.SSL_ATTR_SSL_PROTOCOL); + String protocol = endpoint.getSslProtocol(); if (protocol == null) { protocol = defaultProtocol; } // Certificate encoding algorithm (e.g., SunX509) - String algorithm = (String) attributes.get( - AbstractEndpoint.SSL_ATTR_ALGORITHM); + String algorithm = endpoint.getAlgorithm(); if (algorithm == null) { algorithm = KeyManagerFactory.getDefaultAlgorithm(); } - String keystoreType = (String) attributes.get( - AbstractEndpoint.SSL_ATTR_KEYSTORE_TYPE); + String keystoreType = endpoint.getKeystoreType(); if (keystoreType == null) { keystoreType = defaultKeystoreType; } - String keystoreProvider = - (String) attributes.get( - AbstractEndpoint.SSL_ATTR_KEYSTORE_PROVIDER); + String keystoreProvider = endpoint.getKeystoreProvider(); - String trustAlgorithm = - (String)attributes.get( - AbstractEndpoint.SSL_ATTR_TRUSTSTORE_ALGORITHM); + String trustAlgorithm = endpoint.getTruststoreAlgorithm(); if( trustAlgorithm == null ) { trustAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); } @@ -463,27 +449,22 @@ public class JSSESocketFactory SSLContext context = SSLContext.getInstance(protocol); context.init(getKeyManagers(keystoreType, keystoreProvider, algorithm, - (String) attributes.get(AbstractEndpoint.SSL_ATTR_KEY_ALIAS)), + endpoint.getKeyAlias()), getTrustManagers(keystoreType, keystoreProvider, trustAlgorithm), new SecureRandom()); // Configure SSL session cache int sessionCacheSize; - if (attributes.get( - AbstractEndpoint.SSL_ATTR_SESSION_CACHE_SIZE) != null) { + if (endpoint.getSessionCacheSize() != null) { sessionCacheSize = Integer.parseInt( - (String)attributes.get( - AbstractEndpoint.SSL_ATTR_SESSION_CACHE_SIZE)); + endpoint.getSessionCacheSize()); } else { sessionCacheSize = defaultSessionCacheSize; } int sessionTimeout; - if (attributes.get( - AbstractEndpoint.SSL_ATTR_SESSION_TIMEOUT) != null) { - sessionTimeout = Integer.parseInt( - (String)attributes.get( - AbstractEndpoint.SSL_ATTR_SESSION_TIMEOUT)); + if (endpoint.getSessionTimeout() != null) { + sessionTimeout = Integer.parseInt(endpoint.getSessionTimeout()); } else { sessionTimeout = defaultSessionTimeout; } @@ -498,14 +479,12 @@ public class JSSESocketFactory sslProxy = context.getServerSocketFactory(); // Determine which cipher suites to enable - String requestedCiphers = (String)attributes.get( - AbstractEndpoint.SSL_ATTR_CIPHERS); + String requestedCiphers = endpoint.getCiphers(); enabledCiphers = getEnabledCiphers(requestedCiphers, sslProxy.getSupportedCipherSuites()); - allowUnsafeLegacyRenegotiation = - "true".equals(attributes.get( - AbstractEndpoint.SSL_ATTR_ALLOW_UNSAFE_RENEG)); + allowUnsafeLegacyRenegotiation = "true".equals( + endpoint.getAllowUnsafeLegacyRenegotiation()); // Check the SSL config is OK checkConfig(); @@ -559,8 +538,7 @@ public class JSSESocketFactory protected TrustManager[] getTrustManagers(String keystoreType, String keystoreProvider, String algorithm) throws Exception { - String crlf = (String) attributes.get( - AbstractEndpoint.SSL_ATTR_CRL_FILE); + String crlf = endpoint.getCrlFile(); TrustManager[] tms = null; @@ -608,8 +586,7 @@ public class JSSESocketFactory CertStore store = CertStore.getInstance("Collection", csp); xparams.addCertStore(store); xparams.setRevocationEnabled(true); - String trustLength = (String)attributes.get( - AbstractEndpoint.SSL_ATTR_TRUST_MAX_CERT_LENGTH); + String trustLength = endpoint.getTrustMaxCertLength(); if(trustLength != null) { try { xparams.setMaxPathLength(Integer.parseInt(trustLength)); @@ -677,68 +654,36 @@ public class JSSESocketFactory * Determines the SSL protocol variants to be enabled. * * @param socket The socket to get supported list from. - * @param requestedProtocols Comma-separated list of requested SSL - * protocol variants + * @param requestedProtocols Array of requested protocol names all of which + * must be non-null and non-zero length * * @return Array of SSL protocol variants to be enabled, or null if none of * the requested protocol variants are supported */ protected String[] getEnabledProtocols(SSLServerSocket socket, - String requestedProtocols){ + String[] requestedProtocols){ String[] supportedProtocols = socket.getSupportedProtocols(); String[] enabledProtocols = null; - if (requestedProtocols != null) { + if (requestedProtocols != null && requestedProtocols.length > 0) { Vector vec = null; - String protocol = requestedProtocols; - int index = requestedProtocols.indexOf(','); - if (index != -1) { - int fromIndex = 0; - while (index != -1) { - protocol = - requestedProtocols.substring(fromIndex, index).trim(); - if (protocol.length() > 0) { - /* - * Check to see if the requested protocol is among the - * supported protocols, i.e., may be enabled - */ - for (int i=0; supportedProtocols != null - && i(); - } - vec.addElement(protocol); - break; - } - } - } - fromIndex = index+1; - index = requestedProtocols.indexOf(',', fromIndex); - } // while - protocol = requestedProtocols.substring(fromIndex); - } - - if (protocol != null) { - protocol = protocol.trim(); - if (protocol.length() > 0) { - /* - * Check to see if the requested protocol is among the - * supported protocols, i.e., may be enabled - */ - for (int i=0; supportedProtocols != null - && i(); - } - vec.addElement(protocol); - break; + for (String protocol : requestedProtocols) { + /* + * Check to see if the requested protocol is among the supported + * protocols, i.e., may be enabled + */ + for (int i=0; supportedProtocols != null && + i < supportedProtocols.length; i++) { + if (supportedProtocols[i].equals(protocol)) { + if (vec == null) { + vec = new Vector(); } + vec.addElement(protocol); + break; } } - } + } if (vec != null) { enabledProtocols = new String[vec.size()]; @@ -775,7 +720,7 @@ public class JSSESocketFactory socket.setEnabledCipherSuites(enabledCiphers); } - String requestedProtocols = (String) attributes.get("protocols"); + String[] requestedProtocols = endpoint.getSslEnabledProtocolsArray(); setEnabledProtocols(socket, getEnabledProtocols(socket, requestedProtocols)); diff --git a/webapps/docs/config/http.xml b/webapps/docs/config/http.xml index 053926757..d6ee33651 100644 --- a/webapps/docs/config/http.xml +++ b/webapps/docs/config/http.xml @@ -817,7 +817,7 @@ connector uses OpenSSL. Therefore, in addition to using different attributes to configure SSL, the APR/native connector also requires keys and certificates to be provided in a different format.

- +

The BIO and NIO connectors use the following attributes to configure SSL:

@@ -916,8 +916,15 @@ -

NIO only. The version of the SSL protocols to use. If - not specified, the default is "TLSv1,SSLv3,SSLv2Hello".

+

The list of SSL protocols to use. If not specified, the JVM default is + used.

+
+ + +

The class name of the SSL implementation to use. If not specified, the + default of org.apache.tomcat.util.net.jsse.JSSEImplementation + will be used which wraps JVM's default JSSE provider. Note that the + JVM can be configured to use a different JSSE provider as the default.