001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.extensions;
028 import org.opends.messages.Message;
029
030
031
032 import java.util.List;
033 import java.util.Set;
034
035 import org.opends.server.admin.server.ConfigurationChangeListener;
036 import org.opends.server.admin.std.server.LengthBasedPasswordValidatorCfg;
037 import org.opends.server.admin.std.server.PasswordValidatorCfg;
038 import org.opends.server.api.PasswordValidator;
039 import org.opends.server.config.ConfigException;
040 import org.opends.server.types.ByteString;
041 import org.opends.server.types.ConfigChangeResult;
042 import org.opends.server.types.Entry;
043 import org.opends.server.types.InitializationException;
044 import org.opends.server.types.Operation;
045 import org.opends.server.types.ResultCode;
046
047 import static org.opends.messages.ExtensionMessages.*;
048 import org.opends.messages.MessageBuilder;
049
050
051 /**
052 * This class provides a password validator that can ensure that the provided
053 * password meets minimum and/or maximum length requirements.
054 */
055 public class LengthBasedPasswordValidator extends
056 PasswordValidator<LengthBasedPasswordValidatorCfg> implements
057 ConfigurationChangeListener<LengthBasedPasswordValidatorCfg>
058 {
059 // The current configuration for this password validator.
060 private LengthBasedPasswordValidatorCfg currentConfig;
061
062
063
064 /**
065 * Creates a new instance of this password validator.
066 */
067 public LengthBasedPasswordValidator()
068 {
069 super();
070
071 // All initialization must be done in the initializePasswordValidator
072 // method.
073 }
074
075
076
077 /**
078 * {@inheritDoc}
079 */
080 @Override()
081 public void initializePasswordValidator(
082 LengthBasedPasswordValidatorCfg configuration)
083 throws ConfigException, InitializationException
084 {
085 configuration.addLengthBasedChangeListener(this);
086
087 currentConfig = configuration;
088
089 // Make sure that if both the maximum and minimum lengths are set, the
090 // maximum length is greater than or equal to the minimum length.
091 int maxLength = configuration.getMaxPasswordLength();
092 int minLength = configuration.getMinPasswordLength();
093 if ((maxLength > 0) && (minLength > 0) && (minLength > maxLength))
094 {
095 Message message =
096 ERR_PWLENGTHVALIDATOR_MIN_GREATER_THAN_MAX.get(minLength, maxLength);
097 throw new ConfigException(message);
098 }
099 }
100
101
102
103 /**
104 * {@inheritDoc}
105 */
106 @Override()
107 public void finalizePasswordValidator()
108 {
109 currentConfig.removeLengthBasedChangeListener(this);
110 }
111
112
113
114 /**
115 * {@inheritDoc}
116 */
117 @Override()
118 public boolean passwordIsAcceptable(ByteString newPassword,
119 Set<ByteString> currentPasswords,
120 Operation operation, Entry userEntry,
121 MessageBuilder invalidReason)
122 {
123 LengthBasedPasswordValidatorCfg config = currentConfig;
124
125 int numChars = newPassword.stringValue().length();
126
127 int minLength = config.getMinPasswordLength();
128 if ((minLength > 0) && (numChars < minLength))
129 {
130 invalidReason.append(ERR_PWLENGTHVALIDATOR_TOO_SHORT.get(minLength));
131 return false;
132 }
133
134 int maxLength = config.getMaxPasswordLength();
135 if ((maxLength > 0) && (numChars > maxLength))
136 {
137 invalidReason.append(ERR_PWLENGTHVALIDATOR_TOO_LONG.get(maxLength));
138 return false;
139 }
140
141 return true;
142 }
143
144
145
146 /**
147 * {@inheritDoc}
148 */
149 @Override()
150 public boolean isConfigurationAcceptable(PasswordValidatorCfg configuration,
151 List<Message> unacceptableReasons)
152 {
153 LengthBasedPasswordValidatorCfg config =
154 (LengthBasedPasswordValidatorCfg) configuration;
155 return isConfigurationChangeAcceptable(config, unacceptableReasons);
156 }
157
158
159
160 /**
161 * {@inheritDoc}
162 */
163 public boolean isConfigurationChangeAcceptable(
164 LengthBasedPasswordValidatorCfg configuration,
165 List<Message> unacceptableReasons)
166 {
167 // Make sure that if both the maximum and minimum lengths are set, the
168 // maximum length is greater than or equal to the minimum length.
169 int maxLength = configuration.getMaxPasswordLength();
170 int minLength = configuration.getMinPasswordLength();
171 if ((maxLength > 0) && (minLength > 0) && (minLength > maxLength))
172 {
173 Message message = ERR_PWLENGTHVALIDATOR_MIN_GREATER_THAN_MAX.get(
174 minLength, maxLength);
175 unacceptableReasons.add(message);
176 return false;
177 }
178
179 return true;
180 }
181
182
183
184 /**
185 * {@inheritDoc}
186 */
187 public ConfigChangeResult applyConfigurationChange(
188 LengthBasedPasswordValidatorCfg configuration)
189 {
190 // We will always accept the proposed configuration if it's gotten to this
191 // point.
192 currentConfig = configuration;
193 return new ConfigChangeResult(ResultCode.SUCCESS, false);
194 }
195 }
196