From 7c30dbb5403772b323df3ad907d9ed15d23b5aee Mon Sep 17 00:00:00 2001
From: ludovicp <ludovicp@localhost>
Date: Thu, 29 Apr 2010 20:35:40 +0000
Subject: [PATCH] Last batch of changes for this week. This adds support for the IETF based Password Policy for LDAP as SubEntry. Also resolves the following issues : - 4544 :  initializeBackend() should not set JE env config params directly. - 4478 : ECL in draft compat mode / search lastchangenumber can be very long - 4538 : Virtual attributes not retrieved when entry cache configured - 4547 : Search Filter Matching differ for cn=Directory Manager and plain user. - 4514 : Logs shows unexpected message with replication monitoring data missing (Partial fix) - 4534 : Replication using security does not work after server restart - 4516 : SEVERE_ERROR: servers (...) have the same ServerId In addition, they also improve reliability and performance in various areas including CollectiveAttributes, Virtual Attributes and Subentries management, Schema loading, Replication...

---
 opends/src/server/org/opends/server/core/PasswordPolicyConfigManager.java |  269 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 266 insertions(+), 3 deletions(-)

diff --git a/opends/src/server/org/opends/server/core/PasswordPolicyConfigManager.java b/opends/src/server/org/opends/server/core/PasswordPolicyConfigManager.java
index 5eaf4a0..baa7cfc 100644
--- a/opends/src/server/org/opends/server/core/PasswordPolicyConfigManager.java
+++ b/opends/src/server/org/opends/server/core/PasswordPolicyConfigManager.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Copyright 2006-2010 Sun Microsystems, Inc.
  */
 package org.opends.server.core;
 import org.opends.messages.Message;
@@ -37,15 +37,20 @@
 import org.opends.server.admin.server.ServerManagementContext;
 import org.opends.server.admin.std.server.PasswordPolicyCfg;
 import org.opends.server.admin.std.server.RootCfg;
+import org.opends.server.api.SubentryChangeListener;
 import org.opends.server.config.ConfigException;
+import org.opends.server.loggers.debug.DebugTracer;
 import org.opends.server.types.ConfigChangeResult;
 import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.ResultCode;
+import org.opends.server.types.SubEntry;
 
 import static org.opends.messages.ConfigMessages.*;
-
 import static org.opends.server.util.StaticUtils.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
 
 
 
@@ -56,9 +61,14 @@
  * the server is running.
  */
 public class PasswordPolicyConfigManager
-       implements ConfigurationAddListener<PasswordPolicyCfg>,
+       implements SubentryChangeListener,
+       ConfigurationAddListener<PasswordPolicyCfg>,
        ConfigurationDeleteListener<PasswordPolicyCfg>
 {
+  /**
+   * The tracer object for the debug logger.
+   */
+  private static final DebugTracer TRACER = getTracer();
 
 
 
@@ -72,6 +82,39 @@
 
 
   /**
+   * Creates a password policy configuration object
+   * from password policy subentry.
+   * @param  subEntry password policy subentry.
+   * @return password policy configuration.
+   * @throws InitializationException if an error
+   *         occurs while parsing subentry into
+   *         password policy configuration.
+   */
+  private PasswordPolicyConfig createPasswordPolicyConfig(
+          SubEntry subEntry) throws InitializationException
+  {
+    try
+    {
+      SubentryPasswordPolicy subentryPolicy =
+              new SubentryPasswordPolicy(subEntry);
+      PasswordPolicy passwordPolicy =
+              new PasswordPolicy(subentryPolicy);
+      PasswordPolicyConfig config =
+              new PasswordPolicyConfig(passwordPolicy);
+      return config;
+    }
+    catch (Exception e)
+    {
+      Message message = ERR_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG.
+            get(String.valueOf(subEntry.getDN()),
+                stackTraceToSingleLineString(e));
+      throw new InitializationException(message, e);
+    }
+  }
+
+
+
+  /**
    * Initializes all password policies currently defined in the Directory
    * Server configuration.  This should only be called at Directory Server
    * startup.
@@ -163,6 +206,39 @@
               String.valueOf(defaultPolicyDN));
       throw new ConfigException(message);
     }
+
+    // Process and register any password policy subentries.
+    List<SubEntry> pwpSubEntries =
+            DirectoryServer.getSubentryManager().getSubentries();
+    if ((pwpSubEntries != null) && (!pwpSubEntries.isEmpty()))
+    {
+      for (SubEntry subentry : pwpSubEntries)
+      {
+        if (subentry.getEntry().isPasswordPolicySubentry())
+        {
+          PasswordPolicyConfig config =
+                  createPasswordPolicyConfig(subentry);
+          DirectoryServer.registerPasswordPolicy(
+              subentry.getDN(), config);
+        }
+      }
+    }
+
+    // Register this as subentry change listener with SubentryManager.
+    DirectoryServer.getSubentryManager().registerChangeListener(this);
+  }
+
+
+
+  /**
+   * Perform any required finalization tasks for all password policies
+   * currently defined. This should only be called at Directory Server
+   * shutdown.
+   */
+  public void finalizePasswordPolicies()
+  {
+    // Deregister this as subentry change listener with SubentryManager.
+    DirectoryServer.getSubentryManager().deregisterChangeListener(this);
   }
 
 
@@ -323,4 +399,191 @@
 
     return new ConfigChangeResult(ResultCode.SUCCESS, false, messages);
   }
+
+
+
+  /**
+   * Attempts to parse an entry as password policy
+   * subentry to create a password policy object.
+   * @param entry subentry to parse.
+   * @throws DirectoryException if a problem occurs
+   *         while creating a password policy from
+   *         given subentry.
+   */
+  private void checkSubentryAcceptable(Entry entry)
+          throws DirectoryException
+  {
+    SubEntry subentry = new SubEntry(entry);
+    SubentryPasswordPolicy subentryPolicy =
+            new SubentryPasswordPolicy(subentry);
+    try
+    {
+      new PasswordPolicy(subentryPolicy);
+    }
+    catch (ConfigException ex)
+    {
+      throw new DirectoryException(
+              ResultCode.UNWILLING_TO_PERFORM,
+              ex.getMessageObject());
+    }
+    catch (InitializationException ex)
+    {
+      throw new DirectoryException(
+              ResultCode.UNWILLING_TO_PERFORM,
+              ex.getMessageObject());
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void checkSubentryAddAcceptable(Entry entry)
+          throws DirectoryException
+  {
+    if (entry.isPasswordPolicySubentry())
+    {
+      checkSubentryAcceptable(entry);
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void checkSubentryDeleteAcceptable(Entry entry)
+          throws DirectoryException
+  {
+    // FIXME: something like a referential integrity check is needed to
+    // ensure a policy is not removed when referenced by a user entry (
+    // either directly or via a virtual attribute).
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void checkSubentryModifyAcceptable(Entry oldEntry, Entry newEntry)
+          throws DirectoryException
+  {
+    if (newEntry.isPasswordPolicySubentry())
+    {
+      checkSubentryAcceptable(newEntry);
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void checkSubentryModifyDNAcceptable(Entry oldEntry, Entry newEntry)
+          throws DirectoryException
+  {
+    // FIXME: something like a referential integrity check is needed to
+    // ensure a policy is not removed when referenced by a user entry (
+    // either directly or via a virtual attribute).
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void handleSubentryAdd(Entry entry)
+  {
+    if (entry.isPasswordPolicySubentry())
+    {
+      try
+      {
+        SubEntry subentry = new SubEntry(entry);
+        PasswordPolicyConfig config =
+                  createPasswordPolicyConfig(subentry);
+        DirectoryServer.registerPasswordPolicy(
+            subentry.getDN(), config);
+      }
+      catch (Exception e)
+      {
+        if (debugEnabled())
+        {
+          TRACER.debugError("Could not create password policy subentry "
+                  + "DN %s: %s",
+                  entry.getDN().toString(),
+                  stackTraceToSingleLineString(e));
+        }
+      }
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void handleSubentryDelete(Entry entry)
+  {
+    if (entry.isPasswordPolicySubentry())
+    {
+      DirectoryServer.deregisterPasswordPolicy(entry.getDN());
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void handleSubentryModify(Entry oldEntry, Entry newEntry)
+  {
+    if (oldEntry.isPasswordPolicySubentry())
+    {
+      DirectoryServer.deregisterPasswordPolicy(oldEntry.getDN());
+    }
+
+    if (newEntry.isPasswordPolicySubentry())
+    {
+      try
+      {
+        SubEntry subentry = new SubEntry(newEntry);
+        PasswordPolicyConfig config =
+                  createPasswordPolicyConfig(subentry);
+        DirectoryServer.registerPasswordPolicy(
+            subentry.getDN(), config);
+      }
+      catch (Exception e)
+      {
+        if (debugEnabled())
+        {
+          TRACER.debugError("Could not create password policy subentry "
+                  + "DN %s: %s",
+                  newEntry.getDN().toString(),
+                  stackTraceToSingleLineString(e));
+        }
+      }
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void handleSubentryModifyDN(Entry oldEntry, Entry newEntry)
+  {
+    if (oldEntry.isPasswordPolicySubentry())
+    {
+      DirectoryServer.deregisterPasswordPolicy(oldEntry.getDN());
+    }
+
+    if (newEntry.isPasswordPolicySubentry())
+    {
+      try
+      {
+        SubEntry subentry = new SubEntry(newEntry);
+        PasswordPolicyConfig config =
+                  createPasswordPolicyConfig(subentry);
+        DirectoryServer.registerPasswordPolicy(
+            subentry.getDN(), config);
+      }
+      catch (Exception e)
+      {
+        if (debugEnabled())
+        {
+          TRACER.debugError("Could not create password policy subentry "
+                  + "DN %s: %s",
+                  newEntry.getDN().toString(),
+                  stackTraceToSingleLineString(e));
+        }
+      }
+    }
+  }
 }

--
Gitblit v1.10.0