RepeatedCharactersPasswordValidator.java revision 99faa045b6241c1d2843cce1b7a9d9c97055beae
0N/A/*
0N/A * CDDL HEADER START
0N/A *
0N/A * The contents of this file are subject to the terms of the
0N/A * Common Development and Distribution License, Version 1.0 only
0N/A * (the "License"). You may not use this file except in compliance
0N/A * with the License.
0N/A *
0N/A * You can obtain a copy of the license at
0N/A * trunk/opends/resource/legal-notices/OpenDS.LICENSE
0N/A * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
0N/A * See the License for the specific language governing permissions
0N/A * and limitations under the License.
0N/A *
0N/A * When distributing Covered Code, include this CDDL HEADER in each
0N/A * file and include the License file at
0N/A * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
0N/A * add the following below this CDDL HEADER, with the fields enclosed
0N/A * by brackets "[]" replaced with your own identifying information:
0N/A * Portions Copyright [yyyy] [name of copyright owner]
0N/A *
0N/A * CDDL HEADER END
0N/A *
0N/A *
0N/A * Portions Copyright 2007 Sun Microsystems, Inc.
0N/A */
0N/Apackage org.opends.server.extensions;
0N/A
0N/A
0N/A
0N/Aimport java.util.ArrayList;
0N/Aimport java.util.List;
0N/Aimport java.util.Set;
0N/A
0N/Aimport org.opends.server.admin.server.ConfigurationChangeListener;
0N/Aimport org.opends.server.admin.std.server.
0N/A RepeatedCharactersPasswordValidatorCfg;
0N/Aimport org.opends.server.api.PasswordValidator;
0N/Aimport org.opends.server.types.ConfigChangeResult;
0N/Aimport org.opends.server.types.ByteString;
0N/Aimport org.opends.server.types.Entry;
0N/Aimport org.opends.server.types.Operation;
0N/Aimport org.opends.server.types.ResultCode;
0N/A
0N/Aimport static org.opends.server.messages.ExtensionsMessages.*;
0N/Aimport static org.opends.server.messages.MessageHandler.*;
0N/A
0N/A
0N/A
0N/A/**
0N/A * This class provides an OpenDS password validator that may be used to ensure
0N/A * that proposed passwords are not allowed to have the same character appear
0N/A * several times consecutively.
0N/A */
0N/Apublic class RepeatedCharactersPasswordValidator
0N/A extends PasswordValidator<RepeatedCharactersPasswordValidatorCfg>
0N/A implements ConfigurationChangeListener<
0N/A RepeatedCharactersPasswordValidatorCfg>
0N/A{
0N/A // The current configuration for this password validator.
0N/A private RepeatedCharactersPasswordValidatorCfg currentConfig;
0N/A
0N/A
0N/A
0N/A /**
0N/A * Creates a new instance of this repeated characters password validator.
0N/A */
0N/A public RepeatedCharactersPasswordValidator()
0N/A {
0N/A super();
0N/A
0N/A // No implementation is required here. All initialization should be
0N/A // performed in the initializePasswordValidator() method.
0N/A }
0N/A
0N/A
0N/A
0N/A /**
0N/A * {@inheritDoc}
0N/A */
0N/A @Override()
0N/A public void initializePasswordValidator(
0N/A RepeatedCharactersPasswordValidatorCfg configuration)
0N/A {
0N/A configuration.addRepeatedCharactersChangeListener(this);
0N/A currentConfig = configuration;
0N/A }
0N/A
0N/A
0N/A
0N/A /**
0N/A * {@inheritDoc}
0N/A */
0N/A @Override()
0N/A public void finalizePasswordValidator()
0N/A {
0N/A currentConfig.removeRepeatedCharactersChangeListener(this);
0N/A }
0N/A
0N/A
0N/A
0N/A /**
0N/A * {@inheritDoc}
0N/A */
0N/A @Override()
0N/A public boolean passwordIsAcceptable(ByteString newPassword,
0N/A Set<ByteString> currentPasswords,
0N/A Operation operation, Entry userEntry,
0N/A StringBuilder invalidReason)
0N/A {
0N/A // Get a handle to the current configuration and see if we need to count
0N/A // the number of repeated characters in the password.
0N/A RepeatedCharactersPasswordValidatorCfg config = currentConfig;
0N/A int maxRepeats = config.getMaximumConsecutiveLength();
0N/A if (maxRepeats <= 0)
0N/A {
0N/A // We don't need to check anything, so the password will be acceptable.
0N/A return true;
0N/A }
0N/A
0N/A
0N/A // Get the password as a string. If we should use case-insensitive
0N/A // validation, then convert it to use all lowercase characters.
0N/A String passwordString = newPassword.stringValue();
0N/A if (! config.isCaseSensitiveValidation())
0N/A {
0N/A passwordString = passwordString.toLowerCase();
0N/A }
0N/A
0N/A
0N/A // Create variables to keep track of the last character we've seen and how
0N/A // many times we have seen it.
0N/A char lastCharacter = '\u0000';
0N/A int consecutiveCount = 0;
0N/A
0N/A
0N/A // Iterate through the characters in the password. If the consecutive
0N/A // count ever gets too high, then fail.
0N/A for (int i=0; i < passwordString.length(); i++)
0N/A {
0N/A char currentCharacter = passwordString.charAt(i);
0N/A if (currentCharacter == lastCharacter)
0N/A {
0N/A consecutiveCount++;
0N/A if (consecutiveCount > maxRepeats)
0N/A {
0N/A int msgID = MSGID_REPEATEDCHARS_VALIDATOR_TOO_MANY_CONSECUTIVE;
0N/A String message = getMessage(msgID, maxRepeats);
0N/A invalidReason.append(message);
0N/A return false;
0N/A }
0N/A }
0N/A else
0N/A {
0N/A lastCharacter = currentCharacter;
0N/A consecutiveCount = 1;
0N/A }
0N/A }
0N/A
0N/A return true;
0N/A }
0N/A
0N/A
0N/A
0N/A /**
0N/A * {@inheritDoc}
0N/A */
0N/A public boolean isConfigurationChangeAcceptable(
0N/A RepeatedCharactersPasswordValidatorCfg configuration,
0N/A List<String> unacceptableReasons)
0N/A {
0N/A // All of the necessary validation should have been performed automatically,
0N/A // so if we get to this point then the new configuration will be acceptable.
0N/A return true;
0N/A }
0N/A
0N/A
0N/A
0N/A /**
0N/A * {@inheritDoc}
0N/A */
0N/A public ConfigChangeResult applyConfigurationChange(
0N/A RepeatedCharactersPasswordValidatorCfg configuration)
0N/A {
0N/A ResultCode resultCode = ResultCode.SUCCESS;
0N/A boolean adminActionRequired = false;
0N/A ArrayList<String> messages = new ArrayList<String>();
0N/A
0N/A // For this password validator, we will always be able to successfully apply
0N/A // the new configuration.
0N/A currentConfig = configuration;
0N/A
0N/A return new ConfigChangeResult(resultCode, adminActionRequired, messages);
0N/A }
0N/A}
0N/A
0N/A