| | |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.*; |
| | | import java.util.concurrent.locks.Lock; |
| | | |
| | |
| | | /** The reference to the identity mapper. */ |
| | | private IdentityMapper<?> identityMapper; |
| | | |
| | | /** The default set of supported control OIDs for this extended. */ |
| | | private Set<String> supportedControlOIDs = new HashSet<String>(0); |
| | | |
| | | /** |
| | | * Create an instance of this password modify extended operation. All |
| | | * initialization should be performed in the |
| | |
| | | */ |
| | | public PasswordModifyExtendedOperation() |
| | | { |
| | | super(); |
| | | super(new HashSet<String>(Arrays.asList( |
| | | OID_LDAP_NOOP_OPENLDAP_ASSIGNED, OID_PASSWORD_POLICY_CONTROL))); |
| | | } |
| | | |
| | | /** |
| | |
| | | throw new InitializationException(message, e); |
| | | } |
| | | |
| | | |
| | | supportedControlOIDs = new HashSet<String>(); |
| | | supportedControlOIDs.add(OID_LDAP_NOOP_OPENLDAP_ASSIGNED); |
| | | supportedControlOIDs.add(OID_PASSWORD_POLICY_CONTROL); |
| | | |
| | | |
| | | // Save this configuration for future reference. |
| | | currentConfig = config; |
| | | |
| | | // Register this as a change listener. |
| | | config.addPasswordModifyChangeListener(this); |
| | | |
| | | DirectoryServer.registerSupportedExtension(OID_PASSWORD_MODIFY_REQUEST, |
| | | this); |
| | | |
| | | registerControlsAndFeatures(); |
| | | super.initializeExtendedOperationHandler(config); |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | currentConfig.removePasswordModifyChangeListener(this); |
| | | |
| | | DirectoryServer.deregisterSupportedExtension(OID_PASSWORD_MODIFY_REQUEST); |
| | | |
| | | deregisterControlsAndFeatures(); |
| | | super.finalizeExtendedOperationHandler(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public Set<String> getSupportedControls() |
| | | { |
| | | return supportedControlOIDs; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Processes the provided extended operation. |
| | | * |
| | |
| | | } |
| | | |
| | | operation.setResultCode(ResultCode.PROTOCOL_ERROR); |
| | | |
| | | Message message = ERR_EXTOP_PASSMOD_CANNOT_DECODE_REQUEST.get( |
| | | getExceptionMessage(ae)); |
| | | operation.appendErrorMessage(message); |
| | | |
| | | operation.appendErrorMessage(ERR_EXTOP_PASSMOD_CANNOT_DECODE_REQUEST |
| | | .get(getExceptionMessage(ae))); |
| | | return; |
| | | } |
| | | } |
| | |
| | | if ((! authInfo.isAuthenticated()) || (requestorEntry == null)) |
| | | { |
| | | operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); |
| | | |
| | | operation.appendErrorMessage( |
| | | ERR_EXTOP_PASSMOD_NO_AUTH_OR_USERID.get()); |
| | | |
| | | return; |
| | | } |
| | | |
| | |
| | | return; |
| | | } |
| | | |
| | | |
| | | userEntry = requestorEntry; |
| | | } |
| | | else |
| | |
| | | } |
| | | |
| | | operation.setResultCode(ResultCode.INVALID_DN_SYNTAX); |
| | | |
| | | operation.appendErrorMessage( |
| | | ERR_EXTOP_PASSMOD_CANNOT_DECODE_AUTHZ_DN.get(authzIDStr)); |
| | | |
| | | return; |
| | | } |
| | | |
| | |
| | | ERR_EXTOP_PASSMOD_CANNOT_MAP_USER.get(authzIDStr)); |
| | | return; |
| | | } |
| | | else |
| | | { |
| | | userDN = userEntry.getDN(); |
| | | } |
| | | |
| | | userDN = userEntry.getDN(); |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | |
| | | { |
| | | userDN = DN.decode(authzIDStr); |
| | | } |
| | | catch (DirectoryException de) |
| | | catch (DirectoryException ignored) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, de); |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, ignored); |
| | | } |
| | | // IGNORE. |
| | | } |
| | | |
| | | if ((userDN != null) && (!userDN.isNullDN())) { |
| | | if (userDN != null && !userDN.isNullDN()) { |
| | | // If the provided DN is an alternate DN for a root user, |
| | | // then replace it with the actual root DN. |
| | | DN actualRootDN = DirectoryServer.getActualRootBindDN(userDN); |
| | |
| | | { |
| | | userEntry = identityMapper.getEntryForID(authzIDStr); |
| | | } |
| | | catch (DirectoryException de) |
| | | catch (DirectoryException ignored) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, de); |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, ignored); |
| | | } |
| | | // IGNORE. |
| | | } |
| | | } |
| | | |
| | |
| | | ERR_EXTOP_PASSMOD_INVALID_AUTHZID_STRING.get(authzIDStr)); |
| | | return; |
| | | } |
| | | else |
| | | { |
| | | userDN = userEntry.getDN(); |
| | | } |
| | | |
| | | userDN = userEntry.getDN(); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | operation.setResultCode(DirectoryServer.getServerErrorResultCode()); |
| | | |
| | | operation.appendErrorMessage( |
| | | ERR_EXTOP_PASSMOD_CANNOT_GET_PW_POLICY.get( |
| | | String.valueOf(userDN), |
| | |
| | | { |
| | | if (pwPolicyRequested) |
| | | { |
| | | pwPolicyErrorType = |
| | | PasswordPolicyErrorType.ACCOUNT_LOCKED; |
| | | pwPolicyErrorType = PasswordPolicyErrorType.ACCOUNT_LOCKED; |
| | | operation.addResponseControl( |
| | | new PasswordPolicyResponseControl(pwPolicyWarningType, |
| | | pwPolicyWarningValue, |
| | | pwPolicyErrorType)); |
| | | } |
| | | |
| | | Message message = ERR_EXTOP_PASSMOD_ACCOUNT_DISABLED.get(); |
| | | |
| | | operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); |
| | | operation.appendErrorMessage(message); |
| | | |
| | | operation.appendErrorMessage(ERR_EXTOP_PASSMOD_ACCOUNT_DISABLED.get()); |
| | | return; |
| | | } |
| | | else if (selfChange && |
| | |
| | | { |
| | | if (pwPolicyRequested) |
| | | { |
| | | pwPolicyErrorType = |
| | | PasswordPolicyErrorType.ACCOUNT_LOCKED; |
| | | pwPolicyErrorType = PasswordPolicyErrorType.ACCOUNT_LOCKED; |
| | | operation.addResponseControl( |
| | | new PasswordPolicyResponseControl(pwPolicyWarningType, |
| | | pwPolicyWarningValue, |
| | | pwPolicyErrorType)); |
| | | } |
| | | |
| | | Message message = ERR_EXTOP_PASSMOD_ACCOUNT_LOCKED.get(); |
| | | |
| | | operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); |
| | | operation.appendErrorMessage(message); |
| | | |
| | | operation.appendErrorMessage(ERR_EXTOP_PASSMOD_ACCOUNT_LOCKED.get()); |
| | | return; |
| | | } |
| | | |
| | |
| | | .isPasswordChangeRequiresCurrentPassword()) |
| | | { |
| | | operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); |
| | | |
| | | operation.appendErrorMessage( |
| | | ERR_EXTOP_PASSMOD_REQUIRE_CURRENT_PW.get()); |
| | | |
| | |
| | | { |
| | | if (pwPolicyState.getAuthenticationPolicy() |
| | | .isRequireSecureAuthentication() |
| | | && (!operation.getClientConnection().isSecure())) |
| | | && !operation.getClientConnection().isSecure()) |
| | | { |
| | | operation.setResultCode(ResultCode.CONFIDENTIALITY_REQUIRED); |
| | | operation.addAdditionalLogItem(AdditionalLogItem.quotedKeyValue( |
| | |
| | | // If it is a self password change and we don't allow that, then reject |
| | | // the request. |
| | | if (selfChange |
| | | && (!pwPolicyState.getAuthenticationPolicy() |
| | | .isAllowUserPasswordChanges())) |
| | | && !pwPolicyState.getAuthenticationPolicy() |
| | | .isAllowUserPasswordChanges()) |
| | | { |
| | | if (pwPolicyRequested) |
| | | { |
| | | pwPolicyErrorType = |
| | | PasswordPolicyErrorType.PASSWORD_MOD_NOT_ALLOWED; |
| | | pwPolicyErrorType = PasswordPolicyErrorType.PASSWORD_MOD_NOT_ALLOWED; |
| | | operation.addResponseControl( |
| | | new PasswordPolicyResponseControl(pwPolicyWarningType, |
| | | pwPolicyWarningValue, |
| | |
| | | } |
| | | |
| | | operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); |
| | | |
| | | operation.appendErrorMessage( |
| | | ERR_EXTOP_PASSMOD_USER_PW_CHANGES_NOT_ALLOWED.get()); |
| | | return; |
| | |
| | | // then reject the request. |
| | | if (pwPolicyState.getAuthenticationPolicy() |
| | | .isRequireSecurePasswordChanges() |
| | | && (!operation.getClientConnection().isSecure())) |
| | | && !operation.getClientConnection().isSecure()) |
| | | { |
| | | operation.setResultCode(ResultCode.CONFIDENTIALITY_REQUIRED); |
| | | |
| | | operation.appendErrorMessage( |
| | | ERR_EXTOP_PASSMOD_SECURE_CHANGES_REQUIRED.get()); |
| | | return; |
| | |
| | | { |
| | | if (pwPolicyRequested) |
| | | { |
| | | pwPolicyErrorType = |
| | | PasswordPolicyErrorType.PASSWORD_TOO_YOUNG; |
| | | pwPolicyErrorType = PasswordPolicyErrorType.PASSWORD_TOO_YOUNG; |
| | | operation.addResponseControl( |
| | | new PasswordPolicyResponseControl(pwPolicyWarningType, |
| | | pwPolicyWarningValue, |
| | |
| | | } |
| | | |
| | | operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); |
| | | |
| | | operation.appendErrorMessage(ERR_EXTOP_PASSMOD_IN_MIN_AGE.get()); |
| | | |
| | | return; |
| | | } |
| | | |
| | | |
| | | // If the user's password is expired and it's a self-change request, then |
| | | // see if that's OK. |
| | | if ((selfChange && pwPolicyState.isPasswordExpired() && (!pwPolicyState |
| | | .getAuthenticationPolicy().isAllowExpiredPasswordChanges()))) |
| | | if (selfChange |
| | | && pwPolicyState.isPasswordExpired() |
| | | && !pwPolicyState.getAuthenticationPolicy() |
| | | .isAllowExpiredPasswordChanges()) |
| | | { |
| | | if (pwPolicyRequested) |
| | | { |
| | | pwPolicyErrorType = |
| | | PasswordPolicyErrorType.PASSWORD_EXPIRED; |
| | | pwPolicyErrorType = PasswordPolicyErrorType.PASSWORD_EXPIRED; |
| | | operation.addResponseControl( |
| | | new PasswordPolicyResponseControl(pwPolicyWarningType, |
| | | pwPolicyWarningValue, |
| | |
| | | } |
| | | |
| | | operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); |
| | | |
| | | operation.appendErrorMessage( |
| | | ERR_EXTOP_PASSMOD_PASSWORD_IS_EXPIRED.get()); |
| | | return; |
| | |
| | | if (newPassword == null) |
| | | { |
| | | operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); |
| | | |
| | | operation.appendErrorMessage( |
| | | ERR_EXTOP_PASSMOD_NO_PW_GENERATOR.get()); |
| | | return; |
| | | } |
| | | else |
| | | { |
| | | generatedPassword = true; |
| | | } |
| | | |
| | | generatedPassword = true; |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | |
| | | } |
| | | |
| | | operation.setResultCode(de.getResultCode()); |
| | | |
| | | operation.appendErrorMessage( |
| | | ERR_EXTOP_PASSMOD_CANNOT_GENERATE_PW.get( |
| | | de.getMessageObject())); |
| | |
| | | .isAllowPreEncodedPasswords()) |
| | | { |
| | | operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); |
| | | |
| | | operation.appendErrorMessage( |
| | | ERR_EXTOP_PASSMOD_PRE_ENCODED_NOT_ALLOWED.get()); |
| | | return; |
| | |
| | | { |
| | | // Run the new password through the set of password validators. |
| | | if (selfChange |
| | | || (!pwPolicyState.getAuthenticationPolicy() |
| | | .isSkipValidationForAdministrators())) |
| | | || !pwPolicyState.getAuthenticationPolicy() |
| | | .isSkipValidationForAdministrators()) |
| | | { |
| | | HashSet<ByteString> clearPasswords; |
| | | Set<ByteString> clearPasswords; |
| | | if (oldPassword == null) |
| | | { |
| | | clearPasswords = |
| | |
| | | } |
| | | |
| | | operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); |
| | | |
| | | operation.appendErrorMessage( |
| | | ERR_EXTOP_PASSMOD_UNACCEPTABLE_PW.get( |
| | | String.valueOf(invalidReason))); |
| | |
| | | { |
| | | if (pwPolicyState.isPasswordInHistory(newPassword)) |
| | | { |
| | | if (selfChange || (! pwPolicyState.getAuthenticationPolicy(). |
| | | isSkipValidationForAdministrators())) |
| | | if (selfChange |
| | | || !pwPolicyState.getAuthenticationPolicy() |
| | | .isSkipValidationForAdministrators()) |
| | | { |
| | | operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); |
| | | |
| | | operation.appendErrorMessage( |
| | | ERR_EXTOP_PASSMOD_PW_IN_HISTORY.get()); |
| | | return; |
| | |
| | | } |
| | | |
| | | operation.setResultCode(de.getResultCode()); |
| | | |
| | | operation.appendErrorMessage( |
| | | ERR_EXTOP_PASSMOD_CANNOT_ENCODE_PASSWORD.get( |
| | | de.getMessageObject())); |
| | |
| | | if (noOpRequested) |
| | | { |
| | | operation.appendErrorMessage(WARN_EXTOP_PASSMOD_NOOP.get()); |
| | | |
| | | operation.setResultCode(ResultCode.NO_OPERATION); |
| | | return; |
| | | } |
| | | |
| | | if (selfChange && requestorEntry == null) |
| | | { |
| | | requestorEntry = userEntry; |
| | | } |
| | | |
| | | // Get an internal connection and use it to perform the modification. |
| | | boolean isRoot = DirectoryServer.isRootDN(requestorEntry.getDN()); |
| | | AuthenticationInfo authInfo = new AuthenticationInfo(requestorEntry, |
| | | isRoot); |
| | | InternalClientConnection internalConnection = new |
| | | InternalClientConnection(authInfo); |
| | | |
| | | ModifyOperation modifyOperation = |
| | | internalConnection.processModify(userDN, modList); |
| | | ResultCode resultCode = modifyOperation.getResultCode(); |
| | | if (resultCode != ResultCode.SUCCESS) |
| | | { |
| | | operation.setResultCode(resultCode); |
| | | operation.setErrorMessage(modifyOperation.getErrorMessage()); |
| | | operation.setReferralURLs(modifyOperation.getReferralURLs()); |
| | | return; |
| | | } |
| | | |
| | | |
| | | // If there were any password policy state changes, we need to apply |
| | | // them using a root connection because the end user may not have |
| | | // sufficient access to apply them. This is less efficient than |
| | | // doing them all in the same modification, but it's safer. |
| | | List<Modification> pwPolicyMods = pwPolicyState.getModifications(); |
| | | if (! pwPolicyMods.isEmpty()) |
| | | { |
| | | InternalClientConnection rootConnection = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modOp = |
| | | rootConnection.processModify(userDN, pwPolicyMods); |
| | | if (modOp.getResultCode() != ResultCode.SUCCESS) |
| | | { |
| | | // At this point, the user's password is already changed so there's |
| | | // not much point in returning a non-success result. However, we |
| | | // should at least log that something went wrong. |
| | | ErrorLogger.logError(WARN_EXTOP_PASSMOD_CANNOT_UPDATE_PWP_STATE.get( |
| | | String.valueOf(userDN), |
| | | String.valueOf(modOp.getResultCode()), |
| | | modOp.getErrorMessage())); |
| | | } |
| | | } |
| | | |
| | | |
| | | // If we've gotten here, then everything is OK, so indicate that the |
| | | // operation was successful. |
| | | operation.setResultCode(ResultCode.SUCCESS); |
| | | |
| | | // Save attachments for post-op plugins (e.g. Samba password plugin). |
| | | operation.setAttachment(AUTHZ_DN_ATTACHMENT, userDN); |
| | | operation.setAttachment(PWD_ATTRIBUTE_ATTACHMENT, pwPolicyState |
| | | .getAuthenticationPolicy().getPasswordAttribute()); |
| | | if (!isPreEncoded) |
| | | { |
| | | operation.setAttachment(CLEAR_PWD_ATTACHMENT, newPassword); |
| | | } |
| | | operation.setAttachment(ENCODED_PWD_ATTACHMENT, encodedPasswords); |
| | | |
| | | // If a password was generated, then include it in the response. |
| | | if (generatedPassword) |
| | | { |
| | | ByteStringBuilder builder = new ByteStringBuilder(); |
| | | ASN1Writer writer = ASN1.getWriter(builder); |
| | | |
| | | try |
| | | { |
| | | writer.writeStartSequence(); |
| | | writer.writeOctetString(TYPE_PASSWORD_MODIFY_GENERATED_PASSWORD, |
| | | newPassword); |
| | | writer.writeEndSequence(); |
| | | } |
| | | catch (IOException e) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | operation.setResponseValue(builder.toByteString()); |
| | | } |
| | | |
| | | |
| | | // If this was a self password change, and the client is authenticated |
| | | // as the user whose password was changed, then clear the "must change |
| | | // password" flag in the client connection. Note that we're using the |
| | | // authentication DN rather than the authorization DN in this case to |
| | | // avoid mistakenly clearing the flag for the wrong user. |
| | | if (selfChange && (authInfo.getAuthenticationDN() != null) && |
| | | (authInfo.getAuthenticationDN().equals(userDN))) |
| | | { |
| | | operation.getClientConnection().setMustChangePassword(false); |
| | | } |
| | | |
| | | |
| | | // If the password policy control was requested, then add the |
| | | // appropriate response control. |
| | | if (pwPolicyRequested) |
| | | { |
| | | operation.addResponseControl( |
| | | new PasswordPolicyResponseControl(pwPolicyWarningType, |
| | | pwPolicyWarningValue, |
| | | pwPolicyErrorType)); |
| | | } |
| | | |
| | | // Handle Account Status Notifications that may be needed. |
| | | // They are not handled by the backend for internal operations. |
| | | List<AttributeValue> currentPasswords = null; |
| | | if (oldPassword != null) |
| | | { |
| | | currentPasswords = new ArrayList<AttributeValue>(1); |
| | | currentPasswords.add(AttributeValues |
| | | .create(oldPassword, oldPassword)); |
| | | } |
| | | List<AttributeValue> newPasswords = null; |
| | | if (newPassword != null) |
| | | { |
| | | newPasswords = new ArrayList<AttributeValue>(1); |
| | | newPasswords.add(AttributeValues |
| | | .create(newPassword, newPassword)); |
| | | } |
| | | if (selfChange) |
| | | { |
| | | Message message = INFO_MODIFY_PASSWORD_CHANGED.get(); |
| | | pwPolicyState.generateAccountStatusNotification( |
| | | AccountStatusNotificationType.PASSWORD_CHANGED, |
| | | userEntry, message, |
| | | AccountStatusNotification.createProperties(pwPolicyState, false, |
| | | -1, currentPasswords, newPasswords)); |
| | | } |
| | | else |
| | | { |
| | | if (selfChange && (requestorEntry == null)) |
| | | { |
| | | requestorEntry = userEntry; |
| | | } |
| | | |
| | | // Get an internal connection and use it to perform the modification. |
| | | boolean isRoot = DirectoryServer.isRootDN(requestorEntry.getDN()); |
| | | AuthenticationInfo authInfo = new AuthenticationInfo(requestorEntry, |
| | | isRoot); |
| | | InternalClientConnection internalConnection = new |
| | | InternalClientConnection(authInfo); |
| | | |
| | | ModifyOperation modifyOperation = |
| | | internalConnection.processModify(userDN, modList); |
| | | ResultCode resultCode = modifyOperation.getResultCode(); |
| | | if (resultCode != ResultCode.SUCCESS) |
| | | { |
| | | operation.setResultCode(resultCode); |
| | | operation.setErrorMessage(modifyOperation.getErrorMessage()); |
| | | operation.setReferralURLs(modifyOperation.getReferralURLs()); |
| | | return; |
| | | } |
| | | |
| | | |
| | | // If there were any password policy state changes, we need to apply |
| | | // them using a root connection because the end user may not have |
| | | // sufficient access to apply them. This is less efficient than |
| | | // doing them all in the same modification, but it's safer. |
| | | List<Modification> pwPolicyMods = pwPolicyState.getModifications(); |
| | | if (! pwPolicyMods.isEmpty()) |
| | | { |
| | | InternalClientConnection rootConnection = |
| | | InternalClientConnection.getRootConnection(); |
| | | ModifyOperation modOp = |
| | | rootConnection.processModify(userDN, pwPolicyMods); |
| | | if (modOp.getResultCode() != ResultCode.SUCCESS) |
| | | { |
| | | // At this point, the user's password is already changed so there's |
| | | // not much point in returning a non-success result. However, we |
| | | // should at least log that something went wrong. |
| | | Message message = WARN_EXTOP_PASSMOD_CANNOT_UPDATE_PWP_STATE.get( |
| | | String.valueOf(userDN), |
| | | String.valueOf(modOp.getResultCode()), |
| | | modOp.getErrorMessage()); |
| | | ErrorLogger.logError(message); |
| | | } |
| | | } |
| | | |
| | | |
| | | // If we've gotten here, then everything is OK, so indicate that the |
| | | // operation was successful. |
| | | operation.setResultCode(ResultCode.SUCCESS); |
| | | |
| | | // Save attachments for post-op plugins (e.g. Samba password plugin). |
| | | operation.setAttachment(AUTHZ_DN_ATTACHMENT, userDN); |
| | | operation.setAttachment(PWD_ATTRIBUTE_ATTACHMENT, pwPolicyState |
| | | .getAuthenticationPolicy().getPasswordAttribute()); |
| | | if (!isPreEncoded) |
| | | { |
| | | operation.setAttachment(CLEAR_PWD_ATTACHMENT, newPassword); |
| | | } |
| | | operation.setAttachment(ENCODED_PWD_ATTACHMENT, encodedPasswords); |
| | | |
| | | // If a password was generated, then include it in the response. |
| | | if (generatedPassword) |
| | | { |
| | | ByteStringBuilder builder = new ByteStringBuilder(); |
| | | ASN1Writer writer = ASN1.getWriter(builder); |
| | | |
| | | try |
| | | { |
| | | writer.writeStartSequence(); |
| | | writer.writeOctetString(TYPE_PASSWORD_MODIFY_GENERATED_PASSWORD, |
| | | newPassword); |
| | | writer.writeEndSequence(); |
| | | } |
| | | catch(Exception e) |
| | | { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | operation.setResponseValue(builder.toByteString()); |
| | | } |
| | | |
| | | |
| | | // If this was a self password change, and the client is authenticated |
| | | // as the user whose password was changed, then clear the "must change |
| | | // password" flag in the client connection. Note that we're using the |
| | | // authentication DN rather than the authorization DN in this case to |
| | | // avoid mistakenly clearing the flag for the wrong user. |
| | | if (selfChange && (authInfo.getAuthenticationDN() != null) && |
| | | (authInfo.getAuthenticationDN().equals(userDN))) |
| | | { |
| | | operation.getClientConnection().setMustChangePassword(false); |
| | | } |
| | | |
| | | |
| | | // If the password policy control was requested, then add the |
| | | // appropriate response control. |
| | | if (pwPolicyRequested) |
| | | { |
| | | operation.addResponseControl( |
| | | new PasswordPolicyResponseControl(pwPolicyWarningType, |
| | | pwPolicyWarningValue, |
| | | pwPolicyErrorType)); |
| | | } |
| | | |
| | | // Handle Account Status Notifications that may be needed. |
| | | // They are not handled by the backend for internal operations. |
| | | List<AttributeValue> currentPasswords = null; |
| | | if (oldPassword != null) |
| | | { |
| | | currentPasswords = new ArrayList<AttributeValue>(1); |
| | | currentPasswords.add(AttributeValues |
| | | .create(oldPassword, oldPassword)); |
| | | } |
| | | List<AttributeValue> newPasswords = null; |
| | | if (newPassword != null) |
| | | { |
| | | newPasswords = new ArrayList<AttributeValue>(1); |
| | | newPasswords.add(AttributeValues |
| | | .create(newPassword, newPassword)); |
| | | } |
| | | if (selfChange) |
| | | { |
| | | Message message = INFO_MODIFY_PASSWORD_CHANGED.get(); |
| | | pwPolicyState.generateAccountStatusNotification( |
| | | AccountStatusNotificationType.PASSWORD_CHANGED, |
| | | userEntry, message, |
| | | AccountStatusNotification.createProperties(pwPolicyState, false, |
| | | -1, currentPasswords, newPasswords)); |
| | | } |
| | | else |
| | | { |
| | | Message message = INFO_MODIFY_PASSWORD_RESET.get(); |
| | | pwPolicyState.generateAccountStatusNotification( |
| | | AccountStatusNotificationType.PASSWORD_RESET, |
| | | userEntry, message, |
| | | AccountStatusNotification.createProperties(pwPolicyState, false, |
| | | -1, currentPasswords, newPasswords)); |
| | | } |
| | | Message message = INFO_MODIFY_PASSWORD_RESET.get(); |
| | | pwPolicyState.generateAccountStatusNotification( |
| | | AccountStatusNotificationType.PASSWORD_RESET, |
| | | userEntry, message, |
| | | AccountStatusNotification.createProperties(pwPolicyState, false, |
| | | -1, currentPasswords, newPasswords)); |
| | | } |
| | | } |
| | | finally |
| | |
| | | operation.appendErrorMessage(de.getMessageObject()); |
| | | operation.setMatchedDN(de.getMatchedDN()); |
| | | operation.setReferralURLs(de.getReferralURLs()); |
| | | |
| | | return null; |
| | | } |
| | | } |
| | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String getExtendedOperationOID() |
| | | { |
| | | return OID_PASSWORD_MODIFY_REQUEST; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String getExtendedOperationName() |
| | | { |
| | | return "Password Modify"; |
| | | } |
| | | } |
| | | |