mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Matthew Swift
20.29.2011 af1b4bead731b2dc8f25e4db507afab0428054d0
opendj-sdk/opends/src/server/org/opends/server/api/AuthenticationPolicyState.java
@@ -29,9 +29,20 @@
import org.opends.server.types.ByteString;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
import static org.opends.messages.CoreMessages.*;
import static org.opends.server.config.ConfigConstants.OP_ATTR_ACCOUNT_DISABLED;
import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
import static org.opends.server.loggers.debug.DebugLogger.getTracer;
import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
import static org.opends.server.util.StaticUtils.toLowerCase;
import java.util.List;
import org.opends.messages.Message;
import org.opends.server.core.DirectoryServer;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.schema.GeneralizedTimeSyntax;
import org.opends.server.types.*;
@@ -43,6 +54,13 @@
public abstract class AuthenticationPolicyState
{
  /**
   * The tracer object for the debug logger.
   */
  private static final DebugTracer TRACER = getTracer();
  /**
   * Returns the authentication policy state for the user provided user. This
   * method is equivalent to the following:
   *
@@ -68,10 +86,10 @@
   *           policy for the user.
   * @see AuthenticationPolicy#forUser(Entry, boolean)
   */
  public final static AuthenticationPolicyState forUser(Entry userEntry,
      boolean useDefaultOnError) throws DirectoryException
  public final static AuthenticationPolicyState forUser(final Entry userEntry,
      final boolean useDefaultOnError) throws DirectoryException
  {
    AuthenticationPolicy policy = AuthenticationPolicy.forUser(userEntry,
    final AuthenticationPolicy policy = AuthenticationPolicy.forUser(userEntry,
        useDefaultOnError);
    return policy.createAuthenticationPolicyState(userEntry);
  }
@@ -79,37 +97,184 @@
  /**
   * Creates a new abstract authentication policy context.
   * A utility method which may be used by implementations in order to obtain
   * the value of the specified attribute from the provided entry as a boolean.
   *
   * @param entry
   *          The entry whose attribute is to be parsed as a boolean.
   * @param attributeType
   *          The attribute type whose value should be parsed as a boolean.
   * @return The attribute's value represented as a ConditionResult value, or
   *         ConditionResult.UNDEFINED if the specified attribute does not exist
   *         in the entry.
   * @throws DirectoryException
   *           If the value cannot be decoded as a boolean.
   */
  protected AuthenticationPolicyState()
  protected static final ConditionResult getBoolean(final Entry entry,
      final AttributeType attributeType) throws DirectoryException
  {
    // No implementation required.
    final List<Attribute> attrList = entry.getAttribute(attributeType);
    if (attrList != null)
    {
      for (final Attribute a : attrList)
      {
        if (a.isEmpty())
        {
          continue;
        }
        final String valueString = toLowerCase(a.iterator().next().getValue()
            .toString());
        if (valueString.equals("true") || valueString.equals("yes")
            || valueString.equals("on") || valueString.equals("1"))
        {
          if (debugEnabled())
          {
            TRACER.debugInfo("Attribute %s resolves to true for user entry "
                + "%s", attributeType.getNameOrOID(), entry.getDN().toString());
          }
          return ConditionResult.TRUE;
        }
        if (valueString.equals("false") || valueString.equals("no")
            || valueString.equals("off") || valueString.equals("0"))
        {
          if (debugEnabled())
          {
            TRACER.debugInfo("Attribute %s resolves to false for user "
                + "entry %s", attributeType.getNameOrOID(), entry.getDN()
                .toString());
          }
          return ConditionResult.FALSE;
        }
        if (debugEnabled())
        {
          TRACER.debugError("Unable to resolve value %s for attribute %s "
              + "in user entry %s as a Boolean.", valueString,
              attributeType.getNameOrOID(), entry.getDN().toString());
        }
        final Message message = ERR_PWPSTATE_CANNOT_DECODE_BOOLEAN
            .get(valueString, attributeType.getNameOrOID(), entry.getDN()
                .toString());
        throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
            message);
      }
    }
    if (debugEnabled())
    {
      TRACER.debugInfo("Returning %s because attribute %s does not exist "
          + "in user entry %s", ConditionResult.UNDEFINED.toString(),
          attributeType.getNameOrOID(), entry.getDN().toString());
    }
    return ConditionResult.UNDEFINED;
  }
  /**
   * Returns {@code true} if the provided password value matches any of the
   * user's passwords.
   * A utility method which may be used by implementations in order to obtain
   * the value of the specified attribute from the provided entry as a time in
   * generalized time format.
   *
   * @param password
   *          The user-provided password to verify.
   * @return {@code true} if the provided password value matches any of the
   *         user's passwords.
   * @param entry
   *          The entry whose attribute is to be parsed as a boolean.
   * @param attributeType
   *          The attribute type whose value should be parsed as a generalized
   *          time value.
   * @return The requested time, or -1 if it could not be determined.
   * @throws DirectoryException
   *           If verification unexpectedly failed.
   *           If a problem occurs while attempting to decode the value as a
   *           generalized time.
   */
  public abstract boolean passwordMatches(ByteString password)
      throws DirectoryException;
  protected static final long getGeneralizedTime(final Entry entry,
      final AttributeType attributeType) throws DirectoryException
  {
    long timeValue = -1;
    final List<Attribute> attrList = entry.getAttribute(attributeType);
    if (attrList != null)
    {
      for (final Attribute a : attrList)
      {
        if (a.isEmpty())
        {
          continue;
        }
        final AttributeValue v = a.iterator().next();
        try
        {
          timeValue = GeneralizedTimeSyntax.decodeGeneralizedTimeValue(v
              .getNormalizedValue());
        }
        catch (final Exception e)
        {
          if (debugEnabled())
          {
            TRACER.debugCaught(DebugLogLevel.ERROR, e);
            TRACER.debugWarning("Unable to decode value %s for attribute %s "
                + "in user entry %s: %s", v.getValue().toString(),
                attributeType.getNameOrOID(), entry.getDN().toString(),
                stackTraceToSingleLineString(e));
          }
          final Message message = ERR_PWPSTATE_CANNOT_DECODE_GENERALIZED_TIME
              .get(v.getValue().toString(), attributeType.getNameOrOID(), entry
                  .getDN().toString(), String.valueOf(e));
          throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
              message, e);
        }
        break;
      }
    }
    if (timeValue == -1)
    {
      if (debugEnabled())
      {
        TRACER.debugInfo("Returning -1 because attribute %s does not "
            + "exist in user entry %s", attributeType.getNameOrOID(), entry
            .getDN().toString());
      }
    }
    // FIXME: else to be consistent...
    return timeValue;
  }
  /**
   * Returns the authentication policy associated with this state.
   *
   * @return The authentication policy associated with this state.
   * A boolean indicating whether or not the account associated with this
   * authentication state has been administratively disabled.
   */
  public abstract AuthenticationPolicy getAuthenticationPolicy();
  protected ConditionResult isDisabled = ConditionResult.UNDEFINED;
  /**
   * The user entry associated with this authentication policy state.
   */
  protected final Entry userEntry;
  /**
   * Creates a new abstract authentication policy context.
   *
   * @param userEntry
   *          The user's entry.
   */
  protected AuthenticationPolicyState(final Entry userEntry)
  {
    this.userEntry = userEntry;
  }
@@ -129,6 +294,76 @@
  /**
   * Returns the authentication policy associated with this state.
   *
   * @return The authentication policy associated with this state.
   */
  public abstract AuthenticationPolicy getAuthenticationPolicy();
  /**
   * Returns {@code true} if this authentication policy state is associated with
   * a user whose account has been administratively disabled.
   * <p>
   * The default implementation is use the value of the "ds-pwp-account-disable"
   * attribute in the user's entry.
   *
   * @return {@code true} if this authentication policy state is associated with
   *         a user whose account has been administratively disabled.
   */
  public boolean isDisabled()
  {
    final AttributeType type = DirectoryServer.getAttributeType(
        OP_ATTR_ACCOUNT_DISABLED, true);
    try
    {
      isDisabled = getBoolean(userEntry, type);
    }
    catch (final Exception e)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      isDisabled = ConditionResult.TRUE;
      if (debugEnabled())
      {
        TRACER.debugWarning("User %s is considered administratively "
            + "disabled because an error occurred while "
            + "attempting to make the determination: %s.", userEntry.getDN()
            .toString(), stackTraceToSingleLineString(e));
      }
      return true;
    }
    if (isDisabled == ConditionResult.UNDEFINED)
    {
      isDisabled = ConditionResult.FALSE;
      if (debugEnabled())
      {
        TRACER.debugInfo("User %s is not administratively disabled since "
            + "the attribute \"%s\" is not present in the entry.", userEntry
            .getDN().toString(), OP_ATTR_ACCOUNT_DISABLED);
      }
      return false;
    }
    if (debugEnabled())
    {
      TRACER.debugInfo("User %s %s administratively disabled.", userEntry
          .getDN().toString(), ((isDisabled == ConditionResult.TRUE) ? " is"
          : " is not"));
    }
    return isDisabled == ConditionResult.TRUE;
  }
  /**
   * Returns {@code true} if this authentication policy state is associated with
   * a password policy and the method {@link #getAuthenticationPolicy} will
   * return a {@code PasswordPolicy}.
@@ -140,4 +375,20 @@
  {
    return getAuthenticationPolicy().isPasswordPolicy();
  }
  /**
   * Returns {@code true} if the provided password value matches any of the
   * user's passwords.
   *
   * @param password
   *          The user-provided password to verify.
   * @return {@code true} if the provided password value matches any of the
   *         user's passwords.
   * @throws DirectoryException
   *           If verification unexpectedly failed.
   */
  public abstract boolean passwordMatches(ByteString password)
      throws DirectoryException;
}