From 4a4a8540f0b64feff6934c3215c6f896c9561c7d Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Thu, 08 Feb 2007 22:27:58 +0000
Subject: [PATCH] Update the AuthenticationInfo object to store the entries for the authentication and authorization identities rather than just their DNs. This includes a mechanism to keep those entries up to date as changes occur in the server, and also includes a hook for ClientConnection subclasses to perform processing whenever a connection is terminated.
---
opends/src/server/org/opends/server/core/SearchOperation.java | 62 +-
opends/src/server/org/opends/server/protocols/jmx/RmiAuthenticator.java | 6
opends/src/server/org/opends/server/messages/CoreMessages.java | 16
opends/src/server/org/opends/server/util/ServerConstants.java | 15
opends/tests/unit-tests-testng/src/server/org/opends/server/controls/ProxiedAuthV1ControlTestCase.java | 8
opends/src/server/org/opends/server/extensions/CRAMMD5SASLMechanismHandler.java | 2
opends/tests/unit-tests-testng/src/server/org/opends/server/core/GroupManagerTestCase.java | 6
opends/src/server/org/opends/server/core/Operation.java | 91 ++-
opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/internal/InternalClientConnectionTestCase.java | 21
opends/src/server/org/opends/server/core/AddOperation.java | 12
opends/src/server/org/opends/server/extensions/GSSAPISASLMechanismHandler.java | 6
opends/src/server/org/opends/server/core/ModifyOperation.java | 12
opends/src/server/org/opends/server/core/BindOperation.java | 35
opends/src/server/org/opends/server/core/AuthenticatedUsers.java | 265 +++++++++++
opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java | 3
opends/src/server/org/opends/server/controls/ProxiedAuthV1Control.java | 36
opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java | 2
opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java | 4
opends/src/server/org/opends/server/controls/ProxiedAuthV2Control.java | 43 +
opends/src/server/org/opends/server/core/DirectoryServer.java | 18
opends/src/server/org/opends/server/extensions/PasswordModifyExtendedOperation.java | 31
opends/src/server/org/opends/server/api/ClientConnection.java | 201 ++++++++
opends/src/server/org/opends/server/core/CompareOperation.java | 14
opends/src/server/org/opends/server/core/ModifyDNOperation.java | 12
opends/src/server/org/opends/server/extensions/GSSAPIStateInfo.java | 2
opends/tests/unit-tests-testng/src/server/org/opends/server/controls/ProxiedAuthV2ControlTestCase.java | 20
opends/src/server/org/opends/server/extensions/PlainSASLMechanismHandler.java | 2
opends/src/server/org/opends/server/types/AuthenticationInfo.java | 356 +++++++++-----
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/WhoAmIExtendedOperationTestCase.java | 5
opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java | 72 ++
opends/src/server/org/opends/server/core/DeleteOperation.java | 12
opends/src/server/org/opends/server/extensions/ExternalSASLMechanismHandler.java | 2
32 files changed, 1,054 insertions(+), 338 deletions(-)
diff --git a/opends/src/server/org/opends/server/api/ClientConnection.java b/opends/src/server/org/opends/server/api/ClientConnection.java
index 4bfd6e6..c113d31 100644
--- a/opends/src/server/org/opends/server/api/ClientConnection.java
+++ b/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();
+ }
}
diff --git a/opends/src/server/org/opends/server/controls/ProxiedAuthV1Control.java b/opends/src/server/org/opends/server/controls/ProxiedAuthV1Control.java
index 518d547..4af026e 100644
--- a/opends/src/server/org/opends/server/controls/ProxiedAuthV1Control.java
+++ b/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
{
diff --git a/opends/src/server/org/opends/server/controls/ProxiedAuthV2Control.java b/opends/src/server/org/opends/server/controls/ProxiedAuthV2Control.java
index 07f993d..068151e 100644
--- a/opends/src/server/org/opends/server/controls/ProxiedAuthV2Control.java
+++ b/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
diff --git a/opends/src/server/org/opends/server/core/AddOperation.java b/opends/src/server/org/opends/server/core/AddOperation.java
index 2e4b8bd..0f3e85b 100644
--- a/opends/src/server/org/opends/server/core/AddOperation.java
+++ b/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.
diff --git a/opends/src/server/org/opends/server/core/AuthenticatedUsers.java b/opends/src/server/org/opends/server/core/AuthenticatedUsers.java
new file mode 100644
index 0000000..5560f2d
--- /dev/null
+++ b/opends/src/server/org/opends/server/core/AuthenticatedUsers.java
@@ -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);
+ }
+ }
+ }
+}
+
diff --git a/opends/src/server/org/opends/server/core/BindOperation.java b/opends/src/server/org/opends/server/core/BindOperation.java
index fa694e4..0489f66 100644
--- a/opends/src/server/org/opends/server/core/BindOperation.java
+++ b/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);
diff --git a/opends/src/server/org/opends/server/core/CompareOperation.java b/opends/src/server/org/opends/server/core/CompareOperation.java
index e0015cb..a811667 100644
--- a/opends/src/server/org/opends/server/core/CompareOperation.java
+++ b/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.
diff --git a/opends/src/server/org/opends/server/core/DeleteOperation.java b/opends/src/server/org/opends/server/core/DeleteOperation.java
index f144e2c..94748e9 100644
--- a/opends/src/server/org/opends/server/core/DeleteOperation.java
+++ b/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.
diff --git a/opends/src/server/org/opends/server/core/DirectoryServer.java b/opends/src/server/org/opends/server/core/DirectoryServer.java
index a971890..cf95ab6 100644
--- a/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/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
diff --git a/opends/src/server/org/opends/server/core/ModifyDNOperation.java b/opends/src/server/org/opends/server/core/ModifyDNOperation.java
index 8ec6126..46a6402 100644
--- a/opends/src/server/org/opends/server/core/ModifyDNOperation.java
+++ b/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.
diff --git a/opends/src/server/org/opends/server/core/ModifyOperation.java b/opends/src/server/org/opends/server/core/ModifyOperation.java
index 333a9c4..999c39c 100644
--- a/opends/src/server/org/opends/server/core/ModifyOperation.java
+++ b/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.
diff --git a/opends/src/server/org/opends/server/core/Operation.java b/opends/src/server/org/opends/server/core/Operation.java
index fd81051..5943668 100644
--- a/opends/src/server/org/opends/server/core/Operation.java
+++ b/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.
*
diff --git a/opends/src/server/org/opends/server/core/SearchOperation.java b/opends/src/server/org/opends/server/core/SearchOperation.java
index 5667eae..d8b6f44 100644
--- a/opends/src/server/org/opends/server/core/SearchOperation.java
+++ b/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))
{
diff --git a/opends/src/server/org/opends/server/extensions/CRAMMD5SASLMechanismHandler.java b/opends/src/server/org/opends/server/extensions/CRAMMD5SASLMechanismHandler.java
index ef5d0f1..1978be9 100644
--- a/opends/src/server/org/opends/server/extensions/CRAMMD5SASLMechanismHandler.java
+++ b/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;
diff --git a/opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java b/opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java
index 754879d..7036ebe 100644
--- a/opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java
+++ b/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;
diff --git a/opends/src/server/org/opends/server/extensions/ExternalSASLMechanismHandler.java b/opends/src/server/org/opends/server/extensions/ExternalSASLMechanismHandler.java
index 2a2d491..dd71ace 100644
--- a/opends/src/server/org/opends/server/extensions/ExternalSASLMechanismHandler.java
+++ b/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);
diff --git a/opends/src/server/org/opends/server/extensions/GSSAPISASLMechanismHandler.java b/opends/src/server/org/opends/server/extensions/GSSAPISASLMechanismHandler.java
index e44e3ca..a9954f5 100644
--- a/opends/src/server/org/opends/server/extensions/GSSAPISASLMechanismHandler.java
+++ b/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);
diff --git a/opends/src/server/org/opends/server/extensions/GSSAPIStateInfo.java b/opends/src/server/org/opends/server/extensions/GSSAPIStateInfo.java
index 6d0f3b1..35cc403 100644
--- a/opends/src/server/org/opends/server/extensions/GSSAPIStateInfo.java
+++ b/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);
diff --git a/opends/src/server/org/opends/server/extensions/PasswordModifyExtendedOperation.java b/opends/src/server/org/opends/server/extensions/PasswordModifyExtendedOperation.java
index d3f715f..5eafa77 100644
--- a/opends/src/server/org/opends/server/extensions/PasswordModifyExtendedOperation.java
+++ b/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);
diff --git a/opends/src/server/org/opends/server/extensions/PlainSASLMechanismHandler.java b/opends/src/server/org/opends/server/extensions/PlainSASLMechanismHandler.java
index 5d56eb5..3adb6c0 100644
--- a/opends/src/server/org/opends/server/extensions/PlainSASLMechanismHandler.java
+++ b/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;
diff --git a/opends/src/server/org/opends/server/messages/CoreMessages.java b/opends/src/server/org/opends/server/messages/CoreMessages.java
index 67f2b53..295310f 100644
--- a/opends/src/server/org/opends/server/messages/CoreMessages.java
+++ b/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.");
}
}
diff --git a/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java b/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
index 8508a8e..a56704f 100644
--- a/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
+++ b/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("\")");
}
}
diff --git a/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java b/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
index 79678d2..985f539 100644
--- a/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
+++ b/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);
}
}
diff --git a/opends/src/server/org/opends/server/protocols/jmx/RmiAuthenticator.java b/opends/src/server/org/opends/server/protocols/jmx/RmiAuthenticator.java
index 16d02cf..0013295 100644
--- a/opends/src/server/org/opends/server/protocols/jmx/RmiAuthenticator.java
+++ b/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
diff --git a/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java b/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
index 147535a..9059c8d 100644
--- a/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
+++ b/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
diff --git a/opends/src/server/org/opends/server/types/AuthenticationInfo.java b/opends/src/server/org/opends/server/types/AuthenticationInfo.java
index 05d8df8..a570693 100644
--- a/opends/src/server/org/opends/server/types/AuthenticationInfo.java
+++ b/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;
+ }
}
diff --git a/opends/src/server/org/opends/server/util/ServerConstants.java b/opends/src/server/org/opends/server/util/ServerConstants.java
index b915876..2f13a5a 100644
--- a/opends/src/server/org/opends/server/util/ServerConstants.java
+++ b/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.
*/
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/controls/ProxiedAuthV1ControlTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/controls/ProxiedAuthV1ControlTestCase.java
index b0b6a7c..3515430 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/controls/ProxiedAuthV1ControlTestCase.java
+++ b/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();
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/controls/ProxiedAuthV2ControlTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/controls/ProxiedAuthV2ControlTestCase.java
index 79fea63..72b044f 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/controls/ProxiedAuthV2ControlTestCase.java
+++ b/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();
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/core/GroupManagerTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/core/GroupManagerTestCase.java
index 6721b0c..d9149a2 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/core/GroupManagerTestCase.java
+++ b/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(),
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/WhoAmIExtendedOperationTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/WhoAmIExtendedOperationTestCase.java
index 437b915..58c7c1f 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/WhoAmIExtendedOperationTestCase.java
+++ b/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);
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/internal/InternalClientConnectionTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/internal/InternalClientConnectionTestCase.java
index 9d6a9fb..c0a2e82 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/internal/InternalClientConnectionTestCase.java
+++ b/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)) }
};
}
--
Gitblit v1.10.0