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