in interceptors/authn/src/main/java/org/apache/directory/server/core/authn/AuthenticationInterceptor.java [985:1147]
private void processPasswordPolicydModify( ModifyOperationContext modifyContext ) throws LdapException
{
// handle the case where pwdPolicySubentry AT is about to be deleted in this modify()
PasswordPolicyConfiguration policyConfig = getPwdPolicy( modifyContext.getEntry() );
PwdModDetailsHolder pwdModDetails = getPwdModDetails( modifyContext, policyConfig );
if ( !pwdModDetails.isPwdModPresent() )
{
// We can going on, the password attribute is not present in the Modifications.
next( modifyContext );
}
else
{
// The password is present in the modifications. Deal with the various use cases.
CoreSession userSession = modifyContext.getSession();
boolean isPPolicyReqCtrlPresent = modifyContext.hasRequestControl( PasswordPolicyRequest.OID );
// First, check if the password must be changed, and if the operation allows it
checkPwdMustChange( modifyContext, userSession, pwdModDetails, isPPolicyReqCtrlPresent );
// Check the the old password is present if it's required by the PP config
checkOldPwdRequired( modifyContext, policyConfig, pwdModDetails, isPPolicyReqCtrlPresent );
// Check that we can't update the password if it's not allowed
checkChangePwdAllowed( modifyContext, policyConfig, isPPolicyReqCtrlPresent );
Entry entry = modifyContext.getEntry();
boolean removePwdReset = false;
List<Modification> mods = new ArrayList<>();
if ( pwdModDetails.isAddOrReplace() )
{
if ( isPwdTooYoung( modifyContext, entry, policyConfig ) )
{
if ( isPPolicyReqCtrlPresent )
{
PasswordPolicyResponse responseControl = new PasswordPolicyResponseImpl();
responseControl.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
{
check( modifyContext, entry, newPassword, policyConfig );
}
catch ( PasswordPolicyException e )
{
if ( isPPolicyReqCtrlPresent )
{
PasswordPolicyResponse responseControl = new PasswordPolicyResponseImpl();
responseControl.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( directoryService.getTimeProvider() );
if ( histSize > 0 )
{
Attribute pwdHistoryAt = entry.get( pwdHistoryAT );
if ( pwdHistoryAt == null )
{
pwdHistoryAt = new DefaultAttribute( pwdHistoryAT );
}
// Build the Modification containing the password history
pwdRemHistMod = buildPwdHistory( modifyContext, pwdHistoryAt, histSize,
newPassword, isPPolicyReqCtrlPresent );
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 );
lookupContext.setPartition( modifyContext.getPartition() );
lookupContext.setTransaction( modifyContext.getTransaction() );
entry = directoryService.getPartitionNexus().lookup( lookupContext );
if ( ( policyConfig.getPwdMinAge() > 0 ) || ( policyConfig.getPwdMaxAge() > 0 ) )
{
Attribute pwdChangedTimeAt = new DefaultAttribute( pwdChangedTimeAT );
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( pwdResetAT );
Modification pwdMustChangeMod;
if ( modifyContext.getSession().isAnAdministrator() )
{
pwdMustChangeAt.add( "TRUE" );
pwdMustChangeMod = new DefaultModification( REPLACE_ATTRIBUTE, pwdMustChangeAt );
}
else
{
pwdMustChangeMod = new DefaultModification( REMOVE_ATTRIBUTE, pwdMustChangeAt );
removePwdReset = true;
}
mods.add( pwdMustChangeMod );
}
}
// Add the attributes that have been modified following a Add/Replace password
processModifyAddPwdAttributes( entry, mods, pwdModDetails );
String csnVal = directoryService.getCSN().toString();
Modification csnMod = new DefaultModification( REPLACE_ATTRIBUTE, directoryService.getAtProvider()
.getEntryCSN(), csnVal );
mods.add( csnMod );
ModifyOperationContext internalModifyCtx = new ModifyOperationContext( adminSession );
internalModifyCtx.setPushToEvtInterceptor( true );
internalModifyCtx.setDn( modifyContext.getDn() );
internalModifyCtx.setEntry( entry );
internalModifyCtx.setModItems( mods );
internalModify( modifyContext, internalModifyCtx );
if ( removePwdReset || pwdModDetails.isDelete() )
{
userSession.setPwdMustChange( false );
}
}
}