![JAR search and dependency download from the Maven repository](/logo.png)
com.unboundid.ldap.sdk.unboundidds.extensions.GetPasswordQualityRequirementsExtendedResult Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of unboundid-ldapsdk Show documentation
Show all versions of unboundid-ldapsdk Show documentation
The UnboundID LDAP SDK for Java is a fast, comprehensive, and easy-to-use
Java API for communicating with LDAP directory servers and performing
related tasks like reading and writing LDIF, encoding and decoding data
using base64 and ASN.1 BER, and performing secure communication. This
package contains the Standard Edition of the LDAP SDK, which is a
complete, general-purpose library for communicating with LDAPv3 directory
servers.
/*
* Copyright 2015-2022 Ping Identity Corporation
* All Rights Reserved.
*/
/*
* Copyright 2015-2022 Ping Identity Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright (C) 2015-2022 Ping Identity Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License (GPLv2 only)
* or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
package com.unboundid.ldap.sdk.unboundidds.extensions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import com.unboundid.asn1.ASN1Boolean;
import com.unboundid.asn1.ASN1Element;
import com.unboundid.asn1.ASN1Integer;
import com.unboundid.asn1.ASN1OctetString;
import com.unboundid.asn1.ASN1Sequence;
import com.unboundid.ldap.sdk.Control;
import com.unboundid.ldap.sdk.ExtendedResult;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.ResultCode;
import com.unboundid.util.Debug;
import com.unboundid.util.NotMutable;
import com.unboundid.util.NotNull;
import com.unboundid.util.Nullable;
import com.unboundid.util.StaticUtils;
import com.unboundid.util.ThreadSafety;
import com.unboundid.util.ThreadSafetyLevel;
import com.unboundid.util.Validator;
import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
/**
* This class provides an implementation of an extended result that can provide
* information about the requirements that the server will enforce for
* operations that change or replace a user's password, including adding a new
* user, a user changing his/her own password, and an administrator resetting
* another user's password.
*
*
* NOTE: This class, and other classes within the
* {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
* supported for use against Ping Identity, UnboundID, and
* Nokia/Alcatel-Lucent 8661 server products. These classes provide support
* for proprietary functionality or for external specifications that are not
* considered stable or mature enough to be guaranteed to work in an
* interoperable way with other types of LDAP servers.
*
*
* If the get password quality request was processed successfully, then the
* result will include an OID of 1.3.6.1.4.1.30221.2.6.44 and a value with the
* following encoding:
*
* GetPasswordQualityRequirementsResultValue ::= SEQUENCE {
* requirements SEQUENCE OF PasswordQualityRequirement,
* currentPasswordRequired [0] BOOLEAN OPTIONAL,
* mustChangePassword [1] BOOLEAN OPTIONAL,
* secondsUntilExpiration [2] INTEGER OPTIONAL,
* ... }
*
*/
@NotMutable()
@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
public final class GetPasswordQualityRequirementsExtendedResult
extends ExtendedResult
{
/**
* The OID (1.3.6.1.4.1.30221.2.6.44) for the get password quality
* requirements extended result.
*/
@NotNull public static final String
OID_GET_PASSWORD_QUALITY_REQUIREMENTS_RESULT =
"1.3.6.1.4.1.30221.2.6.44";
/**
* The BER type for the current password required element.
*/
private static final byte TYPE_CURRENT_PW_REQUIRED = (byte) 0x80;
/**
* The BER type for the must change password element.
*/
private static final byte TYPE_MUST_CHANGE_PW = (byte) 0x81;
/**
* The BER type for the seconds until expiration element.
*/
private static final byte TYPE_SECONDS_UNTIL_EXPIRATION = (byte) 0x82;
/**
* The serial version UID for this serializable class.
*/
private static final long serialVersionUID = -4990045432443188148L;
// Indicates whether the user will be required to provide his/her current
// password when performing the associated self password change.
@Nullable private final Boolean currentPasswordRequired;
// Indicates whether the user will be required to change his/her password
// after performing the associated add or administrative reset.
@Nullable private final Boolean mustChangePassword;
// The length of time in seconds that the resulting password will be
// considered valid.
@Nullable private final Integer secondsUntilExpiration;
// The list of password quality requirements that the server will enforce for
// the associated operation.
@NotNull private final List passwordRequirements;
/**
* Creates a new get password quality requirements extended result with the
* provided information.
*
* @param messageID The message ID for the LDAP message that
* is associated with this LDAP result.
* @param resultCode The result code for the response. This
* must not be {@code null}.
* @param diagnosticMessage The diagnostic message for the response.
* This may be {@code null} if no diagnostic
* message is needed.
* @param matchedDN The matched DN for the response. This may
* be {@code null} if no matched DN is
* needed.
* @param referralURLs The set of referral URLs from the
* response. This may be {@code null} or
* empty if no referral URLs are needed.
* @param passwordRequirements The password quality requirements for this
* result. This must be {@code null} or
* empty if this result is for an operation
* that was not processed successfully. It
* may be {@code null} or empty if the
* server will not enforce any password
* quality requirements for the target
* operation.
* @param currentPasswordRequired Indicates whether the user will be
* required to provide his/her current
* password when performing a self change.
* This must be {@code null} if this result
* is for an operation that was not processed
* successfully or if the target operation is
* not a self change.
* @param mustChangePassword Indicates whether the user will be
* required to change their password after
* the associated add or administrative
* reset before that user will be allowed to
* issue any other requests. This must be
* {@code null} if this result is for an
* operation that was not processed
* successfully or if the target operation is
* not an add or an administrative reset.
* @param secondsUntilExpiration Indicates the maximum length of time, in
* seconds, that the password set in the
* target operation will be valid. If
* {@code mustChangePassword} is {@code true}
* then this will indicate the length of time
* that the user has to change his/her
* password after the add/reset. If
* {@code mustChangePassword} is {@code null}
* or {@code false} then this will indicate
* the length of time until the password
* expires. This must be {@code null} if
* this result is for an operation that was
* not processed successfully, or if the new
* password will be valid indefinitely.
* @param controls The set of controls to include in the
* result. It may be {@code null} or empty
* if no controls are needed.
*/
public GetPasswordQualityRequirementsExtendedResult(final int messageID,
@NotNull final ResultCode resultCode,
@Nullable final String diagnosticMessage,
@Nullable final String matchedDN,
@Nullable final String[] referralURLs,
@Nullable final Collection
passwordRequirements,
@Nullable final Boolean currentPasswordRequired,
@Nullable final Boolean mustChangePassword,
@Nullable final Integer secondsUntilExpiration,
@Nullable final Control... controls)
{
super(messageID, resultCode, diagnosticMessage, matchedDN, referralURLs,
((resultCode == ResultCode.SUCCESS)
? OID_GET_PASSWORD_QUALITY_REQUIREMENTS_RESULT
: null),
encodeValue(resultCode, passwordRequirements, currentPasswordRequired,
mustChangePassword, secondsUntilExpiration),
controls);
if ((passwordRequirements == null) || passwordRequirements.isEmpty())
{
this.passwordRequirements = Collections.emptyList();
}
else
{
this.passwordRequirements = Collections.unmodifiableList(
new ArrayList<>(passwordRequirements));
}
this.currentPasswordRequired = currentPasswordRequired;
this.mustChangePassword = mustChangePassword;
this.secondsUntilExpiration = secondsUntilExpiration;
}
/**
* Creates a new get password quality requirements extended result from the
* provided generic result.
*
* @param r The generic extended result to parse as a get password quality
* requirements result.
*
* @throws LDAPException If the provided generic extended result cannot be
* parsed as a get password quality requirements
* result.
*/
public GetPasswordQualityRequirementsExtendedResult(
@NotNull final ExtendedResult r)
throws LDAPException
{
super(r);
final ASN1OctetString value = r.getValue();
if (value == null)
{
passwordRequirements = Collections.emptyList();
currentPasswordRequired = null;
mustChangePassword = null;
secondsUntilExpiration = null;
return;
}
try
{
final ASN1Element[] elements =
ASN1Sequence.decodeAsSequence(value.getValue()).elements();
final ASN1Element[] requirementElements =
ASN1Sequence.decodeAsSequence(elements[0]).elements();
final ArrayList requirementList =
new ArrayList<>(requirementElements.length);
for (final ASN1Element e : requirementElements)
{
requirementList.add(PasswordQualityRequirement.decode(e));
}
passwordRequirements = Collections.unmodifiableList(requirementList);
Boolean cpr = null;
Boolean mcp = null;
Integer sue = null;
for (int i=1; i < elements.length; i++)
{
switch (elements[i].getType())
{
case TYPE_CURRENT_PW_REQUIRED:
cpr = ASN1Boolean.decodeAsBoolean(elements[i]).booleanValue();
break;
case TYPE_MUST_CHANGE_PW:
mcp = ASN1Boolean.decodeAsBoolean(elements[i]).booleanValue();
break;
case TYPE_SECONDS_UNTIL_EXPIRATION:
sue = ASN1Integer.decodeAsInteger(elements[i]).intValue();
break;
default:
// We may update this extended operation in the future to provide
// support for returning additional password-related information.
// If we encounter an unrecognized element, just ignore it rather
// than throwing an exception.
break;
}
}
currentPasswordRequired = cpr;
mustChangePassword = mcp;
secondsUntilExpiration = sue;
}
catch (final Exception e)
{
Debug.debugException(e);
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_GET_PW_QUALITY_REQS_RESULT_CANNOT_DECODE.get(
StaticUtils.getExceptionMessage(e)),
e);
}
}
/**
* Encodes the provided information into an ASN.1 octet string suitable for
* use as the value for this extended result, if appropriate.
*
* @param resultCode The result code for the response. This
* must not be {@code null}.
* @param passwordRequirements The password quality requirements for this
* result. This must be {@code null} or
* empty if this result is for an operation
* that was not processed successfully. It
* may be {@code null} or empty if the
* server will not enforce any password
* quality requirements for the target
* operation.
* @param currentPasswordRequired Indicates whether the user will be
* required to provide his/her current
* password when performing a self change.
* This must be {@code null} if this result
* is for an operation that was not processed
* successfully or if the target operation is
* not a self change.
* @param mustChangePassword Indicates whether the user will be
* required to change their password after
* the associated add or administrative
* reset before that user will be allowed to
* issue any other requests. This must be
* {@code null} if this result is for an
* operation that was not processed
* successfully or if the target operation is
* not an add or an administrative reset.
* @param secondsUntilExpiration Indicates the maximum length of time, in
* seconds, that the password set in the
* target operation will be valid. If
* {@code mustChangePassword} is {@code true}
* then this will indicate the length of time
* that the user has to change his/her
* password after the add/reset. If
* {@code mustChangePassword} is {@code null}
* or {@code false} then this will indicate
* the length of time until the password
* expires. This must be {@code null} if
* this result is for an operation that was
* not processed successfully, or if the new
* password will be valid indefinitely.
*
* @return The ASN.1 element with the encoded result value, or {@code null}
* if the result should not have a value.
*/
@Nullable()
private static ASN1OctetString encodeValue(
@NotNull final ResultCode resultCode,
@Nullable final Collection
passwordRequirements,
@Nullable final Boolean currentPasswordRequired,
@Nullable final Boolean mustChangePassword,
@Nullable final Integer secondsUntilExpiration)
{
if (resultCode != ResultCode.SUCCESS)
{
Validator.ensureTrue((passwordRequirements == null) ||
passwordRequirements.isEmpty());
Validator.ensureTrue(currentPasswordRequired == null);
Validator.ensureTrue(mustChangePassword == null);
Validator.ensureTrue(secondsUntilExpiration == null);
return null;
}
final ArrayList valueSequence = new ArrayList<>(4);
if (passwordRequirements == null)
{
valueSequence.add(new ASN1Sequence());
}
else
{
final ArrayList requirementElements =
new ArrayList<>(passwordRequirements.size());
for (final PasswordQualityRequirement r : passwordRequirements)
{
requirementElements.add(r.encode());
}
valueSequence.add(new ASN1Sequence(requirementElements));
}
if (currentPasswordRequired != null)
{
valueSequence.add(new ASN1Boolean(TYPE_CURRENT_PW_REQUIRED,
currentPasswordRequired));
}
if (mustChangePassword != null)
{
valueSequence.add(new ASN1Boolean(TYPE_MUST_CHANGE_PW,
mustChangePassword));
}
if (secondsUntilExpiration != null)
{
valueSequence.add(new ASN1Integer(TYPE_SECONDS_UNTIL_EXPIRATION,
secondsUntilExpiration));
}
return new ASN1OctetString(new ASN1Sequence(valueSequence).encode());
}
/**
* Retrieves the list of password quality requirements that specify the
* constraints that a proposed password must satisfy in order to be accepted
* by the server in an operation of the type specified in the get password
* quality requirements request.
*
* @return A list of the password quality requirements returned by the
* server, or an empty list if this result is for a non-successful
* get password quality requirements operation or if the server
* will not impose any password quality requirements for the
* specified operation type.
*/
@NotNull()
public List getPasswordRequirements()
{
return passwordRequirements;
}
/**
* Retrieves a flag that indicates whether the target user will be required to
* provide his/her current password in order to set a new password with a self
* change.
*
* @return A value of {@code Boolean.TRUE} if the target operation is a self
* change and the user will be required to provide his/her current
* password when setting a new one, {@code Boolean.FALSE} if the
* target operation is a self change and the user will not be
* required to provide his/her current password, or {@code null} if
* the target operation is not a self change or if this result is for
* a non-successful get password quality requirements operation.
*/
@Nullable()
public Boolean getCurrentPasswordRequired()
{
return currentPasswordRequired;
}
/**
* Retrieves a flag that indicates whether the target user will be required to
* immediately change his/her own password after the associated add or
* administrative reset operation before that user will be allowed to issue
* any other types of requests.
*
* @return A value of {@code Boolean.TRUE} if the target operation is an add
* or administrative reset and the user will be required to
* immediately perform a self change to select a new password before
* being allowed to perform any other kinds of operations,
* {@code Boolean.FALSE} if the target operation is an add or
* administrative reset but the user will not be required to
* immediately select a new password with a self change, or
* {@code null} if the target operation is not an add or
* administrative reset, or if this result is for a non-successful
* get password quality requirements operation.
*/
@Nullable()
public Boolean getMustChangePassword()
{
return mustChangePassword;
}
/**
* Retrieves the length of time, in seconds, that the new password will be
* considered valid after the change is applied. If the associated operation
* is an add or an administrative reset and {@link #getMustChangePassword()}
* returns {@code Boolean.TRUE}, then this will indicate the length of time
* that the user has to choose a new password with a self change before the
* account becomes locked. If the associated operation is a self change, or
* if {@code getMustChangePassword} returns {@code Boolean.FALSE}, then this
* will indicate the maximum length of time that the newly-selected password
* may be used until it expires.
*
* @return The length of time, in seconds, that the new password will be
* considered valid after the change is applied, or {@code null} if
* this result is for a non-successful get password quality
* requirements operation or if the newly-selected password can be
* used indefinitely.
*/
@Nullable()
public Integer getSecondsUntilExpiration()
{
return secondsUntilExpiration;
}
/**
* {@inheritDoc}
*/
@Override()
@NotNull()
public String getExtendedResultName()
{
return INFO_EXTENDED_RESULT_NAME_GET_PW_QUALITY_REQS.get();
}
/**
* {@inheritDoc}
*/
@Override()
public void toString(@NotNull final StringBuilder buffer)
{
buffer.append("GetPasswordQualityRequirementsExtendedResult(resultCode=");
buffer.append(getResultCode());
final int messageID = getMessageID();
if (messageID >= 0)
{
buffer.append(", messageID=");
buffer.append(messageID);
}
buffer.append(", requirements{");
final Iterator requirementsIterator =
passwordRequirements.iterator();
while (requirementsIterator.hasNext())
{
requirementsIterator.next().toString(buffer);
if (requirementsIterator.hasNext())
{
buffer.append(',');
}
}
buffer.append('}');
if (currentPasswordRequired != null)
{
buffer.append(", currentPasswordRequired=");
buffer.append(currentPasswordRequired);
}
if (mustChangePassword != null)
{
buffer.append(", mustChangePassword=");
buffer.append(mustChangePassword);
}
if (secondsUntilExpiration != null)
{
buffer.append(", secondsUntilExpiration=");
buffer.append(secondsUntilExpiration);
}
final String diagnosticMessage = getDiagnosticMessage();
if (diagnosticMessage != null)
{
buffer.append(", diagnosticMessage='");
buffer.append(diagnosticMessage);
buffer.append('\'');
}
final String matchedDN = getMatchedDN();
if (matchedDN != null)
{
buffer.append(", matchedDN='");
buffer.append(matchedDN);
buffer.append('\'');
}
final String[] referralURLs = getReferralURLs();
if (referralURLs.length > 0)
{
buffer.append(", referralURLs={");
for (int i=0; i < referralURLs.length; i++)
{
if (i > 0)
{
buffer.append(", ");
}
buffer.append('\'');
buffer.append(referralURLs[i]);
buffer.append('\'');
}
buffer.append('}');
}
final Control[] responseControls = getResponseControls();
if (responseControls.length > 0)
{
buffer.append(", responseControls={");
for (int i=0; i < responseControls.length; i++)
{
if (i > 0)
{
buffer.append(", ");
}
buffer.append(responseControls[i]);
}
buffer.append('}');
}
buffer.append(')');
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy