// ======================================================================== // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.server.ssl; import java.io.IOException; import java.nio.channels.SocketChannel; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; import org.eclipse.jetty.http.HttpSchemes; import org.eclipse.jetty.io.AsyncEndPoint; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.Buffers.Type; import org.eclipse.jetty.io.BuffersFactory; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.io.bio.SocketEndPoint; import org.eclipse.jetty.io.nio.AsyncConnection; import org.eclipse.jetty.io.nio.SslConnection; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.util.component.AggregateLifeCycle; import org.eclipse.jetty.util.ssl.SslContextFactory; /* ------------------------------------------------------------ */ /** * SslSelectChannelConnector. * * @org.apache.xbean.XBean element="sslConnector" description="Creates an NIO ssl connector" */ public class SslSelectChannelConnector extends SelectChannelConnector implements SslConnector { private final SslContextFactory _sslContextFactory; private Buffers _sslBuffers; /* ------------------------------------------------------------ */ public SslSelectChannelConnector() { this(new SslContextFactory(SslContextFactory.DEFAULT_KEYSTORE_PATH)); setSoLingerTime(30000); } /* ------------------------------------------------------------ */ /** Construct with explicit SslContextFactory. * The SslContextFactory passed is added via {@link #addBean(Object)} so that * it's lifecycle may be managed with {@link AggregateLifeCycle}. * @param sslContextFactory */ public SslSelectChannelConnector(SslContextFactory sslContextFactory) { _sslContextFactory = sslContextFactory; addBean(_sslContextFactory); setUseDirectBuffers(false); setSoLingerTime(30000); } /* ------------------------------------------------------------ */ /** * Allow the Listener a chance to customise the request. before the server * does its stuff. <br> * This allows the required attributes to be set for SSL requests. <br> * The requirements of the Servlet specs are: * <ul> * <li> an attribute named "javax.servlet.request.ssl_session_id" of type * String (since Servlet Spec 3.0).</li> * <li> an attribute named "javax.servlet.request.cipher_suite" of type * String.</li> * <li> an attribute named "javax.servlet.request.key_size" of type Integer.</li> * <li> an attribute named "javax.servlet.request.X509Certificate" of type * java.security.cert.X509Certificate[]. This is an array of objects of type * X509Certificate, the order of this array is defined as being in ascending * order of trust. The first certificate in the chain is the one set by the * client, the next is the one used to authenticate the first, and so on. * </li> * </ul> * * @param endpoint * The Socket the request arrived on. This should be a * {@link SocketEndPoint} wrapping a {@link SSLSocket}. * @param request * HttpRequest to be customised. */ @Override public void customize(EndPoint endpoint, Request request) throws IOException { request.setScheme(HttpSchemes.HTTPS); super.customize(endpoint,request); SslConnection.SslEndPoint sslEndpoint=(SslConnection.SslEndPoint)endpoint; SSLEngine sslEngine=sslEndpoint.getSslEngine(); SSLSession sslSession=sslEngine.getSession(); SslCertificates.customize(sslSession,endpoint,request); } /* ------------------------------------------------------------ */ /** * @return True if SSL re-negotiation is allowed (default false) * @deprecated */ @Deprecated public boolean isAllowRenegotiate() { return _sslContextFactory.isAllowRenegotiate(); } /* ------------------------------------------------------------ */ /** * Set if SSL re-negotiation is allowed. CVE-2009-3555 discovered * a vulnerability in SSL/TLS with re-negotiation. If your JVM * does not have CVE-2009-3555 fixed, then re-negotiation should * not be allowed. CVE-2009-3555 was fixed in Sun java 1.6 with a ban * of renegotiate in u19 and with RFC5746 in u22. * @param allowRenegotiate true if re-negotiation is allowed (default false) * @deprecated */ @Deprecated public void setAllowRenegotiate(boolean allowRenegotiate) { _sslContextFactory.setAllowRenegotiate(allowRenegotiate); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#getExcludeCipherSuites() * @deprecated */ @Deprecated public String[] getExcludeCipherSuites() { return _sslContextFactory.getExcludeCipherSuites(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setExcludeCipherSuites(java.lang.String[]) * @deprecated */ @Deprecated public void setExcludeCipherSuites(String[] cipherSuites) { _sslContextFactory.setExcludeCipherSuites(cipherSuites); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#getExcludeCipherSuites() * @deprecated */ @Deprecated public String[] getIncludeCipherSuites() { return _sslContextFactory.getIncludeCipherSuites(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setExcludeCipherSuites(java.lang.String[]) * @deprecated */ @Deprecated public void setIncludeCipherSuites(String[] cipherSuites) { _sslContextFactory.setIncludeCipherSuites(cipherSuites); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setPassword(java.lang.String) * @deprecated */ @Deprecated public void setPassword(String password) { _sslContextFactory.setKeyStorePassword(password); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setTrustPassword(java.lang.String) * @deprecated */ @Deprecated public void setTrustPassword(String password) { _sslContextFactory.setTrustStorePassword(password); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setKeyPassword(java.lang.String) * @deprecated */ @Deprecated public void setKeyPassword(String password) { _sslContextFactory.setKeyManagerPassword(password); } /* ------------------------------------------------------------ */ /** * Unsupported. * * TODO: we should remove this as it is no longer an overridden method from SslConnector (like it was in the past) * @deprecated */ @Deprecated public String getAlgorithm() { throw new UnsupportedOperationException(); } /* ------------------------------------------------------------ */ /** * Unsupported. * * TODO: we should remove this as it is no longer an overridden method from SslConnector (like it was in the past) * @deprecated */ @Deprecated public void setAlgorithm(String algorithm) { throw new UnsupportedOperationException(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#getProtocol() * @deprecated */ @Deprecated public String getProtocol() { return _sslContextFactory.getProtocol(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setProtocol(java.lang.String) * @deprecated */ @Deprecated public void setProtocol(String protocol) { _sslContextFactory.setProtocol(protocol); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setKeystore(java.lang.String) * @deprecated */ @Deprecated public void setKeystore(String keystore) { _sslContextFactory.setKeyStorePath(keystore); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#getKeystore() * @deprecated */ @Deprecated public String getKeystore() { return _sslContextFactory.getKeyStorePath(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#getKeystoreType() * @deprecated */ @Deprecated public String getKeystoreType() { return _sslContextFactory.getKeyStoreType(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#getNeedClientAuth() * @deprecated */ @Deprecated public boolean getNeedClientAuth() { return _sslContextFactory.getNeedClientAuth(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#getWantClientAuth() * @deprecated */ @Deprecated public boolean getWantClientAuth() { return _sslContextFactory.getWantClientAuth(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setNeedClientAuth(boolean) * @deprecated */ @Deprecated public void setNeedClientAuth(boolean needClientAuth) { _sslContextFactory.setNeedClientAuth(needClientAuth); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setWantClientAuth(boolean) * @deprecated */ @Deprecated public void setWantClientAuth(boolean wantClientAuth) { _sslContextFactory.setWantClientAuth(wantClientAuth); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setKeystoreType(java.lang.String) * @deprecated */ @Deprecated public void setKeystoreType(String keystoreType) { _sslContextFactory.setKeyStoreType(keystoreType); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#getProvider() * @deprecated */ @Deprecated public String getProvider() { return _sslContextFactory.getProvider(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#getSecureRandomAlgorithm() * @deprecated */ @Deprecated public String getSecureRandomAlgorithm() { return _sslContextFactory.getSecureRandomAlgorithm(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#getSslKeyManagerFactoryAlgorithm() * @deprecated */ @Deprecated public String getSslKeyManagerFactoryAlgorithm() { return _sslContextFactory.getSslKeyManagerFactoryAlgorithm(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#getSslTrustManagerFactoryAlgorithm() * @deprecated */ @Deprecated public String getSslTrustManagerFactoryAlgorithm() { return _sslContextFactory.getTrustManagerFactoryAlgorithm(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#getTruststore() * @deprecated */ @Deprecated public String getTruststore() { return _sslContextFactory.getTrustStore(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#getTruststoreType() * @deprecated */ @Deprecated public String getTruststoreType() { return _sslContextFactory.getTrustStoreType(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setProvider(java.lang.String) * @deprecated */ @Deprecated public void setProvider(String provider) { _sslContextFactory.setProvider(provider); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setSecureRandomAlgorithm(java.lang.String) * @deprecated */ @Deprecated public void setSecureRandomAlgorithm(String algorithm) { _sslContextFactory.setSecureRandomAlgorithm(algorithm); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setSslKeyManagerFactoryAlgorithm(java.lang.String) * @deprecated */ @Deprecated public void setSslKeyManagerFactoryAlgorithm(String algorithm) { _sslContextFactory.setSslKeyManagerFactoryAlgorithm(algorithm); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setSslTrustManagerFactoryAlgorithm(java.lang.String) * @deprecated */ @Deprecated public void setSslTrustManagerFactoryAlgorithm(String algorithm) { _sslContextFactory.setTrustManagerFactoryAlgorithm(algorithm); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setTruststore(java.lang.String) * @deprecated */ @Deprecated public void setTruststore(String truststore) { _sslContextFactory.setTrustStore(truststore); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setTruststoreType(java.lang.String) * @deprecated */ @Deprecated public void setTruststoreType(String truststoreType) { _sslContextFactory.setTrustStoreType(truststoreType); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext) * @deprecated */ @Deprecated public void setSslContext(SSLContext sslContext) { _sslContextFactory.setSslContext(sslContext); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext) * @deprecated */ @Deprecated public SSLContext getSslContext() { return _sslContextFactory.getSslContext(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.ssl.SslConnector#getSslContextFactory() */ public SslContextFactory getSslContextFactory() { return _sslContextFactory; } /* ------------------------------------------------------------ */ /** * By default, we're confidential, given we speak SSL. But, if we've been * told about an confidential port, and said port is not our port, then * we're not. This allows separation of listeners providing INTEGRAL versus * CONFIDENTIAL constraints, such as one SSL listener configured to require * client certs providing CONFIDENTIAL, whereas another SSL listener not * requiring client certs providing mere INTEGRAL constraints. */ @Override public boolean isConfidential(Request request) { final int confidentialPort=getConfidentialPort(); return confidentialPort==0||confidentialPort==request.getServerPort(); } /* ------------------------------------------------------------ */ /** * By default, we're integral, given we speak SSL. But, if we've been told * about an integral port, and said port is not our port, then we're not. * This allows separation of listeners providing INTEGRAL versus * CONFIDENTIAL constraints, such as one SSL listener configured to require * client certs providing CONFIDENTIAL, whereas another SSL listener not * requiring client certs providing mere INTEGRAL constraints. */ @Override public boolean isIntegral(Request request) { final int integralPort=getIntegralPort(); return integralPort==0||integralPort==request.getServerPort(); } /* ------------------------------------------------------------------------------- */ @Override protected AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint) { try { SSLEngine engine = createSSLEngine(channel); SslConnection connection = newSslConnection(endpoint, engine); AsyncConnection delegate = newPlainConnection(channel, connection.getSslEndPoint()); connection.getSslEndPoint().setConnection(delegate); connection.setAllowRenegotiate(_sslContextFactory.isAllowRenegotiate()); return connection; } catch (IOException e) { throw new RuntimeIOException(e); } } protected AsyncConnection newPlainConnection(SocketChannel channel, AsyncEndPoint endPoint) { return super.newConnection(channel, endPoint); } protected SslConnection newSslConnection(AsyncEndPoint endpoint, SSLEngine engine) { return new SslConnection(engine, endpoint); } /* ------------------------------------------------------------ */ /** * @param channel A channel which if passed is used as to extract remote * host and port for the purposes of SSL session caching * @return A SSLEngine for a new or cached SSL Session * @throws IOException if the SSLEngine cannot be created */ protected SSLEngine createSSLEngine(SocketChannel channel) throws IOException { SSLEngine engine; if (channel != null) { String peerHost = channel.socket().getInetAddress().getHostAddress(); int peerPort = channel.socket().getPort(); engine = _sslContextFactory.newSslEngine(peerHost, peerPort); } else { engine = _sslContextFactory.newSslEngine(); } engine.setUseClientMode(false); return engine; } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.nio.SelectChannelConnector#doStart() */ @Override protected void doStart() throws Exception { _sslContextFactory.checkKeyStore(); _sslContextFactory.start(); SSLEngine sslEngine = _sslContextFactory.newSslEngine(); sslEngine.setUseClientMode(false); SSLSession sslSession = sslEngine.getSession(); _sslBuffers = BuffersFactory.newBuffers( getUseDirectBuffers()?Type.DIRECT:Type.INDIRECT,sslSession.getApplicationBufferSize(), getUseDirectBuffers()?Type.DIRECT:Type.INDIRECT,sslSession.getApplicationBufferSize(), getUseDirectBuffers()?Type.DIRECT:Type.INDIRECT,getMaxBuffers() ); if (getRequestHeaderSize()<sslSession.getApplicationBufferSize()) setRequestHeaderSize(sslSession.getApplicationBufferSize()); if (getRequestBufferSize()<sslSession.getApplicationBufferSize()) setRequestBufferSize(sslSession.getApplicationBufferSize()); super.doStart(); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.server.nio.SelectChannelConnector#doStop() */ @Override protected void doStop() throws Exception { _sslBuffers=null; super.doStop(); } /* ------------------------------------------------------------ */ /** * @return SSL buffers */ public Buffers getSslBuffers() { return _sslBuffers; } }