| | |
| | | |
| | | |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | import org.opends.server.api.ConfigurableComponent; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.std.server.LengthBasedPasswordValidatorCfg; |
| | | import org.opends.server.api.PasswordValidator; |
| | | import org.opends.server.config.ConfigAttribute; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.IntegerConfigAttribute; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.core.Operation; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.ResultCode; |
| | | |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugCaught; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import static org.opends.server.messages.ExtensionsMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | |
| | | |
| | |
| | | * This class provides a password validator that can ensure that the provided |
| | | * password meets minimum and/or maximum length requirements. |
| | | */ |
| | | public class LengthBasedPasswordValidator |
| | | extends PasswordValidator |
| | | implements ConfigurableComponent |
| | | public class LengthBasedPasswordValidator extends |
| | | PasswordValidator<LengthBasedPasswordValidatorCfg> implements |
| | | ConfigurationChangeListener<LengthBasedPasswordValidatorCfg> |
| | | { |
| | | |
| | | |
| | | |
| | | // The DN of the configuration entry for this password validator. |
| | | private DN configEntryDN; |
| | | |
| | | // The maximum number of characters allowed for a password. |
| | | private int maxLength; |
| | | |
| | | // The minimum number of characters allowed for a password. |
| | | private int minLength; |
| | | // The current configuration for this password validator. |
| | | private LengthBasedPasswordValidatorCfg currentConfig; |
| | | |
| | | |
| | | |
| | |
| | | { |
| | | super(); |
| | | |
| | | |
| | | // All initialization must be done in the initializePasswordValidator |
| | | // method. |
| | | } |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializePasswordValidator(ConfigEntry configEntry) |
| | | public void initializePasswordValidator( |
| | | LengthBasedPasswordValidatorCfg configuration) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | configEntryDN = configEntry.getDN(); |
| | | configuration.addLengthBasedChangeListener(this); |
| | | |
| | | currentConfig = configuration; |
| | | |
| | | // Get the configured minimum length. |
| | | minLength = 0; |
| | | int msgID = MSGID_PWLENGTHVALIDATOR_DESCRIPTION_MIN_LENGTH; |
| | | IntegerConfigAttribute minLengthStub = |
| | | new IntegerConfigAttribute(ATTR_PASSWORD_MIN_LENGTH, getMessage(msgID), |
| | | false, false, false, true, 0, false, 0); |
| | | try |
| | | // Make sure that if both the maximum and minimum lengths are set, the |
| | | // maximum length is greater than or equal to the minimum length. |
| | | int maxLength = configuration.getMaximumPasswordLength(); |
| | | int minLength = configuration.getMinimumPasswordLength(); |
| | | if ((maxLength > 0) && (minLength > 0) && (minLength > maxLength)) |
| | | { |
| | | IntegerConfigAttribute minLengthAttr = |
| | | (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(minLengthStub); |
| | | if (minLengthAttr != null) |
| | | { |
| | | minLength = minLengthAttr.activeIntValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_PWLENGTHVALIDATOR_CANNOT_DETERMINE_MIN_LENGTH; |
| | | String message = getMessage(msgID, stackTraceToSingleLineString(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | |
| | | |
| | | // Get the configured maximum length. |
| | | maxLength = 0; |
| | | msgID = MSGID_PWLENGTHVALIDATOR_DESCRIPTION_MAX_LENGTH; |
| | | IntegerConfigAttribute maxLengthStub = |
| | | new IntegerConfigAttribute(ATTR_PASSWORD_MAX_LENGTH, getMessage(msgID), |
| | | false, false, false, true, 0, false, 0); |
| | | try |
| | | { |
| | | IntegerConfigAttribute maxLengthAttr = |
| | | (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(maxLengthStub); |
| | | if (maxLengthAttr != null) |
| | | { |
| | | maxLength = maxLengthAttr.activeIntValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_PWLENGTHVALIDATOR_CANNOT_DETERMINE_MAX_LENGTH; |
| | | String message = getMessage(msgID, stackTraceToSingleLineString(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | |
| | | |
| | | // If both a minimum and a maximum were provided, then make sure the |
| | | // minimum is less than or equal to the maximum. |
| | | if ((minLength > 0) && (maxLength > 0) && (minLength > maxLength)) |
| | | { |
| | | msgID = MSGID_PWLENGTHVALIDATOR_MIN_GREATER_THAN_MAX; |
| | | int msgID = MSGID_PWLENGTHVALIDATOR_MIN_GREATER_THAN_MAX; |
| | | String message = getMessage(msgID, minLength, maxLength); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | |
| | | |
| | | // Register with the Directory Server as a configurable component. |
| | | DirectoryServer.registerConfigurableComponent(this); |
| | | } |
| | | |
| | | |
| | |
| | | @Override() |
| | | public void finalizePasswordValidator() |
| | | { |
| | | DirectoryServer.deregisterConfigurableComponent(this); |
| | | currentConfig.removeLengthBasedChangeListener(this); |
| | | } |
| | | |
| | | |
| | |
| | | Operation operation, Entry userEntry, |
| | | StringBuilder invalidReason) |
| | | { |
| | | LengthBasedPasswordValidatorCfg config = currentConfig; |
| | | |
| | | int numChars = newPassword.stringValue().length(); |
| | | |
| | | int minLength = config.getMinimumPasswordLength(); |
| | | if ((minLength > 0) && (numChars < minLength)) |
| | | { |
| | | invalidReason.append(getMessage(MSGID_PWLENGTHVALIDATOR_TOO_SHORT, |
| | |
| | | return false; |
| | | } |
| | | |
| | | int maxLength = config.getMaximumPasswordLength(); |
| | | if ((maxLength > 0) && (numChars > maxLength)) |
| | | { |
| | | invalidReason.append(getMessage(MSGID_PWLENGTHVALIDATOR_TOO_LONG, |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public DN getConfigurableComponentEntryDN() |
| | | public boolean isConfigurationChangeAcceptable( |
| | | LengthBasedPasswordValidatorCfg configuration, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | return configEntryDN; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public List<ConfigAttribute> getConfigurationAttributes() |
| | | { |
| | | LinkedList<ConfigAttribute> attrs = new LinkedList<ConfigAttribute>(); |
| | | |
| | | int msgID = MSGID_PWLENGTHVALIDATOR_DESCRIPTION_MIN_LENGTH; |
| | | attrs.add(new IntegerConfigAttribute(ATTR_PASSWORD_MIN_LENGTH, |
| | | getMessage(msgID), false, false, false, |
| | | true, 0, false, 0, minLength)); |
| | | |
| | | msgID = MSGID_PWLENGTHVALIDATOR_DESCRIPTION_MAX_LENGTH; |
| | | attrs.add(new IntegerConfigAttribute(ATTR_PASSWORD_MAX_LENGTH, |
| | | getMessage(msgID), false, false, false, |
| | | true, 0, false, 0, maxLength)); |
| | | |
| | | return attrs; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean hasAcceptableConfiguration(ConfigEntry configEntry, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | // Get the configured minimum length. |
| | | int newMinLength = 0; |
| | | int msgID = MSGID_PWLENGTHVALIDATOR_DESCRIPTION_MIN_LENGTH; |
| | | IntegerConfigAttribute minLengthStub = |
| | | new IntegerConfigAttribute(ATTR_PASSWORD_MIN_LENGTH, getMessage(msgID), |
| | | false, false, false, true, 0, false, 0); |
| | | try |
| | | // Make sure that if both the maximum and minimum lengths are set, the |
| | | // maximum length is greater than or equal to the minimum length. |
| | | int maxLength = configuration.getMaximumPasswordLength(); |
| | | int minLength = configuration.getMinimumPasswordLength(); |
| | | if ((maxLength > 0) && (minLength > 0) && (minLength > maxLength)) |
| | | { |
| | | IntegerConfigAttribute minLengthAttr = |
| | | (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(minLengthStub); |
| | | if (minLengthAttr != null) |
| | | { |
| | | newMinLength = minLengthAttr.activeIntValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_PWLENGTHVALIDATOR_CANNOT_DETERMINE_MIN_LENGTH; |
| | | unacceptableReasons.add(getMessage(msgID, |
| | | stackTraceToSingleLineString(e))); |
| | | } |
| | | |
| | | |
| | | // Get the configured maximum length. |
| | | int newMaxLength = 0; |
| | | msgID = MSGID_PWLENGTHVALIDATOR_DESCRIPTION_MAX_LENGTH; |
| | | IntegerConfigAttribute maxLengthStub = |
| | | new IntegerConfigAttribute(ATTR_PASSWORD_MAX_LENGTH, getMessage(msgID), |
| | | false, false, false, true, 0, false, 0); |
| | | try |
| | | { |
| | | IntegerConfigAttribute maxLengthAttr = |
| | | (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(maxLengthStub); |
| | | if (maxLengthAttr != null) |
| | | { |
| | | newMaxLength = maxLengthAttr.activeIntValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | msgID = MSGID_PWLENGTHVALIDATOR_CANNOT_DETERMINE_MAX_LENGTH; |
| | | unacceptableReasons.add(getMessage(msgID, |
| | | stackTraceToSingleLineString(e))); |
| | | int msgID = MSGID_PWLENGTHVALIDATOR_MIN_GREATER_THAN_MAX; |
| | | String message = getMessage(msgID, minLength, maxLength); |
| | | unacceptableReasons.add(message); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // If both a minimum and a maximum were provided, then make sure the |
| | | // minimum is less than or equal to the maximum. |
| | | if ((newMinLength > 0) && (newMaxLength > 0) && |
| | | (newMinLength > newMaxLength)) |
| | | { |
| | | msgID = MSGID_PWLENGTHVALIDATOR_MIN_GREATER_THAN_MAX; |
| | | unacceptableReasons.add(getMessage(msgID, newMinLength, newMaxLength)); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // If we've gotten here, then everything looks OK. |
| | | return true; |
| | | } |
| | | |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry, |
| | | boolean detailedResults) |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | LengthBasedPasswordValidatorCfg configuration) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | |
| | | // Get the configured minimum length. |
| | | int newMinLength = 0; |
| | | int msgID = MSGID_PWLENGTHVALIDATOR_DESCRIPTION_MIN_LENGTH; |
| | | IntegerConfigAttribute minLengthStub = |
| | | new IntegerConfigAttribute(ATTR_PASSWORD_MIN_LENGTH, getMessage(msgID), |
| | | false, false, false, true, 0, false, 0); |
| | | try |
| | | { |
| | | IntegerConfigAttribute minLengthAttr = |
| | | (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(minLengthStub); |
| | | if (minLengthAttr != null) |
| | | { |
| | | newMinLength = minLengthAttr.activeIntValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX; |
| | | } |
| | | |
| | | msgID = MSGID_PWLENGTHVALIDATOR_CANNOT_DETERMINE_MIN_LENGTH; |
| | | messages.add(getMessage(msgID, stackTraceToSingleLineString(e))); |
| | | } |
| | | |
| | | |
| | | // Get the configured maximum length. |
| | | int newMaxLength = 0; |
| | | msgID = MSGID_PWLENGTHVALIDATOR_DESCRIPTION_MAX_LENGTH; |
| | | IntegerConfigAttribute maxLengthStub = |
| | | new IntegerConfigAttribute(ATTR_PASSWORD_MAX_LENGTH, getMessage(msgID), |
| | | false, false, false, true, 0, false, 0); |
| | | try |
| | | { |
| | | IntegerConfigAttribute maxLengthAttr = |
| | | (IntegerConfigAttribute) |
| | | configEntry.getConfigAttribute(maxLengthStub); |
| | | if (maxLengthAttr != null) |
| | | { |
| | | newMaxLength = maxLengthAttr.activeIntValue(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX; |
| | | } |
| | | |
| | | msgID = MSGID_PWLENGTHVALIDATOR_CANNOT_DETERMINE_MAX_LENGTH; |
| | | messages.add(getMessage(msgID, stackTraceToSingleLineString(e))); |
| | | } |
| | | |
| | | |
| | | // If both a minimum and a maximum were provided, then make sure the |
| | | // minimum is less than or equal to the maximum. |
| | | if ((newMinLength > 0) && (newMaxLength > 0) && |
| | | (newMinLength > newMaxLength)) |
| | | { |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.CONSTRAINT_VIOLATION; |
| | | } |
| | | |
| | | msgID = MSGID_PWLENGTHVALIDATOR_MIN_GREATER_THAN_MAX; |
| | | messages.add(getMessage(msgID, newMinLength, newMaxLength)); |
| | | } |
| | | |
| | | |
| | | // If everything looks good, then apply the changes. |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | if (newMinLength != minLength) |
| | | { |
| | | minLength = newMinLength; |
| | | |
| | | if (detailedResults) |
| | | { |
| | | msgID = MSGID_PWLENGTHVALIDATOR_UPDATED_MIN_LENGTH; |
| | | messages.add(getMessage(msgID, minLength)); |
| | | } |
| | | } |
| | | |
| | | |
| | | if (newMaxLength != maxLength) |
| | | { |
| | | maxLength = newMaxLength; |
| | | |
| | | if (detailedResults) |
| | | { |
| | | msgID = MSGID_PWLENGTHVALIDATOR_UPDATED_MAX_LENGTH; |
| | | messages.add(getMessage(msgID, maxLength)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | // We will always accept the proposed configuration if it's gotten to this |
| | | // point. |
| | | currentConfig = configuration; |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false); |
| | | } |
| | | } |
| | | |