You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2019/07/29 14:14:53 UTC
[directory-server] branch master updated: o Rewritten the
pwdModifyHandler to cover more corner cases o Added a full set of tests for
the PasswordModify extended request when the PPolicy is disabled and the
passwordHashing interceptor is not set o Added the getIoSession() method in
the DefaultCoreSession class
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
The following commit(s) were added to refs/heads/master by this push:
new 294813d o Rewritten the pwdModifyHandler to cover more corner cases o Added a full set of tests for the PasswordModify extended request when the PPolicy is disabled and the passwordHashing interceptor is not set o Added the getIoSession() method in the DefaultCoreSession class
294813d is described below
commit 294813d86dd88b291e37c663718061c45c7e8e05
Author: emmanuel lecharny <el...@apache.org>
AuthorDate: Mon Jul 29 16:14:26 2019 +0200
o Rewritten the pwdModifyHandler to cover more corner cases
o Added a full set of tests for the PasswordModify extended request when
the PPolicy is disabled and the passwordHashing interceptor is not set
o Added the getIoSession() method in the DefaultCoreSession class
---
.../server/core/shared/DefaultCoreSession.java | 11 +
.../ldap/handlers/extended/PwdModifyHandler.java | 448 +++--
.../server/operations/extended/PwdModifyIT.java | 2 +
.../extended/PwdModifyNoPPNoPasswordHashingIT.java | 1828 ++++++++++++++++++++
4 files changed, 2152 insertions(+), 137 deletions(-)
diff --git a/core-shared/src/main/java/org/apache/directory/server/core/shared/DefaultCoreSession.java b/core-shared/src/main/java/org/apache/directory/server/core/shared/DefaultCoreSession.java
index e1361d7..043b739 100644
--- a/core-shared/src/main/java/org/apache/directory/server/core/shared/DefaultCoreSession.java
+++ b/core-shared/src/main/java/org/apache/directory/server/core/shared/DefaultCoreSession.java
@@ -169,6 +169,17 @@ public class DefaultCoreSession implements CoreSession
/**
+ * Gets the IoSession from the CoreSession. This is only useful when the server is not embedded.
+ *
+ * @return ioSession The IoSession for this CoreSession
+ */
+ public IoSession getIoSession()
+ {
+ return ioSession;
+ }
+
+
+ /**
* Stores the IoSession into the CoreSession. This is only useful when the server is not embedded.
*
* @param ioSession The IoSession for this CoreSession
diff --git a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/PwdModifyHandler.java b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/PwdModifyHandler.java
index 16f02eb..7634ea4 100644
--- a/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/PwdModifyHandler.java
+++ b/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/PwdModifyHandler.java
@@ -30,12 +30,14 @@ import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyRes
import org.apache.directory.api.ldap.extras.extended.pwdModify.PasswordModifyResponseImpl;
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.DefaultAttribute;
import org.apache.directory.api.ldap.model.entry.DefaultModification;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.entry.Modification;
import org.apache.directory.api.ldap.model.entry.ModificationOperation;
import org.apache.directory.api.ldap.model.entry.Value;
import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
import org.apache.directory.api.ldap.model.exception.LdapOperationException;
import org.apache.directory.api.ldap.model.message.Control;
@@ -48,6 +50,7 @@ import org.apache.directory.api.util.Strings;
import org.apache.directory.server.core.api.CoreSession;
import org.apache.directory.server.core.api.DirectoryService;
import org.apache.directory.server.core.api.interceptor.context.BindOperationContext;
+import org.apache.directory.server.core.shared.DefaultCoreSession;
import org.apache.directory.server.ldap.ExtendedOperationHandler;
import org.apache.directory.server.ldap.LdapServer;
import org.apache.directory.server.ldap.LdapSession;
@@ -88,157 +91,355 @@ public class PwdModifyHandler implements ExtendedOperationHandler<PasswordModify
/**
* Modify the user's credentials.
+ *
+ * We will need to modify the userPassword attribute, accordingly to a few rules:
+ * - if the old password is present, we should verify it's valid. if not, we return an error
+ * - if the old password is absent, we are modifying the password of the current used.
+ * - if the new password is absent, we will return an error. The RFC says that we could
+ * generate a random password, but that would be dangerous to do so.
+ * - if the new password already exists, we simply return not changing anything
+ * - otherwise, we just remove the old password from the list of passwords (we may have
+ * more than one) and add the new password. This is done with a REPLACE operation (Modify)
*/
- private void modifyUserPassword( CoreSession userSession, IoSession ioPipe, Dn userDn, byte[] oldPassword, byte[] newPassword,
- PasswordModifyRequest req )
+ private void modifyUserPassword( CoreSession userSession, Entry userEntry, Dn userDn,
+ byte[] oldPassword, byte[] newPassword, PasswordModifyRequest req )
{
- // First, check that the user exists
- try
+ IoSession ioSession = ( ( DefaultCoreSession ) userSession ).getIoSession();
+
+ if ( newPassword == null )
{
- Entry userEntry = userSession.lookup( userDn, SchemaConstants.ALL_ATTRIBUTES_ARRAY );
-
- if ( userEntry == null )
- {
- LOG.error( "Cannot find an entry for DN {}", userDn );
- // We can't find the entry in the DIT
- ioPipe.write( new PasswordModifyResponseImpl(
- req.getMessageId(), ResultCodeEnum.NO_SUCH_OBJECT, "Cannot find an entry for DN " + userDn ) );
+ // We don't support password generation on ApacheDS
+ writeResult( ioSession, req, ResultCodeEnum.UNWILLING_TO_PERFORM,
+ "Cannot change a password for user " + userDn + ", exception : null new password" );
- return;
+ return;
+ }
+
+ // Get the user password attribute
+ Attribute userPassword = userEntry.get( SchemaConstants.USER_PASSWORD_AT );
+
+ if ( userPassword == null )
+ {
+ // We can't modify the password
+ writeResult( ioSession, req, ResultCodeEnum.UNWILLING_TO_PERFORM,
+ "Cannot change a password for user " + userDn + ", the user has no existing password" );
+
+ return;
+ }
+
+ if ( userPassword.contains( newPassword ) )
+ {
+ // Ok, we are done : just return success
+ PasswordModifyResponseImpl pmrl = new PasswordModifyResponseImpl(
+ req.getMessageId(), ResultCodeEnum.SUCCESS );
+
+ Control ppolicyControl = req.getControl( PasswordPolicyRequest.OID );
+
+ if ( ppolicyControl != null )
+ {
+ pmrl.addControl( ppolicyControl );
}
+
+ ioSession.write( pmrl );
+
+ return;
+ }
+
+ if ( oldPassword == null )
+ {
+ // We are modifying the password on behalf of another user. ACI will
+ // protect such modification if it's not allowed. In any case, we just
+ // modify the existing userPassword attribute, adding the password
+ ModifyRequest modifyRequest = new ModifyRequestImpl();
+ modifyRequest.setName( userDn );
+
+ Control ppolicyControl = req.getControl( PasswordPolicyRequest.OID );
- Attribute at = userEntry.get( SchemaConstants.USER_PASSWORD_AT );
+ if ( ppolicyControl != null )
+ {
+ modifyRequest.addControl( ppolicyControl );
+ }
- if ( ( oldPassword != null ) && ( at != null ) )
+ try
{
- for ( Value value : at )
+ Modification modification = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
+ userPassword.getAttributeType(), newPassword );
+
+ modifyRequest.addModification( modification );
+ ResultCodeEnum errorCode = null;
+ String errorMessage = null;
+
+ try
{
- byte[] bytes = value.getBytes();
- boolean equal = PasswordUtil.compareCredentials( oldPassword, bytes );
-
- if ( equal )
+ userSession.modify( modifyRequest );
+
+ if ( LOG.isDebugEnabled() )
{
- oldPassword = bytes;
+ LOG.debug( "Password modified for user {}", userDn );
}
- }
- }
- }
- catch ( LdapException le )
- {
- LOG.error( "Cannot find an entry for DN {}, exception : {}", userDn, le.getMessage() );
- // We can't find the entry in the DIT
- ioPipe.write(
- new PasswordModifyResponseImpl(
- req.getMessageId(), ResultCodeEnum.NO_SUCH_OBJECT, "Cannot find an entry for DN " + userDn ) );
- return;
- }
+ // Ok, all done
+ PasswordModifyResponseImpl pmrl = new PasswordModifyResponseImpl(
+ req.getMessageId(), ResultCodeEnum.SUCCESS );
- // We can try to update the userPassword now
- ModifyRequest modifyRequest = new ModifyRequestImpl();
- modifyRequest.setName( userDn );
+ ppolicyControl = modifyRequest.getResultResponse().getControl( PasswordPolicyRequest.OID );
- Control ppolicyControl = req.getControl( PasswordPolicyRequest.OID );
-
- if ( ppolicyControl != null )
- {
- modifyRequest.addControl( ppolicyControl );
- }
+ if ( ppolicyControl != null )
+ {
+ pmrl.addControl( ppolicyControl );
+ }
- Modification modification = null;
+ ioSession.write( pmrl );
- if ( oldPassword != null )
- {
- modification = new DefaultModification( ModificationOperation.REMOVE_ATTRIBUTE,
- SchemaConstants.USER_PASSWORD_AT, oldPassword );
+ return;
+ }
+ catch ( LdapOperationException loe )
+ {
+ errorCode = loe.getResultCode();
+ errorMessage = loe.getMessage();
+ }
+ catch ( LdapException le )
+ {
+ // this exception means something else must be wrong
+ errorCode = ResultCodeEnum.OTHER;
+ errorMessage = le.getMessage();
+ }
- modifyRequest.addModification( modification );
- }
+ // We can't modify the password
+ LOG.error( "Cannot modify the password for user {}, exception : {}", userDn, errorMessage );
+ PasswordModifyResponseImpl errorPmrl = new PasswordModifyResponseImpl(
+ req.getMessageId(), errorCode, "Cannot modify the password for user "
+ + userDn + ", exception : " + errorMessage );
- if ( newPassword != null )
- {
- if ( oldPassword == null )
- {
- modification = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
- SchemaConstants.USER_PASSWORD_AT, newPassword );
+ ppolicyControl = modifyRequest.getResultResponse().getControl( PasswordPolicyRequest.OID );
+
+ if ( ppolicyControl != null )
+ {
+ errorPmrl.addControl( ppolicyControl );
+ }
+
+ ioSession.write( errorPmrl );
+
+ return;
}
- else
+ catch ( LdapInvalidAttributeValueException liave )
{
- modification = new DefaultModification( ModificationOperation.ADD_ATTRIBUTE,
- SchemaConstants.USER_PASSWORD_AT, newPassword );
+ // Nothing to do, this will never be a problem
}
-
- modifyRequest.addModification( modification );
}
else
{
- // In this case, we could either generate a new password, or return an error
- // Atm, we will return an unwillingToPerform error
- LOG.error( "Cannot create a new password for user {}, exception : null new password", userDn );
+ // We are changing the password of the current user, check the password
+ boolean valid = false;
+ Attribute modifiedPassword = new DefaultAttribute( userPassword.getAttributeType() );
+
+ for ( Value value : userPassword )
+ {
+ if ( !valid )
+ {
+ valid = PasswordUtil.compareCredentials( oldPassword, value.getBytes() );
+ }
+
+ try
+ {
+ if ( valid )
+ {
+ modifiedPassword.add( newPassword );
+ }
+ else
+ {
+ modifiedPassword.add( value );
+ }
+ }
+ catch ( LdapInvalidAttributeValueException e )
+ {
+ // Nothing to do, this will never be a problem
+ }
+ }
+
+ // At this point, we have what is needed to modify the password, if the oldPassword
+ // was valid
+ if ( valid )
+ {
+ ModifyRequest modifyRequest = new ModifyRequestImpl();
+ modifyRequest.setName( userDn );
- // We can't modify the password
- ioPipe.write( new PasswordModifyResponseImpl(
- req.getMessageId(), ResultCodeEnum.UNWILLING_TO_PERFORM, "Cannot generate a new password for user "
- + userDn ) );
+ Control ppolicyControl = req.getControl( PasswordPolicyRequest.OID );
+
+ if ( ppolicyControl != null )
+ {
+ modifyRequest.addControl( ppolicyControl );
+ }
+
+ Modification modification = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
+ modifiedPassword );
- return;
- }
+ modifyRequest.addModification( modification );
- ResultCodeEnum errorCode = null;
- String errorMessage = null;
+ ResultCodeEnum errorCode = null;
+ String errorMessage = null;
- try
- {
- userSession.modify( modifyRequest );
+ try
+ {
+ userSession.modify( modifyRequest );
- if ( LOG.isDebugEnabled() )
- {
- LOG.debug( "Password modified for user {}", userDn );
- }
+ if ( LOG.isDebugEnabled() )
+ {
+ LOG.debug( "Password modified for user {}", userDn );
+ }
- // Ok, all done
- PasswordModifyResponseImpl pmrl = new PasswordModifyResponseImpl(
- req.getMessageId(), ResultCodeEnum.SUCCESS );
+ // Ok, all done
+ PasswordModifyResponseImpl pmrl = new PasswordModifyResponseImpl(
+ req.getMessageId(), ResultCodeEnum.SUCCESS );
- ppolicyControl = modifyRequest.getResultResponse().getControl( PasswordPolicyRequest.OID );
+ ppolicyControl = modifyRequest.getResultResponse().getControl( PasswordPolicyRequest.OID );
- if ( ppolicyControl != null )
+ if ( ppolicyControl != null )
+ {
+ pmrl.addControl( ppolicyControl );
+ }
+
+ ioSession.write( pmrl );
+
+ return;
+ }
+ catch ( LdapOperationException loe )
+ {
+ errorCode = loe.getResultCode();
+ errorMessage = loe.getMessage();
+ }
+ catch ( LdapException le )
+ {
+ // this exception means something else must be wrong
+ errorCode = ResultCodeEnum.OTHER;
+ errorMessage = le.getMessage();
+ }
+
+ // We can't modify the password
+ LOG.error( "Cannot modify the password for user {}, exception : {}", userDn, errorMessage );
+ PasswordModifyResponseImpl errorPmrl = new PasswordModifyResponseImpl(
+ req.getMessageId(), errorCode, "Cannot modify the password for user "
+ + userDn + ", exception : " + errorMessage );
+
+ ppolicyControl = modifyRequest.getResultResponse().getControl( PasswordPolicyRequest.OID );
+
+ if ( ppolicyControl != null )
+ {
+ errorPmrl.addControl( ppolicyControl );
+ }
+
+ ioSession.write( errorPmrl );
+
+ return;
+ }
+ else
{
- pmrl.addControl( ppolicyControl );
+ // Too bad, the old password is invalid
+ writeResult( ioSession, req, ResultCodeEnum.INVALID_CREDENTIALS,
+ "Cannot change a password for user " + userDn + ", invalid credentials" );
+
+ return;
}
+ }
+ }
- ioPipe.write( pmrl );
+
+ private void writeResult( LdapSession requestor, PasswordModifyRequest req, ResultCodeEnum error, String errorMessage )
+ {
+ writeResult( requestor.getIoSession(), req, error, errorMessage );
- return;
- }
- catch ( LdapOperationException loe )
+ }
+
+
+ private void writeResult( IoSession ioSession, PasswordModifyRequest req, ResultCodeEnum error, String errorMessage )
+ {
+ LOG.error( errorMessage );
+ ioSession.write( new PasswordModifyResponseImpl(
+ req.getMessageId(), error, errorMessage ) );
+
+ }
+
+
+ private Entry getModifiedEntry( LdapSession requestor, PasswordModifyRequest req, Dn entryDn )
+ {
+ try
{
- errorCode = loe.getResultCode();
- errorMessage = loe.getMessage();
+ Entry modifiedEntry = requestor.getCoreSession().lookup( entryDn, SchemaConstants.ALL_ATTRIBUTES_ARRAY );
+
+ if ( modifiedEntry == null )
+ {
+ // The entry does not exist, we can't modify its password
+ writeResult( requestor, req, ResultCodeEnum.NO_SUCH_OBJECT,
+ "The entry does not exist, we can't modify its password" );
+ return null;
+ }
+ else
+ {
+ return modifiedEntry;
+ }
}
- catch ( LdapException le )
+ catch ( Exception le )
{
- // this exception means something else must be wrong
- errorCode = ResultCodeEnum.OTHER;
- errorMessage = le.getMessage();
+ // The entry does not exist, we can't modify its password
+ writeResult( requestor, req, ResultCodeEnum.NO_SUCH_OBJECT,
+ "The entry does not exist, we can't modify its password" );
+ return null;
}
+ }
+
+
+ private void processAuthenticatedPasswordModify( LdapSession requestor, PasswordModifyRequest req,
+ Dn userDn )
+ {
+ byte[] oldPassword = req.getOldPassword();
+ byte[] newPassword = req.getNewPassword();
- // We can't modify the password
- LOG.error( "Cannot modify the password for user {}, exception : {}", userDn, errorMessage );
- PasswordModifyResponseImpl errorPmrl = new PasswordModifyResponseImpl(
- req.getMessageId(), errorCode, "Cannot modify the password for user "
- + userDn + ", exception : " + errorMessage );
-
- ppolicyControl = modifyRequest.getResultResponse().getControl( PasswordPolicyRequest.OID );
+ // We are already bound. Fetch the entry which we want to modify
+ Entry modifiedEntry = null;
+
+ Dn principalDn = requestor.getCoreSession().getEffectivePrincipal().getDn();
- if ( ppolicyControl != null )
+ LOG.debug( "User {} trying to modify password of user {}", principalDn, userDn );
+
+
+ // First, check that the userDn is null : we can't change the password of someone else
+ // except if we are admin
+ if ( ( userDn != null ) && ( !userDn.equals( principalDn ) ) )
{
- errorPmrl.addControl( ppolicyControl );
+ // Are we admin ?
+ if ( requestor.getCoreSession().isAdministrator() )
+ {
+ modifiedEntry = getModifiedEntry( requestor, req, userDn );
+
+ if ( modifiedEntry == null )
+ {
+ return;
+ }
+
+ // We are administrator, we can try to modify the user's credentials
+ modifyUserPassword( requestor.getCoreSession(), modifiedEntry, userDn, oldPassword, newPassword, req );
+ }
+ else
+ {
+ // No : error
+ writeResult( requestor, req, ResultCodeEnum.INSUFFICIENT_ACCESS_RIGHTS,
+ "Non-admin user cannot access another user's password to modify it" );
+ }
}
+ else
+ {
+ // We are trying to modify our own password
+ modifiedEntry = getModifiedEntry( requestor, req, principalDn );
- ioPipe.write( errorPmrl );
- }
+ if ( modifiedEntry == null )
+ {
+ return;
+ }
+ modifyUserPassword( requestor.getCoreSession(), modifiedEntry, principalDn, oldPassword, newPassword, req );
+ }
+ }
+
/**
* {@inheritDoc}
@@ -261,10 +462,10 @@ public class PwdModifyHandler implements ExtendedOperationHandler<PasswordModify
}
catch ( LdapInvalidDnException lide )
{
- LOG.error( "The user DN is invalid : {}", userDn );
// The userIdentity is not a DN : return with an error code.
- requestor.getIoSession().write( new PasswordModifyResponseImpl(
- req.getMessageId(), ResultCodeEnum.INVALID_DN_SYNTAX, "The user DN is invalid : " + userDn ) );
+ writeResult( requestor, req, ResultCodeEnum.INVALID_DN_SYNTAX,
+ "The user DN is invalid : " + userDn );
+
return;
}
}
@@ -275,34 +476,7 @@ public class PwdModifyHandler implements ExtendedOperationHandler<PasswordModify
// First check if the user is bound or not
if ( requestor.isAuthenticated() )
{
- Dn principalDn = requestor.getCoreSession().getEffectivePrincipal().getDn();
-
- LOG.debug( "User {} trying to modify password of user {}", principalDn, userDn );
-
- // First, check that the userDn is null : we can't change the password of someone else
- // except if we are admin
- if ( ( userDn != null ) && ( !userDn.equals( principalDn ) ) )
- {
- // Are we admin ?
- if ( !requestor.getCoreSession().isAdministrator() )
- {
- // No : error
- LOG.error( "Non-admin user cannot access another user's password to modify it" );
- requestor.getIoSession().write( new PasswordModifyResponseImpl(
- req.getMessageId(), ResultCodeEnum.INSUFFICIENT_ACCESS_RIGHTS,
- "Non-admin user cannot access another user's password to modify it" ) );
- }
- else
- {
- // We are administrator, we can try to modify the user's credentials
- modifyUserPassword( requestor.getCoreSession(), requestor.getIoSession(), userDn, oldPassword, newPassword, req );
- }
- }
- else
- {
- // We are trying to modify our own password
- modifyUserPassword( requestor.getCoreSession(), requestor.getIoSession(), principalDn, oldPassword, newPassword, req );
- }
+ processAuthenticatedPasswordModify( requestor, req, userDn );
}
else
{
@@ -328,7 +502,7 @@ public class PwdModifyHandler implements ExtendedOperationHandler<PasswordModify
// Ok, we were able to bind using the userIdentity and the password. Let's
// modify the password now
- modifyUserPassword( requestor.getCoreSession(), requestor.getIoSession(), userDn, oldPassword, newPassword, req );
+ modifyUserPassword( requestor.getCoreSession(), bindContext.getEntry(), userDn, oldPassword, newPassword, req );
}
}
diff --git a/server-integ/src/test/java/org/apache/directory/server/operations/extended/PwdModifyIT.java b/server-integ/src/test/java/org/apache/directory/server/operations/extended/PwdModifyIT.java
index 82d48f2..0ec2599 100644
--- a/server-integ/src/test/java/org/apache/directory/server/operations/extended/PwdModifyIT.java
+++ b/server-integ/src/test/java/org/apache/directory/server/operations/extended/PwdModifyIT.java
@@ -64,6 +64,7 @@ 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;
@@ -83,6 +84,7 @@ import org.junit.runner.RunWith;
//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();
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..29607d2
--- /dev/null
+++ b/server-integ/src/test/java/org/apache/directory/server/operations/extended/PwdModifyNoPPNoPasswordHashingIT.java
@@ -0,0 +1,1828 @@
+/*
+ * 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, when no PasswordPolicy or PasswordHashing interceptor
+ * are present.
+ *
+ * @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)
+@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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser( adminConnection, "User1", "secret1" );
+
+ // Bind as the user
+ Entry user;
+
+ try ( LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), "cn=user1,ou=system", "secret1" ) )
+ {
+ 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
+ try ( LdapConnection 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" ) );
+ }
+ }
+ }
+
+
+ /**
+ * 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser( adminConnection, "User1", "secret1" );
+
+ // Bind as the user
+ try ( 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
+ try ( LdapConnection 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() );
+ }
+ }
+ }
+
+
+ /**
+ * 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser( adminConnection, "User1", "secret1" );
+
+ // Bind as the user
+ try ( 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 ( LdapConnection userConnection = getNetworkConnectionAs( ldapServer, "cn=User1,ou=system", "secret1Bis" ) )
+ {
+
+ fail();
+ }
+ catch ( LdapAuthenticationException lae )
+ {
+ // We are fine
+ }
+
+ // Rebind with the original password
+ try ( LdapConnection 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" ) );
+ }
+ }
+ }
+
+
+ /**
+ * 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser( adminConnection, "User1", "secret1" );
+
+ // Bind as the user
+ try ( 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
+ try ( LdapConnection 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" ) );
+ }
+ }
+ }
+
+
+ /**
+ * 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser( adminConnection, "User1", "secret1" );
+
+ // Bind as the user
+ try ( 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
+ try ( LdapConnection 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" ) );
+ }
+ }
+ }
+
+
+ /**
+ * 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser( adminConnection, "User1", "secret1" );
+
+ // Bind as the user
+ try ( 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
+ try ( LdapConnection 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() );
+ }
+ }
+ }
+
+
+ //-----------------------------------------------------------------------------------
+ // 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser2Passwords( adminConnection, "User1", "secret1", "other" );
+
+ // Bind as the user
+ try ( 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
+ try ( LdapConnection 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" ) );
+ }
+ }
+ }
+
+
+ /**
+ * 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser2Passwords( adminConnection, "User1", "secret1", "other" );
+
+ // Bind as the user
+ Entry user;
+
+ try ( LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), "cn=user1,ou=system", "secret1" ) )
+ {
+ 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 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() );
+ }
+ }
+ }
+
+
+ /**
+ * 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser2Passwords( adminConnection, "User1", "secret1", "other" );
+
+ // Bind as the user
+ Entry user;
+
+ try ( LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), "cn=user1,ou=system", "secret1" ) )
+ {
+ 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
+ try ( LdapConnection 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" ) );
+ }
+ }
+ }
+
+
+ /**
+ * 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser2Passwords( adminConnection, "User1", "secret1", "other" );
+
+ // Bind as the user
+ try ( 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
+ try ( LdapConnection 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() );
+ }
+ }
+ }
+
+
+ /**
+ * 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser2Passwords( adminConnection, "User1", "secret1", "other" );
+
+ // Bind as the user
+ try ( 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 ( LdapConnection userConnection = getNetworkConnectionAs( ldapServer, "cn=User1,ou=system", "secret1Bis" ) )
+ {
+ fail();
+ }
+ catch ( LdapAuthenticationException lae )
+ {
+ // We are fine
+ }
+
+ // Rebind with the original password
+ try ( LdapConnection 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" ) );
+ }
+ }
+ }
+
+
+ /**
+ * 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser2Passwords( adminConnection, "User1", "secret1", "other" );
+
+ // Bind as the user
+ try ( 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
+ try ( LdapConnection 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" ) );
+ }
+ }
+ }
+
+
+ /**
+ * 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser2Passwords( adminConnection, "User1", "secret1", "other" );
+
+ // Bind as the user
+ try ( 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
+ try ( LdapConnection 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" ) );
+ }
+ }
+ }
+
+
+ //-----------------------------------------------------------------------------------
+ // Non connected user
+ //-----------------------------------------------------------------------------------
+ /**
+ * Modify an existing user password while the user is not connected
+ */
+ @Test
+ public void testModifyUserPasswordAnonymous() throws Exception
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser( adminConnection, "User2", "secret2" );
+
+ try ( LdapConnection userConnection = getNetworkConnectionAs( ldapServer, "cn=User2,ou=system", "secret2" ) )
+ {
+ Entry entry = userConnection.lookup( "cn=User2,ou=system" );
+
+ assertNotNull( entry );
+ }
+
+ // Anonymous Bind
+ try ( 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
+ try ( LdapConnection userConnection = getNetworkConnectionAs( ldapServer, "cn=User2,ou=system", "secret2Bis" ) )
+ {
+ Entry entry = userConnection.lookup( "cn=User2,ou=system" );
+
+ assertNotNull( entry );
+ }
+ }
+ }
+
+
+ /**
+ * Test that the server refuse to generate a password
+ */
+ @Test
+ public void testOwnGenPassword() throws Exception
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser( adminConnection, "User6", "secret6" );
+
+ // Modify the user with the user account
+ try ( 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() );
+ }
+ }
+ }
+
+
+ //-----------------------------------------------------------------------------------
+ // With admin
+ //-----------------------------------------------------------------------------------
+ /**
+ * Modify an existing user password with an admin account
+ */
+ @Test
+ public void testAdminModifyPassword() throws Exception
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ 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" ) );
+ }
+ }
+
+
+ /**
+ * 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ 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 );
+
+ 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ 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
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ 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" ) );
+ }
+ }
+ }
+ //-----------------------------------------------------------------------------------
+ // Admin password modification with two passwords
+ //-----------------------------------------------------------------------------------
+ /**
+ * Modify an existing user password with an admin account:
+ * 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 two values
+ *
+ * At the same time, PP and passwordHashing interceptor are disabled
+ */
+ @Test
+ public void testAdminPasswordModify2PasswordsNoOldNoNew() throws Exception
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser2Passwords( adminConnection, "User1", "secret1", "other" );
+
+ // 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() );
+
+ // Rebind with the original password
+ try ( LdapConnection 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" ) );
+ }
+ }
+ }
+
+
+ /**
+ * Modify an existing user password with an admin account:
+ * o the userIdentity is 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 testAdminPasswordModify2PassworsdNoOldNew() throws Exception
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser2Passwords( adminConnection, "User1", "secret1", "other" );
+
+ Entry user = adminConnection.lookup( "cn=User1,ou=system", "userPassword", "modifyTimestamp" );
+
+ // 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() );
+
+ // Now try to bind with the new password
+ try ( LdapConnection 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() );
+ assertFalse( user.containsAttribute( "modifyTimestamp" ) );
+ assertNotNull( entry.get( "modifyTimestamp" ).getString() );
+ }
+ }
+ }
+
+
+ /**
+ * Modify an existing user password with an admin account:
+ * o the userIdentity is 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 testAdminPasswordModify2PasswordsNoOldNewExists() throws Exception
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser2Passwords( adminConnection, "User1", "secret1", "other" );
+
+ Entry user = adminConnection.lookup( "cn=user1,ou=system", "modifyTimestamp" );
+
+ // 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() );
+
+ // Now try to bind with the new password
+ try ( LdapConnection 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" ) );
+ }
+ }
+ }
+
+
+ /**
+ * Modify an existing user password with an admin account:
+ * o the userIdentity is 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 testAdminPasswordModify2PasswordsOldNew() throws Exception
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser2Passwords( adminConnection, "User1", "secret1", "other" );
+
+ // 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() );
+
+ // Now try to bind with the new password
+ try ( LdapConnection 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() );
+ assertTrue( entry.containsAttribute( "modifyTimestamp" ) );
+ }
+ }
+ }
+
+
+ /**
+ * Modify an existing user password with an admin account:
+ * o the userIdentity is 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 testAdminPasswordModify2PasswordsInvalidOldNew() throws Exception
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser2Passwords( adminConnection, "User1", "secret1", "other" );
+
+ // 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( "secret1Bis" ) );
+
+ // Send the request
+ PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) adminConnection.extended( pwdModifyRequest );
+
+ assertEquals( ResultCodeEnum.INVALID_CREDENTIALS, pwdModifyResponse.getLdapResult().getResultCode() );
+
+ // Now try to bind with the new password. Should fail
+ try
+ {
+ try ( LdapConnection userConnection = getNetworkConnectionAs( ldapServer, "cn=User1,ou=system", "secret1Bis" ) )
+ {
+
+ }
+ fail();
+ }
+ catch ( LdapAuthenticationException lae )
+ {
+ // We are fine
+ }
+
+ // Rebind with the original password
+ try ( LdapConnection 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" ) );
+ }
+ }
+ }
+
+
+ /**
+ * Modify an existing user password with an admin account:
+ * 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 two values
+ *
+ * At the same time, PP and passwordHashing interceptor are disabled
+ */
+ @Test
+ public void testAdminPasswordModify2PasswordsOldNoNew() throws Exception
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser2Passwords( adminConnection, "User1", "secret1", "other" );
+
+ // 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() );
+
+ // Rebind with the original password
+ try ( LdapConnection 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" ) );
+ }
+ }
+ }
+
+
+ /**
+ * Modify an existing user password with an admin account:
+ * o the userIdentity is 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 testAdminPasswordModify2PasswordsOldNewExists() throws Exception
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser2Passwords( adminConnection, "User1", "secret1", "other" );
+
+ // 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( "other" ) );
+
+ // Send the request
+ PasswordModifyResponse pwdModifyResponse = ( PasswordModifyResponse ) adminConnection.extended( pwdModifyRequest );
+
+ assertEquals( ResultCodeEnum.SUCCESS, pwdModifyResponse.getLdapResult().getResultCode() );
+
+ // Rebind with the original password
+ try ( LdapConnection 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" ) );
+ }
+ }
+ }
+
+
+ /**
+ * Modify an existing user password with an admin account
+ */
+ @Test
+ public void testAdminModifyMultiplePassword() throws Exception
+ {
+ try ( LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() ) )
+ {
+ // Create a user
+ addUser2Passwords( adminConnection, "User5", "secret51", "secret52" );
+
+ // Modify the user with the admin account
+ 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
+ try ( LdapConnection userConnection = getNetworkConnectionAs( ldapServer, "cn=User5,ou=system", "secret5Bis" ) )
+ {
+ Entry entry = userConnection.lookup( "cn=User5,ou=system" );
+
+ assertNotNull( entry );
+
+ userConnection.close();
+ }
+ }
+ }
+
+
+ /**
+ * Modify an existing user password with a bad account
+ */
+ @Test
+ public void testAdminModifyPasswordBadUser() throws Exception
+ {
+ try ( 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() );
+ }
+ }
+
+
+ /**
+ * Test that the server refuse to generate a password
+ */
+ @Test
+ public void testAdminGenPassword() throws Exception
+ {
+ try ( 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() );
+ }
+ }
+}