From 4e806081638f22dade6802c2996295d263d3e377 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Mon, 12 Feb 2007 16:39:30 +0000
Subject: [PATCH] Implement support for the proxied-auth privilege, which will be required in order to use the proxied authorization control.  This privilege is also used to determine whether a user can specify an alternate authorization identity for the SASL DIGEST-MD5 and PLAIN mechanisms.

---
 opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java |  172 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 168 insertions(+), 4 deletions(-)

diff --git a/opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java b/opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java
index 7036ebe..9a3303a 100644
--- a/opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java
+++ b/opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java
@@ -55,6 +55,7 @@
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.PasswordPolicyState;
 import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.protocols.internal.InternalClientConnection;
 import org.opends.server.types.AuthenticationInfo;
 import org.opends.server.types.ByteString;
 import org.opends.server.types.ConfigChangeResult;
@@ -66,6 +67,7 @@
 import org.opends.server.types.ErrorLogSeverity;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.LockManager;
+import org.opends.server.types.Privilege;
 import org.opends.server.types.ResultCode;
 import org.opends.server.util.Base64;
 
@@ -893,6 +895,170 @@
     }
 
 
+    Entry authZEntry = userEntry;
+    if (responseAuthzID != null)
+    {
+      if (responseAuthzID.length() == 0)
+      {
+        // The authorization ID must not be an empty string.
+        bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+        int    msgID   = MSGID_SASLDIGESTMD5_EMPTY_AUTHZID;
+        String message = getMessage(msgID);
+        bindOperation.setAuthFailureReason(msgID, message);
+        return;
+      }
+      else if (! responseAuthzID.equals(responseUserName))
+      {
+        String lowerAuthzID = toLowerCase(responseAuthzID);
+
+        if (lowerAuthzID.startsWith("dn:"))
+        {
+          DN authzDN;
+          try
+          {
+            authzDN = DN.decode(responseAuthzID.substring(3));
+          }
+          catch (DirectoryException de)
+          {
+            assert debugException(CLASS_NAME, "processSASLBind", de);
+
+            bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+            int    msgID   = MSGID_SASLDIGESTMD5_AUTHZID_INVALID_DN;
+            String message = getMessage(msgID, responseAuthzID,
+                                        de.getErrorMessage());
+            bindOperation.setAuthFailureReason(msgID, message);
+            return;
+          }
+
+          DN actualAuthzDN = DirectoryServer.getActualRootBindDN(authzDN);
+          if (actualAuthzDN != null)
+          {
+            authzDN = actualAuthzDN;
+          }
+
+          if (! authzDN.equals(userEntry.getDN()))
+          {
+            AuthenticationInfo tempAuthInfo =
+              new AuthenticationInfo(userEntry,
+                       DirectoryServer.isRootDN(userEntry.getDN()));
+            InternalClientConnection tempConn =
+                 new InternalClientConnection(tempAuthInfo);
+            if (! tempConn.hasPrivilege(Privilege.PROXIED_AUTH, bindOperation))
+            {
+              bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+              int msgID = MSGID_SASLDIGESTMD5_AUTHZID_INSUFFICIENT_PRIVILEGES;
+              String message = getMessage(msgID,
+                                          String.valueOf(userEntry.getDN()));
+              bindOperation.setAuthFailureReason(msgID, message);
+              return;
+            }
+
+            if (authzDN.isNullDN())
+            {
+              authZEntry = null;
+            }
+            else
+            {
+              try
+              {
+                authZEntry = DirectoryServer.getEntry(authzDN);
+                if (authZEntry == null)
+                {
+                  bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+                  int msgID = MSGID_SASLDIGESTMD5_AUTHZID_NO_SUCH_ENTRY;
+                  String message = getMessage(msgID, String.valueOf(authzDN));
+                  bindOperation.setAuthFailureReason(msgID, message);
+                  return;
+                }
+              }
+              catch (DirectoryException de)
+              {
+                assert debugException(CLASS_NAME, "processSASLBind", de);
+
+                bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+                int msgID = MSGID_SASLDIGESTMD5_AUTHZID_CANNOT_GET_ENTRY;
+                String message = getMessage(msgID, String.valueOf(authzDN),
+                                            de.getErrorMessage());
+                bindOperation.setAuthFailureReason(msgID, message);
+                return;
+              }
+            }
+          }
+        }
+        else
+        {
+          String idStr;
+          if (lowerAuthzID.startsWith("u:"))
+          {
+            idStr = responseAuthzID.substring(2);
+          }
+          else
+          {
+            idStr = responseAuthzID;
+          }
+
+          if (idStr.length() == 0)
+          {
+            authZEntry = null;
+          }
+          else
+          {
+            try
+            {
+              authZEntry = identityMapper.getEntryForID(idStr);
+              if (authZEntry == null)
+              {
+                bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+                int    msgID   = MSGID_SASLDIGESTMD5_AUTHZID_NO_MAPPED_ENTRY;
+                String message = getMessage(msgID, responseAuthzID);
+                bindOperation.setAuthFailureReason(msgID, message);
+                return;
+              }
+            }
+            catch (DirectoryException de)
+            {
+              assert debugException(CLASS_NAME, "processSASLBind", de);
+
+              bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+              int    msgID   = MSGID_SASLDIGESTMD5_CANNOT_MAP_AUTHZID;
+              String message = getMessage(msgID, responseAuthzID,
+                                          de.getErrorMessage());
+              bindOperation.setAuthFailureReason(msgID, message);
+              return;
+            }
+          }
+
+          if ((authZEntry == null) ||
+              (! authZEntry.getDN().equals(userEntry.getDN())))
+          {
+            AuthenticationInfo tempAuthInfo =
+              new AuthenticationInfo(userEntry,
+                       DirectoryServer.isRootDN(userEntry.getDN()));
+            InternalClientConnection tempConn =
+                 new InternalClientConnection(tempAuthInfo);
+            if (! tempConn.hasPrivilege(Privilege.PROXIED_AUTH, bindOperation))
+            {
+              bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
+
+              int msgID = MSGID_SASLDIGESTMD5_AUTHZID_INSUFFICIENT_PRIVILEGES;
+              String message = getMessage(msgID,
+                                          String.valueOf(userEntry.getDN()));
+              bindOperation.setAuthFailureReason(msgID, message);
+              return;
+            }
+          }
+        }
+      }
+    }
+
+
     // Get the clear-text passwords from the user entry, if there are any.
     List<ByteString> clearPasswords;
     try
@@ -968,9 +1134,6 @@
     }
 
 
-    // FIXME -- Need to do something with the authzid.
-
-
     // Generate the response auth element to include in the response to the
     // client.
     byte[] responseAuth;
@@ -1011,7 +1174,8 @@
 
 
     AuthenticationInfo authInfo =
-         new AuthenticationInfo(userEntry, SASL_MECHANISM_DIGEST_MD5,
+         new AuthenticationInfo(userEntry, authZEntry,
+                                SASL_MECHANISM_DIGEST_MD5,
                                 DirectoryServer.isRootDN(userEntry.getDN()));
     bindOperation.setAuthenticationInfo(authInfo);
     return;

--
Gitblit v1.10.0