throws DirectoryException
{
// FIXME -- We need to check to see if the password policy subentry
// might be specified virtually rather than as a real
// attribute.
PasswordPolicy passwordPolicy = null;
List<Attribute> pwAttrList =
entry.getAttribute(OP_ATTR_PWPOLICY_POLICY_DN);
if ((pwAttrList != null) && (! pwAttrList.isEmpty()))
{
Attribute a = pwAttrList.get(0);
Iterator<AttributeValue> iterator = a.iterator();
if (iterator.hasNext())
{
DN policyDN;
try
{
policyDN = DN.decode(iterator.next().getValue());
}
catch (DirectoryException de)
{
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, de);
}
throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
ERR_ADD_INVALID_PWPOLICY_DN_SYNTAX.get(
String.valueOf(entryDN),
de.getMessageObject()));
}
passwordPolicy = DirectoryServer.getPasswordPolicy(policyDN);
if (passwordPolicy == null)
{
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
ERR_ADD_NO_SUCH_PWPOLICY.get(
String.valueOf(entryDN),
String.valueOf(policyDN)));
}
}
}
if (passwordPolicy == null)
{
passwordPolicy = DirectoryServer.getDefaultPasswordPolicy();
}
// See if a password was specified.
AttributeType passwordAttribute = passwordPolicy.getPasswordAttribute();
List<Attribute> attrList = entry.getAttribute(passwordAttribute);
if ((attrList == null) || attrList.isEmpty())
{
// The entry doesn't have a password, so no action is required.
return;
}
else if (attrList.size() > 1)
{
// This must mean there are attribute options, which we won't allow for
// passwords.
Message message = ERR_PWPOLICY_ATTRIBUTE_OPTIONS_NOT_ALLOWED.get(
passwordAttribute.getNameOrOID());
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
}
Attribute passwordAttr = attrList.get(0);
if (passwordAttr.hasOptions())
{
Message message = ERR_PWPOLICY_ATTRIBUTE_OPTIONS_NOT_ALLOWED.get(
passwordAttribute.getNameOrOID());
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
}
if (passwordAttr.isEmpty())
{
// This will be treated the same as not having a password.
return;
}
if ((!passwordPolicy.allowMultiplePasswordValues())
&& (passwordAttr.size() > 1))
{
// FIXME -- What if they're pre-encoded and might all be the
// same?
addPWPolicyControl(PasswordPolicyErrorType.PASSWORD_MOD_NOT_ALLOWED);
Message message = ERR_PWPOLICY_MULTIPLE_PW_VALUES_NOT_ALLOWED
.get(passwordAttribute.getNameOrOID());
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
}
CopyOnWriteArrayList<PasswordStorageScheme<?>> defaultStorageSchemes =
passwordPolicy.getDefaultStorageSchemes();
AttributeBuilder builder = new AttributeBuilder(passwordAttr, true);
builder.setInitialCapacity(defaultStorageSchemes.size());
for (AttributeValue v : passwordAttr)
{
ByteString value = v.getValue();
// See if the password is pre-encoded.
if (passwordPolicy.usesAuthPasswordSyntax())
{
if (AuthPasswordSyntax.isEncoded(value))
{
if (passwordPolicy.allowPreEncodedPasswords())
{
builder.add(v);
continue;
}
else
{
addPWPolicyControl(
PasswordPolicyErrorType.INSUFFICIENT_PASSWORD_QUALITY);
Message message = ERR_PWPOLICY_PREENCODED_NOT_ALLOWED.get(
passwordAttribute.getNameOrOID());
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
message);
}
}
}
else
{
if (UserPasswordSyntax.isEncoded(value))
{
if (passwordPolicy.allowPreEncodedPasswords())
{
builder.add(v);
continue;
}
else
{
addPWPolicyControl(
PasswordPolicyErrorType.INSUFFICIENT_PASSWORD_QUALITY);
Message message = ERR_PWPOLICY_PREENCODED_NOT_ALLOWED.get(
passwordAttribute.getNameOrOID());
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
message);
}
}
}
// See if the password passes validation. We should only do this if
// validation should be performed for administrators.
if (! passwordPolicy.skipValidationForAdministrators())
{
// There are never any current passwords for an add operation.
HashSet<ByteString> currentPasswords = new HashSet<ByteString>(0);
MessageBuilder invalidReason = new MessageBuilder();
for (PasswordValidator<?> validator :
passwordPolicy.getPasswordValidators().values())
{
if (! validator.passwordIsAcceptable(value, currentPasswords, this,
entry, invalidReason))
{
addPWPolicyControl(
PasswordPolicyErrorType.INSUFFICIENT_PASSWORD_QUALITY);
Message message = ERR_PWPOLICY_VALIDATION_FAILED.
get(passwordAttribute.getNameOrOID(),
String.valueOf(invalidReason));
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
message);
}
}
}
// Encode the password.
if (passwordPolicy.usesAuthPasswordSyntax())
{
for (PasswordStorageScheme s : defaultStorageSchemes)
{
ByteString encodedValue = s.encodeAuthPassword(value);
builder.add(AttributeValues.create(
passwordAttribute, encodedValue));
}
}
else
{
for (PasswordStorageScheme s : defaultStorageSchemes)
{
ByteString encodedValue = s.encodePasswordWithScheme(value);
builder.add(AttributeValues.create(
passwordAttribute, encodedValue));
}
}
}
// Put the new encoded values in the entry.
entry.replaceAttribute(builder.toAttribute());
// Set the password changed time attribute.
ArrayList<Attribute> changedTimeList = new ArrayList<Attribute>(1);
Attribute changedTime = Attributes.create(
OP_ATTR_PWPOLICY_CHANGED_TIME, TimeThread.getGeneralizedTime());
changedTimeList.add(changedTime);
entry.putAttribute(changedTime.getAttributeType(), changedTimeList);
// If we should force change on add, then set the appropriate flag.
if (passwordPolicy.forceChangeOnAdd())
{
addPWPolicyControl(PasswordPolicyErrorType.CHANGE_AFTER_RESET);
ArrayList<Attribute> resetList = new ArrayList<Attribute>(1);
Attribute reset = Attributes.create(