This is an automated email from the ASF dual-hosted git repository. elecharny pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/directory-server.git commit d0da642874509312ea53092a8a3d65edd8095069 Author: emmanuel lecharny AuthorDate: Tue Sep 17 00:28:38 2019 +0200 Added a test for password modify --- .../extended/PwdModifyNoPPNoPasswordHashingIT.java | 1474 ++++++++++++++++++++ 1 file changed, 1474 insertions(+) diff --git a/server-integ/src/test/java/org/apache/directory/server/operations/extended/PwdModifyNoPPNoPasswordHashingIT.java b/server-integ/src/test/java/org/apache/directory/server/operations/extended/PwdModifyNoPPNoPasswordHashingIT.java new file mode 100644 index 0000000..1dd8a77 --- /dev/null +++ b/server-integ/src/test/java/org/apache/directory/server/operations/extended/PwdModifyNoPPNoPasswordHashingIT.java @@ -0,0 +1,1474 @@ +/* + * 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.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +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.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.ResultCodeEnum; +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.authn.AuthenticationInterceptor; +import org.apache.directory.server.core.authn.ppolicy.PpolicyConfigContainer; +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.Test; +import org.junit.runner.RunWith; + + +/** + * Test the PwdModify extended operation + * + * @author Apache Directory Project + */ +@RunWith(FrameworkRunner.class) +@CreateLdapServer( + transports = + { @CreateTransport(protocol = "LDAP") }, + extendedOpHandlers = + { PwdModifyHandler.class }, + allowAnonymousAccess = true) +@CreateDS(name = "PasswordPolicyTest") +public class PwdModifyNoPPNoPasswordHashingIT extends AbstractLdapTestUnit +{ + /** + * 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 ); + + AddResponse addResp = adminConnection.add( addRequest ); + assertEquals( ResultCodeEnum.SUCCESS, addResp.getLdapResult().getResultCode() ); + } + + + /** + * Add a user with no password + */ + private void addUserNoPassword( LdapConnection adminConnection, String user ) throws Exception + { + Entry userEntry = new DefaultEntry( + "cn=" + user + ",ou=system", + "ObjectClass: top", + "ObjectClass: person", + "cn", user, + "sn", user + "_sn" ); + + AddRequest addRequest = new AddRequestImpl(); + addRequest.setEntry( userEntry ); + + AddResponse addResp = adminConnection.add( addRequest ); + assertEquals( ResultCodeEnum.SUCCESS, addResp.getLdapResult().getResultCode() ); + } + + + /** + * Add a user with 2 passwords + */ + private void addUser2Passwords( LdapConnection adminConnection, String user, Object password1, Object password2 ) throws Exception + { + Entry userEntry = new DefaultEntry( + "cn=" + user + ",ou=system", + "ObjectClass: top", + "ObjectClass: person", + "cn", user, + "sn", user + "_sn", + "userPassword", password1, + "userPassword", password2 ); + + AddRequest addRequest = new AddRequestImpl(); + addRequest.setEntry( userEntry ); + + AddResponse addResp = adminConnection.add( addRequest ); + assertEquals( ResultCodeEnum.SUCCESS, addResp.getLdapResult().getResultCode() ); + } + + + //----------------------------------------------------------------------------------- + // Self password modification with one password + //----------------------------------------------------------------------------------- + /** + * Modify an existing user password while the user is connected: + * o the userIdentity is not provided + * o the old password is not provided + * o the new password is new + * o the entry has a userPassword attribute + * o the userPassword attribute contains only one value + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testModifyOwnPasswordNoOldNew() throws Exception + { + // Create a user + try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) ) + { + addUser( adminConnection, "User1", "secret1" ); + + // Bind as the user + try ( LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), "cn=user1,ou=system", "secret1" ) ) + { + Entry user = userConnection.lookup( "cn=user1,ou=system", "modifyTimestamp" ); + + // 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 + try ( LdapConnection newUserConnection = getNetworkConnectionAs( ldapServer, "cn=User1,ou=system", "secret1Bis" ) ) + { + Entry entry = newUserConnection.lookup( "cn=User1,ou=system", "userPassword", "modifyTimestamp" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 1, userPassword.size() ); + assertEquals( "secret1Bis", userPassword.getString() ); + assertNull( user.get( "modifyTimestamp" ) ); + assertNotNull( entry.get( "modifyTimestamp" ).getString() ); + } + } + } + } + + + /** + * Modify an existing user password while the user is connected: + * o the userIdentity is not provided + * o the old password is not provided + * o the new password exists + * o the entry has a userPassword attribute + * o the userPassword attribute contains only one value + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testModifyOwnPasswordNoOldNewExists() throws Exception + { + // Create a user + LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ); + + addUser( adminConnection, "User1", "secret1" ); + + // Bind as the user + LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), "cn=user1,ou=system", "secret1" ); + + Entry user = userConnection.lookup( "cn=user1,ou=system", "modifyTimestamp" ); + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret1" ) ); + + // 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", "secret1" ); + + Entry entry = userConnection.lookup( "cn=User1,ou=system", "userPassword", "modifyTimestamp" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 1, userPassword.size() ); + assertEquals( "secret1", userPassword.getString() ); + assertNull( user.get( "modifyTimestamp" ) ); + assertNull( entry.get( "modifyTimestamp" ) ); + + userConnection.close(); + adminConnection.close(); + } + + + /** + * Modify an existing user password while the user is connected: + * o the userIdentity is not provided + * o the old password is provided + * o the new password is new + * o the entry has a userPassword attribute + * o the userPassword attribute contains only one value + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testModifyOwnPasswordOldNew() throws Exception + { + // Create a user + 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.setOldPassword( Strings.getBytesUtf8( "secret1" ) ); + 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 ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 1, userPassword.size() ); + assertEquals( "secret1Bis", userPassword.getString() ); + + userConnection.close(); + adminConnection.close(); + } + + + /** + * Modify an existing user password while the user is connected: + * o the userIdentity is not provided + * o the old password is provided, but it's the wrong one + * o the new password is new + * o the entry has a userPassword attribute + * o the userPassword attribute contains only one value + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testModifyOwnPasswordInvalidOldNew() throws Exception + { + // Create a user + 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.setOldPassword( Strings.getBytesUtf8( "secret2" ) ); + pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret1Bis" ) ); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) userConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.INVALID_CREDENTIALS, pwdModifyResponse.getLdapResult().getResultCode() ); + + // Now try to bind with the new password. Should fail + try + { + userConnection = getNetworkConnectionAs( ldapServer, "cn=User1,ou=system", "secret1Bis" ); + fail(); + } + catch ( LdapAuthenticationException lae ) + { + // We are fine + } + + // Rebind with the original password + userConnection = getNetworkConnectionAs( ldapServer, "cn=User1,ou=system", "secret1" ); + + Entry entry = userConnection.lookup( "cn=User1,ou=system", "userPassword", "modifyTimestamp" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 1, userPassword.size() ); + assertEquals( "secret1", userPassword.getString() ); + + // The entry should not have been modified + assertFalse( entry.containsAttribute( "modifyTimestamp" ) ); + + userConnection.close(); + adminConnection.close(); + } + + + /** + * Modify an existing user password while the user is connected: + * o the userIdentity is not provided + * o the old password is provided + * o the new password is not provided + * o the entry has a userPassword attribute + * o the userPassword attribute contains only one value + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testModifyOwnPasswordOldNoNew() throws Exception + { + // Create a user + 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.setOldPassword( Strings.getBytesUtf8( "secret1" ) ); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) userConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.UNWILLING_TO_PERFORM, pwdModifyResponse.getLdapResult().getResultCode() ); + + // Rebind with the original password + userConnection = getNetworkConnectionAs( ldapServer, "cn=User1,ou=system", "secret1" ); + + Entry entry = userConnection.lookup( "cn=User1,ou=system", "userPassword", "modifyTimestamp" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 1, userPassword.size() ); + assertEquals( "secret1", userPassword.getString() ); + assertFalse( entry.containsAttribute( "modifyTimestamp" ) ); + + userConnection.close(); + adminConnection.close(); + } + + + /** + * Modify an existing user password while the user is connected: + * o the userIdentity is not provided + * o the old password is provided + * o the new password is already existing + * o the entry has a userPassword attribute + * o the userPassword attribute contains only one value + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testModifyOwnPasswordOldNewExists() throws Exception + { + // Create a user + 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.setOldPassword( Strings.getBytesUtf8( "secret1" ) ); + pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret1" ) ); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) userConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.SUCCESS, pwdModifyResponse.getLdapResult().getResultCode() ); + + // Rebind with the original password + userConnection = getNetworkConnectionAs( ldapServer, "cn=User1,ou=system", "secret1" ); + + Entry entry = userConnection.lookup( "cn=User1,ou=system" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 1, userPassword.size() ); + assertEquals( "secret1", userPassword.getString() ); + assertFalse( entry.containsAttribute( "modifyTimestamp" ) ); + + userConnection.close(); + adminConnection.close(); + } + + + /** + * Modify an existing user password while the user is connected: + * o the userIdentity is not provided + * o the old password is not provided + * o the new password is not provided + * o the entry has a userPassword attribute + * o the userPassword attribute contains only one value + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testModifyOwnPasswordNoOldNoNew() throws Exception + { + // Create a user + 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(); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) userConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.UNWILLING_TO_PERFORM, pwdModifyResponse.getLdapResult().getResultCode() ); + + // Rebind with the original password + userConnection = getNetworkConnectionAs( ldapServer, "cn=User1,ou=system", "secret1" ); + + Entry entry = userConnection.lookup( "cn=User1,ou=system" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 1, userPassword.size() ); + assertEquals( "secret1", userPassword.getString() ); + + userConnection.close(); + adminConnection.close(); + } + + + //----------------------------------------------------------------------------------- + // Self password modification with two passwords + //----------------------------------------------------------------------------------- + /** + * Modify an existing user password while the user is connected: + * o the userIdentity is not provided + * o the old password is not provided + * o the new password is not provided + * o the entry has a userPassword attribute + * o the userPassword attribute contains two values + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testModifyOwn2PasswordsNoOldNoNew() throws Exception + { + // Create a user + LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ); + + addUser2Passwords( adminConnection, "User1", "secret1", "other" ); + + // Bind as the user + LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), "cn=user1,ou=system", "secret1" ); + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) userConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.UNWILLING_TO_PERFORM, pwdModifyResponse.getLdapResult().getResultCode() ); + + // Rebind with the original password + userConnection = getNetworkConnectionAs( ldapServer, "cn=User1,ou=system", "secret1" ); + + Entry entry = userConnection.lookup( "cn=User1,ou=system" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 2, userPassword.size() ); + assertTrue( userPassword.contains( "secret1", "other" ) ); + + userConnection.close(); + adminConnection.close(); + } + + + /** + * Modify an existing user password while the user is connected: + * o the userIdentity is not provided + * o the old password is not provided + * o the new password is new + * o the entry has a userPassword attribute + * o the userPassword attribute contains two values + * + * At the end, we will have only one password remaining + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testModifyOwn2PassworsdNoOldNew() throws Exception + { + // Create a user + LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ); + + addUser2Passwords( adminConnection, "User1", "secret1", "other" ); + + // Bind as the user + LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), "cn=user1,ou=system", "secret1" ); + + Entry user = userConnection.lookup( "cn=user1,ou=system", "modifyTimestamp" ); + + // 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", "userPassword", "modifyTimestamp" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 1, userPassword.size() ); + assertEquals( "secret1Bis", userPassword.getString() ); + assertNull( user.get( "modifyTimestamp" ) ); + assertNotNull( entry.get( "modifyTimestamp" ).getString() ); + + userConnection.close(); + adminConnection.close(); + } + + + /** + * Modify an existing user password while the user is connected: + * o the userIdentity is not provided + * o the old password is not provided + * o the new password exists + * o the entry has a userPassword attribute + * o the userPassword attribute contains two values + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testModifyOwn2PasswordsNoOldNewExists() throws Exception + { + // Create a user + LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ); + + addUser2Passwords( adminConnection, "User1", "secret1", "other" ); + + // Bind as the user + LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), "cn=user1,ou=system", "secret1" ); + + Entry user = userConnection.lookup( "cn=user1,ou=system", "modifyTimestamp" ); + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret1" ) ); + + // 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", "secret1" ); + + Entry entry = userConnection.lookup( "cn=User1,ou=system", "userPassword", "modifyTimestamp" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 2, userPassword.size() ); + assertTrue( userPassword.contains( "secret1", "other" ) ); + assertNull( user.get( "modifyTimestamp" ) ); + assertNull( entry.get( "modifyTimestamp" ) ); + + userConnection.close(); + adminConnection.close(); + } + + + /** + * Modify an existing user password while the user is connected: + * o the userIdentity is not provided + * o the old password is provided + * o the new password is new + * o the entry has a userPassword attribute + * o the userPassword attribute contains two values + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testModifyOwn2PasswordsOldNew() throws Exception + { + // Create a user + LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ); + + addUser2Passwords( adminConnection, "User1", "secret1", "other" ); + + // Bind as the user + LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), "cn=user1,ou=system", "secret1" ); + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setOldPassword( Strings.getBytesUtf8( "secret1" ) ); + 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 ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 1, userPassword.size() ); + assertEquals( "secret1Bis", userPassword.getString() ); + + userConnection.close(); + adminConnection.close(); + } + + + /** + * Modify an existing user password while the user is connected: + * o the userIdentity is not provided + * o the old password is provided, but it's the wrong one + * o the new password is new + * o the entry has a userPassword attribute + * o the userPassword attribute contains two values + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testModifyOwn2PasswordsInvalidOldNew() throws Exception + { + // Create a user + LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ); + + addUser2Passwords( adminConnection, "User1", "secret1", "other" ); + + // Bind as the user + LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), + "cn=user1,ou=system", "secret1" ); + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setOldPassword( Strings.getBytesUtf8( "secret2" ) ); + pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret1Bis" ) ); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) userConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.INVALID_CREDENTIALS, pwdModifyResponse.getLdapResult().getResultCode() ); + + // Now try to bind with the new password. Should fail + try + { + userConnection = getNetworkConnectionAs( ldapServer, "cn=User1,ou=system", "secret1Bis" ); + fail(); + } + catch ( LdapAuthenticationException lae ) + { + // We are fine + } + + // Rebind with the original password + userConnection = getNetworkConnectionAs( ldapServer, "cn=User1,ou=system", "secret1" ); + + Entry entry = userConnection.lookup( "cn=User1,ou=system", "userPassword", "modifyTimestamp" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 2, userPassword.size() ); + assertTrue( userPassword.contains( "secret1", "other" ) ); + + // The entry should not have been modified + assertFalse( entry.containsAttribute( "modifyTimestamp" ) ); + + userConnection.close(); + adminConnection.close(); + } + + + /** + * Modify an existing user password while the user is connected: + * o the userIdentity is not provided + * o the old password is provided + * o the new password is not provided + * o the entry has a userPassword attribute + * o the userPassword attribute contains two values + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testModifyOwn2PasswordsOldNoNew() throws Exception + { + // Create a user + LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ); + + addUser2Passwords( adminConnection, "User1", "secret1", "other" ); + + // Bind as the user + LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), "cn=user1,ou=system", "secret1" ); + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setOldPassword( Strings.getBytesUtf8( "secret1" ) ); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) userConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.UNWILLING_TO_PERFORM, pwdModifyResponse.getLdapResult().getResultCode() ); + + // Rebind with the original password + userConnection = getNetworkConnectionAs( ldapServer, "cn=User1,ou=system", "secret1" ); + + Entry entry = userConnection.lookup( "cn=User1,ou=system", "userPassword", "modifyTimestamp" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 2, userPassword.size() ); + assertTrue( userPassword.contains( "secret1", "other" ) ); + assertFalse( entry.containsAttribute( "modifyTimestamp" ) ); + + userConnection.close(); + adminConnection.close(); + } + + + /** + * Modify an existing user password while the user is connected: + * o the userIdentity is not provided + * o the old password is provided + * o the new password is already existing + * o the entry has a userPassword attribute + * o the userPassword attribute contains two values + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testModifyOwn2PasswordsOldNewExists() throws Exception + { + // Create a user + LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ); + + addUser2Passwords( adminConnection, "User1", "secret1", "other" ); + + // Bind as the user + LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), "cn=user1,ou=system", "secret1" ); + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setOldPassword( Strings.getBytesUtf8( "secret1" ) ); + pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret1" ) ); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) userConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.SUCCESS, pwdModifyResponse.getLdapResult().getResultCode() ); + + // Rebind with the original password + userConnection = getNetworkConnectionAs( ldapServer, "cn=User1,ou=system", "secret1" ); + + Entry entry = userConnection.lookup( "cn=User1,ou=system" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 2, userPassword.size() ); + assertTrue( userPassword.contains( "secret1", "other" ) ); + assertFalse( entry.containsAttribute( "modifyTimestamp" ) ); + + userConnection.close(); + adminConnection.close(); + } + + + //----------------------------------------------------------------------------------- + // Non connected user + //----------------------------------------------------------------------------------- + /** + * 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(); + + // Anonymous Bind + 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(); + } + + + /** + * Test that the server refuse to generate a password + */ + @Test + public void testOwnGenPassword() throws Exception + { + LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ); + + addUser( adminConnection, "User6", "secret6" ); + + // Modify the user with the user account + LdapConnection userConnection = getNetworkConnectionAs( ldapServer, "cn=User6,ou=system", "secret6" ); + + // Now request a new password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User6,ou=system" ) ); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) userConnection.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() ); + + userConnection.close(); + adminConnection.close(); + } + + + //----------------------------------------------------------------------------------- + // With admin + //----------------------------------------------------------------------------------- + /** + * Modify an existing user password with an admin account + */ + @Test + public void testAdminModifyPassword() throws Exception + { + try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) ) + { + addUserNoPassword( adminConnection, "User4" ); + + // Modify the user with the admin account + Entry entry = adminConnection.lookup( "cn=User4,ou=system" ); + + assertNotNull( entry ); + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User4,ou=system" ) ); + pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret4" ) ); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) adminConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.UNWILLING_TO_PERFORM, pwdModifyResponse.getLdapResult().getResultCode() ); + + // Now try to bind with the new password + try( LdapConnection userConnection = getNetworkConnectionAs( ldapServer, "cn=User4,ou=system", "secret4" )) + { + fail(); + } + catch ( LdapException le ) + { + // expected + } + + entry = adminConnection.lookup( "cn=User4,ou=system", SchemaConstants.ALL_ATTRIBUTES_ARRAY ); + + assertNotNull( entry ); + assertFalse( entry.containsAttribute( "userPassword" ) ); + assertFalse( entry.containsAttribute( "modifyTimestamp" ) ); + } + } + + + /** + * Modify an existing user password with admin + * o the userIdentity is provided + * o the old password is not provided + * o the new password is not provided + * o the entry has a userPassword attribute + * o the userPassword attribute contains only one value + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testAdminModifyPasswordNoOldNoNew() throws Exception + { + // Create a user + LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ); + + addUser( adminConnection, "User1", "secret1" ); + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User1,ou=system" ) ); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) adminConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.UNWILLING_TO_PERFORM, pwdModifyResponse.getLdapResult().getResultCode() ); + + Entry entry = adminConnection.lookup( "cn=User1,ou=system", "userPassword", "modifyTimestamp" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 1, userPassword.size() ); + assertEquals( "secret1", userPassword.getString() ); + assertFalse( entry.containsAttribute( "modifyTimestamp" ) ); + + adminConnection.close(); + } + + + /** + * Modify an existing user password with admin + * o the userIdentity is provided + * o the old password is not provided + * o the new password is provided + * o the entry has a userPassword attribute + * o the userPassword attribute contains only one value + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testAdminModifyPasswordNoOldNew() throws Exception + { + // Create a user + try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) ) + { + addUser( adminConnection, "User1", "secret1" ); + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User1,ou=system" ) ); + pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret1Bis" ) ); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) adminConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.SUCCESS, pwdModifyResponse.getLdapResult().getResultCode() ); + + try ( LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), + "cn=user1,ou=system", "secret1Bis" ) ) + { + Entry entry = userConnection.lookup( "cn=User1,ou=system", "userPassword", "modifyTimestamp" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 1, userPassword.size() ); + assertEquals( "secret1Bis", userPassword.getString() ); + assertTrue( entry.containsAttribute( "modifyTimestamp" ) ); + } + } + } + + + /** + * Modify an existing user with no password with admin + * o the userIdentity is provided + * o the old password is not provided + * o the new password is provided + * o the entry does not have a userPassword attribute + * o the userPassword attribute contains only one value + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testAdminAddPasswordNoOldNew() throws Exception + { + // Create a user + try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) ) + { + addUserNoPassword( adminConnection, "User1" ); + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User1,ou=system" ) ); + pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret1" ) ); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) adminConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.UNWILLING_TO_PERFORM, pwdModifyResponse.getLdapResult().getResultCode() ); + + try ( LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), + "cn=user1,ou=system", "secret1" ) ) + { + fail(); + } + catch ( LdapException le ) + { + // expected + } + + Entry entry = adminConnection.lookup( "cn=User1,ou=system", "userPassword", "modifyTimestamp" ); + + assertNotNull( entry ); + assertFalse( entry.containsAttribute( "userPassword" ) ); + assertFalse( entry.containsAttribute( "modifyTimestamp" ) ); + } + } + + + /** + * Modify an existing user password with admin + * o the userIdentity is provided + * o the old password is provided but is invalid + * o the new password is provided + * o the entry has a userPassword attribute + * o the userPassword attribute contains only one value + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testAdminModifyPasswordInvalidOldNew() throws Exception + { + // Create a user + try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) ) + { + addUser( adminConnection, "User1", "secret1" ); + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User1,ou=system" ) ); + pwdModifyRequest.setOldPassword( Strings.getBytesUtf8( "secret2" ) ); + pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret2" ) ); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) adminConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.INVALID_CREDENTIALS, pwdModifyResponse.getLdapResult().getResultCode() ); + + Entry entry = adminConnection.lookup( "cn=User1,ou=system", "userPassword", "modifyTimestamp" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 1, userPassword.size() ); + assertEquals( "secret1", userPassword.getString() ); + assertFalse( entry.containsAttribute( "modifyTimestamp" ) ); + } + } + + + /** + * Modify an existing user password with admin + * o the userIdentity is provided + * o the old password is not provided + * o the new password is provided but already exist + * o the entry has a userPassword attribute + * o the userPassword attribute contains only one value + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testAdminModifyPasswordNoOldNewExists() throws Exception + { + // Create a user + try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) ) + { + addUser( adminConnection, "User1", "secret1" ); + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User1,ou=system" ) ); + pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret1" ) ); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) adminConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.SUCCESS, pwdModifyResponse.getLdapResult().getResultCode() ); + + try ( LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), + "cn=user1,ou=system", "secret1" ) ) + { + Entry entry = userConnection.lookup( "cn=User1,ou=system", "userPassword", "modifyTimestamp" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 1, userPassword.size() ); + assertEquals( "secret1", userPassword.getString() ); + assertFalse( entry.containsAttribute( "modifyTimestamp" ) ); + } + } + } + + + /** + * Modify an existing user password with admin + * o the userIdentity is provided + * o the old password is provided + * o the new password is provided + * o the entry has a userPassword attribute + * o the userPassword attribute contains only one value + * + * At the same time, PP and passwordHashing interceptor are disable + */ + @Test + public void testAdminModifyPasswordOldNew() throws Exception + { + // Create a user + try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) ) + { + addUser( adminConnection, "User1", "secret1" ); + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User1,ou=system" ) ); + pwdModifyRequest.setOldPassword( Strings.getBytesUtf8( "secret1" ) ); + pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret1Bis" ) ); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) adminConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.SUCCESS, pwdModifyResponse.getLdapResult().getResultCode() ); + + try ( LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), + "cn=user1,ou=system", "secret1Bis" ) ) + { + Entry entry = userConnection.lookup( "cn=User1,ou=system", SchemaConstants.ALL_ATTRIBUTES_ARRAY ); + + System.out.println( entry ); + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 1, userPassword.size() ); + assertEquals( "secret1Bis", userPassword.getString() ); + assertTrue( entry.containsAttribute( "modifyTimestamp" ) ); + } + } + } + + + /** + * Modify an existing user password with admin + * o the userIdentity is provided + * o the old password is provided + * o the new password is not provided + * o the entry has a userPassword attribute + * o the userPassword attribute contains only one value + * + * At the same time, PP and passwordHashing interceptor are disable + */ + @Test + public void testAdminModifyPasswordOldNoNew() throws Exception + { + // Create a user + try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) ) + { + addUser( adminConnection, "User1", "secret1" ); + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User1,ou=system" ) ); + pwdModifyRequest.setOldPassword( Strings.getBytesUtf8( "secret1" ) ); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) adminConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.UNWILLING_TO_PERFORM, pwdModifyResponse.getLdapResult().getResultCode() ); + + try ( LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), + "cn=user1,ou=system", "secret1" ) ) + { + Entry entry = userConnection.lookup( "cn=User1,ou=system", SchemaConstants.ALL_ATTRIBUTES_ARRAY ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 1, userPassword.size() ); + assertEquals( "secret1", userPassword.getString() ); + assertFalse( entry.containsAttribute( "modifyTimestamp" ) ); + } + } + } + + + /** + * Modify an existing user password with admin + * o the userIdentity is provided + * o the old password is provided + * o the new password is provided + * o the entry has a userPassword attribute + * o the userPassword attribute contains only one value + * + * At the same time, PP and passwordHashing interceptor are disabled + */ + @Test + public void testAdminModifyPasswordOldNewExists() throws Exception + { + // Create a user + try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) ) + { + addUser( adminConnection, "User1", "secret1" ); + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User1,ou=system" ) ); + pwdModifyRequest.setOldPassword( Strings.getBytesUtf8( "secret1" ) ); + pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret1" ) ); + + // Send the request + PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) adminConnection.extended( pwdModifyRequest ); + + assertEquals( ResultCodeEnum.SUCCESS, pwdModifyResponse.getLdapResult().getResultCode() ); + + try ( LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), + "cn=user1,ou=system", "secret1" ) ) + { + Entry entry = userConnection.lookup( "cn=User1,ou=system", "userPassword", "modifyTimestamp" ); + + assertNotNull( entry ); + assertTrue( entry.containsAttribute( "userPassword" ) ); + Attribute userPassword = entry.get( "userPassword" ); + + assertNull( PasswordUtil.findAlgorithm( userPassword.getBytes() ) ); + + assertEquals( 1, userPassword.size() ); + assertEquals( "secret1", userPassword.getString() ); + assertFalse( entry.containsAttribute( "modifyTimestamp" ) ); + } + } + } + + + /** + * Modify an existing user password with an admin account + */ + @Test + public void testAdminModifyMultiplePassword() throws Exception + { + AuthenticationInterceptor authenticationInterceptor = ( AuthenticationInterceptor ) getService() + .getInterceptor( InterceptorEnum.AUTHENTICATION_INTERCEPTOR.getName() ); + + PpolicyConfigContainer policyContainer = authenticationInterceptor.getPwdPolicyContainer(); + authenticationInterceptor.setPwdPolicies( null ); + + LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ); + + addUser2Passwords( adminConnection, "User5", "secret51", "secret52" ); + + // Modify the user with the admin account + + // Now change the password + PasswordModifyRequest pwdModifyRequest = new PasswordModifyRequestImpl(); + pwdModifyRequest.setUserIdentity( Strings.getBytesUtf8( "cn=User5,ou=system" ) ); + pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret5Bis" ) ); + + // 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=User5,ou=system", "secret5Bis" ); + + Entry entry = userConnection.lookup( "cn=User5,ou=system" ); + + assertNotNull( entry ); + + userConnection.close(); + adminConnection.close(); + authenticationInterceptor.setPwdPolicies( policyContainer ); + } + + + /** + * 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() ); + + adminConnection.close(); + } + + + /** + * Test that the server refuse to generate a password + */ + @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(); + } +}