/*
 *  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.directory.server.ldap.handlers;


import java.util.Map;

import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.directory.server.core.CoreSession;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.LdapPrincipal;
import org.apache.directory.server.core.entry.ClonedServerEntry;
import org.apache.directory.server.core.interceptor.context.BindOperationContext;
import org.apache.directory.server.i18n.I18n;
import org.apache.directory.server.ldap.LdapProtocolUtils;
import org.apache.directory.server.ldap.LdapSession;
import org.apache.directory.server.ldap.handlers.bind.MechanismHandler;
import org.apache.directory.server.ldap.handlers.bind.SaslConstants;
import org.apache.directory.shared.ldap.constants.SchemaConstants;
import org.apache.directory.shared.ldap.entry.Entry;
import org.apache.directory.shared.ldap.exception.LdapAuthenticationException;
import org.apache.directory.shared.ldap.exception.LdapException;
import org.apache.directory.shared.ldap.exception.LdapInvalidDnException;
import org.apache.directory.shared.ldap.exception.LdapUnwillingToPerformException;
import org.apache.directory.shared.ldap.message.BindRequest;
import org.apache.directory.shared.ldap.message.BindResponse;
import org.apache.directory.shared.ldap.message.LdapResult;
import org.apache.directory.shared.ldap.message.ResultCodeEnum;
import org.apache.directory.shared.ldap.name.DN;
import org.apache.directory.shared.ldap.util.StringTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * A single reply handler for {@link BindRequest}s.
 *
 * Implements server-side of RFC 2222, sections 4.2 and 4.3.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class BindHandler extends LdapRequestHandler<BindRequest>
{
    private static final Logger LOG = LoggerFactory.getLogger( BindHandler.class );

    /** A Hashed Adapter mapping SASL mechanisms to their handlers. */
    private Map<String, MechanismHandler> handlers;


    /**
     * Set the mechanisms handler map.
     * 
     * @param handlers The associations btween a machanism and its handler
     */
    public void setSaslMechanismHandlers( Map<String, MechanismHandler> handlers )
    {
        this.handlers = handlers;
    }


    /**
     * Handle the Simple authentication.
     *
     * @param ldapSession The associated Session
     * @param bindRequest The BindRequest received
     * @throws Exception If the authentication cannot be done
     */
    // This will suppress PMD.EmptyCatchBlock warnings in this method
    @SuppressWarnings("PMD.EmptyCatchBlock")
    public void handleSimpleAuth( LdapSession ldapSession, BindRequest bindRequest ) throws Exception
    {
        // if the user is already bound, we have to unbind him
        if ( ldapSession.isAuthenticated() )
        {
            // We already have a bound session for this user. We have to
            // abandon it first.
            ldapSession.getCoreSession().unbind();
        }

        // Set the status to SimpleAuthPending
        ldapSession.setSimpleAuthPending();

        // Now, bind the user

        // create a new Bind context, with a null session, as we don't have 
        // any context yet.
        BindOperationContext bindContext = new BindOperationContext( null );

        // Stores the DN of the user to check, and its password
        bindContext.setDn( bindRequest.getName() );
        bindContext.setCredentials( bindRequest.getCredentials() );

        // Stores the request controls into the operation context
        LdapProtocolUtils.setRequestControls( bindContext, bindRequest );

        try
        {
            /*
             * Referral handling as specified by RFC 3296 here:
             *    
             *      http://www.faqs.org/rfcs/rfc3296.html
             *      
             * See section 5.6.1 where if the bind principal DN is a referral 
             * we return an invalidCredentials result response.  Optionally we
             * could support delegated authentication in the future with this
             * potential.  See the following JIRA for more on this possibility:
             * 
             *      https://issues.apache.org/jira/browse/DIRSERVER-1217
             *      
             * NOTE: if this is done then this handler should extend the 
             * a modified form of the ReferralAwareRequestHandler so it can 
             * detect conditions where ancestors of the DN are referrals
             * and delegate appropriately.
             */
            Entry principalEntry = null;

            try
            {
                principalEntry = getLdapServer().getDirectoryService().getAdminSession().lookup( bindRequest.getName() );
            }
            catch ( LdapException le )
            {
                // this is OK
            }

            if ( principalEntry == null )
            {
                LOG.info( "The {} principalDN cannot be found in the server : bind failure.", bindRequest.getName() );
            }
            else if ( ( ( ClonedServerEntry ) principalEntry ).getOriginalEntry().contains( SchemaConstants.OBJECT_CLASS_AT,
                SchemaConstants.REFERRAL_OC ) )
            {
                LOG.info( "Bind principalDn points to referral." );
                LdapResult result = bindRequest.getResultResponse().getLdapResult();
                result.setErrorMessage( "Bind principalDn points to referral." );
                result.setResultCode( ResultCodeEnum.INVALID_CREDENTIALS );
                ldapSession.getIoSession().write( bindRequest.getResultResponse() );
                return;
            }

            // TODO - might cause issues since lookups are not returning all 
            // attributes right now - this is an optimization that can be 
            // enabled later after determining whether or not this will cause
            // issues.
            // reuse the looked up entry so we don't incur another lookup
            // opContext.setEntry( principalEntry );

            // And call the OperationManager bind operation.
            getLdapServer().getDirectoryService().getOperationManager().bind( bindContext );

            // As a result, store the created session in the Core Session
            ldapSession.setCoreSession( bindContext.getSession() );

            // And set the current state accordingly
            if ( !ldapSession.getCoreSession().isAnonymous() )
            {
                ldapSession.setAuthenticated();
            }
            else
            {
                ldapSession.setAnonymous();
            }

            // Return the successful response
            bindRequest.getResultResponse().addAllControls( bindContext.getResponseControls() );
            sendBindSuccess( ldapSession, bindRequest, null );
        }
        catch ( Exception e )
        {
            // Something went wrong. Write back an error message
            // For BindRequest, it should be an InvalidCredentials, 
            // no matter what kind of exception we got.
            ResultCodeEnum code = null;
            LdapResult result = bindRequest.getResultResponse().getLdapResult();

            if ( e instanceof LdapUnwillingToPerformException )
            {
                code = ResultCodeEnum.UNWILLING_TO_PERFORM;
                result.setResultCode( code );
            }
            else if ( e instanceof LdapInvalidDnException )
            {
                code = ResultCodeEnum.INVALID_DN_SYNTAX;
                result.setResultCode( code );
            }
            else
            {
                code = ResultCodeEnum.INVALID_CREDENTIALS;
                result.setResultCode( code );
            }

            String msg = code.toString() + ": Bind failed: " + e.getLocalizedMessage();

            if ( LOG.isDebugEnabled() )
            {
                msg += ":\n" + ExceptionUtils.getStackTrace( e );
                msg += "\n\nBindRequest = \n" + bindRequest.toString();
            }

            DN dn = null;

            if ( e instanceof LdapAuthenticationException )
            {
                dn = ( ( LdapAuthenticationException ) e ).getResolvedDn();
            }

            if ( ( dn != null )
                && ( ( code == ResultCodeEnum.NO_SUCH_OBJECT ) || ( code == ResultCodeEnum.ALIAS_PROBLEM )
                    || ( code == ResultCodeEnum.INVALID_DN_SYNTAX ) || ( code == ResultCodeEnum.ALIAS_DEREFERENCING_PROBLEM ) ) )
            {
                result.setMatchedDn( dn );
            }

            result.setErrorMessage( msg );
            bindRequest.getResultResponse().addAllControls( bindContext.getResponseControls() );
            ldapSession.getIoSession().write( bindRequest.getResultResponse() );
        }
        finally
        {
            // Reset LDAP session bind status to anonymous if authentication failed
            if ( !ldapSession.isAuthenticated() )
            {
                ldapSession.setAnonymous();
            }
        }
    }


    /**
     * Check if the mechanism exists.
     */
    private boolean checkMechanism( String saslMechanism ) throws Exception
    {
        // Guard clause:  Reject unsupported SASL mechanisms.
        if ( !ldapServer.getSupportedMechanisms().contains( saslMechanism ) )
        {
            LOG.error( I18n.err( I18n.ERR_160, saslMechanism ) );

            return false;
        }
        else
        {
            return true;
        }
    }


    /**
     * For challenge/response exchange, generate the challenge. 
     * If the exchange is complete then send bind success.
     *
     * @param ldapSession
     * @param ss
     * @param bindRequest
     */
    private void generateSaslChallengeOrComplete( LdapSession ldapSession, SaslServer ss,
        BindRequest bindRequest ) throws Exception
    {
        LdapResult result = bindRequest.getResultResponse().getLdapResult();

        // SaslServer will throw an exception if the credentials are null.
        if ( bindRequest.getCredentials() == null )
        {
            bindRequest.setCredentials( StringTools.EMPTY_BYTES );
        }

        try
        {
            // Compute the challenge
            byte[] tokenBytes = ss.evaluateResponse( bindRequest.getCredentials() );

            if ( ss.isComplete() )
            {
                // This is the end of the C/R exchange
                if ( tokenBytes != null )
                {
                    /*
                     * There may be a token to return to the client.  We set it here
                     * so it will be returned in a SUCCESS message, after an LdapContext
                     * has been initialized for the client.
                     */
                    ldapSession.putSaslProperty( SaslConstants.SASL_CREDS, tokenBytes );
                }

                LdapPrincipal ldapPrincipal = ( LdapPrincipal ) ldapSession
                    .getSaslProperty( SaslConstants.SASL_AUTHENT_USER );

                if ( ldapPrincipal != null )
                {
                    DirectoryService ds = ldapSession.getLdapServer().getDirectoryService();
                    String saslMechanism = bindRequest.getSaslMechanism();
                    CoreSession userSession = ds.getSession( ldapPrincipal.getDN(), ldapPrincipal.getUserPassword(),
                        saslMechanism, null );

                    // Set the user session into the ldap session 
                    ldapSession.setCoreSession( userSession );
                }

                // Mark the user as authenticated
                ldapSession.setAuthenticated();

                // Call the cleanup method for the selected mechanism
                MechanismHandler handler = ( MechanismHandler ) ldapSession
                    .getSaslProperty( SaslConstants.SASL_MECH_HANDLER );
                handler.cleanup( ldapSession );

                // Return the successful response
                sendBindSuccess( ldapSession, bindRequest, tokenBytes );
            }
            else
            {
                // The SASL bind must continue, we are sending the computed challenge
                LOG.info( "Continuation token had length " + tokenBytes.length );

                // Build the response
                result.setResultCode( ResultCodeEnum.SASL_BIND_IN_PROGRESS );
                BindResponse resp = ( BindResponse ) bindRequest.getResultResponse();

                // Store the challenge
                resp.setServerSaslCreds( tokenBytes );

                // Switch to SASLAuthPending
                ldapSession.setSaslAuthPending();

                // And write back the response
                ldapSession.getIoSession().write( resp );

                LOG.debug( "Returning final authentication data to client to complete context." );
            }
        }
        catch ( SaslException se )
        {
            sendInvalidCredentials( ldapSession, bindRequest, se );
        }
    }


    /**
     * Send back an AUTH-METH-NOT-SUPPORTED error message to the client
     */
    private void sendAuthMethNotSupported( LdapSession ldapSession, BindRequest bindRequest )
    {
        // First, r-einit the state to Anonymous, and clear the
        // saslProperty map
        ldapSession.clearSaslProperties();
        ldapSession.setAnonymous();

        // And send the response to the client
        LdapResult bindResult = bindRequest.getResultResponse().getLdapResult();
        bindResult.setResultCode( ResultCodeEnum.AUTH_METHOD_NOT_SUPPORTED );
        bindResult.setErrorMessage( ResultCodeEnum.AUTH_METHOD_NOT_SUPPORTED.toString() + ": "
            + bindRequest.getSaslMechanism() + " is not a supported mechanism." );

        // Write back the error
        ldapSession.getIoSession().write( bindRequest.getResultResponse() );
    }


    /**
     * Send back an INVALID-CREDENTIAL error message to the user. If we have an exception
     * as a third argument, then send back the associated message to the client. 
     */
    private void sendInvalidCredentials( LdapSession ldapSession, BindRequest bindRequest, Exception e )
    {
        LdapResult result = bindRequest.getResultResponse().getLdapResult();

        String message = "";

        if ( e != null )
        {
            message = ResultCodeEnum.INVALID_CREDENTIALS + ": " + e.getLocalizedMessage();
        }
        else
        {
            message = ResultCodeEnum.INVALID_CREDENTIALS.toString();
        }

        LOG.error( message );
        result.setResultCode( ResultCodeEnum.INVALID_CREDENTIALS );
        result.setErrorMessage( message );

        // Reinitialize the state to Anonymous and clear the sasl properties
        ldapSession.clearSaslProperties();
        ldapSession.setAnonymous();

        // Write back the error response
        ldapSession.getIoSession().write( bindRequest.getResultResponse() );
    }


    /**
     * Send a SUCCESS message back to the client.
     */
    private void sendBindSuccess( LdapSession ldapSession, BindRequest bindRequest, byte[] tokenBytes )
    {
        // Return the successful response
        BindResponse response = ( BindResponse ) bindRequest.getResultResponse();
        response.getLdapResult().setResultCode( ResultCodeEnum.SUCCESS );
        response.setServerSaslCreds( tokenBytes );

        if ( !ldapSession.getCoreSession().isAnonymous() )
        {
            // If we have not been asked to authenticate as Anonymous, authenticate the user
            ldapSession.setAuthenticated();
        }
        else
        {
            // Otherwise, switch back to Anonymous
            ldapSession.setAnonymous();
        }

        // Clean the SaslProperties, we don't need them anymore
        MechanismHandler handler = ( MechanismHandler ) ldapSession.getSaslProperty( SaslConstants.SASL_MECH_HANDLER );

        if ( handler != null )
        {
            handler.cleanup( ldapSession );
        }

        ldapSession.getIoSession().write( response );

        LOG.debug( "Returned SUCCESS message: {}.", response );
    }


    private void handleSaslAuthPending( LdapSession ldapSession, BindRequest bindRequest ) throws Exception
    {
        // First, check that we have the same mechanism
        String saslMechanism = bindRequest.getSaslMechanism();

        // The empty mechanism is also a request for a new Bind session
        if ( StringTools.isEmpty( saslMechanism )
            || !ldapSession.getSaslProperty( SaslConstants.SASL_MECH ).equals( saslMechanism ) )
        {
            sendAuthMethNotSupported( ldapSession, bindRequest );
            return;
        }

        // We have already received a first BindRequest, and sent back some challenge.
        // First, check if the mechanism is the same
        MechanismHandler mechanismHandler = handlers.get( saslMechanism );

        if ( mechanismHandler == null )
        {
            String message = I18n.err( I18n.ERR_161, saslMechanism );

            // Clear the saslProperties, and move to the anonymous state
            ldapSession.clearSaslProperties();
            ldapSession.setAnonymous();

            LOG.error( message );
            throw new IllegalArgumentException( message );
        }

        // Get the previously created SaslServer instance
        SaslServer ss = mechanismHandler.handleMechanism( ldapSession, bindRequest );

        generateSaslChallengeOrComplete( ldapSession, ss, bindRequest );
    }


    /**
     * Handle the SASL authentication. If the mechanism is known, we are
     * facing three cases :
     * <ul>
     * <li>The user does not has a session yet</li>
     * <li>The user already has a session</li>
     * <li>The user has started a SASL negotiation</li>
     * </lu><br/>
     * 
     * In the first case, we initiate a SaslBind session, which will be used all
     * along the negotiation.<br/>
     * In the second case, we first have to unbind the user, and initiate a new
     * SaslBind session.<br/>
     * In the third case, we have sub cases :
     * <ul>
     * <li>The mechanism is not provided : that means the user want to reset the
     * current negotiation. We move back to an Anonymous state</li>
     * <li>The mechanism is provided : the user is initializing a new negotiation
     * with another mechanism. The current SaslBind session is reinitialized</li>
     * <li></li>
     * </ul><br/>
     *
     * @param ldapSession The associated Session
     * @param bindRequest The BindRequest received
     * @throws Exception If the authentication cannot be done
     */
    public void handleSaslAuth( LdapSession ldapSession, BindRequest bindRequest ) throws Exception
    {
        String saslMechanism = bindRequest.getSaslMechanism();

        // Case #2 : the user does have a session. We have to unbind him
        if ( ldapSession.isAuthenticated() )
        {
            // We already have a bound session for this user. We have to
            // close the previous session first.
            ldapSession.getCoreSession().unbind();

            // Reset the status to Anonymous
            ldapSession.setAnonymous();

            // Clean the sasl properties
            ldapSession.clearSaslProperties();

            // Now we can continue as if the client was Anonymous from the beginning
        }

        // case #1 : The user does not have a session.
        if ( ldapSession.isAnonymous() )
        {
            // fist check that the mechanism exists
            if ( !checkMechanism( saslMechanism ) )
            {
                // get out !
                sendAuthMethNotSupported( ldapSession, bindRequest );
                
                return;
            }
            
            // Store the mechanism in the ldap session
            ldapSession.putSaslProperty( SaslConstants.SASL_MECH, saslMechanism );
            
            // Get the handler for this mechanism
            MechanismHandler mechanismHandler = handlers.get( saslMechanism );
            
            // Store the mechanism handler in the salsProperties
            ldapSession.putSaslProperty( SaslConstants.SASL_MECH_HANDLER, mechanismHandler );
            
            // Initialize the mechanism specific data
            mechanismHandler.init( ldapSession );
            
            // Get the SaslServer instance which manage the C/R exchange
            SaslServer ss = mechanismHandler.handleMechanism( ldapSession, bindRequest );
            
            // We have to generate a challenge
            generateSaslChallengeOrComplete( ldapSession, ss, bindRequest );
            
            // And get back
            return;
        }
        else if ( ldapSession.isAuthPending() )
        {
            try
            {
                handleSaslAuthPending( ldapSession, bindRequest );
            }
            catch ( SaslException se )
            {
                sendInvalidCredentials( ldapSession, bindRequest, se );
            }

            return;
        }
    }


    /**
     * Deal with a received BindRequest
     * 
     * @param ldapSession The current session
     * @param bindRequest The received BindRequest
     * @throws Exception If the authentication cannot be handled
     */
    @Override
    public void handle( LdapSession ldapSession, BindRequest bindRequest ) throws Exception
    {
        LOG.debug( "Received: {}", bindRequest );

        // Guard clause:  LDAP version 3
        if ( !bindRequest.getVersion3() )
        {
            LOG.error( I18n.err( I18n.ERR_162 ) );
            LdapResult bindResult = bindRequest.getResultResponse().getLdapResult();
            bindResult.setResultCode( ResultCodeEnum.PROTOCOL_ERROR );
            bindResult.setErrorMessage( I18n.err( I18n.ERR_163 ) );
            ldapSession.getIoSession().write( bindRequest.getResultResponse() );
            return;
        }

        // Deal with the two kinds of authentication : Simple and SASL
        if ( bindRequest.isSimple() )
        {
            handleSimpleAuth( ldapSession, bindRequest );
        }
        else
        {
            handleSaslAuth( ldapSession, bindRequest );
        }
    }
}
