From 785fcca7ef16dd93aaa3ca22e17a812ab6ac250a Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Wed, 11 Jul 2007 22:25:46 +0000
Subject: [PATCH] Update the password policy configuration to support a new attribute, ds-cfg-state-update-failure-policy. This attribute makes it possible to control how the server should handle failures that may occur when attempting to update password policy state information during a bind operation. This attribute allows the following values:
---
opends/resource/schema/02-config.ldif | 9
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java | 76 +++++++-
opends/src/server/org/opends/server/core/PasswordPolicyState.java | 23 ++
opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyConfiguration.xml | 53 +++++
opends/src/server/org/opends/server/core/PasswordPolicy.java | 24 ++
opends/tests/unit-tests-testng/src/server/org/opends/server/core/BindOperationTestCase.java | 286 +++++++++++++++++++++++++++++++
opends/resource/config/config.ldif | 2
opends/src/server/org/opends/server/messages/CoreMessages.java | 17 +
8 files changed, 471 insertions(+), 19 deletions(-)
diff --git a/opends/resource/config/config.ldif b/opends/resource/config/config.ldif
index 1efaf92..7d1a76c 100644
--- a/opends/resource/config/config.ldif
+++ b/opends/resource/config/config.ldif
@@ -1072,6 +1072,7 @@
ds-cfg-require-secure-authentication: false
ds-cfg-require-secure-password-changes: false
ds-cfg-skip-validation-for-administrators: false
+ds-cfg-state-update-failure-policy: reactive
dn: cn=Root Password Policy,cn=Password Policies,cn=config
objectClass: top
@@ -1099,6 +1100,7 @@
ds-cfg-require-secure-authentication: false
ds-cfg-require-secure-password-changes: false
ds-cfg-skip-validation-for-administrators: false
+ds-cfg-state-update-failure-policy: ignore
dn: cn=Password Storage Schemes,cn=config
objectClass: top
diff --git a/opends/resource/schema/02-config.ldif b/opends/resource/schema/02-config.ldif
index 201b264..d3f874a 100644
--- a/opends/resource/schema/02-config.ldif
+++ b/opends/resource/schema/02-config.ldif
@@ -1475,6 +1475,9 @@
NAME 'ds-cfg-strip-syntax-minimum-upper-bound'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE
X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.443
+ NAME 'ds-cfg-state-update-failure-policy'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL
MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled )
@@ -1602,7 +1605,7 @@
X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.23 NAME 'ds-cfg-access-logger'
SUP ds-cfg-logger
- STRUCTURAL MAY ( ds-cfg-suppress-internal-operations $
+ STRUCTURAL MAY ( ds-cfg-suppress-internal-operations $
ds-cfg-suppress-synchronization-operations )
X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.24 NAME 'ds-cfg-error-logger'
@@ -1803,8 +1806,8 @@
ds-cfg-password-validator-dn $ ds-cfg-previous-last-login-time-format $
ds-cfg-require-change-by-time $ ds-cfg-require-secure-authentication $
ds-cfg-require-secure-password-changes $
- ds-cfg-skip-validation-for-administrators )
- X-ORIGIN 'OpenDS Directory Server' )
+ ds-cfg-skip-validation-for-administrators $
+ ds-cfg-state-update-failure-policy ) X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.63 NAME
'ds-cfg-jmx-connection-handler' SUP ds-cfg-connection-handler
STRUCTURAL MUST ( ds-cfg-listen-port $ ds-cfg-ssl-cert-nickname $
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyConfiguration.xml
index 70a2c3d..933f525 100644
--- a/opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyConfiguration.xml
+++ b/opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyConfiguration.xml
@@ -944,4 +944,57 @@
</ldap:attribute>
</adm:profile>
</adm:property>
+
+ <adm:property name="state-update-failure-policy" mandatory="false"
+ multi-valued="false">
+ <adm:synopsis>
+ Specifies how the server should deal with the inability to update password
+ policy state information during an authentication attempt. In particular,
+ it may be used to control whether an otherwise successful bind operation
+ should fail if a failure occurs while attempting to update password policy
+ state information (e.g., to clear a record of previous authentication
+ failures or to update the last login time), or even whether to reject a
+ bind request if it is known aheaed of time that it will not be possible to
+ update the authentication failure times in the event of an unsuccessful
+ bind attempt (e.g., if the backend writability mode is disabled).
+ </adm:synopsis>
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>reactive</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:enumeration>
+ <adm:value name="ignore">
+ <adm:synopsis>
+ If a bind attempt would otherwise be successful, then do not reject
+ it if a problem occurs while attempting to update the password
+ policy state information for the user.
+ </adm:synopsis>
+ </adm:value>
+ <adm:value name="reactive">
+ <adm:synopsis>
+ Even if a bind attempt would otherwise be successful, reject it if a
+ problem occurs while attempting to update the password policy state
+ information for the user.
+ </adm:synopsis>
+ </adm:value>
+ <adm:value name="proactive">
+ <adm:synopsis>
+ Proactively reject any bind attempt if it is known ahead of time
+ that it would not be possible to update the user's password policy
+ state information.
+ </adm:synopsis>
+ </adm:value>
+ </adm:enumeration>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.443</ldap:oid>
+ <ldap:name>ds-cfg-state-update-failure-policy</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+
</adm:managed-object>
+
diff --git a/opends/src/server/org/opends/server/core/PasswordPolicy.java b/opends/src/server/org/opends/server/core/PasswordPolicy.java
index 14fea7d..6e5eb90 100644
--- a/opends/src/server/org/opends/server/core/PasswordPolicy.java
+++ b/opends/src/server/org/opends/server/core/PasswordPolicy.java
@@ -39,6 +39,7 @@
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
+import org.opends.server.admin.std.meta.PasswordPolicyCfgDefn;
import org.opends.server.admin.std.server.PasswordPolicyCfg;
import org.opends.server.admin.std.server.PasswordValidatorCfg;
import org.opends.server.api.AccountStatusNotificationHandler;
@@ -215,6 +216,11 @@
private CopyOnWriteArrayList<String> previousLastLoginTimeFormats =
new CopyOnWriteArrayList<String>();
+ // The state update failure policy.
+ private PasswordPolicyCfgDefn.StateUpdateFailurePolicy
+ stateUpdateFailurePolicy =
+ PasswordPolicyCfgDefn.StateUpdateFailurePolicy.REACTIVE;
+
/**
@@ -801,6 +807,11 @@
// Get the idle lockout duration.
this.idleLockoutInterval = (int) configuration.getIdleLockoutInterval();
+
+ // Get the state update failure policy.
+ this.stateUpdateFailurePolicy = configuration.getStateUpdateFailurePolicy();
+
+
/*
* Holistic validation.
*/
@@ -1448,6 +1459,19 @@
/**
+ * Retrieves the state update failure policy for this password policy.
+ *
+ * @return The state update failure policy for this password policy.
+ */
+ public PasswordPolicyCfgDefn.StateUpdateFailurePolicy
+ getStateUpdateFailurePolicy()
+ {
+ return stateUpdateFailurePolicy;
+ }
+
+
+
+ /**
* Retrieves a string representation of this password policy.
*
* @return A string representation of this password policy.
diff --git a/opends/src/server/org/opends/server/core/PasswordPolicyState.java b/opends/src/server/org/opends/server/core/PasswordPolicyState.java
index 6c916bf..bd5be3f 100644
--- a/opends/src/server/org/opends/server/core/PasswordPolicyState.java
+++ b/opends/src/server/org/opends/server/core/PasswordPolicyState.java
@@ -39,11 +39,13 @@
import java.util.List;
import java.util.Set;
+import org.opends.server.admin.std.meta.PasswordPolicyCfgDefn;
import org.opends.server.admin.std.server.PasswordValidatorCfg;
import org.opends.server.api.AccountStatusNotificationHandler;
import org.opends.server.api.PasswordGenerator;
import org.opends.server.api.PasswordStorageScheme;
import org.opends.server.api.PasswordValidator;
+import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.ldap.LDAPAttribute;
@@ -57,9 +59,12 @@
import org.opends.server.types.AttributeValue;
import org.opends.server.types.ByteString;
import org.opends.server.types.ConditionResult;
+import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
+import org.opends.server.types.ErrorLogCategory;
+import org.opends.server.types.ErrorLogSeverity;
import org.opends.server.types.Modification;
import org.opends.server.types.ModificationType;
import org.opends.server.types.Operation;
@@ -68,9 +73,8 @@
import org.opends.server.util.TimeThread;
import static org.opends.server.config.ConfigConstants.*;
+import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
-import org.opends.server.loggers.debug.DebugTracer;
-import org.opends.server.types.DebugLogLevel;
import static org.opends.server.messages.CoreMessages.*;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.util.StaticUtils.*;
@@ -4082,7 +4086,20 @@
String message = getMessage(msgID, userDNString,
String.valueOf(internalModify.getErrorMessage()));
- throw new DirectoryException(resultCode, message, msgID);
+ // If this is a root user, or if the password policy says that we should
+ // ignore these problems, then log a warning message. Otherwise, cause
+ // the bind to fail.
+ if ((DirectoryServer.isRootDN(userEntry.getDN()) ||
+ (passwordPolicy.getStateUpdateFailurePolicy() ==
+ PasswordPolicyCfgDefn.StateUpdateFailurePolicy.IGNORE)))
+ {
+ logError(ErrorLogCategory.PASSWORD_POLICY,
+ ErrorLogSeverity.SEVERE_WARNING, message, msgID);
+ }
+ else
+ {
+ throw new DirectoryException(resultCode, message, msgID);
+ }
}
}
}
diff --git a/opends/src/server/org/opends/server/messages/CoreMessages.java b/opends/src/server/org/opends/server/messages/CoreMessages.java
index 54350d9..470fb15 100644
--- a/opends/src/server/org/opends/server/messages/CoreMessages.java
+++ b/opends/src/server/org/opends/server/messages/CoreMessages.java
@@ -6257,6 +6257,18 @@
/**
+ * The message ID for the message that will be used if a bind attempt is
+ * rejected because either the entire server or the user's backend has a
+ * writability mode of "disabled" and the server would not be able to update
+ * the authentication failure count or the last login time. This takes a
+ * single argument, which is the target user DN.
+ */
+ public static final int MSGID_BIND_OPERATION_WRITABILITY_DISABLED =
+ CATEGORY_MASK_CORE | SEVERITY_MASK_MILD_ERROR | 628;
+
+
+
+ /**
* Associates a set of generic messages with the message IDs defined
* in this class.
*/
@@ -8329,6 +8341,11 @@
registerMessage(MSGID_BIND_OPERATION_INSECURE_SIMPLE_BIND,
"Rejecting a simple bind request for user %s because the " +
"password policy requires secure authentication");
+ registerMessage(MSGID_BIND_OPERATION_WRITABILITY_DISABLED,
+ "Rejecting a bind request for user %s because either " +
+ "the entire server or the user's backend has a " +
+ "writability mode of 'disabled' and password policy " +
+ "state updates would not be allowed");
registerMessage(MSGID_BIND_OPERATION_ACCOUNT_DISABLED,
"Rejecting a bind request for user %s because the " +
"account has been administrative disabled");
diff --git a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
index 5208153..e7919f2 100644
--- a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
+++ b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
@@ -45,6 +45,7 @@
import java.util.Map;
import java.util.concurrent.locks.Lock;
+import org.opends.server.admin.std.meta.PasswordPolicyCfgDefn;
import org.opends.server.api.AttributeSyntax;
import org.opends.server.api.Backend;
import org.opends.server.api.ChangeNotificationListener;
@@ -108,13 +109,14 @@
import org.opends.server.types.Modification;
import org.opends.server.types.ModificationType;
import org.opends.server.types.ObjectClass;
+import org.opends.server.types.Operation;
import org.opends.server.types.Privilege;
import org.opends.server.types.RDN;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.SearchResultEntry;
import org.opends.server.types.SynchronizationProviderResult;
-import org.opends.server.types.Operation;
+import org.opends.server.types.WritabilityMode;
import org.opends.server.util.Validator;
import org.opends.server.workflowelement.LeafWorkflowElement;
@@ -3313,8 +3315,8 @@
// Check to see if the user has a password. If not, then fail.
// FIXME -- We need to have a way to enable/disable debugging.
pwPolicyState = new PasswordPolicyState(userEntry, false, false);
- AttributeType pwType
- = pwPolicyState.getPolicy().getPasswordAttribute();
+ PasswordPolicy policy = pwPolicyState.getPolicy();
+ AttributeType pwType = policy.getPasswordAttribute();
List<Attribute> pwAttr = userEntry.getAttribute(pwType);
if ((pwAttr == null) || (pwAttr.isEmpty()))
@@ -3328,9 +3330,35 @@
}
+ // If the password policy is configured to track authentication
+ // failures or keep the last login time and the associated backend
+ // is disabled, then we may need to reject the bind immediately.
+ if ((policy.getStateUpdateFailurePolicy() ==
+ PasswordPolicyCfgDefn.StateUpdateFailurePolicy.PROACTIVE) &&
+ ((policy.getLockoutFailureCount() > 0) ||
+ ((policy.getLastLoginTimeAttribute() != null) &&
+ (policy.getLastLoginTimeFormat() != null))) &&
+ ((DirectoryServer.getWritabilityMode() ==
+ WritabilityMode.DISABLED) ||
+ (backend.getWritabilityMode() == WritabilityMode.DISABLED)))
+ {
+ // This policy isn't applicable to root users, so if it's a root
+ // user then ignore it.
+ if (! DirectoryServer.isRootDN(bindDN))
+ {
+ int msgID = MSGID_BIND_OPERATION_WRITABILITY_DISABLED;
+ String message = getMessage(msgID, String.valueOf(bindDN));
+
+ localOp.setResultCode(ResultCode.INVALID_CREDENTIALS);
+ localOp.setAuthFailureReason(msgID, message);
+ break bindProcessing;
+ }
+ }
+
+
// Check to see if the authentication must be done in a secure
// manner. If so, then the client connection must be secure.
- if (pwPolicyState.getPolicy().requireSecureAuthentication() &&
+ if (policy.requireSecureAuthentication() &&
(! clientConnection.isSecure()))
{
int msgID = MSGID_BIND_OPERATION_INSECURE_SIMPLE_BIND;
@@ -3429,8 +3457,7 @@
pwPolicyErrorType = PasswordPolicyErrorType.PASSWORD_EXPIRED;
}
- int maxGraceLogins
- = pwPolicyState.getPolicy().getGraceLoginCount();
+ int maxGraceLogins = policy.getGraceLoginCount();
if ((maxGraceLogins > 0) && pwPolicyState.mayUseGraceLogin())
{
List<Long> graceLoginTimes = pwPolicyState.getGraceLoginTimes();
@@ -3731,7 +3758,7 @@
localOp.setResultCode(ResultCode.INVALID_CREDENTIALS);
localOp.setAuthFailureReason(msgID, message);
- if (pwPolicyState.getPolicy().getLockoutFailureCount() > 0)
+ if (policy.getLockoutFailureCount() > 0)
{
pwPolicyState.updateAuthFailureTimes();
if (pwPolicyState.lockedDueToFailures())
@@ -3895,7 +3922,33 @@
// regardless of whether the authentication was successful.
if (pwPolicyState != null)
{
- if (pwPolicyState.isDisabled())
+ PasswordPolicy policy = pwPolicyState.getPolicy();
+
+ // If the password policy is configured to track authentication
+ // failures or keep the last login time and the associated backend
+ // is disabled, then we may need to reject the bind immediately.
+ if ((policy.getStateUpdateFailurePolicy() ==
+ PasswordPolicyCfgDefn.StateUpdateFailurePolicy.PROACTIVE) &&
+ ((policy.getLockoutFailureCount() > 0) ||
+ ((policy.getLastLoginTimeAttribute() != null) &&
+ (policy.getLastLoginTimeFormat() != null))) &&
+ ((DirectoryServer.getWritabilityMode() ==
+ WritabilityMode.DISABLED) ||
+ (backend.getWritabilityMode() == WritabilityMode.DISABLED)))
+ {
+ // This policy isn't applicable to root users, so if it's a root
+ // user then ignore it.
+ if (! DirectoryServer.isRootDN(bindDN))
+ {
+ int msgID = MSGID_BIND_OPERATION_WRITABILITY_DISABLED;
+ String message = getMessage(msgID, userDNString);
+
+ localOp.setResultCode(ResultCode.INVALID_CREDENTIALS);
+ localOp.setAuthFailureReason(msgID, message);
+ break bindProcessing;
+ }
+ }
+ else if (pwPolicyState.isDisabled())
{
localOp.setResultCode(ResultCode.INVALID_CREDENTIALS);
@@ -3919,7 +3972,7 @@
break bindProcessing;
}
- if (pwPolicyState.getPolicy().requireSecureAuthentication() &&
+ if (policy.requireSecureAuthentication() &&
(! clientConnection.isSecure()) &&
(! saslHandler.isSecure(saslMechanism)))
{
@@ -3996,8 +4049,7 @@
pwPolicyErrorType = PasswordPolicyErrorType.PASSWORD_EXPIRED;
}
- int maxGraceLogins
- = pwPolicyState.getPolicy().getGraceLoginCount();
+ int maxGraceLogins = policy.getGraceLoginCount();
if ((maxGraceLogins > 0) && pwPolicyState.mayUseGraceLogin())
{
List<Long> graceLoginTimes =
@@ -5472,7 +5524,7 @@
// If the operation is not a synchronization operation,
- // Invoke the pre-operation modify plugins.
+ // Invoke the pre-operation add plugins.
if (!localOp.isSynchronizationOperation())
{
PreOperationPluginResult preOpResult =
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/core/BindOperationTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/core/BindOperationTestCase.java
index b9a23ba..39ac48e 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/core/BindOperationTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/core/BindOperationTestCase.java
@@ -51,6 +51,7 @@
import org.opends.server.protocols.ldap.BindResponseProtocolOp;
import org.opends.server.protocols.ldap.LDAPMessage;
import org.opends.server.protocols.ldap.LDAPResultCode;
+import org.opends.server.tools.LDAPSearch;
import org.opends.server.types.Attribute;
import org.opends.server.types.AuthenticationInfo;
import org.opends.server.types.AuthenticationType;
@@ -1904,7 +1905,7 @@
* cause the connection to no longer be associated with the previous identity.
* This helps provide coverage for issue #1392.
*
- * @throws Exception
+ * @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testRebindClearsAuthInfo()
@@ -1962,5 +1963,288 @@
s.close();
}
+
+
+
+ /**
+ * Tests to ensure that the "ignore" password policy state update policy
+ * works as expected.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testIgnoreStateUpdateFailurePolicy()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ TestCaseUtils.applyModifications(
+ "dn: uid=test.user,o=test",
+ "changetype: add",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password",
+ "",
+ "dn: cn=Default Password Policy,cn=Password Policies,cn=config",
+ "changetype: modify",
+ "replace: ds-cfg-last-login-time-attribute",
+ "ds-cfg-last-login-time-attribute: ds-pwp-last-login-time",
+ "-",
+ "replace: ds-cfg-last-login-time-format",
+ "ds-cfg-last-login-time-format: yyyyMMdd",
+ "-",
+ "replace: ds-cfg-state-update-failure-policy",
+ "ds-cfg-state-update-failure-policy: ignore",
+ "",
+ "dn: cn=config",
+ "changetype: modify",
+ "replace: ds-cfg-writability-mode",
+ "ds-cfg-writability-mode: disabled"
+ );
+
+ try
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "uid=test.user,o=test",
+ "-w", "password",
+ "-b", "",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, System.out, System.err),
+ 0);
+
+ args = new String[]
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-b", "",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, System.out, System.err),
+ 0);
+ }
+ finally
+ {
+ TestCaseUtils.applyModifications(
+ "dn: cn=config",
+ "changetype: modify",
+ "replace: ds-cfg-writability-mode",
+ "ds-cfg-writability-mode: enabled",
+ "",
+ "dn: cn=Default Password Policy,cn=Password Policies,cn=config",
+ "changetype: modify",
+ "replace: ds-cfg-last-login-time-attribute",
+ "-",
+ "replace: ds-cfg-last-login-time-format",
+ "-",
+ "replace: ds-cfg-state-update-failure-policy",
+ "ds-cfg-state-update-failure-policy: reactive"
+ );
+ }
+ }
+
+
+
+ /**
+ * Tests to ensure that the "reactive" password policy state update policy
+ * works as expected.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testReactiveStateUpdateFailurePolicy()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ TestCaseUtils.applyModifications(
+ "dn: uid=test.user,o=test",
+ "changetype: add",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password",
+ "",
+ "dn: cn=Default Password Policy,cn=Password Policies,cn=config",
+ "changetype: modify",
+ "replace: ds-cfg-last-login-time-attribute",
+ "ds-cfg-last-login-time-attribute: ds-pwp-last-login-time",
+ "-",
+ "replace: ds-cfg-last-login-time-format",
+ "ds-cfg-last-login-time-format: yyyyMMdd",
+ "-",
+ "replace: ds-cfg-state-update-failure-policy",
+ "ds-cfg-state-update-failure-policy: reactive",
+ "",
+ "dn: cn=config",
+ "changetype: modify",
+ "replace: ds-cfg-writability-mode",
+ "ds-cfg-writability-mode: disabled"
+ );
+
+ try
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "uid=test.user,o=test",
+ "-w", "password",
+ "-b", "",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ int rc = LDAPSearch.mainSearch(args, false, System.out, System.err);
+ assertFalse(rc == 0);
+ assertFalse(rc == LDAPResultCode.INVALID_CREDENTIALS);
+
+ args = new String[]
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-b", "",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, System.out, System.err),
+ 0);
+ }
+ finally
+ {
+ TestCaseUtils.applyModifications(
+ "dn: cn=config",
+ "changetype: modify",
+ "replace: ds-cfg-writability-mode",
+ "ds-cfg-writability-mode: enabled",
+ "",
+ "dn: cn=Default Password Policy,cn=Password Policies,cn=config",
+ "changetype: modify",
+ "replace: ds-cfg-last-login-time-attribute",
+ "-",
+ "replace: ds-cfg-last-login-time-format",
+ "-",
+ "replace: ds-cfg-state-update-failure-policy",
+ "ds-cfg-state-update-failure-policy: reactive"
+ );
+ }
+ }
+
+
+
+ /**
+ * Tests to ensure that the "proactive" password policy state update policy
+ * works as expected.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testProactiveStateUpdateFailurePolicy()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ TestCaseUtils.applyModifications(
+ "dn: uid=test.user,o=test",
+ "changetype: add",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password",
+ "",
+ "dn: cn=Default Password Policy,cn=Password Policies,cn=config",
+ "changetype: modify",
+ "replace: ds-cfg-last-login-time-attribute",
+ "ds-cfg-last-login-time-attribute: ds-pwp-last-login-time",
+ "-",
+ "replace: ds-cfg-last-login-time-format",
+ "ds-cfg-last-login-time-format: yyyyMMdd",
+ "-",
+ "replace: ds-cfg-state-update-failure-policy",
+ "ds-cfg-state-update-failure-policy: proactive",
+ "",
+ "dn: cn=config",
+ "changetype: modify",
+ "replace: ds-cfg-writability-mode",
+ "ds-cfg-writability-mode: disabled"
+ );
+
+ try
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "uid=test.user,o=test",
+ "-w", "password",
+ "-b", "",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, System.out, System.err),
+ LDAPResultCode.INVALID_CREDENTIALS);
+
+ args = new String[]
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-b", "",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, System.out, System.err),
+ 0);
+ }
+ finally
+ {
+ TestCaseUtils.applyModifications(
+ "dn: cn=config",
+ "changetype: modify",
+ "replace: ds-cfg-writability-mode",
+ "ds-cfg-writability-mode: enabled",
+ "",
+ "dn: cn=Default Password Policy,cn=Password Policies,cn=config",
+ "changetype: modify",
+ "replace: ds-cfg-last-login-time-attribute",
+ "-",
+ "replace: ds-cfg-last-login-time-format",
+ "-",
+ "replace: ds-cfg-state-update-failure-policy",
+ "ds-cfg-state-update-failure-policy: reactive"
+ );
+ }
+ }
}
--
Gitblit v1.10.0