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

dugan
20.33.2007 6bed45cbfe8dba8557a6b8027b6b8fd9992a4e51
Issue 2741. Adding and removing ACI makes OpenDS unstable. Comments in issue.
4 files modified
197 ■■■■■ changed files
opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java 2 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/AciListenerManager.java 11 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/AccessControlConfigManager.java 182 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/ReferencesTestCase.java 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
@@ -107,6 +107,7 @@
  */
  static DN debugSearchIndexDN;
  /**
   * String used to save the original authorization entry in an operation
   * attachment if a proxied authorization control was seen.
@@ -212,6 +213,7 @@
  @Override()
  public void finalizeAccessControlHandler()
  {
    aciListenerMgr.finalizeListenerManager();
    AciEffectiveRights.finalizeOnShutdown();
    DirectoryServer.deregisterSupportedControl(OID_GET_EFFECTIVE_RIGHTS);
  }
opends/src/server/org/opends/server/authorization/dseecompat/AciListenerManager.java
@@ -128,6 +128,17 @@
        DirectoryServer.registerAlertGenerator(this);
    }
   /**
    * Deregister from the change notification listener, the backend
    * initialization listener and the alert generator.
    */
    public void finalizeListenerManager() {
        DirectoryServer.deregisterChangeNotificationListener(this);
        DirectoryServer.deregisterBackendInitializationListener(this);
        DirectoryServer.deregisterAlertGenerator(this);
    }
    /**
     * A delete operation succeeded. Remove any ACIs associated with the
     * entry deleted.
opends/src/server/org/opends/server/core/AccessControlConfigManager.java
@@ -184,6 +184,9 @@
    // order to handle configuration changes.
    accessControlConfiguration.addChangeListener(this);
    //This makes TestCaseUtils.reStartServer happy.
    currentConfiguration=null;
    // The configuration looks valid, so install it.
    updateConfiguration(accessControlConfiguration);
  }
@@ -201,16 +204,17 @@
   * @throws  InitializationException  If the access control handler provider
   *                                   could not be instantiated.
   */
  private void updateConfiguration(AccessControlHandlerCfg newConfiguration)
          throws ConfigException, InitializationException
  {
    DN configEntryDN = newConfiguration.dn();
    String newHandlerClass = null;
    boolean enabledOld = false, enabledNew = newConfiguration.isEnabled();
    if (currentConfiguration == null)
    {
      // Initialization phase.
      if (newConfiguration.isEnabled())
      if (enabledNew)
      {
        newHandlerClass = newConfiguration.getJavaClass();
      }
@@ -218,97 +222,103 @@
      {
        newHandlerClass = DefaultAccessControlHandler.class.getName();
      }
    }
    else
    {
      boolean enabledOld = currentConfiguration.isEnabled();
      boolean enabledNew = newConfiguration.isEnabled();
      if ((! enabledOld) && enabledNew)
      {
        // Access control has been enabled - get the new class name.
      //Get a new handler, initialize it and make it the current handler.
      accessControlHandler.getAndSet(getHandler(newHandlerClass,
              newConfiguration, true, false));
    } else {
      enabledOld = currentConfiguration.isEnabled();
      if(enabledNew) {
        //Access control is either being enabled or a attribute in the
        //configuration has changed such as class name or a global ACI.
        newHandlerClass = newConfiguration.getJavaClass();
      }
      else if (enabledOld && (! enabledNew))
      {
        // Access control has been disabled - get the default handler class
        // name.
        String oldHandlerClass = currentConfiguration.getJavaClass();
        //Check if moving from not enabled to enabled state.
        if(!enabledOld) {
           AccessControlHandler oldHandler =
                   accessControlHandler.getAndSet(getHandler(newHandlerClass,
                                                  newConfiguration, true, true));
           oldHandler.finalizeAccessControlHandler();
        } else {
          //Check if the class name is being changed.
          if(!newHandlerClass.equals(oldHandlerClass)) {
           AccessControlHandler oldHandler =
            accessControlHandler.getAndSet(getHandler(newHandlerClass,
                    newConfiguration, true, true));
            oldHandler.finalizeAccessControlHandler();
          } else {
            //Some other attribute has changed, try to get a new non-initialized
            //handler, but keep the old handler.
            getHandler(newHandlerClass,newConfiguration, false, false);
          }
        }
      } else if (enabledOld && (! enabledNew)) {
        //Access control has been disabled, switch to the default handler and
        //finalize the old handler.
        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.getJavaClass();
      }
    }
    // 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 = loadHandler(newHandlerClass, newConfiguration, true);
        }
        else
        {
          newHandler = new DefaultAccessControlHandler();
          newHandler.initializeAccessControlHandler(null);
        }
      }
      catch (Exception e)
      {
        if (debugEnabled())
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }
        Message message = ERR_CONFIG_AUTHZ_UNABLE_TO_INSTANTIATE_HANDLER.
            get(newHandlerClass, String.valueOf(configEntryDN.toString()),
                stackTraceToSingleLineString(e));
        throw new InitializationException(message, e);
      }
      // Switch the handlers without interfering with other threads.
      AccessControlHandler oldHandler =
           accessControlHandler.getAndSet(newHandler);
      if (oldHandler != null)
      {
        AccessControlHandler oldHandler =
                accessControlHandler.getAndSet(getHandler(newHandlerClass,
                        newConfiguration, false, true));
        oldHandler.finalizeAccessControlHandler();
      }
      // If access control has been disabled put a warning in the log.
      if (newHandlerClass.equals(DefaultAccessControlHandler.class.getName()))
      {
        Message message = WARN_CONFIG_AUTHZ_DISABLED.get();
        logError(message);
        if (currentConfiguration != null)
        {
          DirectoryServer.sendAlertNotification(this,
               ALERT_TYPE_ACCESS_CONTROL_DISABLED, message);
        }
      }
      else
      {
        Message message = NOTE_CONFIG_AUTHZ_ENABLED.get(newHandlerClass);
        logError(message);
        if (currentConfiguration != null)
        {
          DirectoryServer.sendAlertNotification(this,
               ALERT_TYPE_ACCESS_CONTROL_ENABLED, message);
        }
      }
    }
    // Switch in the local configuration.
    currentConfiguration = newConfiguration;
  }
  /**
   * Instantiates a new Access Control Handler using the specified class name,
   * configuration.
   *
   * @param handlerClassName The name of the handler to instantiate.
   * @param config The configuration to use when instantiating a new handler.
   * @param initHandler <code>True</code> if the new handler should be
   *                    initialized.
   * @param logMessage <code>True</code> if an error message should be logged
   *                                     and an alert should be sent.
   * @return The newly instantiated handler.
   *
   * @throws InitializationException  If an error occurs instantiating the
   *                                  the new handler.
   */
  AccessControlHandler<? extends AccessControlHandlerCfg>
  getHandler(String handlerClassName, AccessControlHandlerCfg config,
             boolean initHandler, boolean logMessage)
          throws InitializationException {
    AccessControlHandler<? extends AccessControlHandlerCfg> newHandler;
    try {
      if(handlerClassName.equals(DefaultAccessControlHandler.class.getName())) {
        newHandler = new DefaultAccessControlHandler();
        newHandler.initializeAccessControlHandler(null);
        if(logMessage) {
          Message message = WARN_CONFIG_AUTHZ_DISABLED.get();
          logError(message);
          if (currentConfiguration != null) {
            DirectoryServer.sendAlertNotification(this,
                    ALERT_TYPE_ACCESS_CONTROL_DISABLED, message);
          }
        }
      } else {
        newHandler = loadHandler(handlerClassName, config, initHandler);
        if(logMessage) {
          Message message = NOTE_CONFIG_AUTHZ_ENABLED.get(handlerClassName);
          logError(message);
          if (currentConfiguration != null) {
            DirectoryServer.sendAlertNotification(this,
                    ALERT_TYPE_ACCESS_CONTROL_ENABLED, message);
          }
        }
      }
    } catch (Exception e) {
      if (debugEnabled()) {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      Message message = ERR_CONFIG_AUTHZ_UNABLE_TO_INSTANTIATE_HANDLER.
              get(handlerClassName, String.valueOf(config.dn().toString()),
                      stackTraceToSingleLineString(e));
      throw new InitializationException(message, e);
    }
    return newHandler;
  }
  /**
@@ -446,7 +456,9 @@
        Method method =
          provider.getClass().getMethod("initializeAccessControlHandler",
                  configuration.definition().getServerConfigurationClass());
        method.invoke(provider, configuration);
        if(initialize) {
          method.invoke(provider, configuration);
        }
      }
      else
      {
opends/tests/unit-tests-testng/src/server/org/opends/server/authorization/dseecompat/ReferencesTestCase.java
@@ -81,7 +81,7 @@
  @BeforeClass
  public void setupClass() throws Exception {
    TestCaseUtils.startServer();
    TestCaseUtils.restartServer();
    deleteAttrFromEntry(ACCESS_HANDLER_DN, ATTR_AUTHZ_GLOBAL_ACI);
    TestCaseUtils.clearJEBackend(true,"userRoot", suffix);
    addEntries(suffix);