/*
|
* 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
|
*
|
*
|
* Copyright 2006-2008 Sun Microsystems, Inc.
|
*/
|
package org.opends.server.controls;
|
import org.opends.messages.Message;
|
|
|
|
import java.util.ArrayList;
|
|
import org.opends.server.protocols.asn1.ASN1Boolean;
|
import org.opends.server.protocols.asn1.ASN1Element;
|
import org.opends.server.protocols.asn1.ASN1Exception;
|
import org.opends.server.protocols.asn1.ASN1Integer;
|
import org.opends.server.protocols.asn1.ASN1OctetString;
|
import org.opends.server.protocols.asn1.ASN1Sequence;
|
import org.opends.server.protocols.ldap.LDAPResultCode;
|
import org.opends.server.types.Control;
|
import org.opends.server.types.DebugLogLevel;
|
import org.opends.server.types.LDAPException;
|
|
import static org.opends.server.loggers.debug.DebugLogger.*;
|
import org.opends.server.loggers.debug.DebugTracer;
|
import static org.opends.messages.ProtocolMessages.*;
|
import static org.opends.server.util.ServerConstants.*;
|
import static org.opends.server.util.StaticUtils.*;
|
|
|
|
/**
|
* This class implements the account usable response control. This is a
|
* Sun-defined control with OID 1.3.6.1.4.1.42.2.27.9.5.8. The value of this
|
* control is composed according to the following BNF:
|
* <BR>
|
* <PRE>
|
* ACCOUNT_USABLE_RESPONSE ::= CHOICE {
|
* is_available [0] INTEGER, -- Seconds before expiration --
|
* is_not_available [1] MORE_INFO }
|
*
|
* MORE_INFO ::= SEQUENCE {
|
* inactive [0] BOOLEAN DEFAULT FALSE,
|
* reset [1] BOOLEAN DEFAULT FALSE,
|
* expired [2] BOOLEAN DEFAULT_FALSE,
|
* remaining_grace [3] INTEGER OPTIONAL,
|
* seconds_before_unlock [4] INTEGER OPTIONAL }
|
* </PRE>
|
*/
|
public class AccountUsableResponseControl
|
extends Control
|
{
|
/**
|
* The tracer object for the debug logger.
|
*/
|
private static final DebugTracer TRACER = getTracer();
|
|
|
|
|
/**
|
* The BER type to use for the seconds before expiration when the account is
|
* available.
|
*/
|
public static final byte TYPE_SECONDS_BEFORE_EXPIRATION = (byte) 0x80;
|
|
|
|
/**
|
* The BER type to use for the MORE_INFO sequence when the account is not
|
* available.
|
*/
|
public static final byte TYPE_MORE_INFO = (byte) 0xA1;
|
|
|
|
/**
|
* The BER type to use for the MORE_INFO element that indicates that the
|
* account has been inactivated.
|
*/
|
public static final byte TYPE_INACTIVE = (byte) 0x80;
|
|
|
|
/**
|
* The BER type to use for the MORE_INFO element that indicates that the
|
* password has been administratively reset.
|
*/
|
public static final byte TYPE_RESET = (byte) 0x81;
|
|
|
|
/**
|
* The BER type to use for the MORE_INFO element that indicates that the
|
* user's password is expired.
|
*/
|
public static final byte TYPE_EXPIRED = (byte) 0x82;
|
|
|
|
/**
|
* The BER type to use for the MORE_INFO element that provides the number of
|
* remaining grace logins.
|
*/
|
public static final byte TYPE_REMAINING_GRACE_LOGINS = (byte) 0x83;
|
|
|
|
/**
|
* The BER type to use for the MORE_INFO element that indicates that the
|
* password has been administratively reset.
|
*/
|
public static final byte TYPE_SECONDS_BEFORE_UNLOCK = (byte) 0x84;
|
|
|
|
// Indicates whether the user's account is usable.
|
private boolean isUsable;
|
|
// Indicates whether the user's password is expired.
|
private boolean isExpired;
|
|
// Indicates whether the user's account is inactive.
|
private boolean isInactive;
|
|
// Indicates whether the user's account is currently locked.
|
private boolean isLocked;
|
|
// Indicates whether the user's password has been reset and must be changed
|
// before anything else can be done.
|
private boolean isReset;
|
|
// The number of remaining grace logins, if available.
|
private int remainingGraceLogins;
|
|
// The length of time in seconds before the user's password expires, if
|
// available.
|
private int secondsBeforeExpiration;
|
|
// The length of time before the user's account is unlocked, if available.
|
private int secondsBeforeUnlock;
|
|
|
|
/**
|
* Creates a new account usability response control that may be used to
|
* indicate that the account is available and provide the number of seconds
|
* until expiration. It will use the default OID and criticality.
|
*
|
* @param secondsBeforeExpiration The length of time in seconds until the
|
* user's password expires, or -1 if the
|
* user's password will not expire or the
|
* expiration time is unknown.
|
*/
|
public AccountUsableResponseControl(int secondsBeforeExpiration)
|
{
|
super(OID_ACCOUNT_USABLE_CONTROL, false,
|
encodeValue(secondsBeforeExpiration));
|
|
|
this.secondsBeforeExpiration = secondsBeforeExpiration;
|
|
isUsable = true;
|
isInactive = false;
|
isReset = false;
|
isExpired = false;
|
remainingGraceLogins = -1;
|
isLocked = false;
|
secondsBeforeUnlock = 0;
|
}
|
|
|
|
/**
|
* Creates a new account usability response control that may be used to
|
* indicate that the account is available and provide the number of seconds
|
* until expiration.
|
*
|
* @param oid The OID for this account usability
|
* response control.
|
* @param isCritical Indicates whether this control should be
|
* marked critical.
|
* @param secondsBeforeExpiration The length of time in seconds until the
|
* user's password expires, or -1 if the
|
* user's password will not expire or the
|
* expiration time is unknown.
|
*/
|
public AccountUsableResponseControl(String oid, boolean isCritical,
|
int secondsBeforeExpiration)
|
{
|
super(oid, isCritical, encodeValue(secondsBeforeExpiration));
|
|
|
this.secondsBeforeExpiration = secondsBeforeExpiration;
|
|
isUsable = true;
|
isInactive = false;
|
isReset = false;
|
isExpired = false;
|
remainingGraceLogins = -1;
|
isLocked = false;
|
secondsBeforeUnlock = 0;
|
}
|
|
|
|
/**
|
* Creates a new account usability response control that may be used to
|
* indicate that the account is not available and provide information about
|
* the underlying reason. It will use the default OID and criticality.
|
*
|
* @param isInactive Indicates whether the user's account has been
|
* inactivated by an administrator.
|
* @param isReset Indicates whether the user's password has
|
* been reset by an administrator.
|
* @param isExpired Indicates whether the user's password is
|
* expired.
|
* @param remainingGraceLogins The number of grace logins remaining. A
|
* value of zero indicates that there are none
|
* remaining. A value of -1 indicates that
|
* grace login functionality is not enabled.
|
* @param isLocked Indicates whether the user's account is
|
* currently locked out.
|
* @param secondsBeforeUnlock The length of time in seconds until the
|
* account is unlocked. A value of -1 indicates
|
* that the account will not be automatically
|
* unlocked and must be reset by an
|
* administrator.
|
*/
|
public AccountUsableResponseControl(boolean isInactive, boolean isReset,
|
boolean isExpired,
|
int remainingGraceLogins,
|
boolean isLocked, int secondsBeforeUnlock)
|
{
|
super(OID_ACCOUNT_USABLE_CONTROL, false,
|
encodeValue(isInactive, isReset, isExpired, remainingGraceLogins,
|
isLocked, secondsBeforeUnlock));
|
|
|
this.isInactive = isInactive;
|
this.isReset = isReset;
|
this.isExpired = isExpired;
|
this.remainingGraceLogins = remainingGraceLogins;
|
this.isLocked = isLocked;
|
this.secondsBeforeUnlock = secondsBeforeUnlock;
|
|
isUsable = false;
|
secondsBeforeExpiration = -1;
|
}
|
|
|
|
/**
|
* Creates a new account usability response control that may be used to
|
* indicate that the account is not available and provide information about
|
* the underlying reason.
|
*
|
* @param oid The OID for this account usability response
|
* control.
|
* @param isCritical Indicates whether this control should be
|
* marked critical.
|
* @param isInactive Indicates whether the user's account has been
|
* inactivated by an administrator.
|
* @param isReset Indicates whether the user's password has
|
* been reset by an administrator.
|
* @param isExpired Indicates whether the user's password is
|
* expired.
|
* @param remainingGraceLogins The number of grace logins remaining. A
|
* value of zero indicates that there are none
|
* remaining. A value of -1 indicates that
|
* grace login functionality is not enabled.
|
* @param isLocked Indicates whether the user's account is
|
* currently locked out.
|
* @param secondsBeforeUnlock The length of time in seconds until the
|
* account is unlocked. A value of -1 indicates
|
* that the account will not be automatically
|
* unlocked and must be reset by an
|
* administrator.
|
*/
|
public AccountUsableResponseControl(String oid, boolean isCritical,
|
boolean isInactive, boolean isReset,
|
boolean isExpired,
|
int remainingGraceLogins,
|
boolean isLocked, int secondsBeforeUnlock)
|
{
|
super(oid, isCritical,
|
encodeValue(isInactive, isReset, isExpired, remainingGraceLogins,
|
isLocked, secondsBeforeUnlock));
|
|
|
this.isInactive = isInactive;
|
this.isReset = isReset;
|
this.isExpired = isExpired;
|
this.remainingGraceLogins = remainingGraceLogins;
|
this.isLocked = isLocked;
|
this.secondsBeforeUnlock = secondsBeforeUnlock;
|
|
isUsable = false;
|
secondsBeforeExpiration = -1;
|
}
|
|
|
|
/**
|
* Creates a new account usability response control using the provided
|
* information. This version of the constructor is only intended for internal
|
* use.
|
*
|
* @param oid The OID for this account usability
|
* response control.
|
* @param isCritical Indicates whether this control should be
|
* marked critical.
|
* @param isAvailable Indicates whether the user's account is
|
* available for use.
|
* @param secondsBeforeExpiration The length of time in seconds until the
|
* user's password expires, or -1 if the
|
* user's password will not expire or the
|
* expiration time is unknown.
|
* @param isInactive Indicates whether the user's account has
|
* been inactivated by an administrator.
|
* @param isReset Indicates whether the user's password has
|
* been reset by an administrator.
|
* @param isExpired Indicates whether the user's password is
|
* expired.
|
* @param remainingGraceLogins The number of grace logins remaining. A
|
* value of zero indicates that there are
|
* none remaining. A value of -1 indicates
|
* that grace login functionality is not
|
* enabled.
|
* @param isLocked Indicates whether the user's account is
|
* currently locked out.
|
* @param secondsBeforeUnlock The length of time in seconds until the
|
* account is unlocked. A value of -1
|
* indicates that the account will not be
|
* automatically unlocked and must be reset
|
* by an administrator.
|
* @param encodedValue The pre-encoded value for this account
|
* usable response control.
|
*/
|
private AccountUsableResponseControl(String oid, boolean isCritical,
|
boolean isAvailable,
|
int secondsBeforeExpiration,
|
boolean isInactive,
|
boolean isReset, boolean isExpired,
|
int remainingGraceLogins,
|
boolean isLocked,
|
int secondsBeforeUnlock,
|
ASN1OctetString encodedValue)
|
{
|
super(oid, isCritical, encodedValue);
|
|
|
this.isUsable = isAvailable;
|
this.secondsBeforeExpiration = secondsBeforeExpiration;
|
this.isInactive = isInactive;
|
this.isReset = isReset;
|
this.isExpired = isExpired;
|
this.remainingGraceLogins = remainingGraceLogins;
|
this.isLocked = isLocked;
|
this.secondsBeforeUnlock = secondsBeforeUnlock;
|
}
|
|
|
|
/**
|
* Encodes the provided information into an ASN.1 octet string suitable for
|
* use as the value for an account usable response control in which the use's
|
* account is available.
|
*
|
* @param secondsBeforeExpiration The length of time in seconds until the
|
* user's password expires, or -1 if the
|
* user's password will not expire or the
|
* expiration time is unknown.
|
*
|
* @return An ASN.1 octet string containing the encoded control value.
|
*/
|
private static ASN1OctetString encodeValue(int secondsBeforeExpiration)
|
{
|
ASN1Integer sbeInteger = new ASN1Integer(TYPE_SECONDS_BEFORE_EXPIRATION,
|
secondsBeforeExpiration);
|
|
return new ASN1OctetString(sbeInteger.encode());
|
}
|
|
|
|
/**
|
* Encodes the provided information into an ASN.1 octet string suitable for
|
* use as the value for an account usable response control in which the user's
|
* account is not available.
|
*
|
*
|
* @param isInactive Indicates whether the user's account has been
|
* inactivated by an administrator.
|
* @param isReset Indicates whether the user's password has
|
* been reset by an administrator.
|
* @param isExpired Indicates whether the user's password is
|
* expired.
|
* @param remainingGraceLogins The number of grace logins remaining. A
|
* value of zero indicates that there are none
|
* remaining. A value of -1 indicates that
|
* grace login functionality is not enabled.
|
* @param isLocked Indicates whether the user's account is
|
* currently locked out.
|
* @param secondsBeforeUnlock The length of time in seconds until the
|
* account is unlocked. A value of -1 indicates
|
* that the account will not be automatically
|
* unlocked and must be reset by an
|
* administrator.
|
*
|
* @return An ASN.1 octet string containing the encoded control value.
|
*/
|
private static ASN1OctetString encodeValue(boolean isInactive,
|
boolean isReset, boolean isExpired,
|
int remainingGraceLogins,
|
boolean isLocked,
|
int secondsBeforeUnlock)
|
{
|
ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(5);
|
|
if (isInactive)
|
{
|
elements.add(new ASN1Boolean(TYPE_INACTIVE, true));
|
}
|
|
if (isReset)
|
{
|
elements.add(new ASN1Boolean(TYPE_RESET, true));
|
}
|
|
if (isExpired)
|
{
|
elements.add(new ASN1Boolean(TYPE_EXPIRED, true));
|
|
if (remainingGraceLogins >= 0)
|
{
|
elements.add(new ASN1Integer(TYPE_REMAINING_GRACE_LOGINS,
|
remainingGraceLogins));
|
}
|
}
|
|
if (isLocked)
|
{
|
elements.add(new ASN1Integer(TYPE_SECONDS_BEFORE_UNLOCK,
|
secondsBeforeUnlock));
|
}
|
|
ASN1Sequence moreInfoSequence = new ASN1Sequence(TYPE_MORE_INFO,
|
elements);
|
return new ASN1OctetString(moreInfoSequence.encode());
|
}
|
|
|
|
/**
|
* Creates a new account usable response control from the contents of the
|
* provided control.
|
*
|
* @param control The generic control containing the information to use to
|
* create this account usable response control.
|
*
|
* @return The account usable response control decoded from the provided
|
* control.
|
*
|
* @throws LDAPException If this control cannot be decoded as a valid
|
* account usable response control.
|
*/
|
public static AccountUsableResponseControl decodeControl(Control control)
|
throws LDAPException
|
{
|
ASN1OctetString controlValue = control.getValue();
|
if (controlValue == null)
|
{
|
// The response control must always have a value.
|
Message message = ERR_ACCTUSABLERES_NO_CONTROL_VALUE.get();
|
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
|
}
|
|
|
try
|
{
|
ASN1Element valueElement = ASN1Element.decode(controlValue.value());
|
switch (valueElement.getType())
|
{
|
case TYPE_SECONDS_BEFORE_EXPIRATION:
|
int secondsBeforeExpiration =
|
valueElement.decodeAsInteger().intValue();
|
return new AccountUsableResponseControl(control.getOID(),
|
control.isCritical(), true,
|
secondsBeforeExpiration,
|
false, false, false, -1,
|
false, 0, controlValue);
|
case TYPE_MORE_INFO:
|
boolean isInactive = false;
|
boolean isReset = false;
|
boolean isExpired = false;
|
boolean isLocked = false;
|
int remainingGraceLogins = -1;
|
int secondsBeforeUnlock = 0;
|
|
for (ASN1Element e : valueElement.decodeAsSequence().elements())
|
{
|
switch (e.getType())
|
{
|
case TYPE_INACTIVE:
|
isInactive = e.decodeAsBoolean().booleanValue();
|
break;
|
case TYPE_RESET:
|
isReset = e.decodeAsBoolean().booleanValue();
|
break;
|
case TYPE_EXPIRED:
|
isExpired = e.decodeAsBoolean().booleanValue();
|
break;
|
case TYPE_REMAINING_GRACE_LOGINS:
|
remainingGraceLogins = e.decodeAsInteger().intValue();
|
break;
|
case TYPE_SECONDS_BEFORE_UNLOCK:
|
isLocked = true;
|
secondsBeforeUnlock = e.decodeAsInteger().intValue();
|
break;
|
default:
|
Message message = ERR_ACCTUSABLERES_UNKNOWN_UNAVAILABLE_TYPE.
|
get(byteToHex(e.getType()));
|
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
|
}
|
}
|
|
return new AccountUsableResponseControl(control.getOID(),
|
control.isCritical(), false,
|
-1, isInactive, isReset,
|
isExpired,
|
remainingGraceLogins,
|
isLocked, secondsBeforeUnlock,
|
controlValue);
|
|
default:
|
Message message = ERR_ACCTUSABLERES_UNKNOWN_VALUE_ELEMENT_TYPE.get(
|
byteToHex(valueElement.getType()));
|
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
|
}
|
}
|
catch (LDAPException le)
|
{
|
throw le;
|
}
|
catch (ASN1Exception ae)
|
{
|
if (debugEnabled())
|
{
|
TRACER.debugCaught(DebugLogLevel.ERROR, ae);
|
}
|
|
Message message = ERR_ACCTUSABLERES_DECODE_ERROR.get(ae.getMessage());
|
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
|
}
|
catch (Exception e)
|
{
|
if (debugEnabled())
|
{
|
TRACER.debugCaught(DebugLogLevel.ERROR, e);
|
}
|
|
Message message =
|
ERR_ACCTUSABLERES_DECODE_ERROR.get(getExceptionMessage(e));
|
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
|
}
|
}
|
|
|
|
/**
|
* Indicates whether the associated user account is available for use.
|
*
|
* @return <CODE>true</CODE> if the associated user account is available, or
|
* <CODE>false</CODE> if not.
|
*/
|
public boolean isUsable()
|
{
|
return isUsable;
|
}
|
|
|
|
/**
|
* Retrieves the length of time in seconds before the user's password expires.
|
* This value is unreliable if the account is not available.
|
*
|
* @return The length of time in seconds before the user's password expires,
|
* or -1 if it is unknown or password expiration is not enabled for
|
* the user.
|
*/
|
public int getSecondsBeforeExpiration()
|
{
|
return secondsBeforeExpiration;
|
}
|
|
|
|
/**
|
* Indicates whether the user's account has been inactivated by an
|
* administrator.
|
*
|
* @return <CODE>true</CODE> if the user's account has been inactivated by
|
* an administrator, or <CODE>false</CODE> if not.
|
*/
|
public boolean isInactive()
|
{
|
return isInactive;
|
}
|
|
|
|
/**
|
* Indicates whether the user's password has been administratively reset and
|
* the user must change that password before any other operations will be
|
* allowed.
|
*
|
* @return <CODE>true</CODE> if the user's password has been administratively
|
* reset, or <CODE>false</CODE> if not.
|
*/
|
public boolean isReset()
|
{
|
return isReset;
|
}
|
|
|
|
/**
|
* Indicates whether the user's password is expired.
|
*
|
* @return <CODE>true</CODE> if the user's password is expired, or
|
* <CODE>false</CODE> if not.
|
*/
|
public boolean isExpired()
|
{
|
return isExpired;
|
}
|
|
|
|
/**
|
* Retrieves the number of remaining grace logins for the user. This value is
|
* unreliable if the user's password is not expired.
|
*
|
* @return The number of remaining grace logins for the user, or -1 if the
|
* grace logins feature is not enabled for the user.
|
*/
|
public int getRemainingGraceLogins()
|
{
|
return remainingGraceLogins;
|
}
|
|
|
|
/**
|
* Indicates whether the user's account is locked for some reason.
|
*
|
* @return <CODE>true</CODE> if the user's account is locked, or
|
* <CODE>false</CODE> if it is not.
|
*/
|
public boolean isLocked()
|
{
|
return isLocked;
|
}
|
|
|
|
/**
|
* Retrieves the length of time in seconds before the user's account is
|
* automatically unlocked. This value is unreliable is the user's account is
|
* not locked.
|
*
|
* @return The length of time in seconds before the user's account is
|
* automatically unlocked, or -1 if it requires administrative action
|
* to unlock the account.
|
*/
|
public int getSecondsBeforeUnlock()
|
{
|
return secondsBeforeUnlock;
|
}
|
|
|
|
/**
|
* Retrieves a string representation of this password policy response control.
|
*
|
* @return A string representation of this password policy response control.
|
*/
|
public String toString()
|
{
|
StringBuilder buffer = new StringBuilder();
|
toString(buffer);
|
return buffer.toString();
|
}
|
|
|
|
/**
|
* Appends a string representation of this password policy response control to
|
* the provided buffer.
|
*
|
* @param buffer The buffer to which the information should be appended.
|
*/
|
public void toString(StringBuilder buffer)
|
{
|
buffer.append("AccountUsableResponseControl(isUsable=");
|
buffer.append(isUsable);
|
|
if (isUsable)
|
{
|
buffer.append(",secondsBeforeExpiration=");
|
buffer.append(secondsBeforeExpiration);
|
}
|
else
|
{
|
buffer.append(",isInactive=");
|
buffer.append(isInactive);
|
buffer.append(",isReset=");
|
buffer.append(isReset);
|
buffer.append(",isExpired=");
|
buffer.append(isExpired);
|
buffer.append(",remainingGraceLogins=");
|
buffer.append(remainingGraceLogins);
|
buffer.append(",isLocked=");
|
buffer.append(isLocked);
|
buffer.append(",secondsBeforeUnlock=");
|
buffer.append(secondsBeforeUnlock);
|
}
|
|
buffer.append(")");
|
}
|
}
|