| | |
| | | |
| | | |
| | | |
| | | import java.util.HashSet; |
| | | import java.util.Set; |
| | | |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.ExtendedOperation; |
| | |
| | | |
| | | |
| | | |
| | | // The default set of supported control OIDs for this extended |
| | | // operation. |
| | | private Set<String> supportedControlOIDs = new HashSet<String>(0); |
| | | |
| | | // The default set of supported feature OIDs for this extended |
| | | // operation. |
| | | private Set<String> supportedFeatureOIDs = new HashSet<String>(0); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Initializes this extended operation handler based on the |
| | | * information in the provided configuration entry. It should also |
| | |
| | | */ |
| | | public abstract void processExtendedOperation(ExtendedOperation |
| | | operation); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the OIDs of the controls that may be supported by this |
| | | * extended operation handler. It should be overridden by any |
| | | * extended operation handler which provides special support for one |
| | | * or more controls. |
| | | * |
| | | * @return The OIDs of the controls that may be supported by this |
| | | * extended operation handler. |
| | | */ |
| | | public Set<String> getSupportedControls() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getSupportedControls"); |
| | | |
| | | return supportedControlOIDs; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this extended operation handler supports the |
| | | * specified control. |
| | | * |
| | | * @param controlOID The OID of the control for which to make the |
| | | * determination. |
| | | * |
| | | * @return {@code true} if this extended operation handler does |
| | | * support the requested control, or {@code false} if not. |
| | | */ |
| | | public final boolean supportsControl(String controlOID) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "supportsControl", |
| | | String.valueOf(controlOID)); |
| | | |
| | | return getSupportedControls().contains(controlOID); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the OIDs of the features that may be supported by this |
| | | * extended operation handler. |
| | | * |
| | | * @return The OIDs of the features that may be supported by this |
| | | * extended operation handler. |
| | | */ |
| | | public Set<String> getSupportedFeatures() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getSupportedFeatures"); |
| | | |
| | | return supportedFeatureOIDs; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this extended operation handler supports the |
| | | * specified feature. |
| | | * |
| | | * @param featureOID The OID of the feature for which to make the |
| | | * determination. |
| | | * |
| | | * @return {@code true} if this extended operation handler does |
| | | * support the requested feature, or {@code false} if not. |
| | | */ |
| | | public final boolean supportsFeature(String featureOID) |
| | | { |
| | | assert debugEnter(CLASS_NAME, "supportsFeature", |
| | | String.valueOf(featureOID)); |
| | | |
| | | return getSupportedFeatures().contains(featureOID); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | // Check the set of controls included in the request. If there are any, |
| | | // see if any special processing is required. This should also include |
| | | // taking care of any synchronization that might be needed. |
| | | // NYI |
| | | // Look at the controls included in the request and ensure that all |
| | | // critical controls are supported by the handler. |
| | | List<Control> requestControls = getRequestControls(); |
| | | if ((requestControls != null) && (! requestControls.isEmpty())) |
| | | { |
| | | for (Control c : requestControls) |
| | | { |
| | | if (! c.isCritical()) |
| | | { |
| | | // The control isn't critical, so we don't care if it's supported |
| | | // or not. |
| | | } |
| | | else if (! handler.supportsControl(c.getOID())) |
| | | { |
| | | setResultCode(ResultCode.UNAVAILABLE_CRITICAL_EXTENSION); |
| | | |
| | | int msgID = MSGID_EXTENDED_UNSUPPORTED_CRITICAL_CONTROL; |
| | | appendErrorMessage(getMessage(msgID, String.valueOf(requestOID), |
| | | c.getOID())); |
| | | |
| | | break extendedProcessing; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | // Check to see if the client has permission to perform the |
| | |
| | | import java.util.Iterator; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | import org.opends.server.api.ConfigAddListener; |
| | |
| | | } |
| | | |
| | | |
| | | // If the extended operation handler defines any supported controls and/or |
| | | // features, then register them with the server. |
| | | Set<String> controlOIDs = handler.getSupportedControls(); |
| | | if (controlOIDs != null) |
| | | { |
| | | for (String oid : controlOIDs) |
| | | { |
| | | DirectoryServer.registerSupportedControl(oid); |
| | | } |
| | | } |
| | | |
| | | Set<String> featureOIDs = handler.getSupportedFeatures(); |
| | | if (featureOIDs != null) |
| | | { |
| | | for (String oid : featureOIDs) |
| | | { |
| | | DirectoryServer.registerSupportedFeature(oid); |
| | | } |
| | | } |
| | | |
| | | |
| | | handlers.put(configEntryDN, handler); |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.HashSet; |
| | | import java.util.Set; |
| | | import java.util.concurrent.locks.Lock; |
| | | |
| | | import org.opends.server.api.ClientConnection; |
| | |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.DNConfigAttribute; |
| | | import org.opends.server.controls.PasswordPolicyResponseControl; |
| | | import org.opends.server.controls.PasswordPolicyWarningType; |
| | | import org.opends.server.controls.PasswordPolicyErrorType; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.core.ExtendedOperation; |
| | | import org.opends.server.core.ModifyOperation; |
| | |
| | | import org.opends.server.types.AuthenticationInfo; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.Control; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | |
| | | // The reference to the identity mapper. |
| | | private IdentityMapper identityMapper; |
| | | |
| | | // The set of OIDs for the supported controls. |
| | | private Set<String> supportedControlOIDs; |
| | | |
| | | |
| | | |
| | | /** |
| | |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | |
| | | |
| | | supportedControlOIDs = new HashSet<String>(); |
| | | supportedControlOIDs.add(OID_LDAP_NOOP_OPENLDAP_ASSIGNED); |
| | | supportedControlOIDs.add(OID_PASSWORD_POLICY_CONTROL); |
| | | |
| | | |
| | | DirectoryServer.registerConfigurableComponent(this); |
| | | |
| | | DirectoryServer.registerSupportedExtension(OID_PASSWORD_MODIFY_REQUEST, |
| | |
| | | ByteString newPassword = null; |
| | | |
| | | |
| | | // Look at the set of controls included in the request, if there are any. |
| | | boolean noOpRequested = false; |
| | | boolean pwPolicyRequested = false; |
| | | int pwPolicyWarningValue = 0; |
| | | PasswordPolicyErrorType pwPolicyErrorType = null; |
| | | PasswordPolicyWarningType pwPolicyWarningType = null; |
| | | List<Control> controls = operation.getRequestControls(); |
| | | if (controls != null) |
| | | { |
| | | for (Control c : controls) |
| | | { |
| | | String oid = c.getOID(); |
| | | if (oid.equals(OID_LDAP_NOOP_OPENLDAP_ASSIGNED)) |
| | | { |
| | | noOpRequested = true; |
| | | } |
| | | else if (oid.equals(OID_PASSWORD_POLICY_CONTROL)) |
| | | { |
| | | pwPolicyRequested = true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | // Parse the encoded request, if there is one. |
| | | ByteString requestValue = operation.getRequestValue(); |
| | | if (requestValue != null) |
| | |
| | | userDN.equals(requestorDN)); |
| | | |
| | | |
| | | // See if the account is locked. If so, then reject the request. |
| | | if (pwPolicyState.isDisabled()) |
| | | { |
| | | if (pwPolicyRequested) |
| | | { |
| | | pwPolicyErrorType = |
| | | PasswordPolicyErrorType.ACCOUNT_LOCKED; |
| | | operation.addResponseControl( |
| | | new PasswordPolicyResponseControl(pwPolicyWarningType, |
| | | pwPolicyWarningValue, |
| | | pwPolicyErrorType)); |
| | | } |
| | | |
| | | int msgID = MSGID_EXTOP_PASSMOD_ACCOUNT_DISABLED; |
| | | String message = getMessage(msgID); |
| | | |
| | | if (oldPassword == null) |
| | | { |
| | | operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); |
| | | operation.appendErrorMessage(message); |
| | | } |
| | | else |
| | | { |
| | | operation.setResultCode(ResultCode.INVALID_CREDENTIALS); |
| | | operation.appendAdditionalLogMessage(message); |
| | | } |
| | | |
| | | return; |
| | | } |
| | | else if (selfChange && |
| | | (pwPolicyState.lockedDueToFailures() || |
| | | pwPolicyState.lockedDueToIdleInterval() || |
| | | pwPolicyState.lockedDueToMaximumResetAge())) |
| | | { |
| | | if (pwPolicyRequested) |
| | | { |
| | | pwPolicyErrorType = |
| | | PasswordPolicyErrorType.ACCOUNT_LOCKED; |
| | | operation.addResponseControl( |
| | | new PasswordPolicyResponseControl(pwPolicyWarningType, |
| | | pwPolicyWarningValue, |
| | | pwPolicyErrorType)); |
| | | } |
| | | |
| | | int msgID = MSGID_EXTOP_PASSMOD_ACCOUNT_LOCKED; |
| | | String message = getMessage(msgID); |
| | | |
| | | if (oldPassword == null) |
| | | { |
| | | operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); |
| | | operation.appendErrorMessage(message); |
| | | } |
| | | else |
| | | { |
| | | operation.setResultCode(ResultCode.INVALID_CREDENTIALS); |
| | | operation.appendAdditionalLogMessage(message); |
| | | } |
| | | |
| | | return; |
| | | } |
| | | |
| | | |
| | | // If the current password was provided, then we'll need to verify whether |
| | | // it was correct. If it wasn't provided but this is a self change, then |
| | | // make sure that's OK. |
| | |
| | | |
| | | int msgID = MSGID_EXTOP_PASSMOD_REQUIRE_CURRENT_PW; |
| | | operation.appendErrorMessage(getMessage(msgID)); |
| | | |
| | | if (pwPolicyRequested) |
| | | { |
| | | pwPolicyErrorType = |
| | | PasswordPolicyErrorType.MUST_SUPPLY_OLD_PASSWORD; |
| | | operation.addResponseControl( |
| | | new PasswordPolicyResponseControl(pwPolicyWarningType, |
| | | pwPolicyWarningValue, |
| | | pwPolicyErrorType)); |
| | | } |
| | | |
| | | return; |
| | | } |
| | | } |
| | |
| | | // the request. |
| | | if (selfChange && (! pwPolicyState.allowUserPasswordChanges())) |
| | | { |
| | | if (pwPolicyRequested) |
| | | { |
| | | pwPolicyErrorType = |
| | | PasswordPolicyErrorType.PASSWORD_MOD_NOT_ALLOWED; |
| | | operation.addResponseControl( |
| | | new PasswordPolicyResponseControl(pwPolicyWarningType, |
| | | pwPolicyWarningValue, |
| | | pwPolicyErrorType)); |
| | | } |
| | | |
| | | if (oldPassword == null) |
| | | { |
| | | operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); |
| | |
| | | // then reject it. |
| | | if (selfChange && pwPolicyState.isWithinMinimumAge()) |
| | | { |
| | | if (pwPolicyRequested) |
| | | { |
| | | pwPolicyErrorType = |
| | | PasswordPolicyErrorType.PASSWORD_TOO_YOUNG; |
| | | operation.addResponseControl( |
| | | new PasswordPolicyResponseControl(pwPolicyWarningType, |
| | | pwPolicyWarningValue, |
| | | pwPolicyErrorType)); |
| | | } |
| | | |
| | | if (oldPassword == null) |
| | | { |
| | | operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); |
| | |
| | | if ((selfChange && pwPolicyState.isPasswordExpired() && |
| | | (! pwPolicyState.allowExpiredPasswordChanges()))) |
| | | { |
| | | if (pwPolicyRequested) |
| | | { |
| | | pwPolicyErrorType = |
| | | PasswordPolicyErrorType.PASSWORD_EXPIRED; |
| | | operation.addResponseControl( |
| | | new PasswordPolicyResponseControl(pwPolicyWarningType, |
| | | pwPolicyWarningValue, |
| | | pwPolicyErrorType)); |
| | | } |
| | | |
| | | if (oldPassword == null) |
| | | { |
| | | operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); |
| | |
| | | clearPasswords, |
| | | invalidReason)) |
| | | { |
| | | if (pwPolicyRequested) |
| | | { |
| | | pwPolicyErrorType = |
| | | PasswordPolicyErrorType.INSUFFICIENT_PASSWORD_QUALITY; |
| | | operation.addResponseControl( |
| | | new PasswordPolicyResponseControl(pwPolicyWarningType, |
| | | pwPolicyWarningValue, |
| | | pwPolicyErrorType)); |
| | | } |
| | | |
| | | if (oldPassword == null) |
| | | { |
| | | operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM); |
| | |
| | | modList.addAll(pwPolicyState.getModifications()); |
| | | |
| | | |
| | | // Get an internal connection and use it to perform the modification. |
| | | boolean isRoot = DirectoryServer.isRootDN(requestorDN); |
| | | AuthenticationInfo authInfo = new AuthenticationInfo(requestorDN, isRoot); |
| | | InternalClientConnection internalConnection = new |
| | | InternalClientConnection(authInfo); |
| | | |
| | | ModifyOperation modifyOperation = |
| | | internalConnection.processModify(userDN, modList); |
| | | ResultCode resultCode = modifyOperation.getResultCode(); |
| | | if (resultCode != resultCode.SUCCESS) |
| | | // If the LDAP no-op control was included in the request, then set the |
| | | // appropriate response. Otherwise, process the operation. |
| | | if (noOpRequested) |
| | | { |
| | | operation.setResultCode(resultCode); |
| | | operation.setErrorMessage(modifyOperation.getErrorMessage()); |
| | | operation.setReferralURLs(modifyOperation.getReferralURLs()); |
| | | return; |
| | | operation.appendErrorMessage(getMessage(MSGID_EXTOP_PASSMOD_NOOP)); |
| | | |
| | | // FIXME -- We must set a result code other than SUCCESS. |
| | | operation.setResultCode(ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | // If we've gotten here, then everything is OK, so indicate that the |
| | | // operation was successful. If a password was generated, then include |
| | | // it in the response. |
| | | operation.setResultCode(ResultCode.SUCCESS); |
| | | |
| | | if (generatedPassword) |
| | | else |
| | | { |
| | | ArrayList<ASN1Element> valueElements = new ArrayList<ASN1Element>(1); |
| | | // Get an internal connection and use it to perform the modification. |
| | | boolean isRoot = DirectoryServer.isRootDN(requestorDN); |
| | | AuthenticationInfo authInfo = new AuthenticationInfo(requestorDN, |
| | | isRoot); |
| | | InternalClientConnection internalConnection = new |
| | | InternalClientConnection(authInfo); |
| | | |
| | | ASN1OctetString newPWString = |
| | | new ASN1OctetString(TYPE_PASSWORD_MODIFY_GENERATED_PASSWORD, |
| | | newPassword.value()); |
| | | valueElements.add(newPWString); |
| | | |
| | | ASN1Sequence valueSequence = new ASN1Sequence(valueElements); |
| | | operation.setResponseValue(new ASN1OctetString(valueSequence.encode())); |
| | | } |
| | | 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 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 we've gotten here, then everything is OK, so indicate that the |
| | | // operation was successful. If a password was generated, then include |
| | | // it in the response. |
| | | operation.setResultCode(ResultCode.SUCCESS); |
| | | |
| | | if (generatedPassword) |
| | | { |
| | | ArrayList<ASN1Element> valueElements = new ArrayList<ASN1Element>(1); |
| | | |
| | | ASN1OctetString newPWString = |
| | | new ASN1OctetString(TYPE_PASSWORD_MODIFY_GENERATED_PASSWORD, |
| | | newPassword.value()); |
| | | valueElements.add(newPWString); |
| | | |
| | | ASN1Sequence valueSequence = new ASN1Sequence(valueElements); |
| | | operation.setResponseValue(new ASN1OctetString( |
| | | valueSequence.encode())); |
| | | } |
| | | |
| | | |
| | | // 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)); |
| | | } |
| | | } |
| | | } |
| | | finally |
| | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public Set<String> getSupportedControls() |
| | | { |
| | | assert debugEnter(CLASS_NAME, "getSupportedControls"); |
| | | |
| | | return supportedControlOIDs; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the DN of the configuration entry with which this component is |
| | | * associated. |
| | | * |
| | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if an extended operation |
| | | * cannot be processed because it contains an unsupported critical control. |
| | | * This takes two arguments, which are the OID of the extended request and the |
| | | * OID of the unsupported control. |
| | | */ |
| | | public static final int MSGID_EXTENDED_UNSUPPORTED_CRITICAL_CONTROL = |
| | | CATEGORY_MASK_CORE | SEVERITY_MASK_MILD_ERROR | 570; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Associates a set of generic messages with the message IDs defined |
| | | * in this class. |
| | | */ |
| | |
| | | "There is no extended operation handler registered with " + |
| | | "the Directory Server for handling extended operations " + |
| | | "with a request OID of %s."); |
| | | registerMessage(MSGID_EXTENDED_UNSUPPORTED_CRITICAL_CONTROL, |
| | | "Unable to process the request for extended operation %s " + |
| | | "because it contained an unsupported critical control " + |
| | | "with OID %s."); |
| | | |
| | | |
| | | registerMessage(MSGID_CONNHANDLER_CLOSED_BY_SHUTDOWN, |
| | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if a password change is |
| | | * not actually performed because the request contained the LDAP no-op |
| | | * control. This does not take any arguments. |
| | | */ |
| | | public static final int MSGID_EXTOP_PASSMOD_NOOP = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_WARNING | 380; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the user's account is |
| | | * disabled. This does not take any arguments. |
| | | */ |
| | | public static final int MSGID_EXTOP_PASSMOD_ACCOUNT_DISABLED = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 381; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the user's account is |
| | | * locked. This does not take any arguments. |
| | | */ |
| | | public static final int MSGID_EXTOP_PASSMOD_ACCOUNT_LOCKED = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 382; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Associates a set of generic messages with the message IDs defined in this |
| | | * class. |
| | | */ |
| | |
| | | registerMessage(MSGID_EXTOP_PASSMOD_CANNOT_GET_PW_POLICY, |
| | | "An error occurred while attempting to get the " + |
| | | "password policy for user %s: %s."); |
| | | registerMessage(MSGID_EXTOP_PASSMOD_ACCOUNT_DISABLED, |
| | | "The user account has been administratively disabled."); |
| | | registerMessage(MSGID_EXTOP_PASSMOD_ACCOUNT_LOCKED, |
| | | "The user account is locked."); |
| | | registerMessage(MSGID_EXTOP_PASSMOD_REQUIRE_CURRENT_PW, |
| | | "The current password must be provided for self password " + |
| | | "changes."); |
| | |
| | | registerMessage(MSGID_EXTOP_PASSMOD_CANNOT_ENCODE_PASSWORD, |
| | | "Unable to encode the provided password using the " + |
| | | "default scheme(s): %s."); |
| | | registerMessage(MSGID_EXTOP_PASSMOD_NOOP, |
| | | "The password modify operation was not actually " + |
| | | "performed in the Directory Server because the LDAP " + |
| | | "no-op control was present in the request."); |
| | | |
| | | |
| | | registerMessage(MSGID_NULL_KEYMANAGER_NO_MANAGER, |
| | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used to display warning |
| | | * information included in the password policy response control. This takes |
| | | * two arguments, which are the string representation of the warning type and |
| | | * the integer warning value. |
| | | */ |
| | | public static final int MSGID_LDAPPWMOD_PWPOLICY_WARNING = |
| | | CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 786; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used to display error |
| | | * information included in the password policy response control. This takes |
| | | * a single argument, which is the string representation of the error type. |
| | | */ |
| | | public static final int MSGID_LDAPPWMOD_PWPOLICY_ERROR = |
| | | CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 787; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if an error occurs while |
| | | * trying to decode the password policy response control. This takes a |
| | | * single argument, which is a string representation of the exception that was |
| | | * caught. |
| | | */ |
| | | public static final int MSGID_LDAPPWMOD_CANNOT_DECODE_PWPOLICY_CONTROL = |
| | | CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 788; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Associates a set of generic messages with the message IDs defined in this |
| | | * class. |
| | | */ |
| | |
| | | "The LDAP password modify operation was successful."); |
| | | registerMessage(MSGID_LDAPPWMOD_ADDITIONAL_INFO, |
| | | "Additional Info: %s."); |
| | | registerMessage(MSGID_LDAPPWMOD_PWPOLICY_WARNING, |
| | | "Password Policy Warning: %s = %d."); |
| | | registerMessage(MSGID_LDAPPWMOD_PWPOLICY_ERROR, |
| | | "Password Policy Error: %s."); |
| | | registerMessage(MSGID_LDAPPWMOD_CANNOT_DECODE_PWPOLICY_CONTROL, |
| | | "Unable to decode the password policy response control: " + |
| | | "%s."); |
| | | registerMessage(MSGID_LDAPPWMOD_GENERATED_PASSWORD, |
| | | "Generated Password: %s."); |
| | | registerMessage(MSGID_LDAPPWMOD_UNRECOGNIZED_VALUE_TYPE, |
| | |
| | | import java.util.ArrayList; |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | |
| | | import org.opends.server.controls.PasswordPolicyErrorType; |
| | | import org.opends.server.controls.PasswordPolicyResponseControl; |
| | | import org.opends.server.controls.PasswordPolicyWarningType; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.protocols.asn1.ASN1Element; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | |
| | | } |
| | | |
| | | |
| | | // See if the response included any controls that we recognize, and if so |
| | | // then handle them. |
| | | ArrayList<LDAPControl> responseControls = responseMessage.getControls(); |
| | | if (responseControls != null) |
| | | { |
| | | for (LDAPControl c : responseControls) |
| | | { |
| | | if (c.getOID().equals(OID_PASSWORD_POLICY_CONTROL)) |
| | | { |
| | | try |
| | | { |
| | | PasswordPolicyResponseControl pwPolicyControl = |
| | | PasswordPolicyResponseControl.decodeControl(c.getControl()); |
| | | |
| | | PasswordPolicyWarningType pwPolicyWarningType = |
| | | pwPolicyControl.getWarningType(); |
| | | if (pwPolicyWarningType != null) |
| | | { |
| | | int msgID = MSGID_LDAPPWMOD_PWPOLICY_WARNING; |
| | | String message = getMessage(msgID, pwPolicyWarningType.toString(), |
| | | pwPolicyControl.getWarningValue()); |
| | | out.println(wrapText(message, MAX_LINE_WIDTH)); |
| | | } |
| | | |
| | | PasswordPolicyErrorType pwPolicyErrorType = |
| | | pwPolicyControl.getErrorType(); |
| | | if (pwPolicyErrorType != null) |
| | | { |
| | | int msgID = MSGID_LDAPPWMOD_PWPOLICY_ERROR; |
| | | String message = getMessage(msgID, pwPolicyErrorType.toString()); |
| | | out.println(wrapText(message, MAX_LINE_WIDTH)); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | int msgID = MSGID_LDAPPWMOD_CANNOT_DECODE_PWPOLICY_CONTROL; |
| | | String message = getMessage(msgID, String.valueOf(e)); |
| | | err.println(wrapText(message, MAX_LINE_WIDTH)); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | // See if the response included a generated password. |
| | | ASN1OctetString responseValue = extendedResponse.getValue(); |
| | | if (responseValue != null) |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testSelfChangeCurrentPasswordNewPassword() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testSelfChangeNoCurrentPasswordNewPassword() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testSelfChangeCurrentPasswordNoNewPassword() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testSelfChangeNoCurrentPasswordNoNewPassword() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testAuthenticatedSelfExplicitAuthzIDCurrentNew() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testAuthenticatedSelfImplicitAuthzIDCurrentNew() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testAuthenticatedSelfImplicitAuthzIDNoCurrentNew() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testUnauthenticatedSelfChangeNewPassword() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testUnauthenticatedSelfChangeNoNewPassword() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testAdminResetNewPassword() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testAdminResetNoNewPassword() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testSSLBlindTrust() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testSSLTrustStore() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testStartTLSBlindTrust() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testStartTLSTrustStore() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testBindAndNewPasswordsFromFile() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testCurrentAndNewPasswordsFromFile() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testResetWithInvalidAuthzDN() |
| | | throws Exception |
| | | { |
| | |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testResetOnNonExistentUser() |
| | | throws Exception |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Tests a failure when attempting an administrative reset on a user entry |
| | | * that has been disabled. Also include the password policy control in the |
| | | * request. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testResetOnDisabledUser() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | Entry e = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: password", |
| | | "ds-pwp-account-disabled: true"); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | AddOperation addOperation = |
| | | conn.processAdd(e.getDN(), e.getObjectClasses(), |
| | | e.getUserAttributes(), e.getOperationalAttributes()); |
| | | assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapPort()), |
| | | "-D", "cn=Directory Manager", |
| | | "-w", "password", |
| | | "-a", "dn:uid=test.user,o=test", |
| | | "-n", "newPassword", |
| | | "-J", "pwpolicy:true" |
| | | }; |
| | | |
| | | assertFalse(LDAPPasswordModify.mainPasswordModify(args, false, null, |
| | | null) == 0); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the password modify extended operation in conjunction with a control |
| | | * that is marked critical but that is not supported by the server. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testLDAPNoOpUnsupportedCriticalControl() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | Entry e = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: password"); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | AddOperation addOperation = |
| | | conn.processAdd(e.getDN(), e.getObjectClasses(), |
| | | e.getUserAttributes(), e.getOperationalAttributes()); |
| | | assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapPort()), |
| | | "-D", "cn=Directory Manager", |
| | | "-w", "password", |
| | | "-a", "dn:uid=test.user,o=test", |
| | | "-n", "newPassword", |
| | | "-J", "1.2.3.4:true" |
| | | }; |
| | | |
| | | assertFalse(LDAPPasswordModify.mainPasswordModify(args, false, null, null) |
| | | == 0); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the password modify extended operation in conjunction with the LDAP |
| | | * no-op control using the explicit OID for that control. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testLDAPNoOpExplicitOID() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | Entry e = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: password"); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | AddOperation addOperation = |
| | | conn.processAdd(e.getDN(), e.getObjectClasses(), |
| | | e.getUserAttributes(), e.getOperationalAttributes()); |
| | | assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapPort()), |
| | | "-D", "cn=Directory Manager", |
| | | "-w", "password", |
| | | "-a", "dn:uid=test.user,o=test", |
| | | "-n", "newPassword", |
| | | "-J", OID_LDAP_NOOP_OPENLDAP_ASSIGNED + ":true" |
| | | }; |
| | | |
| | | // FIXME -- Change this whenever the real LDAP No-Op result code is assigned |
| | | assertEquals(LDAPPasswordModify.mainPasswordModify(args, false, null, null), |
| | | 0); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the password modify extended operation in conjunction with the LDAP |
| | | * no-op control using a more user-friendly name instead of an OID. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testLDAPNoOpImplicitOID() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | Entry e = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: password"); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | AddOperation addOperation = |
| | | conn.processAdd(e.getDN(), e.getObjectClasses(), |
| | | e.getUserAttributes(), e.getOperationalAttributes()); |
| | | assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapPort()), |
| | | "-D", "cn=Directory Manager", |
| | | "-w", "password", |
| | | "-a", "dn:uid=test.user,o=test", |
| | | "-n", "newPassword", |
| | | "-J", "noop:true" |
| | | }; |
| | | |
| | | // FIXME -- Change this whenever the real LDAP No-Op result code is assigned |
| | | assertEquals(LDAPPasswordModify.mainPasswordModify(args, false, null, null), |
| | | 0); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the password modify extended operation in conjunction with multiple |
| | | * request controls. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testLDAPMultipleControls() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | Entry e = TestCaseUtils.makeEntry( |
| | | "dn: uid=test.user,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: password"); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | AddOperation addOperation = |
| | | conn.processAdd(e.getDN(), e.getObjectClasses(), |
| | | e.getUserAttributes(), e.getOperationalAttributes()); |
| | | assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | String[] args = |
| | | { |
| | | "-h", "127.0.0.1", |
| | | "-p", String.valueOf(TestCaseUtils.getServerLdapPort()), |
| | | "-D", "cn=Directory Manager", |
| | | "-w", "password", |
| | | "-a", "dn:uid=test.user,o=test", |
| | | "-n", "newPassword", |
| | | "-J", OID_LDAP_NOOP_OPENLDAP_ASSIGNED + ":true", |
| | | "-J", OID_PASSWORD_POLICY_CONTROL + ":true" |
| | | }; |
| | | |
| | | // FIXME -- Change this whenever the real LDAP No-Op result code is assigned |
| | | assertEquals(LDAPPasswordModify.mainPasswordModify(args, false, null, null), |
| | | 0); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the LDAPModify tool with the "--help" option. |
| | | */ |
| | | @Test() |