Return-Path: X-Original-To: apmail-directory-commits-archive@www.apache.org Delivered-To: apmail-directory-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id D1CDC10794 for ; Fri, 14 Feb 2014 20:01:53 +0000 (UTC) Received: (qmail 25073 invoked by uid 500); 14 Feb 2014 20:01:52 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 25015 invoked by uid 500); 14 Feb 2014 20:01:51 -0000 Mailing-List: contact commits-help@directory.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@directory.apache.org Delivered-To: mailing list commits@directory.apache.org Received: (qmail 25008 invoked by uid 99); 14 Feb 2014 20:01:51 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 14 Feb 2014 20:01:51 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 14 Feb 2014 20:01:49 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 53B542388994; Fri, 14 Feb 2014 20:01:29 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: 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 Date: Fri, 14 Feb 2014 20:01:29 -0000 To: commits@directory.apache.org From: kayyagari@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20140214200129.53B542388994@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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 modifications = new ArrayList(); 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 modifications = new ArrayList(); - 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 modifications = new ArrayList(); - 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(); + } }