/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *  
 *    http://www.apache.org/licenses/LICENSE-2.0
 *  
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License. 
 *  
 */
package org.apache.mina.filter;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSession;

import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.ByteBufferProxy;
import org.apache.mina.common.IoFilterAdapter;
import org.apache.mina.common.IoFilterChain;
import org.apache.mina.common.IoFuture;
import org.apache.mina.common.IoFutureListener;
import org.apache.mina.common.IoHandler;
import org.apache.mina.common.IoSession;
import org.apache.mina.common.WriteFuture;
import org.apache.mina.common.support.DefaultWriteFuture;
import org.apache.mina.filter.support.SSLHandler;
import org.apache.mina.util.SessionLog;

/**
 * An SSL filter that encrypts and decrypts the data exchanged in the session.
 * This filter uses an {@link SSLEngine} which was introduced in Java 5, so 
 * Java version 5 or above is mandatory to use this filter. And please note that
 * this filter only works for TCP/IP connections.
 * <p>
 * This filter logs debug information using {@link SessionLog}.
 * 
 * <h2>Implementing StartTLS</h2>
 * <p>
 * You can use {@link #DISABLE_ENCRYPTION_ONCE} attribute to implement StartTLS:
 * <pre>
 * public void messageReceived(IoSession session, Object message) {
 *    if (message instanceof MyStartTLSRequest) {
 *        // Insert SSLFilter to get ready for handshaking
 *        session.getFilterChain().addFirst(sslFilter);
 *
 *        // Disable encryption temporarilly.
 *        // This attribute will be removed by SSLFilter
 *        // inside the Session.write() call below.
 *        session.setAttribute(SSLFilter.DISABLE_ENCRYPTION_ONCE, Boolean.TRUE);
 *
 *        // Write StartTLSResponse which won't be encrypted.
 *        session.write(new MyStartTLSResponse(OK));
 *        
 *        // Now DISABLE_ENCRYPTION_ONCE attribute is cleared.
 *        assert session.getAttribute(SSLFilter.DISABLE_ENCRYPTION_ONCE) == null;
 *    }
 * }
 * </pre>
 * 
 * @author The Apache Directory Project (mina-dev@directory.apache.org)
 * @version $Rev$, $Date$
 */
public class SSLFilter extends IoFilterAdapter
{
    /**
     * A session attribute key that stores underlying {@link SSLSession}
     * for each session.
     */
    public static final String SSL_SESSION = SSLFilter.class.getName() + ".SSLSession";
    
    /**
     * A session attribute key that makes next one write request bypass
     * this filter (not encrypting the data).  This is a marker attribute,
     * which means that you can put whatever as its value. ({@link Boolean#TRUE}
     * is preferred.)  The attribute is automatically removed from the session
     * attribute map as soon as {@link IoSession#write(Object)} is invoked,
     * and therefore should be put again if you want to make more messages
     * bypass this filter.  This is especially useful when you implement
     * StartTLS.   
     */
    public static final String DISABLE_ENCRYPTION_ONCE = SSLFilter.class.getName() + ".DisableEncryptionOnce";

    /**
     * A session attribute key that makes this filter to emit a
     * {@link IoHandler#messageReceived(IoSession, Object)} event with a
     * special message ({@link #SESSION_SECURED} or {@link #SESSION_UNSECURED}).
     * This is a marker attribute, which means that you can put whatever as its
     * value. ({@link Boolean#TRUE} is preferred.)  By default, this filter
     * doesn't emit any events related with SSL session flow control.
     */
    public static final String USE_NOTIFICATION = SSLFilter.class.getName() + ".UseNotification";
    
    /**
     * A special message object which is emitted with a {@link IoHandler#messageReceived(IoSession, Object)}
     * event when the session is secured and its {@link #USE_NOTIFICATION}
     * attribute is set.
     */
    public static final SSLFilterMessage SESSION_SECURED = new SSLFilterMessage( "SESSION_SECURED" );
    
    /**
     * A special message object which is emitted with a {@link IoHandler#messageReceived(IoSession, Object)}
     * event when the session is not secure anymore and its {@link #USE_NOTIFICATION}
     * attribute is set.
     */
    public static final SSLFilterMessage SESSION_UNSECURED = new SSLFilterMessage( "SESSION_UNSECURED" );
    
    private static final String NEXT_FILTER = SSLFilter.class.getName() + ".NextFilter";
    private static final String SSL_HANDLER = SSLFilter.class.getName() + ".SSLHandler";

    // SSL Context
    private SSLContext sslContext;

    private boolean client;
    private boolean needClientAuth;
    private boolean wantClientAuth;
    private String[] enabledCipherSuites;
    private String[] enabledProtocols;

    /**
     * Creates a new SSL filter using the specified {@link SSLContext}.
     */
    public SSLFilter( SSLContext sslContext )
    {
        if( sslContext == null )
        {
            throw new NullPointerException( "sslContext" );
        }

        this.sslContext = sslContext;
    }
    
    /**
     * Returns the underlying {@link SSLSession} for the specified session.
     * 
     * @return <tt>null</tt> if no {@link SSLSession} is initialized yet.
     */
    public SSLSession getSSLSession( IoSession session )
    {
        return ( SSLSession ) session.getAttribute( SSL_SESSION );
    }
    
    /**
     * (Re)starts SSL session for the specified <tt>session</tt> if not started yet.
     * Please note that SSL session is automatically started by default, and therefore
     * you don't need to call this method unless you've used TLS closure.
     * 
     * @return <tt>true</tt> if the SSL session has been started, <tt>false</tt> if already started.
     * @throws SSLException if failed to start the SSL session
     */
    public boolean startSSL( IoSession session ) throws SSLException
    {
        SSLHandler handler = getSSLSessionHandler( session );
        synchronized( handler )
        {
            if( handler.isOutboundDone() )
            {
                NextFilter nextFilter = ( NextFilter ) session.getAttribute( NEXT_FILTER );
                handler.destroy();
                handler.init();
                handler.handshake( nextFilter );
                return true;
            }
            else
            {
                return false;
            }
        }
    }
    
    /**
     * Returns <tt>true</tt> if and only if the specified <tt>session</tt> is
     * encrypted/decrypted over SSL/TLS currently.  This method will start
     * to retun <tt>false</tt> after TLS <tt>close_notify</tt> message
     * is sent and any messages written after then is not goinf to get encrypted.
     */
    public boolean isSSLStarted( IoSession session )
    {
        SSLHandler handler = getSSLSessionHandler( session );
        synchronized( handler )
        {
            return !handler.isOutboundDone();
        }
    }

    /**
     * Stops the SSL session by sending TLS <tt>close_notify</tt> message to
     * initiate TLS closure.
     * 
     * @param session the {@link IoSession} to initiate TLS closure
     * @throws SSLException if failed to initiate TLS closure
     * @throws IllegalArgumentException if this filter is not managing the specified session
     */
    public WriteFuture stopSSL( IoSession session ) throws SSLException
    {
        SSLHandler handler = getSSLSessionHandler( session );
        NextFilter nextFilter = ( NextFilter ) session.getAttribute( NEXT_FILTER );
        synchronized( handler )
        {
            return initiateClosure( nextFilter, session );
        }
    }

    /**
     * Returns <tt>true</tt> if the engine is set to use client mode
     * when handshaking.
     */
    public boolean isUseClientMode()
    {
        return client;
    }
    
    /**
     * Configures the engine to use client (or server) mode when handshaking.
     */
    public void setUseClientMode( boolean clientMode )
    {
        this.client = clientMode;
    }
    
    /**
     * Returns <tt>true</tt> if the engine will <em>require</em> client authentication.
     * This option is only useful to engines in the server mode.
     */
    public boolean isNeedClientAuth()
    {
        return needClientAuth;
    }

    /**
     * Configures the engine to <em>require</em> client authentication.
     * This option is only useful for engines in the server mode.
     */
    public void setNeedClientAuth( boolean needClientAuth )
    {
        this.needClientAuth = needClientAuth;
    }
    
    
    /**
     * Returns <tt>true</tt> if the engine will <em>request</em> client authentication.
     * This option is only useful to engines in the server mode.
     */
    public boolean isWantClientAuth()
    {
        return wantClientAuth;
    }
    
    /**
     * Configures the engine to <em>request</em> client authentication.
     * This option is only useful for engines in the server mode.
     */
    public void setWantClientAuth( boolean wantClientAuth )
    {
        this.wantClientAuth = wantClientAuth;
    }
    
    /**
     * Returns the list of cipher suites to be enabled when {@link SSLEngine}
     * is initialized.
     * 
     * @return <tt>null</tt> means 'use {@link SSLEngine}'s default.'
     */
    public String[] getEnabledCipherSuites()
    {
        return enabledCipherSuites;
    }
    
    /**
     * Sets the list of cipher suites to be enabled when {@link SSLEngine}
     * is initialized.
     * 
     * @param cipherSuites <tt>null</tt> means 'use {@link SSLEngine}'s default.'
     */
    public void setEnabledCipherSuites( String[] cipherSuites )
    {
        this.enabledCipherSuites = cipherSuites;
    }

    /**
     * Returns the list of protocols to be enabled when {@link SSLEngine}
     * is initialized.
     * 
     * @return <tt>null</tt> means 'use {@link SSLEngine}'s default.'
     */
    public String[] getEnabledProtocols()
    {
        return enabledProtocols;
    }
    
    /**
     * Sets the list of protocols to be enabled when {@link SSLEngine}
     * is initialized.
     * 
     * @param protocols <tt>null</tt> means 'use {@link SSLEngine}'s default.'
     */
    public void setEnabledProtocols( String[] protocols )
    {
        this.enabledProtocols = protocols;
    }
    
    public void onPreAdd( IoFilterChain parent, String name, NextFilter nextFilter ) throws SSLException
    {
        if( parent.contains( SSLFilter.class ) )
        {
            throw new IllegalStateException( "A filter chain cannot contain more than one SSLFilter." );
        }

        IoSession session = parent.getSession();
        session.setAttribute( NEXT_FILTER, nextFilter );
        
        // Create an SSL handler and start handshake.
        SSLHandler handler =
            new SSLHandler( this, sslContext, session );
        session.setAttribute( SSL_HANDLER, handler );
    }
    
    public void onPostAdd( IoFilterChain parent, String name, NextFilter nextFilter ) throws SSLException
    {
        getSSLSessionHandler( parent.getSession() ).handshake( nextFilter );
    }
    
    public void onPreRemove( IoFilterChain parent, String name, NextFilter nextFilter ) throws SSLException
    {
        IoSession session = parent.getSession();
        stopSSL( session );
        session.removeAttribute( NEXT_FILTER );
        session.removeAttribute( SSL_HANDLER );
    }

    // IoFilter impl.
    public void sessionClosed( NextFilter nextFilter, IoSession session ) throws SSLException
    {
        SSLHandler handler = getSSLSessionHandler( session );
        try
        {
            synchronized( handler )
            {
                if( isSSLStarted( session ) )
                {
                    if( SessionLog.isDebugEnabled( session ) )
                    {
                        SessionLog.debug( session, " Closed: " + getSSLSessionHandler( session ) );
                    }
                }
                
                // release resources
                handler.destroy();
            }
        }
        finally
        {
           // notify closed session
           nextFilter.sessionClosed( session );
        }
    }
   
    public void messageReceived( NextFilter nextFilter, IoSession session,
                                 Object message ) throws SSLException
    {
        SSLHandler handler = getSSLSessionHandler( session );
        synchronized( handler )
        {
            if( !isSSLStarted( session ) )
            {
                if( handler.isInboundDone() )
                {
                    nextFilter.messageReceived( session, message );
                    return;
                }
            }
    
            ByteBuffer buf = ( ByteBuffer ) message;
            if( SessionLog.isDebugEnabled( session ) )
            {
                SessionLog.debug( session, " Data Read: " + handler + " (" + buf+ ')' );
            }

            try
            {
                // forward read encrypted data to SSL handler
                handler.messageReceived( nextFilter, buf.buf() );

                // Handle data to be forwarded to application or written to net
                handleSSLData( nextFilter, handler );

                if( handler.isInboundDone() )
                {
                    if( handler.isOutboundDone() )
                    {
                        if( SessionLog.isDebugEnabled( session ) )
                        {
                            SessionLog.debug(
                                    session, " SSL Session closed." );
                        }
                        
                        handler.destroy();
                    }
                    else
                    {
                        initiateClosure( nextFilter, session );
                    }

                    if( buf.hasRemaining() )
                    {
                        nextFilter.messageReceived( session, buf );
                    }
                }
            }
            catch( SSLException ssle )
            {
                if( !handler.isInitialHandshakeComplete() )
                {
                    SSLException newSSLE = new SSLHandshakeException(
                            "Initial SSL handshake failed." );
                    newSSLE.initCause( ssle );
                    ssle = newSSLE;
                }

                throw ssle;
            }
        }
    }

    public void messageSent( NextFilter nextFilter, IoSession session,
                             Object message )
    {
        if( message instanceof EncryptedBuffer )
        {
            EncryptedBuffer buf = ( EncryptedBuffer ) message;
            buf.release();
            nextFilter.messageSent( session, buf.originalBuffer );
        }
        else
        {
            // ignore extra buffers used for handshaking
        }
    }

    public void filterWrite( NextFilter nextFilter, IoSession session, WriteRequest writeRequest ) throws SSLException
    {
        SSLHandler handler = getSSLSessionHandler( session );
        synchronized( handler )
        {
            if( !isSSLStarted( session ) )
            {
                nextFilter.filterWrite( session, writeRequest );
                return;
            }
            
            // Don't encrypt the data if encryption is disabled.
            if( session.containsAttribute( DISABLE_ENCRYPTION_ONCE ) )
            {
                // Remove the marker attribute because it is temporary.
                session.removeAttribute( DISABLE_ENCRYPTION_ONCE );
                nextFilter.filterWrite( session, writeRequest );
                return;
            }
            
            // Otherwise, encrypt the buffer.
            ByteBuffer buf = ( ByteBuffer ) writeRequest.getMessage();
        
            if( SessionLog.isDebugEnabled( session ) )
            {
                SessionLog.debug( session, " Filtered Write: " + handler );
            }

            if( handler.isWritingEncryptedData() )
            {
                // data already encrypted; simply return buffer
                if( SessionLog.isDebugEnabled( session ) )
                {
                    SessionLog.debug( session, "   already encrypted: " + buf );
                }
                nextFilter.filterWrite( session, writeRequest );
                return;
            }
            
            if( handler.isInitialHandshakeComplete() )
            {
                // SSL encrypt
                if( SessionLog.isDebugEnabled( session ) )
                {
                    SessionLog.debug( session, " encrypt: " + buf );
                }
                
                int pos = buf.position();
                handler.encrypt( buf.buf() );
                buf.position( pos );
                ByteBuffer encryptedBuffer = new EncryptedBuffer(
                        SSLHandler.copy( handler.getOutNetBuffer() ), buf );

                if( SessionLog.isDebugEnabled( session ) )
                {
                    SessionLog.debug( session, " encrypted buf: " + encryptedBuffer);
                }
                nextFilter.filterWrite( session, new WriteRequest( encryptedBuffer, writeRequest.getFuture() ) );
                return;
            }
            else
            {
                if( !session.isConnected() )
                {
                    if( SessionLog.isDebugEnabled( session ) )
                    {
                        SessionLog.debug( session, " Write request on closed session." );
                    }
                }
                else
                {
                    if( SessionLog.isDebugEnabled( session ) )
                    {
                        SessionLog.debug( session, " Handshaking is not complete yet. Buffering write request." );
                    }
                    handler.scheduleWrite( nextFilter, writeRequest );
                }
            }
        }
    }
    
    public void filterClose( final NextFilter nextFilter, final IoSession session ) throws SSLException
    {
        SSLHandler handler = getSSLSessionHandler( session );

        WriteFuture future = null;
        synchronized( handler )
        {
            try
            {
                if( isSSLStarted( session ) )
                {
                    future = initiateClosure( nextFilter, session );
                }
            }
            finally
            {
                if( future == null )
                {
                    nextFilter.filterClose( session );
                }
                else
                {
                    future.addListener( new IoFutureListener()
                    {
                        public void operationComplete( IoFuture future )
                        {
                            nextFilter.filterClose( session );
                        }
                    });
                }
            }
        }
    }
    
    private WriteFuture initiateClosure( NextFilter nextFilter, IoSession session ) throws SSLException
    {
        SSLHandler handler = getSSLSessionHandler( session );
        // if already shut down
        if( !handler.closeOutbound() )
        {
            return DefaultWriteFuture.newNotWrittenFuture( session );
        }
        
        // there might be data to write out here?
        WriteFuture future = handler.writeNetBuffer( nextFilter );
        
        if( handler.isInboundDone() )
        {
            handler.destroy();
        }

        if( session.containsAttribute( USE_NOTIFICATION ) )
        {
            nextFilter.messageReceived( session, SESSION_UNSECURED );
        }
        
        return future;
    }

    // Utiliities

    private void handleSSLData( NextFilter nextFilter, SSLHandler handler ) throws SSLException
    {
        // Flush any buffered write requests occurred before handshaking.
        if( handler.isInitialHandshakeComplete() )
        {
            handler.flushScheduledWrites();
        }

        // Write encrypted data to be written (if any)
        handler.writeNetBuffer( nextFilter );

        // handle app. data read (if any)
        handleAppDataRead( nextFilter, handler );
    }

    private void handleAppDataRead( NextFilter nextFilter, SSLHandler handler )
    {
        IoSession session = handler.getSession();
        if( !handler.getAppBuffer().hasRemaining() )
        {
            return;
        }

        if( SessionLog.isDebugEnabled( session ) )
        {
            SessionLog.debug( session, " appBuffer: " + handler.getAppBuffer() );
        }

        // forward read app data
        ByteBuffer readBuffer = SSLHandler.copy( handler.getAppBuffer() );
        if( SessionLog.isDebugEnabled( session ) )
        {
            SessionLog.debug( session, " app data read: " + readBuffer + " (" + readBuffer.getHexDump() + ')' );
        }
        nextFilter.messageReceived( session, readBuffer );
    }

    private SSLHandler getSSLSessionHandler( IoSession session )
    {
        SSLHandler handler = ( SSLHandler ) session.getAttribute( SSL_HANDLER );
        if( handler == null )
        {
            throw new IllegalStateException();
        }
        if( handler.getParent() != this )
        {
            throw new IllegalArgumentException( "Not managed by this filter." );
        }
        return handler;
    }
    
    /**
     * A message that is sent from {@link SSLFilter} when the connection became
     * secure or is not secure anymore. 
     *
     * @author The Apache Directory Project (mina-dev@directory.apache.org)
     * @version $Rev$, $Date$
     */
    public static class SSLFilterMessage
    {
        private final String name;
        
        private SSLFilterMessage( String name )
        {
            this.name = name;
        }
        
        public String toString()
        {
            return name;
        }
    }
    
    private static class EncryptedBuffer extends ByteBufferProxy
    {
        private final ByteBuffer originalBuffer;
        
        private EncryptedBuffer( ByteBuffer buf, ByteBuffer originalBuffer )
        {
            super( buf );
            this.originalBuffer = originalBuffer;
        }
    }
}
