From deb5cb32b58a5e4ddf67d263e0e565fd5b068472 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Fri, 04 Aug 2006 13:38:56 +0000
Subject: [PATCH] Update the password modify extended operation to use the identity mapping API to identify users based on an authorization ID in the "u:" form.  This was previously based on a hard-coded mapping.

---
 opends/resource/schema/02-config.ldif                                               |    4 
 opends/src/server/org/opends/server/extensions/PasswordModifyExtendedOperation.java |  333 ++++++++++++++++++++++++++++++++++------
 opends/resource/config/config.ldif                                                  |    2 
 opends/src/server/org/opends/server/messages/ExtensionsMessages.java                |  118 +++++++++++++-
 4 files changed, 390 insertions(+), 67 deletions(-)

diff --git a/opends/resource/config/config.ldif b/opends/resource/config/config.ldif
index 8d246dc..d1f8d7c 100644
--- a/opends/resource/config/config.ldif
+++ b/opends/resource/config/config.ldif
@@ -297,9 +297,11 @@
 dn: cn=Password Modify,cn=Extended Operations,cn=config
 objectClass: top
 objectClass: ds-cfg-extended-operation-handler
+objectClass: ds-cfg-password-modify-extended-operation-handler
 cn: Password Modify
 ds-cfg-extended-operation-handler-class: org.opends.server.extensions.PasswordModifyExtendedOperation
 ds-cfg-extended-operation-handler-enabled: true
+ds-cfg-identity-mapper-dn: cn=Exact Match,cn=Identity Mappers,cn=config
 
 dn: cn=StartTLS,cn=Extended Operations,cn=config
 objectClass: top
diff --git a/opends/resource/schema/02-config.ldif b/opends/resource/schema/02-config.ldif
index 7165ca2..27f01a8 100644
--- a/opends/resource/schema/02-config.ldif
+++ b/opends/resource/schema/02-config.ldif
@@ -1308,4 +1308,8 @@
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.73 NAME 'ds-cfg-traditional-work-queue'
   SUP ds-cfg-work-queue MUST ds-cfg-num-worker-threads
   MAY ds-cfg-max-work-queue-capacity X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.74
+  NAME 'ds-cfg-password-modify-extended-operation-handler'
+  SUP ds-cfg-extended-operation-handler MUST ds-cfg-identity-mapper-dn
+  X-ORIGIN 'OpenDS Directory Server' )
 
diff --git a/opends/src/server/org/opends/server/extensions/PasswordModifyExtendedOperation.java b/opends/src/server/org/opends/server/extensions/PasswordModifyExtendedOperation.java
index 4ff6127..eedeaa2 100644
--- a/opends/src/server/org/opends/server/extensions/PasswordModifyExtendedOperation.java
+++ b/opends/src/server/org/opends/server/extensions/PasswordModifyExtendedOperation.java
@@ -35,10 +35,14 @@
 import java.util.concurrent.locks.Lock;
 
 import org.opends.server.api.ClientConnection;
+import org.opends.server.api.ConfigurableComponent;
 import org.opends.server.api.ExtendedOperationHandler;
+import org.opends.server.api.IdentityMapper;
 import org.opends.server.api.PasswordStorageScheme;
+import org.opends.server.config.ConfigAttribute;
 import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
+import org.opends.server.config.DNConfigAttribute;
 import org.opends.server.core.DirectoryException;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.ExtendedOperation;
@@ -51,8 +55,6 @@
 import org.opends.server.protocols.asn1.ASN1OctetString;
 import org.opends.server.protocols.asn1.ASN1Sequence;
 import org.opends.server.protocols.internal.InternalClientConnection;
-import org.opends.server.protocols.internal.InternalSearchOperation;
-import org.opends.server.protocols.ldap.LDAPFilter;
 import org.opends.server.schema.AuthPasswordSyntax;
 import org.opends.server.schema.UserPasswordSyntax;
 import org.opends.server.types.Attribute;
@@ -60,13 +62,12 @@
 import org.opends.server.types.AttributeValue;
 import org.opends.server.types.AuthenticationInfo;
 import org.opends.server.types.ByteString;
+import org.opends.server.types.ConfigChangeResult;
 import org.opends.server.types.DN;
 import org.opends.server.types.Entry;
 import org.opends.server.types.Modification;
 import org.opends.server.types.ModificationType;
 import org.opends.server.types.ResultCode;
-import org.opends.server.types.SearchResultEntry;
-import org.opends.server.types.SearchScope;
 
 import static org.opends.server.config.ConfigConstants.*;
 import static org.opends.server.extensions.ExtensionsConstants.*;
@@ -85,6 +86,7 @@
  */
 public class PasswordModifyExtendedOperation
        extends ExtendedOperationHandler
+       implements ConfigurableComponent
 {
   /**
    * The fully-qualified name of this class for debugging purposes.
@@ -94,6 +96,17 @@
 
 
 
+  // The DN of the configuration entry.
+  private DN configEntryDN;
+
+  // The DN of the identity mapper.
+  private DN identityMapperDN;
+
+  // The reference to the identity mapper.
+  private IdentityMapper identityMapper;
+
+
+
   /**
    * Create an instance of this password modify extended operation.  All
    * initialization should be performed in the
@@ -131,6 +144,47 @@
     assert debugEnter(CLASS_NAME, "initializeExtendedOperationHandler",
                       String.valueOf(configEntry));
 
+    configEntryDN = configEntry.getDN();
+
+    int msgID = MSGID_EXTOP_PASSMOD_DESCRIPTION_ID_MAPPER;
+    DNConfigAttribute mapperStub =
+         new DNConfigAttribute(ATTR_IDMAPPER_DN, getMessage(msgID), true, false,
+                               false);
+    try
+    {
+      DNConfigAttribute mapperAttr =
+           (DNConfigAttribute) configEntry.getConfigAttribute(mapperStub);
+      if (mapperAttr == null)
+      {
+        msgID = MSGID_EXTOP_PASSMOD_NO_ID_MAPPER;
+        String message = getMessage(msgID, String.valueOf(configEntryDN));
+        throw new ConfigException(msgID, message);
+      }
+      else
+      {
+        identityMapperDN = mapperAttr.activeValue();
+        identityMapper = DirectoryServer.getIdentityMapper(identityMapperDN);
+        if (identityMapper == null)
+        {
+          msgID = MSGID_EXTOP_PASSMOD_NO_SUCH_ID_MAPPER;
+          String message = getMessage(msgID, String.valueOf(identityMapperDN),
+                                      String.valueOf(configEntryDN));
+          throw new ConfigException(msgID, message);
+        }
+      }
+    }
+    catch (Exception e)
+    {
+      assert debugException(CLASS_NAME, "initializeExtendedOperationHandler",
+                            e);
+      msgID = MSGID_EXTOP_PASSMOD_CANNOT_DETERMINE_ID_MAPPER;
+      String message = getMessage(msgID, String.valueOf(configEntryDN),
+                                  stackTraceToSingleLineString(e));
+      throw new InitializationException(msgID, message, e);
+    }
+
+    DirectoryServer.registerConfigurableComponent(this);
+
     DirectoryServer.registerSupportedExtension(OID_PASSWORD_MODIFY_REQUEST,
                                                this);
   }
@@ -145,6 +199,8 @@
   {
     assert debugEnter(CLASS_NAME, "finalizeExtendedOperationHandler");
 
+    DirectoryServer.deregisterConfigurableComponent(this);
+
     DirectoryServer.deregisterSupportedExtension(OID_PASSWORD_MODIFY_REQUEST);
   }
 
@@ -309,15 +365,55 @@
         }
         else if (lowerAuthzIDStr.startsWith("u:"))
         {
-          userDN = getDNByUserID(operation, authzIDStr.substring(2));
-          if (userDN == null)
+          try
           {
-            return;
-          }
+            userEntry = identityMapper.getEntryForID(authzIDStr.substring(2));
+            if (userEntry == null)
+            {
+              if (oldPassword == null)
+              {
+                operation.setResultCode(ResultCode.NO_SUCH_OBJECT);
 
-          userEntry = getEntryByDN(operation, userDN);
-          if (userEntry == null)
+                int msgID = MSGID_EXTOP_PASSMOD_CANNOT_MAP_USER;
+                operation.appendErrorMessage(getMessage(msgID, authzIDStr));
+              }
+              else
+              {
+                operation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+                int msgID = MSGID_EXTOP_PASSMOD_CANNOT_MAP_USER;
+                operation.appendAdditionalLogMessage(getMessage(msgID,
+                                                                authzIDStr));
+              }
+
+              return;
+            }
+            else
+            {
+              userDN = userEntry.getDN();
+            }
+          }
+          catch (DirectoryException de)
           {
+            assert debugException(CLASS_NAME, "processExtendedOperation", de);
+
+            if (oldPassword == null)
+            {
+              operation.setResultCode(de.getResultCode());
+
+              int msgID = MSGID_EXTOP_PASSMOD_ERROR_MAPPING_USER;
+              operation.appendErrorMessage(getMessage(msgID, authzIDStr,
+                                                      de.getErrorMessage()));
+            }
+            else
+            {
+              operation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+              int msgID = MSGID_EXTOP_PASSMOD_ERROR_MAPPING_USER;
+              operation.appendAdditionalLogMessage(getMessage(msgID, authzIDStr,
+                                                        de.getErrorMessage()));
+            }
+
             return;
           }
         }
@@ -918,65 +1014,192 @@
 
 
   /**
-   * Retrieves the DN of the user with the provided user ID.  The DN will be
-   * obtained by performing a subtree search with a base of the null DN (i.e.,
-   * the root DSE) and therefore potentially searching across multiple backends.
-   * If any problem is encountered or the requested entry does not exist, then
-   * the provided operation will be updated with appropriate result information
-   * and this method will return <CODE>null</CODE>.  The caller is not required
-   * to hold any locks.
+   * Retrieves the DN of the configuration entry with which this component is
+   * associated.
    *
-   * @param  operation  The extended operation being processed.
-   * @param  userID     The user ID for which to retrieve the DN.
-   *
-   * @return  The requested DN, or <CODE>null</CODE> if there was no such entry
-   *          or if a problem was encountered.
+   * @return  The DN of the configuration entry with which this component is
+   *          associated.
    */
-  private DN getDNByUserID(ExtendedOperation operation, String userID)
+  public DN getConfigurableComponentEntryDN()
   {
-    assert debugEnter(CLASS_NAME, "getDNByUserID", String.valueOf(operation),
-                      String.valueOf(userID));
+    assert debugEnter(CLASS_NAME, "getConfigurableComponentEntryDN");
 
-    InternalClientConnection internalConnection =
-         InternalClientConnection.getRootConnection();
+    return configEntryDN;
+  }
 
-    LDAPFilter rawFilter =
-         LDAPFilter.createEqualityFilter("uid", new ASN1OctetString(userID));
 
-    InternalSearchOperation internalSearch =
-         internalConnection.processSearch(new ASN1OctetString(),
-                                          SearchScope.WHOLE_SUBTREE, rawFilter);
 
-    ResultCode resultCode = internalSearch.getResultCode();
-    if (resultCode != ResultCode.SUCCESS)
+  /**
+   * Retrieves the set of configuration attributes that are associated with this
+   * configurable component.
+   *
+   * @return  The set of configuration attributes that are associated with this
+   *          configurable component.
+   */
+  public List<ConfigAttribute> getConfigurationAttributes()
+  {
+    assert debugEnter(CLASS_NAME, "getConfigurationAttributes");
+
+    List<ConfigAttribute> attrList = new LinkedList<ConfigAttribute>();
+
+    int msgID = MSGID_EXTOP_PASSMOD_DESCRIPTION_ID_MAPPER;
+    attrList.add(new DNConfigAttribute(ATTR_IDMAPPER_DN, getMessage(msgID),
+                                       true, false, false, identityMapperDN));
+
+    return attrList;
+  }
+
+
+
+  /**
+   * Indicates whether the provided configuration entry has an acceptable
+   * configuration for this component.  If it does not, then detailed
+   * information about the problem(s) should be added to the provided list.
+   *
+   * @param  configEntry          The configuration entry for which to make the
+   *                              determination.
+   * @param  unacceptableReasons  A list that can be used to hold messages about
+   *                              why the provided entry does not have an
+   *                              acceptable configuration.
+   *
+   * @return  <CODE>true</CODE> if the provided entry has an acceptable
+   *          configuration for this component, or <CODE>false</CODE> if not.
+   */
+  public boolean hasAcceptableConfiguration(ConfigEntry configEntry,
+                      List<String> unacceptableReasons)
+  {
+    assert debugEnter(CLASS_NAME, "hasAcceptableConfiguration",
+                      String.valueOf(configEntry), "List<String>");
+
+
+    // Make sure that the specified identity mapper is OK.
+    int msgID = MSGID_EXTOP_PASSMOD_DESCRIPTION_ID_MAPPER;
+    DNConfigAttribute mapperStub =
+         new DNConfigAttribute(ATTR_IDMAPPER_DN, getMessage(msgID), true, false,
+                               false);
+    try
     {
-      operation.setResultCode(resultCode);
-      operation.setErrorMessage(internalSearch.getErrorMessage());
-      operation.setMatchedDN(internalSearch.getMatchedDN());
-      return null;
+      DNConfigAttribute mapperAttr =
+           (DNConfigAttribute) configEntry.getConfigAttribute(mapperStub);
+      if (mapperAttr == null)
+      {
+        msgID = MSGID_EXTOP_PASSMOD_NO_ID_MAPPER;
+        String message = getMessage(msgID, String.valueOf(configEntry.getDN()));
+        unacceptableReasons.add(message);
+        return false;
+      }
+      else
+      {
+        DN mapperDN = mapperAttr.pendingValue();
+        IdentityMapper mapper = DirectoryServer.getIdentityMapper(mapperDN);
+        if (mapper == null)
+        {
+          msgID = MSGID_EXTOP_PASSMOD_NO_SUCH_ID_MAPPER;
+          String message = getMessage(msgID, String.valueOf(mapperDN),
+                                      String.valueOf(configEntry.getDN()));
+          unacceptableReasons.add(message);
+          return false;
+        }
+      }
     }
-
-    LinkedList<SearchResultEntry> entryList = internalSearch.getSearchEntries();
-    if ((entryList == null) || entryList.isEmpty())
+    catch (Exception e)
     {
-      operation.setResultCode(ResultCode.NO_SUCH_OBJECT);
+      assert debugException(CLASS_NAME, "hasAcceptableConfiguration", e);
 
-      int msgID = MSGID_EXTOP_PASSMOD_NO_DN_BY_AUTHZID;
-      operation.appendErrorMessage(getMessage(msgID, String.valueOf(userID)));
-      return null;
-    }
-
-    if (entryList.size() > 1)
-    {
-      operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
-
-      int msgID = MSGID_EXTOP_PASSMOD_MULTIPLE_ENTRIES_BY_AUTHZID;
-      operation.appendErrorMessage(getMessage(msgID, String.valueOf(userID)));
-      return null;
+      msgID = MSGID_EXTOP_PASSMOD_CANNOT_DETERMINE_ID_MAPPER;
+      String message = getMessage(msgID, String.valueOf(configEntry.getDN()),
+                                  stackTraceToSingleLineString(e));
+      unacceptableReasons.add(message);
+      return false;
     }
 
 
-    return entryList.get(0).getDN();
+    // If we've gotten here, then everything is OK.
+    return true;
+  }
+
+
+
+  /**
+   * Makes a best-effort attempt to apply the configuration contained in the
+   * provided entry.  Information about the result of this processing should be
+   * added to the provided message list.  Information should always be added to
+   * this list if a configuration change could not be applied.  If detailed
+   * results are requested, then information about the changes applied
+   * successfully (and optionally about parameters that were not changed) should
+   * also be included.
+   *
+   * @param  configEntry      The entry containing the new configuration to
+   *                          apply for this component.
+   * @param  detailedResults  Indicates whether detailed information about the
+   *                          processing should be added to the list.
+   *
+   * @return  Information about the result of the configuration update.
+   */
+  public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry,
+                                                  boolean detailedResults)
+  {
+    ResultCode        resultCode          = ResultCode.SUCCESS;
+    boolean           adminActionRequired = false;
+    ArrayList<String> messages            = new ArrayList<String>();
+
+
+    // Make sure that the specified identity mapper is OK.
+    DN             mapperDN = null;
+    IdentityMapper mapper   = null;
+    int msgID = MSGID_EXTOP_PASSMOD_DESCRIPTION_ID_MAPPER;
+    DNConfigAttribute mapperStub =
+         new DNConfigAttribute(ATTR_IDMAPPER_DN, getMessage(msgID), true, false,
+                               false);
+    try
+    {
+      DNConfigAttribute mapperAttr =
+           (DNConfigAttribute) configEntry.getConfigAttribute(mapperStub);
+      if (mapperAttr == null)
+      {
+        resultCode = ResultCode.OBJECTCLASS_VIOLATION;
+
+        msgID = MSGID_EXTOP_PASSMOD_NO_ID_MAPPER;
+        messages.add(getMessage(msgID, String.valueOf(configEntry.getDN())));
+      }
+      else
+      {
+        mapperDN = mapperAttr.pendingValue();
+        mapper   = DirectoryServer.getIdentityMapper(mapperDN);
+        if (mapper == null)
+        {
+          resultCode = ResultCode.CONSTRAINT_VIOLATION;
+
+          msgID = MSGID_EXTOP_PASSMOD_NO_SUCH_ID_MAPPER;
+          messages.add(getMessage(msgID, String.valueOf(mapperDN),
+                                  String.valueOf(configEntry.getDN())));
+        }
+      }
+    }
+    catch (Exception e)
+    {
+      assert debugException(CLASS_NAME, "applyNewConfiguration", e);
+
+      resultCode = DirectoryServer.getServerErrorResultCode();
+
+      msgID = MSGID_EXTOP_PASSMOD_CANNOT_DETERMINE_ID_MAPPER;
+      messages.add(getMessage(msgID, String.valueOf(configEntry.getDN()),
+                              stackTraceToSingleLineString(e)));
+    }
+
+
+    // If all of the changes were acceptable, then apply them.
+    if (resultCode == ResultCode.SUCCESS)
+    {
+      if (! identityMapperDN.equals(mapperDN))
+      {
+        identityMapper   = mapper;
+        identityMapperDN = mapperDN;
+      }
+    }
+
+
+    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
   }
 }
 
diff --git a/opends/src/server/org/opends/server/messages/ExtensionsMessages.java b/opends/src/server/org/opends/server/messages/ExtensionsMessages.java
index 102b377..183590d 100644
--- a/opends/src/server/org/opends/server/messages/ExtensionsMessages.java
+++ b/opends/src/server/org/opends/server/messages/ExtensionsMessages.java
@@ -3750,7 +3750,7 @@
    * occurred.
    */
   public static final int MSGID_EXTOP_PASSMOD_CANNOT_GET_PW_POLICY =
-       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 354;
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 354;
 
 
 
@@ -3760,7 +3760,7 @@
    * take any arguments.
    */
   public static final int MSGID_EXTOP_PASSMOD_REQUIRE_CURRENT_PW =
-       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 355;
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 355;
 
 
 
@@ -3770,7 +3770,7 @@
    * communication channel.  This does not take any arguments.
    */
   public static final int MSGID_EXTOP_PASSMOD_SECURE_AUTH_REQUIRED =
-       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 356;
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 356;
 
 
 
@@ -3780,7 +3780,7 @@
    * does not take any arguments.
    */
   public static final int MSGID_EXTOP_PASSMOD_USER_PW_CHANGES_NOT_ALLOWED =
-       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 357;
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 357;
 
 
 
@@ -3790,7 +3790,7 @@
    * communication channel.  This does not take any arguments.
    */
   public static final int MSGID_EXTOP_PASSMOD_SECURE_CHANGES_REQUIRED =
-       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 358;
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 358;
 
 
 
@@ -3800,7 +3800,7 @@
    * any arguments.
    */
   public static final int MSGID_EXTOP_PASSMOD_IN_MIN_AGE =
-       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 359;
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 359;
 
 
 
@@ -3810,7 +3810,7 @@
    * any arguments.
    */
   public static final int MSGID_EXTOP_PASSMOD_PASSWORD_IS_EXPIRED =
-       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 360;
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 360;
 
 
 
@@ -3820,7 +3820,7 @@
    * generator defined.  This does not take any arguments.
    */
   public static final int MSGID_EXTOP_PASSMOD_NO_PW_GENERATOR =
-       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 361;
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 361;
 
 
 
@@ -3830,7 +3830,7 @@
    * a single argument, which is a message explaining the problem that occurred.
    */
   public static final int MSGID_EXTOP_PASSMOD_CANNOT_GENERATE_PW =
-       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 362;
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 362;
 
 
 
@@ -3840,7 +3840,7 @@
    * take any arguments.
    */
   public static final int MSGID_EXTOP_PASSMOD_PRE_ENCODED_NOT_ALLOWED =
-       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 363;
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 363;
 
 
 
@@ -3850,7 +3850,7 @@
    * This takes a single argument, which is a message explaining the rejection.
    */
   public static final int MSGID_EXTOP_PASSMOD_UNACCEPTABLE_PW =
-       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 364;
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 364;
 
 
 
@@ -3861,7 +3861,69 @@
    * problem that occurred.
    */
   public static final int MSGID_EXTOP_PASSMOD_CANNOT_ENCODE_PASSWORD =
-       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 365;
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 365;
+
+
+
+  /**
+   * The message ID for the message that will be used as the description for the
+   * identity mapper DN configuration attribute.  This does not take any
+   * arguments.
+   */
+  public static final int MSGID_EXTOP_PASSMOD_DESCRIPTION_ID_MAPPER =
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 366;
+
+
+
+  /**
+   * The message ID for the message that will be used if no identity mapper DN
+   * is provided for the password modify extended operation.  This takes a
+   * single argument, which is the DN of the configuration entry.
+   */
+  public static final int MSGID_EXTOP_PASSMOD_NO_ID_MAPPER =
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 367;
+
+
+
+  /**
+   * The message ID for the message that will be used if the specified identity
+   * mapper does not exist or is not enabled.  This takes two arguments, which
+   * are the DN of the identity mapper and the DN of the configuration entry.
+   */
+  public static final int MSGID_EXTOP_PASSMOD_NO_SUCH_ID_MAPPER =
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 368;
+
+
+
+  /**
+   * The message ID for the message that will be used if an error occurs while
+   * trying to determine the identity mapper.  This takes two arguments, which
+   * are the DN of the configuration entry and a string representation of the
+   * exception that was caught.
+   */
+  public static final int MSGID_EXTOP_PASSMOD_CANNOT_DETERMINE_ID_MAPPER =
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 369;
+
+
+
+  /**
+   * The message ID for the message that will be used if an attempt to map a
+   * user by an authorization ID string fails.  This takes a single argument,
+   * which is the provided authorization ID string.
+   */
+  public static final int MSGID_EXTOP_PASSMOD_CANNOT_MAP_USER =
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 370;
+
+
+
+  /**
+   * The message ID for the message that will be used if an error occurs while
+   * attempting to map a user by an authorization ID string.  This takes two
+   * arguments, which are the provided authorization ID string and a message
+   * explaining the problem that occurred.
+   */
+  public static final int MSGID_EXTOP_PASSMOD_ERROR_MAPPING_USER =
+       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 371;
 
 
 
@@ -4050,6 +4112,32 @@
                     "updated.");
 
 
+    registerMessage(MSGID_EXTOP_PASSMOD_DESCRIPTION_ID_MAPPER,
+                    "Specifies the DN of the configuration entry for the " +
+                    "identity mapper that should be used in conjunction with " +
+                    "the password modify extended operation.  This will be " +
+                    "used to identify a user based on an authorization ID " +
+                    "in the 'u:' form.  Changes to this configuration " +
+                    "attribute will take effect immediately.");
+    registerMessage(MSGID_EXTOP_PASSMOD_NO_ID_MAPPER,
+                    "No identity mapper DN was specified in the " +
+                    ATTR_IDMAPPER_DN + " attribute of the password modify " +
+                    "extended operation configuration entry %s.  This is a " +
+                    "required attribute, and the password modify extended " +
+                    "operation will not be enabled.");
+    registerMessage(MSGID_EXTOP_PASSMOD_NO_SUCH_ID_MAPPER,
+                    "The identity mapper with configuration entry DN %s as " +
+                    "specified for use with the password modify extended " +
+                    "operation defined in entry %s either does not exist or " +
+                    "is not enabled.  The identity mapper is a required " +
+                    "component, and the password modify extended operation " +
+                    "will not be enabled.");
+    registerMessage(MSGID_EXTOP_PASSMOD_CANNOT_DETERMINE_ID_MAPPER,
+                    "An error occurred while attempting to determine the " +
+                    "identity mapper to use in conjunction with the password " +
+                    "modify extended operation defined in configuration " +
+                    "entry %s:  %s.  The password modify extended operation " +
+                    "will not be enabled for use in the server.");
     registerMessage(MSGID_EXTOP_PASSMOD_ILLEGAL_REQUEST_ELEMENT_TYPE,
                     "The password modify extended request sequence included " +
                     "an ASN.1 element of an invalid type:  %s.");
@@ -4069,6 +4157,12 @@
                     "processed because the server cannot decode \"%s\" as a " +
                     "valid DN for use in the authorization ID for the " +
                     "operation.");
+    registerMessage(MSGID_EXTOP_PASSMOD_CANNOT_MAP_USER,
+                    "The provided authorization ID string \"%s\" could not " +
+                    "be mapped to any user in the directory.");
+    registerMessage(MSGID_EXTOP_PASSMOD_ERROR_MAPPING_USER,
+                    "An error occurred while attempting to map authorization " +
+                    "ID string \"%s\" to a user entry:  %s.");
     registerMessage(MSGID_EXTOP_PASSMOD_INVALID_AUTHZID_STRING,
                     "The password modify extended request cannot be " +
                     "processed because it contained an invalid authorization " +

--
Gitblit v1.10.0