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 legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2006-2008 Sun Microsystems, Inc. 025 * Portions Copyright 2011-2015 ForgeRock AS. 026 */ 027package org.opends.server.core; 028 029import static org.opends.messages.ConfigMessages.*; 030import static org.opends.messages.CoreMessages.*; 031import static org.opends.server.schema.SchemaConstants.*; 032import static org.opends.server.util.ServerConstants.*; 033import static org.opends.server.util.StaticUtils.*; 034 035import java.text.SimpleDateFormat; 036import java.util.*; 037 038import org.forgerock.i18n.LocalizableMessage; 039import org.forgerock.i18n.slf4j.LocalizedLogger; 040import org.forgerock.opendj.config.server.ConfigChangeResult; 041import org.forgerock.opendj.config.server.ConfigException; 042import org.forgerock.opendj.ldap.ByteString; 043import org.forgerock.opendj.ldap.GeneralizedTime; 044import org.forgerock.opendj.ldap.ResultCode; 045import org.opends.server.admin.server.ConfigurationChangeListener; 046import org.opends.server.admin.std.meta.PasswordPolicyCfgDefn.StateUpdateFailurePolicy; 047import org.opends.server.admin.std.server.PasswordPolicyCfg; 048import org.opends.server.api.*; 049import org.opends.server.types.*; 050 051/** 052 * This class is the interface between the password policy configurable 053 * component and a password policy state object. When a password policy entry is 054 * added to the configuration, an instance of this class is created and 055 * registered to manage subsequent modification to that configuration entry, 056 * including validating any proposed modification and applying an accepted 057 * modification. 058 */ 059public final class PasswordPolicyFactory implements 060 AuthenticationPolicyFactory<PasswordPolicyCfg> 061{ 062 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 063 064 065 066 /** 067 * Password policy implementation. 068 */ 069 private static final class PasswordPolicyImpl extends PasswordPolicy 070 implements ConfigurationChangeListener<PasswordPolicyCfg> 071 { 072 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 073 074 /** Current configuration. */ 075 private PasswordPolicyCfg configuration; 076 077 /** Indicates whether the attribute type uses the authPassword syntax. */ 078 private boolean authPasswordSyntax; 079 080 /** The set of account status notification handlers for this password policy. */ 081 private Map<DN, AccountStatusNotificationHandler<?>> notificationHandlers; 082 083 /** 084 * The set of password validators that will be used with this 085 * password policy. 086 */ 087 private Map<DN, PasswordValidator<?>> passwordValidators; 088 089 /** 090 * The set of default password storage schemes for this password policy. 091 */ 092 private List<PasswordStorageScheme<?>> defaultStorageSchemes; 093 094 /** 095 * The names of the deprecated password storage schemes for this password 096 * policy. 097 */ 098 private Set<String> deprecatedStorageSchemes; 099 100 /** The password generator for use with this password policy. */ 101 private PasswordGenerator<?> passwordGenerator; 102 103 /** 104 * The the time by which all users will be required to change their 105 * passwords. 106 */ 107 private long requireChangeByTime; 108 109 private final ServerContext serverContext; 110 111 /** {@inheritDoc} */ 112 @Override 113 public void finalizeAuthenticationPolicy() 114 { 115 configuration.removePasswordPolicyChangeListener(this); 116 } 117 118 /** {@inheritDoc} */ 119 @Override 120 public ConfigChangeResult applyConfigurationChange(PasswordPolicyCfg configuration) 121 { 122 final ConfigChangeResult ccr = new ConfigChangeResult(); 123 try 124 { 125 updateConfiguration(configuration, true); 126 } 127 catch (ConfigException ce) 128 { 129 ccr.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 130 ccr.addMessage(ERR_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG.get(configuration.dn(), ce.getMessage())); 131 } 132 catch (InitializationException ie) 133 { 134 ccr.addMessage(ERR_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG.get( 135 configuration.dn(), ie.getMessage())); 136 ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); 137 } 138 catch (Exception e) 139 { 140 ccr.addMessage(ERR_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG.get( 141 configuration.dn(), stackTraceToSingleLineString(e))); 142 ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); 143 } 144 return ccr; 145 } 146 147 /** {@inheritDoc} */ 148 @Override 149 public boolean isConfigurationChangeAcceptable( 150 PasswordPolicyCfg configuration, List<LocalizableMessage> unacceptableReasons) 151 { 152 try 153 { 154 updateConfiguration(configuration, false); 155 } 156 catch (ConfigException | InitializationException e) 157 { 158 LocalizableMessage message = ERR_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG.get( 159 configuration.dn(), e.getMessage()); 160 unacceptableReasons.add(message); 161 return false; 162 } 163 catch (Exception e) 164 { 165 LocalizableMessage message = ERR_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG 166 .get(configuration.dn(), stackTraceToSingleLineString(e)); 167 unacceptableReasons.add(message); 168 return false; 169 } 170 171 // If we've gotten here, then it is acceptable. 172 return true; 173 } 174 175 176 177 /** 178 * Creates a new password policy based on the configuration contained in the 179 * provided configuration entry. Any parameters not included in the provided 180 * configuration entry will be assigned server-wide default values. 181 * @param serverContext TODO 182 * @param configuration 183 * The configuration with the information to use to initialize this 184 * password policy. 185 * 186 * @throws ConfigException 187 * If the provided entry does not contain a valid password policy 188 * configuration. 189 * @throws InitializationException 190 * If an error occurs while initializing the password policy that 191 * is not related to the server configuration. 192 */ 193 private PasswordPolicyImpl(ServerContext serverContext, PasswordPolicyCfg configuration) 194 throws ConfigException, InitializationException 195 { 196 this.serverContext = serverContext; 197 updateConfiguration(configuration, true); 198 } 199 200 201 202 private void updateConfiguration(PasswordPolicyCfg configuration, 203 boolean applyChanges) throws ConfigException, 204 InitializationException 205 { 206 final DN configEntryDN = configuration.dn(); 207 208 // Get the password attribute. If specified, it must have either the 209 // user password or auth password syntax. 210 final AttributeType passwordAttribute = configuration 211 .getPasswordAttribute(); 212 final String syntaxOID = passwordAttribute.getSyntax().getOID(); 213 final boolean authPasswordSyntax; 214 if (syntaxOID.equals(SYNTAX_AUTH_PASSWORD_OID)) 215 { 216 authPasswordSyntax = true; 217 } 218 else if (syntaxOID.equals(SYNTAX_USER_PASSWORD_OID)) 219 { 220 authPasswordSyntax = false; 221 } 222 else 223 { 224 String syntax = passwordAttribute.getSyntax().getName(); 225 if (syntax == null || syntax.length() == 0) 226 { 227 syntax = syntaxOID; 228 } 229 230 throw new ConfigException(ERR_PWPOLICY_INVALID_PASSWORD_ATTRIBUTE_SYNTAX.get( 231 configEntryDN, passwordAttribute.getNameOrOID(), syntax)); 232 } 233 234 // Get the default storage schemes. They must all reference valid storage 235 // schemes that support the syntax for the specified password attribute. 236 List<PasswordStorageScheme<?>> defaultStorageSchemes = new LinkedList<>(); 237 for (DN schemeDN : configuration.getDefaultPasswordStorageSchemeDNs()) 238 { 239 PasswordStorageScheme<?> scheme = DirectoryServer 240 .getPasswordStorageScheme(schemeDN); 241 242 if (authPasswordSyntax && !scheme.supportsAuthPasswordSyntax()) 243 { 244 throw new ConfigException(ERR_PWPOLICY_SCHEME_DOESNT_SUPPORT_AUTH.get( 245 schemeDN, passwordAttribute.getNameOrOID())); 246 } 247 248 defaultStorageSchemes.add(scheme); 249 } 250 251 // Get the names of the deprecated storage schemes. 252 Set<String> deprecatedStorageSchemes = new LinkedHashSet<>(); 253 for (DN schemeDN : configuration.getDeprecatedPasswordStorageSchemeDNs()) 254 { 255 PasswordStorageScheme<?> scheme = DirectoryServer 256 .getPasswordStorageScheme(schemeDN); 257 if (authPasswordSyntax) 258 { 259 if (scheme.supportsAuthPasswordSyntax()) 260 { 261 deprecatedStorageSchemes.add(toLowerCase(scheme 262 .getAuthPasswordSchemeName())); 263 } 264 else 265 { 266 throw new ConfigException(ERR_PWPOLICY_DEPRECATED_SCHEME_NOT_AUTH.get( 267 configEntryDN, schemeDN)); 268 } 269 } 270 else 271 { 272 deprecatedStorageSchemes.add(toLowerCase(scheme.getStorageSchemeName())); 273 } 274 } 275 276 // Get the password validators. 277 Map<DN, PasswordValidator<?>> passwordValidators = new HashMap<>(); 278 for (DN validatorDN : configuration.getPasswordValidatorDNs()) 279 { 280 passwordValidators.put(validatorDN, 281 DirectoryServer.getPasswordValidator(validatorDN)); 282 } 283 284 // Get the status notification handlers. 285 Map<DN, AccountStatusNotificationHandler<?>> notificationHandlers = new HashMap<>(); 286 for (DN handlerDN : configuration.getAccountStatusNotificationHandlerDNs()) 287 { 288 AccountStatusNotificationHandler<?> handler = DirectoryServer 289 .getAccountStatusNotificationHandler(handlerDN); 290 notificationHandlers.put(handlerDN, handler); 291 } 292 293 // Get the password generator. 294 PasswordGenerator<?> passwordGenerator = null; 295 DN passGenDN = configuration.getPasswordGeneratorDN(); 296 if (passGenDN != null) 297 { 298 passwordGenerator = DirectoryServer.getPasswordGenerator(passGenDN); 299 } 300 301 // If the expire without warning option is disabled, then there must be a 302 // warning interval. 303 if (!configuration.isExpirePasswordsWithoutWarning() 304 && configuration.getPasswordExpirationWarningInterval() <= 0) 305 { 306 LocalizableMessage message = 307 ERR_PWPOLICY_MUST_HAVE_WARNING_IF_NOT_EXPIRE_WITHOUT_WARNING.get(configEntryDN); 308 throw new ConfigException(message); 309 } 310 311 // Get the required change time. 312 String requireChangeBy = configuration.getRequireChangeByTime(); 313 long requireChangeByTime = 0L; 314 try 315 { 316 if (requireChangeBy != null) 317 { 318 ByteString valueString = ByteString.valueOf(requireChangeBy); 319 requireChangeByTime = GeneralizedTime.valueOf(valueString.toString()).getTimeInMillis(); 320 } 321 } 322 catch (Exception e) 323 { 324 logger.traceException(e); 325 326 LocalizableMessage message = ERR_PWPOLICY_CANNOT_DETERMINE_REQUIRE_CHANGE_BY_TIME 327 .get(configEntryDN, getExceptionMessage(e)); 328 throw new InitializationException(message, e); 329 } 330 331 // Get the last login time format. If specified, it must be a valid format 332 // string. 333 String formatString = configuration.getLastLoginTimeFormat(); 334 if (formatString != null) 335 { 336 try 337 { 338 new SimpleDateFormat(formatString); 339 } 340 catch (Exception e) 341 { 342 logger.traceException(e); 343 344 LocalizableMessage message = ERR_PWPOLICY_INVALID_LAST_LOGIN_TIME_FORMAT.get(configEntryDN, formatString); 345 throw new ConfigException(message); 346 } 347 } 348 349 // Get the previous last login time formats. If specified, they must all 350 // be valid format strings. 351 SortedSet<String> formatStrings = configuration 352 .getPreviousLastLoginTimeFormat(); 353 if (formatStrings != null) 354 { 355 for (String s : formatStrings) 356 { 357 try 358 { 359 new SimpleDateFormat(s); 360 } 361 catch (Exception e) 362 { 363 logger.traceException(e); 364 365 LocalizableMessage message = 366 ERR_PWPOLICY_INVALID_PREVIOUS_LAST_LOGIN_TIME_FORMAT.get(configEntryDN, s); 367 throw new ConfigException(message); 368 } 369 } 370 } 371 372 // If both a maximum password age and a warning interval are provided, 373 // then 374 // ensure that the warning interval is less than the maximum age. Further, 375 // if a minimum age is specified, then the sum of the minimum age and the 376 // warning interval should be less than the maximum age. 377 if (configuration.getMaxPasswordAge() > 0) 378 { 379 long warnInterval = Math.max(0L, 380 configuration.getPasswordExpirationWarningInterval()); 381 if (configuration.getMinPasswordAge() > 0) 382 { 383 if (warnInterval + configuration.getMinPasswordAge() >= configuration.getMaxPasswordAge()) 384 { 385 LocalizableMessage message = 386 ERR_PWPOLICY_MIN_AGE_PLUS_WARNING_GREATER_THAN_MAX_AGE.get(configEntryDN); 387 throw new ConfigException(message); 388 } 389 } 390 else if (warnInterval >= configuration.getMaxPasswordAge()) 391 { 392 LocalizableMessage message = ERR_PWPOLICY_WARNING_INTERVAL_LARGER_THAN_MAX_AGE.get(configEntryDN); 393 throw new ConfigException(message); 394 } 395 } 396 397 // If we've got this far then the configuration is good and we can commit 398 // the changes if required. 399 if (applyChanges) 400 { 401 this.configuration = configuration; 402 this.authPasswordSyntax = authPasswordSyntax; 403 this.defaultStorageSchemes = defaultStorageSchemes; 404 this.deprecatedStorageSchemes = deprecatedStorageSchemes; 405 this.notificationHandlers = notificationHandlers; 406 this.passwordGenerator = passwordGenerator; 407 this.passwordValidators = passwordValidators; 408 this.requireChangeByTime = requireChangeByTime; 409 } 410 } 411 412 /** {@inheritDoc} */ 413 @Override 414 public boolean isAuthPasswordSyntax() 415 { 416 return authPasswordSyntax; 417 } 418 419 /** {@inheritDoc} */ 420 @Override 421 public List<PasswordStorageScheme<?>> getDefaultPasswordStorageSchemes() 422 { 423 return defaultStorageSchemes; 424 } 425 426 /** {@inheritDoc} */ 427 @Override 428 public Set<String> getDeprecatedPasswordStorageSchemes() 429 { 430 return deprecatedStorageSchemes; 431 } 432 433 /** {@inheritDoc} */ 434 @Override 435 public DN getDN() 436 { 437 return configuration.dn(); 438 } 439 440 /** {@inheritDoc} */ 441 @Override 442 public boolean isDefaultPasswordStorageScheme(String name) 443 { 444 for (PasswordStorageScheme<?> s : defaultStorageSchemes) 445 { 446 if (authPasswordSyntax) 447 { 448 if (s.getAuthPasswordSchemeName().equalsIgnoreCase(name)) 449 { 450 return true; 451 } 452 } 453 else 454 { 455 if (s.getStorageSchemeName().equalsIgnoreCase(name)) 456 { 457 return true; 458 } 459 } 460 } 461 462 return false; 463 } 464 465 /** {@inheritDoc} */ 466 @Override 467 public boolean isDeprecatedPasswordStorageScheme(String name) 468 { 469 return deprecatedStorageSchemes.contains(toLowerCase(name)); 470 } 471 472 /** {@inheritDoc} */ 473 @Override 474 public Collection<PasswordValidator<?>> getPasswordValidators() 475 { 476 return passwordValidators.values(); 477 } 478 479 /** {@inheritDoc} */ 480 @Override 481 public Collection<AccountStatusNotificationHandler<?>> 482 getAccountStatusNotificationHandlers() 483 { 484 return notificationHandlers.values(); 485 } 486 487 /** {@inheritDoc} */ 488 @Override 489 public PasswordGenerator<?> getPasswordGenerator() 490 { 491 return passwordGenerator; 492 } 493 494 /** {@inheritDoc} */ 495 @Override 496 public long getRequireChangeByTime() 497 { 498 return requireChangeByTime; 499 } 500 501 502 503 /** 504 * Retrieves a string representation of this password policy. 505 * 506 * @return A string representation of this password policy. 507 */ 508 @Override 509 public String toString() 510 { 511 StringBuilder buffer = new StringBuilder(); 512 toString(buffer); 513 return buffer.toString(); 514 } 515 516 517 518 /** 519 * Appends a string representation of this password policy to the provided 520 * buffer. 521 * 522 * @param buffer 523 * The buffer to which the information should be appended. 524 */ 525 public void toString(StringBuilder buffer) 526 { 527 buffer.append("Password Attribute: "); 528 buffer.append(configuration.getPasswordAttribute().getNameOrOID()); 529 buffer.append(EOL); 530 531 buffer.append("Default Password Storage Schemes: "); 532 if (defaultStorageSchemes == null || defaultStorageSchemes.isEmpty()) 533 { 534 buffer.append("{none specified}"); 535 buffer.append(EOL); 536 } 537 else 538 { 539 Iterator<PasswordStorageScheme<?>> iterator = defaultStorageSchemes 540 .iterator(); 541 buffer.append(iterator.next().getStorageSchemeName()); 542 buffer.append(EOL); 543 544 while (iterator.hasNext()) 545 { 546 buffer.append(" "); 547 buffer.append(iterator.next().getStorageSchemeName()); 548 buffer.append(EOL); 549 } 550 } 551 552 buffer.append("Deprecated Password Storage Schemes: "); 553 if (deprecatedStorageSchemes == null || deprecatedStorageSchemes.isEmpty()) 554 { 555 buffer.append("{none specified}"); 556 buffer.append(EOL); 557 } 558 else 559 { 560 Iterator<String> iterator = deprecatedStorageSchemes.iterator(); 561 buffer.append(iterator.next()); 562 buffer.append(EOL); 563 564 while (iterator.hasNext()) 565 { 566 buffer.append(" "); 567 buffer.append(iterator.next()); 568 buffer.append(EOL); 569 } 570 } 571 572 buffer.append("Allow Multiple Password Values: "); 573 buffer.append(configuration.isAllowMultiplePasswordValues()); 574 buffer.append(EOL); 575 576 buffer.append("Allow Pre-Encoded Passwords: "); 577 buffer.append(configuration.isAllowPreEncodedPasswords()); 578 buffer.append(EOL); 579 580 buffer.append("Allow User Password Changes: "); 581 buffer.append(configuration.isAllowUserPasswordChanges()); 582 buffer.append(EOL); 583 584 buffer.append("Force Password Change on Add: "); 585 buffer.append(configuration.isForceChangeOnAdd()); 586 buffer.append(EOL); 587 588 buffer.append("Force Password Change on Admin Reset: "); 589 buffer.append(configuration.isForceChangeOnReset()); 590 buffer.append(EOL); 591 592 buffer.append("Require Current Password: "); 593 buffer.append(configuration.isPasswordChangeRequiresCurrentPassword()); 594 buffer.append(EOL); 595 596 buffer.append("Require Secure Authentication: "); 597 buffer.append(configuration.isRequireSecureAuthentication()); 598 buffer.append(EOL); 599 600 buffer.append("Require Secure Password Changes: "); 601 buffer.append(configuration.isRequireSecurePasswordChanges()); 602 buffer.append(EOL); 603 604 buffer.append("Lockout Failure Expiration Interval: "); 605 buffer.append(configuration.getLockoutFailureExpirationInterval()); 606 buffer.append(" seconds"); 607 buffer.append(EOL); 608 609 buffer.append("Password Validators: "); 610 if (passwordValidators == null || passwordValidators.isEmpty()) 611 { 612 buffer.append("{none specified}"); 613 buffer.append(EOL); 614 } 615 else 616 { 617 Iterator<DN> iterator = passwordValidators.keySet().iterator(); 618 iterator.next().toString(buffer); 619 buffer.append(EOL); 620 621 while (iterator.hasNext()) 622 { 623 buffer.append(" "); 624 iterator.next().toString(buffer); 625 buffer.append(EOL); 626 } 627 } 628 629 buffer.append("Skip Validation for Administrators: "); 630 buffer.append(configuration.isSkipValidationForAdministrators()); 631 buffer.append(EOL); 632 633 buffer.append("Password Generator: "); 634 if (passwordGenerator == null) 635 { 636 buffer.append("{none specified}"); 637 } 638 else 639 { 640 configuration.getPasswordGeneratorDN().toString(buffer); 641 } 642 buffer.append(EOL); 643 644 buffer.append("Account Status Notification Handlers: "); 645 if (notificationHandlers == null || notificationHandlers.isEmpty()) 646 { 647 buffer.append("{none specified}"); 648 buffer.append(EOL); 649 } 650 else 651 { 652 Iterator<DN> iterator = notificationHandlers.keySet().iterator(); 653 iterator.next().toString(buffer); 654 buffer.append(EOL); 655 656 while (iterator.hasNext()) 657 { 658 buffer.append(" "); 659 iterator.next().toString(buffer); 660 buffer.append(EOL); 661 } 662 } 663 664 buffer.append("Minimum Password Age: "); 665 buffer.append(configuration.getMinPasswordAge()); 666 buffer.append(" seconds"); 667 buffer.append(EOL); 668 669 buffer.append("Maximum Password Age: "); 670 buffer.append(configuration.getMaxPasswordAge()); 671 buffer.append(" seconds"); 672 buffer.append(EOL); 673 674 buffer.append("Maximum Password Reset Age: "); 675 buffer.append(configuration.getMaxPasswordResetAge()); 676 buffer.append(" seconds"); 677 buffer.append(EOL); 678 679 buffer.append("Expiration Warning Interval: "); 680 buffer.append(configuration.getPasswordExpirationWarningInterval()); 681 buffer.append(" seconds"); 682 buffer.append(EOL); 683 684 buffer.append("Expire Passwords Without Warning: "); 685 buffer.append(configuration.isExpirePasswordsWithoutWarning()); 686 buffer.append(EOL); 687 688 buffer.append("Allow Expired Password Changes: "); 689 buffer.append(configuration.isAllowExpiredPasswordChanges()); 690 buffer.append(EOL); 691 692 buffer.append("Grace Login Count: "); 693 buffer.append(configuration.getGraceLoginCount()); 694 buffer.append(EOL); 695 696 buffer.append("Lockout Failure Count: "); 697 buffer.append(configuration.getLockoutFailureCount()); 698 buffer.append(EOL); 699 700 buffer.append("Lockout Duration: "); 701 buffer.append(configuration.getLockoutDuration()); 702 buffer.append(" seconds"); 703 buffer.append(EOL); 704 705 buffer.append("Lockout Count Expiration Interval: "); 706 buffer.append(configuration.getLockoutFailureExpirationInterval()); 707 buffer.append(" seconds"); 708 buffer.append(EOL); 709 710 buffer.append("Required Password Change By Time: "); 711 if (requireChangeByTime <= 0) 712 { 713 buffer.append("{none specified}"); 714 } 715 else 716 { 717 SimpleDateFormat dateFormat = new SimpleDateFormat( 718 DATE_FORMAT_GENERALIZED_TIME); 719 dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); 720 buffer.append(dateFormat.format(new Date(requireChangeByTime))); 721 } 722 buffer.append(EOL); 723 724 buffer.append("Last Login Time Attribute: "); 725 if (configuration.getLastLoginTimeAttribute() == null) 726 { 727 buffer.append("{none specified}"); 728 } 729 else 730 { 731 buffer.append(configuration.getLastLoginTimeAttribute().getNameOrOID()); 732 } 733 buffer.append(EOL); 734 735 buffer.append("Last Login Time Format: "); 736 if (configuration.getLastLoginTimeFormat() == null) 737 { 738 buffer.append("{none specified}"); 739 } 740 else 741 { 742 buffer.append(configuration.getLastLoginTimeFormat()); 743 } 744 buffer.append(EOL); 745 746 buffer.append("Previous Last Login Time Formats: "); 747 if (configuration.getPreviousLastLoginTimeFormat().isEmpty()) 748 { 749 buffer.append("{none specified}"); 750 buffer.append(EOL); 751 } 752 else 753 { 754 Iterator<String> iterator = configuration 755 .getPreviousLastLoginTimeFormat().iterator(); 756 757 buffer.append(iterator.next()); 758 buffer.append(EOL); 759 760 while (iterator.hasNext()) 761 { 762 buffer.append(" "); 763 buffer.append(iterator.next()); 764 buffer.append(EOL); 765 } 766 } 767 768 buffer.append("Idle Lockout Interval: "); 769 buffer.append(configuration.getIdleLockoutInterval()); 770 buffer.append(" seconds"); 771 buffer.append(EOL); 772 773 buffer.append("History Count: "); 774 buffer.append(configuration.getPasswordHistoryCount()); 775 buffer.append(EOL); 776 777 buffer.append("Update Failure Policy: "); 778 buffer.append(configuration.getStateUpdateFailurePolicy()); 779 buffer.append(EOL); 780 } 781 782 /** {@inheritDoc} */ 783 @Override 784 public boolean isAllowExpiredPasswordChanges() 785 { 786 return configuration.isAllowExpiredPasswordChanges(); 787 } 788 789 /** {@inheritDoc} */ 790 @Override 791 public boolean isAllowMultiplePasswordValues() 792 { 793 return configuration.isAllowMultiplePasswordValues(); 794 } 795 796 /** {@inheritDoc} */ 797 @Override 798 public boolean isAllowPreEncodedPasswords() 799 { 800 return configuration.isAllowPreEncodedPasswords(); 801 } 802 803 /** {@inheritDoc} */ 804 @Override 805 public boolean isAllowUserPasswordChanges() 806 { 807 return configuration.isAllowUserPasswordChanges(); 808 } 809 810 /** {@inheritDoc} */ 811 @Override 812 public boolean isExpirePasswordsWithoutWarning() 813 { 814 return configuration.isExpirePasswordsWithoutWarning(); 815 } 816 817 /** {@inheritDoc} */ 818 @Override 819 public boolean isForceChangeOnAdd() 820 { 821 return configuration.isForceChangeOnAdd(); 822 } 823 824 /** {@inheritDoc} */ 825 @Override 826 public boolean isForceChangeOnReset() 827 { 828 return configuration.isForceChangeOnReset(); 829 } 830 831 /** {@inheritDoc} */ 832 @Override 833 public int getGraceLoginCount() 834 { 835 return configuration.getGraceLoginCount(); 836 } 837 838 /** {@inheritDoc} */ 839 @Override 840 public long getIdleLockoutInterval() 841 { 842 return configuration.getIdleLockoutInterval(); 843 } 844 845 /** {@inheritDoc} */ 846 @Override 847 public AttributeType getLastLoginTimeAttribute() 848 { 849 return configuration.getLastLoginTimeAttribute(); 850 } 851 852 /** {@inheritDoc} */ 853 @Override 854 public String getLastLoginTimeFormat() 855 { 856 return configuration.getLastLoginTimeFormat(); 857 } 858 859 /** {@inheritDoc} */ 860 @Override 861 public long getLockoutDuration() 862 { 863 return configuration.getLockoutDuration(); 864 } 865 866 /** {@inheritDoc} */ 867 @Override 868 public int getLockoutFailureCount() 869 { 870 return configuration.getLockoutFailureCount(); 871 } 872 873 /** {@inheritDoc} */ 874 @Override 875 public long getLockoutFailureExpirationInterval() 876 { 877 return configuration.getLockoutFailureExpirationInterval(); 878 } 879 880 /** {@inheritDoc} */ 881 @Override 882 public long getMaxPasswordAge() 883 { 884 return configuration.getMaxPasswordAge(); 885 } 886 887 /** {@inheritDoc} */ 888 @Override 889 public long getMaxPasswordResetAge() 890 { 891 return configuration.getMaxPasswordResetAge(); 892 } 893 894 /** {@inheritDoc} */ 895 @Override 896 public long getMinPasswordAge() 897 { 898 return configuration.getMinPasswordAge(); 899 } 900 901 /** {@inheritDoc} */ 902 @Override 903 public AttributeType getPasswordAttribute() 904 { 905 return configuration.getPasswordAttribute(); 906 } 907 908 /** {@inheritDoc} */ 909 @Override 910 public boolean isPasswordChangeRequiresCurrentPassword() 911 { 912 return configuration.isPasswordChangeRequiresCurrentPassword(); 913 } 914 915 /** {@inheritDoc} */ 916 @Override 917 public long getPasswordExpirationWarningInterval() 918 { 919 return configuration.getPasswordExpirationWarningInterval(); 920 } 921 922 /** {@inheritDoc} */ 923 @Override 924 public int getPasswordHistoryCount() 925 { 926 return configuration.getPasswordHistoryCount(); 927 } 928 929 /** {@inheritDoc} */ 930 @Override 931 public long getPasswordHistoryDuration() 932 { 933 return configuration.getPasswordHistoryDuration(); 934 } 935 936 /** {@inheritDoc} */ 937 @Override 938 public SortedSet<String> getPreviousLastLoginTimeFormats() 939 { 940 return configuration.getPreviousLastLoginTimeFormat(); 941 } 942 943 /** {@inheritDoc} */ 944 @Override 945 public boolean isRequireSecureAuthentication() 946 { 947 return configuration.isRequireSecureAuthentication(); 948 } 949 950 /** {@inheritDoc} */ 951 @Override 952 public boolean isRequireSecurePasswordChanges() 953 { 954 return configuration.isRequireSecurePasswordChanges(); 955 } 956 957 /** {@inheritDoc} */ 958 @Override 959 public boolean isSkipValidationForAdministrators() 960 { 961 return configuration.isSkipValidationForAdministrators(); 962 } 963 964 /** {@inheritDoc} */ 965 @Override 966 public StateUpdateFailurePolicy getStateUpdateFailurePolicy() 967 { 968 return configuration.getStateUpdateFailurePolicy(); 969 } 970 971 } 972 973 private ServerContext serverContext; 974 975 /** 976 * Default constructor instantiated from authentication policy config manager. 977 */ 978 public PasswordPolicyFactory() 979 { 980 // Nothing to do . 981 } 982 983 /** 984 * Sets the server context. 985 * 986 * @param serverContext 987 * The server context. 988 */ 989 @Override 990 public void setServerContext(final ServerContext serverContext) { 991 this.serverContext = serverContext; 992 } 993 994 /** {@inheritDoc} */ 995 @Override 996 public PasswordPolicy createAuthenticationPolicy( 997 final PasswordPolicyCfg configuration) throws ConfigException, 998 InitializationException 999 { 1000 PasswordPolicyImpl policy = new PasswordPolicyImpl(serverContext, configuration); 1001 configuration.addPasswordPolicyChangeListener(policy); 1002 return policy; 1003 } 1004 1005 /** {@inheritDoc} */ 1006 @Override 1007 public boolean isConfigurationAcceptable( 1008 final PasswordPolicyCfg configuration, 1009 final List<LocalizableMessage> unacceptableReasons) 1010 { 1011 try 1012 { 1013 new PasswordPolicyImpl(null, configuration); 1014 } 1015 catch (final ConfigException | InitializationException ie) 1016 { 1017 logger.traceException(ie); 1018 1019 unacceptableReasons.add(ie.getMessageObject()); 1020 return false; 1021 } 1022 1023 // If we made it here, then the configuration is acceptable. 1024 return true; 1025 } 1026 1027}