view src/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java @ 848:22a4e93ed20e

remove Container
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 19 Sep 2016 16:38:36 -0600
parents 3428c60d7cfc
children 1c0b6841cd32
line wrap: on
line source

//
//  ========================================================================
//  Copyright (c) 1995-2014 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;
    }
}