You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ka...@apache.org on 2014/02/14 21:01:29 UTC

svn commit: r1568502 - in /directory/apacheds/trunk: protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/PwdModifyHandler.java server-integ/src/test/java/org/apache/directory/server/operations/extended/PwdModifyIT.java

Author: kayyagari
Date: Fri Feb 14 20:01:28 2014
New Revision: 1568502

URL: http://svn.apache.org/r1568502
Log:
o updated the handler to reuse the methods by passing the appropriate session handle
o used CoreSession to perform the operation (this is needed to replicate the changes)
o fixed an issue where password cannot be changed if the old password is hashed
o added a test

Modified:
    directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/PwdModifyHandler.java
    directory/apacheds/trunk/server-integ/src/test/java/org/apache/directory/server/operations/extended/PwdModifyIT.java

Modified: directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/PwdModifyHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/PwdModifyHandler.java?rev=1568502&r1=1568501&r2=1568502&view=diff
==============================================================================
--- directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/PwdModifyHandler.java (original)
+++ directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/handlers/extended/PwdModifyHandler.java Fri Feb 14 20:01:28 2014
@@ -20,10 +20,8 @@
 package org.apache.directory.server.ldap.handlers.extended;
 
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Set;
 
 import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicy;
@@ -31,24 +29,29 @@ import org.apache.directory.api.ldap.ext
 import org.apache.directory.api.ldap.extras.extended.PwdModifyResponse;
 import org.apache.directory.api.ldap.extras.extended.PwdModifyResponseImpl;
 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.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.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.exception.LdapOperationException;
 import org.apache.directory.api.ldap.model.message.Control;
+import org.apache.directory.api.ldap.model.message.ModifyRequest;
+import org.apache.directory.api.ldap.model.message.ModifyRequestImpl;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.ldap.model.password.PasswordUtil;
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.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.api.interceptor.context.HasEntryOperationContext;
-import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
 import org.apache.directory.server.ldap.ExtendedOperationHandler;
 import org.apache.directory.server.ldap.LdapServer;
 import org.apache.directory.server.ldap.LdapSession;
+import org.apache.mina.core.session.IoSession;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -89,51 +92,58 @@ public class PwdModifyHandler implements
     /**
      * Modify the user's credentials.
      */
-    private void modifyUserPassword( LdapSession requestor, Dn userDn, byte[] oldPassword, byte[] newPassword,
+    private void modifyUserPassword( CoreSession userSession, IoSession ioPipe, Dn userDn, byte[] oldPassword, byte[] newPassword,
         PwdModifyRequest req )
     {
-        DirectoryService service = requestor.getLdapServer().getDirectoryService();
-        CoreSession adminSession = service.getAdminSession();
-
         // First, check that the user exists
         try
         {
-            HasEntryOperationContext hasEntryContext = new HasEntryOperationContext( adminSession );
-            hasEntryContext.setDn( userDn );
-
-            if ( !service.getOperationManager().hasEntry( hasEntryContext ) )
+            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
-                requestor.getIoSession().write( new PwdModifyResponseImpl(
+                ioPipe.write( new PwdModifyResponseImpl(
                     req.getMessageId(), ResultCodeEnum.NO_SUCH_OBJECT, "Cannot find an entry for DN " + userDn ) );
 
                 return;
             }
+            
+            Attribute at = userEntry.get( SchemaConstants.USER_PASSWORD_AT );
+            if ( ( oldPassword != null ) && ( at != null ) )
+            {
+                for( Value<?> v : at )
+                {
+                    boolean equal = PasswordUtil.compareCredentials( oldPassword, v.getBytes() );
+                    if( equal )
+                    {
+                        oldPassword = v.getBytes();
+                    }
+                }
+            }
         }
         catch ( LdapException le )
         {
             LOG.error( "Cannot find an entry for DN " + userDn + ", exception : " + le.getMessage() );
             // We can't find the entry in the DIT
-            requestor.getIoSession().write(
+            ioPipe.write(
                 new PwdModifyResponseImpl(
-                    req.getMessageId(), ResultCodeEnum.NO_SUCH_OBJECT, "Cannot find an entry for DN " + userDn
-                        + ", exception : " + le.getMessage() ) );
+                    req.getMessageId(), ResultCodeEnum.NO_SUCH_OBJECT, "Cannot find an entry for DN " + userDn ) );
 
             return;
         }
 
         // We can try to update the userPassword now
-        ModifyOperationContext modifyContext = new ModifyOperationContext( adminSession );
-        modifyContext.setDn( userDn );
+        ModifyRequest modifyRequest = new ModifyRequestImpl();
+        modifyRequest.setName( userDn );
 
         Control ppolicyControl = req.getControl( PasswordPolicy.OID );
         if( ppolicyControl != null )
         {
-            modifyContext.addRequestControl( ppolicyControl );
+            modifyRequest.addControl( ppolicyControl );
         }
 
-        List<Modification> modifications = new ArrayList<Modification>();
         Modification modification = null;
 
         if ( oldPassword != null )
@@ -141,7 +151,7 @@ public class PwdModifyHandler implements
             modification = new DefaultModification( ModificationOperation.REMOVE_ATTRIBUTE,
                 SchemaConstants.USER_PASSWORD_AT, oldPassword );
 
-            modifications.add( modification );
+            modifyRequest.addModification( modification );
         }
 
         if ( newPassword != null )
@@ -157,7 +167,7 @@ public class PwdModifyHandler implements
                     SchemaConstants.USER_PASSWORD_AT, newPassword );
             }
 
-            modifications.add( modification );
+            modifyRequest.addModification( modification );
         }
         else
         {
@@ -166,21 +176,19 @@ public class PwdModifyHandler implements
             LOG.error( "Cannot create a new password for user " + userDn + ", exception : " + userDn );
 
             // We can't modify the password
-            requestor.getIoSession().write( new PwdModifyResponseImpl(
+            ioPipe.write( new PwdModifyResponseImpl(
                 req.getMessageId(), ResultCodeEnum.UNWILLING_TO_PERFORM, "Cannot generate a new password for user "
                     + userDn ) );
 
             return;
         }
 
-        modifyContext.setModItems( modifications );
-
         ResultCodeEnum errorCode = null;
         String errorMessage = null;
 
         try
         {
-            service.getOperationManager().modify( modifyContext );
+            userSession.modify( modifyRequest );
 
             LOG.debug( "Password modified for user " + userDn );
 
@@ -188,14 +196,14 @@ public class PwdModifyHandler implements
             PwdModifyResponseImpl pmrl = new PwdModifyResponseImpl(
                 req.getMessageId(), ResultCodeEnum.SUCCESS );
 
-            ppolicyControl = modifyContext.getResponseControl( PasswordPolicy.OID );
+            ppolicyControl = modifyRequest.getResultResponse().getControl( PasswordPolicy.OID );
 
             if( ppolicyControl != null )
             {
                 pmrl.addControl( ppolicyControl );
             }
 
-            requestor.getIoSession().write( pmrl );
+            ioPipe.write( pmrl );
 
             return;
         }
@@ -217,113 +225,14 @@ public class PwdModifyHandler implements
             req.getMessageId(), errorCode, "Cannot modify the password for user "
                 + userDn + ", exception : " + errorMessage );
 
-        ppolicyControl = modifyContext.getResponseControl( PasswordPolicy.OID );
+        ppolicyControl = modifyRequest.getResultResponse().getControl( PasswordPolicy.OID );
 
         if( ppolicyControl != null )
         {
             errorPmrl.addControl( ppolicyControl );
         }
 
-        requestor.getIoSession().write( errorPmrl );
-    }
-
-
-    /**
-     * Modify his password
-     */
-    private void modifyOwnPassword( LdapSession requestor, Dn principalDn, byte[] oldPassword, byte[] newPassword,
-        PwdModifyRequest req )
-    {
-        DirectoryService service = requestor.getLdapServer().getDirectoryService();
-
-        // Try to update the userPassword
-        ModifyOperationContext modifyContext = new ModifyOperationContext( requestor.getCoreSession() );
-        modifyContext.setDn( principalDn );
-
-        Control ppolicyControl = req.getControl( PasswordPolicy.OID );
-        if( ppolicyControl != null )
-        {
-            modifyContext.addRequestControl( ppolicyControl );
-        }
-
-        List<Modification> modifications = new ArrayList<Modification>();
-        Modification modification = null;
-
-        if ( oldPassword != null )
-        {
-            modification = new DefaultModification( ModificationOperation.REMOVE_ATTRIBUTE,
-                SchemaConstants.USER_PASSWORD_AT, oldPassword );
-
-            modifications.add( modification );
-        }
-        else
-        {
-            modification = new DefaultModification( ModificationOperation.REMOVE_ATTRIBUTE,
-                SchemaConstants.USER_PASSWORD_AT );
-
-            modifications.add( modification );
-        }
-
-        if ( newPassword != null )
-        {
-            modification = new DefaultModification( ModificationOperation.ADD_ATTRIBUTE,
-                SchemaConstants.USER_PASSWORD_AT, newPassword );
-
-            modifications.add( modification );
-        }
-
-        modifyContext.setModItems( modifications );
-
-        ResultCodeEnum errorCode = null;
-        String errorMessage = null;
-
-        try
-        {
-            service.getOperationManager().modify( modifyContext );
-
-            LOG.debug( "Password modified for user " + principalDn );
-
-            // Ok, all done
-            PwdModifyResponseImpl pmrl = new PwdModifyResponseImpl(
-                req.getMessageId(), ResultCodeEnum.SUCCESS );
-
-            ppolicyControl = modifyContext.getResponseControl( PasswordPolicy.OID );
-
-            if( ppolicyControl != null )
-            {
-                pmrl.addControl( ppolicyControl );
-            }
-
-            requestor.getIoSession().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 " + principalDn + ", exception : " + errorMessage );
-
-        PwdModifyResponseImpl errorPmrl = new PwdModifyResponseImpl( req.getMessageId(), errorCode,
-            "Cannot modify the password for user "
-                + principalDn + ", exception : " + errorMessage );
-
-        ppolicyControl = modifyContext.getResponseControl( PasswordPolicy.OID );
-
-        if( ppolicyControl != null )
-        {
-            errorPmrl.addControl( ppolicyControl );
-        }
-
-        requestor.getIoSession().write( errorPmrl );
+        ioPipe.write( errorPmrl );
     }
 
 
@@ -382,13 +291,13 @@ public class PwdModifyHandler implements
                 else
                 {
                     // We are administrator, we can try to modify the user's credentials
-                    modifyUserPassword( requestor, userDn, oldPassword, newPassword, req );
+                    modifyUserPassword( requestor.getCoreSession(), requestor.getIoSession(), userDn, oldPassword, newPassword, req );
                 }
             }
             else
             {
                 // We are trying to modify our own password
-                modifyOwnPassword( requestor, principalDn, oldPassword, newPassword, req );
+                modifyUserPassword( requestor.getCoreSession(), requestor.getIoSession(), principalDn, oldPassword, newPassword, req );
             }
         }
         else
@@ -415,33 +324,7 @@ public class PwdModifyHandler implements
 
             // Ok, we were able to bind using the userIdentity and the password. Let's
             // modify the password now
-            ModifyOperationContext modifyContext = new ModifyOperationContext( 
-                service.getSession( userDn, oldPassword ) );
-            modifyContext.setDn( userDn );
-            List<Modification> modifications = new ArrayList<Modification>();
-            Modification modification = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
-                SchemaConstants.USER_PASSWORD_AT, newPassword );
-            modifications.add( modification );
-            modifyContext.setModItems( modifications );
-
-            try
-            {
-                service.getOperationManager().modify( modifyContext );
-
-                // Ok, all done
-                requestor.getIoSession().write( new PwdModifyResponseImpl(
-                    req.getMessageId(), ResultCodeEnum.SUCCESS ) );
-            }
-            catch ( LdapException le )
-            {
-                // We can't modify the password
-                requestor.getIoSession().write(
-                    new PwdModifyResponseImpl(
-                        req.getMessageId(), ResultCodeEnum.UNWILLING_TO_PERFORM,
-                        "Cannot modify the password, exception : " + le.getMessage() ) );
-
-                return;
-            }
+            modifyUserPassword( requestor.getCoreSession(), requestor.getIoSession(), userDn, oldPassword, newPassword, req );
         }
     }
 

Modified: directory/apacheds/trunk/server-integ/src/test/java/org/apache/directory/server/operations/extended/PwdModifyIT.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/server-integ/src/test/java/org/apache/directory/server/operations/extended/PwdModifyIT.java?rev=1568502&r1=1568501&r2=1568502&view=diff
==============================================================================
--- directory/apacheds/trunk/server-integ/src/test/java/org/apache/directory/server/operations/extended/PwdModifyIT.java (original)
+++ directory/apacheds/trunk/server-integ/src/test/java/org/apache/directory/server/operations/extended/PwdModifyIT.java Fri Feb 14 20:01:28 2014
@@ -28,7 +28,6 @@ import static org.junit.Assert.assertNot
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
-
 import org.apache.directory.api.ldap.codec.api.LdapApiService;
 import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
 import org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicy;
@@ -37,6 +36,7 @@ import org.apache.directory.api.ldap.ext
 import org.apache.directory.api.ldap.extras.controls.ppolicy_impl.PasswordPolicyDecorator;
 import org.apache.directory.api.ldap.extras.extended.PwdModifyRequestImpl;
 import org.apache.directory.api.ldap.extras.extended.PwdModifyResponse;
+import org.apache.directory.api.ldap.model.constants.LdapSecurityConstants;
 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;
@@ -49,6 +49,7 @@ import org.apache.directory.api.ldap.mod
 import org.apache.directory.api.ldap.model.message.Response;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.api.ldap.model.password.PasswordUtil;
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.ldap.client.api.LdapConnection;
 import org.apache.directory.server.annotations.CreateLdapServer;
@@ -532,5 +533,43 @@ public class PwdModifyIT extends Abstrac
             adminConnection.close();
             userConnection.close();
         }
-    }    
+    }
+    
+    
+    /**
+     * Modify an existing user password while the user is connected and the password is stored as a hash
+     */
+    @Test
+    public void testModifyPasswordStoredAsHash() throws Exception
+    {
+        LdapConnection adminConnection = getAdminNetworkConnection( getLdapServer() );
+
+        byte[] password = "secret1".getBytes();
+        byte[] credHash = PasswordUtil.createStoragePassword( password, LdapSecurityConstants.HASH_METHOD_SHA256 );
+        addUser( adminConnection, "User11", credHash );
+
+        // Bind as the user
+        LdapConnection userConnection = getNetworkConnectionAs( getLdapServer(), "cn=user11,ou=system", "secret1" );
+        userConnection.setTimeOut( 0L );
+
+        // Now change the password
+        PwdModifyRequestImpl pwdModifyRequest = new PwdModifyRequestImpl();
+        pwdModifyRequest.setOldPassword( password );
+        pwdModifyRequest.setNewPassword( Strings.getBytesUtf8( "secret1Bis" ) );
+
+        // Send the request
+        PwdModifyResponse pwdModifyResponse = ( PwdModifyResponse ) userConnection.extended( pwdModifyRequest );
+
+        assertEquals( ResultCodeEnum.SUCCESS, pwdModifyResponse.getLdapResult().getResultCode() );
+
+        // Now try to bind with the new password
+        userConnection = getNetworkConnectionAs( ldapServer, "cn=User11,ou=system", "secret1Bis" );
+
+        Entry entry = userConnection.lookup( "cn=User11,ou=system" );
+
+        assertNotNull( entry );
+
+        userConnection.close();
+        adminConnection.close();
+    }
 }