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

Jean-Noel Rouvignac
19.37.2013 4a789af2cc9d96218d4225b9bb9bc99b3b4cd43b
Code cleanup of extended operations.


ExtendedOperationHandler.java:
Added ctor ExtendedOperationHandler(Set<String> supportedControlOIDs).
Implemented initializeExtendedOperationHandler() and finalizeExtendedOperationHandler() by moving common code here from subclasses impls.
Made registerControlsAndFeatures() and deregisterControlsAndFeatures() private.
Added overridable method getExtendedOperationOID().

GetSymmetricKeyExtendedOperation.java, CancelExtendedOperation.java, GetConnectionIDExtendedOperation.java, PasswordModifyExtendedOperation.java, PasswordPolicyStateExtendedOperation.java, StartTLSExtendedOperation.java, WhoAmIExtendedOperation.java:
Removed getSupportedControls() + supportedControlOIDs field member where present - superseded by the superclass ones.
In initializeExtendedOperationHandler(), delegated to superclass method. Cannot replace it fully because method signatures do not match.
Removed finalizeExtendedOperationHandler(), rely on superclass implementation where possible.
Implemented getExtendedOperationOIDI() and getExtendedOperationName() sometimes.
Code cleanup.
8 files modified
1224 ■■■■■ changed files
opends/src/server/org/opends/server/api/ExtendedOperationHandler.java 77 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/crypto/GetSymmetricKeyExtendedOperation.java 94 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/CancelExtendedOperation.java 108 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/GetConnectionIDExtendedOperation.java 58 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/PasswordModifyExtendedOperation.java 434 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/PasswordPolicyStateExtendedOperation.java 319 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/StartTLSExtendedOperation.java 66 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/WhoAmIExtendedOperation.java 68 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/ExtendedOperationHandler.java
@@ -22,23 +22,20 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions copyright 2013 ForgeRock AS
 */
package org.opends.server.api;
import org.opends.messages.Message;
import java.util.HashSet;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.opends.server.config.ConfigException;
import org.opends.server.core.ExtendedOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.InitializationException;
import org.opends.messages.Message;
import org.opends.server.admin.std.server.ExtendedOperationHandlerCfg;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ExtendedOperation;
import org.opends.server.types.InitializationException;
/**
 * This class defines the set of methods and structures that must be
@@ -57,13 +54,33 @@
public abstract class
     ExtendedOperationHandler<T extends ExtendedOperationHandlerCfg>
{
  // The default set of supported control OIDs for this extended
  private Set<String> supportedControlOIDs = new HashSet<String>(0);
  // The default set of supported feature OIDs for this extended
  private Set<String> supportedFeatureOIDs = new HashSet<String>(0);
  /** The default set of supported control OIDs for this extended op. */
  private final Set<String> supportedControlOIDs;
  /** The default set of supported feature OIDs for this extended op. */
  private final Set<String> supportedFeatureOIDs = Collections.emptySet();
  /**
   * Builds an extended operation.
   */
  public ExtendedOperationHandler()
  {
    this.supportedControlOIDs = Collections.<String> emptySet();
  }
  /**
   * Builds an extended operation.
   *
   * @param supportedControlOIDs
   *          the default set of supported control OIDs for this extended op
   */
  public ExtendedOperationHandler(Set<String> supportedControlOIDs)
  {
    this.supportedControlOIDs = supportedControlOIDs != null ?
        Collections.unmodifiableSet(supportedControlOIDs)
        : Collections.<String> emptySet();
  }
  /**
   * Initializes this extended operation handler based on the
@@ -84,8 +101,12 @@
   *                                   not related to the server
   *                                   configuration.
   */
  public abstract void initializeExtendedOperationHandler(T config)
         throws ConfigException, InitializationException;
  public void initializeExtendedOperationHandler(T config)
      throws ConfigException, InitializationException
  {
    DirectoryServer.registerSupportedExtension(getExtendedOperationOID(), this);
    registerControlsAndFeatures();
  }
@@ -130,7 +151,8 @@
   */
  public void finalizeExtendedOperationHandler()
  {
    // No implementation is required by default.
    DirectoryServer.deregisterSupportedExtension(getExtendedOperationOID());
    deregisterControlsAndFeatures();
  }
@@ -212,9 +234,8 @@
  /**
   * If the extended operation handler defines any supported controls
   * and/or features, then register them with the server.
   *
   */
  protected void registerControlsAndFeatures()
  private void registerControlsAndFeatures()
  {
    Set<String> controlOIDs = getSupportedControls();
    if (controlOIDs != null)
@@ -241,7 +262,7 @@
   * If the extended operation handler defines any supported controls
   * and/or features, then deregister them with the server.
   */
  protected void deregisterControlsAndFeatures()
  private void deregisterControlsAndFeatures()
  {
    Set<String> controlOIDs = getSupportedControls();
    if (controlOIDs != null)
@@ -262,19 +283,25 @@
    }
  }
  /**
   * Retrieves the name associated with this extended operation.
   * Implementing classes should override this method with their
   * own providing string representation of the operation name.
   *
   * @return  The name associated with this extended operation,
   *          if any, or <CODE>null</CODE> if there is none.
   */
  public String getExtendedOperationName()
  {
    // Abstract, hence no name associated.
    return null;
  }
  /**
   * Retrieves the object OID associated with this extended operation.
   *
   * @return the oid associated with this extended operation, if any, or
   *         <CODE>null</CODE> if there is none.
   */
  public String getExtendedOperationOID()
  {
    return null;
  }
}
opends/src/server/org/opends/server/crypto/GetSymmetricKeyExtendedOperation.java
@@ -22,30 +22,30 @@
 *
 *
 *      Copyright 2008-2009 Sun Microsystems, Inc.
 *      Portions copyright 2013 ForgeRock AS
 */
package org.opends.server.crypto;
import java.io.IOException;
import org.opends.messages.Message;
import org.opends.server.admin.std.server.
            GetSymmetricKeyExtendedOperationHandlerCfg;
GetSymmetricKeyExtendedOperationHandlerCfg;
import org.opends.server.api.ExtendedOperationHandler;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.loggers.debug.DebugLogger;
import org.opends.server.types.*;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ExtendedOperation;
import org.opends.server.util.StaticUtils;
import org.opends.server.util.ServerConstants;
import org.opends.server.protocols.asn1.ASN1Reader;
import org.opends.server.loggers.debug.DebugLogger;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.protocols.asn1.ASN1;
import org.opends.server.protocols.asn1.ASN1Exception;
import org.opends.server.protocols.asn1.ASN1Reader;
import org.opends.server.protocols.asn1.ASN1Writer;
import org.opends.messages.Message;
import static org.opends.messages.ExtensionMessages.*;
import org.opends.server.types.*;
import org.opends.server.util.ServerConstants;
import org.opends.server.util.StaticUtils;
import java.util.Set;
import java.util.HashSet;
import static org.opends.messages.ExtensionMessages.*;
/**
 * This class implements the get symmetric key extended operation, an OpenDS
@@ -61,27 +61,16 @@
   */
  private static final DebugTracer TRACER = DebugLogger.getTracer();
  /**
   * The BER type value for the symmetric key element of the operation value.
   */
  public static final byte TYPE_SYMMETRIC_KEY_ELEMENT = (byte) 0x80;
  /**
   * The BER type value for the instance key ID element of the operation value.
   */
  public static final byte TYPE_INSTANCE_KEY_ID_ELEMENT = (byte) 0x81;
  // The default set of supported control OIDs for this extended operation.
  private Set<String> supportedControlOIDs = new HashSet<String>(0);
  /**
   * Create an instance of this symmetric key extended operation.  All
   * initialization should be performed in the
@@ -90,60 +79,23 @@
  public GetSymmetricKeyExtendedOperation()
  {
    super();
  }
  /**
   * {@inheritDoc}
   */
  /** {@inheritDoc} */
  @Override
  public void initializeExtendedOperationHandler(
       GetSymmetricKeyExtendedOperationHandlerCfg config)
         throws ConfigException, InitializationException
  {
    supportedControlOIDs = new HashSet<String>();
    DirectoryServer.registerSupportedExtension(
         ServerConstants.OID_GET_SYMMETRIC_KEY_EXTENDED_OP, this);
    registerControlsAndFeatures();
    super.initializeExtendedOperationHandler(config);
  }
  /**
   * Performs any finalization that may be necessary for this extended
   * operation handler.  By default, no finalization is performed.
   */
  public void finalizeExtendedOperationHandler()
  {
    DirectoryServer.deregisterSupportedExtension(
         ServerConstants.OID_GET_SYMMETRIC_KEY_EXTENDED_OP);
    deregisterControlsAndFeatures();
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public Set<String> getSupportedControls()
  {
    return supportedControlOIDs;
  }
  /**
   * Processes the provided extended operation.
   *
   * @param  operation  The extended operation to be processed.
   */
  @Override
  public void processExtendedOperation(ExtendedOperation operation)
  {
    // Initialize the variables associated with components that may be included
@@ -253,7 +205,7 @@
      writer.writeOctetString(TYPE_INSTANCE_KEY_ID_ELEMENT, instanceKeyID);
      writer.writeEndSequence();
    }
    catch(Exception e)
    catch (IOException e)
    {
      // TODO: DO something
    }
@@ -261,5 +213,17 @@
    return builder.toByteString();
  }
  /** {@inheritDoc} */
  @Override
  public String getExtendedOperationOID()
  {
    return ServerConstants.OID_GET_SYMMETRIC_KEY_EXTENDED_OP;
  }
  /** {@inheritDoc} */
  @Override
  public String getExtendedOperationName()
  {
    return "Get Symmetric Key";
  }
}
opends/src/server/org/opends/server/extensions/CancelExtendedOperation.java
@@ -22,36 +22,26 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions copyright 2012 ForgeRock AS.
 *      Portions copyright 2012-2013 ForgeRock AS
 */
package org.opends.server.extensions;
import org.opends.messages.Message;
import org.opends.server.admin.std.server.CancelExtendedOperationHandlerCfg;
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.loggers.debug.DebugTracer;
import org.opends.server.protocols.asn1.ASN1Reader;
import org.opends.server.protocols.asn1.ASN1;
import org.opends.server.types.ByteString;
import org.opends.server.types.CancelRequest;
import org.opends.server.types.CancelResult;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.InitializationException;
import org.opends.server.types.ResultCode;
import org.opends.server.protocols.asn1.ASN1Reader;
import org.opends.server.types.*;
import static org.opends.messages.ExtensionMessages.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class implements the LDAP cancel extended operation defined in RFC 3909.
 * It is similar to the LDAP abandon operation, with the exception that it
@@ -67,8 +57,6 @@
   */
  private static final DebugTracer TRACER = getTracer();
  /**
   * Create an instance of this cancel extended operation.  All initialization
   * should be performed in the <CODE>initializeExtendedOperationHandler</CODE>
@@ -79,55 +67,21 @@
    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.
   */
  /** {@inheritDoc} */
  @Override
  public void initializeExtendedOperationHandler(
                   CancelExtendedOperationHandlerCfg config)
         throws ConfigException, InitializationException
  {
    // No special configuration is required.
    DirectoryServer.registerSupportedExtension(OID_CANCEL_REQUEST, this);
    registerControlsAndFeatures();
    super.initializeExtendedOperationHandler(config);
  }
  /**
   * Performs any finalization that may be necessary for this extended
   * operation handler.  By default, no finalization is performed.
   */
  @Override
  public void finalizeExtendedOperationHandler()
  {
    DirectoryServer.deregisterSupportedExtension(OID_CANCEL_REQUEST);
    deregisterControlsAndFeatures();
  }
  /**
   * Processes the provided extended operation.
   *
   * @param  operation  The extended operation to be processed.
   */
  @Override
  public void processExtendedOperation(ExtendedOperation operation)
  {
    // The value of the request must be a sequence containing an integer element
@@ -138,34 +92,30 @@
    if (requestValue == null)
    {
      operation.setResultCode(ResultCode.PROTOCOL_ERROR);
      operation.appendErrorMessage(ERR_EXTOP_CANCEL_NO_REQUEST_VALUE.get());
      return;
    }
    else
    try
    {
      try
      ASN1Reader reader = ASN1.getReader(requestValue);
      reader.readStartSequence();
      idToCancel = (int)reader.readInteger();
      reader.readEndSequence();
    }
    catch (Exception e)
    {
      if (debugEnabled())
      {
        ASN1Reader reader = ASN1.getReader(requestValue);
        reader.readStartSequence();
        idToCancel = (int)reader.readInteger();
        reader.readEndSequence();
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      catch (Exception e)
      {
        if (debugEnabled())
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }
        operation.setResultCode(ResultCode.PROTOCOL_ERROR);
      operation.setResultCode(ResultCode.PROTOCOL_ERROR);
        Message message = ERR_EXTOP_CANCEL_CANNOT_DECODE_REQUEST_VALUE.get(
                getExceptionMessage(e));
        operation.appendErrorMessage(message);
        return;
      }
      Message message = ERR_EXTOP_CANCEL_CANNOT_DECODE_REQUEST_VALUE.get(
              getExceptionMessage(e));
      operation.appendErrorMessage(message);
      return;
    }
@@ -188,15 +138,17 @@
    operation.appendErrorMessage(cancelResult.getResponseMessage());
  }
  /** {@inheritDoc} */
  @Override
  public String getExtendedOperationOID()
  {
    return OID_CANCEL_REQUEST;
  }
  /**
   * {@inheritDoc}
   */
  /** {@inheritDoc} */
  @Override
  public String getExtendedOperationName()
  {
    return "Cancel";
  }
}
opends/src/server/org/opends/server/extensions/GetConnectionIDExtendedOperation.java
@@ -22,30 +22,24 @@
 *
 *
 *      Copyright 2008-2009 Sun Microsystems, Inc.
 *      Portions copyright 2013 ForgeRock AS
 */
package org.opends.server.extensions;
import org.opends.server.admin.std.server.
            GetConnectionIdExtendedOperationHandlerCfg;
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.types.InitializationException;
import org.opends.server.types.ResultCode;
import org.opends.server.types.ByteString;
import org.opends.server.types.ByteStringBuilder;
import org.opends.server.protocols.asn1.ASN1Writer;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.protocols.asn1.ASN1;
import org.opends.server.protocols.asn1.ASN1Exception;
import org.opends.server.protocols.asn1.ASN1Reader;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.protocols.asn1.ASN1Writer;
import org.opends.server.types.*;
import org.opends.server.types.DebugLogLevel;
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.util.ServerConstants.*;
/**
 * This class implements the "Get Connection ID" extended operation that can be
@@ -60,8 +54,6 @@
   */
  private static final DebugTracer TRACER = getTracer();
  /**
   * Create an instance of this "Get Connection ID" extended operation.  All
   * initialization should be performed in the
@@ -72,41 +64,19 @@
    super();
  }
  /**
   * {@inheritDoc}
   */
  /** {@inheritDoc} */
  @Override
  public void initializeExtendedOperationHandler(
                   GetConnectionIdExtendedOperationHandlerCfg config)
         throws ConfigException, InitializationException
  {
    // No special configuration is required.
    DirectoryServer.registerSupportedExtension(OID_GET_CONNECTION_ID_EXTOP,
                                               this);
    registerControlsAndFeatures();
    super.initializeExtendedOperationHandler(config);
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public void finalizeExtendedOperationHandler()
  {
    DirectoryServer.deregisterSupportedExtension(OID_GET_CONNECTION_ID_EXTOP);
    deregisterControlsAndFeatures();
  }
  /**
   * {@inheritDoc}
   */
  public void processExtendedOperation(ExtendedOperation operation)
  {
    operation.setResponseOID(OID_GET_CONNECTION_ID_EXTOP);
@@ -172,15 +142,17 @@
    }
  }
  /** {@inheritDoc} */
  @Override
  public String getExtendedOperationOID()
  {
    return OID_GET_CONNECTION_ID_EXTOP;
  }
  /**
   * {@inheritDoc}
   */
  /** {@inheritDoc} */
  @Override
  public String getExtendedOperationName()
  {
    return "Get Connection ID";
  }
}
opends/src/server/org/opends/server/extensions/PasswordModifyExtendedOperation.java
@@ -26,6 +26,7 @@
 */
package org.opends.server.extensions;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.locks.Lock;
@@ -123,9 +124,6 @@
  /** The reference to the identity mapper. */
  private IdentityMapper<?> identityMapper;
  /** The default set of supported control OIDs for this extended. */
  private Set<String> supportedControlOIDs = new HashSet<String>(0);
  /**
   * Create an instance of this password modify extended operation.  All
   * initialization should be performed in the
@@ -133,7 +131,8 @@
   */
  public PasswordModifyExtendedOperation()
  {
    super();
    super(new HashSet<String>(Arrays.asList(
        OID_LDAP_NOOP_OPENLDAP_ASSIGNED, OID_PASSWORD_POLICY_CONTROL)));
  }
  /**
@@ -179,22 +178,13 @@
      throw new InitializationException(message, e);
    }
    supportedControlOIDs = new HashSet<String>();
    supportedControlOIDs.add(OID_LDAP_NOOP_OPENLDAP_ASSIGNED);
    supportedControlOIDs.add(OID_PASSWORD_POLICY_CONTROL);
    // Save this configuration for future reference.
    currentConfig = config;
    // Register this as a change listener.
    config.addPasswordModifyChangeListener(this);
    DirectoryServer.registerSupportedExtension(OID_PASSWORD_MODIFY_REQUEST,
                                               this);
    registerControlsAndFeatures();
    super.initializeExtendedOperationHandler(config);
  }
@@ -208,24 +198,9 @@
  {
    currentConfig.removePasswordModifyChangeListener(this);
    DirectoryServer.deregisterSupportedExtension(OID_PASSWORD_MODIFY_REQUEST);
    deregisterControlsAndFeatures();
    super.finalizeExtendedOperationHandler();
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public Set<String> getSupportedControls()
  {
    return supportedControlOIDs;
  }
  /**
   * Processes the provided extended operation.
   *
@@ -298,11 +273,8 @@
        }
        operation.setResultCode(ResultCode.PROTOCOL_ERROR);
        Message message = ERR_EXTOP_PASSMOD_CANNOT_DECODE_REQUEST.get(
                getExceptionMessage(ae));
        operation.appendErrorMessage(message);
        operation.appendErrorMessage(ERR_EXTOP_PASSMOD_CANNOT_DECODE_REQUEST
            .get(getExceptionMessage(ae)));
        return;
      }
    }
@@ -330,10 +302,8 @@
        if ((! authInfo.isAuthenticated()) || (requestorEntry == null))
        {
          operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
          operation.appendErrorMessage(
                  ERR_EXTOP_PASSMOD_NO_AUTH_OR_USERID.get());
          return;
        }
@@ -350,7 +320,6 @@
          return;
        }
        userEntry = requestorEntry;
      }
      else
@@ -372,10 +341,8 @@
            }
            operation.setResultCode(ResultCode.INVALID_DN_SYNTAX);
            operation.appendErrorMessage(
                    ERR_EXTOP_PASSMOD_CANNOT_DECODE_AUTHZ_DN.get(authzIDStr));
            return;
          }
@@ -405,10 +372,8 @@
                      ERR_EXTOP_PASSMOD_CANNOT_MAP_USER.get(authzIDStr));
              return;
            }
            else
            {
              userDN = userEntry.getDN();
            }
            userDN = userEntry.getDN();
          }
          catch (DirectoryException de)
          {
@@ -434,16 +399,15 @@
          {
            userDN = DN.decode(authzIDStr);
          }
          catch (DirectoryException de)
          catch (DirectoryException ignored)
          {
            if (debugEnabled())
            {
              TRACER.debugCaught(DebugLogLevel.ERROR, de);
              TRACER.debugCaught(DebugLogLevel.ERROR, ignored);
            }
            // IGNORE.
          }
          if ((userDN != null) && (!userDN.isNullDN())) {
          if (userDN != null && !userDN.isNullDN()) {
            // If the provided DN is an alternate DN for a root user,
            // then replace it with the actual root DN.
            DN actualRootDN = DirectoryServer.getActualRootBindDN(userDN);
@@ -456,13 +420,12 @@
            {
              userEntry = identityMapper.getEntryForID(authzIDStr);
            }
            catch (DirectoryException de)
            catch (DirectoryException ignored)
            {
              if (debugEnabled())
              {
                TRACER.debugCaught(DebugLogLevel.ERROR, de);
                TRACER.debugCaught(DebugLogLevel.ERROR, ignored);
              }
              // IGNORE.
            }
          }
@@ -473,10 +436,8 @@
              ERR_EXTOP_PASSMOD_INVALID_AUTHZID_STRING.get(authzIDStr));
            return;
          }
          else
          {
            userDN = userEntry.getDN();
          }
          userDN = userEntry.getDN();
        }
      }
@@ -506,7 +467,6 @@
        }
        operation.setResultCode(DirectoryServer.getServerErrorResultCode());
        operation.appendErrorMessage(
                ERR_EXTOP_PASSMOD_CANNOT_GET_PW_POLICY.get(
                        String.valueOf(userDN),
@@ -552,19 +512,15 @@
      {
        if (pwPolicyRequested)
        {
          pwPolicyErrorType =
               PasswordPolicyErrorType.ACCOUNT_LOCKED;
          pwPolicyErrorType = PasswordPolicyErrorType.ACCOUNT_LOCKED;
          operation.addResponseControl(
               new PasswordPolicyResponseControl(pwPolicyWarningType,
                                                 pwPolicyWarningValue,
                                                 pwPolicyErrorType));
        }
        Message message = ERR_EXTOP_PASSMOD_ACCOUNT_DISABLED.get();
        operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
        operation.appendErrorMessage(message);
        operation.appendErrorMessage(ERR_EXTOP_PASSMOD_ACCOUNT_DISABLED.get());
        return;
      }
      else if (selfChange &&
@@ -574,19 +530,15 @@
      {
        if (pwPolicyRequested)
        {
          pwPolicyErrorType =
               PasswordPolicyErrorType.ACCOUNT_LOCKED;
          pwPolicyErrorType = PasswordPolicyErrorType.ACCOUNT_LOCKED;
          operation.addResponseControl(
               new PasswordPolicyResponseControl(pwPolicyWarningType,
                                                 pwPolicyWarningValue,
                                                 pwPolicyErrorType));
        }
        Message message = ERR_EXTOP_PASSMOD_ACCOUNT_LOCKED.get();
        operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
        operation.appendErrorMessage(message);
        operation.appendErrorMessage(ERR_EXTOP_PASSMOD_ACCOUNT_LOCKED.get());
        return;
      }
@@ -601,7 +553,6 @@
                .isPasswordChangeRequiresCurrentPassword())
        {
          operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
          operation.appendErrorMessage(
                  ERR_EXTOP_PASSMOD_REQUIRE_CURRENT_PW.get());
@@ -622,7 +573,7 @@
      {
        if (pwPolicyState.getAuthenticationPolicy()
            .isRequireSecureAuthentication()
            && (!operation.getClientConnection().isSecure()))
            && !operation.getClientConnection().isSecure())
        {
          operation.setResultCode(ResultCode.CONFIDENTIALITY_REQUIRED);
          operation.addAdditionalLogItem(AdditionalLogItem.quotedKeyValue(
@@ -659,13 +610,12 @@
      // If it is a self password change and we don't allow that, then reject
      // the request.
      if (selfChange
          && (!pwPolicyState.getAuthenticationPolicy()
              .isAllowUserPasswordChanges()))
          && !pwPolicyState.getAuthenticationPolicy()
              .isAllowUserPasswordChanges())
      {
        if (pwPolicyRequested)
        {
          pwPolicyErrorType =
               PasswordPolicyErrorType.PASSWORD_MOD_NOT_ALLOWED;
          pwPolicyErrorType = PasswordPolicyErrorType.PASSWORD_MOD_NOT_ALLOWED;
          operation.addResponseControl(
               new PasswordPolicyResponseControl(pwPolicyWarningType,
                                                 pwPolicyWarningValue,
@@ -673,7 +623,6 @@
        }
        operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
        operation.appendErrorMessage(
                ERR_EXTOP_PASSMOD_USER_PW_CHANGES_NOT_ALLOWED.get());
        return;
@@ -684,10 +633,9 @@
      // then reject the request.
      if (pwPolicyState.getAuthenticationPolicy()
          .isRequireSecurePasswordChanges()
          && (!operation.getClientConnection().isSecure()))
          && !operation.getClientConnection().isSecure())
      {
        operation.setResultCode(ResultCode.CONFIDENTIALITY_REQUIRED);
        operation.appendErrorMessage(
                ERR_EXTOP_PASSMOD_SECURE_CHANGES_REQUIRED.get());
        return;
@@ -700,8 +648,7 @@
      {
        if (pwPolicyRequested)
        {
          pwPolicyErrorType =
               PasswordPolicyErrorType.PASSWORD_TOO_YOUNG;
          pwPolicyErrorType = PasswordPolicyErrorType.PASSWORD_TOO_YOUNG;
          operation.addResponseControl(
               new PasswordPolicyResponseControl(pwPolicyWarningType,
                                                 pwPolicyWarningValue,
@@ -709,22 +656,21 @@
        }
        operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
        operation.appendErrorMessage(ERR_EXTOP_PASSMOD_IN_MIN_AGE.get());
        return;
      }
      // If the user's password is expired and it's a self-change request, then
      // see if that's OK.
      if ((selfChange && pwPolicyState.isPasswordExpired() && (!pwPolicyState
          .getAuthenticationPolicy().isAllowExpiredPasswordChanges())))
      if (selfChange
          && pwPolicyState.isPasswordExpired()
          && !pwPolicyState.getAuthenticationPolicy()
              .isAllowExpiredPasswordChanges())
      {
        if (pwPolicyRequested)
        {
          pwPolicyErrorType =
               PasswordPolicyErrorType.PASSWORD_EXPIRED;
          pwPolicyErrorType = PasswordPolicyErrorType.PASSWORD_EXPIRED;
          operation.addResponseControl(
               new PasswordPolicyResponseControl(pwPolicyWarningType,
                                                 pwPolicyWarningValue,
@@ -732,7 +678,6 @@
        }
        operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
        operation.appendErrorMessage(
                ERR_EXTOP_PASSMOD_PASSWORD_IS_EXPIRED.get());
        return;
@@ -752,15 +697,12 @@
          if (newPassword == null)
          {
            operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
            operation.appendErrorMessage(
                    ERR_EXTOP_PASSMOD_NO_PW_GENERATOR.get());
            return;
          }
          else
          {
            generatedPassword = true;
          }
          generatedPassword = true;
        }
        catch (DirectoryException de)
        {
@@ -770,7 +712,6 @@
          }
          operation.setResultCode(de.getResultCode());
          operation.appendErrorMessage(
                  ERR_EXTOP_PASSMOD_CANNOT_GENERATE_PW.get(
                          de.getMessageObject()));
@@ -789,7 +730,6 @@
              .isAllowPreEncodedPasswords())
          {
            operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
            operation.appendErrorMessage(
                    ERR_EXTOP_PASSMOD_PRE_ENCODED_NOT_ALLOWED.get());
            return;
@@ -799,10 +739,10 @@
        {
          // Run the new password through the set of password validators.
          if (selfChange
              || (!pwPolicyState.getAuthenticationPolicy()
                  .isSkipValidationForAdministrators()))
              || !pwPolicyState.getAuthenticationPolicy()
                  .isSkipValidationForAdministrators())
          {
            HashSet<ByteString> clearPasswords;
            Set<ByteString> clearPasswords;
            if (oldPassword == null)
            {
              clearPasswords =
@@ -838,7 +778,6 @@
              }
              operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
              operation.appendErrorMessage(
                      ERR_EXTOP_PASSMOD_UNACCEPTABLE_PW.get(
                              String.valueOf(invalidReason)));
@@ -852,11 +791,11 @@
          {
            if (pwPolicyState.isPasswordInHistory(newPassword))
            {
              if (selfChange || (! pwPolicyState.getAuthenticationPolicy().
                                      isSkipValidationForAdministrators()))
              if (selfChange
                  || !pwPolicyState.getAuthenticationPolicy()
                      .isSkipValidationForAdministrators())
              {
                operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
                operation.appendErrorMessage(
                        ERR_EXTOP_PASSMOD_PW_IN_HISTORY.get());
                return;
@@ -892,7 +831,6 @@
          }
          operation.setResultCode(de.getResultCode());
          operation.appendErrorMessage(
                  ERR_EXTOP_PASSMOD_CANNOT_ENCODE_PASSWORD.get(
                          de.getMessageObject()));
@@ -1043,152 +981,149 @@
      if (noOpRequested)
      {
        operation.appendErrorMessage(WARN_EXTOP_PASSMOD_NOOP.get());
        operation.setResultCode(ResultCode.NO_OPERATION);
        return;
      }
      if (selfChange && requestorEntry == null)
      {
        requestorEntry = userEntry;
      }
      // Get an internal connection and use it to perform the modification.
      boolean isRoot = DirectoryServer.isRootDN(requestorEntry.getDN());
      AuthenticationInfo authInfo = new AuthenticationInfo(requestorEntry,
                                                           isRoot);
      InternalClientConnection internalConnection = new
           InternalClientConnection(authInfo);
      ModifyOperation modifyOperation =
           internalConnection.processModify(userDN, modList);
      ResultCode resultCode = modifyOperation.getResultCode();
      if (resultCode != ResultCode.SUCCESS)
      {
        operation.setResultCode(resultCode);
        operation.setErrorMessage(modifyOperation.getErrorMessage());
        operation.setReferralURLs(modifyOperation.getReferralURLs());
        return;
      }
      // If there were any password policy state changes, we need to apply
      // them using a root connection because the end user may not have
      // sufficient access to apply them.  This is less efficient than
      // doing them all in the same modification, but it's safer.
      List<Modification> pwPolicyMods = pwPolicyState.getModifications();
      if (! pwPolicyMods.isEmpty())
      {
        InternalClientConnection rootConnection =
             InternalClientConnection.getRootConnection();
        ModifyOperation modOp =
             rootConnection.processModify(userDN, pwPolicyMods);
        if (modOp.getResultCode() != ResultCode.SUCCESS)
        {
          // At this point, the user's password is already changed so there's
          // not much point in returning a non-success result.  However, we
          // should at least log that something went wrong.
          ErrorLogger.logError(WARN_EXTOP_PASSMOD_CANNOT_UPDATE_PWP_STATE.get(
                  String.valueOf(userDN),
                  String.valueOf(modOp.getResultCode()),
                  modOp.getErrorMessage()));
        }
      }
      // If we've gotten here, then everything is OK, so indicate that the
      // operation was successful.
      operation.setResultCode(ResultCode.SUCCESS);
      // Save attachments for post-op plugins (e.g. Samba password plugin).
      operation.setAttachment(AUTHZ_DN_ATTACHMENT, userDN);
      operation.setAttachment(PWD_ATTRIBUTE_ATTACHMENT, pwPolicyState
          .getAuthenticationPolicy().getPasswordAttribute());
      if (!isPreEncoded)
      {
        operation.setAttachment(CLEAR_PWD_ATTACHMENT, newPassword);
      }
      operation.setAttachment(ENCODED_PWD_ATTACHMENT, encodedPasswords);
      // If a password was generated, then include it in the response.
      if (generatedPassword)
      {
        ByteStringBuilder builder = new ByteStringBuilder();
        ASN1Writer writer = ASN1.getWriter(builder);
        try
        {
          writer.writeStartSequence();
          writer.writeOctetString(TYPE_PASSWORD_MODIFY_GENERATED_PASSWORD,
              newPassword);
          writer.writeEndSequence();
        }
        catch (IOException e)
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }
        operation.setResponseValue(builder.toByteString());
      }
      // If this was a self password change, and the client is authenticated
      // as the user whose password was changed, then clear the "must change
      // password" flag in the client connection.  Note that we're using the
      // authentication DN rather than the authorization DN in this case to
      // avoid mistakenly clearing the flag for the wrong user.
      if (selfChange && (authInfo.getAuthenticationDN() != null) &&
          (authInfo.getAuthenticationDN().equals(userDN)))
      {
        operation.getClientConnection().setMustChangePassword(false);
      }
      // If the password policy control was requested, then add the
      // appropriate response control.
      if (pwPolicyRequested)
      {
        operation.addResponseControl(
             new PasswordPolicyResponseControl(pwPolicyWarningType,
                                               pwPolicyWarningValue,
                                               pwPolicyErrorType));
      }
      // Handle Account Status Notifications that may be needed.
      // They are not handled by the backend for internal operations.
      List<AttributeValue> currentPasswords = null;
      if (oldPassword != null)
      {
        currentPasswords = new ArrayList<AttributeValue>(1);
        currentPasswords.add(AttributeValues
                            .create(oldPassword, oldPassword));
      }
      List<AttributeValue> newPasswords = null;
      if (newPassword != null)
      {
        newPasswords = new ArrayList<AttributeValue>(1);
        newPasswords.add(AttributeValues
                         .create(newPassword, newPassword));
      }
      if (selfChange)
      {
        Message message = INFO_MODIFY_PASSWORD_CHANGED.get();
        pwPolicyState.generateAccountStatusNotification(
          AccountStatusNotificationType.PASSWORD_CHANGED,
          userEntry, message,
          AccountStatusNotification.createProperties(pwPolicyState, false,
                -1, currentPasswords, newPasswords));
      }
      else
      {
        if (selfChange && (requestorEntry == null))
        {
          requestorEntry = userEntry;
        }
        // Get an internal connection and use it to perform the modification.
        boolean isRoot = DirectoryServer.isRootDN(requestorEntry.getDN());
        AuthenticationInfo authInfo = new AuthenticationInfo(requestorEntry,
                                                             isRoot);
        InternalClientConnection internalConnection = new
             InternalClientConnection(authInfo);
        ModifyOperation modifyOperation =
             internalConnection.processModify(userDN, modList);
        ResultCode resultCode = modifyOperation.getResultCode();
        if (resultCode != ResultCode.SUCCESS)
        {
          operation.setResultCode(resultCode);
          operation.setErrorMessage(modifyOperation.getErrorMessage());
          operation.setReferralURLs(modifyOperation.getReferralURLs());
          return;
        }
        // If there were any password policy state changes, we need to apply
        // them using a root connection because the end user may not have
        // sufficient access to apply them.  This is less efficient than
        // doing them all in the same modification, but it's safer.
        List<Modification> pwPolicyMods = pwPolicyState.getModifications();
        if (! pwPolicyMods.isEmpty())
        {
          InternalClientConnection rootConnection =
               InternalClientConnection.getRootConnection();
          ModifyOperation modOp =
               rootConnection.processModify(userDN, pwPolicyMods);
          if (modOp.getResultCode() != ResultCode.SUCCESS)
          {
            // At this point, the user's password is already changed so there's
            // not much point in returning a non-success result.  However, we
            // should at least log that something went wrong.
            Message message = WARN_EXTOP_PASSMOD_CANNOT_UPDATE_PWP_STATE.get(
                    String.valueOf(userDN),
                    String.valueOf(modOp.getResultCode()),
                    modOp.getErrorMessage());
            ErrorLogger.logError(message);
          }
        }
        // If we've gotten here, then everything is OK, so indicate that the
        // operation was successful.
        operation.setResultCode(ResultCode.SUCCESS);
        // Save attachments for post-op plugins (e.g. Samba password plugin).
        operation.setAttachment(AUTHZ_DN_ATTACHMENT, userDN);
        operation.setAttachment(PWD_ATTRIBUTE_ATTACHMENT, pwPolicyState
            .getAuthenticationPolicy().getPasswordAttribute());
        if (!isPreEncoded)
        {
          operation.setAttachment(CLEAR_PWD_ATTACHMENT, newPassword);
        }
        operation.setAttachment(ENCODED_PWD_ATTACHMENT, encodedPasswords);
        // If a password was generated, then include it in the response.
        if (generatedPassword)
        {
          ByteStringBuilder builder = new ByteStringBuilder();
          ASN1Writer writer = ASN1.getWriter(builder);
          try
          {
          writer.writeStartSequence();
          writer.writeOctetString(TYPE_PASSWORD_MODIFY_GENERATED_PASSWORD,
                                   newPassword);
          writer.writeEndSequence();
          }
          catch(Exception e)
          {
            TRACER.debugCaught(DebugLogLevel.ERROR, e);
          }
          operation.setResponseValue(builder.toByteString());
        }
        // If this was a self password change, and the client is authenticated
        // as the user whose password was changed, then clear the "must change
        // password" flag in the client connection.  Note that we're using the
        // authentication DN rather than the authorization DN in this case to
        // avoid mistakenly clearing the flag for the wrong user.
        if (selfChange && (authInfo.getAuthenticationDN() != null) &&
            (authInfo.getAuthenticationDN().equals(userDN)))
        {
          operation.getClientConnection().setMustChangePassword(false);
        }
        // If the password policy control was requested, then add the
        // appropriate response control.
        if (pwPolicyRequested)
        {
          operation.addResponseControl(
               new PasswordPolicyResponseControl(pwPolicyWarningType,
                                                 pwPolicyWarningValue,
                                                 pwPolicyErrorType));
        }
        // Handle Account Status Notifications that may be needed.
        // They are not handled by the backend for internal operations.
        List<AttributeValue> currentPasswords = null;
        if (oldPassword != null)
        {
          currentPasswords = new ArrayList<AttributeValue>(1);
          currentPasswords.add(AttributeValues
                              .create(oldPassword, oldPassword));
        }
        List<AttributeValue> newPasswords = null;
        if (newPassword != null)
        {
          newPasswords = new ArrayList<AttributeValue>(1);
          newPasswords.add(AttributeValues
                           .create(newPassword, newPassword));
        }
        if (selfChange)
        {
          Message message = INFO_MODIFY_PASSWORD_CHANGED.get();
          pwPolicyState.generateAccountStatusNotification(
            AccountStatusNotificationType.PASSWORD_CHANGED,
            userEntry, message,
            AccountStatusNotification.createProperties(pwPolicyState, false,
                  -1, currentPasswords, newPasswords));
        }
        else
        {
          Message message = INFO_MODIFY_PASSWORD_RESET.get();
          pwPolicyState.generateAccountStatusNotification(
            AccountStatusNotificationType.PASSWORD_RESET,
            userEntry, message,
            AccountStatusNotification.createProperties(pwPolicyState, false,
                  -1, currentPasswords, newPasswords));
        }
        Message message = INFO_MODIFY_PASSWORD_RESET.get();
        pwPolicyState.generateAccountStatusNotification(
          AccountStatusNotificationType.PASSWORD_RESET,
          userEntry, message,
          AccountStatusNotification.createProperties(pwPolicyState, false,
                -1, currentPasswords, newPasswords));
      }
    }
    finally
@@ -1258,7 +1193,6 @@
      operation.appendErrorMessage(de.getMessageObject());
      operation.setMatchedDN(de.getMatchedDN());
      operation.setReferralURLs(de.getReferralURLs());
      return null;
    }
  }
@@ -1428,15 +1362,17 @@
    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
  }
  /** {@inheritDoc} */
  @Override
  public String getExtendedOperationOID()
  {
    return OID_PASSWORD_MODIFY_REQUEST;
  }
  /**
   * {@inheritDoc}
   */
  /** {@inheritDoc} */
  @Override
  public String getExtendedOperationName()
  {
    return "Password Modify";
  }
}
opends/src/server/org/opends/server/extensions/PasswordPolicyStateExtendedOperation.java
@@ -22,16 +22,14 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2011 ForgeRock AS
 *      Portions Copyright 2011-2013 ForgeRock AS
 */
package org.opends.server.extensions;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.io.IOException;
import org.opends.messages.Message;
import org.opends.server.admin.std.server.
@@ -40,27 +38,21 @@
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.core.*;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.protocols.asn1.ASN1;
import org.opends.server.protocols.asn1.ASN1Reader;
import org.opends.server.protocols.asn1.ASN1Writer;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.protocols.asn1.ASN1Reader;
import org.opends.server.protocols.asn1.ASN1;
import org.opends.server.protocols.asn1.ASN1Writer;
import org.opends.server.schema.GeneralizedTimeSyntax;
import org.opends.server.types.*;
import static org.opends.messages.CoreMessages.*;
import static org.opends.messages.ExtensionMessages.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
import static org.opends.messages.CoreMessages.INFO_MODIFY_ACCOUNT_DISABLED;
import static org.opends.messages.CoreMessages.INFO_MODIFY_ACCOUNT_ENABLED;
/**
 * This class implements an LDAP extended operation that can be used to query
@@ -137,302 +129,120 @@
  private static final DebugTracer TRACER = getTracer();
  /**
   * The enumerated value for the getPasswordPolicyDN operation.
   */
  /** The enumerated value for the getPasswordPolicyDN operation. */
  public static final int OP_GET_PASSWORD_POLICY_DN = 0;
  /**
   * The enumerated value for the getAccountDisabledState operation.
   */
  /** The enumerated value for the getAccountDisabledState operation. */
  public static final int OP_GET_ACCOUNT_DISABLED_STATE = 1;
  /**
   * The enumerated value for the setAccountDisabledState operation.
   */
  /** The enumerated value for the setAccountDisabledState operation. */
  public static final int OP_SET_ACCOUNT_DISABLED_STATE = 2;
  /**
   * The enumerated value for the clearAccountDisabledState operation.
   */
  /** The enumerated value for the clearAccountDisabledState operation. */
  public static final int OP_CLEAR_ACCOUNT_DISABLED_STATE = 3;
  /**
   * The enumerated value for the getAccountExpirationTime operation.
   */
  /** The enumerated value for the getAccountExpirationTime operation. */
  public static final int OP_GET_ACCOUNT_EXPIRATION_TIME = 4;
  /**
   * The enumerated value for the setAccountExpirationTime operation.
   */
  /** The enumerated value for the setAccountExpirationTime operation. */
  public static final int OP_SET_ACCOUNT_EXPIRATION_TIME = 5;
  /**
   * The enumerated value for the clearAccountExpirationTime operation.
   */
  /** 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.
   */
  /** The enumerated value for the getPasswordChangedTime operation. */
  public static final int OP_GET_PASSWORD_CHANGED_TIME = 8;
  /**
   * The enumerated value for the setPasswordChangedTime operation.
   */
  /** The enumerated value for the setPasswordChangedTime operation. */
  public static final int OP_SET_PASSWORD_CHANGED_TIME = 9;
  /**
   * The enumerated value for the clearPasswordChangedTime operation.
   */
  /** The enumerated value for the clearPasswordChangedTime operation. */
  public static final int OP_CLEAR_PASSWORD_CHANGED_TIME = 10;
  /**
   * The enumerated value for the getPasswordExpirationWarnedTime operation.
   */
  /** 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.
   */
  /** 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.
   */
  /** The enumerated value for the getAuthenticationFailureTimes operation. */
  public static final int OP_GET_AUTHENTICATION_FAILURE_TIMES = 16;
  /**
   * The enumerated value for the addAuthenticationFailureTime operation.
   */
  /** The enumerated value for the addAuthenticationFailureTime operation. */
  public static final int OP_ADD_AUTHENTICATION_FAILURE_TIME = 17;
  /**
   * The enumerated value for the setAuthenticationFailureTimes operation.
   */
  /** The enumerated value for the setAuthenticationFailureTimes operation. */
  public static final int OP_SET_AUTHENTICATION_FAILURE_TIMES = 18;
  /**
   * The enumerated value for the clearAuthenticationFailureTimes operation.
   */
  /** 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.
   */
  /** The enumerated value for the getLastLoginTime operation. */
  public static final int OP_GET_LAST_LOGIN_TIME = 22;
  /**
   * The enumerated value for the setLastLoginTime operation.
   */
  /** The enumerated value for the setLastLoginTime operation. */
  public static final int OP_SET_LAST_LOGIN_TIME = 23;
  /**
   * The enumerated value for the clearLastLoginTime operation.
   */
  /** The enumerated value for the clearLastLoginTime operation. */
  public static final int OP_CLEAR_LAST_LOGIN_TIME = 24;
  /**
   * The enumerated value for the getSecondsUntilIdleLockout operation.
   */
  /** 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.
   */
  /** The enumerated value for the getPasswordResetState operation. */
  public static final int OP_GET_PASSWORD_RESET_STATE = 26;
  /**
   * The enumerated value for the setPasswordResetState operation.
   */
  /** The enumerated value for the setPasswordResetState operation. */
  public static final int OP_SET_PASSWORD_RESET_STATE = 27;
  /**
   * The enumerated value for the clearPasswordResetState operation.
   */
  /** 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.
   */
  /** 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.
   */
  /** 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.
   */
  /** 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.
   */
  /** 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.
   */
  /** 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 enumerated value for the getPasswordHistory operation.
   */
  /** The enumerated value for the getPasswordHistory operation. */
  public static final int OP_GET_PASSWORD_HISTORY = 39;
  /**
   * The enumerated value for the clearPasswordHistory operation.
   */
  /** The enumerated value for the clearPasswordHistory operation. */
  public static final int OP_CLEAR_PASSWORD_HISTORY = 40;
  // The set of attributes to request when retrieving a user's entry.
  /** 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.
  /** The search filter that will be used to retrieve user entries. */
  private SearchFilter userFilter;
  private boolean isAccountSetDisabled;
@@ -465,6 +275,7 @@
   *                                   that is not related to the server
   *                                   configuration.
   */
  @Override
  public void initializeExtendedOperationHandler(
                   PasswordPolicyStateExtendedOperationHandlerCfg config)
         throws ConfigException, InitializationException
@@ -492,29 +303,15 @@
    DirectoryServer.registerSupportedExtension(OID_PASSWORD_POLICY_STATE_EXTOP,
                                               this);
    // FIXME registerControlAndFeatures?
  }
  /**
   * Performs any finalization that may be necessary for this extended
   * operation handler.  By default, no finalization is performed.
   */
  @Override
  public void finalizeExtendedOperationHandler()
  {
    DirectoryServer.deregisterSupportedExtension(
      OID_PASSWORD_POLICY_STATE_EXTOP);
    deregisterControlsAndFeatures();
  }
  /**
   * Processes the provided extended operation.
   *
   * @param  operation  The extended operation to be processed.
   */
  @Override
  public void processExtendedOperation(ExtendedOperation operation)
  {
    operation.setResultCode(ResultCode.UNDEFINED);
@@ -696,7 +493,7 @@
      // 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()))
      if (stateMods != null && !stateMods.isEmpty())
      {
        ModifyOperation modifyOperation =
            conn.processModify(targetDN, stateMods);
@@ -852,7 +649,7 @@
    writer.writeStartSequence();
    writer.writeEnumerated(opType);
    if ((value != null))
    if (value != null)
    {
      writer.writeStartSequence();
      writer.writeOctetString(value);
@@ -880,12 +677,12 @@
    writer.writeStartSequence();
    writer.writeEnumerated(opType);
    if ((values != null) && (values.length > 0))
    if (values != null && values.length > 0)
    {
      writer.writeStartSequence();
      for (int i=0; i < values.length; i++)
      for (String value : values)
      {
        writer.writeOctetString(values[i]);
        writer.writeOctetString(value);
      }
      writer.writeEndSequence();
    }
@@ -909,7 +706,7 @@
    writer.writeStartSequence();
    writer.writeEnumerated(opType);
    if ((values != null) && (values.size() > 0))
    if (values != null && values.size() > 0)
    {
      writer.writeStartSequence();
      for (long l : values)
@@ -1329,12 +1126,12 @@
        else
        {
          String value = opValues.get(0);
          if (value.equalsIgnoreCase("true"))
          if ("true".equalsIgnoreCase(value))
          {
            pwpState.setDisabled(true);
            isAccountSetDisabled = true;
          }
          else if (value.equalsIgnoreCase("false"))
          else if ("false".equalsIgnoreCase(value))
          {
            pwpState.setDisabled(false);
            isAccountSetEnabled = true;
@@ -1674,11 +1471,11 @@
        else
        {
          String value = opValues.get(0);
          if (value.equalsIgnoreCase("true"))
          if ("true".equalsIgnoreCase(value))
          {
            pwpState.setMustChangePassword(true);
          }
          else if (value.equalsIgnoreCase("false"))
          else if ("false".equalsIgnoreCase(value))
          {
            pwpState.setMustChangePassword(false);
          }
@@ -1859,15 +1656,17 @@
    return true;
  }
  /** {@inheritDoc} */
  @Override
  public String getExtendedOperationOID()
  {
    return OID_PASSWORD_POLICY_STATE_EXTOP;
  }
  /**
   * {@inheritDoc}
   */
  /** {@inheritDoc} */
  @Override
  public String getExtendedOperationName()
  {
    return "Password Policy State";
  }
}
opends/src/server/org/opends/server/extensions/StartTLSExtendedOperation.java
@@ -26,25 +26,18 @@
 */
package org.opends.server.extensions;
import org.opends.messages.MessageBuilder;
import org.opends.server.admin.std.server.StartTLSExtendedOperationHandlerCfg;
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.loggers.debug.DebugTracer;
import org.opends.server.types.InitializationException;
import org.opends.server.types.ResultCode;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.messages.ExtensionMessages.*;
import static org.opends.server.util.ServerConstants.*;
/**
 * This class provides an implementation of the StartTLS extended operation as
 * defined in RFC 2830.  It can enable the TLS connection security provider on
@@ -54,12 +47,6 @@
public class StartTLSExtendedOperation
       extends ExtendedOperationHandler<StartTLSExtendedOperationHandlerCfg>
{
  /**
   * The tracer object for the debug logger.
   */
  private static final DebugTracer TRACER = getTracer();
  /**
   * Create an instance of this StartTLS extended operation handler.  All
@@ -71,54 +58,21 @@
    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.
   */
  /** {@inheritDoc} */
  @Override
  public void initializeExtendedOperationHandler(
                   StartTLSExtendedOperationHandlerCfg config)
         throws ConfigException, InitializationException
  {
    // FIXME -- Are there any configurable options that we should support?
    DirectoryServer.registerSupportedExtension(OID_START_TLS_REQUEST, this);
    registerControlsAndFeatures();
    super.initializeExtendedOperationHandler(config);
  }
  /**
   * Performs any finalization that may be necessary for this extended
   * operation handler.  By default, no finalization is performed.
   */
  @Override
  public void finalizeExtendedOperationHandler()
  {
    DirectoryServer.deregisterSupportedExtension(OID_START_TLS_REQUEST);
    deregisterControlsAndFeatures();
  }
  /**
   * Processes the provided extended operation.
   *
   * @param  operation  The extended operation to be processed.
   */
  @Override
  public void processExtendedOperation(ExtendedOperation operation)
  {
    // We should always include the StartTLS OID in the response (the same OID
@@ -164,15 +118,17 @@
    operation.setResultCode(ResultCode.SUCCESS);
  }
  /** {@inheritDoc} */
  @Override
  public String getExtendedOperationOID()
  {
    return OID_START_TLS_REQUEST;
  }
  /**
   * {@inheritDoc}
   */
  /** {@inheritDoc} */
  @Override
  public String getExtendedOperationName()
  {
    return "StartTLS";
  }
}
opends/src/server/org/opends/server/extensions/WhoAmIExtendedOperation.java
@@ -22,16 +22,12 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2012 ForgeRock AS
 *      Portions Copyright 2011-2013 ForgeRock AS
 */
package org.opends.server.extensions;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.opends.server.admin.std.server.WhoAmIExtendedOperationHandlerCfg;
import org.opends.server.api.ClientConnection;
@@ -39,7 +35,6 @@
import org.opends.server.config.ConfigException;
import org.opends.server.controls.ProxiedAuthV1Control;
import org.opends.server.controls.ProxiedAuthV2Control;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ExtendedOperation;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.*;
@@ -48,7 +43,6 @@
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.util.ServerConstants.*;
/**
 * This class implements the "Who Am I?" extended operation defined in RFC 4532.
 * It simply returns the authorized ID of the currently-authenticated user.
@@ -61,12 +55,6 @@
   */
  private static final DebugTracer TRACER = getTracer();
  /** The default set of supported control OIDs for this extended. */
  private final Set<String> supportedControlOIDs =
      Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
          OID_PROXIED_AUTH_V1, OID_PROXIED_AUTH_V2)));
  /**
   * Create an instance of this "Who Am I?" extended operation.  All
   * initialization should be performed in the
@@ -74,55 +62,17 @@
   */
  public WhoAmIExtendedOperation()
  {
    super();
    super(new HashSet<String>(Arrays.asList(
        OID_PROXIED_AUTH_V1, OID_PROXIED_AUTH_V2)));
  }
  /**
   * 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.
   */
  /** {@inheritDoc} */
  @Override
  public void initializeExtendedOperationHandler(
                   WhoAmIExtendedOperationHandlerCfg config)
         throws ConfigException, InitializationException
  {
    DirectoryServer.registerSupportedExtension(OID_WHO_AM_I_REQUEST, this);
    registerControlsAndFeatures();
  }
  /**
   * Performs any finalization that may be necessary for this extended
   * operation handler.  By default, no finalization is performed.
   */
  @Override()
  public void finalizeExtendedOperationHandler()
  {
    DirectoryServer.deregisterSupportedExtension(OID_WHO_AM_I_REQUEST);
    deregisterControlsAndFeatures();
  }
  /** {@inheritDoc} */
  @Override()
  public Set<String> getSupportedControls()
  {
    return supportedControlOIDs;
    super.initializeExtendedOperationHandler(config);
  }
  /** {@inheritDoc} */
@@ -201,9 +151,15 @@
  /** {@inheritDoc} */
  @Override
  public String getExtendedOperationOID()
  {
    return OID_WHO_AM_I_REQUEST;
  }
  /** {@inheritDoc} */
  @Override
  public String getExtendedOperationName()
  {
    return "Who Am I?";
  }
}