invalidateAuthenticatorCaches( modifyContext.getDn() );
return;
}
// handle the case where pwdPolicySubentry AT is about to be deleted in thid modify()
PasswordPolicyConfiguration policyConfig = getPwdPolicy( modifyContext.getEntry() );
boolean isPPolicyReqCtrlPresent = modifyContext.hasRequestControl( PasswordPolicy.OID );
Dn userDn = modifyContext.getSession().getAuthenticatedPrincipal().getDn();
PwdModDetailsHolder pwdModDetails = null;
pwdModDetails = getPwdModDetails( modifyContext, policyConfig );
if ( pwdModDetails.isPwdModPresent() )
{
if ( pwdResetSet.contains( userDn.getNormName() ) && !pwdModDetails.isDelete() )
{
if ( pwdModDetails.isOtherModExists() )
{
if ( isPPolicyReqCtrlPresent )
{
PasswordPolicyDecorator responseControl =
new PasswordPolicyDecorator( directoryService.getLdapCodecService(), true );
responseControl.getResponse().setPasswordPolicyError(
PasswordPolicyErrorEnum.CHANGE_AFTER_RESET );
modifyContext.addResponseControl( responseControl );
}
throw new LdapNoPermissionException(
"Password should be reset before making any changes to this entry" );
}
}
if ( policyConfig.isPwdSafeModify() && !pwdModDetails.isDelete() )
{
if ( pwdModDetails.isAddOrReplace() && !pwdModDetails.isDelete() )
{
String msg = "trying to update password attribute without the supplying the old password";
LOG.debug( msg );
if ( isPPolicyReqCtrlPresent )
{
PasswordPolicyDecorator responseControl =
new PasswordPolicyDecorator( directoryService.getLdapCodecService(), true );
responseControl.getResponse().setPasswordPolicyError(
PasswordPolicyErrorEnum.MUST_SUPPLY_OLD_PASSWORD );
modifyContext.addResponseControl( responseControl );
}
throw new LdapNoPermissionException( msg );
}
}
if ( !policyConfig.isPwdAllowUserChange() && !modifyContext.getSession().isAnAdministrator() )
{
if ( isPPolicyReqCtrlPresent )
{
PasswordPolicyDecorator responseControl =
new PasswordPolicyDecorator( directoryService.getLdapCodecService(), true );
responseControl.getResponse().setPasswordPolicyError(
PasswordPolicyErrorEnum.PASSWORD_MOD_NOT_ALLOWED );
modifyContext.addResponseControl( responseControl );
}
throw new LdapNoPermissionException();
}
Entry entry = modifyContext.getEntry();
boolean removeFromPwdResetSet = false;
List<Modification> mods = new ArrayList<Modification>();
if ( pwdModDetails.isAddOrReplace() )
{
if ( isPwdTooYoung( entry, policyConfig ) )
{
if ( isPPolicyReqCtrlPresent )
{
PasswordPolicyDecorator responseControl =
new PasswordPolicyDecorator( directoryService.getLdapCodecService(), true );
responseControl.getResponse().setPasswordPolicyError(
PasswordPolicyErrorEnum.PASSWORD_TOO_YOUNG );
modifyContext.addResponseControl( responseControl );
}
throw new LdapOperationException( ResultCodeEnum.CONSTRAINT_VIOLATION,
"password is too young to update" );
}
byte[] newPassword = pwdModDetails.getNewPwd();
try
{
String userName = entry.getDn().getRdn().getValue().getString();
check( userName, newPassword, policyConfig );
}
catch ( PasswordPolicyException e )
{
if ( isPPolicyReqCtrlPresent )
{
PasswordPolicyDecorator responseControl =
new PasswordPolicyDecorator( directoryService.getLdapCodecService(), true );
responseControl.getResponse().setPasswordPolicyError(
PasswordPolicyErrorEnum.get( e.getErrorCode() ) );
modifyContext.addResponseControl( responseControl );
}
// throw exception if userPassword quality checks fail
throw new LdapOperationException( ResultCodeEnum.CONSTRAINT_VIOLATION, e.getMessage(), e );
}
int histSize = policyConfig.getPwdInHistory();
Modification pwdRemHistMod = null;
Modification pwdAddHistMod = null;
String pwdChangedTime = DateUtils.getGeneralizedTime();
if ( histSize > 0 )
{
Attribute pwdHistoryAt = entry.get( AT_PWD_HISTORY );
if ( pwdHistoryAt == null )
{
pwdHistoryAt = new DefaultAttribute( AT_PWD_HISTORY );
}
List<PasswordHistory> pwdHistLst = new ArrayList<PasswordHistory>();
for ( Value<?> value : pwdHistoryAt )
{
PasswordHistory pwdh = new PasswordHistory( Strings.utf8ToString( value.getBytes() ) );
boolean matched = Arrays.equals( newPassword, pwdh.getPassword() );
if ( matched )
{
if ( isPPolicyReqCtrlPresent )
{
PasswordPolicyDecorator responseControl =
new PasswordPolicyDecorator( directoryService.getLdapCodecService(), true );
responseControl.getResponse().setPasswordPolicyError(
PasswordPolicyErrorEnum.PASSWORD_IN_HISTORY );
modifyContext.addResponseControl( responseControl );
}
throw new LdapOperationException( ResultCodeEnum.CONSTRAINT_VIOLATION,
"invalid reuse of password present in password history" );
}
pwdHistLst.add( pwdh );
}
if ( pwdHistLst.size() >= histSize )
{
// see the javadoc of PasswordHistory
Collections.sort( pwdHistLst );
// remove the oldest value
PasswordHistory remPwdHist = ( PasswordHistory ) pwdHistLst.toArray()[histSize - 1];
Attribute tempAt = new DefaultAttribute( AT_PWD_HISTORY );
tempAt.add( remPwdHist.getHistoryValue() );
pwdRemHistMod = new DefaultModification( REMOVE_ATTRIBUTE, tempAt );
}
PasswordHistory newPwdHist = new PasswordHistory( pwdChangedTime, newPassword );
pwdHistoryAt.add( newPwdHist.getHistoryValue() );
pwdAddHistMod = new DefaultModification( REPLACE_ATTRIBUTE, pwdHistoryAt );
}
next( modifyContext );
invalidateAuthenticatorCaches( modifyContext.getDn() );
LookupOperationContext lookupContext = new LookupOperationContext( adminSession, modifyContext.getDn(),
SchemaConstants.ALL_ATTRIBUTES_ARRAY );
entry = directoryService.getPartitionNexus().lookup( lookupContext );
if ( ( policyConfig.getPwdMinAge() > 0 ) || ( policyConfig.getPwdMaxAge() > 0 ) )
{
Attribute pwdChangedTimeAt = new DefaultAttribute( AT_PWD_CHANGED_TIME );
pwdChangedTimeAt.add( pwdChangedTime );
Modification pwdChangedTimeMod = new DefaultModification( REPLACE_ATTRIBUTE, pwdChangedTimeAt );
mods.add( pwdChangedTimeMod );
}
if ( pwdAddHistMod != null )
{
mods.add( pwdAddHistMod );
}
if ( pwdRemHistMod != null )
{
mods.add( pwdRemHistMod );
}
if ( policyConfig.isPwdMustChange() )
{
Attribute pwdMustChangeAt = new DefaultAttribute( AT_PWD_RESET );
Modification pwdMustChangeMod = null;
if ( modifyContext.getSession().isAnAdministrator() )