opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -153,6 +153,7 @@ import org.opends.server.types.WritabilityMode; import org.opends.server.util.MultiOutputStream; import org.opends.server.util.TimeThread; import org.opends.server.util.Validator; import org.opends.server.util.args.ArgumentException; import org.opends.server.util.args.ArgumentParser; import org.opends.server.util.args.BooleanArgument; @@ -296,7 +297,7 @@ // The set of password policies registered with the Directory Server, as a // mapping between the DN of the associated configuration entry and the policy // implementation. private ConcurrentHashMap<DN,PasswordPolicy> passwordPolicies; private ConcurrentHashMap<DN,PasswordPolicyConfig> passwordPolicies; // The set of password validators registered with the Directory Server, as a // mapping between the DN of the associated configuration entry and the @@ -454,7 +455,7 @@ private PasswordGeneratorConfigManager passwordGeneratorConfigManager; // The default password policy for the Directory Server. private PasswordPolicy defaultPasswordPolicy; private PasswordPolicyConfig defaultPasswordPolicyConfig; // The configuration handler used to manage the password policies. private PasswordPolicyConfigManager passwordPolicyConfigManager; @@ -625,9 +626,9 @@ directoryServer.rootDNs = new CopyOnWriteArraySet<DN>(); directoryServer.alternateRootBindDNs = new ConcurrentHashMap<DN,DN>(); directoryServer.passwordPolicies = new ConcurrentHashMap<DN,PasswordPolicy>(); new ConcurrentHashMap<DN,PasswordPolicyConfig>(); directoryServer.defaultPasswordPolicyDN = null; directoryServer.defaultPasswordPolicy = null; directoryServer.defaultPasswordPolicyConfig = null; directoryServer.monitorProviders = new ConcurrentHashMap<String,MonitorProvider>(); directoryServer.backends = new TreeMap<String,Backend>(); @@ -4640,17 +4641,28 @@ /** * Retrieves the set of password policies defined in the Directory Server as a * mapping between the DN of the associated configuration entry and the * corresponding policy. * Retrieves the set of password policies registered with the Directory * Server. The references returned are to the actual password policy objects * currently in use by the directory server and the referenced objects must * not be modified. * * @return The set of password policies defined in the Directory Server. * @return The set of password policies registered with the Directory Server. */ public static ConcurrentHashMap<DN,PasswordPolicy> getPasswordPolicies() public static PasswordPolicy[] getPasswordPolicies() { assert debugEnter(CLASS_NAME, "getPasswordPolicies"); return directoryServer.passwordPolicies; // The password policy objects are returned in an array to prevent the // caller from modifying the map structure. PasswordPolicyConfig[] values = directoryServer.passwordPolicies.values() .toArray(new PasswordPolicyConfig[0]); PasswordPolicy[] policies = new PasswordPolicy[values.length]; for( int i = 0 ; i < values.length; ++i) { policies[i] = values[i].getPolicy(); } return policies; } @@ -4669,8 +4681,11 @@ { assert debugEnter(CLASS_NAME, "getPasswordPolicy", String.valueOf(configEntryDN)); Validator.ensureNotNull(configEntryDN); return directoryServer.passwordPolicies.get(configEntryDN); PasswordPolicyConfig config = directoryServer.passwordPolicies.get(configEntryDN); return (null == config) ? null : config.getPolicy(); } @@ -4689,8 +4704,11 @@ { assert debugEnter(CLASS_NAME, "registerPasswordPolicy", String.valueOf(configEntryDN), String.valueOf(policy)); Validator.ensureNotNull(configEntryDN, policy); directoryServer.passwordPolicies.put(configEntryDN, policy); PasswordPolicyConfig config = new PasswordPolicyConfig(policy); directoryServer.passwordPolicies.put(configEntryDN, config); } @@ -4706,8 +4724,16 @@ { assert debugEnter(CLASS_NAME, "deregisterPasswordPolicy", String.valueOf(configEntryDN)); Validator.ensureNotNull(configEntryDN); directoryServer.passwordPolicies.remove(configEntryDN); if (directoryServer.defaultPasswordPolicyDN.equals(configEntryDN)) { directoryServer.defaultPasswordPolicyConfig = null; } PasswordPolicyConfig config = directoryServer.passwordPolicies.remove(configEntryDN); if (null != config) config.finalizePasswordPolicyConfig(); } @@ -4730,7 +4756,10 @@ /** * Specifies the DN of the configuration entry for the default password policy * for the Directory Server. * for the Directory Server. This routine does not check the registered * password policies for the specified DN, since in the case of server * initialization, the password policy entries will not yet have been loaded * from the configuration backend. * * @param defaultPasswordPolicyDN The DN of the configuration entry for the * default password policy for the Directory @@ -4742,50 +4771,38 @@ String.valueOf(defaultPasswordPolicyDN)); directoryServer.defaultPasswordPolicyDN = defaultPasswordPolicyDN; directoryServer.defaultPasswordPolicy = null; directoryServer.defaultPasswordPolicyConfig = null; } /** * Retrieves the default password policy for the Directory Server. * Retrieves the default password policy for the Directory Server. This method * is equivalent to invoking <CODE>getPasswordPolicy</CODE> on the DN returned * from <CODE>DirectoryServer.getDefaultPasswordPolicyDN()</CODE>. * * @return The default password policy for the Directory Server. */ public static PasswordPolicy getDefaultPasswordPolicy() { assert debugEnter(CLASS_NAME, "getDefaultPasswordPolicy"); assert null != directoryServer.passwordPolicies.get( directoryServer.defaultPasswordPolicyDN) : "Internal Error: no default password policy defined." ; if ((directoryServer.defaultPasswordPolicy == null) && if ((directoryServer.defaultPasswordPolicyConfig == null) && (directoryServer.defaultPasswordPolicyDN != null)) { directoryServer.defaultPasswordPolicy = directoryServer.defaultPasswordPolicyConfig = directoryServer.passwordPolicies.get( directoryServer.defaultPasswordPolicyDN); } return directoryServer.defaultPasswordPolicy; } /** * Specifies the default password policy for the Directory Server. It will * still be necessary to register this policy with the set of defined password * policies. * * @param defaultPasswordPolicy The default password policy for the * Directory Server. */ public static void setDefaultPasswordPolicy(PasswordPolicy defaultPasswordPolicy) { assert debugEnter(CLASS_NAME, "setDefaultPasswordPolicy", String.valueOf(defaultPasswordPolicy)); directoryServer.defaultPasswordPolicy = defaultPasswordPolicy; directoryServer.defaultPasswordPolicyDN = defaultPasswordPolicy.getConfigurableComponentEntryDN(); assert directoryServer.passwordPolicies.get( directoryServer.defaultPasswordPolicyDN) == directoryServer.defaultPasswordPolicyConfig : "Internal Error: inconsistency between defaultPasswordPolicyConfig" + " cache and value in passwordPolicies map."; return directoryServer.defaultPasswordPolicyConfig.getPolicy(); } @@ -7289,6 +7306,13 @@ } // Finalize the password policy map. for (DN configEntryDN : directoryServer.passwordPolicies.keySet()) { DirectoryServer.deregisterPasswordPolicy(configEntryDN); } // Perform any necessary cleanup work for the group manager. directoryServer.groupManager.finalizeGroupManager(); opends/src/server/org/opends/server/core/PasswordPolicy.java
@@ -29,7 +29,6 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.LinkedHashMap; @@ -41,12 +40,10 @@ import java.util.concurrent.CopyOnWriteArraySet; import org.opends.server.api.AccountStatusNotificationHandler; import org.opends.server.api.ConfigurableComponent; import org.opends.server.api.PasswordGenerator; import org.opends.server.api.PasswordStorageScheme; import org.opends.server.api.PasswordValidator; import org.opends.server.config.BooleanConfigAttribute; import org.opends.server.config.ConfigAttribute; import org.opends.server.config.ConfigEntry; import org.opends.server.config.ConfigException; import org.opends.server.config.DNConfigAttribute; @@ -57,10 +54,8 @@ import org.opends.server.schema.GeneralizedTimeSyntax; import org.opends.server.types.AttributeType; import org.opends.server.types.ByteString; import org.opends.server.types.ConfigChangeResult; import org.opends.server.types.DN; import org.opends.server.types.InitializationException; import org.opends.server.types.ResultCode; import static org.opends.server.config.ConfigConstants.*; import static org.opends.server.loggers.Debug.*; @@ -77,7 +72,6 @@ * Server password policy. */ public class PasswordPolicy implements ConfigurableComponent { /** * The fully-qualified name of this class for debugging purposes. @@ -213,6 +207,7 @@ passwordAttribute = null; authPasswordSyntax = false; lastLoginTimeAttribute = null; previousLastLoginTimeFormats = new CopyOnWriteArrayList<String>(); allowExpiredPasswordChanges = DEFAULT_PWPOLICY_ALLOW_EXPIRED_CHANGES; allowMultiplePasswordValues = DEFAULT_PWPOLICY_ALLOW_MULTIPLE_PW_VALUES; @@ -260,8 +255,6 @@ deprecatedStorageSchemes = new CopyOnWriteArraySet<String>(); passwordValidators = new ConcurrentHashMap<DN,PasswordValidator>(); previousLastLoginTimeFormats = new CopyOnWriteArrayList<String>(); } @@ -287,65 +280,7 @@ public PasswordPolicy(ConfigEntry configEntry) throws ConfigException, InitializationException { this(); assert debugConstructor(CLASS_NAME, String.valueOf(configEntry)); this.configEntryDN = configEntry.getDN(); initializePasswordPolicyConfig(configEntry, this); // Ensure that the password attribute was included in the configuration // entry, since it is required. if (passwordAttribute == null) { int msgID = MSGID_PWPOLICY_NO_PASSWORD_ATTRIBUTE; String message = getMessage(msgID, String.valueOf(configEntryDN)); throw new ConfigException(msgID, message); } // Ensure that at least one default password storage scheme was included in // the configuration entry, since it is required. if (defaultStorageSchemes.isEmpty()) { int msgID = MSGID_PWPOLICY_NO_DEFAULT_STORAGE_SCHEMES; String message = getMessage(msgID, String.valueOf(configEntryDN)); throw new ConfigException(msgID, message); } DirectoryServer.registerConfigurableComponent(this); } /** * Initializes the provided password policy with the information contained in * the given configuration entry. * * @param configEntry The configuration entry to use to obtain the settings * for this password policy. * @param policy The password policy to be initialized. * * @throws ConfigException If the provided entry does not contain a valid * password policy configuration. * * @throws InitializationException If an error occurs while initializing the * password policy that is not related to * the server configuration. */ private static void initializePasswordPolicyConfig(ConfigEntry configEntry, PasswordPolicy policy) throws ConfigException, InitializationException { assert debugEnter(CLASS_NAME, "initializePasswordPolicyConfig", String.valueOf(configEntry)); DN configEntryDN = configEntry.getDN(); this(); // Initialize fields to default values. // Create a list of units and values that we can use to represent time // periods. @@ -362,6 +297,8 @@ timeUnits.put(TIME_UNIT_WEEKS_FULL, (double) (60 * 60 * 24 * 7)); this.configEntryDN = configEntry.getDN(); // Get the password attribute. If specified, it must have either the // user password or auth password syntax. int msgID = MSGID_PWPOLICY_DESCRIPTION_PW_ATTR; @@ -372,16 +309,9 @@ { StringConfigAttribute pwAttrAttr = (StringConfigAttribute) configEntry.getConfigAttribute(pwAttrStub); if (pwAttrAttr == null) { msgID = MSGID_PWPOLICY_NO_PASSWORD_ATTRIBUTE; String message = getMessage(msgID, String.valueOf(configEntryDN)); throw new ConfigException(msgID, message); } else if (pwAttrAttr != null) { String lowerName = toLowerCase(pwAttrAttr.pendingValue()); AttributeType pwAttrType = DirectoryServer.getAttributeType(lowerName); if (pwAttrType == null) { @@ -394,13 +324,13 @@ String syntaxOID = pwAttrType.getSyntaxOID(); if (syntaxOID.equals(SYNTAX_AUTH_PASSWORD_OID)) { policy.passwordAttribute = pwAttrType; policy.authPasswordSyntax = true; this.passwordAttribute = pwAttrType; this.authPasswordSyntax = true; } else if (syntaxOID.equals(SYNTAX_USER_PASSWORD_OID)) { policy.passwordAttribute = pwAttrType; policy.authPasswordSyntax = false; this.passwordAttribute = pwAttrType; this.authPasswordSyntax = false; } else { @@ -413,7 +343,7 @@ msgID = MSGID_PWPOLICY_INVALID_PASSWORD_ATTRIBUTE_SYNTAX; String message = getMessage(msgID, String.valueOf(configEntryDN), String.valueOf(pwAttrAttr.pendingValue()), String.valueOf(syntaxOID)); String.valueOf(syntax)); throw new ConfigException(msgID, message); } } @@ -424,7 +354,7 @@ } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_PASSWORD_ATTRIBUTE; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -457,7 +387,7 @@ for (String schemeName : defaultSchemeAttr.pendingValues()) { PasswordStorageScheme scheme; if (policy.authPasswordSyntax) if (this.authPasswordSyntax) { scheme = DirectoryServer.getAuthPasswordStorageScheme(schemeName); } @@ -480,7 +410,7 @@ } } policy.defaultStorageSchemes = this.defaultStorageSchemes = new CopyOnWriteArrayList<PasswordStorageScheme>(schemes); } } @@ -490,7 +420,7 @@ } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_DEFAULT_STORAGE_SCHEMES; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -511,14 +441,14 @@ configEntry.getConfigAttribute(deprecatedSchemeStub); if (deprecatedSchemeAttr != null) { policy.deprecatedStorageSchemes = this.deprecatedStorageSchemes = new CopyOnWriteArraySet<String>( deprecatedSchemeAttr.pendingValues()); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_DEPRECATED_STORAGE_SCHEMES; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -555,7 +485,7 @@ validators.put(validatorDN, validator); } policy.passwordValidators = validators; this.passwordValidators = validators; } } catch (ConfigException ce) @@ -564,7 +494,7 @@ } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_PASSWORD_VALIDATORS; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -601,7 +531,7 @@ handlers.put(handlerDN, handler); } policy.notificationHandlers = handlers; this.notificationHandlers = handlers; } } catch (ConfigException ce) @@ -610,7 +540,7 @@ } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_NOTIFICATION_HANDLERS; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -631,12 +561,12 @@ configEntry.getConfigAttribute(userChangeStub); if (userChangeAttr != null) { policy.allowUserPasswordChanges = userChangeAttr.pendingValue(); this.allowUserPasswordChanges = userChangeAttr.pendingValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_ALLOW_USER_PW_CHANGES; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -657,12 +587,12 @@ configEntry.getConfigAttribute(requirePWStub); if (requirePWAttr != null) { policy.requireCurrentPassword = requirePWAttr.pendingValue(); this.requireCurrentPassword = requirePWAttr.pendingValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_REQUIRE_CURRENT_PW; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -683,12 +613,12 @@ configEntry.getConfigAttribute(forceChangeOnAddStub); if (forceChangeOnAddAttr != null) { policy.forceChangeOnAdd = forceChangeOnAddAttr.pendingValue(); this.forceChangeOnAdd = forceChangeOnAddAttr.pendingValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_FORCE_CHANGE_ON_ADD; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -709,12 +639,12 @@ configEntry.getConfigAttribute(forceChangeOnResetStub); if (forceChangeAttr != null) { policy.forceChangeOnReset = forceChangeAttr.pendingValue(); this.forceChangeOnReset = forceChangeAttr.pendingValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_FORCE_CHANGE_ON_RESET; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -735,13 +665,13 @@ configEntry.getConfigAttribute(validateResetStub); if (validateResetAttr != null) { policy.skipValidationForAdministrators = this.skipValidationForAdministrators = validateResetAttr.pendingValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_SKIP_ADMIN_VALIDATION; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -771,8 +701,8 @@ throw new ConfigException(msgID, message); } policy.passwordGeneratorDN = generatorAttr.pendingValue(); policy.passwordGenerator = generator; this.passwordGeneratorDN = generatorAttr.pendingValue(); this.passwordGenerator = generator; } } catch (ConfigException ce) @@ -781,7 +711,7 @@ } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_PASSWORD_GENERATOR; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -802,12 +732,12 @@ configEntry.getConfigAttribute(secureAuthStub); if (secureAuthAttr != null) { policy.requireSecureAuthentication = secureAuthAttr.pendingValue(); this.requireSecureAuthentication = secureAuthAttr.pendingValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_REQUIRE_SECURE_AUTH; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -829,12 +759,12 @@ configEntry.getConfigAttribute(secureChangeStub); if (secureChangeAttr != null) { policy.requireSecurePasswordChanges = secureChangeAttr.pendingValue(); this.requireSecurePasswordChanges = secureChangeAttr.pendingValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_REQUIRE_SECURE_CHANGES; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -855,12 +785,12 @@ configEntry.getConfigAttribute(allowMultiplePWStub); if (allowMultiplePWAttr != null) { policy.allowMultiplePasswordValues = allowMultiplePWAttr.pendingValue(); this.allowMultiplePasswordValues = allowMultiplePWAttr.pendingValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_ALLOW_MULTIPLE_PW_VALUES; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -881,12 +811,12 @@ configEntry.getConfigAttribute(preEncodedStub); if (preEncodedAttr != null) { policy.allowPreEncodedPasswords = preEncodedAttr.pendingValue(); this.allowPreEncodedPasswords = preEncodedAttr.pendingValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_ALLOW_PREENCODED; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -908,12 +838,12 @@ configEntry.getConfigAttribute(minAgeStub); if (minAgeAttr != null) { policy.minimumPasswordAge = (int) minAgeAttr.pendingCalculatedValue(); this.minimumPasswordAge = (int) minAgeAttr.pendingCalculatedValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_MIN_AGE; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -935,12 +865,12 @@ configEntry.getConfigAttribute(maxAgeStub); if (maxAgeAttr != null) { policy.maximumPasswordAge = (int) maxAgeAttr.pendingCalculatedValue(); this.maximumPasswordAge = (int) maxAgeAttr.pendingCalculatedValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_MAX_AGE; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -962,13 +892,13 @@ configEntry.getConfigAttribute(maxResetStub); if (maxResetAttr != null) { policy.maximumPasswordResetAge = this.maximumPasswordResetAge = (int) maxResetAttr.pendingCalculatedValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_MAX_RESET_AGE; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -990,12 +920,12 @@ configEntry.getConfigAttribute(warningStub); if (warningAttr != null) { policy.warningInterval = (int) warningAttr.pendingCalculatedValue(); this.warningInterval = (int) warningAttr.pendingCalculatedValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_WARNING_INTERVAL; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -1016,13 +946,13 @@ configEntry.getConfigAttribute(expireWithoutWarningStub); if (expireWithoutWarningAttr != null) { policy.expirePasswordsWithoutWarning = this.expirePasswordsWithoutWarning = expireWithoutWarningAttr.pendingValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_EXPIRE_WITHOUT_WARNING; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -1033,8 +963,8 @@ // If the expire without warning option is disabled, then there must be a // warning interval. if ((! policy.expirePasswordsWithoutWarning()) && (policy.getWarningInterval() <= 0)) if ((! this.expirePasswordsWithoutWarning()) && (this.getWarningInterval() <= 0)) { msgID = MSGID_PWPOLICY_MUST_HAVE_WARNING_IF_NOT_EXPIRE_WITHOUT_WARNING; String message = getMessage(msgID, String.valueOf(configEntryDN)); @@ -1054,13 +984,13 @@ configEntry.getConfigAttribute(allowExpiredChangesStub); if (allowExpiredChangesAttr != null) { policy.allowExpiredPasswordChanges = this.allowExpiredPasswordChanges = allowExpiredChangesAttr.pendingValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_ALLOW_EXPIRED_CHANGES; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -1081,12 +1011,12 @@ (IntegerConfigAttribute) configEntry.getConfigAttribute(graceStub); if (graceAttr != null) { policy.graceLoginCount = graceAttr.pendingIntValue(); this.graceLoginCount = graceAttr.pendingIntValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_GRACE_LOGIN_COUNT; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -1108,12 +1038,12 @@ configEntry.getConfigAttribute(failureCountStub); if (failureCountAttr != null) { policy.lockoutFailureCount = failureCountAttr.pendingIntValue(); this.lockoutFailureCount = failureCountAttr.pendingIntValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_LOCKOUT_FAILURE_COUNT; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -1135,13 +1065,13 @@ configEntry.getConfigAttribute(lockoutDurationStub); if (lockoutDurationAttr != null) { policy.lockoutDuration = this.lockoutDuration = (int) lockoutDurationAttr.pendingCalculatedValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_LOCKOUT_DURATION; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -1164,13 +1094,13 @@ configEntry.getConfigAttribute(failureExpirationStub); if (failureExpirationAttr != null) { policy.lockoutFailureExpirationInterval = this.lockoutFailureExpirationInterval = (int) failureExpirationAttr.pendingCalculatedValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_FAILURE_EXPIRATION; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -1201,21 +1131,21 @@ if (syntax == null) { policy.requireChangeByTime = this.requireChangeByTime = GeneralizedTimeSyntax.decodeGeneralizedTimeValue(valueString); } else { valueString = syntax.getEqualityMatchingRule().normalizeValue(valueString); policy.requireChangeByTime = this.requireChangeByTime = GeneralizedTimeSyntax.decodeGeneralizedTimeValue(valueString); } } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_REQUIRE_CHANGE_BY_TIME; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -1250,7 +1180,7 @@ throw new ConfigException(msgID, message); } policy.lastLoginTimeAttribute = attrType; this.lastLoginTimeAttribute = attrType; } } catch (ConfigException ce) @@ -1259,7 +1189,7 @@ } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_LAST_LOGIN_TIME_ATTR; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -1285,12 +1215,11 @@ try { SimpleDateFormat format = new SimpleDateFormat(formatString); policy.lastLoginTimeFormat = formatString; new SimpleDateFormat(formatString); } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_INVALID_LAST_LOGIN_TIME_FORMAT; @@ -1298,6 +1227,8 @@ String.valueOf(formatString)); throw new ConfigException(msgID, message); } this.lastLoginTimeFormat = formatString; } } catch (ConfigException ce) @@ -1306,7 +1237,7 @@ } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_LAST_LOGIN_TIME_FORMAT; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -1334,12 +1265,11 @@ { try { SimpleDateFormat format = new SimpleDateFormat(s); new SimpleDateFormat(s); } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_INVALID_PREVIOUS_LAST_LOGIN_TIME_FORMAT; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -1348,7 +1278,7 @@ } } policy.previousLastLoginTimeFormats = this.previousLastLoginTimeFormats = new CopyOnWriteArrayList<String>(formatStrings); } } @@ -1358,7 +1288,7 @@ } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_PREVIOUS_LAST_LOGIN_TIME_FORMAT; String message = getMessage(msgID, String.valueOf(configEntryDN), @@ -1380,19 +1310,55 @@ configEntry.getConfigAttribute(idleIntervalStub); if (idleIntervalAttr != null) { policy.idleLockoutInterval = this.idleLockoutInterval = (int) idleIntervalAttr.pendingCalculatedValue(); } } catch (Exception e) { assert debugException(CLASS_NAME, "initializePasswordPolicyConfig", e); assert debugException(CLASS_NAME, "PasswordPolicy", e); msgID = MSGID_PWPOLICY_CANNOT_DETERMINE_IDLE_LOCKOUT_INTERVAL; String message = getMessage(msgID, String.valueOf(configEntryDN), stackTraceToSingleLineString(e)); throw new InitializationException(msgID, message, e); } /* * Holistic validation. */ // Ensure that the password attribute was included in the configuration // entry, since it is required. if (passwordAttribute == null) { msgID = MSGID_PWPOLICY_NO_PASSWORD_ATTRIBUTE; String message = getMessage(msgID, String.valueOf(configEntryDN)); throw new ConfigException(msgID, message); } // Ensure that at least one default password storage scheme was included in // the configuration entry, since it is required. if (defaultStorageSchemes.isEmpty()) { msgID = MSGID_PWPOLICY_NO_DEFAULT_STORAGE_SCHEMES; String message = getMessage(msgID, String.valueOf(configEntryDN)); throw new ConfigException(msgID, message); } } /** * Retrieves the DN of the configuration entry to which this password policy * corresponds. * * @return The DN of the configuration entry. */ public DN getConfigEntryDN() { return configEntryDN; } @@ -2074,506 +2040,6 @@ /** * Retrieves the DN of the configuration entry with which this component is * associated. * * @return The DN of the configuration entry with which this component is * associated. */ public DN getConfigurableComponentEntryDN() { assert debugEnter(CLASS_NAME, "getConfigurableComponentEntryDN"); return configEntryDN; } /** * Retrieves the set of configuration attributes that are associated with this * configurable component. * * @return The set of configuration attributes that are associated with this * configurable component. */ public List<ConfigAttribute> getConfigurationAttributes() { assert debugEnter(CLASS_NAME, "getConfigurationAttributes"); // Create a list of units and values that we can use to represent time // periods. LinkedHashMap<String,Double> timeUnits = new LinkedHashMap<String,Double>(); timeUnits.put(TIME_UNIT_SECONDS_ABBR, 1D); timeUnits.put(TIME_UNIT_SECONDS_FULL, 1D); timeUnits.put(TIME_UNIT_MINUTES_ABBR, 60D); timeUnits.put(TIME_UNIT_MINUTES_FULL, 60D); timeUnits.put(TIME_UNIT_HOURS_ABBR, (double) (60 * 60)); timeUnits.put(TIME_UNIT_HOURS_FULL, (double) (60 * 60)); timeUnits.put(TIME_UNIT_DAYS_ABBR, (double) (60 * 60 * 24)); timeUnits.put(TIME_UNIT_DAYS_FULL, (double) (60 * 60 * 24)); timeUnits.put(TIME_UNIT_WEEKS_ABBR, (double) (60 * 60 * 24 * 7)); timeUnits.put(TIME_UNIT_WEEKS_FULL, (double) (60 * 60 * 24 * 7)); LinkedList<ConfigAttribute> attrList = new LinkedList<ConfigAttribute>(); int msgID = MSGID_PWPOLICY_DESCRIPTION_PW_ATTR; String pwAttr; if (passwordAttribute == null) { pwAttr = null; } else { pwAttr = passwordAttribute.getNameOrOID(); } attrList.add(new StringConfigAttribute(ATTR_PWPOLICY_PASSWORD_ATTRIBUTE, getMessage(msgID), false, false, false, pwAttr)); msgID = MSGID_PWPOLICY_DESCRIPTION_DEFAULT_STORAGE_SCHEMES; ArrayList<String> schemes = new ArrayList<String>(); if (defaultStorageSchemes != null) { for (PasswordStorageScheme s : defaultStorageSchemes) { schemes.add(s.getStorageSchemeName()); } } attrList.add(new StringConfigAttribute(ATTR_PWPOLICY_DEFAULT_SCHEME, getMessage(msgID), false, true, false, schemes)); msgID = MSGID_PWPOLICY_DESCRIPTION_DEPRECATED_STORAGE_SCHEMES; schemes = new ArrayList<String>(); if (deprecatedStorageSchemes != null) { schemes.addAll(deprecatedStorageSchemes); } attrList.add(new StringConfigAttribute(ATTR_PWPOLICY_DEPRECATED_SCHEME, getMessage(msgID), false, true, false, schemes)); msgID = MSGID_PWPOLICY_DESCRIPTION_PASSWORD_VALIDATORS; ArrayList<DN> validatorDNs = new ArrayList<DN>(); if (passwordValidators != null) { validatorDNs.addAll(passwordValidators.keySet()); } attrList.add(new DNConfigAttribute(ATTR_PWPOLICY_PASSWORD_VALIDATOR, getMessage(msgID), false, true, false, validatorDNs)); msgID = MSGID_PWPOLICY_DESCRIPTION_NOTIFICATION_HANDLERS; ArrayList<DN> handlerDNs = new ArrayList<DN>(); if (notificationHandlers != null) { handlerDNs.addAll(notificationHandlers.keySet()); } attrList.add(new DNConfigAttribute(ATTR_PWPOLICY_NOTIFICATION_HANDLER, getMessage(msgID), false, true, false, handlerDNs)); msgID = MSGID_PWPOLICY_DESCRIPTION_ALLOW_USER_PW_CHANGES; attrList.add(new BooleanConfigAttribute(ATTR_PWPOLICY_ALLOW_USER_CHANGE, getMessage(msgID), false, allowUserPasswordChanges)); msgID = MSGID_PWPOLICY_DESCRIPTION_REQUIRE_CURRENT_PW; attrList.add(new BooleanConfigAttribute( ATTR_PWPOLICY_REQUIRE_CURRENT_PASSWORD, getMessage(msgID), false, requireCurrentPassword)); msgID = MSGID_PWPOLICY_DESCRIPTION_FORCE_CHANGE_ON_ADD; attrList.add(new BooleanConfigAttribute(ATTR_PWPOLICY_FORCE_CHANGE_ON_ADD, getMessage(msgID), false, forceChangeOnAdd)); msgID = MSGID_PWPOLICY_DESCRIPTION_FORCE_CHANGE_ON_RESET; attrList.add(new BooleanConfigAttribute(ATTR_PWPOLICY_FORCE_CHANGE_ON_RESET, getMessage(msgID), false, forceChangeOnReset)); msgID = MSGID_PWPOLICY_DESCRIPTION_SKIP_ADMIN_VALIDATION; attrList.add(new BooleanConfigAttribute(ATTR_PWPOLICY_SKIP_ADMIN_VALIDATION, getMessage(msgID), false, skipValidationForAdministrators)); msgID = MSGID_PWPOLICY_DESCRIPTION_PASSWORD_GENERATOR; attrList.add(new DNConfigAttribute(ATTR_PWPOLICY_PASSWORD_GENERATOR, getMessage(msgID), false, false, false, passwordGeneratorDN)); msgID = MSGID_PWPOLICY_DESCRIPTION_REQUIRE_SECURE_AUTH; attrList.add(new BooleanConfigAttribute( ATTR_PWPOLICY_REQUIRE_SECURE_AUTHENTICATION, getMessage(msgID), false, requireSecureAuthentication)); msgID = MSGID_PWPOLICY_DESCRIPTION_REQUIRE_SECURE_CHANGES; attrList.add(new BooleanConfigAttribute( ATTR_PWPOLICY_REQUIRE_SECURE_PASSWORD_CHANGES, getMessage(msgID), false, requireSecurePasswordChanges)); msgID = MSGID_PWPOLICY_DESCRIPTION_ALLOW_MULTIPLE_PW_VALUES; attrList.add(new BooleanConfigAttribute( ATTR_PWPOLICY_ALLOW_MULTIPLE_PW_VALUES, getMessage(msgID), false, allowMultiplePasswordValues)); msgID = MSGID_PWPOLICY_DESCRIPTION_ALLOW_PREENCODED; attrList.add(new BooleanConfigAttribute( ATTR_PWPOLICY_ALLOW_PRE_ENCODED_PASSWORDS, getMessage(msgID), false, allowPreEncodedPasswords)); msgID = MSGID_PWPOLICY_DESCRIPTION_MIN_AGE; attrList.add(new IntegerWithUnitConfigAttribute( ATTR_PWPOLICY_MINIMUM_PASSWORD_AGE, getMessage(msgID), false, timeUnits, true, 0, true, Integer.MAX_VALUE, minimumPasswordAge, TIME_UNIT_SECONDS_FULL)); msgID = MSGID_PWPOLICY_DESCRIPTION_MAX_AGE; attrList.add(new IntegerWithUnitConfigAttribute( ATTR_PWPOLICY_MAXIMUM_PASSWORD_AGE, getMessage(msgID), false, timeUnits, true, 0, true, Integer.MAX_VALUE, maximumPasswordAge, TIME_UNIT_SECONDS_FULL)); msgID = MSGID_PWPOLICY_DESCRIPTION_MAX_RESET_AGE; attrList.add(new IntegerWithUnitConfigAttribute( ATTR_PWPOLICY_MAXIMUM_PASSWORD_RESET_AGE, getMessage(msgID), false, timeUnits, true, 0, true, Integer.MAX_VALUE, maximumPasswordResetAge, TIME_UNIT_SECONDS_FULL)); msgID = MSGID_PWPOLICY_DESCRIPTION_WARNING_INTERVAL; attrList.add(new IntegerWithUnitConfigAttribute( ATTR_PWPOLICY_WARNING_INTERVAL, getMessage(msgID), false, timeUnits, true, 0, true, Integer.MAX_VALUE, warningInterval, TIME_UNIT_SECONDS_FULL)); msgID = MSGID_PWPOLICY_DESCRIPTION_EXPIRE_WITHOUT_WARNING; attrList.add(new BooleanConfigAttribute( ATTR_PWPOLICY_EXPIRE_WITHOUT_WARNING, getMessage(msgID), false, expirePasswordsWithoutWarning)); msgID = MSGID_PWPOLICY_DESCRIPTION_ALLOW_EXPIRED_CHANGES; attrList.add(new BooleanConfigAttribute( ATTR_PWPOLICY_ALLOW_EXPIRED_CHANGES, getMessage(msgID), false, allowExpiredPasswordChanges)); msgID = MSGID_PWPOLICY_DESCRIPTION_GRACE_LOGIN_COUNT; attrList.add(new IntegerConfigAttribute(ATTR_PWPOLICY_GRACE_LOGIN_COUNT, getMessage(msgID), false, false, false, true, 0, true, Integer.MAX_VALUE, graceLoginCount)); msgID = MSGID_PWPOLICY_DESCRIPTION_LOCKOUT_FAILURE_COUNT; attrList.add(new IntegerConfigAttribute(ATTR_PWPOLICY_LOCKOUT_FAILURE_COUNT, getMessage(msgID), false, false, false, true, 0, true, Integer.MAX_VALUE, lockoutFailureCount)); msgID = MSGID_PWPOLICY_DESCRIPTION_LOCKOUT_DURATION; attrList.add(new IntegerWithUnitConfigAttribute( ATTR_PWPOLICY_LOCKOUT_DURATION, getMessage(msgID), false, timeUnits, true, 0, true, Integer.MAX_VALUE, lockoutDuration, TIME_UNIT_SECONDS_FULL)); msgID = MSGID_PWPOLICY_DESCRIPTION_FAILURE_EXPIRATION; attrList.add(new IntegerWithUnitConfigAttribute( ATTR_PWPOLICY_LOCKOUT_FAILURE_EXPIRATION_INTERVAL, getMessage(msgID), false, timeUnits, true, 0, true, Integer.MAX_VALUE, lockoutFailureExpirationInterval, TIME_UNIT_SECONDS_FULL)); msgID = MSGID_PWPOLICY_DESCRIPTION_REQUIRE_CHANGE_BY_TIME; String timeStr = null; if (requireChangeByTime > 0) { timeStr = GeneralizedTimeSyntax.createGeneralizedTimeValue( requireChangeByTime).getStringValue(); } attrList.add(new StringConfigAttribute(ATTR_PWPOLICY_REQUIRE_CHANGE_BY_TIME, getMessage(msgID), false, false, false, timeStr)); msgID = MSGID_PWPOLICY_DESCRIPTION_LAST_LOGIN_TIME_ATTR; String loginTimeAttr; if (lastLoginTimeAttribute == null) { loginTimeAttr = null; } else { loginTimeAttr = lastLoginTimeAttribute.getNameOrOID(); } attrList.add(new StringConfigAttribute( ATTR_PWPOLICY_LAST_LOGIN_TIME_ATTRIBUTE, getMessage(msgID), false, false, false, loginTimeAttr)); msgID = MSGID_PWPOLICY_DESCRIPTION_LAST_LOGIN_TIME_FORMAT; attrList.add(new StringConfigAttribute(ATTR_PWPOLICY_LAST_LOGIN_TIME_FORMAT, getMessage(msgID), false, false, false, lastLoginTimeFormat)); msgID = MSGID_PWPOLICY_DESCRIPTION_PREVIOUS_LAST_LOGIN_TIME_FORMAT; ArrayList<String> previousFormats = new ArrayList<String>(); if (previousLastLoginTimeFormats != null) { previousFormats.addAll(previousLastLoginTimeFormats); } attrList.add(new StringConfigAttribute( ATTR_PWPOLICY_PREVIOUS_LAST_LOGIN_TIME_FORMAT, getMessage(msgID), false, false, false, previousFormats)); msgID = MSGID_PWPOLICY_DESCRIPTION_IDLE_LOCKOUT_INTERVAL; attrList.add(new IntegerWithUnitConfigAttribute( ATTR_PWPOLICY_IDLE_LOCKOUT_INTERVAL, getMessage(msgID), false, timeUnits, true, 0, true, Integer.MAX_VALUE, idleLockoutInterval, TIME_UNIT_SECONDS_FULL)); return attrList; } /** * Indicates whether the provided configuration entry has an acceptable * configuration for this component. If it does not, then detailed * information about the problem(s) should be added to the provided list. * * @param configEntry The configuration entry for which to make the * determination. * @param unacceptableReasons A list that can be used to hold messages about * why the provided entry does not have an * acceptable configuration. * * @return <CODE>true</CODE> if the provided entry has an acceptable * configuration for this component, or <CODE>false</CODE> if not. */ public boolean hasAcceptableConfiguration(ConfigEntry configEntry, List<String> unacceptableReasons) { assert debugEnter(CLASS_NAME, "hasAcceptableConfiguration", String.valueOf(configEntry), "java.util.List<String>"); PasswordPolicy p = new PasswordPolicy(); try { initializePasswordPolicyConfig(configEntry, p); } catch (ConfigException ce) { assert debugException(CLASS_NAME, "hasAcceptableConfiguration", ce); unacceptableReasons.add(ce.getMessage()); return false; } catch (InitializationException ie) { assert debugException(CLASS_NAME, "hasAcceptableConfiguration", ie); unacceptableReasons.add(ie.getMessage()); return false; } // The provided config entry must at least specify the password attribute // and at least one default storage scheme. if (p.passwordAttribute == null) { int msgID = MSGID_PWPOLICY_NO_PASSWORD_ATTRIBUTE; String message = getMessage(msgID, String.valueOf(configEntryDN)); unacceptableReasons.add(message); return false; } if ((p.defaultStorageSchemes == null) || p.defaultStorageSchemes.isEmpty()) { int msgID = MSGID_PWPOLICY_NO_DEFAULT_STORAGE_SCHEMES; String message = getMessage(msgID, String.valueOf(configEntryDN)); unacceptableReasons.add(message); return false; } // If we made it here, then the configuration is acceptable. return true; } /** * Makes a best-effort attempt to apply the configuration contained in the * provided entry. Information about the result of this processing should be * added to the provided message list. Information should always be added to * this list if a configuration change could not be applied. If detailed * results are requested, then information about the changes applied * successfully (and optionally about parameters that were not changed) should * also be included. * * @param configEntry The entry containing the new configuration to * apply for this component. * @param detailedResults Indicates whether detailed information about the * processing should be added to the list. * * @return Information about the result of the configuration update. */ public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry, boolean detailedResults) { assert debugEnter(CLASS_NAME, "applyNewConfiguration", String.valueOf(configEntry), String.valueOf(detailedResults)); ResultCode resultCode = ResultCode.SUCCESS; boolean adminActionRequired = false; ArrayList<String> messages = new ArrayList<String>(); PasswordPolicy p = new PasswordPolicy(); try { initializePasswordPolicyConfig(configEntry, p); } catch (ConfigException ce) { assert debugException(CLASS_NAME, "hasAcceptableConfiguration", ce); resultCode = DirectoryServer.getServerErrorResultCode(); messages.add(ce.getMessage()); return new ConfigChangeResult(resultCode, adminActionRequired, messages); } catch (InitializationException ie) { assert debugException(CLASS_NAME, "hasAcceptableConfiguration", ie); resultCode = DirectoryServer.getServerErrorResultCode(); messages.add(ie.getMessage()); return new ConfigChangeResult(resultCode, adminActionRequired, messages); } // The provided config entry must at least specify the password attribute // and at least one default storage scheme. if (p.passwordAttribute == null) { resultCode = DirectoryServer.getServerErrorResultCode(); int msgID = MSGID_PWPOLICY_NO_PASSWORD_ATTRIBUTE; messages.add(getMessage(msgID, String.valueOf(configEntryDN))); return new ConfigChangeResult(resultCode, adminActionRequired, messages); } if ((p.defaultStorageSchemes == null) || p.defaultStorageSchemes.isEmpty()) { resultCode = DirectoryServer.getServerErrorResultCode(); int msgID = MSGID_PWPOLICY_NO_DEFAULT_STORAGE_SCHEMES; messages.add(getMessage(msgID, String.valueOf(configEntryDN))); return new ConfigChangeResult(resultCode, adminActionRequired, messages); } // If we've made it here, then everything is acceptable. Apply the new // configuration. passwordAttribute = p.passwordAttribute; authPasswordSyntax = p.authPasswordSyntax; lastLoginTimeAttribute = p.lastLoginTimeAttribute; allowMultiplePasswordValues = p.allowMultiplePasswordValues; allowPreEncodedPasswords = p.allowPreEncodedPasswords; allowUserPasswordChanges = p.allowUserPasswordChanges; expirePasswordsWithoutWarning = p.expirePasswordsWithoutWarning; allowExpiredPasswordChanges = p.allowExpiredPasswordChanges; forceChangeOnAdd = p.forceChangeOnAdd; forceChangeOnReset = p.forceChangeOnReset; requireCurrentPassword = p.requireCurrentPassword; requireSecureAuthentication = p.requireSecureAuthentication; requireSecurePasswordChanges = p.requireSecurePasswordChanges; skipValidationForAdministrators = p.skipValidationForAdministrators; graceLoginCount = p.graceLoginCount; idleLockoutInterval = p.idleLockoutInterval; lockoutDuration = p.lockoutDuration; lockoutFailureCount = p.lockoutFailureCount; lockoutFailureExpirationInterval = p.lockoutFailureExpirationInterval; minimumPasswordAge = p.minimumPasswordAge; maximumPasswordAge = p.maximumPasswordAge; maximumPasswordResetAge = p.maximumPasswordResetAge; warningInterval = p.warningInterval; requireChangeByTime = p.requireChangeByTime; lastLoginTimeFormat = p.lastLoginTimeFormat; previousLastLoginTimeFormats = p.previousLastLoginTimeFormats; passwordGenerator = p.passwordGenerator; passwordGeneratorDN = p.passwordGeneratorDN; notificationHandlers = p.notificationHandlers; defaultStorageSchemes = p.defaultStorageSchemes; deprecatedStorageSchemes = p.deprecatedStorageSchemes; passwordValidators = p.passwordValidators; if (detailedResults) { int msgID = MSGID_PWPOLICY_UPDATED_POLICY; messages.add(getMessage(msgID, String.valueOf(configEntryDN))); } return new ConfigChangeResult(resultCode, adminActionRequired, messages); } /** * Retrieves a string representation of this password policy. * * @return A string representation of this password policy. opends/src/server/org/opends/server/core/PasswordPolicyConfig.java
New file @@ -0,0 +1,522 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Portions Copyright 2006-2007 Sun Microsystems, Inc. */ package org.opends.server.core; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import org.opends.server.api.ConfigurableComponent; import org.opends.server.api.PasswordStorageScheme; import org.opends.server.config.BooleanConfigAttribute; import org.opends.server.config.ConfigAttribute; import org.opends.server.config.ConfigEntry; import org.opends.server.config.ConfigException; import org.opends.server.config.DNConfigAttribute; import org.opends.server.config.IntegerConfigAttribute; import org.opends.server.config.IntegerWithUnitConfigAttribute; import org.opends.server.config.StringConfigAttribute; import org.opends.server.schema.GeneralizedTimeSyntax; import org.opends.server.types.ConfigChangeResult; import org.opends.server.types.DN; import org.opends.server.types.InitializationException; import org.opends.server.types.ResultCode; import static org.opends.server.config.ConfigConstants.*; import static org.opends.server.loggers.Debug.*; import static org.opends.server.messages.CoreMessages.*; import static org.opends.server.messages.MessageHandler.getMessage; import static org.opends.server.util.ServerConstants.*; /** This class is the interface between the password policy configurable component and a password policy state object. When a password policy entry is added to the configuration, an instance of this class is created and registered to manage subsequent modification to that configuration entry, including valiadating any proposed modification and applying an accepted modification. */ public class PasswordPolicyConfig implements ConfigurableComponent { /** * The fully-qualified name of this class for debugging purposes. */ private static final String CLASS_NAME = "org.opends.server.core.PasswordPolicyConfig"; /** * The password policy object corresponding to the configuration entry. The * policy referenced by this field is assumed to be valid, hence any * changes resulting from a modification of the configuration entry must be * applied to a newly allocated instance and validated before updating this * reference to point to the new policy instance. */ private PasswordPolicy currentPolicy; /** * Creates a new password policy configurable component to manage the provided * password policy object. * * @param policy The password policy object this object will manage. */ public PasswordPolicyConfig(PasswordPolicy policy) { assert debugConstructor(CLASS_NAME, String.valueOf(policy)); this.currentPolicy = policy; DirectoryServer.registerConfigurableComponent(this); } /** * Finalize a password policy configuration handler. */ public void finalizePasswordPolicyConfig() { assert debugEnter(CLASS_NAME, "finalizePasswordPolicyConfig"); DirectoryServer.deregisterConfigurableComponent(this); } /** * Retrieves the DN of the configuration entry with which this component is * associated. * * @return The DN of the configuration entry with which this component is * associated. */ public DN getConfigurableComponentEntryDN() { assert debugEnter(CLASS_NAME, "getConfigurableComponentEntryDN"); return currentPolicy.getConfigEntryDN(); } /** * Retrieves the set of configuration attributes that are associated with this * configurable component. * * @return The set of configuration attributes that are associated with this * configurable component. */ public List<ConfigAttribute> getConfigurationAttributes() { assert debugEnter(CLASS_NAME, "getConfigurationAttributes"); // Create a list of units and values that we can use to represent time // periods. LinkedHashMap<String,Double> timeUnits = new LinkedHashMap<String,Double>(); timeUnits.put(TIME_UNIT_SECONDS_ABBR, 1D); timeUnits.put(TIME_UNIT_SECONDS_FULL, 1D); timeUnits.put(TIME_UNIT_MINUTES_ABBR, 60D); timeUnits.put(TIME_UNIT_MINUTES_FULL, 60D); timeUnits.put(TIME_UNIT_HOURS_ABBR, (double) (60 * 60)); timeUnits.put(TIME_UNIT_HOURS_FULL, (double) (60 * 60)); timeUnits.put(TIME_UNIT_DAYS_ABBR, (double) (60 * 60 * 24)); timeUnits.put(TIME_UNIT_DAYS_FULL, (double) (60 * 60 * 24)); timeUnits.put(TIME_UNIT_WEEKS_ABBR, (double) (60 * 60 * 24 * 7)); timeUnits.put(TIME_UNIT_WEEKS_FULL, (double) (60 * 60 * 24 * 7)); PasswordPolicy policy = this.currentPolicy; // this field is volatile LinkedList<ConfigAttribute> attrList = new LinkedList<ConfigAttribute>(); int msgID = MSGID_PWPOLICY_DESCRIPTION_PW_ATTR; String pwAttr = (policy.getPasswordAttribute() == null) ? null : policy.getPasswordAttribute().getNameOrOID(); attrList.add(new StringConfigAttribute(ATTR_PWPOLICY_PASSWORD_ATTRIBUTE, getMessage(msgID), false, false, false, pwAttr)); msgID = MSGID_PWPOLICY_DESCRIPTION_DEFAULT_STORAGE_SCHEMES; ArrayList<String> schemes = new ArrayList<String>(); for (PasswordStorageScheme s : policy.getDefaultStorageSchemes()) { schemes.add(s.getStorageSchemeName()); } attrList.add(new StringConfigAttribute(ATTR_PWPOLICY_DEFAULT_SCHEME, getMessage(msgID), false, true, false, schemes)); msgID = MSGID_PWPOLICY_DESCRIPTION_DEPRECATED_STORAGE_SCHEMES; ArrayList<String> deprecatedSchemes = new ArrayList<String>(); deprecatedSchemes.addAll(policy.getDeprecatedStorageSchemes()); attrList.add(new StringConfigAttribute(ATTR_PWPOLICY_DEPRECATED_SCHEME, getMessage(msgID), false, true, false, deprecatedSchemes)); msgID = MSGID_PWPOLICY_DESCRIPTION_PASSWORD_VALIDATORS; ArrayList<DN> validatorDNs = new ArrayList<DN>(); validatorDNs.addAll(policy.getPasswordValidators().keySet()); attrList.add(new DNConfigAttribute(ATTR_PWPOLICY_PASSWORD_VALIDATOR, getMessage(msgID), false, true, false, validatorDNs)); msgID = MSGID_PWPOLICY_DESCRIPTION_NOTIFICATION_HANDLERS; ArrayList<DN> handlerDNs = new ArrayList<DN>(); handlerDNs.addAll(policy.getAccountStatusNotificationHandlers().keySet()); attrList.add(new DNConfigAttribute(ATTR_PWPOLICY_NOTIFICATION_HANDLER, getMessage(msgID), false, true, false, handlerDNs)); msgID = MSGID_PWPOLICY_DESCRIPTION_ALLOW_USER_PW_CHANGES; attrList.add(new BooleanConfigAttribute(ATTR_PWPOLICY_ALLOW_USER_CHANGE, getMessage(msgID), false, policy.allowUserPasswordChanges())); msgID = MSGID_PWPOLICY_DESCRIPTION_REQUIRE_CURRENT_PW; attrList.add(new BooleanConfigAttribute( ATTR_PWPOLICY_REQUIRE_CURRENT_PASSWORD, getMessage(msgID), false, policy.requireCurrentPassword())); msgID = MSGID_PWPOLICY_DESCRIPTION_FORCE_CHANGE_ON_ADD; attrList.add(new BooleanConfigAttribute(ATTR_PWPOLICY_FORCE_CHANGE_ON_ADD, getMessage(msgID), false, policy.forceChangeOnAdd())); msgID = MSGID_PWPOLICY_DESCRIPTION_FORCE_CHANGE_ON_RESET; attrList.add(new BooleanConfigAttribute(ATTR_PWPOLICY_FORCE_CHANGE_ON_RESET, getMessage(msgID), false, policy.forceChangeOnReset())); msgID = MSGID_PWPOLICY_DESCRIPTION_SKIP_ADMIN_VALIDATION; attrList.add(new BooleanConfigAttribute( ATTR_PWPOLICY_SKIP_ADMIN_VALIDATION, getMessage(msgID), false, policy.skipValidationForAdministrators())); msgID = MSGID_PWPOLICY_DESCRIPTION_PASSWORD_GENERATOR; attrList.add(new DNConfigAttribute(ATTR_PWPOLICY_PASSWORD_GENERATOR, getMessage(msgID), false, false, false, policy.getPasswordGeneratorDN())); msgID = MSGID_PWPOLICY_DESCRIPTION_REQUIRE_SECURE_AUTH; attrList.add(new BooleanConfigAttribute( ATTR_PWPOLICY_REQUIRE_SECURE_AUTHENTICATION, getMessage(msgID), false, policy.requireSecureAuthentication())); msgID = MSGID_PWPOLICY_DESCRIPTION_REQUIRE_SECURE_CHANGES; attrList.add(new BooleanConfigAttribute( ATTR_PWPOLICY_REQUIRE_SECURE_PASSWORD_CHANGES, getMessage(msgID), false, policy.requireSecurePasswordChanges())); msgID = MSGID_PWPOLICY_DESCRIPTION_ALLOW_MULTIPLE_PW_VALUES; attrList.add(new BooleanConfigAttribute( ATTR_PWPOLICY_ALLOW_MULTIPLE_PW_VALUES, getMessage(msgID), false, policy.allowMultiplePasswordValues())); msgID = MSGID_PWPOLICY_DESCRIPTION_ALLOW_PREENCODED; attrList.add(new BooleanConfigAttribute( ATTR_PWPOLICY_ALLOW_PRE_ENCODED_PASSWORDS, getMessage(msgID), false, policy.allowPreEncodedPasswords())); msgID = MSGID_PWPOLICY_DESCRIPTION_MIN_AGE; attrList.add(new IntegerWithUnitConfigAttribute( ATTR_PWPOLICY_MINIMUM_PASSWORD_AGE, getMessage(msgID), false, timeUnits, true, 0, true, Integer.MAX_VALUE, policy.getMinimumPasswordAge(), TIME_UNIT_SECONDS_FULL)); msgID = MSGID_PWPOLICY_DESCRIPTION_MAX_AGE; attrList.add(new IntegerWithUnitConfigAttribute( ATTR_PWPOLICY_MAXIMUM_PASSWORD_AGE, getMessage(msgID), false, timeUnits, true, 0, true, Integer.MAX_VALUE, policy.getMaximumPasswordAge(), TIME_UNIT_SECONDS_FULL)); msgID = MSGID_PWPOLICY_DESCRIPTION_MAX_RESET_AGE; attrList.add(new IntegerWithUnitConfigAttribute( ATTR_PWPOLICY_MAXIMUM_PASSWORD_RESET_AGE, getMessage(msgID), false, timeUnits, true, 0, true, Integer.MAX_VALUE, policy.getMaximumPasswordResetAge(), TIME_UNIT_SECONDS_FULL)); msgID = MSGID_PWPOLICY_DESCRIPTION_WARNING_INTERVAL; attrList.add(new IntegerWithUnitConfigAttribute( ATTR_PWPOLICY_WARNING_INTERVAL, getMessage(msgID), false, timeUnits, true, 0, true, Integer.MAX_VALUE, policy.getWarningInterval(), TIME_UNIT_SECONDS_FULL)); msgID = MSGID_PWPOLICY_DESCRIPTION_EXPIRE_WITHOUT_WARNING; attrList.add(new BooleanConfigAttribute( ATTR_PWPOLICY_EXPIRE_WITHOUT_WARNING, getMessage(msgID), false, policy.expirePasswordsWithoutWarning())); msgID = MSGID_PWPOLICY_DESCRIPTION_ALLOW_EXPIRED_CHANGES; attrList.add(new BooleanConfigAttribute( ATTR_PWPOLICY_ALLOW_EXPIRED_CHANGES, getMessage(msgID), false, policy.allowExpiredPasswordChanges())); msgID = MSGID_PWPOLICY_DESCRIPTION_GRACE_LOGIN_COUNT; attrList.add(new IntegerConfigAttribute(ATTR_PWPOLICY_GRACE_LOGIN_COUNT, getMessage(msgID), false, false, false, true, 0, true, Integer.MAX_VALUE, policy.getGraceLoginCount())); msgID = MSGID_PWPOLICY_DESCRIPTION_LOCKOUT_FAILURE_COUNT; attrList.add(new IntegerConfigAttribute(ATTR_PWPOLICY_LOCKOUT_FAILURE_COUNT, getMessage(msgID), false, false, false, true, 0, true, Integer.MAX_VALUE, policy.getLockoutFailureCount())); msgID = MSGID_PWPOLICY_DESCRIPTION_LOCKOUT_DURATION; attrList.add(new IntegerWithUnitConfigAttribute( ATTR_PWPOLICY_LOCKOUT_DURATION, getMessage(msgID), false, timeUnits, true, 0, true, Integer.MAX_VALUE, policy.getLockoutDuration(), TIME_UNIT_SECONDS_FULL)); msgID = MSGID_PWPOLICY_DESCRIPTION_FAILURE_EXPIRATION; attrList.add(new IntegerWithUnitConfigAttribute( ATTR_PWPOLICY_LOCKOUT_FAILURE_EXPIRATION_INTERVAL, getMessage(msgID), false, timeUnits, true, 0, true, Integer.MAX_VALUE, policy.getLockoutFailureExpirationInterval(), TIME_UNIT_SECONDS_FULL)); msgID = MSGID_PWPOLICY_DESCRIPTION_REQUIRE_CHANGE_BY_TIME; String timeStr = null; if (policy.getRequireChangeByTime() > 0) { timeStr = GeneralizedTimeSyntax.createGeneralizedTimeValue( policy.getRequireChangeByTime()).getStringValue(); } attrList.add(new StringConfigAttribute(ATTR_PWPOLICY_REQUIRE_CHANGE_BY_TIME, getMessage(msgID), false, false, false, timeStr)); msgID = MSGID_PWPOLICY_DESCRIPTION_LAST_LOGIN_TIME_ATTR; String loginTimeAttr = (policy.getLastLoginTimeAttribute() == null) ? null : policy.getLastLoginTimeAttribute().getNameOrOID(); attrList.add(new StringConfigAttribute( ATTR_PWPOLICY_LAST_LOGIN_TIME_ATTRIBUTE, getMessage(msgID), false, false, false, loginTimeAttr)); msgID = MSGID_PWPOLICY_DESCRIPTION_LAST_LOGIN_TIME_FORMAT; attrList.add(new StringConfigAttribute(ATTR_PWPOLICY_LAST_LOGIN_TIME_FORMAT, getMessage(msgID), false, false, false, policy.getLastLoginTimeFormat())); msgID = MSGID_PWPOLICY_DESCRIPTION_PREVIOUS_LAST_LOGIN_TIME_FORMAT; ArrayList<String> previousFormats = new ArrayList<String>(); previousFormats.addAll(policy.getPreviousLastLoginTimeFormats()); attrList.add(new StringConfigAttribute( ATTR_PWPOLICY_PREVIOUS_LAST_LOGIN_TIME_FORMAT, getMessage(msgID), false, false, false, previousFormats)); msgID = MSGID_PWPOLICY_DESCRIPTION_IDLE_LOCKOUT_INTERVAL; attrList.add(new IntegerWithUnitConfigAttribute( ATTR_PWPOLICY_IDLE_LOCKOUT_INTERVAL, getMessage(msgID), false, timeUnits, true, 0, true, Integer.MAX_VALUE, policy.getIdleLockoutInterval(), TIME_UNIT_SECONDS_FULL)); return attrList; } /** * Indicates whether the provided configuration entry has an acceptable * configuration for this component. If it does not, then detailed * information about the problem(s) should be added to the provided list. * * @param configEntry The configuration entry for which to make the * determination. * @param unacceptableReasons A list that can be used to hold messages about * why the provided entry does not have an * acceptable configuration. * * @return <CODE>true</CODE> if the provided entry has an acceptable * configuration for this component, or <CODE>false</CODE> if not. */ public boolean hasAcceptableConfiguration(ConfigEntry configEntry, List<String> unacceptableReasons) { assert debugEnter(CLASS_NAME, "hasAcceptableConfiguration", String.valueOf(configEntry), "java.util.List<String>"); assert configEntry.getDN().equals(this.currentPolicy.getConfigEntryDN() ) : "Internal Error: mismatch between DN of configuration entry and" + "DN of current password policy." ; try { new PasswordPolicy(configEntry); } catch (ConfigException ce) { assert debugException(CLASS_NAME, "hasAcceptableConfiguration", ce); unacceptableReasons.add(ce.getMessage()); return false; } catch (InitializationException ie) { assert debugException(CLASS_NAME, "hasAcceptableConfiguration", ie); unacceptableReasons.add(ie.getMessage()); return false; } // If we made it here, then the configuration is acceptable. return true; } /** * Makes a best-effort attempt to apply the configuration contained in the * provided entry. Information about the result of this processing should be * added to the provided message list. Information should always be added to * this list if a configuration change could not be applied. If detailed * results are requested, then information about the changes applied * successfully (and optionally about parameters that were not changed) should * also be included. * * @param configEntry The entry containing the new configuration to * apply for this component. * @param detailedResults Indicates whether detailed information about the * processing should be added to the list. * * @return Information about the result of the configuration update. */ public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry, boolean detailedResults) { assert debugEnter(CLASS_NAME, "applyNewConfiguration", String.valueOf(configEntry), String.valueOf(detailedResults)); assert configEntry.getDN().equals(this.currentPolicy.getConfigEntryDN() ) : "Internal Error: mismatch between DN of configuration entry and" + "DN of current password policy." ; PasswordPolicy p; try { p = new PasswordPolicy(configEntry); } catch (ConfigException ce) { assert debugException(CLASS_NAME, "applyNewConfiguration", ce); ArrayList<String> messages = new ArrayList<String>(); messages.add(ce.getMessage()); return new ConfigChangeResult( DirectoryServer.getServerErrorResultCode(), /*adminActionRequired*/ true, messages); } catch (InitializationException ie) { assert debugException(CLASS_NAME, "applyNewConfiguration", ie); ArrayList<String> messages = new ArrayList<String>(); messages.add(ie.getMessage()); return new ConfigChangeResult( DirectoryServer.getServerErrorResultCode(), /*adminActionRequired*/ true, messages); } // If we've made it here, then everything is acceptable. Apply the new // configuration. ArrayList<String> messages = new ArrayList<String>(); if (detailedResults) { int msgID = MSGID_PWPOLICY_UPDATED_POLICY; messages.add(getMessage(msgID, String.valueOf(p.getConfigEntryDN()))); } this.currentPolicy = p; return new ConfigChangeResult(ResultCode.SUCCESS, /*adminActionRequired*/ false, messages); } /** * Retrieves the PasswordPolicy object representing the configuration entry * managed by this object. * * @return The PasswordPolicy object. */ public PasswordPolicy getPolicy() { return currentPolicy; } } opends/src/server/org/opends/server/core/PasswordPolicyConfigManager.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Portions Copyright 2006 Sun Microsystems, Inc. * Portions Copyright 2006-2007 Sun Microsystems, Inc. */ package org.opends.server.core; @@ -136,8 +136,7 @@ // Get the DN of the default password policy from the core configuration. DN defaultPolicyDN = DirectoryServer.getDefaultPasswordPolicyDN(); if (defaultPolicyDN == null) if( null == DirectoryServer.getDefaultPasswordPolicyDN()) { int msgID = MSGID_CONFIG_PWPOLICY_NO_DEFAULT_POLICY; String message = getMessage(msgID); @@ -147,24 +146,12 @@ // Iterate through the child entries and process them as password policy // configuration entries. boolean defaultExists = false; for (ConfigEntry childEntry : baseEntry.getChildren().values()) { boolean isDefault = defaultPolicyDN.equals(childEntry.getDN()); if (isDefault) { defaultExists = true; } try { PasswordPolicy policy = new PasswordPolicy(childEntry); DirectoryServer.registerPasswordPolicy(childEntry.getDN(), policy); if (isDefault) { DirectoryServer.setDefaultPasswordPolicy(policy); } } catch (ConfigException ce) { @@ -190,10 +177,12 @@ } // If we didn't find the default password policy, then fail. if (! defaultExists) // If the entry specified by the default password policy DN has not been // registered, then fail. if (null == DirectoryServer.getDefaultPasswordPolicy()) { int msgID = MSGID_CONFIG_PWPOLICY_MISSING_DEFAULT_POLICY; DN defaultPolicyDN = DirectoryServer.getDefaultPasswordPolicyDN(); String message = getMessage(msgID, String.valueOf(defaultPolicyDN)); throw new ConfigException(msgID, message); } @@ -225,7 +214,7 @@ // entry. If so, then it's acceptable. try { PasswordPolicy policy = new PasswordPolicy(configEntry); new PasswordPolicy(configEntry); } catch (ConfigException ce) { @@ -338,6 +327,9 @@ // We'll allow the policy to be removed as long as it isn't the default. // FIXME: something like a referential integrity check is needed to ensure // a policy is not removed when referenced by a user entry (either // directly or via a virtual attribute). DN defaultPolicyDN = DirectoryServer.getDefaultPasswordPolicyDN(); if ((defaultPolicyDN != null) && defaultPolicyDN.equals(configEntry.getDN())) @@ -370,6 +362,9 @@ // We'll allow the policy to be removed as long as it isn't the default. // FIXME: something like a referential integrity check is needed to ensure // a policy is not removed when referenced by a user entry (either // directly or via a virtual attribute). ArrayList<String> messages = new ArrayList<String>(1); DN policyDN = configEntry.getDN(); DN defaultPolicyDN = DirectoryServer.getDefaultPasswordPolicyDN(); @@ -381,8 +376,7 @@ return new ConfigChangeResult(ResultCode.CONSTRAINT_VIOLATION, false, messages); } else { DirectoryServer.deregisterPasswordPolicy(policyDN); int msgID = MSGID_CONFIG_PWPOLICY_REMOVED_POLICY; @@ -391,5 +385,3 @@ return new ConfigChangeResult(ResultCode.SUCCESS, false, messages); } } } opends/src/server/org/opends/server/plugins/PasswordPolicyImportPlugin.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Portions Copyright 2006 Sun Microsystems, Inc. * Portions Copyright 2006-2007 Sun Microsystems, Inc. */ package org.opends.server.plugins; @@ -107,7 +107,7 @@ // "final". authPasswordSchemes = new HashMap<AttributeType,PasswordStorageScheme[]>(); userPasswordSchemes = new HashMap<AttributeType,PasswordStorageScheme[]>(); for (PasswordPolicy p : DirectoryServer.getPasswordPolicies().values()) for (PasswordPolicy p : DirectoryServer.getPasswordPolicies()) { AttributeType t = p.getPasswordAttribute(); if (p.usesAuthPasswordSyntax()) opends/tests/unit-tests-testng/src/server/org/opends/server/core/PasswordPolicyTestCase.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Portions Copyright 2006 Sun Microsystems, Inc. * Portions Copyright 2006-2007 Sun Microsystems, Inc. */ package org.opends.server.core; @@ -30,7 +30,6 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; @@ -42,7 +41,6 @@ import org.opends.server.api.PasswordStorageScheme; import org.opends.server.config.ConfigEntry; import org.opends.server.config.ConfigException; import org.opends.server.core.ModifyOperation; import org.opends.server.protocols.internal.InternalClientConnection; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeType; @@ -2113,7 +2111,7 @@ ConfigEntry parentEntry = DirectoryServer.getConfigEntry(parentDN); ConfigEntry configEntry = new ConfigEntry(e, parentEntry); PasswordPolicy p = new PasswordPolicy(configEntry); new PasswordPolicy(configEntry); } @@ -2211,6 +2209,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); defaultSchemes = p.getDefaultStorageSchemes(); assertNotNull(defaultSchemes); assertFalse(defaultSchemes.isEmpty()); @@ -2254,6 +2253,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); defaultSchemes = p.getDefaultStorageSchemes(); assertNotNull(defaultSchemes); assertFalse(defaultSchemes.isEmpty()); @@ -2295,6 +2295,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertTrue(p.isDefaultStorageScheme("BASE64")); assertFalse(p.isDefaultStorageScheme("SSHA")); p.toString(); @@ -2335,6 +2336,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertTrue(p.isDefaultStorageScheme("MD5")); assertFalse(p.isDefaultStorageScheme("SHA1")); p.toString(); @@ -2378,6 +2380,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); deprecatedSchemes = p.getDeprecatedStorageSchemes(); assertNotNull(deprecatedSchemes); assertFalse(deprecatedSchemes.isEmpty()); @@ -2421,6 +2424,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); deprecatedSchemes = p.getDeprecatedStorageSchemes(); assertNotNull(deprecatedSchemes); assertFalse(deprecatedSchemes.isEmpty()); @@ -2461,6 +2465,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertTrue(p.isDeprecatedStorageScheme("BASE64")); p.toString(); @@ -2499,6 +2504,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertTrue(p.isDeprecatedStorageScheme("MD5")); p.toString(); @@ -2540,6 +2546,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertNotNull(p.getPasswordValidators()); assertFalse(p.getPasswordValidators().isEmpty()); p.toString(); @@ -2583,6 +2590,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertNotNull(p.getPasswordValidators()); assertFalse(p.getPasswordValidators().isEmpty()); p.toString(); @@ -2625,6 +2633,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertNotNull(p.getAccountStatusNotificationHandlers()); assertFalse(p.getAccountStatusNotificationHandlers().isEmpty()); p.toString(); @@ -2668,6 +2677,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertNotNull(p.getAccountStatusNotificationHandlers()); assertFalse(p.getAccountStatusNotificationHandlers().isEmpty()); p.toString(); @@ -2706,6 +2716,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertFalse(p.allowUserPasswordChanges()); p.toString(); @@ -2744,6 +2755,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertFalse(p.allowUserPasswordChanges()); p.toString(); @@ -2782,6 +2794,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertTrue(p.requireCurrentPassword()); p.toString(); @@ -2820,6 +2833,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertTrue(p.allowUserPasswordChanges()); p.toString(); @@ -2858,6 +2872,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertTrue(p.forceChangeOnAdd()); p.toString(); @@ -2896,6 +2911,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertTrue(p.forceChangeOnAdd()); p.toString(); @@ -2934,6 +2950,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertTrue(p.forceChangeOnReset()); p.toString(); @@ -2972,6 +2989,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertTrue(p.forceChangeOnReset()); p.toString(); @@ -3010,6 +3028,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertTrue(p.skipValidationForAdministrators()); p.toString(); @@ -3048,6 +3067,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertTrue(p.skipValidationForAdministrators()); p.toString(); @@ -3089,6 +3109,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertNull(p.getPasswordGeneratorDN()); p.toString(); @@ -3130,6 +3151,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertNull(p.getPasswordGeneratorDN()); p.toString(); @@ -3171,6 +3193,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertNull(p.getPasswordGenerator()); p.toString(); @@ -3212,6 +3235,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertNull(p.getPasswordGenerator()); p.toString(); @@ -3250,6 +3274,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertTrue(p.requireSecureAuthentication()); p.toString(); @@ -3288,6 +3313,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertTrue(p.requireSecureAuthentication()); p.toString(); @@ -3326,6 +3352,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertTrue(p.requireSecurePasswordChanges()); p.toString(); @@ -3364,6 +3391,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertTrue(p.requireSecurePasswordChanges()); p.toString(); @@ -3402,6 +3430,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertTrue(p.allowMultiplePasswordValues()); p.toString(); @@ -3440,6 +3469,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertTrue(p.allowMultiplePasswordValues()); p.toString(); @@ -3478,6 +3508,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertTrue(p.allowPreEncodedPasswords()); p.toString(); @@ -3516,6 +3547,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertTrue(p.allowPreEncodedPasswords()); p.toString(); @@ -3554,6 +3586,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertEquals(p.getMinimumPasswordAge(), (24*60*60)); p.toString(); @@ -3592,6 +3625,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertEquals(p.getMinimumPasswordAge(), (24*60*60)); p.toString(); @@ -3630,6 +3664,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertEquals(p.getMaximumPasswordAge(), (90*60*60*24)); p.toString(); @@ -3668,6 +3703,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertEquals(p.getMaximumPasswordAge(), (90*60*60*24)); p.toString(); @@ -3706,6 +3742,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertEquals(p.getMaximumPasswordResetAge(), (24*60*60)); p.toString(); @@ -3744,6 +3781,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertEquals(p.getMaximumPasswordResetAge(), (24*60*60)); p.toString(); @@ -3782,6 +3820,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertEquals(p.getWarningInterval(), (24*60*60)); p.toString(); @@ -3820,6 +3859,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertEquals(p.getWarningInterval(), (24*60*60)); p.toString(); @@ -3858,6 +3898,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertTrue(p.expirePasswordsWithoutWarning()); p.toString(); @@ -3896,6 +3937,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertTrue(p.expirePasswordsWithoutWarning()); p.toString(); @@ -3934,6 +3976,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertTrue(p.allowExpiredPasswordChanges()); p.toString(); @@ -3972,6 +4015,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertTrue(p.allowExpiredPasswordChanges()); p.toString(); @@ -4010,6 +4054,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertEquals(p.getGraceLoginCount(), 3); p.toString(); @@ -4048,6 +4093,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertEquals(p.getGraceLoginCount(), 3); p.toString(); @@ -4086,6 +4132,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertEquals(p.getLockoutFailureCount(), 3); p.toString(); @@ -4124,6 +4171,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertEquals(p.getLockoutFailureCount(), 3); p.toString(); @@ -4162,6 +4210,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertEquals(p.getLockoutDuration(), (15*60)); p.toString(); @@ -4200,6 +4249,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertEquals(p.getLockoutDuration(), (15*60)); p.toString(); @@ -4238,6 +4288,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertEquals(p.getLockoutFailureExpirationInterval(), (10*60)); p.toString(); @@ -4276,6 +4327,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertEquals(p.getLockoutFailureExpirationInterval(), (10*60)); p.toString(); @@ -4315,6 +4367,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertEquals(p.getRequireChangeByTime(), 1000); p.toString(); @@ -4353,6 +4406,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertEquals(p.getRequireChangeByTime(), 1000); p.toString(); @@ -4391,6 +4445,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertNotNull(p.getLastLoginTimeAttribute()); p.toString(); @@ -4429,6 +4484,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertNotNull(p.getLastLoginTimeAttribute()); p.toString(); @@ -4467,6 +4523,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertEquals(p.getLastLoginTimeFormat(), "yyyyMMdd"); p.toString(); @@ -4505,6 +4562,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertEquals(p.getLastLoginTimeFormat(), "yyyyMMdd"); p.toString(); @@ -4544,6 +4602,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertNotNull(p.getPreviousLastLoginTimeFormats()); assertFalse(p.getPreviousLastLoginTimeFormats().isEmpty()); p.toString(); @@ -4584,6 +4643,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertNotNull(p.getPreviousLastLoginTimeFormats()); assertFalse(p.getPreviousLastLoginTimeFormats().isEmpty()); p.toString(); @@ -4622,6 +4682,7 @@ conn.processModify(DN.decode(dnStr), mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getDefaultPasswordPolicy(); assertEquals(p.getIdleLockoutInterval(), (90*60*60*24)); p.toString(); @@ -4660,6 +4721,7 @@ ModifyOperation modifyOperation = conn.processModify(dn, mods); assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS); p = DirectoryServer.getPasswordPolicy(dn); assertEquals(p.getIdleLockoutInterval(), (90*60*60*24)); p.toString();