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.core;
028
029
030
031 import java.text.SimpleDateFormat;
032 import java.util.Date;
033 import java.util.Iterator;
034 import java.util.LinkedHashMap;
035 import java.util.LinkedHashSet;
036 import java.util.LinkedList;
037 import java.util.SortedSet;
038 import java.util.TimeZone;
039 import java.util.concurrent.ConcurrentHashMap;
040 import java.util.concurrent.CopyOnWriteArrayList;
041 import java.util.concurrent.CopyOnWriteArraySet;
042
043 import org.opends.messages.Message;
044 import org.opends.server.admin.std.meta.PasswordPolicyCfgDefn;
045 import org.opends.server.admin.std.server.PasswordPolicyCfg;
046 import org.opends.server.admin.std.server.PasswordValidatorCfg;
047 import org.opends.server.api.AccountStatusNotificationHandler;
048 import org.opends.server.api.PasswordGenerator;
049 import org.opends.server.api.PasswordStorageScheme;
050 import org.opends.server.api.PasswordValidator;
051 import org.opends.server.config.ConfigException;
052 import org.opends.server.loggers.debug.DebugTracer;
053 import org.opends.server.protocols.asn1.ASN1OctetString;
054 import org.opends.server.schema.GeneralizedTimeSyntax;
055 import org.opends.server.types.AttributeType;
056 import org.opends.server.types.ByteString;
057 import org.opends.server.types.DebugLogLevel;
058 import org.opends.server.types.DN;
059 import org.opends.server.types.InitializationException;
060
061 import static org.opends.messages.CoreMessages.*;
062 import static org.opends.server.config.ConfigConstants.*;
063 import static org.opends.server.loggers.debug.DebugLogger.*;
064 import static org.opends.server.schema.SchemaConstants.*;
065 import static org.opends.server.util.ServerConstants.*;
066 import static org.opends.server.util.StaticUtils.*;
067
068
069
070 /**
071 * This class defines a data structure that holds information about a Directory
072 * Server password policy.
073 */
074 public class PasswordPolicy
075 {
076 /**
077 * The tracer object for the debug logger.
078 */
079 private static final DebugTracer TRACER = getTracer();
080
081 // The DN of the entry containing the configuration for this password
082 // policy.
083 private final DN configEntryDN;
084
085 // The attribute type that will hold user passwords for this password policy.
086 private final AttributeType passwordAttribute;
087
088 // Indicates whether the attribute type uses the authPassword syntax.
089 private final boolean authPasswordSyntax;
090
091 // Indicates whether a user with an expired password will still be allowed to
092 // change it via the password modify extended operation.
093 private boolean allowExpiredPasswordChanges =
094 DEFAULT_PWPOLICY_ALLOW_EXPIRED_CHANGES;
095
096 // Indicates whether the password attribute will be allowed to have multiple
097 // distinct values.
098 private boolean allowMultiplePasswordValues =
099 DEFAULT_PWPOLICY_ALLOW_MULTIPLE_PW_VALUES;
100
101 // Indicates whether to allow pre-encoded passwords.
102 private boolean allowPreEncodedPasswords =
103 DEFAULT_PWPOLICY_ALLOW_PRE_ENCODED_PASSWORDS;
104
105 // Indicates whether users will be allowed to change their passwords.
106 private boolean allowUserPasswordChanges =
107 DEFAULT_PWPOLICY_ALLOW_USER_CHANGE;
108
109 // Indicates whether to allow a password to expire without ever providing the
110 // user with a notification.
111 private boolean expirePasswordsWithoutWarning =
112 DEFAULT_PWPOLICY_EXPIRE_WITHOUT_WARNING;
113
114 // Indicates whether users must change their passwords the first time they
115 // authenticate after their account is created.
116 private boolean forceChangeOnAdd =
117 DEFAULT_PWPOLICY_FORCE_CHANGE_ON_ADD;
118
119 // Indicates whether a user must change their password after it has been reset
120 // by an administrator.
121 private boolean forceChangeOnReset =
122 DEFAULT_PWPOLICY_FORCE_CHANGE_ON_RESET;
123
124 // Indicates whether a user must provide their current password in order to
125 // use a new password.
126 private boolean requireCurrentPassword =
127 DEFAULT_PWPOLICY_REQUIRE_CURRENT_PASSWORD;
128
129 // Indicates whether users will be required to authenticate using a secure
130 // mechanism.
131 private boolean requireSecureAuthentication =
132 DEFAULT_PWPOLICY_REQUIRE_SECURE_AUTHENTICATION;
133
134 // Indicates whether users will be required to change their passwords using a
135 // secure mechanism.
136 private boolean requireSecurePasswordChanges =
137 DEFAULT_PWPOLICY_REQUIRE_SECURE_PASSWORD_CHANGES;
138
139 // Indicates whether password validation should be performed for
140 // administrative password changes.
141 private boolean skipValidationForAdministrators =
142 DEFAULT_PWPOLICY_SKIP_ADMIN_VALIDATION;
143
144 // The set of account status notification handlers for this password policy.
145 private ConcurrentHashMap<DN, AccountStatusNotificationHandler>
146 notificationHandlers;
147
148 // The set of password validators that will be used with this
149 // password policy.
150 private ConcurrentHashMap<DN, PasswordValidator<?>> passwordValidators;
151
152 // The set of default password storage schemes for this password
153 // policy.
154 private CopyOnWriteArrayList<PasswordStorageScheme> defaultStorageSchemes =
155 new CopyOnWriteArrayList<PasswordStorageScheme>();
156 {
157 PasswordStorageScheme defaultScheme =
158 DirectoryServer.getPasswordStorageScheme(DEFAULT_PASSWORD_STORAGE_SCHEME);
159 if (defaultScheme != null) defaultStorageSchemes.add(defaultScheme);
160 }
161
162 // The names of the deprecated password storage schemes for this password
163 // policy.
164 private CopyOnWriteArraySet<String> deprecatedStorageSchemes =
165 new CopyOnWriteArraySet<String>();
166
167 // The DN of the password validator for this password policy.
168 private DN passwordGeneratorDN = null;
169
170 // The password generator for use with this password policy.
171 private PasswordGenerator passwordGenerator = null;
172
173 // The number of grace logins that a user may have.
174 private int graceLoginCount = DEFAULT_PWPOLICY_GRACE_LOGIN_COUNT;
175
176 // The number of passwords to keep in the history.
177 private int historyCount = DEFAULT_PWPOLICY_HISTORY_COUNT;
178
179 // The maximum length of time in seconds to keep passwords in the history.
180 private int historyDuration = DEFAULT_PWPOLICY_HISTORY_DURATION;
181
182 // The maximum length of time in seconds that an account may remain idle
183 // before it is locked out.
184 private int idleLockoutInterval = DEFAULT_PWPOLICY_IDLE_LOCKOUT_INTERVAL;
185
186 // The length of time a user should stay locked out, in seconds.
187 private int lockoutDuration = DEFAULT_PWPOLICY_LOCKOUT_DURATION;
188
189 // The number of authentication failures before an account is locked out.
190 private int lockoutFailureCount = DEFAULT_PWPOLICY_LOCKOUT_FAILURE_COUNT;
191
192 // The length of time that authentication failures should be counted against
193 // a user.
194 private int lockoutFailureExpirationInterval =
195 DEFAULT_PWPOLICY_LOCKOUT_FAILURE_EXPIRATION_INTERVAL;
196
197 // The maximum password age (i.e., expiration interval), in seconds.
198 private int maximumPasswordAge = DEFAULT_PWPOLICY_MAXIMUM_PASSWORD_AGE;
199
200 // The maximum password age for administratively reset passwords, in seconds.
201 private int maximumPasswordResetAge =
202 DEFAULT_PWPOLICY_MAXIMUM_PASSWORD_RESET_AGE;
203
204 // The minimum password age, in seconds.
205 private int minimumPasswordAge = DEFAULT_PWPOLICY_MINIMUM_PASSWORD_AGE;
206
207 // The password expiration warning interval, in seconds.
208 private int warningInterval = DEFAULT_PWPOLICY_WARNING_INTERVAL;
209
210 // The the time by which all users will be required to change their passwords.
211 private long requireChangeByTime = -1L;
212
213 // The attribute type that will hold the last login time.
214 private AttributeType lastLoginTimeAttribute = null;
215
216 // The format string to use when generating the last login time.
217 private String lastLoginTimeFormat = null;
218
219 // The set of previous last login time format strings.
220 private CopyOnWriteArrayList<String> previousLastLoginTimeFormats =
221 new CopyOnWriteArrayList<String>();
222
223 // The state update failure policy.
224 private PasswordPolicyCfgDefn.StateUpdateFailurePolicy
225 stateUpdateFailurePolicy =
226 PasswordPolicyCfgDefn.StateUpdateFailurePolicy.REACTIVE;
227
228
229
230 /**
231 * Creates a new password policy based on the configuration contained in the
232 * provided configuration entry. Any parameters not included in the provided
233 * configuration entry will be assigned server-wide default values.
234 *
235 * @param configuration The configuration with the information to use to
236 * initialize this password policy.
237 *
238 * @throws ConfigException If the provided entry does not contain a valid
239 * password policy configuration.
240 *
241 * @throws InitializationException If an error occurs while initializing the
242 * password policy that is not related to
243 * the server configuration.
244 */
245 public PasswordPolicy(PasswordPolicyCfg configuration)
246 throws ConfigException, InitializationException
247 {
248 // Create a list of units and values that we can use to represent time
249 // periods.
250 LinkedHashMap<String,Double> timeUnits = new LinkedHashMap<String,Double>();
251 timeUnits.put(TIME_UNIT_SECONDS_ABBR, 1D);
252 timeUnits.put(TIME_UNIT_SECONDS_FULL, 1D);
253 timeUnits.put(TIME_UNIT_MINUTES_ABBR, 60D);
254 timeUnits.put(TIME_UNIT_MINUTES_FULL, 60D);
255 timeUnits.put(TIME_UNIT_HOURS_ABBR, (double) (60 * 60));
256 timeUnits.put(TIME_UNIT_HOURS_FULL, (double) (60 * 60));
257 timeUnits.put(TIME_UNIT_DAYS_ABBR, (double) (60 * 60 * 24));
258 timeUnits.put(TIME_UNIT_DAYS_FULL, (double) (60 * 60 * 24));
259 timeUnits.put(TIME_UNIT_WEEKS_ABBR, (double) (60 * 60 * 24 * 7));
260 timeUnits.put(TIME_UNIT_WEEKS_FULL, (double) (60 * 60 * 24 * 7));
261
262 this.configEntryDN = configuration.dn();
263
264 // Get the password attribute. If specified, it must have either the
265 // user password or auth password syntax.
266 passwordAttribute = configuration.getPasswordAttribute();
267 String syntaxOID = passwordAttribute.getSyntaxOID();
268 if (syntaxOID.equals(SYNTAX_AUTH_PASSWORD_OID))
269 {
270 authPasswordSyntax = true;
271 }
272 else if (syntaxOID.equals(SYNTAX_USER_PASSWORD_OID))
273 {
274 authPasswordSyntax = false;
275 }
276 else
277 {
278 String syntax = passwordAttribute.getSyntax().getSyntaxName();
279 if ((syntax == null) || (syntax.length() == 0))
280 {
281 syntax = syntaxOID;
282 }
283
284 Message message = ERR_PWPOLICY_INVALID_PASSWORD_ATTRIBUTE_SYNTAX.
285 get(String.valueOf(configEntryDN), passwordAttribute.getNameOrOID(),
286 String.valueOf(syntax));
287 throw new ConfigException(message);
288 }
289
290
291 // Get the default storage schemes. They must all reference valid storage
292 // schemes that support the syntax for the specified password attribute.
293 SortedSet<DN> storageSchemeDNs =
294 configuration.getDefaultPasswordStorageSchemeDNs();
295 try
296 {
297 LinkedList<PasswordStorageScheme> schemes =
298 new LinkedList<PasswordStorageScheme>();
299 for (DN configEntryDN : storageSchemeDNs)
300 {
301 PasswordStorageScheme scheme =
302 DirectoryServer.getPasswordStorageScheme(configEntryDN);
303
304 if (this.authPasswordSyntax &&
305 (! scheme.supportsAuthPasswordSyntax()))
306 {
307 Message message = ERR_PWPOLICY_SCHEME_DOESNT_SUPPORT_AUTH.get(
308 String.valueOf(configEntryDN),
309 this.passwordAttribute.getNameOrOID());
310 throw new ConfigException(message);
311 }
312
313 schemes.add(scheme);
314 }
315
316 this.defaultStorageSchemes =
317 new CopyOnWriteArrayList<PasswordStorageScheme>(schemes);
318 }
319 catch (ConfigException ce)
320 {
321 throw ce;
322 }
323 catch (Exception e)
324 {
325 if (debugEnabled())
326 {
327 TRACER.debugCaught(DebugLogLevel.ERROR, e);
328 }
329
330 Message message = ERR_PWPOLICY_CANNOT_DETERMINE_DEFAULT_STORAGE_SCHEMES.
331 get(String.valueOf(configEntryDN), getExceptionMessage(e));
332 throw new InitializationException(message, e);
333 }
334
335
336 // Get the names of the deprecated storage schemes.
337 SortedSet<DN> deprecatedStorageSchemeDNs =
338 configuration.getDeprecatedPasswordStorageSchemeDNs();
339 try
340 {
341 LinkedHashSet<String> newDeprecatedStorageSchemes =
342 new LinkedHashSet<String>();
343 for (DN schemeDN : deprecatedStorageSchemeDNs)
344 {
345 PasswordStorageScheme scheme =
346 DirectoryServer.getPasswordStorageScheme(schemeDN);
347 if (this.authPasswordSyntax)
348 {
349 if (scheme.supportsAuthPasswordSyntax())
350 {
351 newDeprecatedStorageSchemes.add(
352 scheme.getAuthPasswordSchemeName());
353 }
354 else
355 {
356 Message message = ERR_PWPOLICY_DEPRECATED_SCHEME_NOT_AUTH.get(
357 String.valueOf(configEntryDN),
358 String.valueOf(schemeDN));
359 throw new ConfigException(message);
360 }
361 }
362 else
363 {
364 newDeprecatedStorageSchemes.add(
365 toLowerCase(scheme.getStorageSchemeName()));
366 }
367 }
368
369 this.deprecatedStorageSchemes =
370 new CopyOnWriteArraySet<String>(newDeprecatedStorageSchemes);
371 }
372 catch (Exception e)
373 {
374 if (debugEnabled())
375 {
376 TRACER.debugCaught(DebugLogLevel.ERROR, e);
377 }
378
379 Message message =
380 ERR_PWPOLICY_CANNOT_DETERMINE_DEPRECATED_STORAGE_SCHEMES.
381 get(String.valueOf(configEntryDN), getExceptionMessage(e));
382 throw new InitializationException(message, e);
383 }
384
385
386 // Get the password validators.
387 SortedSet<DN> passwordValidators = configuration.getPasswordValidatorDNs();
388 ConcurrentHashMap<DN, PasswordValidator<?>> validators =
389 new ConcurrentHashMap<DN, PasswordValidator<?>>();
390 for (DN validatorDN : passwordValidators)
391 {
392 validators.put(validatorDN,
393 DirectoryServer.getPasswordValidator(validatorDN));
394 }
395 this.passwordValidators = validators;
396
397
398 // Get the status notification handlers.
399 SortedSet<DN> statusNotificationHandlers =
400 configuration.getAccountStatusNotificationHandlerDNs();
401 ConcurrentHashMap<DN,AccountStatusNotificationHandler> handlers =
402 new ConcurrentHashMap<DN,AccountStatusNotificationHandler>();
403 for (DN handlerDN : statusNotificationHandlers)
404 {
405 AccountStatusNotificationHandler handler =
406 DirectoryServer.getAccountStatusNotificationHandler(handlerDN);
407 handlers.put(handlerDN, handler);
408 }
409 this.notificationHandlers = handlers;
410
411
412 // Determine whether to allow user password changes.
413 this.allowUserPasswordChanges = configuration.isAllowUserPasswordChanges();
414
415 // Determine whether to require the current password for user changes.
416 this.requireCurrentPassword =
417 configuration.isPasswordChangeRequiresCurrentPassword();
418
419 // Determine whether to force password changes on add.
420 this.forceChangeOnAdd = configuration.isForceChangeOnAdd();
421
422 // Determine whether to force password changes on reset.
423 this.forceChangeOnReset = configuration.isForceChangeOnReset();
424
425 // Determine whether to validate reset passwords.
426 this.skipValidationForAdministrators =
427 configuration.isSkipValidationForAdministrators();
428
429 // Get the password generator.
430 DN passGenDN = configuration.getPasswordGeneratorDN() ;
431 if (passGenDN != null)
432 {
433 this.passwordGeneratorDN = passGenDN;
434 this.passwordGenerator = DirectoryServer.getPasswordGenerator(passGenDN);
435 }
436
437
438 // Determine whether to require secure authentication.
439 this.requireSecureAuthentication =
440 configuration.isRequireSecureAuthentication();
441
442 // Determine whether to require secure password changes.
443 this.requireSecurePasswordChanges =
444 configuration.isRequireSecurePasswordChanges() ;
445
446 // Determine whether to allow multiple password values.
447 this.allowMultiplePasswordValues =
448 configuration.isAllowMultiplePasswordValues();
449
450 // Determine whether to allow pre-encoded passwords.
451 this.allowPreEncodedPasswords = configuration.isAllowPreEncodedPasswords();
452
453 // Get the minimum password age.
454 this.minimumPasswordAge = (int) configuration.getMinPasswordAge();
455
456 // Get the maximum password age.
457 this.maximumPasswordAge = (int) configuration.getMaxPasswordAge();
458
459 // Get the maximum password reset age.
460 this.maximumPasswordResetAge = (int) configuration
461 .getMaxPasswordResetAge();
462
463 // Get the warning interval.
464 this.warningInterval = (int) configuration
465 .getPasswordExpirationWarningInterval();
466
467 // Determine whether to expire passwords without warning.
468 this.expirePasswordsWithoutWarning = configuration
469 .isExpirePasswordsWithoutWarning();
470
471 // If the expire without warning option is disabled, then there must be a
472 // warning interval.
473 if ((! this.expirePasswordsWithoutWarning()) &&
474 (this.getWarningInterval() <= 0))
475 {
476 Message message =
477 ERR_PWPOLICY_MUST_HAVE_WARNING_IF_NOT_EXPIRE_WITHOUT_WARNING.
478 get(String.valueOf(configEntryDN));
479 throw new ConfigException(message);
480 }
481
482 // Determine whether to allow user changes for expired passwords.
483 this.allowExpiredPasswordChanges = configuration
484 .isAllowExpiredPasswordChanges();
485
486 // Get the grace login count.
487 this.graceLoginCount = configuration.getGraceLoginCount();
488
489 // Get the lockout failure count.
490 this.lockoutFailureCount = configuration.getLockoutFailureCount();
491
492 // Get the lockout duration.
493 this.lockoutDuration = (int) configuration.getLockoutDuration();
494
495 // Get the lockout failure expiration interval.
496 this.lockoutFailureExpirationInterval = (int) configuration
497 .getLockoutFailureExpirationInterval();
498
499 // Get the required change time.
500 String requireChangeBy = configuration.getRequireChangeByTime();
501 try
502 {
503 if (requireChangeBy != null)
504 {
505 ByteString valueString = new ASN1OctetString(requireChangeBy);
506
507 GeneralizedTimeSyntax syntax =
508 (GeneralizedTimeSyntax)
509 DirectoryServer.getAttributeSyntax(SYNTAX_GENERALIZED_TIME_OID,
510 false);
511
512 if (syntax == null)
513 {
514 this.requireChangeByTime =
515 GeneralizedTimeSyntax.decodeGeneralizedTimeValue(valueString);
516 }
517 else
518 {
519 valueString =
520 syntax.getEqualityMatchingRule().normalizeValue(valueString);
521 this.requireChangeByTime =
522 GeneralizedTimeSyntax.decodeGeneralizedTimeValue(valueString);
523 }
524 }
525 }
526 catch (Exception e)
527 {
528 if (debugEnabled())
529 {
530 TRACER.debugCaught(DebugLogLevel.ERROR, e);
531 }
532
533 Message message = ERR_PWPOLICY_CANNOT_DETERMINE_REQUIRE_CHANGE_BY_TIME.
534 get(String.valueOf(configEntryDN), getExceptionMessage(e));
535 throw new InitializationException(message, e);
536 }
537
538
539 // Get the last login time attribute. If specified, it must be defined in
540 // the server schema. It does not need to have a generalized time syntax
541 // because the value that it will store will not necessarily conform to this
542 // format.
543 lastLoginTimeAttribute = configuration.getLastLoginTimeAttribute();
544
545
546 // Get the last login time format. If specified, it must be a valid format
547 // string.
548 String formatString = configuration.getLastLoginTimeFormat();
549 try
550 {
551 if (formatString != null)
552 {
553 try
554 {
555 new SimpleDateFormat(formatString);
556 }
557 catch (Exception e)
558 {
559 if (debugEnabled())
560 {
561 TRACER.debugCaught(DebugLogLevel.ERROR, e);
562 }
563
564 Message message = ERR_PWPOLICY_INVALID_LAST_LOGIN_TIME_FORMAT.get(
565 String.valueOf(configEntryDN), String.valueOf(formatString));
566 throw new ConfigException(message);
567 }
568
569 this.lastLoginTimeFormat = formatString;
570 }
571 }
572 catch (ConfigException ce)
573 {
574 throw ce;
575 }
576 catch (Exception e)
577 {
578 if (debugEnabled())
579 {
580 TRACER.debugCaught(DebugLogLevel.ERROR, e);
581 }
582
583 Message message = ERR_PWPOLICY_CANNOT_DETERMINE_LAST_LOGIN_TIME_FORMAT.
584 get(String.valueOf(configEntryDN), getExceptionMessage(e));
585 throw new InitializationException(message, e);
586 }
587
588
589 // Get the previous last login time formats. If specified, they must all
590 // be valid format strings.
591 SortedSet<String> formatStrings =
592 configuration.getPreviousLastLoginTimeFormat() ;
593 try
594 {
595 if (formatStrings != null)
596 {
597 for (String s : formatStrings)
598 {
599 try
600 {
601 new SimpleDateFormat(s);
602 }
603 catch (Exception e)
604 {
605 if (debugEnabled())
606 {
607 TRACER.debugCaught(DebugLogLevel.ERROR, e);
608 }
609
610 Message message =
611 ERR_PWPOLICY_INVALID_PREVIOUS_LAST_LOGIN_TIME_FORMAT.
612 get(String.valueOf(configEntryDN), String.valueOf(s));
613 throw new ConfigException(message);
614 }
615 }
616
617 this.previousLastLoginTimeFormats =
618 new CopyOnWriteArrayList<String>(formatStrings);
619 }
620 }
621 catch (ConfigException ce)
622 {
623 throw ce;
624 }
625 catch (Exception e)
626 {
627 if (debugEnabled())
628 {
629 TRACER.debugCaught(DebugLogLevel.ERROR, e);
630 }
631
632 Message message =
633 ERR_PWPOLICY_CANNOT_DETERMINE_PREVIOUS_LAST_LOGIN_TIME_FORMAT.
634 get(String.valueOf(configEntryDN), getExceptionMessage(e));
635 throw new InitializationException(message, e);
636 }
637
638
639 // Get the idle lockout duration.
640 this.idleLockoutInterval = (int) configuration.getIdleLockoutInterval();
641
642
643 // Get the state update failure policy.
644 this.stateUpdateFailurePolicy = configuration.getStateUpdateFailurePolicy();
645
646
647 // Get the password history count and duration.
648 this.historyCount = configuration.getPasswordHistoryCount();
649 this.historyDuration = (int) configuration.getPasswordHistoryDuration();
650
651
652 /*
653 * Holistic validation.
654 */
655
656 // Ensure that the password attribute was included in the configuration
657 // entry, since it is required.
658 if (passwordAttribute == null)
659 {
660 Message message =
661 ERR_PWPOLICY_NO_PASSWORD_ATTRIBUTE.get(String.valueOf(configEntryDN));
662 throw new ConfigException(message);
663 }
664
665 // Ensure that at least one default password storage scheme was included in
666 // the configuration entry, since it is required.
667 if (defaultStorageSchemes.isEmpty())
668 {
669 Message message = ERR_PWPOLICY_NO_DEFAULT_STORAGE_SCHEMES.get(
670 String.valueOf(configEntryDN));
671 throw new ConfigException(message);
672 }
673
674 // If both a maximum password age and a warning interval are provided, then
675 // ensure that the warning interval is less than the maximum age. Further,
676 // if a minimum age is specified, then the sum of the minimum age and the
677 // warning interval should be less than the maximum age.
678 if (maximumPasswordAge > 0)
679 {
680 int warnInterval = Math.max(0, warningInterval);
681 if (minimumPasswordAge > 0)
682 {
683 if ((warnInterval + minimumPasswordAge) >= maximumPasswordAge)
684 {
685 Message message =
686 ERR_PWPOLICY_MIN_AGE_PLUS_WARNING_GREATER_THAN_MAX_AGE.
687 get(String.valueOf(configEntryDN));
688 throw new ConfigException(message);
689 }
690 }
691 else if (warnInterval >= maximumPasswordAge)
692 {
693 Message message = ERR_PWPOLICY_WARNING_INTERVAL_LARGER_THAN_MAX_AGE.get(
694 String.valueOf(configEntryDN));
695 throw new ConfigException(message);
696 }
697 }
698 }
699
700
701
702 /**
703 * Retrieves the DN of the configuration entry to which this password policy
704 * corresponds.
705 *
706 * @return The DN of the configuration entry.
707 */
708 public DN getConfigEntryDN()
709 {
710 return configEntryDN;
711 }
712
713
714
715 /**
716 * Retrieves the attribute type used to store the password.
717 *
718 * @return The attribute type used to store the password.
719 */
720 public AttributeType getPasswordAttribute()
721 {
722 return passwordAttribute;
723 }
724
725
726
727 /**
728 * Indicates whether the associated password attribute uses the auth password
729 * syntax.
730 *
731 * @return <CODE>true</CODE> if the associated password attribute uses the
732 * auth password syntax, or <CODE>false</CODE> if not.
733 */
734 public boolean usesAuthPasswordSyntax()
735 {
736 return authPasswordSyntax;
737 }
738
739
740
741 /**
742 * Retrieves the default set of password storage schemes that will be used for
743 * this password policy. The returned set should not be modified by the
744 * caller.
745 *
746 * @return The default set of password storage schemes that will be used for
747 * this password policy.
748 */
749 public CopyOnWriteArrayList<PasswordStorageScheme> getDefaultStorageSchemes()
750 {
751 return defaultStorageSchemes;
752 }
753
754
755
756 /**
757 * Indicates whether the specified storage scheme is a default scheme for this
758 * password policy.
759 *
760 * @param name The name of the password storage scheme for which to make the
761 * determination.
762 *
763 * @return <CODE>true</CODE> if the storage scheme is a default scheme for
764 * this password policy, or <CODE>false</CODE> if not.
765 */
766 public boolean isDefaultStorageScheme(String name)
767 {
768 CopyOnWriteArrayList<PasswordStorageScheme> defaultSchemes =
769 getDefaultStorageSchemes();
770 if (defaultSchemes == null)
771 {
772 return false;
773 }
774
775 for (PasswordStorageScheme s : defaultSchemes)
776 {
777 if (authPasswordSyntax)
778 {
779 if (s.getAuthPasswordSchemeName().equalsIgnoreCase(name))
780 {
781 return true;
782 }
783 }
784 else
785 {
786 if (s.getStorageSchemeName().equalsIgnoreCase(name))
787 {
788 return true;
789 }
790 }
791 }
792
793
794 return false;
795 }
796
797
798
799 /**
800 * Retrieves the names of the password storage schemes that have been
801 * deprecated. If an authenticating user has one or more of these deprecated
802 * storage schemes in use in their entry, then they will be removed and
803 * replaced with the passwords encoded in the default storage scheme(s). The
804 * returned list should not be altered by the caller.
805 *
806 * @return The names of the password storage schemes that have been
807 * deprecated.
808 */
809 public CopyOnWriteArraySet<String> getDeprecatedStorageSchemes()
810 {
811 return deprecatedStorageSchemes;
812 }
813
814
815
816 /**
817 * Indicates whether the specified storage scheme is deprecated.
818 *
819 * @param name The name of the password storage scheme for which to make the
820 * determination.
821 *
822 * @return <CODE>true</CODE> if the storage scheme is deprecated, or
823 * <CODE>false</CODE> if not.
824 */
825 public boolean isDeprecatedStorageScheme(String name)
826 {
827 CopyOnWriteArraySet<String> deprecatedSchemes =
828 getDeprecatedStorageSchemes();
829 if (deprecatedSchemes == null)
830 {
831 return false;
832 }
833
834 for (String s : deprecatedSchemes)
835 {
836 if (s.equalsIgnoreCase(name))
837 {
838 return true;
839 }
840 }
841
842 return false;
843 }
844
845
846
847 /**
848 * Retrieves the set of password validators for this password policy. The
849 * returned list should not be altered by the caller.
850 *
851 * @return The set of password validators for this password policy.
852 */
853 public ConcurrentHashMap<DN,
854 PasswordValidator<? extends PasswordValidatorCfg>>
855 getPasswordValidators()
856 {
857 return passwordValidators;
858 }
859
860
861
862 /**
863 * Retrieves the set of account status notification handlers that should be
864 * used with this password policy. The returned list should not be altered by
865 * the caller.
866 *
867 * @return The set of account status notification handlers that should be
868 * used with this password policy.
869 */
870 public ConcurrentHashMap<DN,AccountStatusNotificationHandler>
871 getAccountStatusNotificationHandlers()
872 {
873 return notificationHandlers;
874 }
875
876
877
878 /**
879 * Indicates whether end users will be allowed to change their own passwords
880 * (subject to access control restrictions).
881 *
882 * @return <CODE>true</CODE> if users will be allowed to change their own
883 * passwords, or <CODE>false</CODE> if not.
884 */
885 public boolean allowUserPasswordChanges()
886 {
887 return allowUserPasswordChanges;
888 }
889
890
891
892 /**
893 * Indicates whether the end user must provide their current password (via the
894 * password modify extended operation) in order to set a new password.
895 *
896 * @return <CODE>true</CODE> if the end user must provide their current
897 * password in order to set a new password, or <CODE>false</CODE> if
898 * they will not.
899 */
900 public boolean requireCurrentPassword()
901 {
902 return requireCurrentPassword;
903 }
904
905
906
907 /**
908 * Indicates whether users will be required to change their passwords as soon
909 * as they authenticate after their accounts have been created.
910 *
911 * @return <CODE>true</CODE> if users will be required to change their
912 * passwords at the initial authentication, or <CODE>false</CODE> if
913 * not.
914 */
915 public boolean forceChangeOnAdd()
916 {
917 return forceChangeOnAdd;
918 }
919
920
921
922 /**
923 * Indicates whether a user will be required to change their password after it
924 * has been reset by an administrator.
925 *
926 * @return <CODE>true</CODE> if a user will be required to change their
927 * password after it has been reset by an administrator, or
928 * <CODE>false</CODE> if they can continue using that password.
929 */
930 public boolean forceChangeOnReset()
931 {
932 return forceChangeOnReset;
933 }
934
935
936
937 /**
938 * Indicates whether operations by administrators that specify a new password
939 * for a user (e.g., add, modify, or password modify) will be allowed to
940 * bypass the password validation process that will be required for user
941 * password changes.
942 *
943 * @return <CODE>true</CODE> if administrators will be allowed to bypass the
944 * validation checks, or <CODE>false</CODE> if not.
945 */
946 public boolean skipValidationForAdministrators()
947 {
948 return skipValidationForAdministrators;
949 }
950
951
952
953 /**
954 * Retrieves the DN of the password validator configuration entry.
955 *
956 * @return The DN of the password validator configuration entry.
957 */
958 public DN getPasswordGeneratorDN()
959 {
960 return passwordGeneratorDN;
961 }
962
963
964
965 /**
966 * Retrieves the password generator that will be used with this password
967 * policy.
968 *
969 * @return The password generator that will be used with this password
970 * policy, or <CODE>null</CODE> if there is none.
971 */
972 public PasswordGenerator getPasswordGenerator()
973 {
974 return passwordGenerator;
975 }
976
977
978
979 /**
980 * Retrieves the maximum number of previous passwords to maintain in the
981 * password history.
982 *
983 * @return The maximum number of previous passwords to maintain in the
984 * password history.
985 */
986 public int getPasswordHistoryCount()
987 {
988 return historyCount;
989 }
990
991
992
993 /**
994 * Retrieves the maximum length of time in seconds that previous passwords
995 * should remain in the password history.
996 *
997 * @return The maximum length of time in seconds that previous passwords
998 * should remain in the password history.
999 */
1000 public int getPasswordHistoryDuration()
1001 {
1002 return historyDuration;
1003 }
1004
1005
1006
1007 /**
1008 * Indicates whether users with this password policy will be required to
1009 * authenticate in a secure manner that does not expose their password.
1010 *
1011 * @return <CODE>true</CODE> if users with this password policy will be
1012 * required to authenticate in a secure manner that does not expose
1013 * their password, or <CODE>false</CODE> if they may authenticate in
1014 * an insecure manner.
1015 */
1016 public boolean requireSecureAuthentication()
1017 {
1018 return requireSecureAuthentication;
1019 }
1020
1021
1022
1023 /**
1024 * Indicates whether users with this password policy will be required to
1025 * change their passwords in a secure manner that does not expose the new
1026 * password.
1027 *
1028 * @return <CODE>true</CODE> if users with this password policy will be
1029 * required to change their passwords in a secure manner that does
1030 * not expose the new password, or <CODE>false</CODE> if they may
1031 * change their password in an insecure manner.
1032 */
1033 public boolean requireSecurePasswordChanges()
1034 {
1035 return requireSecurePasswordChanges;
1036 }
1037
1038
1039
1040 /**
1041 * Indicates whether user entries will be allowed to have multiple distinct
1042 * values in the password attribute.
1043 *
1044 * @return <CODE>true</CODE> if clients will be allowed to have multiple
1045 * distinct password values, or <CODE>false</CODE> if not.
1046 */
1047 public boolean allowMultiplePasswordValues()
1048 {
1049 return allowMultiplePasswordValues;
1050 }
1051
1052
1053
1054 /**
1055 * Indicates whether clients will be allowed to set pre-encoded passwords that
1056 * are already hashed and therefore cannot be validated for correctness.
1057 *
1058 * @return <CODE>true</CODE> if clients will be allowed to set pre-encoded
1059 * passwords that cannot be validated, or <CODE>false</CODE> if not.
1060 */
1061 public boolean allowPreEncodedPasswords()
1062 {
1063 return allowPreEncodedPasswords;
1064 }
1065
1066
1067
1068 /**
1069 * Retrieves the minimum password age, which is the minimum length of time in
1070 * seconds that must elapse between user password changes.
1071 *
1072 * @return The minimum password age, which is the minimum length of time in
1073 * seconds that must elapse between user password changes, or zero if
1074 * there is no minimum age.
1075 */
1076 public int getMinimumPasswordAge()
1077 {
1078 if (minimumPasswordAge <= 0)
1079 {
1080 return 0;
1081 }
1082
1083 return minimumPasswordAge;
1084 }
1085
1086
1087
1088 /**
1089 * Retrieves the maximum length of time in seconds that will be allowed to
1090 * pass between password changes before the password is expired.
1091 *
1092 * @return The maximum length of time in seconds that will be allowed to pass
1093 * between password changes before the password is expired, or zero
1094 * if password expiration should not be used.
1095 */
1096 public int getMaximumPasswordAge()
1097 {
1098 if (maximumPasswordAge < 0)
1099 {
1100 return 0;
1101 }
1102
1103 return maximumPasswordAge;
1104 }
1105
1106
1107
1108 /**
1109 * Retrieves the maximum length of time in seconds that will be allowed to
1110 * pass after an administrative password reset before that password is
1111 * expired.
1112 *
1113 * @return The maximum length of time in seconds that will be allowed to pass
1114 * after an administrative password reset before that password is
1115 * expired, or zero if there is no limit.
1116 */
1117 public int getMaximumPasswordResetAge()
1118 {
1119 if (maximumPasswordResetAge < 0)
1120 {
1121 return 0;
1122 }
1123
1124 return maximumPasswordResetAge;
1125 }
1126
1127
1128
1129 /**
1130 * Retrieves the maximum length of time in seconds before the password will
1131 * expire that the user should start receiving warning notifications.
1132 *
1133 * @return The maximum length of time in seconds before the password will
1134 * expire that the user should start receiving warning notifications,
1135 * or zero if no warning should be given.
1136 */
1137 public int getWarningInterval()
1138 {
1139 if (warningInterval < 0)
1140 {
1141 return 0;
1142 }
1143
1144 return warningInterval;
1145 }
1146
1147
1148
1149 /**
1150 * Indicates whether user passwords will be allowed to expire without the
1151 * user receiving at least one notification during the warning period.
1152 *
1153 * @return <CODE>true</CODE> if user passwords will be allowed to expire
1154 * without the user receiving at least one notification during the
1155 * warning period, or <CODE>false</CODE> if the user will always see
1156 * at least one warning before the password expires.
1157 */
1158 public boolean expirePasswordsWithoutWarning()
1159 {
1160 return expirePasswordsWithoutWarning;
1161 }
1162
1163
1164
1165 /**
1166 * Indicates whether a user will be allowed to change their password after it
1167 * expires and they have no remaining grace logins (and will not be allowed to
1168 * perform any other operation until the password is changed).
1169 *
1170 * @return <CODE>true</CODE> if a user will be allowed to change their
1171 * password after it expires and they have no remaining grace longs,
1172 * or <CODE>false</CODE> if the account will be completely locked and
1173 * the password must be reset by an administrator.
1174 */
1175 public boolean allowExpiredPasswordChanges()
1176 {
1177 return allowExpiredPasswordChanges;
1178 }
1179
1180
1181
1182 /**
1183 * Retrieves the maximum number of grace logins that a user will be allowed
1184 * after their password has expired before they are completely locked out.
1185 *
1186 * @return The maximum number of grace logins that a user will be allowed
1187 * after their password has expired before they are completely
1188 * locked out, or zero if no grace logins will be allowed or the
1189 * grace login duration will be in effect instead of a fixed number
1190 * of logins.
1191 */
1192 public int getGraceLoginCount()
1193 {
1194 if (graceLoginCount < 0)
1195 {
1196 return 0;
1197 }
1198
1199 return graceLoginCount;
1200 }
1201
1202
1203
1204 /**
1205 * Retrieves the maximum number of authentication failures that will be
1206 * allowed before an account is locked out.
1207 *
1208 * @return The maximum number of authentication failures that will be allowed
1209 * before an account is locked out, or zero if no account lockout
1210 * will be in effect.
1211 */
1212 public int getLockoutFailureCount()
1213 {
1214 if (lockoutFailureCount < 0)
1215 {
1216 return 0;
1217 }
1218
1219 return lockoutFailureCount;
1220 }
1221
1222
1223
1224 /**
1225 * Retrieves the maximum length of time in seconds that an account will be
1226 * locked out due to too many failed authentication attempts.
1227 *
1228 * @return The maximum length of time in seconds that an account will be
1229 * locked out due to too many failed authentication attempts, or
1230 * zero if the account will remain locked until explicitly unlocked
1231 * by an administrator.
1232 */
1233 public int getLockoutDuration()
1234 {
1235 if (lockoutDuration < 0)
1236 {
1237 return 0;
1238 }
1239
1240 return lockoutDuration;
1241 }
1242
1243
1244
1245 /**
1246 * Retrieves the maximum length of time in seconds that an authentication
1247 * failure will be held against a user before it is removed from the failed
1248 * login count.
1249 *
1250 * @return The maximum length of time in seconds that an authentication
1251 * failure will be held against a user before it is removed from the
1252 * failed login count, or zero if authentication failures will never
1253 * expire.
1254 */
1255 public int getLockoutFailureExpirationInterval()
1256 {
1257 if (lockoutFailureExpirationInterval < 0)
1258 {
1259 return 0;
1260 }
1261
1262 return lockoutFailureExpirationInterval;
1263 }
1264
1265
1266
1267 /**
1268 * Retrieves the time by which all users will be required to change their
1269 * passwords, expressed in the number of milliseconds since midnight of
1270 * January 1, 1970 (i.e., the zero time for
1271 * <CODE>System.currentTimeMillis()</CODE>). Any passwords not changed before
1272 * this time will automatically enter a state in which they must be changed
1273 * before any other operation will be allowed.
1274 *
1275 * @return The time by which all users will be required to change their
1276 * passwords, or zero if no such constraint is in effect.
1277 */
1278 public long getRequireChangeByTime()
1279 {
1280 if (requireChangeByTime < 0)
1281 {
1282 return 0;
1283 }
1284
1285 return requireChangeByTime;
1286 }
1287
1288
1289
1290 /**
1291 * Retrieves the attribute type used to store the last login time.
1292 *
1293 * @return The attribute type used to store the last login time, or
1294 * <CODE>null</CODE> if the last login time is not to be maintained.
1295 */
1296 public AttributeType getLastLoginTimeAttribute()
1297 {
1298 return lastLoginTimeAttribute;
1299 }
1300
1301
1302
1303 /**
1304 * Retrieves the format string that should be used for the last login time.
1305 *
1306 * @return The format string that should be used to for the last login time,
1307 * or <CODE>null</CODE> if the last login time is not to be
1308 * maintained.
1309 */
1310 public String getLastLoginTimeFormat()
1311 {
1312 return lastLoginTimeFormat;
1313 }
1314
1315
1316
1317 /**
1318 * Retrieves the list of previous last login time formats that might have been
1319 * used for users associated with this password policy.
1320 *
1321 * @return The list of previous last login time formats that might have been
1322 * used for users associated with this password policy.
1323 */
1324 public CopyOnWriteArrayList<String> getPreviousLastLoginTimeFormats()
1325 {
1326 return previousLastLoginTimeFormats;
1327 }
1328
1329
1330
1331 /**
1332 * Retrieves the maximum length of time in seconds that an account will be
1333 * allowed to remain idle (no authentications performed as the user) before it
1334 * will be locked out.
1335 *
1336 * @return The maximum length of time in seconds that an account will be
1337 * allowed to remain idle before it will be locked out.
1338 */
1339 public int getIdleLockoutInterval()
1340 {
1341 if (idleLockoutInterval < 0)
1342 {
1343 return 0;
1344 }
1345
1346 return idleLockoutInterval;
1347 }
1348
1349
1350
1351 /**
1352 * Retrieves the state update failure policy for this password policy.
1353 *
1354 * @return The state update failure policy for this password policy.
1355 */
1356 public PasswordPolicyCfgDefn.StateUpdateFailurePolicy
1357 getStateUpdateFailurePolicy()
1358 {
1359 return stateUpdateFailurePolicy;
1360 }
1361
1362
1363
1364 /**
1365 * Retrieves a string representation of this password policy.
1366 *
1367 * @return A string representation of this password policy.
1368 */
1369 public String toString()
1370 {
1371 StringBuilder buffer = new StringBuilder();
1372 toString(buffer);
1373 return buffer.toString();
1374 }
1375
1376
1377
1378 /**
1379 * Appends a string representation of this password policy to the provided
1380 * buffer.
1381 *
1382 * @param buffer The buffer to which the information should be appended.
1383 */
1384 public void toString(StringBuilder buffer)
1385 {
1386 buffer.append("Password Attribute: ");
1387 buffer.append(passwordAttribute.getNameOrOID());
1388 buffer.append(EOL);
1389
1390 buffer.append("Default Password Storage Schemes: ");
1391 if ((defaultStorageSchemes == null) || defaultStorageSchemes.isEmpty())
1392 {
1393 buffer.append("{none specified}");
1394 buffer.append(EOL);
1395 }
1396 else
1397 {
1398 Iterator<PasswordStorageScheme> iterator =
1399 defaultStorageSchemes.iterator();
1400 buffer.append(iterator.next().getStorageSchemeName());
1401 buffer.append(EOL);
1402
1403 while (iterator.hasNext())
1404 {
1405 buffer.append(" ");
1406 buffer.append(iterator.next().getStorageSchemeName());
1407 buffer.append(EOL);
1408 }
1409 }
1410
1411 buffer.append("Deprecated Password Storage Schemes: ");
1412 if ((deprecatedStorageSchemes == null) ||
1413 deprecatedStorageSchemes.isEmpty())
1414 {
1415 buffer.append("{none specified}");
1416 buffer.append(EOL);
1417 }
1418 else
1419 {
1420 Iterator<String> iterator = deprecatedStorageSchemes.iterator();
1421 buffer.append(iterator.next());
1422 buffer.append(EOL);
1423
1424 while (iterator.hasNext())
1425 {
1426 buffer.append(" ");
1427 buffer.append(iterator.next());
1428 buffer.append(EOL);
1429 }
1430 }
1431
1432 buffer.append("Allow Multiple Password Values: ");
1433 buffer.append(allowMultiplePasswordValues);
1434 buffer.append(EOL);
1435
1436 buffer.append("Allow Pre-Encoded Passwords: ");
1437 buffer.append(allowPreEncodedPasswords);
1438 buffer.append(EOL);
1439
1440 buffer.append("Allow User Password Changes: ");
1441 buffer.append(allowUserPasswordChanges);
1442 buffer.append(EOL);
1443
1444 buffer.append("Force Password Change on Add: ");
1445 buffer.append(forceChangeOnAdd);
1446 buffer.append(EOL);
1447
1448 buffer.append("Force Password Change on Admin Reset: ");
1449 buffer.append(forceChangeOnReset);
1450 buffer.append(EOL);
1451
1452 buffer.append("Require Current Password: ");
1453 buffer.append(requireCurrentPassword);
1454 buffer.append(EOL);
1455
1456 buffer.append("Require Secure Authentication: ");
1457 buffer.append(requireSecureAuthentication);
1458 buffer.append(EOL);
1459
1460 buffer.append("Require Secure Password Changes: ");
1461 buffer.append(requireSecurePasswordChanges);
1462 buffer.append(EOL);
1463
1464 buffer.append("Lockout Failure Expiration Interval: ");
1465 buffer.append(lockoutFailureExpirationInterval);
1466 buffer.append(" seconds");
1467 buffer.append(EOL);
1468
1469 buffer.append("Password Validators: ");
1470 if ((passwordValidators == null) || passwordValidators.isEmpty())
1471 {
1472 buffer.append("{none specified}");
1473 buffer.append(EOL);
1474 }
1475 else
1476 {
1477 Iterator<DN> iterator = passwordValidators.keySet().iterator();
1478 iterator.next().toString(buffer);
1479 buffer.append(EOL);
1480
1481 while (iterator.hasNext())
1482 {
1483 buffer.append(" ");
1484 iterator.next().toString(buffer);
1485 buffer.append(EOL);
1486 }
1487 }
1488
1489 buffer.append("Skip Validation for Administrators: ");
1490 buffer.append(skipValidationForAdministrators);
1491 buffer.append(EOL);
1492
1493 buffer.append("Password Generator: ");
1494 if (passwordGenerator == null)
1495 {
1496 buffer.append("{none specified}");
1497 }
1498 else
1499 {
1500 passwordGeneratorDN.toString(buffer);
1501 }
1502 buffer.append(EOL);
1503
1504 buffer.append("Account Status Notification Handlers: ");
1505 if ((notificationHandlers == null) || notificationHandlers.isEmpty())
1506 {
1507 buffer.append("{none specified}");
1508 buffer.append(EOL);
1509 }
1510 else
1511 {
1512 Iterator<DN> iterator = notificationHandlers.keySet().iterator();
1513 iterator.next().toString(buffer);
1514 buffer.append(EOL);
1515
1516 while (iterator.hasNext())
1517 {
1518 buffer.append(" ");
1519 iterator.next().toString(buffer);
1520 buffer.append(EOL);
1521 }
1522 }
1523
1524 buffer.append("Minimum Password Age: ");
1525 buffer.append(minimumPasswordAge);
1526 buffer.append(" seconds");
1527 buffer.append(EOL);
1528
1529 buffer.append("Maximum Password Age: ");
1530 buffer.append(maximumPasswordAge);
1531 buffer.append(" seconds");
1532 buffer.append(EOL);
1533
1534 buffer.append("Maximum Password Reset Age: ");
1535 buffer.append(maximumPasswordResetAge);
1536 buffer.append(" seconds");
1537 buffer.append(EOL);
1538
1539 buffer.append("Expiration Warning Interval: ");
1540 buffer.append(warningInterval);
1541 buffer.append(" seconds");
1542 buffer.append(EOL);
1543
1544 buffer.append("Expire Passwords Without Warning: ");
1545 buffer.append(expirePasswordsWithoutWarning);
1546 buffer.append(EOL);
1547
1548 buffer.append("Allow Expired Password Changes: ");
1549 buffer.append(allowExpiredPasswordChanges);
1550 buffer.append(EOL);
1551
1552 buffer.append("Grace Login Count: ");
1553 buffer.append(graceLoginCount);
1554 buffer.append(EOL);
1555
1556 buffer.append("Lockout Failure Count: ");
1557 buffer.append(lockoutFailureCount);
1558 buffer.append(EOL);
1559
1560 buffer.append("Lockout Duration: ");
1561 buffer.append(lockoutDuration);
1562 buffer.append(" seconds");
1563 buffer.append(EOL);
1564
1565 buffer.append("Lockout Count Expiration Interval: ");
1566 buffer.append(lockoutFailureExpirationInterval);
1567 buffer.append(" seconds");
1568 buffer.append(EOL);
1569
1570 buffer.append("Required Password Change By Time: ");
1571 if (requireChangeByTime <= 0)
1572 {
1573 buffer.append("{none specified}");
1574 }
1575 else
1576 {
1577 SimpleDateFormat dateFormat =
1578 new SimpleDateFormat(DATE_FORMAT_GENERALIZED_TIME);
1579 dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
1580 buffer.append(dateFormat.format(new Date(requireChangeByTime)));
1581 }
1582 buffer.append(EOL);
1583
1584 buffer.append("Last Login Time Attribute: ");
1585 if (lastLoginTimeAttribute == null)
1586 {
1587 buffer.append("{none specified}");
1588 }
1589 else
1590 {
1591 buffer.append(lastLoginTimeAttribute.getNameOrOID());
1592 }
1593 buffer.append(EOL);
1594
1595 buffer.append("Last Login Time Format: ");
1596 if (lastLoginTimeFormat == null)
1597 {
1598 buffer.append("{none specified}");
1599 }
1600 else
1601 {
1602 buffer.append(lastLoginTimeFormat);
1603 }
1604 buffer.append(EOL);
1605
1606 buffer.append("Previous Last Login Time Formats: ");
1607 if ((previousLastLoginTimeFormats == null) ||
1608 previousLastLoginTimeFormats.isEmpty())
1609 {
1610 buffer.append("{none specified}");
1611 buffer.append(EOL);
1612 }
1613 else
1614 {
1615 Iterator<String> iterator = previousLastLoginTimeFormats.iterator();
1616
1617 buffer.append(iterator.next());
1618 buffer.append(EOL);
1619
1620 while (iterator.hasNext())
1621 {
1622 buffer.append(" ");
1623 buffer.append(iterator.next());
1624 buffer.append(EOL);
1625 }
1626 }
1627
1628 buffer.append("Idle Lockout Interval: ");
1629 buffer.append(idleLockoutInterval);
1630 buffer.append(" seconds");
1631 buffer.append(EOL);
1632
1633 buffer.append("History Count: ");
1634 buffer.append(historyCount);
1635 buffer.append(EOL);
1636
1637 buffer.append("Update Failure Policy: ");
1638 buffer.append(stateUpdateFailurePolicy.toString());
1639 buffer.append(EOL);
1640 }
1641 }
1642