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

neil_a_wilson
23.22.2006 ff29306505dc180c711220f8d3b572ceb0ff1b3e
Update the GSSAPI SASL mechanism handler to use the identity mapper API in to
resolve the Kerberos principal to the corresponding directory user, rather than
a fixed exact-search mechanism. This is more flexible and more consistent with
the implementation of the other SASL mechanisms.
4 files modified
428 ■■■■ changed files
opends/resource/config/config.ldif 2 ●●● patch | view | raw | blame | history
opends/resource/schema/02-config.ldif 6 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/GSSAPISASLMechanismHandler.java 338 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/messages/ExtensionsMessages.java 82 ●●●●● patch | view | raw | blame | history
opends/resource/config/config.ldif
@@ -1034,7 +1034,7 @@
cn: GSSAPI
ds-cfg-sasl-mechanism-handler-class: org.opends.server.extensions.GSSAPISASLMechanismHandler
ds-cfg-sasl-mechanism-handler-enabled: true
ds-cfg-user-name-attribute: uid
ds-cfg-identity-mapper-dn: cn=Exact Match,cn=Identity Mappers,cn=config
ds-cfg-keytab: /etc/krb5/krb5.keytab
dn: cn=PLAIN,cn=SASL Mechanisms,cn=config
opends/resource/schema/02-config.ldif
@@ -1157,9 +1157,9 @@
  MAY ds-cfg-realm X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.48
  NAME 'ds-cfg-gssapi-sasl-mechanism-handler'
  SUP ds-cfg-sasl-mechanism-handler MAY ( ds-cfg-user-name-attribute $
  ds-cfg-user-base-dn $ ds-cfg-realm $ ds-cfg-kdc-address $
  ds-cfg-keytab $ ds-cfg-server-fqdn ) X-ORIGIN 'OpenDS Directory Server' )
  SUP ds-cfg-sasl-mechanism-handler MAY ( ds-cfg-identity-mapper-dn $
  ds-cfg-realm $ ds-cfg-kdc-address $ ds-cfg-keytab $ ds-cfg-server-fqdn )
  X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.49 NAME 'ds-task' SUP top
  STRUCTURAL MUST ( ds-task-class-name $ ds-task-id ) MAY ( ds-task-state $
  ds-task-scheduled-start-time $ ds-task-actual-start-time $
opends/src/server/org/opends/server/extensions/GSSAPISASLMechanismHandler.java
@@ -38,6 +38,7 @@
import org.opends.server.api.ClientConnection;
import org.opends.server.api.ConfigurableComponent;
import org.opends.server.api.IdentityMapper;
import org.opends.server.api.SASLMechanismHandler;
import org.opends.server.config.ConfigAttribute;
import org.opends.server.config.ConfigEntry;
@@ -48,18 +49,11 @@
import org.opends.server.core.DirectoryException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.InitializationException;
import org.opends.server.protocols.asn1.ASN1OctetString;
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.types.AttributeType;
import org.opends.server.types.AuthenticationInfo;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
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.loggers.Debug.*;
@@ -86,15 +80,15 @@
  // The attribute type that should be used to resolve user IDs to the
  // corresponding entries.
  private AttributeType uidAttributeType;
  // The DN of the configuration entry for this SASL mechanism handler.
  private DN configEntryDN;
  // The DN to use as the search base when trying to find matching user entries.
  private DN userBaseDN;
  // The DN of the identity mapper configuration entry.
  private DN identityMapperDN;
  // The identity mapper that will be used to map the Kerberos principal to a
  // directory user.
  private IdentityMapper identityMapper;
  // The address of the KDC to use for Kerberos authentication.
  private String kdcAddress;
@@ -151,65 +145,43 @@
    this.configEntryDN = configEntry.getDN();
    // Determine the name of the attribute that should be used for username
    // lookups.
    // FIXME -- We should have some kind of a mapping function instead.
    String attrTypeName = DEFAULT_USERNAME_ATTRIBUTE;
    int msgID = MSGID_SASLGSSAPI_DESCRIPTION_USERNAME_ATTRIBUTE;
    StringConfigAttribute uidAttributeStub =
         new StringConfigAttribute(ATTR_USERNAME_ATTRIBUTE,
                                   getMessage(msgID), false, false, false);
    // Get the identity mapper that should be used to find users.
    int msgID = MSGID_SASLGSSAPI_DESCRIPTION_IDENTITY_MAPPER_DN;
    DNConfigAttribute mapperStub =
         new DNConfigAttribute(ATTR_IDMAPPER_DN, getMessage(msgID), true, false,
                               false);
    try
    {
      StringConfigAttribute uidAttributeAttr =
           (StringConfigAttribute)
           configEntry.getConfigAttribute(uidAttributeStub);
      if (uidAttributeAttr != null)
      DNConfigAttribute mapperAttr =
           (DNConfigAttribute) configEntry.getConfigAttribute(mapperStub);
      if (mapperAttr == null)
      {
        attrTypeName = toLowerCase(uidAttributeAttr.activeValue());
        msgID = MSGID_SASLGSSAPI_NO_IDENTITY_MAPPER_ATTR;
        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_SASLGSSAPI_NO_SUCH_IDENTITY_MAPPER;
          String message = getMessage(msgID, String.valueOf(identityMapperDN),
                                      String.valueOf(configEntryDN));
          throw new ConfigException(msgID, message);
        }
      }
    }
    catch (ConfigException ce)
    {
      throw ce;
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeSASLMechanismHandler", e);
      msgID = MSGID_SASLGSSAPI_CANNOT_GET_USERNAME_ATTR;
      String message = getMessage(msgID, String.valueOf(configEntryDN),
                                  stackTraceToSingleLineString(e));
      throw new InitializationException(msgID, message, e);
    }
    uidAttributeType = DirectoryServer.getAttributeType(attrTypeName);
    if (uidAttributeType == null)
    {
      msgID = MSGID_SASLGSSAPI_UNKNOWN_USERNAME_ATTR;
      String message = getMessage(msgID, String.valueOf(attrTypeName),
                                  String.valueOf(configEntryDN));
      throw new ConfigException(msgID, message);
    }
    // Determine the base DN that we should use when searching for users by
    // username.
    userBaseDN = new DN();
    msgID = MSGID_SASLGSSAPI_DESCRIPTION_USER_BASE_DN;
    DNConfigAttribute userBaseStub =
         new DNConfigAttribute(ATTR_USER_BASE_DN, getMessage(msgID), false,
                               false, false);
    try
    {
      DNConfigAttribute userBaseAttr =
           (DNConfigAttribute) configEntry.getConfigAttribute(userBaseStub);
      if (userBaseAttr != null)
      {
        userBaseDN = userBaseAttr.activeValue();
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "initializeSASLMechanismHandler", e);
      msgID = MSGID_SASLGSSAPI_CANNOT_GET_USER_BASE_DN;
      msgID = MSGID_SASLGSSAPI_CANNOT_GET_IDENTITY_MAPPER;
      String message = getMessage(msgID, String.valueOf(configEntryDN),
                                  stackTraceToSingleLineString(e));
      throw new InitializationException(msgID, message, e);
@@ -522,44 +494,10 @@
  public Entry getUserForAuthzID(BindOperation bindOperation, String authzID)
         throws DirectoryException
  {
    // FIXME -- This needs to use some kind of identity mapping.
    LDAPFilter filter =
         LDAPFilter.createEqualityFilter(uidAttributeType.getNameOrOID(),
                                         new ASN1OctetString(authzID));
    assert debugEnter(CLASS_NAME, "getUserForAuthzID",
                      String.valueOf(bindOperation), String.valueOf(authzID));
    InternalClientConnection conn =
         InternalClientConnection.getRootConnection();
    InternalSearchOperation op =
         conn.processSearch(new ASN1OctetString(userBaseDN.toString()),
                            SearchScope.WHOLE_SUBTREE, filter);
    ResultCode rc = op.getResultCode();
    if (rc != ResultCode.SUCCESS)
    {
      int    msgID   = MSGID_SASLGSSAPI_CANNOT_PERFORM_INTERNAL_SEARCH;
      String message = getMessage(msgID, authzID, String.valueOf(rc),
                                  String.valueOf(op.getErrorMessage()));
      throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, message,
                                   msgID);
    }
    Entry userEntry = null;
    LinkedList<SearchResultEntry> searchEntries = op.getSearchEntries();
    if (! searchEntries.isEmpty())
    {
      userEntry = searchEntries.removeFirst();
      if (! searchEntries.isEmpty())
      {
        int    msgID   = MSGID_SASLGSSAPI_MULTIPLE_MATCHING_ENTRIES;
        String message = getMessage(msgID, authzID);
        throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, message,
                                     msgID);
      }
    }
    return userEntry;
    return identityMapper.getEntryForID(authzID);
  }
@@ -595,15 +533,9 @@
    LinkedList<ConfigAttribute> attrList = new LinkedList<ConfigAttribute>();
    int msgID = MSGID_SASLGSSAPI_DESCRIPTION_USERNAME_ATTRIBUTE;
    String uidTypeStr = uidAttributeType.getNameOrOID();
    attrList.add(new StringConfigAttribute(ATTR_USERNAME_ATTRIBUTE,
                                           getMessage(msgID), false, false,
                                           false, uidTypeStr));
    msgID = MSGID_SASLGSSAPI_DESCRIPTION_USER_BASE_DN;
    attrList.add(new DNConfigAttribute(ATTR_USER_BASE_DN, getMessage(msgID),
                                       false, false, false, userBaseDN));
    int msgID = MSGID_SASLGSSAPI_DESCRIPTION_IDENTITY_MAPPER_DN;
    attrList.add(new DNConfigAttribute(ATTR_IDMAPPER_DN, getMessage(msgID),
                                       true, false, false, identityMapperDN));
    msgID = MSGID_SASLGSSAPI_DESCRIPTION_SERVER_FQDN;
    attrList.add(new StringConfigAttribute(ATTR_SERVER_FQDN, getMessage(msgID),
@@ -643,62 +575,45 @@
                      String.valueOf(configEntry), "java.util.List<String>");
    // Look at the username attribute type configuration.
    String attrTypeName = DEFAULT_USERNAME_ATTRIBUTE;
    int msgID = MSGID_SASLGSSAPI_DESCRIPTION_USERNAME_ATTRIBUTE;
    StringConfigAttribute uidAttributeStub =
         new StringConfigAttribute(ATTR_USERNAME_ATTRIBUTE, getMessage(msgID),
                                   false, false, false);
    // Look at the identity mapper configuration
    int msgID = MSGID_SASLGSSAPI_DESCRIPTION_IDENTITY_MAPPER_DN;
    DNConfigAttribute mapperStub =
         new DNConfigAttribute(ATTR_IDMAPPER_DN, getMessage(msgID), true, false,
                               false);
    try
    {
      StringConfigAttribute uidAttributeAttr =
           (StringConfigAttribute)
           configEntry.getConfigAttribute(uidAttributeStub);
      if (uidAttributeAttr != null)
      DNConfigAttribute mapperAttr =
           (DNConfigAttribute) configEntry.getConfigAttribute(mapperStub);
      if (mapperAttr == null)
      {
        attrTypeName = toLowerCase(uidAttributeAttr.activeValue());
        msgID = MSGID_SASLGSSAPI_NO_IDENTITY_MAPPER_ATTR;
        String message = getMessage(msgID, String.valueOf(configEntryDN));
        unacceptableReasons.add(message);
        return false;
      }
      else
      {
        DN mapperDN = mapperAttr.activeValue();
        IdentityMapper mapper =
             DirectoryServer.getIdentityMapper(mapperDN);
        if (mapper == null)
        {
          msgID = MSGID_SASLGSSAPI_NO_SUCH_IDENTITY_MAPPER;
          String message = getMessage(msgID, String.valueOf(mapperDN),
                                      String.valueOf(configEntryDN));
          unacceptableReasons.add(message);
          return false;
        }
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "hasAcceptableConfiguration", e);
      assert debugException(CLASS_NAME, "initializeSASLMechanismHandler", e);
      msgID = MSGID_SASLGSSAPI_CANNOT_GET_USERNAME_ATTR;
      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
                                         stackTraceToSingleLineString(e)));
      return false;
    }
    if (DirectoryServer.getAttributeType(attrTypeName) == null)
    {
      msgID = MSGID_SASLGSSAPI_UNKNOWN_USERNAME_ATTR;
      unacceptableReasons.add(getMessage(msgID, String.valueOf(attrTypeName),
                                         String.valueOf(configEntryDN)));
      return false;
    }
    // Look at the user base DN configuration.
    msgID = MSGID_SASLGSSAPI_DESCRIPTION_USER_BASE_DN;
    DNConfigAttribute userBaseStub =
         new DNConfigAttribute(ATTR_USER_BASE_DN, getMessage(msgID), false,
                               false, false);
    try
    {
      DNConfigAttribute userBaseAttr =
           (DNConfigAttribute) configEntry.getConfigAttribute(userBaseStub);
      if (userBaseAttr != null)
      {
        DN userBaseDN = userBaseAttr.activeValue();
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "hasAcceptableConfiguration", e);
      msgID = MSGID_SASLGSSAPI_CANNOT_GET_USER_BASE_DN;
      unacceptableReasons.add(getMessage(msgID, String.valueOf(configEntryDN),
                                         stackTraceToSingleLineString(e)));
      msgID = MSGID_SASLGSSAPI_CANNOT_GET_IDENTITY_MAPPER;
      String message = getMessage(msgID, String.valueOf(configEntryDN),
                                  stackTraceToSingleLineString(e));
      unacceptableReasons.add(message);
      return false;
    }
@@ -804,66 +719,50 @@
    ArrayList<String> messages            = new ArrayList<String>();
    // Look at the username attribute type configuration.
    String attrTypeName = DEFAULT_USERNAME_ATTRIBUTE;
    int msgID = MSGID_SASLGSSAPI_DESCRIPTION_USERNAME_ATTRIBUTE;
    StringConfigAttribute usernameAttributeStub =
         new StringConfigAttribute(ATTR_USERNAME_ATTRIBUTE, getMessage(msgID),
                                   false, false, false);
    // Look at the identity mapper configuration
    DN             newIdentityMapperDN = null;
    IdentityMapper newIdentityMapper   = null;
    int msgID = MSGID_SASLGSSAPI_DESCRIPTION_IDENTITY_MAPPER_DN;
    DNConfigAttribute mapperStub =
         new DNConfigAttribute(ATTR_IDMAPPER_DN, getMessage(msgID), true, false,
                               false);
    try
    {
      StringConfigAttribute usernameAttributeAttr =
           (StringConfigAttribute)
           configEntry.getConfigAttribute(usernameAttributeStub);
      if (usernameAttributeAttr != null)
      DNConfigAttribute mapperAttr =
           (DNConfigAttribute) configEntry.getConfigAttribute(mapperStub);
      if (mapperAttr == null)
      {
        attrTypeName = toLowerCase(usernameAttributeAttr.activeValue());
        msgID = MSGID_SASLGSSAPI_NO_IDENTITY_MAPPER_ATTR;
        messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
        if (resultCode == ResultCode.SUCCESS)
        {
          resultCode = ResultCode.OBJECTCLASS_VIOLATION;
        }
      }
      else
      {
        newIdentityMapperDN = mapperAttr.activeValue();
        newIdentityMapper =
             DirectoryServer.getIdentityMapper(newIdentityMapperDN);
        if (newIdentityMapper == null)
        {
          msgID = MSGID_SASLGSSAPI_NO_SUCH_IDENTITY_MAPPER;
          messages.add(getMessage(msgID, String.valueOf(newIdentityMapperDN),
                                  String.valueOf(configEntryDN)));
          if (resultCode == ResultCode.SUCCESS)
          {
            resultCode = ResultCode.CONSTRAINT_VIOLATION;
          }
        }
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyNewConfiguration", e);
      assert debugException(CLASS_NAME, "initializeSASLMechanismHandler", e);
      msgID = MSGID_SASLGSSAPI_CANNOT_GET_USERNAME_ATTR;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                              stackTraceToSingleLineString(e)));
      resultCode = DirectoryServer.getServerErrorResultCode();
    }
    AttributeType newUIDType = DirectoryServer.getAttributeType(attrTypeName);
    if (newUIDType == null)
    {
      msgID = MSGID_SASLGSSAPI_UNKNOWN_USERNAME_ATTR;
      messages.add(getMessage(msgID, String.valueOf(attrTypeName),
                              String.valueOf(configEntryDN)));
      if (resultCode == ResultCode.SUCCESS)
      {
        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
      }
    }
    // Look at the user base DN configuration.
    DN newUserBase = new DN();
    msgID = MSGID_SASLGSSAPI_DESCRIPTION_USER_BASE_DN;
    DNConfigAttribute userBaseStub =
         new DNConfigAttribute(ATTR_USER_BASE_DN, getMessage(msgID), false,
                               false, false);
    try
    {
      DNConfigAttribute userBaseAttr =
           (DNConfigAttribute) configEntry.getConfigAttribute(userBaseStub);
      if (userBaseAttr != null)
      {
        newUserBase = userBaseAttr.pendingValue();
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "applyNewConfiguration", e);
      msgID = MSGID_SASLGSSAPI_CANNOT_GET_USER_BASE_DN;
      msgID = MSGID_SASLGSSAPI_CANNOT_GET_IDENTITY_MAPPER;
      messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                              stackTraceToSingleLineString(e)));
@@ -972,27 +871,16 @@
    // If everything has been successful, then apply any changes that were made.
    if (resultCode == ResultCode.SUCCESS)
    {
      if (! uidAttributeType.equals(newUIDType))
      if (! identityMapperDN.equals(newIdentityMapperDN))
      {
        uidAttributeType = newUIDType;
        identityMapperDN = newIdentityMapperDN;
        identityMapper   = newIdentityMapper;
        if (detailedResults)
        {
          msgID = MSGID_SASLGSSAPI_UPDATED_USERNAME_ATTR;
          msgID = MSGID_SASLGSSAPI_UPDATED_IDENTITY_MAPPER;
          messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                                  uidAttributeType.getNameOrOID()));
        }
      }
      if (! userBaseDN.equals(newUserBase))
      {
        userBaseDN = newUserBase;
        if (detailedResults)
        {
          msgID = MSGID_SASLGSSAPI_UPDATED_USER_BASE_DN;
          messages.add(getMessage(msgID, String.valueOf(configEntryDN),
                                  String.valueOf(userBaseDN)));
                                  String.valueOf(identityMapperDN)));
        }
      }
opends/src/server/org/opends/server/messages/ExtensionsMessages.java
@@ -3687,6 +3687,61 @@
       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 348;
  /**
   * The message ID for the message that will be used as the description of the
   * attribute used to specify the DN of the configuration entry that defines
   * the identity mapper to use in conjunction with the GSSAPI SASL mechanism.
   * This does not take any arguments.
   */
  public static final int MSGID_SASLGSSAPI_DESCRIPTION_IDENTITY_MAPPER_DN =
       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 349;
  /**
   * The message ID for the message that will be used if the GSSAPI handler
   * configuration entry does not have an attribute that specifies which
   * identity mapper should be used.  This takes a single argument, which is the
   * DN of the SASL GSSAPI configuration entry.
   */
  public static final int MSGID_SASLGSSAPI_NO_IDENTITY_MAPPER_ATTR =
       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 350;
  /**
   * The message ID for the message that will be used if the identity mapper DN
   * specified in the GSSAPI handler entry does not refer to an active identity
   * mapper.  This takes two arguments, which are the DN of the specified
   * identity mapper and the DN of the SASL GSSAPI configuration entry.
   */
  public static final int MSGID_SASLGSSAPI_NO_SUCH_IDENTITY_MAPPER =
       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 351;
  /**
   * The message ID for the message that will be used if an error occurs while
   * trying to determine which identity mapper to use in conjunction with the
   * DIGEST-MD5 SASL mechanism.  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_SASLGSSAPI_CANNOT_GET_IDENTITY_MAPPER =
       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 352;
  /**
   * The message ID for the message that will be used to indicate that the
   * identity mapper used for GSSAPI authentication has been updated with a new
   * value.  This takes two arguments, which are the DN of the configuration
   * entry and the new identity mapper DN.
   */
  public static final int MSGID_SASLGSSAPI_UPDATED_IDENTITY_MAPPER =
       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_INFORMATIONAL | 353;
  /**
   * Associates a set of generic messages with the message IDs defined in this
@@ -5003,6 +5058,28 @@
                    "An unexpected error occurred while attempting to " +
                    "determine the value of the " + ATTR_USER_BASE_DN +
                    " attribute in configuration entry %s:  %s.");
    registerMessage(MSGID_SASLGSSAPI_DESCRIPTION_IDENTITY_MAPPER_DN,
                    "Specifies the DN of the configuration entry that holds " +
                    "the configuration for the identity mapper that should " +
                    "be used to map the GSSAPI principal to a Directory " +
                    "Server user entry.  Changes to this configuration " +
                    "attribute will take effect immediately.");
    registerMessage(MSGID_SASLGSSAPI_NO_IDENTITY_MAPPER_ATTR,
                    "Configuration entry %s does not contain attribute " +
                    ATTR_IDMAPPER_DN + " which specifies the DN of the " +
                    "identity mapper to use in conjunction with the GSSAPI " +
                    "SASL mechanism.  This is a required attribute.");
    registerMessage(MSGID_SASLGSSAPI_NO_SUCH_IDENTITY_MAPPER,
                    "The identity mapper %s specified in attribute " +
                    ATTR_IDMAPPER_DN + " of configuration entry %s does not " +
                    "reference a valid identity mapper configuration that is " +
                    "enabled for use in the Directory Server.");
    registerMessage(MSGID_SASLGSSAPI_CANNOT_GET_IDENTITY_MAPPER,
                    "An error occurred while trying to process the value " +
                    "of the " + ATTR_IDMAPPER_DN + " attribute in " +
                    "configuration entry %s to determine which identity " +
                    "mapper should be used in conjunction with the GSSAPI " +
                    "SASL mechanism:  %s.");
    registerMessage(MSGID_SASLGSSAPI_DESCRIPTION_SERVER_FQDN,
                    "Specifies the fully-qualified domain name that should " +
                    "be used for the server during SASL GSSAPI " +
@@ -5022,6 +5099,11 @@
                    " in configuration entry %s has been updated.  The DN %s " +
                    "will now be used as the search base when looking up " +
                    "user entries based on their username.");
    registerMessage(MSGID_SASLGSSAPI_UPDATED_IDENTITY_MAPPER,
                    "Attribute " + ATTR_IDMAPPER_DN +
                    " in configuration entry %s has been updated.  The value " +
                    "\"%s\" will now be used as the DN of the identity " +
                    "mapper configuration entry for GSSAPI authentication.");
    registerMessage(MSGID_SASLGSSAPI_UPDATED_NEW_SERVER_FQDN,
                    "Attribute " + ATTR_SERVER_FQDN +
                    " in configuration entry %s has been updated.  The value " +