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

neil_a_wilson
09.09.2007 93ff600530bef0b1acb70290b0d6cc38653e5fb9
Update the access control API to get rid of the AccessControlProvider interface
and move all of its methods into the abstract AccessControlHandler class. This
makes the access control API more future-proof because the use of an interface
would not allow the introduction of new methods into the API (such as will be
required for issue #1861) without breaking backward compatibility, and
potentially interfering with third-party implementations.

Also, the access control handler config manager implementation has been
dramatically simplified.

OpenDS Issue Number: 1912
3 files deleted
1 files added
5 files modified
1507 ■■■■■ changed files
opends/resource/config/config.ldif 2 ●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/AccessControlHandlerConfiguration.xml 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/AccessControlHandler.java 180 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/AccessControlProvider.java 87 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java 198 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/AciProvider.java 87 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/AccessControlConfigManager.java 493 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/DefaultAccessControlHandler.java 239 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/DefaultAccessControlProvider.java 219 ●●●●● patch | view | raw | blame | history
opends/resource/config/config.ldif
@@ -57,7 +57,7 @@
ds-cfg-global-aci: (target="ldap:///")(targetscope="base")(targetattr="namingContexts||supportedAuthPasswordSchemes||supportedControl||supportedExtension||supportedFeatures||supportedSASLMechanisms||vendorName||vendorVersion")(version 3.0; acl "User-Visible Root DSE Operational Attributes"; allow (read,search,compare) userdn="ldap:///anyone";)
ds-cfg-global-aci: (targetattr="createTimestamp||creatorsName||modifiersName||modifyTimestamp||entryDN||entryUUID||subschemaSubentry")(version 3.0; acl "User-Visible Operational Attributes"; allow (read,search,compare) userdn="ldap:///anyone";)
cn: Access Control Handler
ds-cfg-acl-handler-class: org.opends.server.authorization.dseecompat.AciProvider
ds-cfg-acl-handler-class: org.opends.server.authorization.dseecompat.AciHandler
ds-cfg-acl-handler-enabled: true
dn: cn=Account Status Notification Handlers,cn=config
opends/src/admin/defn/org/opends/server/admin/std/AccessControlHandlerConfiguration.xml
@@ -68,7 +68,7 @@
    <adm:syntax>
      <adm:java-class>
        <adm:instance-of>
          org.opends.server.api.AccessControlProvider
          org.opends.server.api.AccessControlHandler
        </adm:instance-of>
      </adm:java-class>
    </adm:syntax>
opends/src/server/org/opends/server/api/AccessControlHandler.java
@@ -27,21 +27,61 @@
package org.opends.server.api;
import org.opends.server.admin.std.server.AccessControlHandlerCfg;
import org.opends.server.config.ConfigException;
import org.opends.server.core.*;
import org.opends.server.types.*;
import org.opends.server.workflowelement.localbackend.*;
/**
 * This class defines the set of methods and structures that must be
 * implemented by a Directory Server access control handler.  All
 * methods in this class should take the entire request into account
 * when making the determination, including any request controls that
 * might have been provided.
 *
 * @param  <T>  The type of access control configuration handled by
 *              this access control provider implementation.
 */
public abstract class AccessControlHandler
                      <T extends AccessControlHandlerCfg>
{
  /**
   * Initializes the access control handler implementation based on
   * the information in the provided configuration entry.
   *
   * @param  configuration  The configuration object that contains the
   *                        information to use to initialize this
   *                        access control 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.
   */
  public abstract void initializeAccessControlHandler(T configuration)
         throws ConfigException, InitializationException;
  /**
   * Performs any necessary finalization for the access control
   * handler implementation. This will be called just after the
   * handler has been deregistered with the server but before it has
   * been unloaded.
   */
  public abstract void finalizeAccessControlHandler();
  /**
   * Indicates whether the provided add operation is allowed based on
   * the access control configuration.  This method should not alter
   * the provided add operation in any way.
@@ -49,12 +89,11 @@
   * @param  addOperation  The operation for which to make the
   *                       determination.
   *
   * @return  <CODE>true</CODE> if the operation should be allowed by
   *          the access control configuration, or <CODE>false</CODE>
   *          if not.
   * @return  {@code true} if the operation should be allowed by the
   *          access control configuration, or {@code false} if not.
   */
  public abstract boolean isAllowed(LocalBackendAddOperation
      addOperation);
                                         addOperation);
@@ -66,12 +105,11 @@
   * @param  bindOperation  The operation for which to make the
   *                        determination.
   *
   * @return  <CODE>true</CODE> if the operation should be allowed by
   *          the access control configuration, or <CODE>false</CODE>
   *          if not.
   * @return  {@code true} if the operation should be allowed by the
   *          access control configuration, or {@code false} if not.
   */
  public abstract boolean isAllowed(LocalBackendBindOperation
      bindOperation);
                                         bindOperation);
@@ -83,9 +121,8 @@
   * @param  compareOperation  The operation for which to make the
   *                           determination.
   *
   * @return  <CODE>true</CODE> if the operation should be allowed by
   *          the access control configuration, or <CODE>false</CODE>
   *          if not.
   * @return  {@code true} if the operation should be allowed by the
   *          access control configuration, or {@code false} if not.
   */
  public abstract boolean isAllowed(CompareOperation
                                         compareOperation);
@@ -100,12 +137,11 @@
   * @param  deleteOperation  The operation for which to make the
   *                          determination.
   *
   * @return  <CODE>true</CODE> if the operation should be allowed by
   *          the access control configuration, or <CODE>false</CODE>
   *          if not.
   * @return  {@code true} if the operation should be allowed by the
   *          access control configuration, or {@code false} if not.
   */
  public abstract boolean isAllowed(LocalBackendDeleteOperation
      deleteOperation);
                                         deleteOperation);
@@ -117,9 +153,8 @@
   * @param  extendedOperation  The operation for which to make the
   *                            determination.
   *
   * @return  <CODE>true</CODE> if the operation should be allowed by
   *          the access control configuration, or <CODE>false</CODE>
   *          if not.
   * @return  {@code true} if the operation should be allowed by the
   *          access control configuration, or {@code false} if not.
   */
  public abstract boolean isAllowed(ExtendedOperation
                                         extendedOperation);
@@ -134,12 +169,11 @@
   * @param  modifyOperation  The operation for which to make the
   *                          determination.
   *
   * @return  <CODE>true</CODE> if the operation should be allowed by
   *          the access control configuration, or <CODE>false</CODE>
   *          if not.
   * @return  {@code true} if the operation should be allowed by the
   *          access control configuration, or {@code false} if not.
   */
  public abstract boolean isAllowed(LocalBackendModifyOperation
      modifyOperation);
                                         modifyOperation);
@@ -151,9 +185,8 @@
   * @param  modifyDNOperation  The operation for which to make the
   *                            determination.
   *
   * @return  <CODE>true</CODE> if the operation should be allowed by
   *          the access control configuration, or <CODE>false</CODE>
   *          if not.
   * @return  {@code true} if the operation should be allowed by the
   *          access control configuration, or {@code false} if not.
   */
  public abstract boolean isAllowed(ModifyDNOperation
                                         modifyDNOperation);
@@ -171,12 +204,11 @@
   * @param  searchOperation  The operation for which to make the
   *                          determination.
   *
   * @return  <CODE>true</CODE> if the operation should be allowed by
   *          the access control configuration, or <CODE>false</CODE>
   *          if not.
   * @return  {@code true} if the operation should be allowed by the
   *          access control configuration, or {@code false} if not.
   */
  public abstract boolean isAllowed(LocalBackendSearchOperation
      searchOperation);
                                         searchOperation);
@@ -190,13 +222,12 @@
   * @param  searchEntry      The search result entry for which to
   *                          make the determination.
   *
   * @return  <CODE>true</CODE> if the operation should be allowed by
   *          the access control configuration, or <CODE>false</CODE>
   * @return  {@code true} if the access control configuration allows
   *          the entry to be returned to the client, or {@code false}
   *          if not.
   */
  public abstract boolean maySend(
                         SearchOperation searchOperation,
                         SearchResultEntry searchEntry);
  public abstract boolean maySend(SearchOperation searchOperation,
                                  SearchResultEntry searchEntry);
@@ -212,9 +243,9 @@
   * @return  Returns the entry with filtered attributes and values
   *          removed.
   */
  public abstract SearchResultEntry filterEntry(
                         SearchOperation searchOperation,
                         SearchResultEntry searchEntry);
  public abstract SearchResultEntry
                       filterEntry(SearchOperation searchOperation,
                                   SearchResultEntry searchEntry);
@@ -222,57 +253,56 @@
   * Indicates whether the provided search result reference may be
   * sent to the client.
   *
   * @param searchOperation
   *          The search operation with which the provided reference
   *          is associated.
   * @param searchReference
   *          The search result reference for which to make the
   *          determination.
   * @return <CODE>true</CODE> if the operation should be allowed by
   *         the access control configuration, or <CODE>false</CODE>
   *         if not.
   * @param  searchOperation  The search operation with which the
   *                          provided reference is associated.
   * @param  searchReference  The search result reference for which to
   *                          make the determination.
   *
   * @return  {@code true} if the access control configuration allows
   *          the reference to be returned to the client, or
   *          {@code false} if not.
   */
  public abstract boolean maySend(
                          SearchOperation searchOperation,
                          SearchResultReference searchReference);
  public abstract boolean maySend(SearchOperation searchOperation,
                               SearchResultReference searchReference);
  /**
   * Indicates whether a proxied authorization control is allowed
   * based on the current operation and the new authorization
   * entry.
   * based on the current operation and the new authorization entry.
   *
   * @param operation
   *        The operation with which the proxied authorization
   *        control is associated.
   * @param newAuthorizationEntry
   *        The new authorization entry related to the
   *        proxied authorization control authorization ID.
   * @return  <CODE>true</CODE> if the operation should be allowed by
   *         the access control configuration, or <CODE>false</CODE>
   *         if not.
   * @param  operation              The operation with which the
   *                                proxied authorization control is
   *                                associated.
   * @param  newAuthorizationEntry  The new authorization entry
   *                                related to the proxied
   *                                authorization control
   *                                authorization ID.
   *
   * @return  {@code true} if the operation should be allowed to use
   *          the proxied authorization control, or {@code false} if
   *          not.
   */
  public abstract boolean isProxiedAuthAllowed(Operation operation,
                                        Entry newAuthorizationEntry);
                               Entry newAuthorizationEntry);
  /**
   * Indicates whether a geteffectiverights control is allowed
   * Indicates whether a getEffectiveRights control is allowed
   * based on the current operation and the control contents.
   *
   * @param operation
   *        The operation with which the geteffectiverights
   *        control is associated. This is always a
   *       SearchOperation.
   * @param control
   *        The control class containing the decoded
   *        geteffectiverights control contents.
   * @return  <CODE>true</CODE> if the operation should be allowed
   *          by the access control configuration, or
   *          <CODE>false</CODE> if not.
   * @param  operation  The operation with which the
   *                    getEffectiveRights control is associated.
   *                    This is always a SearchOperation.
   * @param  control    The control class containing the decoded
   *                    getEffectiveRights control contents.
   *
   * @return  {@code true} if the use of the getEffectiveRights
   *          control should be allowed, or {@code false} if not.
   */
  public abstract
  boolean isGetEffectiveRightsAllowed(Operation operation,
                                      Control control);
  public abstract boolean isGetEffectiveRightsAllowed(
                               SearchOperation operation,
                               Control control);
}
opends/src/server/org/opends/server/api/AccessControlProvider.java
File was deleted
opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
@@ -28,23 +28,15 @@
package org.opends.server.authorization.dseecompat;
import static org.opends.server.authorization.dseecompat.Aci.*;
import org.opends.server.admin.std.server.DseeCompatAccessControlHandlerCfg;
import org.opends.server.api.AccessControlHandler;
import static org.opends.server.config.ConfigConstants.ATTR_AUTHZ_GLOBAL_ACI;
import org.opends.server.core.*;
import static org.opends.server.loggers.ErrorLogger.logError;
import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
import static org.opends.server.loggers.debug.DebugLogger.getTracer;
import org.opends.server.loggers.debug.DebugTracer;
import static org.opends.server.messages.AciMessages.*;
import static org.opends.server.messages.MessageHandler.getMessage;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
import static org.opends.server.schema.SchemaConstants.SYNTAX_DN_OID;
import org.opends.server.types.*;
import static org.opends.server.util.ServerConstants.OID_GET_EFFECTIVE_RIGHTS;
import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
import static org.opends.server.util.StaticUtils.toLowerCase;
@@ -52,104 +44,132 @@
import java.util.*;
import java.util.concurrent.locks.Lock;
import org.opends.server.admin.std.server.DseeCompatAccessControlHandlerCfg;
import org.opends.server.api.AccessControlHandler;
import org.opends.server.config.ConfigException;
import org.opends.server.core.*;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.types.*;
import org.opends.server.workflowelement.localbackend.*;
/**
 * The AciHandler class performs the main processing for the
 * dseecompat package.
 * The AciHandler class performs the main processing for the dseecompat package.
 */
public class AciHandler extends AccessControlHandler {
public class AciHandler
       extends AccessControlHandler<DseeCompatAccessControlHandlerCfg>
{
  /**
   * The tracer object for the debug logger.
   */
  private static final DebugTracer TRACER = getTracer();
    /*
     * The list that holds that ACIs keyed by the DN of the entry
     * holding the ACI.
     */
    private AciList aciList;
  /**
   * The list that holds that ACIs keyed by the DN of the entry
   * holding the ACI.
   */
  private AciList aciList;
    /*
     * The listener that handles ACI changes caused by LDAP operations, ACI
     * decode failure alert logging and backend initialization ACI list
     * adjustment.
     */
    private AciListenerManager aciListenerMgr;
  /**
   * The listener that handles ACI changes caused by LDAP operations, ACI
   * decode failure alert logging and backend initialization ACI list
   * adjustment.
   */
  private AciListenerManager aciListenerMgr;
    /**
     * Attribute type corresponding to "aci" attribute.
     */
    public static AttributeType aciType;
  /**
   * Attribute type corresponding to "aci" attribute.
   */
  public static AttributeType aciType;
    /**
     * Attribute type corresponding to global "ds-cfg-global-aci" attribute.
     */
    public static AttributeType globalAciType;
  /**
   * Attribute type corresponding to global "ds-cfg-global-aci" attribute.
   */
  public static AttributeType globalAciType;
    /**
     * String used to save the original authorization entry in an operation
     * attachment if a proxied authorization control was seen.
     */
    public static String ORIG_AUTH_ENTRY="origAuthorizationEntry";
  /**
   * String used to save the original authorization entry in an operation
   * attachment if a proxied authorization control was seen.
   */
  public static String ORIG_AUTH_ENTRY="origAuthorizationEntry";
   /**
     * String used to save a resource entry containing all the attributes in
     * the SearchOperation attachment list. This is only used during
     * geteffectiverights read right processing when all of an entry'ss
     * attributes need to examined.
     */
    public static String ALL_ATTRS_RESOURCE_ENTRY = "allAttrsResourceEntry";
  /**
   * String used to save a resource entry containing all the attributes in
   * the SearchOperation attachment list. This is only used during
   * geteffectiverights read right processing when all of an entry'ss
   * attributes need to examined.
   */
  public static String ALL_ATTRS_RESOURCE_ENTRY = "allAttrsResourceEntry";
    /**
     * String used to indicate that the evaluating ACI had a all user attributes
     * targetattr match (targetattr="*").
     */
     public static String ALL_USER_ATTRS_MATCHED = "allUserAttrsMatched";
  /**
   * String used to indicate that the evaluating ACI had a all user attributes
   * targetattr match (targetattr="*").
   */
   public static String ALL_USER_ATTRS_MATCHED = "allUserAttrsMatched";
    /**
     * String used to indicate that the evaluating ACI had a all operational
     * attributes targetattr match (targetattr="+").
     */
     public static String ALL_OP_ATTRS_MATCHED = "allOpAttrsMatched";
  /**
   * String used to indicate that the evaluating ACI had a all operational
   * attributes targetattr match (targetattr="+").
   */
   public static String ALL_OP_ATTRS_MATCHED = "allOpAttrsMatched";
    /**
     * This constructor instantiates the ACI handler class that performs the
     * main processing for the dseecompat ACI package. It does the following
     * initializations:
     *
     *
     *  - Instantiates the ACI list cache.
     *
     *  - Instantiates thr AciListenerManager.
     *
     *  - Processes all global attribute types found in the configuration entry
     *    and adds them to the ACI list cache.
     *
     *  - Processes all "aci" attributes found in the "cn=config" naming
     *    context and adds them to the ACI list cache.
     *
     * @param configuration The config handler containing the ACI
     *  configuration information.
     * @throws InitializationException if there is a problem processing the
     * config entry or config naming context.
    */
    public AciHandler(DseeCompatAccessControlHandlerCfg configuration)
    throws InitializationException  {
        DN configurationDN=configuration.dn();
        aciList = new AciList(configurationDN);
        aciListenerMgr = new AciListenerManager(aciList, configurationDN);
        if((aciType = DirectoryServer.getAttributeType("aci")) == null)
            aciType = DirectoryServer.getDefaultAttributeType("aci");
        if((globalAciType =
               DirectoryServer.getAttributeType(ATTR_AUTHZ_GLOBAL_ACI)) == null)
            globalAciType =
                 DirectoryServer.getDefaultAttributeType(ATTR_AUTHZ_GLOBAL_ACI);
        processGlobalAcis(configuration);
        processConfigAcis();
  /**
   * Creates a new DSEE-compatible access control handler.
   */
  public AciHandler()
  {
    // No implementation required.  All initialization should be done in the
    // intializeAccessControlHandler method.
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public void initializeAccessControlHandler(
                   DseeCompatAccessControlHandlerCfg configuration)
         throws ConfigException, InitializationException
  {
    DN configurationDN=configuration.dn();
    aciList = new AciList(configurationDN);
    aciListenerMgr = new AciListenerManager(aciList, configurationDN);
    if((aciType = DirectoryServer.getAttributeType("aci")) == null)
    {
      aciType = DirectoryServer.getDefaultAttributeType("aci");
    }
    if((globalAciType =
           DirectoryServer.getAttributeType(ATTR_AUTHZ_GLOBAL_ACI)) == null)
    {
      globalAciType =
           DirectoryServer.getDefaultAttributeType(ATTR_AUTHZ_GLOBAL_ACI);
    }
    processGlobalAcis(configuration);
    processConfigAcis();
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public void finalizeAccessControlHandler()
  {
    // No implementation required.
  }
    /**
     * Process all global ACI attribute types found in the configuration
     * entry and adds them to that ACI list cache. It also logs messages about
@@ -1153,7 +1173,8 @@
   * @param c  The request control to save.
   * @return  True if the control is allowed access.
   */
  public boolean isGetEffectiveRightsAllowed(Operation operation, Control c) {
  public boolean isGetEffectiveRightsAllowed(SearchOperation operation,
                                             Control c) {
    operation.setAttachment(OID_GET_EFFECTIVE_RIGHTS, c);
    return true;
  }
@@ -1197,3 +1218,4 @@
      return true;
  }
}
opends/src/server/org/opends/server/authorization/dseecompat/AciProvider.java
File was deleted
opends/src/server/org/opends/server/core/AccessControlConfigManager.java
@@ -26,10 +26,10 @@
 */
package org.opends.server.core;
import org.opends.server.types.DebugLogLevel;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import org.opends.server.loggers.debug.DebugTracer;
import static org.opends.server.messages.ConfigMessages.*;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.util.ServerConstants.*;
@@ -48,25 +48,29 @@
import org.opends.server.admin.std.server.AccessControlHandlerCfg;
import org.opends.server.admin.std.server.RootCfg;
import org.opends.server.api.AccessControlHandler;
import org.opends.server.api.AccessControlProvider;
import org.opends.server.api.AlertGenerator;
import org.opends.server.config.ConfigException;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.DN;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
import org.opends.server.types.InitializationException;
import org.opends.server.types.ResultCode;
/**
 * This class manages the application-wide access-control configuration.
 * <p>
 * When access control is disabled a default "permissive" access control
 * implementation is used, which permits all operations regardless of
 * the identity of the user.
 * implementation is used, which permits all operations regardless of the
 * identity of the user.
 */
public final class AccessControlConfigManager
       implements AlertGenerator
       implements AlertGenerator ,
                  ConfigurationChangeListener<AccessControlHandlerCfg>
{
  /**
   * The tracer object for the debug logger.
@@ -81,48 +85,72 @@
  private static AccessControlConfigManager instance = null;
  // The active access control implementation.
  private AtomicReference<AccessControlProvider> accessControlProvider;
  private AtomicReference<AccessControlHandler> accessControlHandler;
  // The current configuration.
  private PrivateACLConfiguration currentConfiguration;
  private AccessControlHandlerCfg currentConfiguration;
  /**
   * Creates a new instance of this access control configuration
   * manager.
   */
  private AccessControlConfigManager()
  {
    this.accessControlHandler = new AtomicReference<AccessControlHandler>(
        new DefaultAccessControlHandler());
    this.currentConfiguration = null;
  }
  /**
   * Get the single application-wide access control manager instance.
   *
   * @return The access control manager.
   */
  public static AccessControlConfigManager getInstance() {
    if (instance == null) {
  public static AccessControlConfigManager getInstance()
  {
    if (instance == null)
    {
      instance = new AccessControlConfigManager();
    }
    return instance;
  }
  /**
   * Determine if access control is enabled according to the current
   * configuration.
   *
   * @return Returns <code>true</code> if access control is enabled,
   *         <code>false</code> otherwise.
   * @return  {@code true} if access control is enabled, {@code false}
   *          otherwise.
   */
  public boolean isAccessControlEnabled() {
  public boolean isAccessControlEnabled()
  {
    return currentConfiguration.isEnabled();
  }
  /**
   * Get the active access control handler.
   * <p>
   * When access control is disabled, this method returns a default
   * access control implementation which permits all operations.
   * When access control is disabled, this method returns a default access
   * control implementation which permits all operations.
   *
   * @return Returns the active access control handler (never
   *         <code>null</code>).
   * @return   The active access control handler (never {@code null}).
   */
  public AccessControlHandler getAccessControlHandler() {
    return accessControlProvider.get().getInstance();
  public AccessControlHandler getAccessControlHandler()
  {
    return accessControlHandler.get();
  }
  /**
   * Initializes the access control sub-system. This should only be
   * called at Directory Server startup. If an error occurs then an
@@ -137,9 +165,9 @@
   *           handler that is not related to the Directory Server
   *           configuration.
   */
  void initializeAccessControl() throws ConfigException,
      InitializationException {
  public void initializeAccessControl()
         throws ConfigException, InitializationException
  {
    // Get the root configuration object.
    ServerManagementContext managementContext =
         ServerManagementContext.getInstance();
@@ -153,371 +181,212 @@
    AccessControlHandlerCfg accessControlConfiguration =
           rootConfiguration.getAccessControlHandler();
    // Parse the configuration entry.
    PrivateACLConfiguration configuration = PrivateACLConfiguration
        .readConfiguration(accessControlConfiguration);
    // We have a valid usable entry, so register a change listener in
    // order to handle configuration changes.
    accessControlConfiguration.addChangeListener(new ChangeListener());
    accessControlConfiguration.addChangeListener(this);
    // The configuration looks valid, so install it.
    updateConfiguration(configuration);
    updateConfiguration(accessControlConfiguration);
  }
  /**
   * Creates a new instance of this access control configuration
   * manager.
   */
  private AccessControlConfigManager() {
    this.accessControlProvider = new AtomicReference<AccessControlProvider>(
        new DefaultAccessControlProvider());
    this.currentConfiguration = null;
  }
  /**
   * Updates the access control configuration based on the contents of a
   * valid configuration entry.
   *
   * @param newConfiguration
   *          The new configuration object.
   * @throws ConfigException
   *           If the access control configuration is invalid.
   * @throws InitializationException
   *           If the access control handler provider could not be
   *           instantiated.
   * @param  newConfiguration  The new configuration object.
   *
   * @throws  ConfigException If the access control configuration is invalid.
   *
   * @throws  InitializationException  If the access control handler provider
   *                                   could not be instantiated.
   */
  private void updateConfiguration(PrivateACLConfiguration newConfiguration)
      throws ConfigException, InitializationException {
  private void updateConfiguration(AccessControlHandlerCfg newConfiguration)
          throws ConfigException, InitializationException
  {
    DN configEntryDN = newConfiguration.dn();
    String newHandlerClass = null;
    DN configEntryDN = newConfiguration.getConfiguration().dn();
    Class<? extends AccessControlProvider> newHandlerClass = null;
    if (currentConfiguration == null) {
    if (currentConfiguration == null)
    {
      // Initialization phase.
      if (newConfiguration.isEnabled()) {
        newHandlerClass = newConfiguration.getProviderClass();
      } else {
        newHandlerClass = DefaultAccessControlProvider.class;
      if (newConfiguration.isEnabled())
      {
        newHandlerClass = newConfiguration.getAclHandlerClass();
      }
    } else {
      else
      {
        newHandlerClass = DefaultAccessControlHandler.class.getName();
      }
    }
    else
    {
      boolean enabledOld = currentConfiguration.isEnabled();
      boolean enabledNew = newConfiguration.isEnabled();
      if (enabledOld == false && enabledNew == true) {
        // Access control has been enabled - load new class.
        newHandlerClass = newConfiguration.getProviderClass();
      } else if (enabledOld == true && enabledNew == false) {
        // Access control has been disabled - load null handler.
        newHandlerClass = DefaultAccessControlProvider.class;
      } else if (enabledNew == true) {
        // Access control is enabled - load new class if it has changed.
        if (currentConfiguration.getProviderClass().equals(
            newConfiguration.getProviderClass()) == false) {
          newHandlerClass = newConfiguration.getProviderClass();
        }
      if ((! enabledOld) && enabledNew)
      {
        // Access control has been enabled - get the new class name.
        newHandlerClass = newConfiguration.getAclHandlerClass();
      }
      else if (enabledOld && (! enabledNew))
      {
        // Access control has been disabled - get the default handler class
        // name.
        newHandlerClass = DefaultAccessControlHandler.class.getName();
      }
      else if (enabledNew)
      {
        // Access control is already enabled, but still get the handler class
        // name to see if it has changed.
        newHandlerClass = newConfiguration.getAclHandlerClass();
      }
    }
    // If the access control handler provider class has changed,
    // finalize the old
    // one and instantiate the new.
    if (newHandlerClass != null) {
      AccessControlProvider<? extends AccessControlHandlerCfg> newHandler ;
      try {
    // If the access control handler provider class has changed, finalize the
    // old one and instantiate the new one.
    if (newHandlerClass != null)
    {
      AccessControlHandler<? extends AccessControlHandlerCfg> newHandler;
      try
      {
        if (newConfiguration.isEnabled())
        {
          newHandler = loadProvider(newHandlerClass.getName(), newConfiguration
            .getConfiguration());
          newHandler = loadHandler(newHandlerClass, newConfiguration);
        }
        else
        {
          newHandler = new DefaultAccessControlProvider();
          newHandler = new DefaultAccessControlHandler();
          newHandler.initializeAccessControlHandler(null);
        }
      } catch (Exception e) {
      }
      catch (Exception e)
      {
        if (debugEnabled())
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }
        int msgID = MSGID_CONFIG_AUTHZ_UNABLE_TO_INSTANTIATE_HANDLER;
        String message = getMessage(msgID, newHandlerClass.getName(),
            String.valueOf(configEntryDN.toString()),
            stackTraceToSingleLineString(e));
        String message = getMessage(msgID, newHandlerClass,
                                    String.valueOf(configEntryDN.toString()),
                                    stackTraceToSingleLineString(e));
        throw new InitializationException(msgID, message, e);
      }
      // Switch the handlers without interfering with other threads.
      AccessControlProvider oldHandler = accessControlProvider
          .getAndSet(newHandler);
      AccessControlHandler oldHandler =
           accessControlHandler.getAndSet(newHandler);
      if (oldHandler != null) {
      if (oldHandler != null)
      {
        oldHandler.finalizeAccessControlHandler();
      }
      // If access control has been disabled put a warning in the log.
      if (newHandlerClass.equals(DefaultAccessControlProvider.class)) {
      if (newHandlerClass.equals(DefaultAccessControlHandler.class))
      {
        int msgID = MSGID_CONFIG_AUTHZ_DISABLED;
        String message = getMessage(msgID);
        logError(ErrorLogCategory.CONFIGURATION,
            ErrorLogSeverity.SEVERE_WARNING, message, msgID);
                 ErrorLogSeverity.SEVERE_WARNING, message, msgID);
        if (currentConfiguration != null)
        {
          DirectoryServer.sendAlertNotification(this,
              ALERT_TYPE_ACCESS_CONTROL_DISABLED, msgID, message);
               ALERT_TYPE_ACCESS_CONTROL_DISABLED, msgID, message);
        }
      } else {
      }
      else
      {
        int msgID = MSGID_CONFIG_AUTHZ_ENABLED;
        String message = getMessage(msgID, newHandlerClass.getName());
        logError(ErrorLogCategory.CONFIGURATION,
            ErrorLogSeverity.NOTICE, message, msgID);
        String message = getMessage(msgID, newHandlerClass);
        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.NOTICE,
                 message, msgID);
        if (currentConfiguration != null)
        {
          DirectoryServer.sendAlertNotification(this,
              ALERT_TYPE_ACCESS_CONTROL_ENABLED, msgID, message);
               ALERT_TYPE_ACCESS_CONTROL_ENABLED, msgID, message);
        }
      }
    }
    // Switch in the local configuration.
    //
    // TODO: possible race condition here - should be an atomic
    // reference and sync'ed with the handler reference. We can assume
    // that config changes won't happen that much though.
    currentConfiguration = newConfiguration;
  }
  /**
   * Internal class implementing the change listener interface.
   * {@inheritDoc}
   */
  private class ChangeListener implements
      ConfigurationChangeListener<AccessControlHandlerCfg>
  public boolean isConfigurationChangeAcceptable(
                      AccessControlHandlerCfg configuration,
                      List<String> unacceptableReasons)
  {
    /**
     * {@inheritDoc}
     */
    public boolean isConfigurationChangeAcceptable(
        AccessControlHandlerCfg configuration,
        List<String> unacceptableReasons)
    try
    {
      try {
        // Parse the configuration entry.
        PrivateACLConfiguration.readConfiguration(configuration);
      } catch (ConfigException e) {
        unacceptableReasons.add(e.getMessage());
        return false;
      // If the access control handler is disabled, we don't care about the
      // configuration.  If it is enabled, then all we care about is whether we
      // can load the access control handler class.
      if (configuration.isEnabled())
      {
        loadHandler(configuration.getAclHandlerClass(), null);
      }
      return true;
    }
    catch (InitializationException e)
    {
      unacceptableReasons.add(e.getMessage());
      return false;
    }
    /**
     * {@inheritDoc}
     */
    public ConfigChangeResult applyConfigurationChange(
        AccessControlHandlerCfg configuration)
    {
      ResultCode resultCode = ResultCode.SUCCESS;
      ArrayList<String> messages = new ArrayList<String>();
      try {
        // Parse the configuration entry.
        PrivateACLConfiguration newConfiguration = PrivateACLConfiguration
            .readConfiguration(configuration);
        // The configuration looks valid, so install it.
        updateConfiguration(newConfiguration);
      } catch (ConfigException e) {
        messages.add(e.getMessage());
        resultCode = ResultCode.CONSTRAINT_VIOLATION;
      } catch (InitializationException e) {
        messages.add(e.getMessage());
        resultCode = DirectoryServer.getServerErrorResultCode();
      }
      return new ConfigChangeResult(resultCode, false, messages);
    }
    return true;
  }
  /**
   * Internal class used to represent the parsed configuration entry.
   * {@inheritDoc}
   */
  private static class PrivateACLConfiguration {
  public ConfigChangeResult applyConfigurationChange(
                                 AccessControlHandlerCfg configuration)
  {
    ResultCode resultCode = ResultCode.SUCCESS;
    ArrayList<String> messages = new ArrayList<String>();
    // Flag indicating whether or not access control is enabled.
    private boolean enabled;
    // The current access control provider class specified in
    // the configuration.
    private Class<? extends AccessControlProvider> providerClass;
    // The entry that this object is mapped to.
    private AccessControlHandlerCfg configuration;
    /**
     * Parses a configuration entry and, if it is valid, returns an
     * object representation of it.
     *
     * @param configuration
     *          The access control configuration entry.
     * @return An object representation of the parsed configuration.
     * @throws ConfigException
     *           If a the access control configuration is invalid.
     */
    public static PrivateACLConfiguration readConfiguration(
        AccessControlHandlerCfg configuration) throws ConfigException {
      // The access control configuration entry must have the correct
      // object class.
      if (configuration.getAclHandlerClass() == null) {
        int msgID = MSGID_CONFIG_AUTHZ_ENTRY_DOES_NOT_HAVE_OBJECT_CLASS;
        String message = getMessage(msgID, configuration.toString());
        throw new ConfigException(msgID, message);
      }
      // Parse the attributes.
      boolean enabled = configuration.isEnabled() ;
      Class<? extends AccessControlProvider> providerClass =
        getClassAttribute(configuration);
      return new PrivateACLConfiguration(configuration, enabled, providerClass);
    try
    {
      // Attempt to install the new configuration.
      updateConfiguration(configuration);
    }
    catch (ConfigException e)
    {
      messages.add(e.getMessage());
      resultCode = ResultCode.CONSTRAINT_VIOLATION;
    }
    catch (InitializationException e)
    {
      messages.add(e.getMessage());
      resultCode = DirectoryServer.getServerErrorResultCode();
    }
    /**
     * Determine if access control is enabled according to the
     * configuration.
     *
     * @return Returns <code>true</code> if access control is enabled,
     *         <code>false</code> otherwise.
     */
    public boolean isEnabled() {
      return enabled;
    }
    /**
     * Get the access control provider class specified in the
     * configuration.
     *
     * @return Returns the {@link AccessControlProvider} class.
     */
    public Class<? extends AccessControlProvider> getProviderClass() {
      return providerClass;
    }
    /**
     * Get the configuration entry associated with this configuration
     * object.
     *
     * @return Returns the configuration entry.
     */
    public AccessControlHandlerCfg getConfiguration() {
      return configuration;
    }
    /**
     * Construct a new configuration object with the specified parsed
     * attribute values.
     *
     * @param configuration
     *          The associated access control configuration entry.
     * @param enabled
     *          The value of the enabled attribute.
     * @param providerClass
     *          The access control provider class.
     */
    private PrivateACLConfiguration(
        AccessControlHandlerCfg configuration, boolean enabled,
        Class<? extends AccessControlProvider> providerClass) {
      this.configuration = configuration;
      this.enabled = enabled;
      this.providerClass = providerClass;
    }
    /**
     * Read the value of the attribute which indicates which access
     * control implementation class to use. This method checks the
     * validity of the class name.
     *
     * @param configuration
     *          The access control configuration.
     * @return The access control provider class.
     * @throws ConfigException
     *           If the class attribute could not be read or if it
     *           contains an invalid class name.
     */
    private static Class<? extends AccessControlProvider> getClassAttribute(
        AccessControlHandlerCfg configuration) throws ConfigException {
      // If access control is enabled then make sure that the class
      // attribute is present.
      try {
        // Load the access control implementation class.
        String className = configuration.getAclHandlerClass();
        try {
          return DirectoryServer.loadClass(className).asSubclass(
              AccessControlProvider.class);
        } catch (ClassNotFoundException e) {
          if (debugEnabled())
          {
            TRACER.debugCaught(DebugLogLevel.ERROR, e);
          }
          int msgID = MSGID_CONFIG_AUTHZ_UNABLE_TO_LOAD_CLASS;
          String message = getMessage(msgID, className, String
              .valueOf(configuration.dn().toString()),
              getExceptionMessage(e));
          throw new ConfigException(msgID, message, e);
        } catch (ClassCastException e) {
          if (debugEnabled())
          {
            TRACER.debugCaught(DebugLogLevel.ERROR, e);
          }
          int msgID = MSGID_CONFIG_AUTHZ_BAD_CLASS;
          String message = getMessage(msgID, className, String
              .valueOf(configuration.dn().toString()),
              AccessControlProvider.class.getName(),
              getExceptionMessage(e));
          throw new ConfigException(msgID, message, e);
        }
      } catch (ConfigException e) {
        int msgID = MSGID_CONFIG_AUTHZ_UNABLE_TO_DETERMINE_CLASS;
        String message = getMessage(msgID, configuration.dn()
            .toString(), getExceptionMessage(e));
        throw new ConfigException(msgID, message, e);
      }
    }
    return new ConfigChangeResult(resultCode, false, messages);
  }
  /**
   * Retrieves the DN of the configuration entry with which this alert
   * generator is associated.
   *
   * @return  The DN of the configuration entry with which this alert
   *          generator is associated.
   * {@inheritDoc}
   */
  public DN getComponentEntryDN()
  {
    return currentConfiguration.getConfiguration().dn();
    return currentConfiguration.dn();
  }
  /**
   * Retrieves the fully-qualified name of the Java class for this
   * alert generator implementation.
   *
   * @return  The fully-qualified name of the Java class for this
   *          alert generator implementation.
   * {@inheritDoc}
   */
  public String getClassName()
  {
@@ -527,15 +396,7 @@
  /**
   * Retrieves information about the set of alerts that this generator
   * may produce.  The map returned should be between the notification
   * type for a particular notification and the human-readable
   * description for that notification.  This alert generator must not
   * generate any alerts with types that are not contained in this
   * list.
   *
   * @return  Information about the set of alerts that this generator
   *          may produce.
   * {@inheritDoc}
   */
  public LinkedHashMap<String,String> getAlerts()
  {
@@ -549,6 +410,8 @@
    return alerts;
  }
  /**
   * Loads the specified class, instantiates it as a AccessControlProvider, and
   * optionally initializes that instance.
@@ -564,21 +427,21 @@
   * @throws  InitializationException  If a problem occurred while attempting to
   *                                   initialize the Access Control Provider.
   */
  private AccessControlProvider<? extends AccessControlHandlerCfg>
               loadProvider(String className,
                             AccessControlHandlerCfg configuration)
  private AccessControlHandler<? extends AccessControlHandlerCfg>
               loadHandler(String className,
                           AccessControlHandlerCfg configuration)
          throws InitializationException
  {
    try
    {
      AccessControlHandlerCfgDefn definition =
        AccessControlHandlerCfgDefn.getInstance();
           AccessControlHandlerCfgDefn.getInstance();
      ClassPropertyDefinition propertyDefinition =
           definition.getAclHandlerClassPropertyDefinition();
      Class<? extends AccessControlProvider> providerClass =
           propertyDefinition.loadClass(className, AccessControlProvider.class);
      AccessControlProvider<? extends AccessControlHandlerCfg> provider =
           (AccessControlProvider<? extends AccessControlHandlerCfg>)
      Class<? extends AccessControlHandler> providerClass =
           propertyDefinition.loadClass(className, AccessControlHandler.class);
      AccessControlHandler<? extends AccessControlHandlerCfg> provider =
          (AccessControlHandler<? extends AccessControlHandlerCfg>)
           providerClass.newInstance();
      if (configuration != null)
opends/src/server/org/opends/server/core/DefaultAccessControlHandler.java
New file
@@ -0,0 +1,239 @@
/*
 * 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
 *
 *
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.core;
import org.opends.server.admin.std.server.AccessControlHandlerCfg;
import org.opends.server.api.AccessControlHandler;
import org.opends.server.config.ConfigException;
import org.opends.server.types.*;
import org.opends.server.workflowelement.localbackend.*;
/**
 * This class implements a default access control provider for the Directory
 * Server.
 * <p>
 * This class provides and access control handler which is used when access
 * control is disabled and implements a default access control decision function
 * which grants access to everything and anyone.
 */
class DefaultAccessControlHandler
      extends AccessControlHandler<AccessControlHandlerCfg>
{
  /**
   * The single handler instance.
   */
  private static DefaultAccessControlHandler instance = null;
  /**
   * Create a new default access control handler.
   */
  public DefaultAccessControlHandler()
  {
    super();
    // No implementation required.
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public void initializeAccessControlHandler(AccessControlHandlerCfg
                                                  configuration)
      throws ConfigException, InitializationException
  {
    // No implementation required.
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public void finalizeAccessControlHandler()
  {
    // No implementation required.
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isAllowed(LocalBackendAddOperation addOperation)
  {
    return true;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isAllowed(LocalBackendBindOperation bindOperation)
  {
    return true;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isAllowed(CompareOperation compareOperation)
  {
    return true;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isAllowed(LocalBackendDeleteOperation deleteOperation)
  {
    return true;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isAllowed(ExtendedOperation extendedOperation)
  {
    return true;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isAllowed(LocalBackendModifyOperation modifyOperation)
  {
    return true;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isAllowed(ModifyDNOperation modifyDNOperation)
  {
    return true;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isAllowed(LocalBackendSearchOperation searchOperation)
  {
    return true;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public boolean maySend(SearchOperation searchOperation,
                         SearchResultEntry searchEntry)
  {
    return true;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public SearchResultEntry filterEntry(SearchOperation searchOperation,
                                       SearchResultEntry searchEntry)
  {
    // No implementation required.
    return searchEntry;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public boolean maySend(SearchOperation searchOperation,
                         SearchResultReference searchReference)
  {
    return true;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isProxiedAuthAllowed(Operation operation, Entry entry)
  {
   return true;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isGetEffectiveRightsAllowed(SearchOperation operation,
                                             Control c)
  {
      return true;
  }
}
opends/src/server/org/opends/server/core/DefaultAccessControlProvider.java
File was deleted