From 92be69ced668ace6903a27efa86aefd5f064b4d7 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Sat, 04 Aug 2007 22:25:50 +0000
Subject: [PATCH] Update the "Who Am I?" extended operation handler so that it supports the use of the proxied authorization control (versions 1 and 2).  Also, add test cases that cover the use of the proxied auth control and an alternate authorization identity from a SASL bind.

---
 opendj-sdk/opends/src/server/org/opends/server/extensions/WhoAmIExtendedOperation.java |  202 +++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 175 insertions(+), 27 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/WhoAmIExtendedOperation.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/WhoAmIExtendedOperation.java
index 763a50b..ddd61c7 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/WhoAmIExtendedOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/WhoAmIExtendedOperation.java
@@ -28,20 +28,34 @@
 
 
 
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.opends.server.admin.std.server.ExtendedOperationHandlerCfg;
 import org.opends.server.api.ClientConnection;
 import org.opends.server.api.ExtendedOperationHandler;
 import org.opends.server.config.ConfigException;
+import org.opends.server.controls.ProxiedAuthV1Control;
+import org.opends.server.controls.ProxiedAuthV2Control;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.ExtendedOperation;
+import org.opends.server.loggers.debug.DebugTracer;
 import org.opends.server.protocols.asn1.ASN1OctetString;
-import org.opends.server.types.AuthenticationInfo;
+import org.opends.server.types.Control;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DN;
+import org.opends.server.types.Entry;
 import org.opends.server.types.InitializationException;
+import org.opends.server.types.LDAPException;
+import org.opends.server.types.Privilege;
 import org.opends.server.types.ResultCode;
 
+import static org.opends.server.loggers.debug.DebugLogger.*;
 import static org.opends.server.messages.ExtensionsMessages.*;
 import static org.opends.server.messages.MessageHandler.*;
 import static org.opends.server.util.ServerConstants.*;
-import org.opends.server.admin.std.server.ExtendedOperationHandlerCfg;
 
 
 /**
@@ -51,6 +65,10 @@
 public class WhoAmIExtendedOperation
        extends ExtendedOperationHandler<ExtendedOperationHandlerCfg>
 {
+  /**
+   * The tracer object for the debug logger.
+   */
+  private static final DebugTracer TRACER = getTracer();
 
 
 
@@ -62,7 +80,6 @@
   public WhoAmIExtendedOperation()
   {
     super();
-
   }
 
 
@@ -99,6 +116,7 @@
    * Performs any finalization that may be necessary for this extended
    * operation handler.  By default, no finalization is performed.
    */
+  @Override()
   public void finalizeExtendedOperationHandler()
   {
     DirectoryServer.deregisterSupportedExtension(OID_WHO_AM_I_REQUEST);
@@ -109,42 +127,172 @@
 
 
   /**
-   * Processes the provided extended operation.
-   *
-   * @param  operation  The extended operation to be processed.
+   * {@inheritDoc}
    */
+  @Override()
+  public Set<String> getSupportedControls()
+  {
+    HashSet<String> supportedControls = new HashSet<String>(2);
+
+    supportedControls.add(OID_PROXIED_AUTH_V1);
+    supportedControls.add(OID_PROXIED_AUTH_V2);
+
+    return supportedControls;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
   public void processExtendedOperation(ExtendedOperation operation)
   {
-    // Get the client connection and determine the DN of the user associated
-    // with it.
+    // Process any supported controls for this operation, including the
+    // proxied authorization control.
     ClientConnection clientConnection = operation.getClientConnection();
-    if (clientConnection == null)
+    List<Control> requestControls = operation.getRequestControls();
+    if (requestControls != null)
     {
-      // There is no client connection, so we can't make the determination.
-      operation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
+      for (Control c : requestControls)
+      {
+        String oid = c.getOID();
+        if (oid.equals(OID_PROXIED_AUTH_V1))
+        {
+          // The requester must have the PROXIED_AUTH privilige in order to
+          // be able to use this control.
+          if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH,
+                                              operation))
+          {
+            int msgID = MSGID_EXTOP_WHOAMI_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
+            operation.appendErrorMessage(getMessage(msgID));
+            operation.setResultCode(ResultCode.AUTHORIZATION_DENIED);
+            return;
+          }
 
-      int msgID = MSGID_EXTOP_WHOAMI_NO_CLIENT_CONNECTION;
-      operation.appendErrorMessage(getMessage(msgID));
-      return;
+
+          ProxiedAuthV1Control proxyControl;
+          if (c instanceof ProxiedAuthV1Control)
+          {
+            proxyControl = (ProxiedAuthV1Control) c;
+          }
+          else
+          {
+            try
+            {
+              proxyControl = ProxiedAuthV1Control.decodeControl(c);
+            }
+            catch (LDAPException le)
+            {
+              if (debugEnabled())
+              {
+                TRACER.debugCaught(DebugLogLevel.ERROR, le);
+              }
+
+              operation.setResultCode(ResultCode.valueOf(le.getResultCode()));
+              operation.appendErrorMessage(le.getMessage());
+              return;
+            }
+          }
+
+
+          Entry authorizationEntry;
+          try
+          {
+            authorizationEntry = proxyControl.getAuthorizationEntry();
+          }
+          catch (DirectoryException de)
+          {
+            if (debugEnabled())
+            {
+              TRACER.debugCaught(DebugLogLevel.ERROR, de);
+            }
+
+            operation.setResultCode(de.getResultCode());
+            operation.appendErrorMessage(de.getErrorMessage());
+            return;
+          }
+
+          operation.setAuthorizationEntry(authorizationEntry);
+        }
+        else if (oid.equals(OID_PROXIED_AUTH_V2))
+        {
+          // The requester must have the PROXIED_AUTH privilige in order to
+          // be able to use this control.
+          if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH,
+                                              operation))
+          {
+            int msgID = MSGID_EXTOP_WHOAMI_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
+            operation.appendErrorMessage(getMessage(msgID));
+            operation.setResultCode(ResultCode.AUTHORIZATION_DENIED);
+            return;
+          }
+
+
+          ProxiedAuthV2Control proxyControl;
+          if (c instanceof ProxiedAuthV2Control)
+          {
+            proxyControl = (ProxiedAuthV2Control) c;
+          }
+          else
+          {
+            try
+            {
+              proxyControl = ProxiedAuthV2Control.decodeControl(c);
+            }
+            catch (LDAPException le)
+            {
+              if (debugEnabled())
+              {
+                TRACER.debugCaught(DebugLogLevel.ERROR, le);
+              }
+
+              operation.setResultCode(ResultCode.valueOf(le.getResultCode()));
+              operation.appendErrorMessage(le.getMessage());
+              return;
+            }
+          }
+
+
+          Entry authorizationEntry;
+          try
+          {
+            authorizationEntry = proxyControl.getAuthorizationEntry();
+          }
+          catch (DirectoryException de)
+          {
+            if (debugEnabled())
+            {
+              TRACER.debugCaught(DebugLogLevel.ERROR, de);
+            }
+
+            operation.setResultCode(de.getResultCode());
+            operation.appendErrorMessage(de.getErrorMessage());
+            return;
+          }
+
+          operation.setAuthorizationEntry(authorizationEntry);
+        }
+      }
     }
 
-    // Get the auth info from the client connection.
-    AuthenticationInfo authInfo = clientConnection.getAuthenticationInfo();
-    if ((authInfo == null) || (authInfo.getAuthenticationDN() == null))
+
+    // Get the authorization DN for the operation and add it to the response
+    // value.
+    String authzID;
+    DN authzDN = operation.getAuthorizationDN();
+    if (authzDN == null)
     {
-      // The user must not be authenticated, so we can send back an empty
-      // response value.
-      operation.setResultCode(ResultCode.SUCCESS);
-      operation.setResponseValue(new ASN1OctetString());
-      return;
+      authzID = "";
+    }
+    else
+    {
+      authzID = "dn:" + authzDN.toString();
     }
 
-    // Get the DN of the authenticated user and put that in the response.
-    // FIXME -- Do we need to support the use of an authorization ID that is
-    //          different from the authentication ID?
+    operation.setResponseValue(new ASN1OctetString(authzID));
+    operation.appendAdditionalLogMessage("authzID=\"" + authzID + "\"");
     operation.setResultCode(ResultCode.SUCCESS);
-    operation.setResponseValue(new ASN1OctetString("dn:" +
-                                    authInfo.getAuthenticationDN().toString()));
   }
 }
 

--
Gitblit v1.10.0