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

neil_a_wilson
08.27.2007 4a4a8540f0b64feff6934c3215c6f896c9561c7d
opends/src/server/org/opends/server/api/ClientConnection.java
@@ -80,6 +80,10 @@
  // until the bind completes.
  private boolean bindInProgress;
  // Indicates whether any necessary finalization work has been done
  // for this client connection.
  private boolean finalized;
  // The size limit for use with this client connection.
  private int sizeLimit;
@@ -122,6 +126,79 @@
    sizeLimit          = DirectoryServer.getSizeLimit();
    timeLimit          = DirectoryServer.getTimeLimit();
    lookthroughLimit   = DirectoryServer.getLookthroughLimit();
    finalized          = false;
  }
  /**
   * Performs any internal cleanup that may be necessary when this
   * client connection is disconnected, or if not on disconnec, then
   * ultimately whenever it is reaped by the garbage collector.  In
   * this case, it will be used to ensure that the connection is
   * deregistered with the {@code AuthenticatedUsers} manager, and
   * will then invoke the {@code finalizeClientConnection} method.
   */
  protected final void finalizeConnectionInternal()
  {
    if (finalized)
    {
      return;
    }
    finalized = true;
    // Deregister with the set of authenticated users.
    Entry authNEntry = authenticationInfo.getAuthenticationEntry();
    Entry authZEntry = authenticationInfo.getAuthorizationEntry();
    if (authNEntry != null)
    {
      if ((authZEntry == null) ||
          authZEntry.getDN().equals(authNEntry.getDN()))
      {
        DirectoryServer.getAuthenticatedUsers().remove(
             authNEntry.getDN(), this);
      }
      else
      {
        DirectoryServer.getAuthenticatedUsers().remove(
             authNEntry.getDN(), this);
        DirectoryServer.getAuthenticatedUsers().remove(
             authZEntry.getDN(), this);
      }
    }
    else if (authZEntry != null)
    {
      DirectoryServer.getAuthenticatedUsers().remove(
           authZEntry.getDN(), this);
    }
    try
    {
      finalizeClientConnection();
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "finalizeConnectionInternal",
                            e);
    }
  }
  /**
   * Performs any cleanup work that may be necessary when this client
   * connection is terminated.  By default, no action is taken.
   * <BR><BR>
   * If possible, this method will be invoked when the client
   * connection is disconnected.  If it isn't invoked at that time,
   * then it will be called when the client connection object is
   * finalized by the garbage collector.
   */
  protected void finalizeClientConnection()
  {
    // No implementation is required by default.
  }
@@ -430,9 +507,9 @@
   *                           associated with the provided message
   *                           ID.
   */
  public void disconnect(DisconnectReason disconnectReason,
                         boolean sendNotification, int messageID,
                         Object... arguments)
  public final void disconnect(DisconnectReason disconnectReason,
                               boolean sendNotification,
                               int messageID, Object... arguments)
  {
    assert debugEnter(CLASS_NAME, "disconnect",
                      String.valueOf(disconnectReason),
@@ -456,6 +533,9 @@
   * operation processing (e.g., within a plugin or other extension),
   * the <CODE>disconnectClient</CODE> method within that operation
   * should be called rather than invoking this method directly.
   * <BR><BR>
   * All subclasses must invoke the {@code finalizeConnectionInternal}
   * method during the course of processing this method.
   *
   * @param  disconnectReason  The disconnect reason that provides the
   *                           generic cause for the disconnect.
@@ -733,6 +813,36 @@
    assert debugEnter(CLASS_NAME, "setAuthenticationInfo",
                      String.valueOf(authenticationInfo));
    if (this.authenticationInfo != null)
    {
      Entry authNEntry =
                 this.authenticationInfo.getAuthenticationEntry();
      Entry authZEntry =
                 this.authenticationInfo.getAuthorizationEntry();
      if (authNEntry != null)
      {
        if ((authZEntry == null) ||
            authZEntry.getDN().equals(authNEntry.getDN()))
        {
          DirectoryServer.getAuthenticatedUsers().remove(
               authNEntry.getDN(), this);
        }
        else
        {
          DirectoryServer.getAuthenticatedUsers().remove(
               authNEntry.getDN(), this);
          DirectoryServer.getAuthenticatedUsers().remove(
               authZEntry.getDN(), this);
        }
      }
      else if (authZEntry != null)
      {
        DirectoryServer.getAuthenticatedUsers().remove(
             authZEntry.getDN(), this);
      }
    }
    if (authenticationInfo == null)
    {
      this.authenticationInfo = new AuthenticationInfo();
@@ -740,6 +850,76 @@
    else
    {
      this.authenticationInfo = authenticationInfo;
      Entry authNEntry = authenticationInfo.getAuthenticationEntry();
      Entry authZEntry = authenticationInfo.getAuthorizationEntry();
      if (authNEntry != null)
      {
        if ((authZEntry == null) ||
            authZEntry.getDN().equals(authNEntry.getDN()))
        {
          DirectoryServer.getAuthenticatedUsers().put(
               authNEntry.getDN(), this);
        }
        else
        {
          DirectoryServer.getAuthenticatedUsers().put(
               authNEntry.getDN(), this);
          DirectoryServer.getAuthenticatedUsers().put(
               authZEntry.getDN(), this);
        }
      }
      else if (authZEntry != null)
      {
        DirectoryServer.getAuthenticatedUsers().put(
             authZEntry.getDN(), this);
      }
    }
  }
  /**
   * Updates the cached entry associated with either the
   * authentication and/or authorization identity with the provided
   * version.
   *
   * @param  oldEntry  The user entry currently serving as the
   *                   authentication and/or authorization identity.
   * @param  newEntry  The updated entry that should replace the
   *                   existing entry.  It may optionally have a
   *                   different DN than the old entry.
   */
  public void updateAuthenticationInfo(Entry oldEntry, Entry newEntry)
  {
    assert debugEnter(CLASS_NAME, "updateAuthenticationInfo",
                      String.valueOf(oldEntry),
                      String.valueOf(newEntry));
    Entry authNEntry = authenticationInfo.getAuthenticationEntry();
    Entry authZEntry = authenticationInfo.getAuthorizationEntry();
    if ((authNEntry != null) &&
        authNEntry.getDN().equals(oldEntry.getDN()))
    {
      if ((authZEntry == null) ||
          (! authZEntry.getDN().equals(authNEntry.getDN())))
      {
        authenticationInfo =
             authenticationInfo.duplicate(newEntry, authZEntry);
      }
      else
      {
        authenticationInfo =
             authenticationInfo.duplicate(newEntry, newEntry);
      }
    }
    else if ((authZEntry != null) &&
             (authZEntry.getDN().equals(oldEntry.getDN())))
    {
      authenticationInfo =
           authenticationInfo.duplicate(authNEntry, newEntry);
    }
  }
@@ -1053,5 +1233,20 @@
   *                 appended.
   */
  public abstract void toString(StringBuilder buffer);
  /**
   * Performs any work that may be needed before the JVM invokes
   * garbage collection for this object.  In this case, it makes sure
   * to deregister with the Directory Server as a change notification
   * listener.  If a subclass wishes to perform custom finalization
   * processing, then it should override this method and make sure to
   * invoke {@code super.finalize} as its first call.
   */
  protected void finalize()
  {
    finalizeConnectionInternal();
  }
}
opends/src/server/org/opends/server/controls/ProxiedAuthV1Control.java
@@ -327,27 +327,37 @@
  /**
   * Retrieves the authorization DN for this proxied authorization V1 control
   * only if it references a valid Directory Server user entry.  It will also
   * perform any necessary password policy checks to ensure that the specified
   * user account is suitable for use in performing this processing.
   * Retrieves the authorization entry for this proxied authorization V1
   * control.  It will also perform any necessary password policy checks to
   * ensure that the associated user account is suitable for use in performing
   * this processing.
   *
   * @return  The validated authorization DN for this proxied authorization V1
   *          control.
   * @return  The entry for user specified as the authorization identity in this
   *          proxied authorization V1 control, or {@code null} if the
   *          authorization DN is the null DN.
   *
   * @throws  DirectoryException  If an error occurs while attempting to make
   *                              the determination, or if the target user does
   *                              not exist.
   * @throws  DirectoryException  If the target user does not exist or is not
   *                              available for use, or if a problem occurs
   *                              while making the determination.
   */
  public DN getValidatedAuthorizationDN()
  public Entry getAuthorizationEntry()
         throws DirectoryException
  {
    assert debugEnter(CLASS_NAME, "getValidatedAuthorizationDN");
    assert debugEnter(CLASS_NAME, "getAuthorizationEntry");
    DN authzDN = getAuthorizationDN();
    if (authzDN.isNullDN())
    {
      return authzDN;
      return null;
    }
    // See if the authorization DN is one of the alternate bind DNs for one of
    // the root users and if so then map it accordingly.
    DN actualDN = DirectoryServer.getActualRootBindDN(authzDN);
    if (actualDN != null)
    {
      authzDN = actualDN;
    }
@@ -400,7 +410,7 @@
      // If we've made it here, then the user is acceptable.
      return authzDN;
      return userEntry;
    }
    finally
    {
opends/src/server/org/opends/server/controls/ProxiedAuthV2Control.java
@@ -233,19 +233,20 @@
  /**
   * Retrieves the authorization DN for this proxied authorization V2 control
   * only if it references a valid Directory Server user entry.  It will also
   * perform any necessary password policy checks to ensure that the specified
   * user account is suitable for use in performing this processing.
   * Retrieves the authorization entry for this proxied authorization V2
   * control.  It will also perform any necessary password policy checks to
   * ensure that the associated user account is suitable for use in performing
   * this processing.
   *
   * @return  The validated authorization DN for this proxied authorization V2
   *          control.
   * @return  The entry for user specified as the authorization identity in this
   *          proxied authorization V1 control, or {@code null} if the
   *          authorization DN is the null DN.
   *
   * @throws  DirectoryException  If an error occurs while attempting to make
   *                              the determination, or if the target user does
   *                              not exist.
   * @throws  DirectoryException  If the target user does not exist or is not
   *                              available for use, or if a problem occurs
   *                              while making the determination.
   */
  public DN getValidatedAuthorizationDN()
  public Entry getAuthorizationEntry()
         throws DirectoryException
  {
    assert debugEnter(CLASS_NAME, "getValidatedAuthorizationDN");
@@ -254,7 +255,7 @@
    // Check for a zero-length value, which would be for an anonymous user.
    if (authorizationID.value().length == 0)
    {
      return DN.nullDN();
      return null;
    }
@@ -269,10 +270,18 @@
      DN authzDN = DN.decode(authzID.substring(3));
      if (authzDN.isNullDN())
      {
        return authzDN;
        return null;
      }
      else
      {
        // See if the authorization DN is one of the alternate bind DNs for one
        // of the root users and if so then map it accordingly.
        DN actualDN = DirectoryServer.getActualRootBindDN(authzDN);
        if (actualDN != null)
        {
          authzDN = actualDN;
        }
        Lock entryLock = null;
        for (int i=0; i < 3; i++)
        {
@@ -321,7 +330,7 @@
          // If we've made it here, then the user is acceptable.
          return authzDN;
          return userEntry;
        }
        finally
        {
@@ -334,7 +343,7 @@
      // If the authorization ID is just "u:", then it's an anonymous request.
      if (lowerAuthzID.length() == 2)
      {
        return DN.nullDN();
        return null;
      }
@@ -360,8 +369,6 @@
      }
      else
      {
        DN authzDN = userEntry.getDN();
        // FIXME -- We should provide some mechanism for enabling debug
        // processing.
        PasswordPolicyState pwpState =
@@ -373,12 +380,12 @@
            pwpState.isPasswordExpired())
        {
          int    msgID   = MSGID_PROXYAUTH2_UNUSABLE_ACCOUNT;
          String message = getMessage(msgID, String.valueOf(authzDN));
          String message = getMessage(msgID, String.valueOf(userEntry.getDN()));
          throw new DirectoryException(ResultCode.AUTHORIZATION_DENIED,
                                       message, msgID);
        }
        return authzDN;
        return userEntry;
      }
    }
    else
opends/src/server/org/opends/server/core/AddOperation.java
@@ -1783,10 +1783,10 @@
              }
              DN authzDN;
              Entry authorizationEntry;
              try
              {
                authzDN = proxyControl.getValidatedAuthorizationDN();
                authorizationEntry = proxyControl.getAuthorizationEntry();
              }
              catch (DirectoryException de)
              {
@@ -1801,7 +1801,7 @@
              // FIXME -- Should we specifically check permissions here, or let
              //          the earlier access control checks handle it?
              setAuthorizationDN(authzDN);
              setAuthorizationEntry(authorizationEntry);
            }
            else if (oid.equals(OID_PROXIED_AUTH_V2))
            {
@@ -1828,10 +1828,10 @@
              }
              DN authzDN;
              Entry authorizationEntry;
              try
              {
                authzDN = proxyControl.getValidatedAuthorizationDN();
                authorizationEntry = proxyControl.getAuthorizationEntry();
              }
              catch (DirectoryException de)
              {
@@ -1846,7 +1846,7 @@
              // FIXME -- Should we specifically check permissions here, or let
              //          the earlier access control checks handle it?
              setAuthorizationDN(authzDN);
              setAuthorizationEntry(authorizationEntry);
            }
            // NYI -- Add support for additional controls.
opends/src/server/org/opends/server/core/AuthenticatedUsers.java
New file
@@ -0,0 +1,265 @@
/*
 * 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 2007 Sun Microsystems, Inc.
 */
package org.opends.server.core;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import org.opends.server.api.ChangeNotificationListener;
import org.opends.server.api.ClientConnection;
import org.opends.server.types.DisconnectReason;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.operation.PostResponseAddOperation;
import org.opends.server.types.operation.PostResponseDeleteOperation;
import org.opends.server.types.operation.PostResponseModifyOperation;
import org.opends.server.types.operation.PostResponseModifyDNOperation;
import static org.opends.server.loggers.Debug.*;
import static org.opends.server.messages.CoreMessages.*;
import static org.opends.server.messages.MessageHandler.*;
/**
 * This class provides a data structure which maps an authenticated user DN to
 * the set of client connections authenticated as that user.  Note that a single
 * client connection may be registered with two different user DNs if the client
 * has different authentication and authorization identities.
 * <BR><BR>
 * This class also provides a mechanism for detecting changes to authenticated
 * user entries and notifying the corresponding client connections so that they
 * can update their cached versions.
 */
public class AuthenticatedUsers
       implements ChangeNotificationListener
{
  /**
   * The fully-qualified name of this class for debugging purposes.
   */
  private static final String CLASS_NAME =
       "org.opends.server.core.AuthenticatedUsers";
  // The mapping between authenticated user DNs and the associated client
  // connection objects.
  private ConcurrentHashMap<DN,CopyOnWriteArraySet<ClientConnection>>
               userMap;
  /**
   * Creates a new instance of this authenticated users object.
   */
  public AuthenticatedUsers()
  {
    assert debugConstructor(CLASS_NAME);
    userMap = new ConcurrentHashMap<DN,CopyOnWriteArraySet<ClientConnection>>();
    DirectoryServer.registerChangeNotificationListener(this);
  }
  /**
   * Registers the provided user DN and client connection with this object.
   *
   * @param  userDN            The DN of the user associated with the provided
   *                           client connection.
   * @param  clientConnection  The client connection over which the user is
   *                           authenticated.
   */
  public synchronized void put(DN userDN, ClientConnection clientConnection)
  {
    assert debugEnter(CLASS_NAME, "put", String.valueOf(userDN),
                      String.valueOf(clientConnection));
    CopyOnWriteArraySet<ClientConnection> connectionSet = userMap.get(userDN);
    if (connectionSet == null)
    {
      connectionSet = new CopyOnWriteArraySet<ClientConnection>();
      connectionSet.add(clientConnection);
      userMap.put(userDN, connectionSet);
    }
    else
    {
      connectionSet.add(clientConnection);
    }
  }
  /**
   * Deregisters the provided user DN and client connection with this object.
   *
   * @param  userDN            The DN of the user associated with the provided
   *                           client connection.
   * @param  clientConnection  The client connection over which the user is
   *                           authenticated.
   */
  public synchronized void remove(DN userDN, ClientConnection clientConnection)
  {
    assert debugEnter(CLASS_NAME, "put", String.valueOf(userDN),
                      String.valueOf(clientConnection));
    CopyOnWriteArraySet<ClientConnection> connectionSet = userMap.get(userDN);
    if (connectionSet != null)
    {
      connectionSet.remove(clientConnection);
      if (connectionSet.isEmpty())
      {
        userMap.remove(userDN);
      }
    }
  }
  /**
   * Performs any processing that may be required after an add
   * operation.
   *
   * @param  addOperation  The add operation that was performed in the
   *                       server.
   * @param  entry         The entry that was added to the server.
   */
  public void handleAddOperation(
                   PostResponseAddOperation addOperation,
                   Entry entry)
  {
    // No implementation is required for add operations, since a connection
    // can't be authenticated as a user that doesn't exist yet.
  }
  /**
   * Performs any processing that may be required after a delete
   * operation.
   *
   * @param  deleteOperation  The delete operation that was performed
   *                          in the server.
   * @param  entry            The entry that was removed from the
   *                          server.
   */
  public void handleDeleteOperation(
                   PostResponseDeleteOperation deleteOperation,
                   Entry entry)
  {
    // Identify any client connections that may be authenticated or
    // authorized as the user whose entry has been deleted and terminate them.
    CopyOnWriteArraySet<ClientConnection> connectionSet =
         userMap.remove(entry.getDN());
    if (connectionSet != null)
    {
      for (ClientConnection conn : connectionSet)
      {
        int    msgID   = MSGID_CLIENTCONNECTION_DISCONNECT_DUE_TO_DELETE;
        String message = getMessage(msgID, String.valueOf(entry.getDN()));
        conn.disconnect(DisconnectReason.OTHER, true, message, msgID);
      }
    }
  }
  /**
   * Performs any processing that may be required after a modify
   * operation.
   *
   * @param  modifyOperation  The modify operation that was performed
   *                          in the server.
   * @param  oldEntry         The entry before it was updated.
   * @param  newEntry         The entry after it was updated.
   */
  public void handleModifyOperation(
                   PostResponseModifyOperation modifyOperation,
                   Entry oldEntry, Entry newEntry)
  {
    // Identify any client connections that may be authenticated or authorized
    // as the user whose entry has been modified and update them with the latest
    // version of the entry.
    CopyOnWriteArraySet<ClientConnection> connectionSet =
         userMap.get(oldEntry.getDN());
    if (connectionSet != null)
    {
      for (ClientConnection conn : connectionSet)
      {
        conn.updateAuthenticationInfo(oldEntry, newEntry);
      }
    }
  }
  /**
   * Performs any processing that may be required after a modify DN
   * operation.
   *
   * @param  modifyDNOperation  The modify DN operation that was
   *                            performed in the server.
   * @param  oldEntry           The entry before it was updated.
   * @param  newEntry           The entry after it was updated.
   */
  public void handleModifyDNOperation(
                   PostResponseModifyDNOperation modifyDNOperation,
                   Entry oldEntry, Entry newEntry)
  {
    // Identify any client connections that may be authenticated or authorized
    // as the user whose entry has been modified and update them with the latest
    // version of the entry.
    CopyOnWriteArraySet<ClientConnection> connectionSet =
         userMap.remove(oldEntry.getDN());
    if (connectionSet != null)
    {
      synchronized (this)
      {
        CopyOnWriteArraySet<ClientConnection> existingNewSet =
             userMap.get(newEntry.getDN());
        if (existingNewSet == null)
        {
          userMap.put(newEntry.getDN(), connectionSet);
        }
        else
        {
          existingNewSet.addAll(connectionSet);
        }
      }
      for (ClientConnection conn : connectionSet)
      {
        conn.updateAuthenticationInfo(oldEntry, newEntry);
      }
    }
  }
}
opends/src/server/org/opends/server/core/BindOperation.java
@@ -147,6 +147,10 @@
  // The DN of the user entry that is attempting to authenticate.
  private DN userEntryDN;
  // The entry of the user that successfully authenticated during processing of
  // this bind operation.
  private Entry authenticatedUserEntry;
  // The DN of the user as whom a SASL authentication was attempted (regardless
  // of whether the authentication was successful) for the purpose of updating
  // password policy state information.
@@ -244,6 +248,7 @@
    responseControls         = new ArrayList<Control>(0);
    authFailureID            = 0;
    authFailureReason        = null;
    authenticatedUserEntry   = null;
    saslAuthUserEntry        = null;
    isFirstWarning           = false;
    isGraceLogin             = false;
@@ -304,12 +309,13 @@
      this.rawBindDN = rawBindDN;
    }
    bindDN            = null;
    userEntryDN       = null;
    responseControls  = new ArrayList<Control>(0);
    authFailureID     = 0;
    authFailureReason = null;
    saslAuthUserEntry = null;
    bindDN                 = null;
    userEntryDN            = null;
    responseControls       = new ArrayList<Control>(0);
    authFailureID          = 0;
    authFailureReason      = null;
    authenticatedUserEntry = null;
    saslAuthUserEntry      = null;
  }
@@ -369,6 +375,7 @@
    responseControls         = new ArrayList<Control>(0);
    authFailureID            = 0;
    authFailureReason        = null;
    authenticatedUserEntry   = null;
    saslAuthUserEntry        = null;
    isFirstWarning           = false;
    isGraceLogin             = false;
@@ -429,11 +436,12 @@
      rawBindDN = new ASN1OctetString(bindDN.toString());
    }
    responseControls  = new ArrayList<Control>(0);
    authFailureID     = 0;
    authFailureReason = null;
    saslAuthUserEntry = null;
    userEntryDN       = null;
    responseControls       = new ArrayList<Control>(0);
    authFailureID          = 0;
    authFailureReason      = null;
    authenticatedUserEntry = null;
    saslAuthUserEntry      = null;
    userEntryDN            = null;
  }
@@ -1481,8 +1489,8 @@
              setResultCode(ResultCode.SUCCESS);
              boolean isRoot = DirectoryServer.isRootDN(userEntry.getDN());
              authInfo = new AuthenticationInfo(userEntry.getDN(),
                                                simplePassword, isRoot);
              authInfo = new AuthenticationInfo(userEntry, simplePassword,
                                                isRoot);
              // See if the user's entry contains a custom size limit.
@@ -2220,6 +2228,7 @@
    // Update the authentication information for the user.
    if ((getResultCode() == ResultCode.SUCCESS) && (authInfo != null))
    {
      authenticatedUserEntry = authInfo.getAuthenticationEntry();
      clientConnection.setAuthenticationInfo(authInfo);
      clientConnection.setSizeLimit(sizeLimit);
      clientConnection.setTimeLimit(timeLimit);
opends/src/server/org/opends/server/core/CompareOperation.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.core;
@@ -837,10 +837,10 @@
              }
              DN authzDN;
              Entry authorizationEntry;
              try
              {
                authzDN = proxyControl.getValidatedAuthorizationDN();
                authorizationEntry = proxyControl.getAuthorizationEntry();
              }
              catch (DirectoryException de)
              {
@@ -855,7 +855,7 @@
              // FIXME -- Should we specifically check permissions here, or let
              //          the earlier access control checks handle it?
              setAuthorizationDN(authzDN);
              setAuthorizationEntry(authorizationEntry);
            }
            else if (oid.equals(OID_PROXIED_AUTH_V2))
            {
@@ -882,10 +882,10 @@
              }
              DN authzDN;
              Entry authorizationEntry;
              try
              {
                authzDN = proxyControl.getValidatedAuthorizationDN();
                authorizationEntry = proxyControl.getAuthorizationEntry();
              }
              catch (DirectoryException de)
              {
@@ -900,7 +900,7 @@
              // FIXME -- Should we specifically check permissions here, or let
              //          the earlier access control checks handle it?
              setAuthorizationDN(authzDN);
              setAuthorizationEntry(authorizationEntry);
            }
            // NYI -- Add support for additional controls.
opends/src/server/org/opends/server/core/DeleteOperation.java
@@ -816,10 +816,10 @@
              }
              DN authzDN;
              Entry authorizationEntry;
              try
              {
                authzDN = proxyControl.getValidatedAuthorizationDN();
                authorizationEntry = proxyControl.getAuthorizationEntry();
              }
              catch (DirectoryException de)
              {
@@ -834,7 +834,7 @@
              // FIXME -- Should we specifically check permissions here, or let
              //          the earlier access control checks handle it?
              setAuthorizationDN(authzDN);
              setAuthorizationEntry(authorizationEntry);
            }
            else if (oid.equals(OID_PROXIED_AUTH_V2))
            {
@@ -861,10 +861,10 @@
              }
              DN authzDN;
              Entry authorizationEntry;
              try
              {
                authzDN = proxyControl.getValidatedAuthorizationDN();
                authorizationEntry = proxyControl.getAuthorizationEntry();
              }
              catch (DirectoryException de)
              {
@@ -879,7 +879,7 @@
              // FIXME -- Should we specifically check permissions here, or let
              //          the earlier access control checks handle it?
              setAuthorizationDN(authzDN);
              setAuthorizationEntry(authorizationEntry);
            }
            // NYI -- Add support for additional controls.
opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -224,6 +224,9 @@
  // The attribute type used to reference the "objectclass" attribute.
  private AttributeType objectClassAttributeType;
  // The authenticated users manager for the server.
  private AuthenticatedUsers authenticatedUsers;
  // The configuration manager that will handle the server backends.
  private BackendConfigManager backendConfigManager;
@@ -649,6 +652,7 @@
         new ConcurrentHashMap<String,ExtendedOperationHandler>();
    directoryServer.saslMechanismHandlers =
         new ConcurrentHashMap<String,SASLMechanismHandler>();
    directoryServer.authenticatedUsers = new AuthenticatedUsers();
  }
@@ -1761,6 +1765,20 @@
  /**
   * Retrieves the authenticated users manager for the Directory Server.
   *
   * @return  The authenticated users manager for the Directory Server.
   */
  public static AuthenticatedUsers getAuthenticatedUsers()
  {
    assert debugEnter(CLASS_NAME, "getAuthenticatedUsers");
    return directoryServer.authenticatedUsers;
  }
  /**
   * Initializes the crypto manager for the Directory Server.
   *
   * @throws  ConfigException  If a configuration problem is identified while
opends/src/server/org/opends/server/core/ModifyDNOperation.java
@@ -1307,10 +1307,10 @@
              }
              DN authzDN;
              Entry authorizationEntry;
              try
              {
                authzDN = proxyControl.getValidatedAuthorizationDN();
                authorizationEntry = proxyControl.getAuthorizationEntry();
              }
              catch (DirectoryException de)
              {
@@ -1325,7 +1325,7 @@
              // FIXME -- Should we specifically check permissions here, or let
              //          the earlier access control checks handle it?
              setAuthorizationDN(authzDN);
              setAuthorizationEntry(authorizationEntry);
            }
            else if (oid.equals(OID_PROXIED_AUTH_V2))
            {
@@ -1352,10 +1352,10 @@
              }
              DN authzDN;
              Entry authorizationEntry;
              try
              {
                authzDN = proxyControl.getValidatedAuthorizationDN();
                authorizationEntry = proxyControl.getAuthorizationEntry();
              }
              catch (DirectoryException de)
              {
@@ -1370,7 +1370,7 @@
              // FIXME -- Should we specifically check permissions here, or let
              //          the earlier access control checks handle it?
              setAuthorizationDN(authzDN);
              setAuthorizationEntry(authorizationEntry);
            }
            // NYI -- Add support for additional controls.
opends/src/server/org/opends/server/core/ModifyOperation.java
@@ -1109,10 +1109,10 @@
              }
              DN authzDN;
              Entry authorizationEntry;
              try
              {
                authzDN = proxyControl.getValidatedAuthorizationDN();
                authorizationEntry = proxyControl.getAuthorizationEntry();
              }
              catch (DirectoryException de)
              {
@@ -1127,7 +1127,7 @@
              // FIXME -- Should we specifically check permissions here, or let
              //          the earlier access control checks handle it?
              setAuthorizationDN(authzDN);
              setAuthorizationEntry(authorizationEntry);
            }
            else if (oid.equals(OID_PROXIED_AUTH_V2))
            {
@@ -1154,10 +1154,10 @@
              }
              DN authzDN;
              Entry authorizationEntry;
              try
              {
                authzDN = proxyControl.getValidatedAuthorizationDN();
                authorizationEntry = proxyControl.getAuthorizationEntry();
              }
              catch (DirectoryException de)
              {
@@ -1172,7 +1172,7 @@
              // FIXME -- Should we specifically check permissions here, or let
              //          the earlier access control checks handle it?
              setAuthorizationDN(authzDN);
              setAuthorizationEntry(authorizationEntry);
            }
            // NYI -- Add support for additional controls.
opends/src/server/org/opends/server/core/Operation.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.core;
@@ -34,13 +34,13 @@
import java.util.Map;
import org.opends.server.api.ClientConnection;
import org.opends.server.types.AuthenticationInfo;
import org.opends.server.types.CancelRequest;
import org.opends.server.types.CancelResult;
import org.opends.server.types.Control;
import org.opends.server.types.DisconnectReason;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
import org.opends.server.types.OperationType;
import org.opends.server.types.ResultCode;
import org.opends.server.types.operation.PostOperationOperation;
@@ -111,12 +111,12 @@
  // The cancel result for this operation.
  private CancelResult cancelResult;
  // The authorization DN for this operation.
  private DN authorizationDN;
  // The matched DN for this operation.
  private DN matchedDN;
  // The entry for the authorization identify for this operation.
  private Entry authorizationEntry;
  // A set of attachments associated with this operation that might be used by
  // various components during its processing.
  private Map<String,Object> attachments;
@@ -180,8 +180,8 @@
    cancelResult               = null;
    isInternalOperation        = false;
    isSynchronizationOperation = false;
    authorizationDN =
         clientConnection.getAuthenticationInfo().getAuthorizationDN();
    authorizationEntry         =
         clientConnection.getAuthenticationInfo().getAuthorizationEntry();
  }
@@ -732,6 +732,48 @@
  /**
   * Retrieves the entry for the user that should be considered the
   * authorization identity for this operation.  In many cases, it will be the
   * same as the authorization entry for the underlying client connection, or
   * {@code null} if no authentication has been performed on that connection.
   * However, it may be some other value if special processing has been
   * requested (e.g., the operation included a proxied authorization control).
   * This method should not be called by pre-parse plugins because the correct
   * value may not yet have been determined.
   *
   * @return  The entry for the user that should be considered the authorization
   *          identity for this operation, or {@code null} if the authorization
   *          identity should be the unauthenticated  user.
   */
  public final Entry getAuthorizationEntry()
  {
    assert debugEnter(CLASS_NAME, "getAuthorizationEntry");
    return authorizationEntry;
  }
  /**
   * Provides the entry for the user that should be considered the authorization
   * identity for this operation.  This must not be called from within a plugin.
   *
   * @param  authorizationEntry  The entry for the user that should be
   *                             considered the authorization identity for this
   *                             operation, or {@code null} if it should be the
   *                             unauthenticated user.
   */
  public final void setAuthorizationEntry(Entry authorizationEntry)
  {
    assert debugEnter(CLASS_NAME, "setAuthorizationEntry",
                      String.valueOf(authorizationEntry));
    this.authorizationEntry = authorizationEntry;
  }
  /**
   * Retrieves the authorization DN for this operation.  In many cases, it will
   * be the same as the DN of the authenticated user for the underlying
   * connection, or the null DN if no authentication has been performed on that
@@ -740,51 +782,26 @@
   * control).  This method should not be called by pre-parse plugins because
   * the correct value may not have yet been determined.
   *
   * @return  The authorization DN for this operation.
   * @return  The authorization DN for this operation, or the null DN if it
   *          should be the unauthenticated user..
   */
  public final DN getAuthorizationDN()
  {
    assert debugEnter(CLASS_NAME, "getAuthorizationDN");
    if (authorizationDN == null)
    if (authorizationEntry == null)
    {
      AuthenticationInfo authInfo = clientConnection.getAuthenticationInfo();
      if (authInfo == null)
      {
        return DN.nullDN();
      }
      else
      {
        return authInfo.getAuthorizationDN();
      }
      return DN.nullDN();
    }
    else
    {
      return authorizationDN;
      return authorizationEntry.getDN();
    }
  }
  /**
   * Specifies the authorization DN for this operation.  This method may not be
   * called from within a plugin.
   *
   * @param  authorizationDN  The authorization DN for this operation, or
   *                          <CODE>null</CODE> if it should use the DN of the
   *                          authenticated user.
   */
  public final void setAuthorizationDN(DN authorizationDN)
  {
    assert debugEnter(CLASS_NAME, "setAuthorizationDN",
                      String.valueOf(authorizationDN));
    this.authorizationDN = authorizationDN;
  }
  /**
   * Retrieves the set of attachments defined for this operation, as a mapping
   * between the attachment name and the associated object.
   *
opends/src/server/org/opends/server/core/SearchOperation.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.core;
@@ -1783,25 +1783,25 @@
            }
            DN authzDN;
            try
            {
              authzDN = proxyControl.getValidatedAuthorizationDN();
            }
            catch (DirectoryException de)
            {
              assert debugException(CLASS_NAME, "run", de);
              Entry authorizationEntry;
              try
              {
                authorizationEntry = proxyControl.getAuthorizationEntry();
              }
              catch (DirectoryException de)
              {
                assert debugException(CLASS_NAME, "run", de);
              setResultCode(de.getResultCode());
              appendErrorMessage(de.getErrorMessage());
                setResultCode(de.getResultCode());
                appendErrorMessage(de.getErrorMessage());
              break searchProcessing;
            }
                break searchProcessing;
              }
            // FIXME -- Should we specifically check permissions here, or let
            //          the earlier access control checks handle it?
            setAuthorizationDN(authzDN);
              // FIXME -- Should we specifically check permissions here, or let
              //          the earlier access control checks handle it?
              setAuthorizationEntry(authorizationEntry);
          }
          else if (oid.equals(OID_PROXIED_AUTH_V2))
          {
@@ -1828,25 +1828,25 @@
            }
            DN authzDN;
            try
            {
              authzDN = proxyControl.getValidatedAuthorizationDN();
            }
            catch (DirectoryException de)
            {
              assert debugException(CLASS_NAME, "run", de);
              Entry authorizationEntry;
              try
              {
                authorizationEntry = proxyControl.getAuthorizationEntry();
              }
              catch (DirectoryException de)
              {
                assert debugException(CLASS_NAME, "run", de);
              setResultCode(de.getResultCode());
              appendErrorMessage(de.getErrorMessage());
                setResultCode(de.getResultCode());
                appendErrorMessage(de.getErrorMessage());
              break searchProcessing;
            }
                break searchProcessing;
              }
            // FIXME -- Should we specifically check permissions here, or let
            //          the earlier access control checks handle it?
            setAuthorizationDN(authzDN);
              // FIXME -- Should we specifically check permissions here, or let
              //          the earlier access control checks handle it?
              setAuthorizationEntry(authorizationEntry);
          }
          else if (oid.equals(OID_PERSISTENT_SEARCH))
          {
opends/src/server/org/opends/server/extensions/CRAMMD5SASLMechanismHandler.java
@@ -547,7 +547,7 @@
    bindOperation.setResultCode(ResultCode.SUCCESS);
    AuthenticationInfo authInfo =
         new AuthenticationInfo(userEntry.getDN(), SASL_MECHANISM_CRAM_MD5,
         new AuthenticationInfo(userEntry, SASL_MECHANISM_CRAM_MD5,
                                DirectoryServer.isRootDN(userEntry.getDN()));
    bindOperation.setAuthenticationInfo(authInfo);
    return;
opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java
@@ -1011,7 +1011,7 @@
    AuthenticationInfo authInfo =
         new AuthenticationInfo(userEntry.getDN(), SASL_MECHANISM_DIGEST_MD5,
         new AuthenticationInfo(userEntry, SASL_MECHANISM_DIGEST_MD5,
                                DirectoryServer.isRootDN(userEntry.getDN()));
    bindOperation.setAuthenticationInfo(authInfo);
    return;
opends/src/server/org/opends/server/extensions/ExternalSASLMechanismHandler.java
@@ -455,7 +455,7 @@
    AuthenticationInfo authInfo =
         new AuthenticationInfo(userEntry.getDN(), SASL_MECHANISM_EXTERNAL,
         new AuthenticationInfo(userEntry, SASL_MECHANISM_EXTERNAL,
                                DirectoryServer.isRootDN(userEntry.getDN()));
    bindOperation.setAuthenticationInfo(authInfo);
    bindOperation.setResultCode(ResultCode.SUCCESS);
opends/src/server/org/opends/server/extensions/GSSAPISASLMechanismHandler.java
@@ -419,10 +419,10 @@
    {
      // The authentication was successful, so set the proper state information
      // in the client connection and return success.
      DN userDN = stateInfo.getUserEntry().getDN();
      Entry userEntry = stateInfo.getUserEntry();
      AuthenticationInfo authInfo =
           new AuthenticationInfo(userDN, SASL_MECHANISM_GSSAPI,
                                  DirectoryServer.isRootDN(userDN));
           new AuthenticationInfo(userEntry, SASL_MECHANISM_GSSAPI,
                                  DirectoryServer.isRootDN(userEntry.getDN()));
      bindOperation.setAuthenticationInfo(authInfo);
      bindOperation.setResultCode(ResultCode.SUCCESS);
opends/src/server/org/opends/server/extensions/GSSAPIStateInfo.java
@@ -430,7 +430,7 @@
    // The authentication was successful, so set the proper state information
    // in the client connection and return success.
    AuthenticationInfo authInfo =
         new AuthenticationInfo(userEntry.getDN(), SASL_MECHANISM_GSSAPI,
         new AuthenticationInfo(userEntry, SASL_MECHANISM_GSSAPI,
                                DirectoryServer.isRootDN(userEntry.getDN()));
    bindOperation.setAuthenticationInfo(authInfo);
    bindOperation.setResultCode(ResultCode.SUCCESS);
opends/src/server/org/opends/server/extensions/PasswordModifyExtendedOperation.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.extensions;
@@ -310,8 +310,8 @@
    }
    // Get the DN of the user that issued the request.
    DN requestorDN = operation.getAuthorizationDN();
    // Get the entry for the user that issued the request.
    Entry requestorEntry = operation.getAuthorizationEntry();
    // See if a user identity was provided.  If so, then try to resolve it to
@@ -329,8 +329,7 @@
        // authenticated.
        ClientConnection   clientConnection = operation.getClientConnection();
        AuthenticationInfo authInfo = clientConnection.getAuthenticationInfo();
        if ((! authInfo.isAuthenticated()) || (requestorDN == null) ||
            (requestorDN.isNullDN()))
        if ((! authInfo.isAuthenticated()) || (requestorEntry == null))
        {
          operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
@@ -342,7 +341,7 @@
        // Retrieve a write lock on that user's entry.
        userDN = requestorDN;
        userDN = requestorEntry.getDN();
        for (int i=0; i < 3; i++)
        {
@@ -366,11 +365,7 @@
        }
        userEntry = getEntryByDN(operation, userDN);
        if (userEntry == null)
        {
          return;
        }
        userEntry = requestorEntry;
      }
      else
      {
@@ -500,8 +495,9 @@
      // Determine whether the user is changing his own password or if it's an
      // administrative reset.
      boolean selfChange = ((userIdentity == null) || (requestorDN == null) ||
                            userDN.equals(requestorDN));
      boolean selfChange = ((userIdentity == null) ||
                            (requestorEntry == null) ||
                            userDN.equals(requestorEntry.getDN()));
      // See if the account is locked.  If so, then reject the request.
@@ -1085,9 +1081,14 @@
      }
      else
      {
        if (selfChange && (requestorEntry == null))
        {
          requestorEntry = userEntry;
        }
        // Get an internal connection and use it to perform the modification.
        boolean isRoot = DirectoryServer.isRootDN(requestorDN);
        AuthenticationInfo authInfo = new AuthenticationInfo(requestorDN,
        boolean isRoot = DirectoryServer.isRootDN(requestorEntry.getDN());
        AuthenticationInfo authInfo = new AuthenticationInfo(requestorEntry,
                                                             isRoot);
        InternalClientConnection internalConnection = new
             InternalClientConnection(authInfo);
opends/src/server/org/opends/server/extensions/PlainSASLMechanismHandler.java
@@ -435,7 +435,7 @@
    bindOperation.setResultCode(ResultCode.SUCCESS);
    AuthenticationInfo authInfo =
         new AuthenticationInfo(userEntry.getDN(), SASL_MECHANISM_PLAIN,
         new AuthenticationInfo(userEntry, SASL_MECHANISM_PLAIN,
                                DirectoryServer.isRootDN(userEntry.getDN()));
    bindOperation.setAuthenticationInfo(authInfo);
    return;
opends/src/server/org/opends/server/messages/CoreMessages.java
@@ -6150,6 +6150,17 @@
  /**
   * The message ID for the message that will be used if a client connection is
   * terminated because the associated authentication or authorization entry was
   * removed from the server.  It takes a single argument, which is the DN of
   * the entry that has been removed.
   */
  public static final int MSGID_CLIENTCONNECTION_DISCONNECT_DUE_TO_DELETE =
       CATEGORY_MASK_CORE | SEVERITY_MASK_MILD_WARNING | 588;
  /**
   * Associates a set of generic messages with the message IDs defined
   * in this class.
   */
@@ -8321,6 +8332,11 @@
                     "Rejecting the requested operation  " +
                     "because the connection has not been authenticated.");
    registerMessage(MSGID_CLIENTCONNECTION_DISCONNECT_DUE_TO_DELETE,
                    "Terminating the client connection because its " +
                    "associated authentication or authorization entry %s has " +
                    "been deleted.");
  }
}
opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
@@ -32,6 +32,7 @@
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
@@ -46,6 +47,7 @@
import org.opends.server.core.BindOperation;
import org.opends.server.core.CompareOperation;
import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ExtendedOperation;
import org.opends.server.core.ModifyOperation;
import org.opends.server.core.ModifyDNOperation;
@@ -70,6 +72,7 @@
import org.opends.server.types.ErrorLogSeverity;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.IntermediateResponse;
import org.opends.server.types.Modification;
import org.opends.server.types.ObjectClass;
@@ -79,10 +82,12 @@
import org.opends.server.types.SearchResultReference;
import org.opends.server.types.SearchScope;
import static org.opends.server.config.ConfigConstants.*;
import static org.opends.server.loggers.Debug.*;
import static org.opends.server.loggers.Error.*;
import static org.opends.server.messages.MessageHandler.*;
import static org.opends.server.messages.ProtocolMessages.*;
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
@@ -152,13 +157,60 @@
    // This connection will be authenticated as a root user so that no
    // access control will be enforced.
    String dnString = "cn=Internal Client";
    String commonName    = "Internal Client";
    String shortDNString = "cn=" + commonName;
    String fullDNString  = shortDNString + ",cn=Root DNs,cn=config";
    try
    {
      DN internalUserDN = DN.decode(dnString);
      LinkedHashMap<ObjectClass,String> objectClasses =
           new LinkedHashMap<ObjectClass,String>();
      ObjectClass topOC = DirectoryServer.getTopObjectClass();
      ObjectClass personOC = DirectoryServer.getObjectClass(OC_PERSON,
                                                            true);
      ObjectClass rootOC = DirectoryServer.getObjectClass(OC_ROOT_DN,
                                                          true);
      objectClasses.put(topOC, topOC.getPrimaryName());
      objectClasses.put(personOC, personOC.getPrimaryName());
      objectClasses.put(rootOC, rootOC.getPrimaryName());
      LinkedHashMap<AttributeType,List<Attribute>> userAttrs =
           new LinkedHashMap<AttributeType,List<Attribute>>();
      AttributeType cnAT =
           DirectoryServer.getAttributeType(ATTR_COMMON_NAME, true);
      AttributeType snAT = DirectoryServer.getAttributeType(ATTR_SN,
                                                            true);
      AttributeType altDNAT =
           DirectoryServer.getAttributeType(
                ATTR_ROOTDN_ALTERNATE_BIND_DN, true);
      LinkedList<Attribute> attrList = new LinkedList<Attribute>();
      attrList.add(new Attribute(ATTR_COMMON_NAME, commonName));
      userAttrs.put(cnAT, attrList);
      attrList = new LinkedList<Attribute>();
      attrList.add(new Attribute(ATTR_SN, commonName));
      userAttrs.put(snAT, attrList);
      attrList = new LinkedList<Attribute>();
      attrList.add(new Attribute(ATTR_ROOTDN_ALTERNATE_BIND_DN,
                                 shortDNString));
      userAttrs.put(altDNAT, attrList);
      LinkedHashMap<AttributeType,List<Attribute>> operationalAttrs =
           new LinkedHashMap<AttributeType,List<Attribute>>();
      // FIXME -- Add privileges here.
      DN internalUserDN = DN.decode(fullDNString);
      Entry internalUserEntry =
                 new Entry(internalUserDN, objectClasses, userAttrs,
                           operationalAttrs);
      this.authenticationInfo =
           new AuthenticationInfo(internalUserDN, true);
           new AuthenticationInfo(internalUserEntry, true);
    }
    catch (DirectoryException de)
    {
@@ -166,7 +218,7 @@
      logError(ErrorLogCategory.CONNECTION_HANDLING,
               ErrorLogSeverity.SEVERE_ERROR,
               MSGID_INTERNAL_CANNOT_DECODE_DN, dnString,
               MSGID_INTERNAL_CANNOT_DECODE_DN, fullDNString,
               stackTraceToSingleLineString(de));
    }
@@ -1535,7 +1587,10 @@
                      String.valueOf(messageID));
    // No implementation is required since there is nothing to
    // disconnect.
    // disconnect.  Further, since there is no real disconnect, we can
    // wait to have the garbage collector call
    // finalizeConnectionInternal whenever this internal connection is
    // garbage collected.
  }
@@ -1735,7 +1790,12 @@
    buffer.append("InternalClientConnection(connID=");
    buffer.append(connectionID);
    buffer.append(", authDN=\"");
    buffer.append(getAuthenticationInfo().getAuthenticationDN());
    if (getAuthenticationInfo() != null)
    {
      buffer.append(getAuthenticationInfo().getAuthenticationDN());
    }
    buffer.append("\")");
  }
}
opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.protocols.jmx;
@@ -895,6 +895,7 @@
      return;
    }
    disconnectStarted = true ;
    finalizeConnectionInternal();
@@ -1144,6 +1145,7 @@
   */
  protected void finalize()
  {
    super.finalize();
    disconnect(DisconnectReason.OTHER, false, null, -1);
  }
}
opends/src/server/org/opends/server/protocols/jmx/RmiAuthenticator.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.protocols.jmx;
@@ -265,7 +265,7 @@
      bindPW = new ASN1OctetString(password);
    }
    AuthenticationInfo authInfo = new AuthenticationInfo(bindDN, bindPW, false);
    AuthenticationInfo authInfo = new AuthenticationInfo();
    JmxClientConnection jmxClientConnection = new JmxClientConnection(
        jmxConnectionHandler, authInfo);
@@ -284,6 +284,8 @@
          "bind",
          "User is authenticated");
      authInfo = bindOp.getAuthenticationInfo();
      jmxClientConnection.setAuthenticationInfo(authInfo);
      return jmxClientConnection;
    }
    else
opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.protocols.ldap;
@@ -1032,6 +1032,7 @@
    }
    cancelAllOperations(new CancelRequest(true, message));
    finalizeConnectionInternal();
    // See if we should send a notification to the client.  If so, then
opends/src/server/org/opends/server/types/AuthenticationInfo.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.types;
@@ -34,6 +34,7 @@
import java.util.Set;
import static org.opends.server.loggers.Debug.*;
import static org.opends.server.util.Validator.*;
@@ -68,11 +69,12 @@
  // other operation will be allowed.
  private boolean mustChangePassword;
  // The DN of the user that is currently authenticated.
  private DN authenticationDN;
  // The entry of the user that is currently authenticated.
  private Entry authenticationEntry;
  // The authorization DN for this authentication info structure.
  private DN authorizationDN;
  // The entry of the user that will be used as the default
  // authorization identity.
  private Entry authorizationEntry;
  // The type of authentication performed on this connection.
  private Set<AuthenticationType> authenticationTypes;
@@ -95,8 +97,8 @@
    mustChangePassword  = false;
    simplePassword      = null;
    authenticationTypes = new HashSet<AuthenticationType>(0);
    authenticationDN    = null;
    authorizationDN     = null;
    authenticationEntry = null;
    authorizationEntry  = null;
    saslMechanisms      = new HashSet<String>(0);
  }
@@ -106,24 +108,25 @@
   * Creates a new set of authentication information to be used for
   * clients that are authenticated internally.
   *
   * @param  authenticationDN  The DN of the user that has
   *                           authenticated.
   * @param  isRoot            Indicates whether the authenticated
   *                           user is a root user.
   * @param  authenticationEntry  The entry of the user that has
   *                              authenticated, or {@code null} to
   *                              indicate an unauthenticated user.
   * @param  isRoot               Indicates whether the authenticated
   *                              user is a root user.
   */
  public AuthenticationInfo(DN authenticationDN, boolean isRoot)
  public AuthenticationInfo(Entry authenticationEntry, boolean isRoot)
  {
    assert debugConstructor(CLASS_NAME,
                            String.valueOf(authenticationDN),
                            String.valueOf(authenticationEntry),
                            String.valueOf(isRoot));
    this.authenticationDN = authenticationDN;
    this.isRoot           = isRoot;
    this.authenticationEntry = authenticationEntry;
    this.isRoot              = isRoot;
    isAuthenticated     = true;
    isAuthenticated     = (authenticationEntry != null);
    mustChangePassword  = false;
    simplePassword      = null;
    authorizationDN     = authenticationDN;
    authorizationEntry  = authenticationEntry;
    saslMechanisms      = new HashSet<String>(0);
    authenticationTypes = new HashSet<AuthenticationType>(1);
@@ -136,28 +139,32 @@
   * Creates a new set of authentication information to be used for
   * clients that have successfully performed simple authentication.
   *
   * @param  authenticationDN  The DN of the user that has
   *                           authenticated.
   * @param  simplePassword    The password that was used to perform
   *                           the simple authentication.
   * @param  isRoot            Indicates whether the authenticated
   *                           user is a root user.
   * @param  authenticationEntry  The entry of the user that has
   *                              authenticated.  It must not be
   *                              {@code null}.
   * @param  simplePassword       The password that was used to
   *                              perform the simple authentication.
   *                              It must not be {@code null}.
   * @param  isRoot               Indicates whether the authenticated
   *                              user is a root user.
   */
  public AuthenticationInfo(DN authenticationDN,
  public AuthenticationInfo(Entry authenticationEntry,
                            ByteString simplePassword, boolean isRoot)
  {
    assert debugConstructor(CLASS_NAME,
                            String.valueOf(authenticationDN),
                            String.valueOf(authenticationEntry),
                            String.valueOf(simplePassword),
                            String.valueOf(isRoot));
    this.authenticationDN = authenticationDN;
    this.simplePassword   = simplePassword;
    this.isRoot           = isRoot;
    ensureNotNull(authenticationEntry, simplePassword);
    this.authenticationEntry = authenticationEntry;
    this.simplePassword      = simplePassword;
    this.isRoot              = isRoot;
    isAuthenticated     = true;
    mustChangePassword  = false;
    authorizationDN     = authenticationDN;
    authorizationEntry  = authenticationEntry;
    saslMechanisms      = new HashSet<String>(0);
    authenticationTypes = new HashSet<AuthenticationType>(1);
@@ -170,28 +177,32 @@
   * Creates a new set of authentication information to be used for
   * clients that have authenticated using a SASL mechanism.
   *
   * @param  authenticationDN  The DN of the user that has
   *                           authenticated.
   * @param  saslMechanism     The SASL mechanism used to
   *                           authenticate.  Note that this must be
   *                           provided in all-uppercase characters.
   * @param  isRoot            Indicates whether the authenticated
   *                           user is a root user.
   * @param  authenticationEntry  The entry of the user that has
   *                              authenticated.  It must not be
   *                              {@code null}.
   * @param  saslMechanism        The SASL mechanism used to
   *                              authenticate.  This must be provided
   *                              in all-uppercase characters and must
   *                              not be {@code null}.
   * @param  isRoot               Indicates whether the authenticated
   *                              user is a root user.
   */
  public AuthenticationInfo(DN authenticationDN, String saslMechanism,
                            boolean isRoot)
  public AuthenticationInfo(Entry authenticationEntry,
                            String saslMechanism, boolean isRoot)
  {
    assert debugConstructor(CLASS_NAME,
                            String.valueOf(authenticationDN),
                            String.valueOf(authenticationEntry),
                            String.valueOf(saslMechanism),
                            String.valueOf(isRoot));
    this.authenticationDN = authenticationDN;
    this.isRoot           = isRoot;
    ensureNotNull(authenticationEntry, saslMechanism);
    this.authenticationEntry = authenticationEntry;
    this.isRoot              = isRoot;
    isAuthenticated    = true;
    mustChangePassword = false;
    authorizationDN    = authenticationDN;
    authorizationEntry = authenticationEntry;
    simplePassword     = null;
    authenticationTypes = new HashSet<AuthenticationType>(1);
@@ -207,35 +218,43 @@
   * Creates a new set of authentication information to be used for
   * clients that have authenticated using a SASL mechanism.
   *
   * @param  authenticationDN  The DN of the user that has
   *                           authenticated.
   * @param  authorizationDN   The authorization DN for the
   *                           authenticated user.
   * @param  saslMechanism     The SASL mechanism used to
   *                           authenticate.  Note that this must be
   *                           provided in all-uppercase characters.
   * @param  isRoot            Indicates whether the authenticated
   *                           user is a root user.
   * @param  authenticationEntry  The entry of the user that has
   *                              authenticated.  It must not be
   *                              {@code null}.
   * @param  authorizationEntry   The entry of the user that will be
   *                              used as the default authorization
   *                              identity, or {@code null} to
   *                              indicate that it should be the same
   *                              as the authentication entry.
   * @param  saslMechanism        The SASL mechanism used to
   *                              authenticate.  This must be provided
   *                              in all-uppercase characters and must
   *                              not be {@code null}.
   * @param  isRoot               Indicates whether the authenticated
   *                              user is a root user.
   */
  public AuthenticationInfo(DN authenticationDN, DN authorizationDN,
  public AuthenticationInfo(Entry authenticationEntry,
                            Entry authorizationEntry,
                            String saslMechanism, boolean isRoot)
  {
    assert debugConstructor(CLASS_NAME,
                            String.valueOf(authenticationDN),
                            String.valueOf(authorizationDN),
                            String.valueOf(authenticationEntry),
                            String.valueOf(authorizationEntry),
                            String.valueOf(saslMechanism),
                            String.valueOf(isRoot));
    this.authenticationDN = authenticationDN;
    this.isRoot           = isRoot;
    ensureNotNull(authenticationEntry, saslMechanism);
    if (authorizationDN == null)
    this.authenticationEntry = authenticationEntry;
    this.isRoot              = isRoot;
    if (authorizationEntry == null)
    {
      this.authorizationDN = authenticationDN;
      this.authorizationEntry = authenticationEntry;
    }
    else
    {
      this.authorizationDN = authorizationDN;
      this.authorizationEntry = authorizationEntry;
    }
    isAuthenticated    = true;
@@ -255,9 +274,8 @@
   * Indicates whether this client has successfully authenticated to
   * the server.
   *
   * @return  <CODE>true</CODE> if this client has successfully
   *          authenticated to the server, or <CODE>false</CODE> if
   *          not.
   * @return  {@code true} if this client has successfully
   *          authenticated to the server, or {@code false} if not.
   */
  public boolean isAuthenticated()
  {
@@ -280,8 +298,8 @@
    isRoot              = false;
    mustChangePassword  = false;
    simplePassword      = null;
    authenticationDN    = null;
    authorizationDN     = null;
    authenticationEntry = null;
    authorizationEntry  = null;
    authenticationTypes.clear();
    saslMechanisms.clear();
@@ -292,8 +310,8 @@
  /**
   * Indicates whether this client should be considered a root user.
   *
   * @return  <CODE>true</CODE> if this client should be considered a
   *          root user, or <CODE>false</CODE> if not.
   * @return  {@code true} if this client should be considered a root
   *          user, or {@code false} if not.
   */
  public boolean isRoot()
  {
@@ -305,12 +323,12 @@
  /**
   * Indicates whether the associated user must change their password
   * before any other operation will be allowed.
   * Indicates whether the authenticated user must change his/her
   * password before any other operation will be allowed.
   *
   * @return  <CODE>true</CODE> if the user must change their password
   * @return  {@code true} if the user must change his/her password
   *          before any other operation will be allowed, or
   *          <CODE>false</CODE> if not.
   *          {@code false} if not.
   */
  public boolean mustChangePassword()
  {
@@ -322,12 +340,13 @@
  /**
   * Specifies whether the associated user must change their password
   * before any other operation will be allowed.
   * Specifies whether the authenticated user must change his/her
   * password before any other operation will be allowed.
   *
   * @param  mustChangePassword  Specifies whether the associated user
   *                             must change their password before any
   *                             other operation will be allowed.
   * @param  mustChangePassword  Specifies whether the authenticated
   *                             user must change his/her password
   *                             before any other operation will be
   *                             allowed.
   */
  public void setMustChangePassword(boolean mustChangePassword)
  {
@@ -346,9 +365,8 @@
   * @param  authenticationType  The authentication type for which to
   *                             make the determination.
   *
   * @return  <CODE>true</CODE> if the client has authenticated using
   *          the specified authentication type, or <CODE>false</CODE>
   *          if not.
   * @return  {@code true} if the client has authenticated using the
   *          specified authentication type, or {@code false} if not.
   */
  public boolean hasAuthenticationType(AuthenticationType
                                            authenticationType)
@@ -368,9 +386,9 @@
   * @param  types  The collection of authentication types for which
   *                to make the determination.
   *
   * @return  <CODE>true</CODE> if the client has authenticated using
   *          any of the specified authentication types, or
   *          <CODE>false</CODE> if not.
   * @return  {@code true} if the client has authenticated using any
   *          of the specified authentication types, or {@code false}
   *          if not.
   */
  public boolean hasAnyAuthenticationType(
                      Collection<AuthenticationType> types)
@@ -426,30 +444,83 @@
  /**
   * Retrieves the DN of the user as whom the client is authenticated.
   * Retrieves the entry for the user as whom the client is
   * authenticated.
   *
   * @return  The DN of the user as whom the client is authenticated,
   *          or <CODE>null</CODE> if the client is unauthenticated.
   * @return  The entry for the user as whom the client is
   *          authenticated, or {@code null} if the client is
   *          unauthenticated.
   */
  public DN getAuthenticationDN()
  public Entry getAuthenticationEntry()
  {
    assert debugEnter(CLASS_NAME, "getAuthenticationDN");
    assert debugEnter(CLASS_NAME, "getAuthenticationEntry");
    return authenticationDN;
    return authenticationEntry;
  }
  /**
   * Retrieves the authorization DN for this client.
   * Retrieves the DN of the user as whom the client is authenticated.
   *
   * @return  The authorization DN for this client.
   * @return  The DN of the user as whom the client is authenticated,
   *          or {@code null} if the client is unauthenticated.
   */
  public DN getAuthenticationDN()
  {
    assert debugEnter(CLASS_NAME, "getAuthenticationDN");
    if (authenticationEntry == null)
    {
      return null;
    }
    else
    {
      return authenticationEntry.getDN();
    }
  }
  /**
   * Retrieves the entry for the user that should be used as the
   * default authorization identity.
   *
   * @return  The entry for the user that should be used as the
   *          default authorization identity, or {@code null} if the
   *          authorization identity should be the unauthenticated
   *          user.
   */
  public Entry getAuthorizationEntry()
  {
    assert debugEnter(CLASS_NAME, "getAuthorizationEntry");
    return authorizationEntry;
  }
  /**
   * Retrieves the DN for the user that should be used as the default
   * authorization identity.
   *
   * @return  The DN for the user that should be used as the default
   *          authorization identity, or {@code null} if the
   *          authorization identity should be the unauthenticated
   *          user.
   */
  public DN getAuthorizationDN()
  {
    assert debugEnter(CLASS_NAME, "getAuthorizationDN");
    return authorizationDN;
    if (authorizationEntry == null)
    {
      return null;
    }
    else
    {
      return authorizationEntry.getDN();
    }
  }
@@ -459,8 +530,8 @@
   * authentication.
   *
   * @return  The password that the client used for simple
   *          authentication, or <CODE>null</CODE> if the client is
   *          not authenticated using simple authentication.
   *          authentication, or {@code null} if the client is not
   *          authenticated using simple authentication.
   */
  public ByteString getSimplePassword()
  {
@@ -479,9 +550,8 @@
   *                        determination.  Note that this must be
   *                        provided in all uppercase characters.
   *
   * @return  <CODE>true</CODE> if the client is authenticated using
   *          the specified SASL mechanism, or <CODE>false</CODE> if
   *          not.
   * @return  {@code true} if the client is authenticated using the
   *          specified SASL mechanism, or {@code false} if not.
   */
  public boolean hasSASLMechanism(String saslMechanism)
  {
@@ -500,9 +570,9 @@
   * @param  mechanisms  The collection of SASL mechanisms for which
   *                     to make the determination.
   *
   * @return  <CODE>true</CODE> if the client has authenticated using
   *          any of the provided SASL mechanisms, or
   *          <CODE>false</CODE> if not.
   * @return  {@code true} if the client has authenticated using any
   *          of the provided SASL mechanisms, or {@code false} if
   *          not.
   */
  public boolean hasAnySASLMechanism(Collection<String> mechanisms)
  {
@@ -560,39 +630,6 @@
  /**
   * Indicates whether the user associated with this authentication
   * info is a member of the group with the specified DN.
   *
   * @param  groupDN  The DN of the group for which to make the
   *                  determination.
   *
   * @return  <CODE>true</CODE> if the authenticated user is a member
   *          of the specified group, or <CODE>false</CODE> if not.
   */
  public boolean isMemberOf(DN groupDN)
  {
    // NYI
    return false;
  }
  /**
   * Retrieves the DNs of the groups in which the user associated with
   * this authentication info is a member.
   *
   * @return  The DNs of the groups in which the user associated with
   *          this authentication info is a member.
   */
  public Collection<DN> getMembershipDNs()
  {
    // NYI
    return null;
  }
  /**
   * Retrieves a string representation of this authentication info
   * structure.
   *
@@ -630,16 +667,22 @@
    buffer.append(",mustChangePassword=");
    buffer.append(mustChangePassword);
    buffer.append(",authenticationDN=\"");
    buffer.append(authenticationDN);
    if ((authorizationDN == null) ||
        authorizationDN.equals(authenticationDN))
    if (authenticationEntry != null)
    {
      buffer.append("\",authorizationDN=\"");
      buffer.append(authorizationDN);
      authenticationEntry.getDN().toString(buffer);
    }
    buffer.append("\"");
    if (authorizationEntry == null)
    {
      buffer.append("\",authorizationDN=\"\"");
    }
    else
    {
      buffer.append("\",authorizationDN=\"");
      authorizationEntry.getDN().toString(buffer);
      buffer.append("\"");
    }
    if (! authenticationTypes.isEmpty())
    {
@@ -694,5 +737,44 @@
    buffer.append(")");
  }
  /**
   * Creates a duplicate of this {@code AuthenticationInfo} object
   * with the new authentication and authorization entries.
   *
   * @param  newAuthenticationEntry  The updated entry for the user
   *                                 as whom the associated client
   *                                 connection is authenticated.
   * @param  newAuthorizationEntry   The updated entry for the default
   *                                 authorization identity for the
   *                                 associated client connection.
   *
   * @return  The duplicate of this {@code AuthenticationInfo} object
   *          with the specified authentication and authorization
   *          entries.
   */
  public AuthenticationInfo duplicate(Entry newAuthenticationEntry,
                                      Entry newAuthorizationEntry)
  {
    assert debugEnter(CLASS_NAME, "duplicate",
                      String.valueOf(newAuthenticationEntry),
                      String.valueOf(newAuthorizationEntry));
    AuthenticationInfo authInfo = new AuthenticationInfo();
    authInfo.simplePassword      = simplePassword;
    authInfo.isAuthenticated     = isAuthenticated;
    authInfo.isRoot              = isRoot;
    authInfo.mustChangePassword  = mustChangePassword;
    authInfo.authenticationEntry = newAuthenticationEntry;
    authInfo.authorizationEntry  = newAuthorizationEntry;
    authInfo.authenticationTypes.addAll(authenticationTypes);
    authInfo.saslMechanisms.addAll(saslMechanisms);
    return authInfo;
  }
}
opends/src/server/org/opends/server/util/ServerConstants.java
@@ -338,6 +338,14 @@
  /**
   * The name of the standard attribute that is used to hold surnames, formatted
   * in all lowercase.
   */
  public static final String ATTR_SN = "sn";
  /**
   * The name of the standard attribute that is used to specify the location
   * for the Directory Server schema, formatted in camel case.
   */
@@ -719,6 +727,13 @@
  /**
   * The name of the person objectclass, formatted in all lowercase characters.
   */
  public static final String OC_PERSON = "person";
  /**
   * The name of the standard objectclass that is used to indicate that an entry
   * is a smart referral, formatted in all lowercase.
   */
opends/tests/unit-tests-testng/src/server/org/opends/server/controls/ProxiedAuthV1ControlTestCase.java
@@ -419,7 +419,7 @@
    ProxiedAuthV1Control proxyControl =
         new ProxiedAuthV1Control(DN.nullDN());
    assertTrue(proxyControl.getValidatedAuthorizationDN().isNullDN());
    assertNull(proxyControl.getAuthorizationEntry());
  }
@@ -450,7 +450,7 @@
    ProxiedAuthV1Control proxyControl =
         new ProxiedAuthV1Control(DN.decode("uid=test,o=test"));
    assertEquals(proxyControl.getValidatedAuthorizationDN(),
    assertEquals(proxyControl.getAuthorizationEntry().getDN(),
                 DN.decode("uid=test,o=test"));
  }
@@ -471,7 +471,7 @@
    ProxiedAuthV1Control proxyControl =
         new ProxiedAuthV1Control(DN.decode("uid=test,o=test"));
    proxyControl.getValidatedAuthorizationDN();
    proxyControl.getAuthorizationEntry();
  }
@@ -501,7 +501,7 @@
    ProxiedAuthV1Control proxyControl =
         new ProxiedAuthV1Control(DN.decode("uid=test,o=test"));
    proxyControl.getValidatedAuthorizationDN();
    proxyControl.getAuthorizationEntry();
  }
opends/tests/unit-tests-testng/src/server/org/opends/server/controls/ProxiedAuthV2ControlTestCase.java
@@ -309,7 +309,7 @@
  {
    ProxiedAuthV2Control proxyControl =
         new ProxiedAuthV2Control(new ASN1OctetString(""));
    assertEquals(proxyControl.getValidatedAuthorizationDN(), DN.nullDN());
    assertNull(proxyControl.getAuthorizationEntry());
  }
@@ -326,7 +326,7 @@
  {
    ProxiedAuthV2Control proxyControl =
         new ProxiedAuthV2Control(new ASN1OctetString("dn:"));
    assertEquals(proxyControl.getValidatedAuthorizationDN(), DN.nullDN());
    assertNull(proxyControl.getAuthorizationEntry());
  }
@@ -355,7 +355,7 @@
    ProxiedAuthV2Control proxyControl =
         new ProxiedAuthV2Control(new ASN1OctetString("dn:uid=test,o=test"));
    assertEquals(proxyControl.getValidatedAuthorizationDN(),
    assertEquals(proxyControl.getAuthorizationEntry().getDN(),
                 DN.decode("uid=test,o=test"));
  }
@@ -375,7 +375,7 @@
    ProxiedAuthV2Control proxyControl =
         new ProxiedAuthV2Control(new ASN1OctetString("dn:uid=test,o=test"));
    proxyControl.getValidatedAuthorizationDN();
    proxyControl.getAuthorizationEntry();
  }
@@ -406,7 +406,7 @@
    ProxiedAuthV2Control proxyControl =
         new ProxiedAuthV2Control(new ASN1OctetString("dn:uid=test,o=test"));
    proxyControl.getValidatedAuthorizationDN();
    proxyControl.getAuthorizationEntry();
  }
@@ -423,7 +423,7 @@
  {
    ProxiedAuthV2Control proxyControl =
         new ProxiedAuthV2Control(new ASN1OctetString("u:"));
    assertEquals(proxyControl.getValidatedAuthorizationDN(), DN.nullDN());
    assertNull(proxyControl.getAuthorizationEntry());
  }
@@ -452,7 +452,7 @@
    ProxiedAuthV2Control proxyControl =
         new ProxiedAuthV2Control(new ASN1OctetString("u:test"));
    assertEquals(proxyControl.getValidatedAuthorizationDN(),
    assertEquals(proxyControl.getAuthorizationEntry().getDN(),
                 DN.decode("uid=test,o=test"));
  }
@@ -472,7 +472,7 @@
    ProxiedAuthV2Control proxyControl =
         new ProxiedAuthV2Control(new ASN1OctetString("u:test"));
    proxyControl.getValidatedAuthorizationDN();
    proxyControl.getAuthorizationEntry();
  }
@@ -503,7 +503,7 @@
    ProxiedAuthV2Control proxyControl =
         new ProxiedAuthV2Control(new ASN1OctetString("u:test"));
    proxyControl.getValidatedAuthorizationDN();
    proxyControl.getAuthorizationEntry();
  }
@@ -520,7 +520,7 @@
  {
    ProxiedAuthV2Control proxyControl =
         new ProxiedAuthV2Control(new ASN1OctetString("invalid"));
    proxyControl.getValidatedAuthorizationDN();
    proxyControl.getAuthorizationEntry();
  }
opends/tests/unit-tests-testng/src/server/org/opends/server/core/GroupManagerTestCase.java
@@ -831,7 +831,7 @@
    // Get a client connection authenticated as user1 and make sure it handles
    // group operations correctly.
    authInfo = new AuthenticationInfo(user1DN, false);
    authInfo = new AuthenticationInfo(DirectoryServer.getEntry(user1DN), false);
    InternalClientConnection conn1 = new InternalClientConnection(authInfo);
    searchOperation =
         new InternalSearchOperation(conn1, conn1.nextOperationID(),
@@ -862,7 +862,7 @@
    // Get a client connection authenticated as user2 and make sure it handles
    // group operations correctly.
    authInfo = new AuthenticationInfo(user2DN, false);
    authInfo = new AuthenticationInfo(DirectoryServer.getEntry(user2DN), false);
    InternalClientConnection conn2 = new InternalClientConnection(authInfo);
    searchOperation =
         new InternalSearchOperation(conn2, conn2.nextOperationID(),
@@ -893,7 +893,7 @@
    // Get a client connection authenticated as user3 and make sure it handles
    // group operations correctly.
    authInfo = new AuthenticationInfo(user3DN, false);
    authInfo = new AuthenticationInfo(DirectoryServer.getEntry(user3DN), false);
    InternalClientConnection conn3 = new InternalClientConnection(authInfo);
    searchOperation =
         new InternalSearchOperation(conn3, conn3.nextOperationID(),
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/WhoAmIExtendedOperationTestCase.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.extensions;
@@ -143,8 +143,7 @@
    assertEquals(addOp.getResultCode(), ResultCode.SUCCESS);
    conn = new InternalClientConnection(new AuthenticationInfo(e.getDN(),
                                                               false));
    conn = new InternalClientConnection(new AuthenticationInfo(e, false));
    ExtendedOperation extOp =
         conn.processExtendedOperation(OID_WHO_AM_I_REQUEST, null);
    assertEquals(extOp.getResultCode(), ResultCode.SUCCESS);
opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/internal/InternalClientConnectionTestCase.java
@@ -108,14 +108,31 @@
  public Object[][] getInternalConnections()
         throws Exception
  {
    DN dmDN = DN.decode("cn=Directory Manager,cn=Root DNs,cn=config");
    Entry dmEntry = DirectoryServer.getEntry(dmDN);
    TestCaseUtils.initializeTestBackend(true);
    Entry userEntry = TestCaseUtils.makeEntry(
      "dn: uid=test.user,o=test",
      "objectClass: top",
      "objectClass: person",
      "objectClass: organizationalPerson",
      "objectClass: inetOrgPerson",
      "uid: test.user",
      "givenName: Test",
      "sn: User",
      "cn: Test User",
      "userPassword: password");
    TestCaseUtils.addEntry(userEntry);
    return new Object[][]
    {
      new Object[] { InternalClientConnection.getRootConnection() },
      new Object[] { new InternalClientConnection(new AuthenticationInfo()) },
      new Object[] { new InternalClientConnection(
           new AuthenticationInfo(DN.decode("cn=Directory Manager"), true)) },
           new AuthenticationInfo(dmEntry, true)) },
      new Object[] { new InternalClientConnection(
           new AuthenticationInfo(DN.decode("uid=test,o=test"), false)) },
           new AuthenticationInfo(userEntry, false)) }
    };
  }