/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt * or http://forgerock.org/license/CDDLv1.0.html. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at legal-notices/CDDLv1_0.txt. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2010 Sun Microsystems, Inc. * Portions Copyright 2011 ForgeRock AS */ package com.forgerock.opendj.ldap.extensions; import static com.forgerock.opendj.util.StaticUtils.formatAsGeneralizedTime; import static com.forgerock.opendj.util.StaticUtils.getExceptionMessage; import static org.forgerock.opendj.ldap.CoreMessages.ERR_PWPSTATE_EXTOP_DECODE_FAILURE; import static org.forgerock.opendj.ldap.CoreMessages.ERR_PWPSTATE_EXTOP_NO_REQUEST_VALUE; import static org.forgerock.opendj.ldap.CoreMessages.ERR_PWPSTATE_EXTOP_UNKNOWN_OP_TYPE; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import org.forgerock.i18n.LocalizableMessage; import org.forgerock.opendj.asn1.ASN1; import org.forgerock.opendj.asn1.ASN1Reader; import org.forgerock.opendj.asn1.ASN1Writer; import org.forgerock.opendj.ldap.ByteString; import org.forgerock.opendj.ldap.ByteStringBuilder; import org.forgerock.opendj.ldap.DN; import org.forgerock.opendj.ldap.DecodeException; import org.forgerock.opendj.ldap.DecodeOptions; import org.forgerock.opendj.ldap.ResultCode; import org.forgerock.opendj.ldap.controls.Control; import org.forgerock.opendj.ldap.requests.AbstractExtendedRequest; import org.forgerock.opendj.ldap.requests.ExtendedRequest; import org.forgerock.opendj.ldap.requests.ExtendedRequestDecoder; import org.forgerock.opendj.ldap.responses.AbstractExtendedResultDecoder; import org.forgerock.opendj.ldap.responses.ExtendedResult; import org.forgerock.opendj.ldap.responses.ExtendedResultDecoder; import com.forgerock.opendj.util.Validator; /** * This class implements an LDAP extended operation that can be used to query * and update elements of the Directory Server password policy state for a given * user. The ASN.1 definition for the value of the extended request is:
* *
 * PasswordPolicyStateValue ::= SEQUENCE {
 *      targetUser     LDAPDN
 *      operations     SEQUENCE OF PasswordPolicyStateOperation OPTIONAL }
 * PasswordPolicyStateOperation ::= SEQUENCE {
 *      opType       ENUMERATED {
 *           getPasswordPolicyDN                          (0),
 *           getAccountDisabledState                      (1),
 *           setAccountDisabledState                      (2),
 *           clearAccountDisabledState                    (3),
 *           getAccountExpirationTime                     (4),
 *           setAccountExpirationTime                     (5),
 *           clearAccountExpirationTime                   (6),
 *           getSecondsUntilAccountExpiration             (7),
 *           getPasswordChangedTime                       (8),
 *           setPasswordChangedTime                       (9),
 *           clearPasswordChangedTime                     (10),
 *           getPasswordExpirationWarnedTime              (11),
 *           setPasswordExpirationWarnedTime              (12),
 *           clearPasswordExpirationWarnedTime            (13),
 *           getSecondsUntilPasswordExpiration            (14),
 *           getSecondsUntilPasswordExpirationWarning     (15),
 *           getAuthenticationFailureTimes                (16),
 *           addAuthenticationFailureTime                 (17),
 *           setAuthenticationFailureTimes                (18),
 *           clearAuthenticationFailureTimes              (19),
 *           getSecondsUntilAuthenticationFailureUnlock   (20),
 *           getRemainingAuthenticationFailureCount       (21),
 *           getLastLoginTime                             (22),
 *           setLastLoginTime                             (23),
 *           clearLastLoginTime                           (24),
 *           getSecondsUntilIdleLockout                   (25),
 *           getPasswordResetState                        (26),
 *           setPasswordResetState                        (27),
 *           clearPasswordResetState                      (28),
 *           getSecondsUntilPasswordResetLockout          (29),
 *           getGraceLoginUseTimes                        (30),
 *           addGraceLoginUseTime                         (31),
 *           setGraceLoginUseTimes                        (32),
 *           clearGraceLoginUseTimes                      (33),
 *           getRemainingGraceLoginCount                  (34),
 *           getPasswordChangedByRequiredTime             (35),
 *           setPasswordChangedByRequiredTime             (36),
 *           clearPasswordChangedByRequiredTime           (37),
 *           getSecondsUntilRequiredChangeTime            (38),
 *           getPasswordHistory                           (39),
 *           clearPasswordHistory                         (40),
 *           ... },
 *      opValues     SEQUENCE OF OCTET STRING OPTIONAL }
 * 
* *
* Both the request and response values use the same encoded form, and they both * use the same OID of "1.3.6.1.4.1.26027.1.6.1". The response value will only * include get* elements. If the request did not include any operations, then * the response will include all get* elements; otherwise, the response will * only include the get* elements that correspond to the state fields referenced * in the request (regardless of whether that operation was included in a get*, * set*, add*, remove*, or clear* operation). */ public final class PasswordPolicyStateExtendedRequest extends AbstractExtendedRequest implements PasswordPolicyStateOperationContainer { private static final class MultiValueOperation implements PasswordPolicyStateOperation { private final PasswordPolicyStateOperationType property; private final List values; private MultiValueOperation(final PasswordPolicyStateOperationType property, final ByteString value) { this.property = property; this.values = Collections.singletonList(value); } private MultiValueOperation(final PasswordPolicyStateOperationType property, final List values) { this.property = property; this.values = values; } public PasswordPolicyStateOperationType getOperationType() { return property; } public Iterable getValues() { return values; } /** * {@inheritDoc} */ @Override public String toString() { return property.toString() + ": " + values; } } private static final class RequestDecoder implements ExtendedRequestDecoder { public PasswordPolicyStateExtendedRequest decodeExtendedRequest( final ExtendedRequest request, final DecodeOptions options) throws DecodeException { final ByteString requestValue = request.getValue(); if ((requestValue == null) || (requestValue.length() <= 0)) { throw DecodeException.error(ERR_PWPSTATE_EXTOP_NO_REQUEST_VALUE.get()); } try { final ASN1Reader reader = ASN1.getReader(requestValue); reader.readStartSequence(); // Read the target user DN final PasswordPolicyStateExtendedRequest newRequest = new PasswordPolicyStateExtendedRequest(reader.readOctetStringAsString()); decodeOperations(reader, newRequest); reader.readEndSequence(); for (final Control control : request.getControls()) { newRequest.addControl(control); } return newRequest; } catch (final IOException ioe) { final LocalizableMessage message = ERR_PWPSTATE_EXTOP_DECODE_FAILURE.get(getExceptionMessage(ioe)); throw DecodeException.error(message, ioe); } } } private static final class ResultDecoder extends AbstractExtendedResultDecoder { /** * {@inheritDoc} */ public PasswordPolicyStateExtendedResult newExtendedErrorResult( final ResultCode resultCode, final String matchedDN, final String diagnosticMessage) { if (!resultCode.isExceptional()) { // A successful response must contain a response name and // value. throw new IllegalArgumentException("No response name and value for result code " + resultCode.intValue()); } return new PasswordPolicyStateExtendedResult(resultCode, (String) null).setMatchedDN( matchedDN).setDiagnosticMessage(diagnosticMessage); } public PasswordPolicyStateExtendedResult decodeExtendedResult(final ExtendedResult result, final DecodeOptions options) throws DecodeException { final ResultCode resultCode = result.getResultCode(); final ByteString responseValue = result.getValue(); if (!resultCode.isExceptional() && ((responseValue == null) || (responseValue.length() <= 0))) { throw DecodeException.error(ERR_PWPSTATE_EXTOP_NO_REQUEST_VALUE.get()); } try { final ASN1Reader reader = ASN1.getReader(responseValue); reader.readStartSequence(); // Read the target user DN final PasswordPolicyStateExtendedResult newResult = new PasswordPolicyStateExtendedResult(resultCode, reader .readOctetStringAsString()).setMatchedDN(result.getMatchedDN()) .setDiagnosticMessage(result.getDiagnosticMessage()); decodeOperations(reader, newResult); reader.readEndSequence(); for (final Control control : result.getControls()) { newResult.addControl(control); } return newResult; } catch (final IOException ioe) { final LocalizableMessage message = ERR_PWPSTATE_EXTOP_DECODE_FAILURE.get(getExceptionMessage(ioe)); throw DecodeException.error(message, ioe); } } } /** * The OID for the password policy state extended operation (both the * request and response types). */ public static final String OID = "1.3.6.1.4.1.26027.1.6.1"; private final String targetUser; private final List operations = new ArrayList(); static final String PASSWORD_POLICY_DN_NAME = "Password Policy DN"; static final String ACCOUNT_DISABLED_STATE_NAME = "Account Disabled State"; static final String ACCOUNT_EXPIRATION_TIME_NAME = "Account Expiration Time"; static final String SECONDS_UNTIL_ACCOUNT_EXPIRATION_NAME = "Seconds Until Account Expiration"; static final String PASSWORD_CHANGED_TIME_NAME = "Password Changed Time"; static final String PASSWORD_EXPIRATION_WARNED_TIME_NAME = "Password Expiration Warned Time"; static final String SECONDS_UNTIL_PASSWORD_EXPIRATION_NAME = "Seconds Until Password Expiration"; static final String SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING_NAME = "Seconds Until Password Expiration Warning"; static final String AUTHENTICATION_FAILURE_TIMES_NAME = "Authentication Failure Times"; static final String SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK_NAME = "Seconds Until Authentication Failure Unlock"; static final String REMAINING_AUTHENTICATION_FAILURE_COUNT_NAME = "Remaining Authentication Failure Count"; static final String LAST_LOGIN_TIME_NAME = "Last Login Time"; static final String SECONDS_UNTIL_IDLE_LOCKOUT_NAME = "Seconds Until Idle Lockout"; static final String PASSWORD_RESET_STATE_NAME = "Password Reset State"; static final String SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT_NAME = "Seconds Until Password Reset Lockout"; static final String GRACE_LOGIN_USE_TIMES_NAME = "Grace Login Use Times"; static final String REMAINING_GRACE_LOGIN_COUNT_NAME = "Remaining Grace Login Count"; static final String PASSWORD_CHANGED_BY_REQUIRED_TIME_NAME = "Password Changed By Required Time"; static final String SECONDS_UNTIL_REQUIRED_CHANGE_TIME_NAME = "Seconds Until Required Change Time"; static final String PASSWORD_HISTORY_NAME = "Password History"; /** * A decoder which can be used to decode password policy state extended * operation requests. */ public static final RequestDecoder REQUEST_DECODER = new RequestDecoder(); // No need to expose this. private static final ResultDecoder RESULT_DECODER = new ResultDecoder(); static ByteString encode(final String targetUser, final List operations) { final ByteStringBuilder buffer = new ByteStringBuilder(6); final ASN1Writer writer = ASN1.getWriter(buffer); try { writer.writeStartSequence(); writer.writeOctetString(targetUser); if (!operations.isEmpty()) { writer.writeStartSequence(); for (final PasswordPolicyStateOperation operation : operations) { writer.writeStartSequence(); writer.writeEnumerated(operation.getOperationType().ordinal()); if (operation.getValues() != null) { writer.writeStartSequence(); for (final ByteString value : operation.getValues()) { writer.writeOctetString(value); } writer.writeEndSequence(); } writer.writeEndSequence(); } writer.writeEndSequence(); } writer.writeEndSequence(); } catch (final IOException ioe) { // This should never happen unless there is a bug somewhere. throw new RuntimeException(ioe); } return buffer.toByteString(); } private static void decodeOperations(final ASN1Reader reader, final PasswordPolicyStateOperationContainer container) throws IOException, DecodeException { // See if we have operations if (reader.hasNextElement()) { reader.readStartSequence(); int opType; PasswordPolicyStateOperationType type; while (reader.hasNextElement()) { reader.readStartSequence(); // Read the opType opType = reader.readEnumerated(); try { type = PasswordPolicyStateOperationType.values()[opType]; } catch (final IndexOutOfBoundsException iobe) { throw DecodeException.error(ERR_PWPSTATE_EXTOP_UNKNOWN_OP_TYPE.get(String .valueOf(opType)), iobe); } // See if we have any values if (reader.hasNextElement()) { reader.readStartSequence(); final ArrayList values = new ArrayList(); while (reader.hasNextElement()) { values.add(reader.readOctetString()); } reader.readEndSequence(); container.addOperation(new MultiValueOperation(type, values)); } else { container.addOperation(type); } reader.readEndSequence(); } reader.readEndSequence(); } } /** * Creates a new password policy state extended request using the provided * user name. * * @param targetUser * The name of the user. */ public PasswordPolicyStateExtendedRequest(final DN targetUser) { Validator.ensureNotNull(targetUser); this.targetUser = targetUser.toString(); } /** * Creates a new password policy state extended request using the provided * user name. * * @param targetUser * The name of the user. */ public PasswordPolicyStateExtendedRequest(final String targetUser) { Validator.ensureNotNull(targetUser); this.targetUser = targetUser; } /** * Adds the provided authentication failure time to this request. * * @param date * The authentication failure time. */ public void addAuthenticationFailureTime(final Date date) { if (date == null) { operations.add(PasswordPolicyStateOperationType.ADD_AUTHENTICATION_FAILURE_TIMES); } else { operations.add(new MultiValueOperation( PasswordPolicyStateOperationType.ADD_AUTHENTICATION_FAILURE_TIMES, ByteString .valueOf(formatAsGeneralizedTime(date)))); } } /** * Adds the provided grace login use time to this request. * * @param date * The grace login use time. */ public void addGraceLoginUseTime(final Date date) { if (date == null) { operations.add(PasswordPolicyStateOperationType.ADD_GRACE_LOGIN_USE_TIME); } else { operations.add(new MultiValueOperation( PasswordPolicyStateOperationType.ADD_GRACE_LOGIN_USE_TIME, ByteString .valueOf(formatAsGeneralizedTime(date)))); } } /** * {@inheritDoc} */ public void addOperation(final PasswordPolicyStateOperation operation) { operations.add(operation); } /** * Clears the account disabled state. */ public void clearAccountDisabledState() { operations.add(PasswordPolicyStateOperationType.CLEAR_ACCOUNT_DISABLED_STATE); } /** * Clears the account expiration time. */ public void clearAccountExpirationTime() { operations.add(PasswordPolicyStateOperationType.CLEAR_ACCOUNT_EXPIRATION_TIME); } /** * Clears the authentication failure times. */ public void clearAuthenticationFailureTimes() { operations.add(PasswordPolicyStateOperationType.CLEAR_AUTHENTICATION_FAILURE_TIMES); } /** * Clears the grace login use times. */ public void clearGraceLoginUseTimes() { operations.add(PasswordPolicyStateOperationType.CLEAR_GRACE_LOGIN_USE_TIMES); } /** * Clears the last login time. */ public void clearLastLoginTime() { operations.add(PasswordPolicyStateOperationType.CLEAR_LAST_LOGIN_TIME); } /** * Clears the password changed by required time. */ public void clearPasswordChangedByRequiredTime() { operations.add(PasswordPolicyStateOperationType.CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME); } /** * Clears the password changed time. */ public void clearPasswordChangedTime() { operations.add(PasswordPolicyStateOperationType.CLEAR_PASSWORD_CHANGED_TIME); } /** * Clears the password expiration warned time. */ public void clearPasswordExpirationWarnedTime() { operations.add(PasswordPolicyStateOperationType.CLEAR_PASSWORD_EXPIRATION_WARNED_TIME); } /** * Clears the password history. */ public void clearPasswordHistory() { operations.add(PasswordPolicyStateOperationType.CLEAR_PASSWORD_HISTORY); } /** * Clears the password reset state. */ public void clearPasswordResetState() { operations.add(PasswordPolicyStateOperationType.CLEAR_PASSWORD_RESET_STATE); } /** * {@inheritDoc} */ @Override public String getOID() { return OID; } /** * {@inheritDoc} */ public Iterable getOperations() { return operations; } /** * {@inheritDoc} */ @Override public ExtendedResultDecoder getResultDecoder() { return RESULT_DECODER; } /** * {@inheritDoc} */ @Override public ByteString getValue() { return encode(targetUser, operations); } /** * {@inheritDoc} */ @Override public boolean hasValue() { return true; } /** * Returns the account disabled state. */ public void requestAccountDisabledState() { operations.add(PasswordPolicyStateOperationType.GET_ACCOUNT_DISABLED_STATE); } /** * Returns the account expiration time. */ public void requestAccountExpirationTime() { operations.add(PasswordPolicyStateOperationType.GET_ACCOUNT_EXPIRATION_TIME); } /** * Returns the authentication failure times. */ public void requestAuthenticationFailureTimes() { operations.add(PasswordPolicyStateOperationType.GET_AUTHENTICATION_FAILURE_TIMES); } /** * Returns the grace login use times. */ public void requestGraceLoginUseTimes() { operations.add(PasswordPolicyStateOperationType.GET_GRACE_LOGIN_USE_TIMES); } /** * Returns the last login time. */ public void requestLastLoginTime() { operations.add(PasswordPolicyStateOperationType.GET_LAST_LOGIN_TIME); } /** * Returns the password changed by required time. */ public void requestPasswordChangedByRequiredTime() { operations.add(PasswordPolicyStateOperationType.GET_PASSWORD_CHANGED_BY_REQUIRED_TIME); } /** * Returns the password changed time. */ public void requestPasswordChangedTime() { operations.add(PasswordPolicyStateOperationType.GET_PASSWORD_CHANGED_TIME); } /** * Returns the password expiration warned time. */ public void requestPasswordExpirationWarnedTime() { operations.add(PasswordPolicyStateOperationType.GET_PASSWORD_EXPIRATION_WARNED_TIME); } /** * Returns the password history. */ public void requestPasswordHistory() { operations.add(PasswordPolicyStateOperationType.GET_PASSWORD_HISTORY); } /** * Returns the password policy DN. */ public void requestPasswordPolicyDN() { operations.add(PasswordPolicyStateOperationType.GET_PASSWORD_POLICY_DN); } /** * Returns the password reset state. */ public void requestPasswordResetState() { operations.add(PasswordPolicyStateOperationType.GET_PASSWORD_RESET_STATE); } /** * Returns the remaining authentication failure count. */ public void requestRemainingAuthenticationFailureCount() { operations.add(PasswordPolicyStateOperationType.GET_REMAINING_AUTHENTICATION_FAILURE_COUNT); } /** * Returns the remaining grace login count. */ public void requestRemainingGraceLoginCount() { operations.add(PasswordPolicyStateOperationType.GET_REMAINING_GRACE_LOGIN_COUNT); } /** * Returns the seconds until account expiration. */ public void requestSecondsUntilAccountExpiration() { operations.add(PasswordPolicyStateOperationType.GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION); } /** * Returns the seconds until authentication failure unlock. */ public void requestSecondsUntilAuthenticationFailureUnlock() { operations .add(PasswordPolicyStateOperationType.GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK); } /** * Returns the seconds until idle lockout. */ public void requestSecondsUntilIdleLockout() { operations.add(PasswordPolicyStateOperationType.GET_SECONDS_UNTIL_IDLE_LOCKOUT); } /** * Returns the seconds until password expiration. */ public void requestSecondsUntilPasswordExpiration() { operations.add(PasswordPolicyStateOperationType.GET_SECONDS_UNTIL_PASSWORD_EXPIRATION); } /** * Returns the seconds until password expiration warning. */ public void requestSecondsUntilPasswordExpirationWarning() { operations .add(PasswordPolicyStateOperationType.GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING); } /** * Returns the seconds until password reset lockout. */ public void requestSecondsUntilPasswordResetLockout() { operations.add(PasswordPolicyStateOperationType.GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT); } /** * Returns the seconds until required change time. */ public void requestSecondsUntilRequiredChangeTime() { operations.add(PasswordPolicyStateOperationType.GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME); } /** * Sets the account disabled state. * * @param state * The account disabled state. */ public void setAccountDisabledState(final boolean state) { operations.add(new MultiValueOperation( PasswordPolicyStateOperationType.SET_ACCOUNT_DISABLED_STATE, ByteString .valueOf(String.valueOf(state)))); } /** * Sets the account expiration time. * * @param date * The account expiration time. */ public void setAccountExpirationTime(final Date date) { if (date == null) { operations.add(PasswordPolicyStateOperationType.SET_ACCOUNT_EXPIRATION_TIME); } else { operations.add(new MultiValueOperation( PasswordPolicyStateOperationType.SET_ACCOUNT_EXPIRATION_TIME, ByteString .valueOf(formatAsGeneralizedTime(date)))); } } /** * Sets the authentication failure times. * * @param dates * The authentication failure times. */ public void setAuthenticationFailureTimes(final Date... dates) { if (dates == null) { operations.add(PasswordPolicyStateOperationType.SET_AUTHENTICATION_FAILURE_TIMES); } else { final ArrayList times = new ArrayList(dates.length); for (final Date date : dates) { times.add(ByteString.valueOf(formatAsGeneralizedTime(date))); } operations.add(new MultiValueOperation( PasswordPolicyStateOperationType.SET_AUTHENTICATION_FAILURE_TIMES, times)); } } /** * Sets the grace login use times. * * @param dates * The grace login use times. */ public void setGraceLoginUseTimes(final Date... dates) { if (dates == null) { operations.add(PasswordPolicyStateOperationType.SET_GRACE_LOGIN_USE_TIMES); } else { final ArrayList times = new ArrayList(dates.length); for (final Date date : dates) { times.add(ByteString.valueOf(formatAsGeneralizedTime(date))); } operations.add(new MultiValueOperation( PasswordPolicyStateOperationType.SET_GRACE_LOGIN_USE_TIMES, times)); } } /** * Sets the last login time. * * @param date * The last login time. */ public void setLastLoginTime(final Date date) { if (date == null) { operations.add(PasswordPolicyStateOperationType.SET_LAST_LOGIN_TIME); } else { operations.add(new MultiValueOperation( PasswordPolicyStateOperationType.SET_LAST_LOGIN_TIME, ByteString .valueOf(formatAsGeneralizedTime(date)))); } } /** * Sets the password changed by required time. * * @param state * The password changed by required time. */ public void setPasswordChangedByRequiredTime(final boolean state) { operations.add(new MultiValueOperation( PasswordPolicyStateOperationType.SET_PASSWORD_CHANGED_BY_REQUIRED_TIME, ByteString .valueOf(String.valueOf(state)))); } /** * Sets the password changed time. * * @param date * The password changed time. */ public void setPasswordChangedTime(final Date date) { if (date == null) { operations.add(PasswordPolicyStateOperationType.SET_PASSWORD_CHANGED_TIME); } else { operations.add(new MultiValueOperation( PasswordPolicyStateOperationType.SET_PASSWORD_CHANGED_TIME, ByteString .valueOf(formatAsGeneralizedTime(date)))); } } /** * Sets the password expiration warned time. * * @param date * The password expiration warned time. */ public void setPasswordExpirationWarnedTime(final Date date) { if (date == null) { operations.add(PasswordPolicyStateOperationType.SET_PASSWORD_EXPIRATION_WARNED_TIME); } else { operations.add(new MultiValueOperation( PasswordPolicyStateOperationType.SET_PASSWORD_EXPIRATION_WARNED_TIME, ByteString.valueOf(formatAsGeneralizedTime(date)))); } } /** * Sets the password reset state. * * @param state * The password reset state. */ public void setPasswordResetState(final boolean state) { operations.add(new MultiValueOperation( PasswordPolicyStateOperationType.SET_PASSWORD_RESET_STATE, ByteString .valueOf(String.valueOf(state)))); } /** * {@inheritDoc} */ @Override public String toString() { final StringBuilder builder = new StringBuilder(); builder.append("PasswordPolicyStateExtendedRequest(requestName="); builder.append(getOID()); builder.append(", targetUser="); builder.append(targetUser); builder.append(", operations="); builder.append(operations); builder.append(", controls="); builder.append(getControls()); builder.append(")"); return builder.toString(); } }