From 93a5c2c6d0c5e2acc2fd59618af6537af33f99f7 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Wed, 27 Jun 2007 22:15:31 +0000
Subject: [PATCH] Add a new extended operation that can be used to interact with password policy state information for a user, including getting and setting various state variables (even those marked NO-USER-MODIFICATION, although these are typically intended for testing purposes only). Users will be required to have the password-reset privilege in order to be able to use this extended operation, and access control will also come into play.
---
opendj-sdk/opends/resource/bin/manage-account | 37
opendj-sdk/opends/resource/bin/manage-account.bat | 33
opendj-sdk/opends/src/server/org/opends/server/core/PasswordPolicyState.java | 552 ++++
opendj-sdk/opends/src/server/org/opends/server/extensions/PasswordPolicyStateExtendedOperation.java | 1703 +++++++++++++++
opendj-sdk/opends/src/server/org/opends/server/tools/ManageAccount.java | 1688 +++++++++++++++
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/PasswordPolicyTestCase.java | 80
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/ManageAccountTestCase.java | 871 +++++++
opendj-sdk/opends/resource/config/config.ldif | 7
opendj-sdk/opends/src/server/org/opends/server/messages/ExtensionsMessages.java | 383 +++
opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java | 5
opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java | 9
opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java | 1184 ++++++++++
12 files changed, 6,501 insertions(+), 51 deletions(-)
diff --git a/opendj-sdk/opends/resource/bin/manage-account b/opendj-sdk/opends/resource/bin/manage-account
new file mode 100755
index 0000000..f022410
--- /dev/null
+++ b/opendj-sdk/opends/resource/bin/manage-account
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# 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.
+
+
+# This script may be used to perform LDAP search operations.
+OPENDS_INVOKE_CLASS="org.opends.server.tools.PasswordPolicyState"
+export OPENDS_INVOKE_CLASS
+
+SCRIPT_NAME_ARG="-Dorg.opends.server.scriptName=password-policy-state"
+export SCRIPT_NAME_ARG
+
+SCRIPT_DIR=`dirname "${0}"`
+"${SCRIPT_DIR}/../lib/_client-script.sh" "${@}"
diff --git a/opendj-sdk/opends/resource/bin/manage-account.bat b/opendj-sdk/opends/resource/bin/manage-account.bat
new file mode 100644
index 0000000..c2bf1b0
--- /dev/null
+++ b/opendj-sdk/opends/resource/bin/manage-account.bat
@@ -0,0 +1,33 @@
+
+@echo off
+rem CDDL HEADER START
+rem
+rem The contents of this file are subject to the terms of the
+rem Common Development and Distribution License, Version 1.0 only
+rem (the "License"). You may not use this file except in compliance
+rem with the License.
+rem
+rem You can obtain a copy of the license at
+rem trunk/opends/resource/legal-notices/OpenDS.LICENSE
+rem or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+rem See the License for the specific language governing permissions
+rem and limitations under the License.
+rem
+rem When distributing Covered Code, include this CDDL HEADER in each
+rem file and include the License file at
+rem trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+rem add the following below this CDDL HEADER, with the fields enclosed
+rem by brackets "[]" replaced with your own identifying information:
+rem Portions Copyright [yyyy] [name of copyright owner]
+rem
+rem CDDL HEADER END
+rem
+rem
+rem Portions Copyright 2006-2007 Sun Microsystems, Inc.
+
+setlocal
+
+set OPENDS_INVOKE_CLASS="org.opends.server.tools.PasswordPolicyState"
+set SCRIPT_NAME_ARG="-Dorg.opends.server.scriptName=password-policy-state"
+call "%~dP0\..\lib\_client-script.bat" %*
+
diff --git a/opendj-sdk/opends/resource/config/config.ldif b/opendj-sdk/opends/resource/config/config.ldif
index 59a1c70..927836c 100644
--- a/opendj-sdk/opends/resource/config/config.ldif
+++ b/opendj-sdk/opends/resource/config/config.ldif
@@ -406,6 +406,13 @@
ds-cfg-extended-operation-handler-enabled: true
ds-cfg-identity-mapper-dn: cn=Exact Match,cn=Identity Mappers,cn=config
+dn: cn=Password Policy State,cn=Extended Operations,cn=config
+objectClass: top
+objectCLass: ds-cfg-extended-operation-handler
+cn: Password Policy State
+ds-cfg-extended-operation-handler-class: org.opends.server.extensions.PasswordPolicyStateExtendedOperation
+ds-cfg-extended-operation-handler-enabled: true
+
dn: cn=StartTLS,cn=Extended Operations,cn=config
objectClass: top
objectClass: ds-cfg-extended-operation-handler
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java
index 78ba9fe..e9661d4 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java
@@ -810,7 +810,7 @@
// If the user must change their password before doing anything else, and
// if the target of the modify operation isn't the user's own entry, then
// reject the request.
- if (clientConnection.mustChangePassword())
+ if ((! isInternalOperation()) && clientConnection.mustChangePassword())
{
DN authzDN = getAuthorizationDN();
if ((authzDN != null) && (! authzDN.equals(entryDN)))
@@ -2450,7 +2450,8 @@
break modifyProcessing;
}
}
- else if(pwPolicyState.mustChangePassword())
+ else if ((! isInternalOperation()) &&
+ pwPolicyState.mustChangePassword())
{
// The user will not be allowed to do anything else before
// the password gets changed.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/PasswordPolicyState.java b/opendj-sdk/opends/src/server/org/opends/server/core/PasswordPolicyState.java
index e37f904..d3a43fe 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/PasswordPolicyState.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/PasswordPolicyState.java
@@ -31,6 +31,7 @@
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
@@ -147,8 +148,8 @@
// The set of grace login times for this user.
private List<Long> graceLoginTimes = null;
- // The time that the user's password should expire (or did expire).
- private long expirationTime = Long.MIN_VALUE;
+ // The time that the user's account should expire (or did expire).
+ private long accountExpirationTime = Long.MIN_VALUE;
// The time that the user's entry was locked due to too many authentication
// failures.
@@ -157,6 +158,9 @@
// The time that the user last authenticated to the Directory Server.
private long lastLoginTime = Long.MIN_VALUE;
+ // The time that the user's password should expire (or did expire).
+ private long passwordExpirationTime = Long.MIN_VALUE;
+
// The last required change time with which the user complied.
private long requiredChangeTime = Long.MIN_VALUE;
@@ -187,13 +191,42 @@
boolean debug)
throws DirectoryException
{
+ this(userEntry, updateEntry, TimeThread.getTime(), debug);
+ }
+
+
+
+ /**
+ * Creates a new password policy state object with the provided information.
+ * Note that this version of the constructor should only be used for testing
+ * purposes when the tests should be evaluated with a fixed time rather than
+ * the actual current time. For all other purposes, the other constructor
+ * should be used.
+ *
+ * @param userEntry The entry with the user account.
+ * @param updateEntry Indicates whether changes should update the provided
+ * user entry directly or whether they should be
+ * collected as a set of modifications.
+ * @param currentTime The time to use as the current time for all
+ * time-related determinations.
+ * @param debug Indicates whether to enable debugging for the
+ * operations performed.
+ *
+ * @throws DirectoryException If a problem occurs while attempting to
+ * determine the password policy for the user or
+ * perform any other state initialization.
+ */
+ public PasswordPolicyState(Entry userEntry, boolean updateEntry,
+ long currentTime, boolean debug)
+ throws DirectoryException
+ {
this.userEntry = userEntry;
this.updateEntry = updateEntry;
this.debug = debug;
+ this.currentTime = currentTime;
userDNString = userEntry.getDN().toString();
passwordPolicy = getPasswordPolicyInternal(this.userEntry, this.debug);
- currentTime = TimeThread.getTime();
// Get the password changed time for the user.
AttributeType type
@@ -636,6 +669,30 @@
/**
+ * Retrieves the time that the password was last changed.
+ *
+ * @return The time that the password was last changed.
+ */
+ public long getPasswordChangedTime()
+ {
+ return passwordChangedTime;
+ }
+
+
+
+ /**
+ * Retrieves the time that this password policy state object was created.
+ *
+ * @return The time that this password policy state object was created.
+ */
+ public long getCurrentTime()
+ {
+ return currentTime;
+ }
+
+
+
+ /**
* Retrieves the set of values for the password attribute from the user entry.
*
* @return The set of values for the password attribute from the user entry.
@@ -664,6 +721,20 @@
*/
public void setPasswordChangedTime()
{
+ setPasswordChangedTime(currentTime);
+ }
+
+
+
+ /**
+ * Sets a new value for the password changed time equal to the specified time.
+ * This method should generally only be used for testing purposes, since the
+ * variant that uses the current time is preferred almost everywhere else.
+ *
+ * @param passwordChangedTime The time to use
+ */
+ public void setPasswordChangedTime(long passwordChangedTime)
+ {
if (debug)
{
if (debugEnabled())
@@ -675,9 +746,9 @@
// passwordChangedTime is computed in the constructor from values in the
// entry.
- if (passwordChangedTime != currentTime)
+ if (this.passwordChangedTime != passwordChangedTime)
{
- passwordChangedTime = currentTime;
+ this.passwordChangedTime = passwordChangedTime;
AttributeType type =
DirectoryServer.getAttributeType(OP_ATTR_PWPOLICY_CHANGED_TIME_LC);
@@ -693,11 +764,11 @@
values.add(new AttributeValue(type, timeValue));
Attribute a = new Attribute(type, OP_ATTR_PWPOLICY_CHANGED_TIME, values);
- ArrayList<Attribute> attrList = new ArrayList<Attribute>(1);
- attrList.add(a);
if (updateEntry)
{
+ ArrayList<Attribute> attrList = new ArrayList<Attribute>(1);
+ attrList.add(a);
userEntry.putAttribute(type, attrList);
}
else
@@ -710,6 +781,57 @@
/**
+ * Removes the password changed time value from the user's entry. This should
+ * only be used for testing purposes, as it can really mess things up if you
+ * don't know what you're doing.
+ */
+ public void clearPasswordChangedTime()
+ {
+ if (debug)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugInfo("Clearing password changed time for user %s",
+ userDNString);
+ }
+ }
+
+ AttributeType type =
+ DirectoryServer.getAttributeType(OP_ATTR_PWPOLICY_CHANGED_TIME_LC,
+ true);
+ if (updateEntry)
+ {
+ userEntry.removeAttribute(type);
+ }
+ else
+ {
+ Attribute a = new Attribute(type);
+ modifications.add(new Modification(ModificationType.REPLACE, a, true));
+ }
+
+
+ // Fall back to using the entry creation time as the password changed time,
+ // if it's defined. Otherwise, use a value of zero.
+ AttributeType createTimeType =
+ DirectoryServer.getAttributeType(OP_ATTR_CREATE_TIMESTAMP_LC, true);
+ try
+ {
+ passwordChangedTime = getGeneralizedTime(createTimeType);
+ if (passwordChangedTime <= 0)
+ {
+ passwordChangedTime = 0;
+ }
+ }
+ catch (Exception e)
+ {
+ passwordChangedTime = 0;
+ }
+ }
+
+
+
+
+ /**
* Indicates whether the user account has been administratively disabled.
*
* @return <CODE>true</CODE> if the user account has been administratively
@@ -876,10 +998,9 @@
DirectoryServer.getAttributeType(OP_ATTR_ACCOUNT_EXPIRATION_TIME,
true);
- long expirationTime;
try
{
- expirationTime = getGeneralizedTime(type);
+ accountExpirationTime = getGeneralizedTime(type);
}
catch (Exception e)
{
@@ -900,7 +1021,7 @@
return true;
}
- if (expirationTime > currentTime)
+ if (accountExpirationTime > currentTime)
{
// The user does have an expiration time, but it hasn't arrived yet.
isAccountExpired = ConditionResult.FALSE;
@@ -913,7 +1034,7 @@
}
}
}
- else if (expirationTime >= 0)
+ else if (accountExpirationTime >= 0)
{
// The user does have an expiration time, and it is in the past.
isAccountExpired = ConditionResult.TRUE;
@@ -948,6 +1069,109 @@
/**
+ * Retrieves the time at which the user's account will expire.
+ *
+ * @return The time at which the user's account will expire, or -1 if it is
+ * not configured with an expiration time.
+ */
+ public long getAccountExpirationTime()
+ {
+ if (accountExpirationTime == Long.MIN_VALUE)
+ {
+ isAccountExpired();
+ }
+
+ return accountExpirationTime;
+ }
+
+
+
+ /**
+ * Sets the user's account expiration time to the specified value.
+ *
+ * @param accountExpirationTime The time that the user's account should
+ * expire.
+ */
+ public void setAccountExpirationTime(long accountExpirationTime)
+ {
+ if (accountExpirationTime < 0)
+ {
+ clearAccountExpirationTime();
+ }
+ else
+ {
+ String timeStr = GeneralizedTimeSyntax.format(accountExpirationTime);
+
+ if (debug)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugInfo("Setting account expiration time for user %s to %s",
+ userDNString, timeStr);
+ }
+ }
+
+ this.accountExpirationTime = accountExpirationTime;
+ AttributeType type =
+ DirectoryServer.getAttributeType(OP_ATTR_ACCOUNT_EXPIRATION_TIME,
+ true);
+
+ LinkedHashSet<AttributeValue> values =
+ new LinkedHashSet<AttributeValue>(1);
+ values.add(new AttributeValue(type, timeStr));
+
+ Attribute a = new Attribute(type, OP_ATTR_ACCOUNT_EXPIRATION_TIME,
+ values);
+
+ if (updateEntry)
+ {
+ ArrayList<Attribute> attrList = new ArrayList<Attribute>(1);
+ attrList.add(a);
+ userEntry.putAttribute(type, attrList);
+ }
+ else
+ {
+ modifications.add(new Modification(ModificationType.REPLACE, a, true));
+ }
+ }
+ }
+
+
+
+ /**
+ * Clears the user's account expiration time.
+ */
+ public void clearAccountExpirationTime()
+ {
+ if (debug)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugInfo("Clearing account expiration time for user %s",
+ userDNString);
+ }
+ }
+
+ accountExpirationTime = -1;
+
+ AttributeType type =
+ DirectoryServer.getAttributeType(OP_ATTR_ACCOUNT_EXPIRATION_TIME,
+ true);
+
+ if (updateEntry)
+ {
+ userEntry.removeAttribute(type);
+ }
+ else
+ {
+ modifications.add(new Modification(ModificationType.REPLACE,
+ new Attribute(type), true));
+ }
+ }
+
+
+
+ /**
* Retrieves the set of times of failed authentication attempts for the user.
* If authentication failure time expiration is enabled, and there are expired
* times in the entry, these times are removed from the instance field and an
@@ -957,7 +1181,7 @@
* which will be an empty list in the case of no valid (unexpired)
* times in the entry.
*/
- private List<Long> getAuthFailureTimes()
+ public List<Long> getAuthFailureTimes()
{
if (authFailureTimes != null)
{
@@ -1185,7 +1409,75 @@
// Now check to see if there have been sufficient failures to lock the
// account.
- if (passwordPolicy.getLockoutFailureCount() <= failureTimes.size())
+ int lockoutCount = passwordPolicy.getLockoutFailureCount();
+ if ((lockoutCount > 0) && (lockoutCount <= authFailureTimes.size()))
+ {
+ setFailureLockedTime(highestFailureTime);
+ if (debug)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugInfo("Locking user account %s due to too many failures.",
+ userDNString);
+ }
+ }
+ }
+ }
+
+
+
+ /**
+ * Explicitly specifies the auth failure times for the associated user. This
+ * should generally only be used for testing purposes. Note that it will also
+ * set or clear the locked time as appropriate.
+ *
+ * @param authFailureTimes The set of auth failure times to use for the
+ * account. An empty list or {@code null} will
+ * clear the account of any existing failures.
+ */
+ public void setAuthFailureTimes(List<Long> authFailureTimes)
+ {
+ if ((authFailureTimes == null) || authFailureTimes.isEmpty())
+ {
+ clearAuthFailureTimes();
+ clearFailureLockedTime();
+ return;
+ }
+
+ long highestFailureTime = -1;
+ for (Long l : authFailureTimes)
+ {
+ highestFailureTime = Math.max(l, highestFailureTime);
+ }
+
+ AttributeType type =
+ DirectoryServer.getAttributeType(OP_ATTR_PWPOLICY_FAILURE_TIME_LC,
+ true);
+
+ LinkedHashSet<AttributeValue> values =
+ new LinkedHashSet<AttributeValue>(authFailureTimes.size());
+ for (Long l : authFailureTimes)
+ {
+ values.add(new AttributeValue(type, GeneralizedTimeSyntax.format(l)));
+ }
+
+ Attribute a = new Attribute(type, OP_ATTR_PWPOLICY_FAILURE_TIME, values);
+
+ if (updateEntry)
+ {
+ ArrayList<Attribute> attrList = new ArrayList<Attribute>(1);
+ attrList.add(a);
+ userEntry.putAttribute(type, attrList);
+ }
+ else
+ {
+ modifications.add(new Modification(ModificationType.REPLACE, a, true));
+ }
+
+ // Now check to see if there have been sufficient failures to lock the
+ // account.
+ int lockoutCount = passwordPolicy.getLockoutFailureCount();
+ if ((lockoutCount > 0) && (lockoutCount <= authFailureTimes.size()))
{
setFailureLockedTime(highestFailureTime);
if (debug)
@@ -1686,6 +1978,20 @@
*/
public void setLastLoginTime()
{
+ setLastLoginTime(currentTime);
+ }
+
+
+
+ /**
+ * Updates the user entry to use the specified last login time. This should
+ * be used primarily for testing purposes, as the variant that uses the
+ * current time should be used most of the time.
+ *
+ * @param lastLoginTime The last login time to set in the user entry.
+ */
+ public void setLastLoginTime(long lastLoginTime)
+ {
AttributeType type = passwordPolicy.getLastLoginTimeAttribute();
String format = passwordPolicy.getLastLoginTimeFormat();
@@ -1698,7 +2004,8 @@
try
{
SimpleDateFormat dateFormat = new SimpleDateFormat(format);
- timestamp = dateFormat.format(TimeThread.getDate());
+ timestamp = dateFormat.format(new Date(lastLoginTime));
+ this.lastLoginTime = dateFormat.parse(timestamp).getTime();
}
catch (Exception e)
{
@@ -1764,6 +2071,38 @@
/**
+ * Clears the last login time from the user's entry. This should generally be
+ * used only for testing purposes.
+ */
+ public void clearLastLoginTime()
+ {
+ if (debug)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugInfo("Clearing last login time for user %s", userDNString);
+ }
+ }
+
+ lastLoginTime = -1;
+
+ AttributeType type =
+ DirectoryServer.getAttributeType(OP_ATTR_LAST_LOGIN_TIME, true);
+
+ if (updateEntry)
+ {
+ userEntry.removeAttribute(type);
+ }
+ else
+ {
+ modifications.add(new Modification(ModificationType.REPLACE,
+ new Attribute(type), true));
+ }
+ }
+
+
+
+ /**
* Indicates whether the user's account is currently locked because it has
* been idle for too long.
*
@@ -2108,9 +2447,9 @@
*/
public long getPasswordExpirationTime()
{
- if (expirationTime == Long.MIN_VALUE)
+ if (passwordExpirationTime == Long.MIN_VALUE)
{
- expirationTime = Long.MAX_VALUE;
+ passwordExpirationTime = Long.MAX_VALUE;
boolean checkWarning = false;
@@ -2118,9 +2457,9 @@
if (maxAge > 0)
{
long expTime = passwordChangedTime + (1000L*maxAge);
- if (expTime < expirationTime)
+ if (expTime < passwordExpirationTime)
{
- expirationTime = expTime;
+ passwordExpirationTime = expTime;
checkWarning = true;
}
}
@@ -2129,9 +2468,9 @@
if (mustChangePassword() && (maxResetAge > 0))
{
long expTime = passwordChangedTime + (1000L*maxResetAge);
- if (expTime < expirationTime)
+ if (expTime < passwordExpirationTime)
{
- expirationTime = expTime;
+ passwordExpirationTime = expTime;
checkWarning = false;
}
}
@@ -2141,20 +2480,20 @@
{
long reqChangeTime = getRequiredChangeTime();
if ((reqChangeTime != mustChangeTime) &&
- (mustChangeTime < expirationTime))
+ (mustChangeTime < passwordExpirationTime))
{
- expirationTime = mustChangeTime;
+ passwordExpirationTime = mustChangeTime;
checkWarning = true;
}
}
- if (expirationTime == Long.MAX_VALUE)
+ if (passwordExpirationTime == Long.MAX_VALUE)
{
- expirationTime = -1;
- shouldWarn = ConditionResult.FALSE;
- isFirstWarning = ConditionResult.FALSE;
- isPasswordExpired = ConditionResult.FALSE;
- mayUseGraceLogin = ConditionResult.TRUE;
+ passwordExpirationTime = -1;
+ shouldWarn = ConditionResult.FALSE;
+ isFirstWarning = ConditionResult.FALSE;
+ isPasswordExpired = ConditionResult.FALSE;
+ mayUseGraceLogin = ConditionResult.TRUE;
}
else if (checkWarning)
{
@@ -2163,7 +2502,8 @@
int warningInterval = passwordPolicy.getWarningInterval();
if (warningInterval > 0)
{
- long shouldWarnTime = expirationTime - (warningInterval*1000L);
+ long shouldWarnTime =
+ passwordExpirationTime - (warningInterval*1000L);
if (shouldWarnTime > currentTime)
{
// The warning time is in the future, so we know the password isn't
@@ -2178,7 +2518,7 @@
// expired.
long warnedTime = getWarnedTime();
- if (expirationTime > currentTime)
+ if (passwordExpirationTime > currentTime)
{
// The password is not expired but we should warn the user.
shouldWarn = ConditionResult.TRUE;
@@ -2191,7 +2531,8 @@
if (! passwordPolicy.expirePasswordsWithoutWarning())
{
- expirationTime = currentTime + (warningInterval*1000L);
+ passwordExpirationTime =
+ currentTime + (warningInterval*1000L);
}
}
else
@@ -2200,7 +2541,7 @@
if (! passwordPolicy.expirePasswordsWithoutWarning())
{
- expirationTime = warnedTime + (warningInterval*1000L);
+ passwordExpirationTime = warnedTime + (warningInterval*1000L);
}
}
}
@@ -2216,8 +2557,8 @@
}
else if (warnedTime > 0)
{
- expirationTime = warnedTime + (warningInterval*1000L);
- if (expirationTime > currentTime)
+ passwordExpirationTime = warnedTime + (warningInterval*1000L);
+ if (passwordExpirationTime > currentTime)
{
shouldWarn = ConditionResult.TRUE;
isFirstWarning = ConditionResult.FALSE;
@@ -2232,10 +2573,10 @@
}
else
{
- shouldWarn = ConditionResult.TRUE;
- isFirstWarning = ConditionResult.TRUE;
- isPasswordExpired = ConditionResult.FALSE;
- expirationTime = currentTime + (warningInterval*1000L);
+ shouldWarn = ConditionResult.TRUE;
+ isFirstWarning = ConditionResult.TRUE;
+ isPasswordExpired = ConditionResult.FALSE;
+ passwordExpirationTime = currentTime + (warningInterval*1000L);
}
}
}
@@ -2247,7 +2588,7 @@
shouldWarn = ConditionResult.FALSE;
isFirstWarning = ConditionResult.FALSE;
- if (currentTime > expirationTime)
+ if (currentTime > passwordExpirationTime)
{
isPasswordExpired = ConditionResult.TRUE;
}
@@ -2263,7 +2604,7 @@
shouldWarn = ConditionResult.FALSE;
isFirstWarning = ConditionResult.FALSE;
- if (expirationTime < currentTime)
+ if (passwordExpirationTime < currentTime)
{
isPasswordExpired = ConditionResult.TRUE;
}
@@ -2279,11 +2620,11 @@
if (debugEnabled())
{
TRACER.debugInfo("Returning password expiration time of %d for user " +
- "%s.", expirationTime, userDNString);
+ "%s.", passwordExpirationTime, userDNString);
}
}
- return expirationTime;
+ return passwordExpirationTime;
}
@@ -2538,6 +2879,24 @@
*/
public void setRequiredChangeTime()
{
+ long requiredChangeByTimePolicy = passwordPolicy.getRequireChangeByTime();
+ if (requiredChangeByTimePolicy > 0)
+ {
+ setRequiredChangeTime(requiredChangeByTimePolicy);
+ }
+ }
+
+
+
+ /**
+ * Updates the user entry with a timestamp indicating that the password has
+ * been changed in accordance with the require change time.
+ *
+ * @param requiredChangeTime The timestamp to use for the required change
+ * time value.
+ */
+ public void setRequiredChangeTime(long requiredChangeTime)
+ {
if (debug)
{
if (debugEnabled())
@@ -2547,16 +2906,14 @@
}
}
- long requiredChangeByTimePolicy = passwordPolicy.getRequireChangeByTime();
- if (getRequiredChangeTime() != requiredChangeByTimePolicy)
+ if (getRequiredChangeTime() != requiredChangeTime)
{
AttributeType type = DirectoryServer.getAttributeType(
OP_ATTR_PWPOLICY_CHANGED_BY_REQUIRED_TIME, true);
LinkedHashSet<AttributeValue> values =
new LinkedHashSet<AttributeValue>(1);
- String timeValue =
- GeneralizedTimeSyntax.format(requiredChangeByTimePolicy);
+ String timeValue = GeneralizedTimeSyntax.format(requiredChangeTime);
values.add(new AttributeValue(type, timeValue));
Attribute a = new Attribute(type,
@@ -2579,6 +2936,36 @@
/**
+ * Updates the user entry to remove any timestamp indicating that the password
+ * has been changed in accordance with the required change time.
+ */
+ public void clearRequiredChangeTime()
+ {
+ if (debug)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugInfo("Clearing required change time for user %s",
+ userDNString);
+ }
+ }
+
+ AttributeType type = DirectoryServer.getAttributeType(
+ OP_ATTR_PWPOLICY_CHANGED_BY_REQUIRED_TIME, true);
+ if (updateEntry)
+ {
+ userEntry.removeAttribute(type);
+ }
+ else
+ {
+ modifications.add(new Modification(ModificationType.REPLACE,
+ new Attribute(type), true));
+ }
+ }
+
+
+
+ /**
* Retrieves the time that the user was first warned about an upcoming
* expiration.
*
@@ -2632,22 +3019,37 @@
*/
public void setWarnedTime()
{
+ setWarnedTime(currentTime);
+ }
+
+
+
+ /**
+ * Updates the user entry to set the warned time to the specified time. This
+ * method should generally only be used for testing purposes, since the
+ * variant that uses the current time is preferred almost everywhere else.
+ *
+ * @param warnedTime The value to use for the warned time.
+ */
+ public void setWarnedTime(long warnedTime)
+ {
long warnTime = getWarnedTime();
- if (warnTime == currentTime)
+ if (warnTime == warnedTime)
{
if (debug)
{
if (debugEnabled())
{
TRACER.debugInfo("Not updating warned time for user %s because " +
- "the warned time is the same as the current time.", userDNString);
+ "the warned time is the same as the specified time.",
+ userDNString);
}
}
return;
}
- warnedTime = currentTime;
+ this.warnedTime = warnedTime;
AttributeType type =
DirectoryServer.getAttributeType(OP_ATTR_PWPOLICY_WARNED_TIME, true);
@@ -2879,6 +3281,58 @@
/**
+ * Specifies the set of grace login use times for the associated user. If
+ * the provided list is empty or {@code null}, then the set will be cleared.
+ *
+ * @param graceLoginTimes The grace login use times for the associated user.
+ */
+ public void setGraceLoginTimes(List<Long> graceLoginTimes)
+ {
+ if ((graceLoginTimes == null) || graceLoginTimes.isEmpty())
+ {
+ clearGraceLoginTimes();
+ return;
+ }
+
+
+ if (debug)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugInfo("Updating grace login times for user %s",
+ userDNString);
+ }
+ }
+
+
+ AttributeType type =
+ DirectoryServer.getAttributeType(OP_ATTR_PWPOLICY_GRACE_LOGIN_TIME_LC,
+ true);
+ LinkedHashSet<AttributeValue> values =
+ new LinkedHashSet<AttributeValue>(graceLoginTimes.size());
+ for (Long l : graceLoginTimes)
+ {
+ values.add(new AttributeValue(type, GeneralizedTimeSyntax.format(l)));
+ }
+ Attribute a =
+ new Attribute(type, OP_ATTR_PWPOLICY_GRACE_LOGIN_TIME, values);
+
+ if (updateEntry)
+ {
+ ArrayList<Attribute> attrList = new ArrayList<Attribute>(1);
+ attrList.add(a);
+
+ userEntry.putAttribute(type, attrList);
+ }
+ else
+ {
+ modifications.add(new Modification(ModificationType.REPLACE, a, true));
+ }
+ }
+
+
+
+ /**
* Updates the user entry to remove any record of previous grace logins.
*/
public void clearGraceLoginTimes()
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/PasswordPolicyStateExtendedOperation.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/PasswordPolicyStateExtendedOperation.java
new file mode 100644
index 0000000..a8c6deb
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/PasswordPolicyStateExtendedOperation.java
@@ -0,0 +1,1703 @@
+/*
+ * 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.extensions;
+
+
+
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+
+import org.opends.server.admin.std.server.ExtendedOperationHandlerCfg;
+import org.opends.server.api.ClientConnection;
+import org.opends.server.api.ExtendedOperationHandler;
+import org.opends.server.config.ConfigException;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.ExtendedOperation;
+import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.PasswordPolicy;
+import org.opends.server.core.PasswordPolicyState;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.protocols.asn1.ASN1Element;
+import org.opends.server.protocols.asn1.ASN1Enumerated;
+import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.protocols.asn1.ASN1Sequence;
+import org.opends.server.protocols.internal.InternalClientConnection;
+import org.opends.server.protocols.internal.InternalSearchOperation;
+import org.opends.server.schema.GeneralizedTimeSyntax;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DereferencePolicy;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DN;
+import org.opends.server.types.Entry;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.Modification;
+import org.opends.server.types.Privilege;
+import org.opends.server.types.ResultCode;
+import org.opends.server.types.SearchFilter;
+import org.opends.server.types.SearchResultEntry;
+import org.opends.server.types.SearchScope;
+
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.messages.ExtensionsMessages.*;
+import static org.opends.server.messages.MessageHandler.*;
+import static org.opends.server.util.ServerConstants.*;
+import static org.opends.server.util.StaticUtils.*;
+
+
+
+/**
+ * This class implements an LDAP extended operation that can be used to query
+ * and update elements of the Directory Server password policy state for a given
+ * user. The ASN.1 definition for the value of the extended request is:
+ * <BR>
+ * <PRE>
+ * PasswordPolicyStateValue ::= SEQUENCE {
+ * targetUser LDAPDN
+ * operations SEQUENCE OF PasswordPolicyStateOperation OPTIONAL }
+ *
+ * PasswordPolicyStateOperation ::= SEQUENCE {
+ * opType ENUMERATED {
+ * getPasswordPolicyDN (0),
+ * getAccountDisabledState (1),
+ * setAccountDisabledState (2),
+ * clearAccountDisabledState (3),
+ * getAccountExpirationTime (4),
+ * setAccountExpirationTime (5),
+ * clearAccountExpirationTime (6),
+ * getSecondsUntilAccountExpiration (7),
+ * getPasswordChangedTime (8),
+ * setPasswordChangedTime (9),
+ * clearPasswordChangedTime (10),
+ * getPasswordExpirationWarnedTime (11),
+ * setPasswordExpirationWarnedTime (12),
+ * clearPasswordExpirationWarnedTime (13),
+ * getSecondsUntilPasswordExpiration (14),
+ * getSecondsUntilPasswordExpirationWarning (15),
+ * getAuthenticationFailureTimes (16),
+ * addAuthenticationFailureTime (17),
+ * setAuthenticationFailureTimes (18),
+ * clearAuthenticationFailureTimes (19),
+ * getSecondsUntilAuthenticationFailureUnlock (20),
+ * getRemainingAuthenticationFailureCount (21),
+ * getLastLoginTime (22),
+ * setLastLoginTime (23),
+ * clearLastLoginTime (24),
+ * getSecondsUntilIdleLockout (25),
+ * getPasswordResetState (26),
+ * setPasswordResetState (27),
+ * clearPasswordResetState (28),
+ * getSecondsUntilPasswordResetLockout (29),
+ * getGraceLoginUseTimes (30),
+ * addGraceLoginUseTime (31),
+ * setGraceLoginUseTimes (32),
+ * clearGraceLoginUseTimes (33),
+ * getRemainingGraceLoginCount (34),
+ * getPasswordChangedByRequiredTime (35),
+ * setPasswordChangedByRequiredTime (36),
+ * clearPasswordChangedByRequiredTime (37),
+ * getSecondsUntilRequiredChangeTime (38),
+ * ... },
+ * opValues SEQUENCE OF OCTET STRING OPTIONAL }
+ * </PRE>
+ * <BR>
+ * Both the request and response values use the same encoded form, and they both
+ * use the same OID of "1.3.6.1.4.1.26027.1.6.1". The response value will only
+ * include get* elements. If the request did not include any operations, then
+ * the response will include all get* elements; otherwise, the response will
+ * only include the get* elements that correspond to the state fields referenced
+ * in the request (regardless of whether that operation was included in a get*,
+ * set*, add*, remove*, or clear* operation).
+ */
+public class PasswordPolicyStateExtendedOperation
+ extends ExtendedOperationHandler<ExtendedOperationHandlerCfg>
+{
+ /**
+ * The tracer object for the debug logger.
+ */
+ private static final DebugTracer TRACER = getTracer();
+
+
+
+ /**
+ * The enumerated value for the getPasswordPolicyDN operation.
+ */
+ public static final int OP_GET_PASSWORD_POLICY_DN = 0;
+
+
+
+ /**
+ * The enumerated value for the getAccountDisabledState operation.
+ */
+ public static final int OP_GET_ACCOUNT_DISABLED_STATE = 1;
+
+
+
+ /**
+ * The enumerated value for the setAccountDisabledState operation.
+ */
+ public static final int OP_SET_ACCOUNT_DISABLED_STATE = 2;
+
+
+
+ /**
+ * The enumerated value for the clearAccountDisabledState operation.
+ */
+ public static final int OP_CLEAR_ACCOUNT_DISABLED_STATE = 3;
+
+
+
+ /**
+ * The enumerated value for the getAccountExpirationTime operation.
+ */
+ public static final int OP_GET_ACCOUNT_EXPIRATION_TIME = 4;
+
+
+
+ /**
+ * The enumerated value for the setAccountExpirationTime operation.
+ */
+ public static final int OP_SET_ACCOUNT_EXPIRATION_TIME = 5;
+
+
+
+ /**
+ * The enumerated value for the clearAccountExpirationTime operation.
+ */
+ public static final int OP_CLEAR_ACCOUNT_EXPIRATION_TIME = 6;
+
+
+
+ /**
+ * The enumerated value for the getSecondsUntilAccountExpiration operation.
+ */
+ public static final int OP_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION = 7;
+
+
+
+ /**
+ * The enumerated value for the getPasswordChangedTime operation.
+ */
+ public static final int OP_GET_PASSWORD_CHANGED_TIME = 8;
+
+
+
+ /**
+ * The enumerated value for the setPasswordChangedTime operation.
+ */
+ public static final int OP_SET_PASSWORD_CHANGED_TIME = 9;
+
+
+
+ /**
+ * The enumerated value for the clearPasswordChangedTime operation.
+ */
+ public static final int OP_CLEAR_PASSWORD_CHANGED_TIME = 10;
+
+
+
+ /**
+ * The enumerated value for the getPasswordExpirationWarnedTime operation.
+ */
+ public static final int OP_GET_PASSWORD_EXPIRATION_WARNED_TIME = 11;
+
+
+
+ /**
+ * The enumerated value for the setPasswordExpirationWarnedTime operation.
+ */
+ public static final int OP_SET_PASSWORD_EXPIRATION_WARNED_TIME = 12;
+
+
+
+ /**
+ * The enumerated value for the clearPasswordExpirationWarnedTime operation.
+ */
+ public static final int OP_CLEAR_PASSWORD_EXPIRATION_WARNED_TIME = 13;
+
+
+
+ /**
+ * The enumerated value for the getSecondsUntilPasswordExpiration operation.
+ */
+ public static final int OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION = 14;
+
+
+
+ /**
+ * The enumerated value for the getSecondsUntilPasswordExpirationWarning
+ * operation.
+ */
+ public static final int OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING = 15;
+
+
+
+ /**
+ * The enumerated value for the getAuthenticationFailureTimes operation.
+ */
+ public static final int OP_GET_AUTHENTICATION_FAILURE_TIMES = 16;
+
+
+
+ /**
+ * The enumerated value for the addAuthenticationFailureTime operation.
+ */
+ public static final int OP_ADD_AUTHENTICATION_FAILURE_TIME = 17;
+
+
+
+ /**
+ * The enumerated value for the setAuthenticationFailureTimes operation.
+ */
+ public static final int OP_SET_AUTHENTICATION_FAILURE_TIMES = 18;
+
+
+
+ /**
+ * The enumerated value for the clearAuthenticationFailureTimes operation.
+ */
+ public static final int OP_CLEAR_AUTHENTICATION_FAILURE_TIMES = 19;
+
+
+
+ /**
+ * The enumerated value for the getSecondsUntilAuthenticationFailureUnlock
+ * operation.
+ */
+ public static final int OP_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK =
+ 20;
+
+
+
+ /**
+ * The enumerated value for the getRemainingAuthenticationFailureCount
+ * operation.
+ */
+ public static final int OP_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT = 21;
+
+
+
+ /**
+ * The enumerated value for the getLastLoginTime operation.
+ */
+ public static final int OP_GET_LAST_LOGIN_TIME = 22;
+
+
+
+ /**
+ * The enumerated value for the setLastLoginTime operation.
+ */
+ public static final int OP_SET_LAST_LOGIN_TIME = 23;
+
+
+
+ /**
+ * The enumerated value for the clearLastLoginTime operation.
+ */
+ public static final int OP_CLEAR_LAST_LOGIN_TIME = 24;
+
+
+
+ /**
+ * The enumerated value for the getSecondsUntilIdleLockout operation.
+ */
+ public static final int OP_GET_SECONDS_UNTIL_IDLE_LOCKOUT = 25;
+
+
+
+ /**
+ * The enumerated value for the getPasswordResetState operation.
+ */
+ public static final int OP_GET_PASSWORD_RESET_STATE = 26;
+
+
+
+ /**
+ * The enumerated value for the setPasswordResetState operation.
+ */
+ public static final int OP_SET_PASSWORD_RESET_STATE = 27;
+
+
+
+ /**
+ * The enumerated value for the clearPasswordResetState operation.
+ */
+ public static final int OP_CLEAR_PASSWORD_RESET_STATE = 28;
+
+
+
+ /**
+ * The enumerated value for the getSecondsUntilPasswordResetLockout operation.
+ */
+ public static final int OP_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT = 29;
+
+
+
+ /**
+ * The enumerated value for the getGraceLoginUseTimes operation.
+ */
+ public static final int OP_GET_GRACE_LOGIN_USE_TIMES = 30;
+
+
+
+ /**
+ * The enumerated value for the addGraceLoginUseTime operation.
+ */
+ public static final int OP_ADD_GRACE_LOGIN_USE_TIME = 31;
+
+
+
+ /**
+ * The enumerated value for the setGraceLoginUseTimes operation.
+ */
+ public static final int OP_SET_GRACE_LOGIN_USE_TIMES = 32;
+
+
+
+ /**
+ * The enumerated value for the clearGraceLoginUseTimes operation.
+ */
+ public static final int OP_CLEAR_GRACE_LOGIN_USE_TIMES = 33;
+
+
+
+ /**
+ * The enumerated value for the getRemainingGraceLoginCount operation.
+ */
+ public static final int OP_GET_REMAINING_GRACE_LOGIN_COUNT = 34;
+
+
+
+ /**
+ * The enumerated value for the getPasswordChangedByRequiredTime operation.
+ */
+ public static final int OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME = 35;
+
+
+
+ /**
+ * The enumerated value for the setPasswordChangedByRequiredTime operation.
+ */
+ public static final int OP_SET_PASSWORD_CHANGED_BY_REQUIRED_TIME = 36;
+
+
+
+ /**
+ * The enumerated value for the clearPasswordChangedByRequiredTime operation.
+ */
+ public static final int OP_CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME = 37;
+
+
+
+ /**
+ * The enumerated value for the getSecondsUntilRequiredChangeTime operation.
+ */
+ public static final int OP_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME = 38;
+
+
+
+ // The set of attributes to request when retrieving a user's entry.
+ private LinkedHashSet<String> requestAttributes;
+
+ // The search filter that will be used to retrieve user entries.
+ private SearchFilter userFilter;
+
+
+
+ /**
+ * Create an instance of this password policy state extended operation. All
+ * initialization should be performed in the
+ * {@code initializeExtendedOperationHandler} method.
+ */
+ public PasswordPolicyStateExtendedOperation()
+ {
+ super();
+ }
+
+
+ /**
+ * Initializes this extended operation handler based on the information in the
+ * provided configuration entry. It should also register itself with the
+ * Directory Server for the particular kinds of extended operations that it
+ * will process.
+ *
+ * @param config The configuration that contains the information
+ * to use to initialize this extended operation handler.
+ *
+ * @throws ConfigException If an unrecoverable problem arises in the
+ * process of performing the initialization.
+ *
+ * @throws InitializationException If a problem occurs during initialization
+ * that is not related to the server
+ * configuration.
+ */
+ public void initializeExtendedOperationHandler(
+ ExtendedOperationHandlerCfg config)
+ throws ConfigException, InitializationException
+ {
+ // Construct the filter that will be used to retrieve user entries.
+ try
+ {
+ userFilter = SearchFilter.createFilterFromString("(objectClass=*)");
+ }
+ catch (Exception e)
+ {
+ // This should never happen.
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+
+
+ // Construct the set of request attributes.
+ requestAttributes = new LinkedHashSet<String>(2);
+ requestAttributes.add("*");
+ requestAttributes.add("+");
+
+
+ DirectoryServer.registerSupportedExtension(OID_PASSWORD_POLICY_STATE_EXTOP,
+ this);
+ }
+
+
+
+ /**
+ * Performs any finalization that may be necessary for this extended
+ * operation handler. By default, no finalization is performed.
+ */
+ public void finalizeExtendedOperationHandler()
+ {
+ DirectoryServer.deregisterSupportedExtension(OID_CANCEL_REQUEST);
+ }
+
+
+
+ /**
+ * Processes the provided extended operation.
+ *
+ * @param operation The extended operation to be processed.
+ */
+ public void processExtendedOperation(ExtendedOperation operation)
+ {
+ operation.setResultCode(ResultCode.UNDEFINED);
+
+
+ // The user must have the password-reset privilege in order to be able to do
+ // anything with this extended operation.
+ ClientConnection clientConnection = operation.getClientConnection();
+ if (! clientConnection.hasPrivilege(Privilege.PASSWORD_RESET, operation))
+ {
+ String message = getMessage(MSGID_PWPSTATE_EXTOP_NO_PRIVILEGE);
+ operation.appendErrorMessage(message);
+ operation.setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
+ return;
+ }
+
+
+ // There must be a request value, and it must be a sequence. Decode it
+ // into its components.
+ ASN1OctetString requestValue = operation.getRequestValue();
+ if (requestValue == null)
+ {
+ String message = getMessage(MSGID_PWPSTATE_EXTOP_NO_REQUEST_VALUE);
+ operation.appendErrorMessage(message);
+ operation.setResultCode(ResultCode.PROTOCOL_ERROR);
+ return;
+ }
+
+ ASN1OctetString dnString;
+ ASN1Sequence opSequence;
+ try
+ {
+ ASN1Sequence valueSequence =
+ ASN1Sequence.decodeAsSequence(requestValue.value());
+ List<ASN1Element> elements = valueSequence.elements();
+ dnString = elements.get(0).decodeAsOctetString();
+
+ if (elements.size() == 2)
+ {
+ opSequence = elements.get(1).decodeAsSequence();
+ }
+ else
+ {
+ opSequence = null;
+ }
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ String message = getMessage(MSGID_PWPSTATE_EXTOP_DECODE_FAILURE,
+ getExceptionMessage(e));
+ operation.appendErrorMessage(message);
+ operation.setResultCode(ResultCode.PROTOCOL_ERROR);
+ return;
+ }
+
+
+ // Decode the DN and get the corresponding user entry.
+ DN targetDN;
+ try
+ {
+ targetDN = DN.decode(dnString);
+ }
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+
+ operation.setResponseData(de);
+ return;
+ }
+
+ DN rootDN = DirectoryServer.getActualRootBindDN(targetDN);
+ if (rootDN != null)
+ {
+ targetDN = rootDN;
+ }
+
+ Entry userEntry;
+ InternalClientConnection conn =
+ new InternalClientConnection(clientConnection.getAuthenticationInfo());
+ InternalSearchOperation internalSearch =
+ conn.processSearch(targetDN, SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 1, 0,
+ false, userFilter, requestAttributes, null);
+ if (internalSearch.getResultCode() != ResultCode.SUCCESS)
+ {
+ operation.setResultCode(internalSearch.getResultCode());
+ operation.setErrorMessage(internalSearch.getErrorMessage());
+ operation.setMatchedDN(internalSearch.getMatchedDN());
+ operation.setReferralURLs(internalSearch.getReferralURLs());
+ return;
+ }
+
+ List<SearchResultEntry> matchingEntries = internalSearch.getSearchEntries();
+ if (matchingEntries.isEmpty())
+ {
+ operation.setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
+ return;
+ }
+ else if (matchingEntries.size() > 1)
+ {
+ String message = getMessage(MSGID_PWPSTATE_EXTOP_MULTIPLE_ENTRIES);
+ operation.appendErrorMessage(message);
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ else
+ {
+ userEntry = matchingEntries.get(0);
+ }
+
+
+ // Get the password policy state for the user entry.
+ PasswordPolicyState pwpState;
+ PasswordPolicy policy;
+ try
+ {
+ pwpState = new PasswordPolicyState(userEntry, false, false);
+ policy = pwpState.getPolicy();
+ }
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+
+ operation.setResponseData(de);
+ return;
+ }
+
+
+ // Create a hash set that will be used to hold the types of the return
+ // types that should be included in the response.
+ boolean returnAll;
+ LinkedHashSet<Integer> returnTypes = new LinkedHashSet<Integer>();
+ if ((opSequence == null) || opSequence.elements().isEmpty())
+ {
+ returnAll = true;
+ }
+ else
+ {
+ returnAll = false;
+ for (ASN1Element element : opSequence.elements())
+ {
+ int opType;
+ ArrayList<String> opValues;
+ try
+ {
+ List<ASN1Element> opElements = element.decodeAsSequence().elements();
+ opType = opElements.get(0).decodeAsEnumerated().intValue();
+
+ if (opElements.size() == 1)
+ {
+ opValues = null;
+ }
+ else
+ {
+ List<ASN1Element> valueElements =
+ opElements.get(1).decodeAsSequence().elements();
+ if (valueElements.isEmpty())
+ {
+ opValues = null;
+ }
+ else
+ {
+ opValues = new ArrayList<String>(valueElements.size());
+ for (ASN1Element e : valueElements)
+ {
+ opValues.add(e.decodeAsOctetString().stringValue());
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ String message = getMessage(MSGID_PWPSTATE_EXTOP_INVALID_OP_ENCODING);
+ operation.appendErrorMessage(message);
+ operation.setResultCode(ResultCode.PROTOCOL_ERROR);
+ return;
+ }
+
+ switch (opType)
+ {
+ case OP_GET_PASSWORD_POLICY_DN:
+ returnTypes.add(OP_GET_PASSWORD_POLICY_DN);
+ break;
+
+ case OP_GET_ACCOUNT_DISABLED_STATE:
+ returnTypes.add(OP_GET_ACCOUNT_DISABLED_STATE);
+ break;
+
+ case OP_SET_ACCOUNT_DISABLED_STATE:
+ if (opValues == null)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_NO_DISABLED_VALUE;
+ operation.appendErrorMessage(getMessage(msgID));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ else if (opValues.size() != 1)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_DISABLED_VALUE_COUNT;
+ operation.appendErrorMessage(getMessage(msgID));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ else
+ {
+ String value = opValues.get(0);
+ if (value.equalsIgnoreCase("true"))
+ {
+ pwpState.setDisabled(true);
+ }
+ else if (value.equalsIgnoreCase("false"))
+ {
+ pwpState.setDisabled(false);
+ }
+ else
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_DISABLED_VALUE;
+ operation.appendErrorMessage(getMessage(msgID));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ }
+
+ returnTypes.add(OP_GET_ACCOUNT_DISABLED_STATE);
+ break;
+
+ case OP_CLEAR_ACCOUNT_DISABLED_STATE:
+ pwpState.setDisabled(false);
+ returnTypes.add(OP_GET_ACCOUNT_DISABLED_STATE);
+ break;
+
+ case OP_GET_ACCOUNT_EXPIRATION_TIME:
+ returnTypes.add(OP_GET_ACCOUNT_EXPIRATION_TIME);
+ break;
+
+ case OP_SET_ACCOUNT_EXPIRATION_TIME:
+ if (opValues == null)
+ {
+ pwpState.setAccountExpirationTime(pwpState.getCurrentTime());
+ }
+ else if (opValues.size() != 1)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_ACCT_EXP_VALUE_COUNT;
+ operation.appendErrorMessage(getMessage(msgID));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ else
+ {
+ try
+ {
+ ASN1OctetString valueString =
+ new ASN1OctetString(opValues.get(0));
+ long time = GeneralizedTimeSyntax.decodeGeneralizedTimeValue(
+ valueString);
+ pwpState.setAccountExpirationTime(time);
+ }
+ catch (DirectoryException de)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_ACCT_EXP_VALUE;
+ operation.appendErrorMessage(getMessage(msgID, opValues.get(0),
+ de.getErrorMessage()));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ }
+
+ returnTypes.add(OP_GET_ACCOUNT_EXPIRATION_TIME);
+ break;
+
+ case OP_CLEAR_ACCOUNT_EXPIRATION_TIME:
+ pwpState.clearAccountExpirationTime();
+ returnTypes.add(OP_GET_ACCOUNT_EXPIRATION_TIME);
+ break;
+
+ case OP_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION:
+ returnTypes.add(OP_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION);
+ break;
+
+ case OP_GET_PASSWORD_CHANGED_TIME:
+ returnTypes.add(OP_GET_PASSWORD_CHANGED_TIME);
+ break;
+
+ case OP_SET_PASSWORD_CHANGED_TIME:
+ if (opValues == null)
+ {
+ pwpState.setPasswordChangedTime();
+ }
+ else if (opValues.size() != 1)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_PWCHANGETIME_VALUE_COUNT;
+ operation.appendErrorMessage(getMessage(msgID));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ else
+ {
+ try
+ {
+ ASN1OctetString valueString =
+ new ASN1OctetString(opValues.get(0));
+ long time = GeneralizedTimeSyntax.decodeGeneralizedTimeValue(
+ valueString);
+ pwpState.setPasswordChangedTime(time);
+ }
+ catch (DirectoryException de)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_PWCHANGETIME_VALUE;
+ operation.appendErrorMessage(getMessage(msgID, opValues.get(0),
+ de.getErrorMessage()));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ }
+
+ returnTypes.add(OP_GET_PASSWORD_CHANGED_TIME);
+ break;
+
+ case OP_CLEAR_PASSWORD_CHANGED_TIME:
+ pwpState.clearPasswordChangedTime();
+ returnTypes.add(OP_GET_PASSWORD_CHANGED_TIME);
+ break;
+
+ case OP_GET_PASSWORD_EXPIRATION_WARNED_TIME:
+ returnTypes.add(OP_GET_PASSWORD_EXPIRATION_WARNED_TIME);
+ break;
+
+ case OP_SET_PASSWORD_EXPIRATION_WARNED_TIME:
+ if (opValues == null)
+ {
+ pwpState.setWarnedTime();
+ }
+ else if (opValues.size() != 1)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_PWWARNEDTIME_VALUE_COUNT;
+ operation.appendErrorMessage(getMessage(msgID));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ else
+ {
+ try
+ {
+ ASN1OctetString valueString =
+ new ASN1OctetString(opValues.get(0));
+ long time = GeneralizedTimeSyntax.decodeGeneralizedTimeValue(
+ valueString);
+ pwpState.setWarnedTime(time);
+ }
+ catch (DirectoryException de)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_PWWARNEDTIME_VALUE;
+ operation.appendErrorMessage(getMessage(msgID,
+ opValues.get(0),
+ de.getErrorMessage()));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ }
+
+ returnTypes.add(OP_GET_PASSWORD_EXPIRATION_WARNED_TIME);
+ break;
+
+ case OP_CLEAR_PASSWORD_EXPIRATION_WARNED_TIME:
+ pwpState.clearWarnedTime();
+ returnTypes.add(OP_GET_PASSWORD_EXPIRATION_WARNED_TIME);
+ break;
+
+ case OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION:
+ returnTypes.add(OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION);
+ break;
+
+ case OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING:
+ returnTypes.add(OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING);
+ break;
+
+ case OP_GET_AUTHENTICATION_FAILURE_TIMES:
+ returnTypes.add(OP_GET_AUTHENTICATION_FAILURE_TIMES);
+ break;
+
+ case OP_ADD_AUTHENTICATION_FAILURE_TIME:
+ if (opValues == null)
+ {
+ if (policy.getLockoutFailureCount() == 0)
+ {
+ returnTypes.add(OP_GET_AUTHENTICATION_FAILURE_TIMES);
+ break;
+ }
+
+ pwpState.updateAuthFailureTimes();
+ }
+ else if (opValues.size() != 1)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_ADD_FAILURE_TIME_COUNT;
+ operation.appendErrorMessage(getMessage(msgID));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ else
+ {
+ try
+ {
+ ASN1OctetString valueString =
+ new ASN1OctetString(opValues.get(0));
+ long time = GeneralizedTimeSyntax.decodeGeneralizedTimeValue(
+ valueString);
+ List<Long> authFailureTimes = pwpState.getAuthFailureTimes();
+ ArrayList<Long> newFailureTimes =
+ new ArrayList<Long>(authFailureTimes.size()+1);
+ newFailureTimes.addAll(authFailureTimes);
+ newFailureTimes.add(time);
+ pwpState.setAuthFailureTimes(newFailureTimes);
+ }
+ catch (DirectoryException de)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_AUTH_FAILURE_TIME;
+ String message = getMessage(msgID, opValues.get(0),
+ de.getErrorMessage());
+ operation.setResultCode(de.getResultCode());
+ operation.appendErrorMessage(message);
+ return;
+ }
+ }
+
+ returnTypes.add(OP_GET_AUTHENTICATION_FAILURE_TIMES);
+ break;
+
+ case OP_SET_AUTHENTICATION_FAILURE_TIMES:
+ if (opValues == null)
+ {
+ ArrayList<Long> valueList = new ArrayList<Long>(1);
+ valueList.add(pwpState.getCurrentTime());
+ pwpState.setAuthFailureTimes(valueList);
+ }
+ else
+ {
+ ArrayList<Long> valueList = new ArrayList<Long>(opValues.size());
+ for (String s : opValues)
+ {
+ try
+ {
+ valueList.add(
+ GeneralizedTimeSyntax.decodeGeneralizedTimeValue(
+ new ASN1OctetString(s)));
+ }
+ catch (DirectoryException de)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_AUTH_FAILURE_TIME;
+ String message = getMessage(msgID, s, de.getErrorMessage());
+ operation.setResultCode(de.getResultCode());
+ operation.appendErrorMessage(message);
+ return;
+ }
+ }
+ pwpState.setAuthFailureTimes(valueList);
+ }
+
+ returnTypes.add(OP_GET_AUTHENTICATION_FAILURE_TIMES);
+ break;
+
+ case OP_CLEAR_AUTHENTICATION_FAILURE_TIMES:
+ pwpState.clearFailureLockout();
+ returnTypes.add(OP_GET_AUTHENTICATION_FAILURE_TIMES);
+ break;
+
+ case OP_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK:
+ returnTypes.add(OP_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK);
+ break;
+
+ case OP_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT:
+ returnTypes.add(OP_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT);
+ break;
+
+ case OP_GET_LAST_LOGIN_TIME:
+ returnTypes.add(OP_GET_LAST_LOGIN_TIME);
+ break;
+
+ case OP_SET_LAST_LOGIN_TIME:
+ if (opValues == null)
+ {
+ pwpState.setLastLoginTime();
+ }
+ else if (opValues.size() != 1)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_LAST_LOGIN_TIME_COUNT;
+ operation.appendErrorMessage(getMessage(msgID));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ else
+ {
+ try
+ {
+ ASN1OctetString valueString =
+ new ASN1OctetString(opValues.get(0));
+ long time = GeneralizedTimeSyntax.decodeGeneralizedTimeValue(
+ valueString);
+ pwpState.setLastLoginTime(time);
+ }
+ catch (DirectoryException de)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_LAST_LOGIN_TIME;
+ operation.appendErrorMessage(getMessage(msgID, opValues.get(0),
+ de.getErrorMessage()));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ }
+
+ returnTypes.add(OP_GET_LAST_LOGIN_TIME);
+ break;
+
+ case OP_CLEAR_LAST_LOGIN_TIME:
+ pwpState.clearLastLoginTime();
+ returnTypes.add(OP_GET_LAST_LOGIN_TIME);
+ break;
+
+ case OP_GET_SECONDS_UNTIL_IDLE_LOCKOUT:
+ returnTypes.add(OP_GET_SECONDS_UNTIL_IDLE_LOCKOUT);
+ break;
+
+ case OP_GET_PASSWORD_RESET_STATE:
+ returnTypes.add(OP_GET_PASSWORD_RESET_STATE);
+ break;
+
+ case OP_SET_PASSWORD_RESET_STATE:
+ if (opValues == null)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_NO_RESET_STATE_VALUE;
+ operation.appendErrorMessage(getMessage(msgID));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ else if (opValues.size() != 1)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_RESET_STATE_VALUE_COUNT;
+ operation.appendErrorMessage(getMessage(msgID));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ else
+ {
+ String value = opValues.get(0);
+ if (value.equalsIgnoreCase("true"))
+ {
+ pwpState.setMustChangePassword(true);
+ }
+ else if (value.equalsIgnoreCase("false"))
+ {
+ pwpState.setMustChangePassword(false);
+ }
+ else
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_RESET_STATE_VALUE;
+ operation.appendErrorMessage(getMessage(msgID));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ }
+
+ returnTypes.add(OP_GET_PASSWORD_RESET_STATE);
+ break;
+
+ case OP_CLEAR_PASSWORD_RESET_STATE:
+ pwpState.setMustChangePassword(false);
+ returnTypes.add(OP_GET_PASSWORD_RESET_STATE);
+ break;
+
+ case OP_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT:
+ returnTypes.add(OP_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT);
+ break;
+
+ case OP_GET_GRACE_LOGIN_USE_TIMES:
+ returnTypes.add(OP_GET_GRACE_LOGIN_USE_TIMES);
+ break;
+
+ case OP_ADD_GRACE_LOGIN_USE_TIME:
+ if (opValues == null)
+ {
+ pwpState.updateGraceLoginTimes();
+ }
+ else if (opValues.size() != 1)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_ADD_GRACE_LOGIN_TIME_COUNT;
+ operation.appendErrorMessage(getMessage(msgID));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ else
+ {
+ try
+ {
+ ASN1OctetString valueString =
+ new ASN1OctetString(opValues.get(0));
+ long time = GeneralizedTimeSyntax.decodeGeneralizedTimeValue(
+ valueString);
+ List<Long> authFailureTimes = pwpState.getGraceLoginTimes();
+ ArrayList<Long> newGraceTimes =
+ new ArrayList<Long>(authFailureTimes.size()+1);
+ newGraceTimes.addAll(authFailureTimes);
+ newGraceTimes.add(time);
+ pwpState.setGraceLoginTimes(newGraceTimes);
+ }
+ catch (DirectoryException de)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_GRACE_LOGIN_TIME;
+ String message = getMessage(msgID, opValues.get(0),
+ de.getErrorMessage());
+ operation.setResultCode(de.getResultCode());
+ operation.appendErrorMessage(message);
+ return;
+ }
+ }
+
+ returnTypes.add(OP_GET_GRACE_LOGIN_USE_TIMES);
+ break;
+
+ case OP_SET_GRACE_LOGIN_USE_TIMES:
+ if (opValues == null)
+ {
+ ArrayList<Long> valueList = new ArrayList<Long>(1);
+ valueList.add(pwpState.getCurrentTime());
+ pwpState.setGraceLoginTimes(valueList);
+ }
+ else
+ {
+ ArrayList<Long> valueList = new ArrayList<Long>(opValues.size());
+ for (String s : opValues)
+ {
+ try
+ {
+ valueList.add(
+ GeneralizedTimeSyntax.decodeGeneralizedTimeValue(
+ new ASN1OctetString(s)));
+ }
+ catch (DirectoryException de)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_GRACE_LOGIN_TIME;
+ String message = getMessage(msgID, s, de.getErrorMessage());
+ operation.setResultCode(de.getResultCode());
+ operation.appendErrorMessage(message);
+ return;
+ }
+ }
+ pwpState.setGraceLoginTimes(valueList);
+ }
+
+ returnTypes.add(OP_GET_GRACE_LOGIN_USE_TIMES);
+ break;
+
+ case OP_CLEAR_GRACE_LOGIN_USE_TIMES:
+ pwpState.clearGraceLoginTimes();
+ returnTypes.add(OP_GET_GRACE_LOGIN_USE_TIMES);
+ break;
+
+ case OP_GET_REMAINING_GRACE_LOGIN_COUNT:
+ returnTypes.add(OP_GET_REMAINING_GRACE_LOGIN_COUNT);
+ break;
+
+ case OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME:
+ returnTypes.add(OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME);
+ break;
+
+ case OP_SET_PASSWORD_CHANGED_BY_REQUIRED_TIME:
+ if (opValues == null)
+ {
+ pwpState.setRequiredChangeTime();
+ }
+ else if (opValues.size() != 1)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_REQUIRED_CHANGE_TIME_COUNT;
+ operation.appendErrorMessage(getMessage(msgID));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ else
+ {
+ try
+ {
+ ASN1OctetString valueString =
+ new ASN1OctetString(opValues.get(0));
+ long time = GeneralizedTimeSyntax.decodeGeneralizedTimeValue(
+ valueString);
+ pwpState.setRequiredChangeTime(time);
+ }
+ catch (DirectoryException de)
+ {
+ int msgID = MSGID_PWPSTATE_EXTOP_BAD_REQUIRED_CHANGE_TIME;
+ operation.appendErrorMessage(getMessage(msgID, opValues.get(0),
+ de.getErrorMessage()));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ }
+
+ returnTypes.add(OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME);
+ break;
+
+ case OP_CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME:
+ pwpState.clearRequiredChangeTime();
+ returnTypes.add(OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME);
+ break;
+
+ case OP_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME:
+ returnTypes.add(OP_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME);
+ break;
+
+ default:
+ int msgID = MSGID_PWPSTATE_EXTOP_UNKNOWN_OP_TYPE;
+ operation.appendErrorMessage(getMessage(msgID, opType));
+ operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
+ return;
+ }
+ }
+
+
+ // If there are any modifications that need to be made to the password
+ // policy state, then apply them now.
+ List<Modification> stateMods = pwpState.getModifications();
+ if ((stateMods != null) && (! stateMods.isEmpty()))
+ {
+ ModifyOperation modifyOperation =
+ conn.processModify(targetDN, stateMods);
+ if (modifyOperation.getResultCode() != ResultCode.SUCCESS)
+ {
+ operation.setResultCode(modifyOperation.getResultCode());
+ operation.setErrorMessage(modifyOperation.getErrorMessage());
+ operation.setMatchedDN(modifyOperation.getMatchedDN());
+ operation.setReferralURLs(modifyOperation.getReferralURLs());
+ return;
+ }
+ }
+ }
+
+
+ // Construct the sequence of values to return.
+ ArrayList<ASN1Element> opElements = new ArrayList<ASN1Element>();
+ if (returnAll || returnTypes.contains(OP_GET_PASSWORD_POLICY_DN))
+ {
+ opElements.add(encode(OP_GET_PASSWORD_POLICY_DN,
+ policy.getConfigEntryDN().toString()));
+ }
+
+ if (returnAll || returnTypes.contains(OP_GET_ACCOUNT_DISABLED_STATE))
+ {
+ opElements.add(encode(OP_GET_ACCOUNT_DISABLED_STATE,
+ String.valueOf(pwpState.isDisabled())));
+ }
+
+ if (returnAll || returnTypes.contains(OP_GET_ACCOUNT_EXPIRATION_TIME))
+ {
+ String expTimeStr;
+ long expTime = pwpState.getAccountExpirationTime();
+ if (expTime < 0)
+ {
+ expTimeStr = null;
+ }
+ else
+ {
+ expTimeStr = GeneralizedTimeSyntax.format(expTime);
+ }
+
+ opElements.add(encode(OP_GET_ACCOUNT_EXPIRATION_TIME, expTimeStr));
+ }
+
+ if (returnAll ||
+ returnTypes.contains(OP_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION))
+ {
+ String secondsStr;
+ long expTime = pwpState.getAccountExpirationTime();
+ if (expTime < 0)
+ {
+ secondsStr = null;
+ }
+ else
+ {
+ secondsStr =
+ String.valueOf((expTime - pwpState.getCurrentTime()) / 1000);
+ }
+
+ opElements.add(encode(OP_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION,
+ secondsStr));
+ }
+
+ if (returnAll || returnTypes.contains(OP_GET_PASSWORD_CHANGED_TIME))
+ {
+ String timeStr;
+ long changedTime = pwpState.getPasswordChangedTime();
+ if (changedTime < 0)
+ {
+ timeStr = null;
+ }
+ else
+ {
+ timeStr = GeneralizedTimeSyntax.format(changedTime);
+ }
+
+ opElements.add(encode(OP_GET_PASSWORD_CHANGED_TIME, timeStr));
+ }
+
+ if (returnAll ||
+ returnTypes.contains(OP_GET_PASSWORD_EXPIRATION_WARNED_TIME))
+ {
+ String timeStr;
+ long warnedTime = pwpState.getWarnedTime();
+ if (warnedTime < 0)
+ {
+ timeStr = null;
+ }
+ else
+ {
+ timeStr = GeneralizedTimeSyntax.format(warnedTime);
+ }
+
+ opElements.add(encode(OP_GET_PASSWORD_EXPIRATION_WARNED_TIME, timeStr));
+ }
+
+ if (returnAll ||
+ returnTypes.contains(OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION))
+ {
+ String secondsStr;
+ int secondsUntilExp = pwpState.getSecondsUntilExpiration();
+ if (secondsUntilExp < 0)
+ {
+ secondsStr = null;
+ }
+ else
+ {
+ secondsStr = String.valueOf(secondsUntilExp);
+ }
+
+ opElements.add(encode(OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION,
+ secondsStr));
+ }
+
+ if (returnAll ||
+ returnTypes.contains(OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING))
+ {
+ String secondsStr;
+ int secondsUntilExp = pwpState.getSecondsUntilExpiration();
+ if (secondsUntilExp < 0)
+ {
+ secondsStr = null;
+ }
+ else
+ {
+ int secondsUntilWarning = secondsUntilExp - policy.getWarningInterval();
+ if (secondsUntilWarning <= 0)
+ {
+ secondsStr = "0";
+ }
+ else
+ {
+ secondsStr = String.valueOf(secondsUntilWarning);
+ }
+ }
+
+ opElements.add(encode(OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING,
+ secondsStr));
+ }
+
+ if (returnAll || returnTypes.contains(OP_GET_AUTHENTICATION_FAILURE_TIMES))
+ {
+ opElements.add(encode(OP_GET_AUTHENTICATION_FAILURE_TIMES,
+ pwpState.getAuthFailureTimes()));
+ }
+
+ if (returnAll || returnTypes.contains(
+ OP_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK))
+ {
+ // We have to check whether the account is locked due to failures before
+ // we can get the length of time until the account is unlocked.
+ String secondsStr;
+ if (pwpState.lockedDueToFailures())
+ {
+ int seconds = pwpState.getSecondsUntilUnlock();
+ if (seconds <= 0)
+ {
+ secondsStr = null;
+ }
+ else
+ {
+ secondsStr = String.valueOf(seconds);
+ }
+ }
+ else
+ {
+ secondsStr = null;
+ }
+
+ opElements.add(encode(OP_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK,
+ secondsStr));
+ }
+
+ if (returnAll ||
+ returnTypes.contains(OP_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT))
+ {
+ String remainingFailuresStr;
+ int allowedFailureCount = policy.getLockoutFailureCount();
+ if (allowedFailureCount > 0)
+ {
+ int remainingFailures =
+ allowedFailureCount - pwpState.getAuthFailureTimes().size();
+ if (remainingFailures < 0)
+ {
+ remainingFailures = 0;
+ }
+
+ remainingFailuresStr = String.valueOf(remainingFailures);
+ }
+ else
+ {
+ remainingFailuresStr = null;
+ }
+
+ opElements.add(encode(OP_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT,
+ remainingFailuresStr));
+ }
+
+ if (returnAll || returnTypes.contains(OP_GET_LAST_LOGIN_TIME))
+ {
+ String timeStr;
+ long lastLoginTime = pwpState.getLastLoginTime();
+ if (lastLoginTime < 0)
+ {
+ timeStr = null;
+ }
+ else
+ {
+ timeStr = GeneralizedTimeSyntax.format(lastLoginTime);
+ }
+
+ opElements.add(encode(OP_GET_LAST_LOGIN_TIME, timeStr));
+ }
+
+ if (returnAll || returnTypes.contains(OP_GET_SECONDS_UNTIL_IDLE_LOCKOUT))
+ {
+ String secondsStr;
+ int lockoutInterval = policy.getIdleLockoutInterval();
+ if (lockoutInterval > 0)
+ {
+ long lastLoginTime = pwpState.getLastLoginTime();
+ if (lastLoginTime < 0)
+ {
+ secondsStr = "0";
+ }
+ else
+ {
+ long lockoutTime = lastLoginTime + (lockoutInterval*1000);
+ long currentTime = pwpState.getCurrentTime();
+ int secondsUntilLockout = (int) ((lockoutTime - currentTime) / 1000);
+ if (secondsUntilLockout <= 0)
+ {
+ secondsStr = "0";
+ }
+ else
+ {
+ secondsStr = String.valueOf(secondsUntilLockout);
+ }
+ }
+ }
+ else
+ {
+ secondsStr = null;
+ }
+
+ opElements.add(encode(OP_GET_SECONDS_UNTIL_IDLE_LOCKOUT, secondsStr));
+ }
+
+ if (returnAll || returnTypes.contains(OP_GET_PASSWORD_RESET_STATE))
+ {
+ opElements.add(encode(OP_GET_PASSWORD_RESET_STATE,
+ String.valueOf(pwpState.mustChangePassword())));
+ }
+
+ if (returnAll ||
+ returnTypes.contains(OP_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT))
+ {
+ String secondsStr;
+ if (pwpState.mustChangePassword())
+ {
+ int maxAge = policy.getMaximumPasswordResetAge();
+ if (maxAge > 0)
+ {
+ long currentTime = pwpState.getCurrentTime();
+ long changedTime = pwpState.getPasswordChangedTime();
+ int changeAge = (int) ((currentTime - changedTime) / 1000);
+ int timeToLockout = maxAge - changeAge;
+ if (timeToLockout <= 0)
+ {
+ secondsStr = "0";
+ }
+ else
+ {
+ secondsStr = String.valueOf(timeToLockout);
+ }
+ }
+ else
+ {
+ secondsStr = null;
+ }
+ }
+ else
+ {
+ secondsStr = null;
+ }
+
+ opElements.add(encode(OP_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT,
+ secondsStr));
+ }
+
+ if (returnAll || returnTypes.contains(OP_GET_GRACE_LOGIN_USE_TIMES))
+ {
+ opElements.add(encode(OP_GET_GRACE_LOGIN_USE_TIMES,
+ pwpState.getGraceLoginTimes()));
+ }
+
+ if (returnAll || returnTypes.contains(OP_GET_REMAINING_GRACE_LOGIN_COUNT))
+ {
+ String remainingStr;
+ int remainingGraceLogins = pwpState.getGraceLoginsRemaining();
+ if (remainingGraceLogins <= 0)
+ {
+ remainingStr = "0";
+ }
+ else
+ {
+ remainingStr = String.valueOf(remainingGraceLogins);
+ }
+
+ opElements.add(encode(OP_GET_REMAINING_GRACE_LOGIN_COUNT, remainingStr));
+ }
+
+ if (returnAll ||
+ returnTypes.contains(OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME))
+ {
+ String timeStr;
+ long requiredChangeTime = pwpState.getRequiredChangeTime();
+ if (requiredChangeTime < 0)
+ {
+ timeStr = null;
+ }
+ else
+ {
+ timeStr = GeneralizedTimeSyntax.format(requiredChangeTime);
+ }
+
+ opElements.add(encode(OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME, timeStr));
+ }
+
+ if (returnAll ||
+ returnTypes.contains(OP_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME))
+ {
+ String secondsStr;
+ long policyRequiredChangeTime = policy.getRequireChangeByTime();
+ if (policyRequiredChangeTime > 0)
+ {
+ long accountRequiredChangeTime = pwpState.getRequiredChangeTime();
+ if (accountRequiredChangeTime >= policyRequiredChangeTime)
+ {
+ secondsStr = null;
+ }
+ else
+ {
+ long currentTime = pwpState.getCurrentTime();
+ if (currentTime >= policyRequiredChangeTime)
+ {
+ secondsStr = "0";
+ }
+ else
+ {
+ secondsStr =
+ String.valueOf((policyRequiredChangeTime-currentTime) / 1000);
+
+ }
+ }
+ }
+ else
+ {
+ secondsStr = null;
+ }
+
+ opElements.add(encode(OP_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME,
+ secondsStr));
+ }
+
+ ArrayList<ASN1Element> responseValueElements =
+ new ArrayList<ASN1Element>(2);
+ responseValueElements.add(dnString);
+ responseValueElements.add(new ASN1Sequence(opElements));
+
+ ASN1OctetString responseValue =
+ new ASN1OctetString(new ASN1Sequence(responseValueElements).encode());
+
+ operation.setResponseOID(OID_PASSWORD_POLICY_STATE_EXTOP);
+ operation.setResponseValue(responseValue);
+ operation.setResultCode(ResultCode.SUCCESS);
+ }
+
+
+
+ /**
+ * Encodes the provided information in a form suitable for including in the
+ * response value.
+ *
+ * @param opType The operation type to use for the value.
+ * @param value The single value to include in the response.
+ *
+ * @return The encoded ASN.1 element.
+ */
+ public static ASN1Element encode(int opType, String value)
+ {
+ ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2);
+ elements.add(new ASN1Enumerated(opType));
+
+ if (value != null)
+ {
+ ArrayList<ASN1Element> valueElements = new ArrayList<ASN1Element>(1);
+ valueElements.add(new ASN1OctetString(value));
+ elements.add(new ASN1Sequence(valueElements));
+ }
+
+ return new ASN1Sequence(elements);
+ }
+
+
+
+ /**
+ * Encodes the provided information in a form suitable for including in the
+ * response value.
+ *
+ * @param opType The operation type to use for the value.
+ * @param values The set of string values to include in the response.
+ *
+ * @return The encoded ASN.1 element.
+ */
+ public static ASN1Element encode(int opType, String[] values)
+ {
+ ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2);
+ elements.add(new ASN1Enumerated(opType));
+
+ if ((values != null) && (values.length > 0))
+ {
+ ArrayList<ASN1Element> valueElements =
+ new ArrayList<ASN1Element>(values.length);
+ for (int i=0; i < values.length; i++)
+ {
+ valueElements.add(new ASN1OctetString(values[i]));
+ }
+ elements.add(new ASN1Sequence(valueElements));
+ }
+
+ return new ASN1Sequence(elements);
+ }
+
+
+
+ /**
+ * Encodes the provided information in a form suitable for including in the
+ * response value.
+ *
+ * @param opType The operation type to use for the value.
+ * @param values The set of timestamp values to include in the response.
+ *
+ * @return The encoded ASN.1 element.
+ */
+ public static ASN1Element encode(int opType, List<Long> values)
+ {
+ ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2);
+ elements.add(new ASN1Enumerated(opType));
+
+ ArrayList<ASN1Element> valueElements =
+ new ArrayList<ASN1Element>(values.size());
+ for (long l : values)
+ {
+ valueElements.add(new ASN1OctetString(GeneralizedTimeSyntax.format(l)));
+ }
+ elements.add(new ASN1Sequence(valueElements));
+
+ return new ASN1Sequence(elements);
+ }
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/messages/ExtensionsMessages.java b/opendj-sdk/opends/src/server/org/opends/server/messages/ExtensionsMessages.java
index 660702a..4ac4dab 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/messages/ExtensionsMessages.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/messages/ExtensionsMessages.java
@@ -5212,6 +5212,274 @@
/**
+ * The message ID for the message that will be used if a user requests the
+ * password policy state extended operation but does not have adequate
+ * privileges to do so. This does not take any arguments.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_NO_PRIVILEGE =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 502;
+
+
+
+ /**
+ * The message ID for the message that will be used if a user requests the
+ * password policy state extended operation but does not include a request
+ * value. This does not take any arguments.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_NO_REQUEST_VALUE =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 503;
+
+
+
+ /**
+ * The message ID for the message that will be used if an error occurs while
+ * attempting to decode the password policy state extended request value.
+ * This takes a single argument, which is a message explaining the problem
+ * that occurred.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_DECODE_FAILURE =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 504;
+
+
+
+ /**
+ * The message ID for the message that will be used if the server finds
+ * multiple entries for a given DN. This takes a single argument, which is a
+ * string representation of the provided DN.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_MULTIPLE_ENTRIES =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 505;
+
+
+
+ /**
+ * The message ID for the message that will be used if the password policy
+ * state request includes an operation with an invalid encoding. This takes a
+ * single argument, which is a message explaining the problem that occurred.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_INVALID_OP_ENCODING =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 506;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * set the disabled state for an account but does not provide a value. This
+ * does not take any arguments.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_NO_DISABLED_VALUE =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 507;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * set the disabled state for an account but provides multiple values. This
+ * does not take any arguments.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_DISABLED_VALUE_COUNT =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 508;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * set the disabled state for an account but provides an invalid value. This
+ * does not take any arguments.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_DISABLED_VALUE =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 509;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * set the account expiration time but provides multiple values. This does
+ * not take any arguments.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_ACCT_EXP_VALUE_COUNT =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 510;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * set the account expiration time but provides an invalid value. This takes
+ * two arguments, which are the provided value and a message explaining the
+ * problem that occurred.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_ACCT_EXP_VALUE =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 511;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * set the password changed time but provides multiple values. This does not
+ * take any arguments.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_PWCHANGETIME_VALUE_COUNT =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 512;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * set the password changed time but provides an invalid value. This takes
+ * two arguments, which are the provided value and a message explaining the
+ * problem that occurred.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_PWCHANGETIME_VALUE =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 513;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * set the password warned time but provides multiple values. This does not
+ * take any arguments.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_PWWARNEDTIME_VALUE_COUNT =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 514;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * set the password warned time but provides an invalid value. This takes
+ * two arguments, which are the provided value and a message explaining the
+ * problem that occurred.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_PWWARNEDTIME_VALUE =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 515;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * add a failure time but provides multiple values. This does not take any
+ * arguments.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_ADD_FAILURE_TIME_COUNT =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 516;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * alter the failure times but provides an invalid value. This takes two
+ * arguments, which are the provided value and a message explaining the
+ * that occurred.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_AUTH_FAILURE_TIME =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 517;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * set the last login time but provides multiple values. This does not take
+ * any arguments.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_LAST_LOGIN_TIME_COUNT =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 518;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * set the last login time but provides an invalid value. This takes two
+ * arguments, which are the provided value and a message explaining the
+ * problem that occurred.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_LAST_LOGIN_TIME =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 519;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * set the reset state for an account but does not provide a value. This
+ * does not take any arguments.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_NO_RESET_STATE_VALUE =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 520;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * set the reset state for an account but provides multiple values. This does
+ * does not take any arguments.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_RESET_STATE_VALUE_COUNT =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 521;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * set the reset state for an account but provides an invalid value. This
+ * does not take any arguments.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_RESET_STATE_VALUE =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 522;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * add a grace login time but provides multiple values. This does not take
+ * any arguments.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_ADD_GRACE_LOGIN_TIME_COUNT =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 523;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * alter the grace login times but provides an invalid value. This takes two
+ * arguments, which are the provided value and a message explaining the
+ * that occurred.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_GRACE_LOGIN_TIME =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 524;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * set the required change time but provides multiple values. This does not
+ * take any arguments.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_REQUIRED_CHANGE_TIME_COUNT =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 525;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user attempts to
+ * set the required change time but provides an invalid value. This takes two
+ * arguments, which are the provided value and a message explaining the
+ * problem that occurred.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_BAD_REQUIRED_CHANGE_TIME =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 526;
+
+
+
+ /**
+ * The message ID for the message that will be used if the password policy
+ * state request includes an operation with an unrecognized type. This takes
+ * a single argument, which is the provided operation type.
+ */
+ public static final int MSGID_PWPSTATE_EXTOP_UNKNOWN_OP_TYPE =
+ CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_SEVERE_ERROR | 527;
+
+
+
+ /**
* Associates a set of generic messages with the message IDs defined in this
* class.
*/
@@ -7492,6 +7760,121 @@
registerMessage(MSGID_ENTRYUUID_VATTR_NOT_SEARCHABLE,
"The %s attribute is not searchable and should not be " +
"included in otherwise unindexed search filters");
+
+
+ registerMessage(MSGID_PWPSTATE_EXTOP_NO_PRIVILEGE,
+ "You do not have sufficient privileges to use the " +
+ "password policy state extended operation");
+ registerMessage(MSGID_PWPSTATE_EXTOP_NO_REQUEST_VALUE,
+ "The provided password policy state extended request " +
+ "did not include a request value");
+ registerMessage(MSGID_PWPSTATE_EXTOP_DECODE_FAILURE,
+ "An unexpected error occurred while attempting to decode " +
+ "password policy state extended request value: %s");
+ registerMessage(MSGID_PWPSTATE_EXTOP_MULTIPLE_ENTRIES,
+ "SEVERE ERROR: Multiple entries were found with DN %s");
+ registerMessage(MSGID_PWPSTATE_EXTOP_INVALID_OP_ENCODING,
+ "An unexpected error occurred while attempting to decode " +
+ "an operation from the password policy state extended " +
+ "request: %s");
+ registerMessage(MSGID_PWPSTATE_EXTOP_NO_DISABLED_VALUE,
+ "No value was provided for the password policy state " +
+ "operation intended to set the disabled state for the " +
+ "user. Exactly one value (either 'true' or 'false') " +
+ "must be given");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_DISABLED_VALUE_COUNT,
+ "Multiple values were provided for the password policy " +
+ "state operation intended to set the disabled state " +
+ "for the user. Exactly one value (either 'true' or " +
+ "'false') must be given");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_DISABLED_VALUE,
+ "The value provided for the password policy state " +
+ "operation intended to set the disabled state for the " +
+ "user was invalid. The value must be either 'true' or " +
+ "'false'");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_ACCT_EXP_VALUE_COUNT,
+ "Multiple values were provided for the password policy " +
+ "state operation intended to set the account expiration " +
+ "time for the user. Exactly one value must be given");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_ACCT_EXP_VALUE,
+ "The value %s provided for the password policy state " +
+ "operation used to set the account expiration time was " +
+ "invalid: %s. The value should be specifed using the " +
+ "generalized time format");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_PWCHANGETIME_VALUE_COUNT,
+ "Multiple values were provided for the password policy " +
+ "state operation intended to set the password changed " +
+ "time for the user. Exactly one value must be given");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_PWCHANGETIME_VALUE,
+ "The value %s provided for the password policy state " +
+ "operation used to set the password changed time was " +
+ "invalid: %s. The value should be specifed using the " +
+ "generalized time format");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_PWWARNEDTIME_VALUE_COUNT,
+ "Multiple values were provided for the password policy " +
+ "state operation intended to set the password warned " +
+ "time for the user. Exactly one value must be given");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_PWWARNEDTIME_VALUE,
+ "The value %s provided for the password policy state " +
+ "operation used to set the password warned time was " +
+ "invalid: %s. The value should be specifed using the " +
+ "generalized time format");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_ADD_FAILURE_TIME_COUNT,
+ "Multiple values were provided for the password policy " +
+ "state operation intended to add an authentication " +
+ "failure time for the user. Exactly one value must be " +
+ "given");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_AUTH_FAILURE_TIME,
+ "The value %s provided for the password policy state " +
+ "operation used to update the authentication failure " +
+ "times was invalid: %s. The value should be specifed " +
+ "using the generalized time format");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_LAST_LOGIN_TIME_COUNT,
+ "Multiple values were provided for the password policy " +
+ "state operation intended to set the last login time for " +
+ "the user. Exactly one value must be given");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_LAST_LOGIN_TIME,
+ "The value %s provided for the password policy state " +
+ "operation used to set the last login time was invalid: " +
+ "%s. The value should be specifed using the " +
+ "generalized time format");
+ registerMessage(MSGID_PWPSTATE_EXTOP_NO_RESET_STATE_VALUE,
+ "No value was provided for the password policy state " +
+ "operation intended to set the reset state for the " +
+ "user. Exactly one value (either 'true' or 'false') " +
+ "must be given");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_RESET_STATE_VALUE_COUNT,
+ "Multiple values were provided for the password policy " +
+ "state operation intended to set the reset state " +
+ "for the user. Exactly one value (either 'true' or " +
+ "'false') must be given");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_RESET_STATE_VALUE,
+ "The value provided for the password policy state " +
+ "operation intended to set the reset state for the " +
+ "user was invalid. The value must be either 'true' or " +
+ "'false'");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_ADD_GRACE_LOGIN_TIME_COUNT,
+ "Multiple values were provided for the password policy " +
+ "state operation intended to add a grace login use time " +
+ "for the user. Exactly one value must be given");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_GRACE_LOGIN_TIME,
+ "The value %s provided for the password policy state " +
+ "operation used to update the grace login use times was " +
+ "invalid: %s. The value should be specifed using the " +
+ "generalized time format");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_REQUIRED_CHANGE_TIME_COUNT,
+ "Multiple values were provided for the password policy " +
+ "state operation intended to set the required change " +
+ "time for the user. Exactly one value must be given");
+ registerMessage(MSGID_PWPSTATE_EXTOP_BAD_REQUIRED_CHANGE_TIME,
+ "The value %s provided for the password policy state " +
+ "operation used to set the required change time was " +
+ "invalid: %s. The value should be specifed using the " +
+ "generalized time format");
+ registerMessage(MSGID_PWPSTATE_EXTOP_UNKNOWN_OP_TYPE,
+ "The password policy state extended request included an " +
+ "operation with an invalid or unsupported operation type " +
+ "of %s");
}
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java b/opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java
index 24e71bd..9055d7e 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java
@@ -8028,6 +8028,918 @@
/**
+ * The message ID for the message that will be used as the description for the
+ * password policy state tool.
+ */
+ public static final int MSGID_PWPSTATE_TOOL_DESCRIPTION =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1094;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * hostname argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_HOST =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1095;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * port argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_PORT =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1096;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * useSSL argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_USESSL =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1097;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * useStartTLS argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_USESTARTTLS =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1098;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * bindDN argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_BINDDN =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1099;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * bindPassword argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_BINDPW =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1100;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * bindPasswordFile argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_BINDPWFILE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1101;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * targetDN argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_TARGETDN =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1102;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * saslOptions argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_SASLOPTIONS =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1103;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * trustAll argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_TRUST_ALL =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1104;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * keyStorePath argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_KSFILE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1105;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * keyStorePIN argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_KSPW =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1106;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * keyStorePINFile argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_KSPWFILE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1107;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * trustStorePath argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_TSFILE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1108;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * trustStorePIN argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_TSPW =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1109;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * trustStorePINFile argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_TSPWFILE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1110;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * showUsage argument.
+ */
+ public static final int MSGID_PWPSTATE_DESCRIPTION_SHOWUSAGE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1111;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-all subcommand.
+ */
+ public static final int MSGID_DESCRIPTION_PWPSTATE_GET_ALL =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1112;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-password-policy-dn subcommand.
+ */
+ public static final int MSGID_DESCRIPTION_PWPSTATE_GET_PASSWORD_POLICY_DN =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1113;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-account-is-disabled subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_GET_ACCOUNT_DISABLED_STATE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1114;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * set-account-is-disabled subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_SET_ACCOUNT_DISABLED_STATE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1115;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * argument used to set Boolean values.
+ */
+ public static final int MSGID_DESCRIPTION_OPERATION_BOOLEAN_VALUE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1116;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * clear-account-is-disabled subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_CLEAR_ACCOUNT_DISABLED_STATE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1117;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-account-expiration-time subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_GET_ACCOUNT_EXPIRATION_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1118;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * set-account-expiration-time subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_SET_ACCOUNT_EXPIRATION_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1119;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * argument used to set single values for single-valued attributes.
+ */
+ public static final int MSGID_DESCRIPTION_OPERATION_TIME_VALUE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1120;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * clear-account-expiration-time subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_CLEAR_ACCOUNT_EXPIRATION_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1121;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-seconds-until-account-expiration subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1122;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-password-changed-time subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_GET_PASSWORD_CHANGED_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1123;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * set-password-changed-time subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_SET_PASSWORD_CHANGED_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1124;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * clear-password-changed-time subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_CLEAR_PASSWORD_CHANGED_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1125;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-password-expiration-warned-time subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_GET_PASSWORD_EXPIRATION_WARNED_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1126;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * set-password-expiration-warned-time subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_SET_PASSWORD_EXPIRATION_WARNED_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1127;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * clear-password-expiration-warned-time subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_CLEAR_PASSWORD_EXPIRATION_WARNED_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1128;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-seconds-until-password-expiration subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_PASSWORD_EXP =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1129;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-seconds-until-password-expiration-warning subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_PASSWORD_EXP_WARNING =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1130;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-auth-failure-times subcommand.
+ */
+ public static final int MSGID_DESCRIPTION_PWPSTATE_GET_AUTH_FAILURE_TIMES =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1131;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * add-auth-failure-time subcommand.
+ */
+ public static final int MSGID_DESCRIPTION_PWPSTATE_ADD_AUTH_FAILURE_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1132;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * set-auth-failure-times subcommand.
+ */
+ public static final int MSGID_DESCRIPTION_PWPSTATE_SET_AUTH_FAILURE_TIMES =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1133;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * argument used to set single values for multi-valued attributes.
+ */
+ public static final int MSGID_DESCRIPTION_OPERATION_TIME_VALUES =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1134;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * clear-auth-failure-times subcommand.
+ */
+ public static final int MSGID_DESCRIPTION_PWPSTATE_CLEAR_AUTH_FAILURE_TIMES =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1135;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-seconds-until-authentication-failure-unlock subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_AUTH_FAILURE_UNLOCK =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1136;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-remaining-authentication-failure-count subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_GET_REMAINING_AUTH_FAILURE_COUNT =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1137;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-last-login-time subcommand.
+ */
+ public static final int MSGID_DESCRIPTION_PWPSTATE_GET_LAST_LOGIN_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1138;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * set-last-login-time subcommand.
+ */
+ public static final int MSGID_DESCRIPTION_PWPSTATE_SET_LAST_LOGIN_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1139;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * clear-last-login-time subcommand.
+ */
+ public static final int MSGID_DESCRIPTION_PWPSTATE_CLEAR_LAST_LOGIN_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1140;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-seconds-until-idle-lockout subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_IDLE_LOCKOUT =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1141;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-password-is-reset subcommand.
+ */
+ public static final int MSGID_DESCRIPTION_PWPSTATE_GET_PASSWORD_RESET_STATE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1142;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * set-password-is-reset subcommand.
+ */
+ public static final int MSGID_DESCRIPTION_PWPSTATE_SET_PASSWORD_RESET_STATE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1143;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * clear-password-is-reset subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_CLEAR_PASSWORD_RESET_STATE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1144;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-seconds-until-reset-lockout subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_RESET_LOCKOUT =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1145;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-grace-login-use-times subcommand.
+ */
+ public static final int MSGID_DESCRIPTION_PWPSTATE_GET_GRACE_LOGIN_USE_TIMES =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1146;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * add-grace-login-use-time subcommand.
+ */
+ public static final int MSGID_DESCRIPTION_PWPSTATE_ADD_GRACE_LOGIN_USE_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1147;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * set-grace-login-use-times subcommand.
+ */
+ public static final int MSGID_DESCRIPTION_PWPSTATE_SET_GRACE_LOGIN_USE_TIMES =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1148;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * clear-grace-login-use-times subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_CLEAR_GRACE_LOGIN_USE_TIMES =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1149;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-remaining-grace-login-count subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_GET_REMAINING_GRACE_LOGIN_COUNT =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1150;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-password-changed-by-required-time subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_GET_PW_CHANGED_BY_REQUIRED_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1151;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * set-password-changed-by-required-time subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_SET_PW_CHANGED_BY_REQUIRED_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1152;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * clear-password-changed-by-required-time subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_CLEAR_PW_CHANGED_BY_REQUIRED_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1153;
+
+
+
+ /**
+ * The message ID for the message that will be used as the description for the
+ * get-seconds-until-required-time subcommand.
+ */
+ public static final int
+ MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1154;
+
+
+
+ /**
+ * The message ID for the message that will be used if no subcommand was
+ * provided on the command line. This does not take any arguments.
+ */
+ public static final int MSGID_PWPSTATE_NO_SUBCOMMAND =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1155;
+
+
+
+ /**
+ * The message ID for the message that will be used if the operation value
+ * provided could not be parsed as a Boolean value. This takes a single
+ * argument, which is the provided value.
+ */
+ public static final int MSGID_PWPSTATE_INVALID_BOOLEAN_VALUE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1156;
+
+
+
+ /**
+ * The message ID for the message that will be used if no value was provided
+ * for an operation that requires a Boolean value. This does not take any
+ * arguments.
+ */
+ public static final int MSGID_PWPSTATE_NO_BOOLEAN_VALUE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1157;
+
+
+
+ /**
+ * The message ID for the message that will be used if an unrecognized
+ * subcommand was provided. This takes a single argument, which is the
+ * unrecognized subcommand.
+ */
+ public static final int MSGID_PWPSTATE_INVALID_SUBCOMMAND =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1158;
+
+
+
+ /**
+ * The message ID for the message that will be used if an error occurs while
+ * attempting to send the extended request to the server. This takes a single
+ * argument, which is a message explaining the problem that occurred.
+ */
+ public static final int MSGID_PWPSTATE_CANNOT_SEND_REQUEST_EXTOP =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1159;
+
+
+
+ /**
+ * The message ID for the message that will be used if the server closed the
+ * connection without sending a response. This does not take any arguments.
+ */
+ public static final int MSGID_PWPSTATE_CONNECTION_CLOSED_READING_RESPONSE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1160;
+
+
+
+ /**
+ * The message ID for the message that will be used if the response from the
+ * server indicates that the request was not processed properly. This takes
+ * three arguments, which are the result code, a string representation of the
+ * result code, and the error message.
+ */
+ public static final int MSGID_PWPSTATE_REQUEST_FAILED =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1161;
+
+
+
+ /**
+ * The message ID for the message that will be used if an error occurred while
+ * attempting to decode the response message from the server. This takes a
+ * single argument, which is a message explaining the problem that occurred.
+ */
+ public static final int MSGID_PWPSTATE_CANNOT_DECODE_RESPONSE_MESSAGE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1162;
+
+
+
+ /**
+ * The message ID for the message that will be used if an error occurred while
+ * attempting to decode a response op. This takes a single argument, which is
+ * a message explaining the problem that occurred.
+ */
+ public static final int MSGID_PWPSTATE_CANNOT_DECODE_RESPONSE_OP =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1163;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the password policy DN.
+ */
+ public static final int MSGID_PWPSTATE_LABEL_PASSWORD_POLICY_DN =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1164;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the account disabled state.
+ */
+ public static final int MSGID_PWPSTATE_LABEL_ACCOUNT_DISABLED_STATE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1165;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the account expiration time.
+ */
+ public static final int MSGID_PWPSTATE_LABEL_ACCOUNT_EXPIRATION_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1166;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the seconds until account expiration.
+ */
+ public static final int
+ MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_ACCOUNT_EXPIRATION =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1167;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the password changed time.
+ */
+ public static final int MSGID_PWPSTATE_LABEL_PASSWORD_CHANGED_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1168;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the password expiration warned time.
+ */
+ public static final int MSGID_PWPSTATE_LABEL_PASSWORD_EXPIRATION_WARNED_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1169;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the seconds until password expiration.
+ */
+ public static final int
+ MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_PASSWORD_EXPIRATION =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1170;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the seconds until the password expiration warning.
+ */
+ public static final int
+ MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1171;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the auth failure times.
+ */
+ public static final int MSGID_PWPSTATE_LABEL_AUTH_FAILURE_TIMES =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1172;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the seconds until auth failure unlock.
+ */
+ public static final int
+ MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_AUTH_FAILURE_UNLOCK =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1173;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the remaining auth failure count.
+ */
+ public static final int MSGID_PWPSTATE_LABEL_REMAINING_AUTH_FAILURE_COUNT =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1174;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the last login time.
+ */
+ public static final int MSGID_PWPSTATE_LABEL_LAST_LOGIN_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1175;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the seconds until idle lockout.
+ */
+ public static final int MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_IDLE_LOCKOUT =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1176;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the password reset state.
+ */
+ public static final int MSGID_PWPSTATE_LABEL_PASSWORD_RESET_STATE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1177;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the seconds until password reset lockout.
+ */
+ public static final int
+ MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1178;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the grace login use times.
+ */
+ public static final int MSGID_PWPSTATE_LABEL_GRACE_LOGIN_USE_TIMES =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1179;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the remaining grace login count.
+ */
+ public static final int MSGID_PWPSTATE_LABEL_REMAINING_GRACE_LOGIN_COUNT =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1180;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the password changed by required time.
+ */
+ public static final int
+ MSGID_PWPSTATE_LABEL_PASSWORD_CHANGED_BY_REQUIRED_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1181;
+
+
+
+ /**
+ * The message ID for the message that will be used as the label when
+ * displaying the seconds until required change time.
+ */
+ public static final int
+ MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_REQUIRED_CHANGE_TIME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1182;
+
+
+
+ /**
+ * The message ID for the message that will be used if the response contained
+ * an unknown or invalid operation type. This takes a single argument, which
+ * is the invalid operation type.
+ */
+ public static final int MSGID_PWPSTATE_INVALID_RESPONSE_OP_TYPE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1183;
+
+
+
+ /**
+ * The message ID for the message that will be used if two arguments that are
+ * mutually exclusive were both provided. This takes two arguments, which are
+ * the long identifiers for the mutually-exclusive command line arguments.
+ */
+ public static final int MSGID_PWPSTATE_MUTUALLY_EXCLUSIVE_ARGUMENTS =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1184;
+
+
+
+ /**
+ * The message ID for the message that will be used if an error occurs while
+ * trying to perform SSL initialization. This takes a single argument, which
+ * is a message explaining the problem that occurred.
+ */
+ public static final int MSGID_PWPSTATE_CANNOT_INITIALIZE_SSL =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1185;
+
+
+
+ /**
+ * The message ID for the message that will be used if an error occurs while
+ * trying to parse a SASL option string. This takes a single argument, which
+ * is the SASL option string.
+ */
+ public static final int MSGID_PWPSTATE_CANNOT_PARSE_SASL_OPTION =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1186;
+
+
+
+ /**
+ * The message ID for the message that will be used if SASL options were used
+ * without specifying the SASL mechanism. This does not take any arguments.
+ */
+ public static final int MSGID_PWPSTATE_NO_SASL_MECHANISM =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1187;
+
+
+
+ /**
+ * The message ID for the message that will be used if an error occurs while
+ * trying to determine the port to use to communicate with the Directory
+ * Server. This takes two arguments, which are the name of the port argument
+ * and a message explaining the problem that occurred.
+ */
+ public static final int MSGID_PWPSTATE_CANNOT_DETERMINE_PORT =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1188;
+
+
+
+ /**
+ * The message ID for the message that will be used if an error occurs while
+ * trying to connect to the Directory Server. This takes a single argument,
+ * which is a message explaining the problem that occurred.
+ */
+ public static final int MSGID_PWPSTATE_CANNOT_CONNECT =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1189;
+
+
+
+ /**
* Associates a set of generic messages with the message IDs defined in this
* class.
*/
@@ -10634,6 +11546,278 @@
registerMessage(MSGID_DSCFG_DESCRIPTION_SHOW_GROUP_USAGE_SUMMARY,
"Display summary usage information");
+
+
+ registerMessage(MSGID_PWPSTATE_TOOL_DESCRIPTION,
+ "This utility may be used to retrieve and manipulate " +
+ "the values of password policy state variables");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_HOST,
+ "Directory server hostname or IP address");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_PORT,
+ "Directory server port number");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_USESSL,
+ "Use SSL for secure communication with the server");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_USESTARTTLS,
+ "Use StartTLS to secure communication with the server");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_BINDDN,
+ "The DN to use to bind to the server");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_BINDPW,
+ "The password to use to bind to the server");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_BINDPWFILE,
+ "The path to the file containing the bind password");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_TARGETDN,
+ "The DN of the user entry for which to get and set " +
+ "password policy state information");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_SASLOPTIONS,
+ "SASL bind options");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_TRUST_ALL,
+ "Trust all server SSL certificates");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_KSFILE,
+ "Certificate keystore path");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_KSPW,
+ "Certificate keystore PIN");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_KSPWFILE,
+ "Certificate keystore PIN file");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_TSFILE,
+ "Certificate trust store path");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_TSPW,
+ "Certificate trust store PIN");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_TSPWFILE,
+ "Certificate trust store PIN file");
+ registerMessage(MSGID_PWPSTATE_DESCRIPTION_SHOWUSAGE,
+ "Display this usage information");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_GET_ALL,
+ "Display all password policy state information for the " +
+ "user");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_GET_PASSWORD_POLICY_DN,
+ "Display the DN of the password policy for the user");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_GET_ACCOUNT_DISABLED_STATE,
+ "Display information about whether the user account has " +
+ "been administratively disabled");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_SET_ACCOUNT_DISABLED_STATE,
+ "Specify whether the user account has been " +
+ "administratively disabled");
+ registerMessage(MSGID_DESCRIPTION_OPERATION_BOOLEAN_VALUE,
+ "'true' to indicate that the account is disabled, or " +
+ "'false' to indicate that it is not disabled");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_CLEAR_ACCOUNT_DISABLED_STATE,
+ "Clear account disabled state information from the user " +
+ "account");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_GET_ACCOUNT_EXPIRATION_TIME,
+ "Display when the user account will expire");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_SET_ACCOUNT_EXPIRATION_TIME,
+ "Specify when the user account will expire");
+ registerMessage(MSGID_DESCRIPTION_OPERATION_TIME_VALUE,
+ "A timestamp value using the generalized time syntax");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_CLEAR_ACCOUNT_EXPIRATION_TIME,
+ "Clear account expiration time information from the user " +
+ "account");
+ registerMessage(
+ MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION,
+ "Display the length of time in seconds until the user account " +
+ "expires");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_GET_PASSWORD_CHANGED_TIME,
+ "Display the time that the user's password was last " +
+ "changed");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_SET_PASSWORD_CHANGED_TIME,
+ "Specify the time that the user's password was last " +
+ "changed. This should be used only for testing purposes");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_CLEAR_PASSWORD_CHANGED_TIME,
+ "Clear information about the time that the user's " +
+ "password was last changed. This should be used only " +
+ "for testing purposes");
+ registerMessage(
+ MSGID_DESCRIPTION_PWPSTATE_GET_PASSWORD_EXPIRATION_WARNED_TIME,
+ "Display the time that the user first received an expiration " +
+ "warning notice");
+ registerMessage(
+ MSGID_DESCRIPTION_PWPSTATE_SET_PASSWORD_EXPIRATION_WARNED_TIME,
+ "Specify the time that the user first received an expiration " +
+ "warning notice. This should be used only for testing purposes");
+ registerMessage(
+ MSGID_DESCRIPTION_PWPSTATE_CLEAR_PASSWORD_EXPIRATION_WARNED_TIME,
+ "Clear information about the time that the user first received an " +
+ "expiration warning notice. This should be used only for testing " +
+ "purposes");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_PASSWORD_EXP,
+ "Display length of time in seconds until the user's " +
+ "password expires");
+ registerMessage(
+ MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_PASSWORD_EXP_WARNING,
+ "Display the length of time in seconds until the user should start " +
+ "receiving password expiration warning notices");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_GET_AUTH_FAILURE_TIMES,
+ "Display the authentication failure times for the user");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_ADD_AUTH_FAILURE_TIME,
+ "Add an authentication failure time to the user " +
+ "account. This should be used only for testing purposes");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_SET_AUTH_FAILURE_TIMES,
+ "Specify the authentication failure times for the user. " +
+ "This should be used only for testing purposes");
+ registerMessage(MSGID_DESCRIPTION_OPERATION_TIME_VALUES,
+ "A timestamp value using the generalized time syntax. " +
+ "Multiple timestamp values may be given by providing " +
+ "this argument multiple times");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_CLEAR_AUTH_FAILURE_TIMES,
+ "Clear authentication failure time information from the " +
+ "user's account. This should be used only for testing " +
+ "purposes");
+ registerMessage(
+ MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_AUTH_FAILURE_UNLOCK,
+ "Display the length of time in seconds until the authentication " +
+ "failure lockout expires");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_GET_REMAINING_AUTH_FAILURE_COUNT,
+ "Display the number of remaining authentication failures " +
+ "until the user's account is locked");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_GET_LAST_LOGIN_TIME,
+ "Display the time that the user last authenticated to " +
+ "the server");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_SET_LAST_LOGIN_TIME,
+ "Specify the time that the user last authenticated to " +
+ "the server. This should be used only for testing " +
+ "purposes");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_CLEAR_LAST_LOGIN_TIME,
+ "Clear the time that the user last authenticated to the " +
+ "server. This should be used only for testing purposes");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_IDLE_LOCKOUT,
+ "Display the length of time in seconds until user's " +
+ "account is locked because it has remained idle for " +
+ "too long");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_GET_PASSWORD_RESET_STATE,
+ "Display information about whether the user will be " +
+ "required to change his or her password on the next " +
+ "successful authentication");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_SET_PASSWORD_RESET_STATE,
+ "Specify whether the user will be required to change his " +
+ "or her password on the next successful authentication. " +
+ "This should be used only for testing purposes");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_CLEAR_PASSWORD_RESET_STATE,
+ "Clear information about whether the user will be " +
+ "required to change his or her password on the next " +
+ "successful authentication. This should be used only " +
+ "for testing purposes");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_RESET_LOCKOUT,
+ "Display the length of time in seconds until user's " +
+ "account is locked because the user failed to change the " +
+ "password in a timely manner after an administrative " +
+ "reset");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_GET_GRACE_LOGIN_USE_TIMES,
+ "Display the grace login use times for the user");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_ADD_GRACE_LOGIN_USE_TIME,
+ "Add a grace login use time to the user account. This " +
+ "should be used only for testing purposes");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_SET_GRACE_LOGIN_USE_TIMES,
+ "Specify the grace login use times for the user. This " +
+ "should be used only for testing purposes");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_CLEAR_GRACE_LOGIN_USE_TIMES,
+ "Clear the set of grace login use times for the user. " +
+ "This should be used only for testing purposes");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_GET_REMAINING_GRACE_LOGIN_COUNT,
+ "Display the number of grace logins remaining for the " +
+ "user");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_GET_PW_CHANGED_BY_REQUIRED_TIME,
+ "Display the required password change time with which " +
+ "the user last complied");
+ registerMessage(MSGID_DESCRIPTION_PWPSTATE_SET_PW_CHANGED_BY_REQUIRED_TIME,
+ "Specify the required password change time with which " +
+ "the user last complied. This should be used only for " +
+ "testing purposes");
+ registerMessage(
+ MSGID_DESCRIPTION_PWPSTATE_CLEAR_PW_CHANGED_BY_REQUIRED_TIME,
+ "Clear information about the required password change time with " +
+ "which the user last complied. This should be used only for " +
+ "testing purposes");
+ registerMessage(
+ MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME,
+ "Display the length of time in seconds that the user has remaining " +
+ "to change his or her password before the account becomes locked " +
+ "due to the required change time");
+ registerMessage(MSGID_PWPSTATE_MUTUALLY_EXCLUSIVE_ARGUMENTS,
+ "ERROR: You may not provide both the %s and the %s " +
+ "arguments");
+ registerMessage(MSGID_PWPSTATE_CANNOT_INITIALIZE_SSL,
+ "ERROR: Unable to perform SSL initialization: %s");
+ registerMessage(MSGID_PWPSTATE_CANNOT_PARSE_SASL_OPTION,
+ "ERROR: The provided SASL option string \"%s\" could " +
+ "not be parsed in the form \"name=value\"");
+ registerMessage(MSGID_PWPSTATE_NO_SASL_MECHANISM,
+ "ERROR: One or more SASL options were provided, but " +
+ "none of them were the \"mech\" option to specify which " +
+ "SASL mechanism should be used");
+ registerMessage(MSGID_PWPSTATE_CANNOT_DETERMINE_PORT,
+ "ERROR: Cannot parse the value of the %s argument as " +
+ "an integer value between 1 and 65535: %s");
+ registerMessage(MSGID_PWPSTATE_CANNOT_CONNECT,
+ "ERROR: Cannot establish a connection to the " +
+ "Directory Server: %s");
+ registerMessage(MSGID_PWPSTATE_NO_SUBCOMMAND,
+ "No subcommand was provided to indicate which password " +
+ "policy state operation should be performed");
+ registerMessage(MSGID_PWPSTATE_INVALID_BOOLEAN_VALUE,
+ "The provided value '%s' was invalid for the requested " +
+ "operation. A Boolean value of either 'true' or 'false' " +
+ "was expected");
+ registerMessage(MSGID_PWPSTATE_NO_BOOLEAN_VALUE,
+ "No value was specified, but the requested operation " +
+ "requires a Boolean value of either 'true' or 'false'");
+ registerMessage(MSGID_PWPSTATE_INVALID_SUBCOMMAND,
+ "Unrecognized subcommand '%s'");
+ registerMessage(MSGID_PWPSTATE_CANNOT_SEND_REQUEST_EXTOP,
+ "An error occurred while attempting to send the request " +
+ "to the server: %s");
+ registerMessage(MSGID_PWPSTATE_CONNECTION_CLOSED_READING_RESPONSE,
+ "The Directory Server closed the connection before the " +
+ "response could be read");
+ registerMessage(MSGID_PWPSTATE_REQUEST_FAILED,
+ "The server was unable to process the request: result " +
+ "code %d (%s), error message '%s'");
+ registerMessage(MSGID_PWPSTATE_CANNOT_DECODE_RESPONSE_MESSAGE,
+ "The server was unable to decode the response message " +
+ "from the server: %s");
+ registerMessage(MSGID_PWPSTATE_CANNOT_DECODE_RESPONSE_OP,
+ "Unable to decode information about an operation " +
+ "contained in the response: %s");
+ registerMessage(MSGID_PWPSTATE_LABEL_PASSWORD_POLICY_DN,
+ "Password Policy DN");
+ registerMessage(MSGID_PWPSTATE_LABEL_ACCOUNT_DISABLED_STATE,
+ "Account Is Disabled");
+ registerMessage(MSGID_PWPSTATE_LABEL_ACCOUNT_EXPIRATION_TIME,
+ "Account Expiration Time");
+ registerMessage(MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_ACCOUNT_EXPIRATION,
+ "Seconds Until Account Expiration");
+ registerMessage(MSGID_PWPSTATE_LABEL_PASSWORD_CHANGED_TIME,
+ "Password Changed Time");
+ registerMessage(MSGID_PWPSTATE_LABEL_PASSWORD_EXPIRATION_WARNED_TIME,
+ "Password Expiration Warned Time");
+ registerMessage(MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_PASSWORD_EXPIRATION,
+ "Seconds Until Password Expiration");
+ registerMessage(
+ MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING,
+ "Seconds Until Password Expiration Warning");
+ registerMessage(MSGID_PWPSTATE_LABEL_AUTH_FAILURE_TIMES,
+ "Authentication Failure Times");
+ registerMessage(MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_AUTH_FAILURE_UNLOCK,
+ "Seconds Until Authentication Failure Unlock");
+ registerMessage(MSGID_PWPSTATE_LABEL_REMAINING_AUTH_FAILURE_COUNT,
+ "Remaining Authentication Failure Count");
+ registerMessage(MSGID_PWPSTATE_LABEL_LAST_LOGIN_TIME,
+ "Last Login Time");
+ registerMessage(MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_IDLE_LOCKOUT,
+ "Seconds Until Idle Account Lockout");
+ registerMessage(MSGID_PWPSTATE_LABEL_PASSWORD_RESET_STATE,
+ "Password Is Reset");
+ registerMessage(MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT,
+ "Seconds Until Password Reset Lockout");
+ registerMessage(MSGID_PWPSTATE_LABEL_GRACE_LOGIN_USE_TIMES,
+ "Grace Login Use Times");
+ registerMessage(MSGID_PWPSTATE_LABEL_REMAINING_GRACE_LOGIN_COUNT,
+ "Remaining Grace Login Count");
+ registerMessage(MSGID_PWPSTATE_LABEL_PASSWORD_CHANGED_BY_REQUIRED_TIME,
+ "Password Changed by Required Time");
+ registerMessage(MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_REQUIRED_CHANGE_TIME,
+ "Seconds Until Required Change Time");
+ registerMessage(MSGID_PWPSTATE_INVALID_RESPONSE_OP_TYPE,
+ "Unrecognized or invalid operation type: %s");
}
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/ManageAccount.java b/opendj-sdk/opends/src/server/org/opends/server/tools/ManageAccount.java
new file mode 100644
index 0000000..36f7d77
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/ManageAccount.java
@@ -0,0 +1,1688 @@
+/*
+ * 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.tools;
+
+
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.HashSet;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.opends.server.protocols.asn1.ASN1Element;
+import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.protocols.asn1.ASN1Reader;
+import org.opends.server.protocols.asn1.ASN1Sequence;
+import org.opends.server.protocols.asn1.ASN1Writer;
+import org.opends.server.protocols.ldap.ExtendedRequestProtocolOp;
+import org.opends.server.protocols.ldap.ExtendedResponseProtocolOp;
+import org.opends.server.protocols.ldap.LDAPMessage;
+import org.opends.server.protocols.ldap.LDAPResultCode;
+import org.opends.server.types.NullOutputStream;
+import org.opends.server.util.args.Argument;
+import org.opends.server.util.args.ArgumentException;
+import org.opends.server.util.args.BooleanArgument;
+import org.opends.server.util.args.FileBasedArgument;
+import org.opends.server.util.args.IntegerArgument;
+import org.opends.server.util.args.MultiChoiceArgument;
+import org.opends.server.util.args.StringArgument;
+import org.opends.server.util.args.SubCommand;
+import org.opends.server.util.args.SubCommandArgumentParser;
+
+import static org.opends.server.extensions.
+ PasswordPolicyStateExtendedOperation.*;
+import static org.opends.server.messages.MessageHandler.*;
+import static org.opends.server.messages.ToolMessages.*;
+import static org.opends.server.tools.ToolConstants.*;
+import static org.opends.server.util.ServerConstants.*;
+import static org.opends.server.util.StaticUtils.*;
+
+
+
+/**
+ * This class provides a tool that can be used to perform various kinds of
+ * account management using the password policy state extended operation.
+ */
+public class ManageAccount
+{
+ /**
+ * The fully-qualified name of this class.
+ */
+ private static final String CLASS_NAME =
+ "org.opends.server.tools.ManageAccount";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get all password policy
+ * state information for the user.
+ */
+ private static final String SC_GET_ALL = "get-all";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the DN of the password
+ * policy for a given user.
+ */
+ private static final String SC_GET_PASSWORD_POLICY_DN =
+ "get-password-policy-dn";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the disabled state for
+ * a user.
+ */
+ private static final String SC_GET_ACCOUNT_DISABLED_STATE =
+ "get-account-is-disabled";
+
+
+
+ /**
+ * The name of the subcommand that will be used to set the disabled state for
+ * a user.
+ */
+ private static final String SC_SET_ACCOUNT_DISABLED_STATE =
+ "set-account-is-disabled";
+
+
+
+ /**
+ * The name of the subcommand that will be used to clear the disabled state
+ * for a user.
+ */
+ private static final String SC_CLEAR_ACCOUNT_DISABLED_STATE =
+ "clear-account-is-disabled";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the account expiration
+ * time.
+ */
+ private static final String SC_GET_ACCOUNT_EXPIRATION_TIME =
+ "get-account-expiration-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to set the account expiration
+ * time.
+ */
+ private static final String SC_SET_ACCOUNT_EXPIRATION_TIME =
+ "set-account-expiration-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to clear the account
+ * expiration time.
+ */
+ private static final String SC_CLEAR_ACCOUNT_EXPIRATION_TIME =
+ "clear-account-expiration-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the length of time
+ * before the account expires.
+ */
+ private static final String SC_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION =
+ "get-seconds-until-account-expiration";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the time the password
+ * was last changed.
+ */
+ private static final String SC_GET_PASSWORD_CHANGED_TIME =
+ "get-password-changed-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to set the time the password
+ * was last changed.
+ */
+ private static final String SC_SET_PASSWORD_CHANGED_TIME =
+ "set-password-changed-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to clear the time the password
+ * was last changed.
+ */
+ private static final String SC_CLEAR_PASSWORD_CHANGED_TIME =
+ "clear-password-changed-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the time the user was
+ * first warned about an upcoming password expiration.
+ */
+ private static final String SC_GET_PASSWORD_EXP_WARNED_TIME =
+ "get-password-expiration-warned-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to set the time the user was
+ * first warned about an upcoming password expiration.
+ */
+ private static final String SC_SET_PASSWORD_EXP_WARNED_TIME =
+ "set-password-expiration-warned-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to clear the time the user was
+ * first warned about an upcoming password expiration.
+ */
+ private static final String SC_CLEAR_PASSWORD_EXP_WARNED_TIME =
+ "clear-password-expiration-warned-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the length of time
+ * before the password expires.
+ */
+ private static final String SC_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION =
+ "get-seconds-until-password-expiration";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the length of time
+ * before the user is first warned about an upcoming password expiration.
+ */
+ private static final String SC_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING =
+ "get-seconds-until-password-expiration-warning";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the authentication
+ * failure times for the user.
+ */
+ private static final String SC_GET_AUTHENTICATION_FAILURE_TIMES =
+ "get-authentication-failure-times";
+
+
+
+ /**
+ * The name of the subcommand that will be used to add an authentication
+ * failure time for the user.
+ */
+ private static final String SC_ADD_AUTHENTICATION_FAILURE_TIME =
+ "add-authentication-failure-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to set the authentication
+ * failure times for the user.
+ */
+ private static final String SC_SET_AUTHENTICATION_FAILURE_TIMES =
+ "set-authentication-failure-times";
+
+
+
+ /**
+ * The name of the subcommand that will be used to clear the authentication
+ * failure times for the user.
+ */
+ private static final String SC_CLEAR_AUTHENTICATION_FAILURE_TIMES =
+ "clear-authentication-failure-times";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the length of time
+ * before the user's account is unlocked.
+ */
+ private static final String
+ SC_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK =
+ "get-seconds-until-authentication-failure-unlock";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the number of remaining
+ * authentication failures for the user.
+ */
+ private static final String SC_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT =
+ "get-remaining-authentication-failure-count";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the last login time for
+ * the user.
+ */
+ private static final String SC_GET_LAST_LOGIN_TIME =
+ "get-last-login-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to set the last login time for
+ * the user.
+ */
+ private static final String SC_SET_LAST_LOGIN_TIME =
+ "set-last-login-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to clear the last login time
+ * for the user.
+ */
+ private static final String SC_CLEAR_LAST_LOGIN_TIME =
+ "clear-last-login-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the length of time
+ * before the account is idle locked.
+ */
+ private static final String SC_GET_SECONDS_UNTIL_IDLE_LOCKOUT =
+ "get-seconds-until-idle-lockout";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the password reset
+ * state for a user.
+ */
+ private static final String SC_GET_PASSWORD_RESET_STATE =
+ "get-password-is-reset";
+
+
+
+ /**
+ * The name of the subcommand that will be used to set the password reset
+ * state for a user.
+ */
+ private static final String SC_SET_PASSWORD_RESET_STATE =
+ "set-password-is-reset";
+
+
+
+ /**
+ * The name of the subcommand that will be used to clear the password reset
+ * state for a user.
+ */
+ private static final String SC_CLEAR_PASSWORD_RESET_STATE =
+ "clear-password-is-reset";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the length of time
+ * before the password reset lockout occurs.
+ */
+ private static final String SC_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT =
+ "get-seconds-until-password-reset-lockout";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the grace login use
+ * times for the user.
+ */
+ private static final String SC_GET_GRACE_LOGIN_USE_TIMES =
+ "get-grace-login-use-times";
+
+
+
+ /**
+ * The name of the subcommand that will be used to add a grace login use time
+ * for the user.
+ */
+ private static final String SC_ADD_GRACE_LOGIN_USE_TIME =
+ "add-grace-login-use-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to set the grace login use
+ * times for the user.
+ */
+ private static final String SC_SET_GRACE_LOGIN_USE_TIMES =
+ "set-grace-login-use-times";
+
+
+
+ /**
+ * The name of the subcommand that will be used to clear the grace login use
+ * times for the user.
+ */
+ private static final String SC_CLEAR_GRACE_LOGIN_USE_TIMES =
+ "clear-grace-login-use-times";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get number of remaining
+ * grace logins for the user.
+ */
+ private static final String SC_GET_REMAINING_GRACE_LOGIN_COUNT =
+ "get-remaining-grace-login-count";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the password changed by
+ * required time for the user.
+ */
+ private static final String SC_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME =
+ "get-password-changed-by-required-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to set the password changed by
+ * required time for the user.
+ */
+ private static final String SC_SET_PASSWORD_CHANGED_BY_REQUIRED_TIME =
+ "set-password-changed-by-required-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to clear the password changed
+ * by required time for the user.
+ */
+ private static final String SC_CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME =
+ "clear-password-changed-by-required-time";
+
+
+
+ /**
+ * The name of the subcommand that will be used to get the length of time
+ * before the user is required to change his/her password due to the required
+ * change time.
+ */
+ private static final String SC_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME =
+ "get-seconds-until-required-change-time";
+
+
+
+ /**
+ * The name of the argument that will be used for holding the value(s) to use
+ * for the target operation.
+ */
+ private static final String ARG_OP_VALUE = "opvalue";
+
+
+
+ /**
+ * The value that will be used when encoding a password policy state operation
+ * that should not have any values.
+ */
+ private static final String NO_VALUE = null;
+
+
+
+ // The ASN.1 reader used to read responses from the server.
+ private static ASN1Reader asn1Reader;
+
+ // The ASN.1 writer used to send requests to the server.
+ private static ASN1Writer asn1Writer;
+
+ // The counter that will be used for LDAP message IDs.
+ private static AtomicInteger nextMessageID;
+
+ // The connection to the server.
+ private static LDAPConnection connection;
+
+ // The print stream to use when writing messages to standard error.
+ private static PrintStream err;
+
+ // The print stream to use when writing messages to standard output.
+ private static PrintStream out;
+
+ // The DN of the user to target with the operation.
+ private static String targetDNString;
+
+ // The argument parser for this tool.
+ private static SubCommandArgumentParser argParser;
+
+
+
+ /**
+ * Parses the command-line arguments, connects to the server, and performs the
+ * appropriate processing.
+ *
+ * @param args The command-line arguments provided to this program.
+ */
+ public static void main(String[] args)
+ {
+ int returnCode = main(args, System.out, System.err);
+ if (returnCode != 0)
+ {
+ System.exit(returnCode);
+ }
+ }
+
+
+
+ /**
+ * Parses the command-line arguments, connects to the server, and performs the
+ * appropriate processing.
+ *
+ * @param args The command-line arguments provided to this program.
+ * @param outStream The output stream to use for standard output, or
+ * {@code null} if standard output is not needed.
+ * @param errStream The output stream to use for standard error, or
+ * {@code null} if standard error is not needed.
+ *
+ * @return A result code indicating whether the processing was successful.
+ */
+ public static int main(String[] args, OutputStream outStream,
+ OutputStream errStream)
+ {
+ if (outStream == null)
+ {
+ out = NullOutputStream.printStream();
+ }
+ else
+ {
+ out = new PrintStream(outStream);
+ }
+
+ if (errStream == null)
+ {
+ err = NullOutputStream.printStream();
+ }
+ else
+ {
+ err = new PrintStream(errStream);
+ }
+
+
+
+
+ // Parse the command-line arguments provided to the program.
+ int result = parseArgsAndConnect(args);
+ if (result < 0)
+ {
+ // This should only happen if we're only displaying usage information or
+ // doing something else other than actually running the tool.
+ return LDAPResultCode.SUCCESS;
+ }
+ else if (result != LDAPResultCode.SUCCESS)
+ {
+ return result;
+ }
+
+
+ try
+ {
+ // Use the subcommand provided to figure out how to encode the request.
+ ArrayList<ASN1Element> opElements = new ArrayList<ASN1Element>(1);
+ result = processSubcommand(opElements);
+ if (result != LDAPResultCode.SUCCESS)
+ {
+ return result;
+ }
+
+
+ // Generate the extended request and send it to the server.
+ ArrayList<ASN1Element> valueElements = new ArrayList<ASN1Element>(2);
+ valueElements.add(new ASN1OctetString(targetDNString));
+ if (! opElements.isEmpty())
+ {
+ valueElements.add(new ASN1Sequence(opElements));
+ }
+ ASN1OctetString requestValue =
+ new ASN1OctetString(new ASN1Sequence(valueElements).encode());
+
+ ExtendedRequestProtocolOp extendedRequest =
+ new ExtendedRequestProtocolOp(OID_PASSWORD_POLICY_STATE_EXTOP,
+ requestValue);
+
+ LDAPMessage requestMessage =
+ new LDAPMessage(nextMessageID.getAndIncrement(), extendedRequest);
+
+ try
+ {
+ asn1Writer.writeElement(requestMessage.encode());
+ }
+ catch (Exception e)
+ {
+ int msgID = MSGID_PWPSTATE_CANNOT_SEND_REQUEST_EXTOP;
+ String message = getMessage(msgID, getExceptionMessage(e));
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ return LDAPResultCode.CLIENT_SIDE_SERVER_DOWN;
+ }
+
+
+ // Read the response from the server.
+ ArrayList<ASN1Element> responseOpElements;
+ try
+ {
+ ASN1Element responseElement = asn1Reader.readElement();
+ if (responseElement == null)
+ {
+ int msgID = MSGID_PWPSTATE_CONNECTION_CLOSED_READING_RESPONSE;
+ String message = getMessage(msgID);
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ return LDAPResultCode.CLIENT_SIDE_SERVER_DOWN;
+ }
+
+ LDAPMessage responseMessage =
+ LDAPMessage.decode(responseElement.decodeAsSequence());
+ ExtendedResponseProtocolOp extendedResponse =
+ responseMessage.getExtendedResponseProtocolOp();
+
+ int resultCode = extendedResponse.getResultCode();
+ if (resultCode != LDAPResultCode.SUCCESS)
+ {
+ int msgID = MSGID_PWPSTATE_REQUEST_FAILED;
+ String message =
+ getMessage(msgID, resultCode,
+ LDAPResultCode.toString(resultCode),
+ String.valueOf(extendedResponse.getErrorMessage()));
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ return resultCode;
+ }
+
+ ASN1Sequence valueSequence =
+ ASN1Sequence.decodeAsSequence(extendedResponse.getValue().value());
+ responseOpElements =
+ valueSequence.elements().get(1).decodeAsSequence().elements();
+ }
+ catch (Exception e)
+ {
+ int msgID = MSGID_PWPSTATE_CANNOT_DECODE_RESPONSE_MESSAGE;
+ String message = getMessage(msgID, getExceptionMessage(e));
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ return LDAPResultCode.CLIENT_SIDE_SERVER_DOWN;
+ }
+
+
+ // Get the response value and parse its individual elements.
+ for (ASN1Element opElement : responseOpElements)
+ {
+ int opType;
+ ArrayList<String> opValues;
+
+ try
+ {
+ ASN1Sequence opSequence = opElement.decodeAsSequence();
+ ArrayList<ASN1Element> elements = opSequence.elements();
+ opType = elements.get(0).decodeAsEnumerated().intValue();
+ opValues = new ArrayList<String>();
+ if (elements.size() == 2)
+ {
+ for (ASN1Element e : elements.get(1).decodeAsSequence().elements())
+ {
+ opValues.add(e.decodeAsOctetString().stringValue());
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ int msgID = MSGID_PWPSTATE_CANNOT_DECODE_RESPONSE_OP;
+ String message = getMessage(msgID, getExceptionMessage(e));
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ continue;
+ }
+
+ switch (opType)
+ {
+ case OP_GET_PASSWORD_POLICY_DN:
+ int msgID = MSGID_PWPSTATE_LABEL_PASSWORD_POLICY_DN;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_ACCOUNT_DISABLED_STATE:
+ msgID = MSGID_PWPSTATE_LABEL_ACCOUNT_DISABLED_STATE;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_ACCOUNT_EXPIRATION_TIME:
+ msgID = MSGID_PWPSTATE_LABEL_ACCOUNT_EXPIRATION_TIME;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION:
+ msgID = MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_ACCOUNT_EXPIRATION;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_PASSWORD_CHANGED_TIME:
+ msgID = MSGID_PWPSTATE_LABEL_PASSWORD_CHANGED_TIME;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_PASSWORD_EXPIRATION_WARNED_TIME:
+ msgID = MSGID_PWPSTATE_LABEL_PASSWORD_EXPIRATION_WARNED_TIME;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION:
+ msgID = MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_PASSWORD_EXPIRATION;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING:
+ msgID =
+ MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_AUTHENTICATION_FAILURE_TIMES:
+ msgID = MSGID_PWPSTATE_LABEL_AUTH_FAILURE_TIMES;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK:
+ msgID = MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_AUTH_FAILURE_UNLOCK;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT:
+ msgID = MSGID_PWPSTATE_LABEL_REMAINING_AUTH_FAILURE_COUNT;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_LAST_LOGIN_TIME:
+ msgID = MSGID_PWPSTATE_LABEL_LAST_LOGIN_TIME;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_SECONDS_UNTIL_IDLE_LOCKOUT:
+ msgID = MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_IDLE_LOCKOUT;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_PASSWORD_RESET_STATE:
+ msgID = MSGID_PWPSTATE_LABEL_PASSWORD_RESET_STATE;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT:
+ msgID = MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_GRACE_LOGIN_USE_TIMES:
+ msgID = MSGID_PWPSTATE_LABEL_GRACE_LOGIN_USE_TIMES;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_REMAINING_GRACE_LOGIN_COUNT:
+ msgID = MSGID_PWPSTATE_LABEL_REMAINING_GRACE_LOGIN_COUNT;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME:
+ msgID = MSGID_PWPSTATE_LABEL_PASSWORD_CHANGED_BY_REQUIRED_TIME;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ case OP_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME:
+ msgID = MSGID_PWPSTATE_LABEL_SECONDS_UNTIL_REQUIRED_CHANGE_TIME;
+ printLabelAndValues(msgID, opValues);
+ break;
+
+ default:
+ msgID = MSGID_PWPSTATE_INVALID_RESPONSE_OP_TYPE;
+ String message = getMessage(msgID, opType);
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ break;
+ }
+ }
+
+
+ // If we've gotten here, then everything completed successfully.
+ return 0;
+ }
+ finally
+ {
+ // Close the connection to the server if it's active.
+ if (connection != null)
+ {
+ connection.close(nextMessageID);
+ }
+ }
+ }
+
+
+
+ /**
+ * Initializes the argument parser for this tool, parses the provided
+ * arguments, and establishes a connection to the server.
+ *
+ * @return A result code that indicates the result of the processing. A
+ * value of zero indicates that all processing completed
+ * successfully. A value of -1 indicates that only the usage
+ * information was displayed and no further action is required.
+ */
+ private static int parseArgsAndConnect(String[] args)
+ {
+ int msgID = MSGID_PWPSTATE_TOOL_DESCRIPTION;
+ argParser = new SubCommandArgumentParser(CLASS_NAME, getMessage(msgID),
+ false);
+
+ BooleanArgument showUsage;
+ BooleanArgument trustAll;
+ BooleanArgument useSSL;
+ BooleanArgument useStartTLS;
+ FileBasedArgument bindPWFile;
+ FileBasedArgument keyStorePWFile;
+ FileBasedArgument trustStorePWFile;
+ IntegerArgument port;
+ StringArgument bindDN;
+ StringArgument bindPW;
+ StringArgument certNickname;
+ StringArgument host;
+ StringArgument keyStoreFile;
+ StringArgument keyStorePW;
+ StringArgument saslOption;
+ StringArgument targetDN;
+ StringArgument trustStoreFile;
+ StringArgument trustStorePW;
+
+ try
+ {
+ host = new StringArgument("host", OPTION_SHORT_HOST,
+ OPTION_LONG_HOST, false, false, true,
+ OPTION_VALUE_HOST, "127.0.0.1", null,
+ MSGID_PWPSTATE_DESCRIPTION_HOST);
+ argParser.addGlobalArgument(host);
+
+ port = new IntegerArgument("port", OPTION_SHORT_PORT,
+ OPTION_LONG_PORT, false, false, true,
+ OPTION_VALUE_PORT, 389, null, true, 1,
+ true, 65535, MSGID_PWPSTATE_DESCRIPTION_PORT);
+ argParser.addGlobalArgument(port);
+
+ useSSL = new BooleanArgument("usessl", OPTION_SHORT_USE_SSL,
+ OPTION_LONG_USE_SSL,
+ MSGID_PWPSTATE_DESCRIPTION_USESSL);
+ argParser.addGlobalArgument(useSSL);
+
+ useStartTLS = new BooleanArgument("usestarttls", OPTION_SHORT_START_TLS,
+ OPTION_LONG_START_TLS,
+ MSGID_PWPSTATE_DESCRIPTION_USESTARTTLS);
+ argParser.addGlobalArgument(useStartTLS);
+
+ bindDN = new StringArgument("binddn", OPTION_SHORT_BINDDN,
+ OPTION_LONG_BINDDN, false, false, true,
+ OPTION_VALUE_BINDDN, null, null,
+ MSGID_PWPSTATE_DESCRIPTION_BINDDN);
+ argParser.addGlobalArgument(bindDN);
+
+ bindPW = new StringArgument("bindpw", OPTION_SHORT_BINDPWD,
+ OPTION_LONG_BINDPWD, false, false,
+ true,
+ OPTION_VALUE_BINDPWD, null, null,
+ MSGID_PWPSTATE_DESCRIPTION_BINDPW);
+ argParser.addGlobalArgument(bindPW);
+
+ bindPWFile = new FileBasedArgument("bindpwfile",
+ OPTION_SHORT_BINDPWD_FILE,
+ OPTION_LONG_BINDPWD_FILE,
+ false, false,
+ OPTION_VALUE_BINDPWD_FILE,
+ null, null,
+ MSGID_PWPSTATE_DESCRIPTION_BINDPWFILE);
+ argParser.addGlobalArgument(bindPWFile);
+
+ targetDN = new StringArgument("targetdn", 'b', "targetDN", true, false,
+ true, "{targetDN}", null, null,
+ MSGID_PWPSTATE_DESCRIPTION_TARGETDN);
+ argParser.addGlobalArgument(targetDN);
+
+ saslOption = new StringArgument("sasloption", OPTION_SHORT_SASLOPTION,
+ OPTION_LONG_SASLOPTION, false,
+ true, true,
+ OPTION_VALUE_SASLOPTION, null, null,
+ MSGID_PWPSTATE_DESCRIPTION_SASLOPTIONS);
+ argParser.addGlobalArgument(saslOption);
+
+ trustAll = new BooleanArgument("trustall", 'X', "trustAll",
+ MSGID_PWPSTATE_DESCRIPTION_TRUST_ALL);
+ argParser.addGlobalArgument(trustAll);
+
+ keyStoreFile = new StringArgument("keystorefile",
+ OPTION_SHORT_KEYSTOREPATH,
+ OPTION_LONG_KEYSTOREPATH,
+ false, false, true,
+ OPTION_VALUE_KEYSTOREPATH,
+ null, null,
+ MSGID_PWPSTATE_DESCRIPTION_KSFILE);
+ argParser.addGlobalArgument(keyStoreFile);
+
+ keyStorePW = new StringArgument("keystorepw", OPTION_SHORT_KEYSTORE_PWD,
+ OPTION_LONG_KEYSTORE_PWD,
+ false, false, true,
+ OPTION_VALUE_KEYSTORE_PWD,
+ null, null,
+ MSGID_PWPSTATE_DESCRIPTION_KSPW);
+ argParser.addGlobalArgument(keyStorePW);
+
+ keyStorePWFile = new FileBasedArgument("keystorepwfile",
+ OPTION_SHORT_KEYSTORE_PWD_FILE,
+ OPTION_LONG_KEYSTORE_PWD_FILE, false, false,
+ OPTION_VALUE_KEYSTORE_PWD_FILE, null, null,
+ MSGID_PWPSTATE_DESCRIPTION_KSPWFILE);
+ argParser.addGlobalArgument(keyStorePWFile);
+
+ certNickname = new StringArgument("certnickname", 'N', "certNickname",
+ false, false, true, "{nickname}", null,
+ null, MSGID_DESCRIPTION_CERT_NICKNAME);
+ argParser.addGlobalArgument(certNickname);
+
+ trustStoreFile = new StringArgument("truststorefile",
+ OPTION_SHORT_TRUSTSTOREPATH,
+ OPTION_LONG_TRUSTSTOREPATH,
+ false, false, true,
+ OPTION_VALUE_TRUSTSTOREPATH,
+ null, null,
+ MSGID_PWPSTATE_DESCRIPTION_TSFILE);
+ argParser.addGlobalArgument(trustStoreFile);
+
+ trustStorePW = new StringArgument("truststorepw", 'T',
+ OPTION_LONG_TRUSTSTORE_PWD,
+ false, false,
+ true, OPTION_VALUE_TRUSTSTORE_PWD, null,
+ null, MSGID_PWPSTATE_DESCRIPTION_TSPW);
+ argParser.addGlobalArgument(trustStorePW);
+
+ trustStorePWFile = new FileBasedArgument("truststorepwfile",
+ OPTION_SHORT_TRUSTSTORE_PWD_FILE,
+ OPTION_LONG_TRUSTSTORE_PWD_FILE,
+ false, false,
+ OPTION_VALUE_TRUSTSTORE_PWD_FILE, null, null,
+ MSGID_PWPSTATE_DESCRIPTION_TSPWFILE);
+ argParser.addGlobalArgument(trustStorePWFile);
+
+ showUsage = new BooleanArgument("showusage", OPTION_SHORT_HELP,
+ OPTION_LONG_HELP,
+ MSGID_PWPSTATE_DESCRIPTION_SHOWUSAGE);
+ argParser.addGlobalArgument(showUsage);
+ argParser.setUsageArgument(showUsage, out);
+
+
+ HashSet<String> booleanValues = new HashSet<String>(2);
+ booleanValues.add("true");
+ booleanValues.add("false");
+
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_ALL;
+ new SubCommand(argParser, SC_GET_ALL, msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_PASSWORD_POLICY_DN;
+ new SubCommand(argParser, SC_GET_PASSWORD_POLICY_DN, msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_ACCOUNT_DISABLED_STATE;
+ new SubCommand(argParser, SC_GET_ACCOUNT_DISABLED_STATE, msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_SET_ACCOUNT_DISABLED_STATE;
+ SubCommand sc = new SubCommand(argParser, SC_SET_ACCOUNT_DISABLED_STATE,
+ msgID);
+ sc.addArgument(new MultiChoiceArgument(ARG_OP_VALUE, 'O',
+ "operationValue", true, false, true,
+ "{true|false}", null, null, booleanValues, false,
+ MSGID_DESCRIPTION_OPERATION_BOOLEAN_VALUE));
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_CLEAR_ACCOUNT_DISABLED_STATE;
+ new SubCommand(argParser, SC_CLEAR_ACCOUNT_DISABLED_STATE, msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_ACCOUNT_EXPIRATION_TIME;
+ new SubCommand(argParser, SC_GET_ACCOUNT_EXPIRATION_TIME, msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_SET_ACCOUNT_EXPIRATION_TIME;
+ sc = new SubCommand(argParser, SC_SET_ACCOUNT_EXPIRATION_TIME, msgID);
+ sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
+ false, false, true, "{time}", null, null,
+ MSGID_DESCRIPTION_OPERATION_TIME_VALUE));
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_CLEAR_ACCOUNT_EXPIRATION_TIME;
+ sc = new SubCommand(argParser, SC_CLEAR_ACCOUNT_EXPIRATION_TIME, msgID);
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION;
+ new SubCommand(argParser, SC_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION, msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_PASSWORD_CHANGED_TIME;
+ new SubCommand(argParser, SC_GET_PASSWORD_CHANGED_TIME, msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_SET_PASSWORD_CHANGED_TIME;
+ sc = new SubCommand(argParser, SC_SET_PASSWORD_CHANGED_TIME, msgID);
+ sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
+ false, false, true, "{time}", null, null,
+ MSGID_DESCRIPTION_OPERATION_TIME_VALUE));
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_CLEAR_PASSWORD_CHANGED_TIME;
+ sc = new SubCommand(argParser, SC_CLEAR_PASSWORD_CHANGED_TIME, msgID);
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_PASSWORD_EXPIRATION_WARNED_TIME;
+ new SubCommand(argParser, SC_GET_PASSWORD_EXP_WARNED_TIME, msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_SET_PASSWORD_EXPIRATION_WARNED_TIME;
+ sc = new SubCommand(argParser, SC_SET_PASSWORD_EXP_WARNED_TIME, msgID);
+ sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
+ false, false, true, "{time}", null, null,
+ MSGID_DESCRIPTION_OPERATION_TIME_VALUE));
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_CLEAR_PASSWORD_EXPIRATION_WARNED_TIME;
+ sc = new SubCommand(argParser, SC_CLEAR_PASSWORD_EXP_WARNED_TIME, msgID);
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_PASSWORD_EXP;
+ new SubCommand(argParser, SC_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION,
+ msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_PASSWORD_EXP_WARNING;
+ new SubCommand(argParser,
+ SC_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING, msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_AUTH_FAILURE_TIMES;
+ new SubCommand(argParser, SC_GET_AUTHENTICATION_FAILURE_TIMES, msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_ADD_AUTH_FAILURE_TIME;
+ sc = new SubCommand(argParser, SC_ADD_AUTHENTICATION_FAILURE_TIME, msgID);
+ sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
+ false, true, true, "{time}", null, null,
+ MSGID_DESCRIPTION_OPERATION_TIME_VALUE));
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_SET_AUTH_FAILURE_TIMES;
+ sc = new SubCommand(argParser, SC_SET_AUTHENTICATION_FAILURE_TIMES,
+ msgID);
+ sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
+ false, true, true, "{time}", null, null,
+ MSGID_DESCRIPTION_OPERATION_TIME_VALUES));
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_CLEAR_AUTH_FAILURE_TIMES;
+ sc = new SubCommand(argParser, SC_CLEAR_AUTHENTICATION_FAILURE_TIMES,
+ msgID);
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_AUTH_FAILURE_UNLOCK;
+ new SubCommand(argParser,
+ SC_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK, msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_REMAINING_AUTH_FAILURE_COUNT;
+ new SubCommand(argParser, SC_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT,
+ msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_LAST_LOGIN_TIME;
+ new SubCommand(argParser, SC_GET_LAST_LOGIN_TIME, msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_SET_LAST_LOGIN_TIME;
+ sc = new SubCommand(argParser, SC_SET_LAST_LOGIN_TIME, msgID);
+ sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
+ false, false, true, "{time}", null, null,
+ MSGID_DESCRIPTION_OPERATION_TIME_VALUE));
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_CLEAR_LAST_LOGIN_TIME;
+ sc = new SubCommand(argParser, SC_CLEAR_LAST_LOGIN_TIME, msgID);
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_IDLE_LOCKOUT;
+ new SubCommand(argParser, SC_GET_SECONDS_UNTIL_IDLE_LOCKOUT, msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_PASSWORD_RESET_STATE;
+ new SubCommand(argParser, SC_GET_PASSWORD_RESET_STATE, msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_SET_PASSWORD_RESET_STATE;
+ sc = new SubCommand(argParser, SC_SET_PASSWORD_RESET_STATE, msgID);
+ sc.addArgument(new MultiChoiceArgument(ARG_OP_VALUE, 'O',
+ "operationValue", true, false, true,
+ "{true|false}", null, null, booleanValues, false,
+ MSGID_DESCRIPTION_OPERATION_BOOLEAN_VALUE));
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_CLEAR_PASSWORD_RESET_STATE;
+ sc = new SubCommand(argParser, SC_CLEAR_PASSWORD_RESET_STATE, msgID);
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_RESET_LOCKOUT;
+ new SubCommand(argParser, SC_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT,
+ msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_GRACE_LOGIN_USE_TIMES;
+ new SubCommand(argParser, SC_GET_GRACE_LOGIN_USE_TIMES, msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_ADD_GRACE_LOGIN_USE_TIME;
+ sc = new SubCommand(argParser, SC_ADD_GRACE_LOGIN_USE_TIME, msgID);
+ sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
+ false, true, true, "{time}", null, null,
+ MSGID_DESCRIPTION_OPERATION_TIME_VALUE));
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_SET_GRACE_LOGIN_USE_TIMES;
+ sc = new SubCommand(argParser, SC_SET_GRACE_LOGIN_USE_TIMES, msgID);
+ sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
+ false, true, true, "{time}", null, null,
+ MSGID_DESCRIPTION_OPERATION_TIME_VALUES));
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_CLEAR_GRACE_LOGIN_USE_TIMES;
+ sc = new SubCommand(argParser, SC_CLEAR_GRACE_LOGIN_USE_TIMES, msgID);
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_REMAINING_GRACE_LOGIN_COUNT;
+ new SubCommand(argParser, SC_GET_REMAINING_GRACE_LOGIN_COUNT,
+ msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_PW_CHANGED_BY_REQUIRED_TIME;
+ new SubCommand(argParser, SC_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME,
+ msgID);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_SET_PW_CHANGED_BY_REQUIRED_TIME;
+ sc = new SubCommand(argParser, SC_SET_PASSWORD_CHANGED_BY_REQUIRED_TIME,
+ msgID);
+ sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
+ false, false, true, "{time}", null, null,
+ MSGID_DESCRIPTION_OPERATION_TIME_VALUE));
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_CLEAR_PW_CHANGED_BY_REQUIRED_TIME;
+ sc = new SubCommand(argParser, SC_CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME,
+ msgID);
+ sc.setHidden(true);
+
+ msgID = MSGID_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME;
+ new SubCommand(argParser, SC_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME,
+ msgID);
+ }
+ catch (ArgumentException ae)
+ {
+ msgID = MSGID_CANNOT_INITIALIZE_ARGS;
+ String message = getMessage(msgID, ae.getMessage());
+
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ return LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR;
+ }
+
+ try
+ {
+ argParser.parseArguments(args);
+ }
+ catch (ArgumentException ae)
+ {
+ msgID = MSGID_ERROR_PARSING_ARGS;
+ String message = getMessage(msgID, ae.getMessage());
+
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ err.println(argParser.getUsage());
+ return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
+ }
+
+
+ // If we should just display usage or version information,
+ // then exit because it will have already been done.
+ if (argParser.usageOrVersionDisplayed())
+ {
+ return -1;
+ }
+
+
+ // Get the target DN as a string for later use.
+ targetDNString = targetDN.getValue();
+
+
+ // Create the LDAP connection options object, which will be used to
+ // customize the way that we connect to the server and specify a set of
+ // basic defaults.
+ LDAPConnectionOptions connectionOptions = new LDAPConnectionOptions();
+ connectionOptions.setVersionNumber(3);
+
+
+ // See if we should use SSL or StartTLS when establishing the connection.
+ // If so, then make sure only one of them was specified.
+ if (useSSL.isPresent())
+ {
+ if (useStartTLS.isPresent())
+ {
+ msgID = MSGID_PWPSTATE_MUTUALLY_EXCLUSIVE_ARGUMENTS;
+ String message = getMessage(msgID, useSSL.getLongIdentifier(),
+ useStartTLS.getLongIdentifier());
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
+ }
+ else
+ {
+ connectionOptions.setUseSSL(true);
+ }
+ }
+ else if (useStartTLS.isPresent())
+ {
+ connectionOptions.setStartTLS(true);
+ }
+
+
+ // If we should blindly trust any certificate, then install the appropriate
+ // SSL connection factory.
+ if (useSSL.isPresent() || useStartTLS.isPresent())
+ {
+ try
+ {
+ String clientAlias;
+ if (certNickname.isPresent())
+ {
+ clientAlias = certNickname.getValue();
+ }
+ else
+ {
+ clientAlias = null;
+ }
+
+ SSLConnectionFactory sslConnectionFactory = new SSLConnectionFactory();
+ sslConnectionFactory.init(trustAll.isPresent(), keyStoreFile.getValue(),
+ keyStorePW.getValue(), clientAlias,
+ trustStoreFile.getValue(),
+ trustStorePW.getValue());
+
+ connectionOptions.setSSLConnectionFactory(sslConnectionFactory);
+ }
+ catch (SSLConnectionException sce)
+ {
+ msgID = MSGID_PWPSTATE_CANNOT_INITIALIZE_SSL;
+ String message = getMessage(msgID, sce.getMessage());
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ return LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR;
+ }
+ }
+
+
+ // If one or more SASL options were provided, then make sure that one of
+ // them was "mech" and specified a valid SASL mechanism.
+ if (saslOption.isPresent())
+ {
+ String mechanism = null;
+ LinkedList<String> options = new LinkedList<String>();
+
+ for (String s : saslOption.getValues())
+ {
+ int equalPos = s.indexOf('=');
+ if (equalPos <= 0)
+ {
+ msgID = MSGID_PWPSTATE_CANNOT_PARSE_SASL_OPTION;
+ String message = getMessage(msgID, s);
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
+ }
+ else
+ {
+ String name = s.substring(0, equalPos);
+
+ if (name.equalsIgnoreCase("mech"))
+ {
+ mechanism = s;
+ }
+ else
+ {
+ options.add(s);
+ }
+ }
+ }
+
+ if (mechanism == null)
+ {
+ msgID = MSGID_PWPSTATE_NO_SASL_MECHANISM;
+ String message = getMessage(msgID);
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
+ }
+
+ connectionOptions.setSASLMechanism(mechanism);
+
+ for (String option : options)
+ {
+ connectionOptions.addSASLProperty(option);
+ }
+ }
+
+
+ // Attempt to connect and authenticate to the Directory Server.
+ nextMessageID = new AtomicInteger(1);
+ try
+ {
+ connection = new LDAPConnection(host.getValue(), port.getIntValue(),
+ connectionOptions, out, err);
+ connection.connectToHost(bindDN.getValue(), bindPW.getValue(),
+ nextMessageID);
+ }
+ catch (ArgumentException ae)
+ {
+ msgID = MSGID_PWPSTATE_CANNOT_DETERMINE_PORT;
+ String message = getMessage(msgID, port.getLongIdentifier(),
+ ae.getMessage());
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
+ }
+ catch (LDAPConnectionException lce)
+ {
+ msgID = MSGID_PWPSTATE_CANNOT_CONNECT;
+ String message = getMessage(msgID, lce.getMessage());
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ return LDAPResultCode.CLIENT_SIDE_CONNECT_ERROR;
+ }
+
+ asn1Reader = connection.getASN1Reader();
+ asn1Writer = connection.getASN1Writer();
+
+ return LDAPResultCode.SUCCESS;
+ }
+
+
+
+ /**
+ * Processes the subcommand from the provided argument parser and appends the
+ * appropriate operation elements to the given list.
+ *
+ * @param opElements A list into which the operation elements shouold be
+ * placed.
+ *
+ * @return A result code indicating the results of the processing.
+ */
+ private static int processSubcommand(ArrayList<ASN1Element> opElements)
+ {
+ int msgID;
+ SubCommand subCommand = argParser.getSubCommand();
+ if (subCommand == null)
+ {
+ msgID = MSGID_PWPSTATE_NO_SUBCOMMAND;
+ String message = getMessage(msgID);
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ err.println(argParser.getUsage());
+ return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
+ }
+
+ String subCommandName = subCommand.getName();
+ if (subCommandName.equals(SC_GET_ALL))
+ {
+ // The list should stay empty for this one.
+ }
+ else if (subCommandName.equals(SC_GET_PASSWORD_POLICY_DN))
+ {
+ opElements.add(encode(OP_GET_PASSWORD_POLICY_DN, NO_VALUE));
+ }
+ else if (subCommandName.equals(SC_GET_ACCOUNT_DISABLED_STATE))
+ {
+ opElements.add(encode(OP_GET_ACCOUNT_DISABLED_STATE, NO_VALUE));
+ }
+ else if (subCommandName.equals(SC_SET_ACCOUNT_DISABLED_STATE))
+ {
+ Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
+ if ((a != null) && a.isPresent())
+ {
+ String valueStr = a.getValue();
+ if (valueStr.equalsIgnoreCase("true"))
+ {
+ opElements.add(encode(OP_SET_ACCOUNT_DISABLED_STATE, "true"));
+ }
+ else if (valueStr.equalsIgnoreCase("false"))
+ {
+ opElements.add(encode(OP_SET_ACCOUNT_DISABLED_STATE, "false"));
+ }
+ else
+ {
+ msgID = MSGID_PWPSTATE_INVALID_BOOLEAN_VALUE;
+ String message = getMessage(msgID, valueStr);
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
+ }
+ }
+ else
+ {
+ msgID = MSGID_PWPSTATE_NO_BOOLEAN_VALUE;
+ String message = getMessage(msgID);
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
+ }
+ }
+ else if (subCommandName.equals(SC_CLEAR_ACCOUNT_DISABLED_STATE))
+ {
+ opElements.add(encode(OP_CLEAR_ACCOUNT_DISABLED_STATE, NO_VALUE));
+ }
+ else if (subCommandName.equals(SC_GET_ACCOUNT_EXPIRATION_TIME))
+ {
+ opElements.add(encode(OP_GET_ACCOUNT_EXPIRATION_TIME, NO_VALUE));
+ }
+ else if (subCommandName.equals(SC_SET_ACCOUNT_EXPIRATION_TIME))
+ {
+ Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
+ if ((a != null) && a.isPresent())
+ {
+ opElements.add(encode(OP_SET_ACCOUNT_EXPIRATION_TIME, a.getValue()));
+ }
+ else
+ {
+ opElements.add(encode(OP_SET_ACCOUNT_EXPIRATION_TIME, NO_VALUE));
+ }
+ }
+ else if (subCommandName.equals(SC_CLEAR_ACCOUNT_EXPIRATION_TIME))
+ {
+ opElements.add(encode(OP_CLEAR_ACCOUNT_EXPIRATION_TIME, NO_VALUE));
+ }
+ else if (subCommandName.equals(SC_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION))
+ {
+ opElements.add(encode(OP_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION, NO_VALUE));
+ }
+ else if (subCommandName.equals(SC_GET_PASSWORD_CHANGED_TIME))
+ {
+ opElements.add(encode(OP_GET_PASSWORD_CHANGED_TIME, NO_VALUE));
+ }
+ else if (subCommandName.equals(SC_SET_PASSWORD_CHANGED_TIME))
+ {
+ Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
+ if ((a != null) && a.isPresent())
+ {
+ opElements.add(encode(OP_SET_PASSWORD_CHANGED_TIME, a.getValue()));
+ }
+ else
+ {
+ opElements.add(encode(OP_SET_PASSWORD_CHANGED_TIME, NO_VALUE));
+ }
+ }
+ else if (subCommandName.equals(SC_CLEAR_PASSWORD_CHANGED_TIME))
+ {
+ opElements.add(encode(OP_CLEAR_PASSWORD_CHANGED_TIME, NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_GET_PASSWORD_EXP_WARNED_TIME))
+ {
+ opElements.add(encode(OP_GET_PASSWORD_EXPIRATION_WARNED_TIME, NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_SET_PASSWORD_EXP_WARNED_TIME))
+ {
+ Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
+ if ((a != null) && a.isPresent())
+ {
+ opElements.add(encode(OP_SET_PASSWORD_EXPIRATION_WARNED_TIME,
+ a.getValue()));
+ }
+ else
+ {
+ opElements.add(encode(OP_SET_PASSWORD_EXPIRATION_WARNED_TIME,
+ NO_VALUE));
+ }
+ }
+ else if(subCommandName.equals(SC_CLEAR_PASSWORD_EXP_WARNED_TIME))
+ {
+ opElements.add(encode(OP_CLEAR_PASSWORD_EXPIRATION_WARNED_TIME,
+ NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION))
+ {
+ opElements.add(encode(OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION,
+ NO_VALUE));
+ }
+ else if(subCommandName.equals(
+ SC_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING))
+ {
+ opElements.add(encode(OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING,
+ NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_GET_AUTHENTICATION_FAILURE_TIMES))
+ {
+ opElements.add(encode(OP_GET_AUTHENTICATION_FAILURE_TIMES, NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_ADD_AUTHENTICATION_FAILURE_TIME))
+ {
+ Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
+ if ((a != null) && a.isPresent())
+ {
+ opElements.add(encode(OP_ADD_AUTHENTICATION_FAILURE_TIME,
+ a.getValue()));
+ }
+ else
+ {
+ opElements.add(encode(OP_ADD_AUTHENTICATION_FAILURE_TIME, NO_VALUE));
+ }
+ }
+ else if(subCommandName.equals(SC_SET_AUTHENTICATION_FAILURE_TIMES))
+ {
+ Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
+ if ((a != null) && a.isPresent())
+ {
+ ArrayList<String> valueList = new ArrayList<String>(a.getValues());
+ String[] values = new String[valueList.size()];
+ valueList.toArray(values);
+
+ opElements.add(encode(OP_SET_AUTHENTICATION_FAILURE_TIMES, values));
+ }
+ else
+ {
+ opElements.add(encode(OP_SET_AUTHENTICATION_FAILURE_TIMES, NO_VALUE));
+ }
+ }
+ else if(subCommandName.equals(SC_CLEAR_AUTHENTICATION_FAILURE_TIMES))
+ {
+ opElements.add(encode(OP_CLEAR_AUTHENTICATION_FAILURE_TIMES, NO_VALUE));
+ }
+ else if(subCommandName.equals(
+ SC_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK))
+ {
+ opElements.add(encode(OP_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK,
+ NO_VALUE));
+ }
+ else if(subCommandName.equals(
+ SC_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT))
+ {
+ opElements.add(encode(OP_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT,
+ NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_GET_LAST_LOGIN_TIME))
+ {
+ opElements.add(encode(OP_GET_LAST_LOGIN_TIME, NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_SET_LAST_LOGIN_TIME))
+ {
+ Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
+ if ((a != null) && a.isPresent())
+ {
+ opElements.add(encode(OP_SET_LAST_LOGIN_TIME, a.getValue()));
+ }
+ else
+ {
+ opElements.add(encode(OP_SET_LAST_LOGIN_TIME, NO_VALUE));
+ }
+ }
+ else if(subCommandName.equals(SC_CLEAR_LAST_LOGIN_TIME))
+ {
+ opElements.add(encode(OP_CLEAR_LAST_LOGIN_TIME, NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_GET_SECONDS_UNTIL_IDLE_LOCKOUT))
+ {
+ opElements.add(encode(OP_GET_SECONDS_UNTIL_IDLE_LOCKOUT, NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_GET_PASSWORD_RESET_STATE))
+ {
+ opElements.add(encode(OP_GET_PASSWORD_RESET_STATE, NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_SET_PASSWORD_RESET_STATE))
+ {
+ Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
+ if ((a != null) && a.isPresent())
+ {
+ String valueStr = a.getValue();
+ if (valueStr.equalsIgnoreCase("true"))
+ {
+ opElements.add(encode(OP_SET_PASSWORD_RESET_STATE, "true"));
+ }
+ else if (valueStr.equalsIgnoreCase("false"))
+ {
+ opElements.add(encode(OP_SET_PASSWORD_RESET_STATE, "false"));
+ }
+ else
+ {
+ msgID = MSGID_PWPSTATE_INVALID_BOOLEAN_VALUE;
+ String message = getMessage(msgID, valueStr);
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
+ }
+ }
+ else
+ {
+ msgID = MSGID_PWPSTATE_NO_BOOLEAN_VALUE;
+ String message = getMessage(msgID);
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
+ }
+ }
+ else if(subCommandName.equals(SC_CLEAR_PASSWORD_RESET_STATE))
+ {
+ opElements.add(encode(OP_GET_PASSWORD_RESET_STATE, NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT))
+ {
+ opElements.add(encode(OP_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT,
+ NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_GET_GRACE_LOGIN_USE_TIMES))
+ {
+ opElements.add(encode(OP_GET_GRACE_LOGIN_USE_TIMES, NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_ADD_GRACE_LOGIN_USE_TIME))
+ {
+ Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
+ if ((a != null) && a.isPresent())
+ {
+ opElements.add(encode(OP_ADD_GRACE_LOGIN_USE_TIME, a.getValue()));
+ }
+ else
+ {
+ opElements.add(encode(OP_ADD_GRACE_LOGIN_USE_TIME, NO_VALUE));
+ }
+ }
+ else if(subCommandName.equals(SC_SET_GRACE_LOGIN_USE_TIMES))
+ {
+ Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
+ if ((a != null) && a.isPresent())
+ {
+ ArrayList<String> valueList = new ArrayList<String>(a.getValues());
+ String[] values = new String[valueList.size()];
+ valueList.toArray(values);
+
+ opElements.add(encode(OP_SET_GRACE_LOGIN_USE_TIMES, values));
+ }
+ else
+ {
+ opElements.add(encode(OP_SET_GRACE_LOGIN_USE_TIMES, NO_VALUE));
+ }
+ }
+ else if(subCommandName.equals(SC_CLEAR_GRACE_LOGIN_USE_TIMES))
+ {
+ opElements.add(encode(OP_CLEAR_GRACE_LOGIN_USE_TIMES, NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_GET_REMAINING_GRACE_LOGIN_COUNT))
+ {
+ opElements.add(encode(OP_GET_REMAINING_GRACE_LOGIN_COUNT, NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME))
+ {
+ opElements.add(encode(OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME,
+ NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_SET_PASSWORD_CHANGED_BY_REQUIRED_TIME))
+ {
+ Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
+ if ((a != null) && a.isPresent())
+ {
+ opElements.add(encode(OP_SET_PASSWORD_CHANGED_BY_REQUIRED_TIME,
+ a.getValue()));
+ }
+ else
+ {
+ opElements.add(encode(OP_SET_PASSWORD_CHANGED_BY_REQUIRED_TIME,
+ NO_VALUE));
+ }
+ }
+ else if(subCommandName.equals(SC_CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME))
+ {
+ opElements.add(encode(OP_CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME,
+ NO_VALUE));
+ }
+ else if(subCommandName.equals(SC_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME))
+ {
+ opElements.add(encode(OP_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME,
+ NO_VALUE));
+ }
+ else
+ {
+ msgID = MSGID_PWPSTATE_INVALID_SUBCOMMAND;
+ String message = getMessage(msgID, subCommandName);
+ err.println(wrapText(message, MAX_LINE_WIDTH));
+ err.println(argParser.getUsage());
+ return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
+ }
+
+ return LDAPResultCode.SUCCESS;
+ }
+
+
+
+ /**
+ * Prints information about a password policy state variable to standard
+ * output.
+ *
+ * @param msgID The message ID for the message to use as the label.
+ * @param values The set of values for the associated state variable.
+ */
+ private static void printLabelAndValues(int msgID, ArrayList<String> values)
+ {
+ String label = getMessage(msgID);
+ if ((values == null) || values.isEmpty())
+ {
+ out.print(label);
+ out.println(":");
+ }
+ else
+ {
+ for (String value : values)
+ {
+ out.print(label);
+ out.print(": ");
+ out.println(value);
+ }
+ }
+ }
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java b/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
index 52d9ae1..0db5653 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
@@ -695,6 +695,15 @@
/**
+ * The OID for the password policy state extended operation (both the request
+ * and response types).
+ */
+ public static final String OID_PASSWORD_POLICY_STATE_EXTOP =
+ "1.3.6.1.4.1.26027.1.6.1";
+
+
+
+ /**
* The request OID for the StartTLS extended operation.
*/
public static final String OID_START_TLS_REQUEST = "1.3.6.1.4.1.1466.20037";
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/PasswordPolicyTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/PasswordPolicyTestCase.java
index 17f4068..6384d01 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/PasswordPolicyTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/PasswordPolicyTestCase.java
@@ -45,6 +45,7 @@
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.protocols.internal.InternalClientConnection;
+import org.opends.server.tools.LDAPModify;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
@@ -4742,6 +4743,85 @@
/**
+ * Tests the ability of a user to bind to the server when their account
+ * includes the pwdReset operational attribute and last login time tracking is
+ * enabled.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testResetWithLastLoginTime()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: oldpassword",
+ "ds-privilege-name: bypass-acl"
+ );
+
+ try
+ {
+ TestCaseUtils.applyModifications(
+ "dn: cn=Default Password Policy,cn=Password Policies,cn=config",
+ "changetype: modify",
+ "replace: ds-cfg-force-change-on-reset",
+ "ds-cfg-force-change-on-reset: true",
+ "-",
+ "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",
+ "",
+ "dn: uid=test.user,o=test",
+ "changetype: modify",
+ "replace: userPassword",
+ "userPassword: newpassword");
+
+ String path = TestCaseUtils.createTempFile(
+ "dn: uid=test.user,o=test",
+ "changetype: modify",
+ "replace: userPassword",
+ "userPassword: newnewpassword"
+ );
+
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "uid=test.user,o=test",
+ "-w", "newpassword",
+ "-f", path
+ };
+
+ assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
+ }
+ finally
+ {
+ TestCaseUtils.applyModifications(
+ "dn: cn=Default Password Policy,cn=Password Policies,cn=config",
+ "changetype: modify",
+ "replace: ds-cfg-force-change-on-reset",
+ "ds-cfg-force-change-on-reset: false",
+ "-",
+ "replace: ds-cfg-last-login-time-attribute",
+ "-",
+ "replace: ds-cfg-last-login-time-format");
+ }
+ }
+
+
+
+ /**
* Tests the <CODE>toString</CODE> methods with the default password policy.
*/
@Test()
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/ManageAccountTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/ManageAccountTestCase.java
new file mode 100644
index 0000000..0ca38f2
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/ManageAccountTestCase.java
@@ -0,0 +1,871 @@
+/*
+ * 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.tools;
+
+
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import org.opends.server.TestCaseUtils;
+import org.opends.server.schema.GeneralizedTimeSyntax;
+
+import static org.testng.Assert.*;
+
+
+
+/**
+ * A set of test cases for the ManageAccount tool.
+ */
+public class ManageAccountTestCase
+ extends ToolsTestCase
+{
+ /**
+ * Ensures that the Directory Server is running before starting any of the
+ * tests.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ public void startServer()
+ throws Exception
+ {
+ TestCaseUtils.startServer();
+ }
+
+
+
+ /**
+ * Retrieves the names of all of all the subcommands available for use with
+ * the manage-account tool.
+ *
+ * @return The names of all of the subcommands available for use with the
+ * manage-account tool.
+ */
+ @DataProvider(name = "allSubCommands")
+ public Object[][] getAllSubCommands()
+ {
+ return new Object[][]
+ {
+ new Object[] { "get-all" },
+ new Object[] { "get-password-policy-dn" },
+ new Object[] { "get-account-is-disabled" },
+ new Object[] { "set-account-is-disabled" },
+ new Object[] { "clear-account-is-disabled" },
+ new Object[] { "get-account-expiration-time" },
+ new Object[] { "set-account-expiration-time" },
+ new Object[] { "clear-account-expiration-time" },
+ new Object[] { "get-seconds-until-account-expiration" },
+ new Object[] { "get-password-changed-time" },
+ new Object[] { "set-password-changed-time" },
+ new Object[] { "clear-password-changed-time" },
+ new Object[] { "get-password-expiration-warned-time" },
+ new Object[] { "set-password-expiration-warned-time" },
+ new Object[] { "clear-password-expiration-warned-time" },
+ new Object[] { "get-seconds-until-password-expiration" },
+ new Object[] { "get-seconds-until-password-expiration-warning" },
+ new Object[] { "get-authentication-failure-times" },
+ new Object[] { "add-authentication-failure-time" },
+ new Object[] { "set-authentication-failure-times" },
+ new Object[] { "clear-authentication-failure-times" },
+ new Object[] { "get-seconds-until-authentication-failure-unlock" },
+ new Object[] { "get-remaining-authentication-failure-count" },
+ new Object[] { "get-last-login-time" },
+ new Object[] { "set-last-login-time" },
+ new Object[] { "clear-last-login-time" },
+ new Object[] { "get-seconds-until-idle-lockout" },
+ new Object[] { "get-password-is-reset" },
+ new Object[] { "set-password-is-reset" },
+ new Object[] { "clear-password-is-reset" },
+ new Object[] { "get-seconds-until-password-reset-lockout" },
+ new Object[] { "get-grace-login-use-times" },
+ new Object[] { "add-grace-login-use-time" },
+ new Object[] { "set-grace-login-use-times" },
+ new Object[] { "clear-grace-login-use-times" },
+ new Object[] { "get-remaining-grace-login-count" },
+ new Object[] { "get-password-changed-by-required-time" },
+ new Object[] { "set-password-changed-by-required-time" },
+ new Object[] { "clear-password-changed-by-required-time" },
+ new Object[] { "get-seconds-until-required-change-time" }
+ };
+ }
+
+
+
+ /**
+ * Retrieves the names of all of the subcommands used for performing "get"
+ * operations.
+ *
+ * @return The names of all of the subcommands used for performing "get"
+ * operations.
+ */
+ @DataProvider(name = "getSubCommands")
+ public Object[][] getGetSubCommands()
+ {
+ return new Object[][]
+ {
+ new Object[] { "get-all" },
+ new Object[] { "get-password-policy-dn" },
+ new Object[] { "get-account-is-disabled" },
+ new Object[] { "get-account-expiration-time" },
+ new Object[] { "get-seconds-until-account-expiration" },
+ new Object[] { "get-password-changed-time" },
+ new Object[] { "get-password-expiration-warned-time" },
+ new Object[] { "get-seconds-until-password-expiration" },
+ new Object[] { "get-seconds-until-password-expiration-warning" },
+ new Object[] { "get-authentication-failure-times" },
+ new Object[] { "get-seconds-until-authentication-failure-unlock" },
+ new Object[] { "get-remaining-authentication-failure-count" },
+ new Object[] { "get-last-login-time" },
+ new Object[] { "get-seconds-until-idle-lockout" },
+ new Object[] { "get-password-is-reset" },
+ new Object[] { "get-seconds-until-password-reset-lockout" },
+ new Object[] { "get-grace-login-use-times" },
+ new Object[] { "get-remaining-grace-login-count" },
+ new Object[] { "get-password-changed-by-required-time" },
+ new Object[] { "get-seconds-until-required-change-time" }
+ };
+ }
+
+
+
+ /**
+ * Retrieves the names of the subcommands that may be used to set a Boolean
+ * value in the user's password policy state.
+ *
+ * @return The names of all of the subcommands that may be used to set a
+ * Boolean value in the user's password policy state.
+ */
+ @DataProvider(name = "setBooleanSubCommands")
+ public Object[][] getSetBooleanSubCommands()
+ {
+ return new Object[][]
+ {
+ new Object[] { "set-account-is-disabled" },
+ new Object[] { "set-password-is-reset" },
+ };
+ }
+
+
+
+ /**
+ * Retrieves the names of the subcommands that may be used to set time value
+ * in the user's password policy state. This will also include the
+ * subcommands that may be used to add a value to a multivalued property.
+ *
+ * @return The names of all of the subcommands that may be used to set a
+ * time value in the user's password policy state.
+ */
+ @DataProvider(name = "setTimeSubCommands")
+ public Object[][] getSetTimeSubCommands()
+ {
+ return new Object[][]
+ {
+ new Object[] { "set-account-expiration-time" },
+ new Object[] { "set-password-changed-time" },
+ new Object[] { "set-password-expiration-warned-time" },
+ new Object[] { "set-authentication-failure-times" },
+ new Object[] { "add-authentication-failure-time" },
+ new Object[] { "set-last-login-time" },
+ new Object[] { "set-grace-login-use-times" },
+ new Object[] { "add-grace-login-use-time" },
+ new Object[] { "set-password-changed-by-required-time" },
+ };
+ }
+
+
+
+ /**
+ * Retrieves the names of all of all the subcommands that may be used to clear
+ * some part of the password policy state.
+ *
+ * @return The names of all of the subcommands that may be used to clear some
+ * part of the password policy state.
+ */
+ @DataProvider(name = "clearSubCommands")
+ public Object[][] clearAllSubCommands()
+ {
+ return new Object[][]
+ {
+ new Object[] { "clear-account-is-disabled" },
+ new Object[] { "clear-account-expiration-time" },
+ new Object[] { "clear-password-changed-time" },
+ new Object[] { "clear-password-expiration-warned-time" },
+ new Object[] { "clear-authentication-failure-times" },
+ new Object[] { "clear-last-login-time" },
+ new Object[] { "clear-password-is-reset" },
+ new Object[] { "clear-grace-login-use-times" },
+ new Object[] { "clear-password-changed-by-required-time" }
+ };
+ }
+
+
+
+ /**
+ * Tests the various sets of arguments that may be used to get usage
+ * information when no subcommand is given.
+ */
+ @Test()
+ public void testHelpNoSubCommand()
+ {
+ assertEquals(ManageAccount.main(new String[] { "-H" }, null, System.err),
+ 0);
+ assertEquals(ManageAccount.main(new String[] { "--help" }, null,
+ System.err),
+ 0);
+ assertEquals(ManageAccount.main(new String[] { "-?" }, null, System.err),
+ 0);
+ }
+
+
+
+ /**
+ * Tests the various sets of arguments that may be used to get usage
+ * information when a subcommand is given.
+ *
+ * @param subCommand The subcommand to use in the test.
+ */
+ @Test(dataProvider="allSubCommands")
+ public void testHelpWithSubCommand(String subCommand)
+ {
+ String[] args =
+ {
+ subCommand,
+ "--help"
+ };
+
+ assertEquals(ManageAccount.main(args, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests the manage-account tool without any subcommand.
+ */
+ @Test()
+ public void testNoSubCommand()
+ {
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-b", "uid=test.user,o=test"
+ };
+
+ assertFalse(ManageAccount.main(args, null, null) == 0);
+ }
+
+
+
+ /**
+ * Tests the manage-account tool with an invalid subcommand.
+ */
+ @Test()
+ public void testInvalidSubCommand()
+ {
+ String[] args =
+ {
+ "invalid-subcommand",
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-b", "uid=test.user,o=test"
+ };
+
+ assertFalse(ManageAccount.main(args, null, null) == 0);
+ }
+
+
+
+ /**
+ * Tests an attempt to use the manage-account tool as an anonymous user.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ public void testAnonymousUser()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password"
+ );
+
+ String[] args =
+ {
+ "get-all",
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "",
+ "-w", "",
+ "-b", "uid=test.user,o=test"
+ };
+
+ assertFalse(ManageAccount.main(args, null, System.err) == 0);
+ }
+
+
+
+ /**
+ * Tests an attempt to use the manage-account tool as an unprivileged user.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ public void testUnprivilegedUser()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password"
+ );
+
+ String[] args =
+ {
+ "get-all",
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "uid=test.user,o=test",
+ "-w", "password",
+ "-b", "uid=test.user,o=test"
+ };
+
+ assertFalse(ManageAccount.main(args, null, System.err) == 0);
+ }
+
+
+
+ /**
+ * Tests the ability to use the manage-account tool when using SSL.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ public void testUsingSSL()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password"
+ );
+
+ String[] args =
+ {
+ "get-all",
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()),
+ "-Z",
+ "-X",
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-b", "uid=test.user,o=test"
+ };
+
+ assertEquals(ManageAccount.main(args, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests the ability to use the manage-account tool when using StartTLS.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ public void testUsingStartTLS()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password"
+ );
+
+ String[] args =
+ {
+ "get-all",
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-q",
+ "-X",
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-b", "uid=test.user,o=test"
+ };
+
+ assertEquals(ManageAccount.main(args, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests the ability to use the manage-account tool when using SASL
+ * authentication.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ public void testUsingSASL()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password"
+ );
+
+ String[] args =
+ {
+ "get-all",
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-o", "mech=PLAIN",
+ "-o", "authid=dn:cn=Directory Manager",
+ "-w", "password",
+ "-b", "uid=test.user,o=test"
+ };
+
+ assertEquals(ManageAccount.main(args, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the various "get" subcommands work without throwing
+ * exceptions or returning unexpected results.
+ *
+ * @param subCommand The name of the "get" subcommand to invoke.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider="getSubCommands")
+ public void testGetSubCommands(String subCommand)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password"
+ );
+
+ String[] args =
+ {
+ subCommand,
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-b", "uid=test.user,o=test",
+ };
+
+ assertEquals(ManageAccount.main(args, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the various "get" subcommands fail when provided with
+ * a value.
+ *
+ * @param subCommand The name of the "get" subcommand to invoke.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider="getSubCommands")
+ public void testGetSubCommandsWithValue(String subCommand)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password"
+ );
+
+ String[] args =
+ {
+ subCommand,
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-b", "uid=test.user,o=test",
+ "-O", "not-appropriate-for-this-subcommand"
+ };
+
+ assertFalse(ManageAccount.main(args, null, System.err) == 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the various "set" subcommands that take Boolean
+ * arguments work properly when given a value of "true".
+ *
+ * @param subCommand The name of the "set" subcommand to invoke.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider="setBooleanSubCommands")
+ public void testSetBooleanSubCommandsTrue(String subCommand)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password"
+ );
+
+ String[] args =
+ {
+ subCommand,
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-b", "uid=test.user,o=test",
+ "-O", "true"
+ };
+
+ assertEquals(ManageAccount.main(args, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the various "set" subcommands that take Boolean
+ * arguments work properly when given a value of "false".
+ *
+ * @param subCommand The name of the "set" subcommand to invoke.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider="setBooleanSubCommands")
+ public void testSetBooleanSubCommandsFalse(String subCommand)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password"
+ );
+
+ String[] args =
+ {
+ subCommand,
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-b", "uid=test.user,o=test",
+ "-O", "false"
+ };
+
+ assertEquals(ManageAccount.main(args, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the various "set" subcommands that take Boolean
+ * arguments work properly when given a non-Boolean value.
+ *
+ * @param subCommand The name of the "set" subcommand to invoke.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider="setBooleanSubCommands")
+ public void testSetBooleanSubCommandsNonBooleanValue(String subCommand)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password"
+ );
+
+ String[] args =
+ {
+ subCommand,
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-b", "uid=test.user,o=test",
+ "-O", "nonboolean"
+ };
+
+ assertFalse(ManageAccount.main(args, null, System.err) == 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the various "set" subcommands that take timestamp
+ * arguments work properly when used without any value.
+ *
+ * @param subCommand The name of the "set" subcommand to invoke.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider="setTimeSubCommands")
+ public void testSetTimeSubCommandsNoValue(String subCommand)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password"
+ );
+
+ String[] args =
+ {
+ subCommand,
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-b", "uid=test.user,o=test"
+ };
+
+ assertEquals(ManageAccount.main(args, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the various "set" subcommands that take timestamp
+ * arguments work properly when used with a value equal to the current time.
+ *
+ * @param subCommand The name of the "set" subcommand to invoke.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider="setTimeSubCommands")
+ public void testSetTimeSubCommandsCurrentTime(String subCommand)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password"
+ );
+
+ String[] args =
+ {
+ subCommand,
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-b", "uid=test.user,o=test",
+ "-O", GeneralizedTimeSyntax.format(System.currentTimeMillis())
+ };
+
+ assertEquals(ManageAccount.main(args, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the various "set" subcommands that take timestamp
+ * arguments work properly when used with an invalid value.
+ *
+ * @param subCommand The name of the "set" subcommand to invoke.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider="setTimeSubCommands")
+ public void testSetTimeSubCommandsInvalidTime(String subCommand)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password"
+ );
+
+ String[] args =
+ {
+ subCommand,
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-b", "uid=test.user,o=test",
+ "-O", "invalid"
+ };
+
+ assertFalse(ManageAccount.main(args, null, System.err) == 0);
+ }
+
+
+
+ /**
+ * Tests to ensure that the various "clear" subcommands work without throwing
+ * exceptions or returning unexpected results.
+ *
+ * @param subCommand The name of the "clear" subcommand to invoke.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider="clearSubCommands")
+ public void testClearSubCommands(String subCommand)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.addEntry(
+ "dn: uid=test.user,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password"
+ );
+
+ String[] args =
+ {
+ subCommand,
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-b", "uid=test.user,o=test",
+ };
+
+ assertEquals(ManageAccount.main(args, null, System.err), 0);
+ }
+}
+
--
Gitblit v1.10.0