/*
 *  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.operations.extended;


import static org.apache.directory.server.core.integ.IntegrationUtils.getAdminNetworkConnection;
import static org.apache.directory.server.core.integ.IntegrationUtils.getAnonymousNetworkConnection;
import static org.apache.directory.server.core.integ.IntegrationUtils.getNetworkConnectionAs;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicyErrorEnum;
import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicyResponse;
import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicyResponseImpl;
import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyRequest;
import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyRequestImpl;
import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyResponse;
import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants;
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.entry.Attribute;
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.exception.LdapAuthenticationException;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.message.AddRequest;
import org.apache.directory.api.ldap.model.message.AddRequestImpl;
import org.apache.directory.api.ldap.model.message.AddResponse;
import org.apache.directory.api.ldap.model.message.Control;
import org.apache.directory.api.ldap.model.message.Response;
import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.api.ldap.model.password.PasswordUtil;
import org.apache.directory.api.util.Strings;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.server.annotations.CreateLdapServer;
import org.apache.directory.server.annotations.CreateTransport;
import org.apache.directory.server.core.annotations.CreateDS;
import org.apache.directory.server.core.api.InterceptorEnum;
import org.apache.directory.server.core.api.authn.ppolicy.CheckQualityEnum;
import org.apache.directory.server.core.api.authn.ppolicy.PasswordPolicyConfiguration;
import org.apache.directory.server.core.authn.AuthenticationInterceptor;
import org.apache.directory.server.core.authn.ppolicy.PpolicyConfigContainer;
import org.apache.directory.server.core.hash.Sha512PasswordHashingInterceptor;
import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
import org.apache.directory.server.core.integ.FrameworkRunner;
import org.apache.directory.server.ldap.handlers.extended.PwdModifyHandler;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;


/**
 * Test the PwdModify extended operation
 * 
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
@RunWith(FrameworkRunner.class)
@CreateLdapServer(
    transports =
        { @CreateTransport(protocol = "LDAP") },
    extendedOpHandlers =
        { PwdModifyHandler.class },
    allowAnonymousAccess = true)
//disable changelog, for more info see DIRSERVER-1528
@CreateDS(enableChangeLog = false, name = "PasswordPolicyTest", additionalInterceptors =
    { Sha512PasswordHashingInterceptor.class })
//@Ignore
public class PwdModifyIT extends AbstractLdapTestUnit
{
    private static final PasswordPolicyResponse PP_REQ_CTRL = new PasswordPolicyResponseImpl();

    /** The passwordPolicy configuration */
    private PasswordPolicyConfiguration policyConfig;


    /**
     * Get the PasswordPolicy control from a response
     */
    private PasswordPolicyResponse getPwdRespCtrl( Response resp ) throws Exception
    {
        Control control = resp.getControls().get( PP_REQ_CTRL.getOid() );

        if ( control == null )
        {
            return null;
        }

        return ( PasswordPolicyResponse ) control;
    }


    /**
     * Add a user with a password
     */
    private void addUser( LdapConnection adminConnection, String user, Object password ) throws Exception
    {
        Entry userEntry = new DefaultEntry(
            "cn=" + user + ",ou=system",
            "ObjectClass: top",
            "ObjectClass: person",
            "cn", user,
            "sn", user + "_sn",
            "userPassword", password );

        AddRequest addRequest = new AddRequestImpl();
        addRequest.setEntry( userEntry );
        addRequest.addControl( PP_REQ_CTRL );

        AddResponse addResp = adminConnection.add( addRequest );
        assertEquals( ResultCodeEnum.SUCCESS, addResp.getLdapResult().getResultCode() );
        PasswordPolicyResponse respCtrl = getPwdRespCtrl( addResp );
        assertNull( respCtrl );
    }


    /**
     * Check that we can bind N times with a user/password
     */
    private void checkBind( LdapConnection connection, Dn userDn, String password, int nbIterations,
        String expectedMessage ) throws Exception
    {
        for ( int i = 0; i < nbIterations; i++ )
        {
            try
            {
                connection.bind( userDn, password );
            }
            catch ( LdapAuthenticationException le )
            {
                assertEquals( expectedMessage, le.getMessage() );
            }
        }
    }


    private void safeCloseConnections( LdapConnection... connections )
    {
        for ( LdapConnection connection : connections )
        {
            if ( connection != null )
            {
                try
                {
                    connection.close();
                }
                catch ( Exception e )
                {
                    // may wanna log a message or something
                }
            }
        }
    }


    /**
     * Set a default PaswordPolicy configuration
     */
    @Before
    public void setPwdPolicy() throws LdapException
    {
        policyConfig = new PasswordPolicyConfiguration();

        policyConfig.setPwdMaxAge( 110 );
        policyConfig.setPwdFailureCountInterval( 30 );
        policyConfig.setPwdMaxFailure( 3 );
        policyConfig.setPwdLockout( true );
        policyConfig.setPwdLockoutDuration( 0 );
        policyConfig.setPwdMinLength( 5 );
        policyConfig.setPwdInHistory( 5 );
        policyConfig.setPwdExpireWarning( 600 );
        policyConfig.setPwdGraceAuthNLimit( 5 );
        policyConfig.setPwdCheckQuality( CheckQualityEnum.CHECK_REJECT ); // DO NOT allow the password if its quality can't be checked

        PpolicyConfigContainer policyContainer = new PpolicyConfigContainer();
        Dn defaultPolicyDn = new Dn( ldapServer.getDirectoryService().getSchemaManager(), "cn=default" );
        policyContainer.addPolicy( defaultPolicyDn, policyConfig );
        policyContainer.setDefaultPolicyDn( defaultPolicyDn );
        
        AuthenticationInterceptor authenticationInterceptor = ( AuthenticationInterceptor ) getService()
            .getInterceptor( InterceptorEnum.AUTHENTICATION_INTERCEPTOR.getName() );

        authenticationInterceptor.setPwdPolicies( policyContainer );
    }


    /**
     * Modify an existing user password while the user is connected
     */
    @Test
    public void testModifyOwnPasswordConnected() throws Exception
    {
        LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() );

        addUser( adminConnection, "User1", "secret1" );

        // Bind as the user
        LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), "cn=user1,ou=system", "secret1" );

        // Now change the password
        PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl();
        pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret1Bis" ) );

        // Send the request
        PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) userConnection.extended( pwdModifyRequest );

        assertEquals( ResultCodeEnum.SUCCESS, pwdModifyResponse.getLdapResult().getResultCode() );

        // Now try to bind with the new password
        userConnection = getNetworkConnectionAs( ldapServer, "cn=User1,ou=system", "secret1Bis" );

        Entry entry = userConnection.lookup( "cn=User1,ou=system" );

        assertNotNull( entry );

        userConnection.close();
        adminConnection.close();
    }


    /**
     * Modify an existing user password while the user is not connected
     */
    @Test
    public void testModifyUserPasswordAnonymous() throws Exception
    {
        LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() );

        addUser( adminConnection, "User2", "secret2" );

        LdapConnection userConnection = getNetworkConnectionAs( ldapServer, "cn=User2,ou=system", "secret2" );

        Entry entry = userConnection.lookup( "cn=User2,ou=system" );

        assertNotNull( entry );

        userConnection.close();

        // Bind as the user
        LdapConnection anonymousConnection = getAnonymousNetworkConnection( getLdapServer() );

        // Now change the password
        PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl();
        pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User2,ou=system" ) );
        pwdModifyRequest.setOldPassword( Strings.getBytesUtf8( "secret2" ) );
        pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret2Bis" ) );

        // Send the request
        PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) anonymousConnection.extended( pwdModifyRequest );

        assertEquals( ResultCodeEnum.SUCCESS, pwdModifyResponse.getLdapResult().getResultCode() );

        // Check that we can now bind using the new credentials
        userConnection = getNetworkConnectionAs( ldapServer, "cn=User2,ou=system", "secret2Bis" );

        entry = userConnection.lookup( "cn=User2,ou=system" );

        assertNotNull( entry );

        userConnection.close();
        anonymousConnection.close();
        adminConnection.close();
    }


    /**
     * Modify an existing user password while the user is not connected, when
     * the PasswordPolicy is activated
     */
    @Test
    public void testModifyUserPasswordAnonymousPPActivated() throws Exception
    {
        policyConfig.setPwdCheckQuality( CheckQualityEnum.CHECK_ACCEPT ); // allow the password if its quality can't be checked
        LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() );

        addUser( adminConnection, "User3", "secret3" );
        Dn userDn = new Dn( "cn=User3,ou=system" );

        LdapConnection userConnection = getNetworkConnectionAs( ldapServer, "cn=User3,ou=system", "secret3" );

        Entry entry = userConnection.lookup( "cn=User3,ou=system" );

        assertNotNull( entry );

        userConnection.close();

        // almost lock the user now
        checkBind( userConnection, userDn, "badPassword", 2,
            "INVALID_CREDENTIALS: Bind failed: ERR_229 Cannot authenticate user cn=User3,ou=system" );

        // Bind as the user
        LdapConnection anonymousConnection = getAnonymousNetworkConnection( getLdapServer() );

        // Now change the password
        PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl();
        pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User3,ou=system" ) );
        pwdModifyRequest.setOldPassword( Strings.getBytesUtf8( "secret3" ) );
        pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret3Bis" ) );

        // Send the request
        PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) anonymousConnection.extended( pwdModifyRequest );

        assertEquals( ResultCodeEnum.SUCCESS, pwdModifyResponse.getLdapResult().getResultCode() );

        // Check that we can now bind using the new credentials
        userConnection = getNetworkConnectionAs( ldapServer, "cn=User3,ou=system", "secret3Bis" );

        entry = userConnection.lookup( "cn=User3,ou=system" );

        assertNotNull( entry );

        // almost lock the user now, the count should be reset
        checkBind( userConnection, userDn, "badPassword", 2,
            "INVALID_CREDENTIALS: Bind failed: ERR_229 Cannot authenticate user cn=User3,ou=system" );

        userConnection.close();
        anonymousConnection.close();
        adminConnection.close();
    }


    /**
     * Modify an existing user password with an admin account
     */
    @Test
    public void testAdminModifyPassword() throws Exception
    {
        LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() );

        addUser( adminConnection, "User4", "secret4" );

        // Modify the user with the admin account

        // Now change the password
        PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl();
        pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User4,ou=system" ) );
        pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret4Bis" ) );

        // Send the request
        PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) adminConnection.extended( pwdModifyRequest );

        assertEquals( ResultCodeEnum.SUCCESS, pwdModifyResponse.getLdapResult().getResultCode() );

        // Now try to bind with the new password
        LdapConnection userConnection = getNetworkConnectionAs( ldapServer, "cn=User4,ou=system", "secret4Bis" );

        Entry entry = userConnection.lookup( "cn=User4,ou=system" );

        assertNotNull( entry );

        userConnection.close();
        adminConnection.close();
    }


    /**
     * Modify an existing user password with a bad account
     */
    @Test
    public void testAdminModifyPasswordBadUser() throws Exception
    {
        LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() );

        addUser( adminConnection, "User5", "secret5" );

        // Modify the user with the admin account

        // Now change the password
        PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl();
        pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=baduser,ou=system" ) );
        pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret5Bis" ) );

        // Send the request
        PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) adminConnection.extended( pwdModifyRequest );

        assertEquals( ResultCodeEnum.NO_SUCH_OBJECT, pwdModifyResponse.getLdapResult().getResultCode() );
        
        assertEquals( "The entry does not exist, we can't modify its password", pwdModifyResponse.getLdapResult()
            .getDiagnosticMessage() );

        adminConnection.close();
    }


    /**
     * Test that the server generates a new password when required
     */
    @Test
    public void testAdminGenPassword() throws Exception
    {
        LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() );

        addUser( adminConnection, "User6", "secret6" );

        // Modify the user with the admin account

        // Now request a new password
        PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl();
        pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User6,ou=system" ) );

        // Send the request
        PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) adminConnection.extended( pwdModifyRequest );

        // We should not be allowed to do that, as the operation is not yet implemented
        assertEquals( ResultCodeEnum.UNWILLING_TO_PERFORM, pwdModifyResponse.getLdapResult().getResultCode() );

        adminConnection.close();
    }


    /**
     * Modify an existing user password with an admin account
     */
    @Test
    public void testModifyPasswordTooSoon() throws Exception
    {
        LdapConnection adminConnection = null;
        LdapConnection userConnection = null;
        int minAge = policyConfig.getPwdMinAge();
        try
        {
            policyConfig.setPwdMinAge( 1000 );

            adminConnection = getAdminNetworkConnection( getLdapServer() );
            addUser( adminConnection, "User7", "secret7" );
            Entry userEntry = adminConnection.lookup( "cn=User7,ou=system", "*", "+" );
            Attribute attribute = userEntry.get( "pwdHistory" );
            assertEquals( 1, attribute.size() );

            PasswordModifyRequest pwdModifyRequest = null;
            PasswordModifyResponse pwdModifyResponse = null;

            // Fail modify user with user account
            try
            {
                userConnection = getNetworkConnectionAs( getLdapServer(), "cn=User7,ou=system", "secret7" );
                pwdModifyRequest = new PasswordModifyRequestImpl();
                pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User7,ou=system" ) );
                pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret4Bis" ) );
                pwdModifyResponse = ( PasswordModifyResponse ) userConnection.extended( pwdModifyRequest );
                assertNotEquals( ResultCodeEnum.SUCCESS, pwdModifyResponse.getLdapResult().getResultCode() );
            }
            finally
            {
                safeCloseConnections( userConnection );
            }

            // Modify the user with the admin account
            pwdModifyRequest = new PasswordModifyRequestImpl();
            pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User7,ou=system" ) );
            pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret4Bis" ) );
            pwdModifyResponse = ( PasswordModifyResponse ) adminConnection.extended( pwdModifyRequest );
            assertEquals( ResultCodeEnum.SUCCESS, pwdModifyResponse.getLdapResult().getResultCode() );
            userEntry = adminConnection.lookup( "cn=User7,ou=system", "*", "+" );
            attribute = userEntry.get( "pwdHistory" );
            assertEquals( 2, attribute.size() );

            // Now try to bind with the new password
            userConnection = getNetworkConnectionAs( ldapServer, "cn=User7,ou=system", "secret4Bis" );
            Entry entry = userConnection.lookup( "cn=User7,ou=system" );

            assertNotNull( entry );
        }
        finally
        {
            policyConfig.setPwdMinAge( minAge );
            safeCloseConnections( userConnection, adminConnection );
        }
    }


    /**
     * Attempt to modify an existing user password and fail.  Then process the
     * password policy control from the response.
     */
    @Test
    public void testModifyUserPasswordWithPasswordPolicyControl() throws Exception
    {
        policyConfig.setPwdCheckQuality( CheckQualityEnum.CHECK_ACCEPT ); // allow the password if its quality can't be checked
        policyConfig.setPwdMinLength( 5 );
        policyConfig.setPwdMinAge( 5 );

        LdapConnection adminConnection = null;
        LdapConnection userConnection = null;
        try
        {
            adminConnection = getAdminNetworkConnection( getLdapServer() );
            addUser( adminConnection, "UserXY", "secret3" );
            Dn userDn = new Dn( "cn=UserXY,ou=system" );

            userConnection = getNetworkConnectionAs( ldapServer, userDn.toString(), "secret3" );
            PasswordPolicyResponse passwordPolicyRequestControl =
                new PasswordPolicyResponseImpl();
            PasswordModifyRequest selfPwdModifyRequest = new PasswordModifyRequestImpl();
            selfPwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( userDn.getNormName() ) );
            selfPwdModifyRequest.setOldPassword( Strings.getBytesUtf8( "secret3" ) );
            selfPwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "1234567" ) );
            selfPwdModifyRequest.addControl( passwordPolicyRequestControl );

            // Send the request to update own password
            PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) userConnection.extended( selfPwdModifyRequest );
            // passwordTooShort is a constraint violation
            assertEquals( ResultCodeEnum.CONSTRAINT_VIOLATION, pwdModifyResponse.getLdapResult().getResultCode() );
            Control passwordPolicyResponseControl = pwdModifyResponse
                .getControl( passwordPolicyRequestControl.getOid() );
            assertNotNull( passwordPolicyResponseControl );
            assertEquals( PasswordPolicyErrorEnum.PASSWORD_TOO_YOUNG,
                ( ( PasswordPolicyResponse ) passwordPolicyResponseControl )
                    .getPasswordPolicyError() );

            addUser( adminConnection, "UserZZ", "secret4" );
            Dn otherUserDn = new Dn( "cn=UserZZ,ou=system" );

            PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl();
            pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( otherUserDn.getNormName() ) );
            pwdModifyRequest.setOldPassword( Strings.getBytesUtf8( "secret4" ) );
            pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "1234567" ) );
            pwdModifyResponse = ( PasswordModifyResponse ) userConnection.extended( pwdModifyRequest );
            assertEquals( ResultCodeEnum.INSUFFICIENT_ACCESS_RIGHTS, pwdModifyResponse.getLdapResult().getResultCode() );
        }
        finally
        {
            adminConnection.close();
            userConnection.close();
        }
    }


    /**
     * Modify an existing user password while the user is connected and the password is stored as a hash
     */
    @Test
    public void testModifyPasswordStoredAsHash() throws Exception
    {
        LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() );

        byte[] password = Strings.getBytesUtf8( "secret1" );
        byte[] credHash = PasswordUtil.createStoragePassword( password, LdapSecurityConstants.HASH_METHOD_SHA256 );
        addUser( adminConnection, "User11", credHash );

        // Bind as the user
        LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), "cn=user11,ou=system", "secret1" );

        // Now change the password
        PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl();
        pwdModifyRequest.setOldPassword( password );
        pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret1Bis" ) );

        // Send the request
        PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) userConnection.extended( pwdModifyRequest );

        assertEquals( ResultCodeEnum.SUCCESS, pwdModifyResponse.getLdapResult().getResultCode() );

        // Now try to bind with the new password
        userConnection = getNetworkConnectionAs( ldapServer, "cn=User11,ou=system", "secret1Bis" );
        userConnection.loadSchema();

        Entry entry = userConnection.lookup( "cn=User11,ou=system", SchemaConstants.ALL_ATTRIBUTES_ARRAY );

        assertNotNull( entry );

        Attribute at = entry.get( SchemaConstants.USER_PASSWORD_AT );
        assertEquals( LdapSecurityConstants.HASH_METHOD_SHA512, PasswordUtil.findAlgorithm( at.getBytes() ) );

        userConnection.close();
        adminConnection.close();
    }
}
