From 34451f14f9d4ef9efb313ecbdd22633eec5fd1ff Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Thu, 21 Sep 2006 15:01:12 +0000
Subject: [PATCH] Update the PLAIN, CRAM-MD5, and DIGEST-MD5 SASL mechanism handlers to use the password policy during the process of verifying the credentials rather than just assuming that the password is held in the userPassword attribute.

---
 opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java |  206 +++++++++++++--------------------------------------
 1 files changed, 53 insertions(+), 153 deletions(-)

diff --git a/opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java b/opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java
index acb0870..121d6e9 100644
--- a/opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java
+++ b/opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java
@@ -45,7 +45,6 @@
 import org.opends.server.api.ClientConnection;
 import org.opends.server.api.ConfigurableComponent;
 import org.opends.server.api.IdentityMapper;
-import org.opends.server.api.PasswordStorageScheme;
 import org.opends.server.api.SASLMechanismHandler;
 import org.opends.server.config.ConfigAttribute;
 import org.opends.server.config.ConfigEntry;
@@ -57,10 +56,8 @@
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.InitializationException;
 import org.opends.server.core.LockManager;
+import org.opends.server.core.PasswordPolicyState;
 import org.opends.server.protocols.asn1.ASN1OctetString;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.AttributeType;
-import org.opends.server.types.AttributeValue;
 import org.opends.server.types.AuthenticationInfo;
 import org.opends.server.types.ByteString;
 import org.opends.server.types.ConfigChangeResult;
@@ -862,6 +859,7 @@
     else
     {
       // Use the identity mapper to resolve the username to an entry.
+      String userName = responseUserName;
       if (lowerUserName.startsWith("u:"))
       {
         if (lowerUserName.equals("u:"))
@@ -874,13 +872,13 @@
           return;
         }
 
-        responseUserName = responseUserName.substring(2);
+        userName = responseUserName.substring(2);
       }
 
 
       try
       {
-        userEntry = identityMapper.getEntryForID(responseUserName);
+        userEntry = identityMapper.getEntryForID(userName);
       }
       catch (DirectoryException de)
       {
@@ -913,154 +911,66 @@
     }
 
 
-    // Get the password attribute from the user entry and iterate through the
-    // available values.  We can only look at reversible values, so all
-    // non-reversible values will be ignored.  For each reversible value, see
-    // if we can use it in conjunction with the challenge to construct the
-    // provided digest.
-    // FIXME -- Determine the attribute based on the user's password policy.
-    AttributeType pwType = DirectoryServer.getAttributeType(ATTR_USER_PASSWORD);
-    if (pwType == null)
+    // Get the clear-text passwords from the user entry, if there are any.
+    List<ByteString> clearPasswords;
+    try
     {
-      pwType = DirectoryServer.getDefaultAttributeType(ATTR_USER_PASSWORD);
-    }
+      PasswordPolicyState pwPolicyState =
+           new PasswordPolicyState(userEntry, false, false);
+      clearPasswords = pwPolicyState.getClearPasswords();
+      if ((clearPasswords == null) || clearPasswords.isEmpty())
+      {
+        bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
 
-    List<Attribute> pwAttr = userEntry.getAttribute(pwType);
-    if ((pwAttr == null) || pwAttr.isEmpty())
+        int msgID = MSGID_SASLDIGESTMD5_NO_REVERSIBLE_PASSWORDS;
+        String message = getMessage(msgID, String.valueOf(userEntry.getDN()));
+        bindOperation.setAuthFailureReason(msgID, message);
+        return;
+      }
+    }
+    catch (Exception e)
     {
       bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
 
-      int    msgID   = MSGID_SASLDIGESTMD5_NO_PW_ATTR;
-      String message = getMessage(msgID, pwType.getNameOrOID());
+      int    msgID   = MSGID_SASLDIGESTMD5_CANNOT_GET_REVERSIBLE_PASSWORDS;
+      String message = getMessage(msgID, String.valueOf(userEntry.getDN()),
+                                  String.valueOf(e));
       bindOperation.setAuthFailureReason(msgID, message);
       return;
     }
 
-    boolean reversibleFound = false;
-    boolean matchFound       = false;
-    byte[]  passwordBytes    = null;
-    for (Attribute a : pwAttr)
+
+    // Iterate through the clear-text values and see if any of them can be used
+    // in conjunction with the challenge to construct the provided digest.
+    boolean matchFound    = false;
+    byte[]  passwordBytes = null;
+    for (ByteString clearPassword : clearPasswords)
     {
-      for (AttributeValue v : a.getValues())
+      byte[] generatedDigest;
+      try
       {
-        String valueStr = v.getStringValue();
-        int closePos;
-        if (valueStr.startsWith(STORAGE_SCHEME_PREFIX) &&
-            (closePos = valueStr.indexOf(STORAGE_SCHEME_SUFFIX, 2)) > 0)
-        {
-          String schemeName =
-               toLowerCase(valueStr.substring(1, closePos));
-          PasswordStorageScheme scheme =
-               DirectoryServer.getPasswordStorageScheme(schemeName);
-          if (scheme == null)
-          {
-            // We can't do anything with this.  Append a message to the
-            // error message to include in the response and continue.
-            int    msgID   = MSGID_SASLDIGESTMD5_UNKNOWN_STORAGE_SCHEME;
-            String message = getMessage(msgID,
-                                        String.valueOf(userEntry.getDN()),
-                                        schemeName);
-            logError(ErrorLogCategory.EXTENSIONS,
-                     ErrorLogSeverity.SEVERE_WARNING, message, msgID);
-            continue;
-          }
-          else if (! scheme.isReversible())
-          {
-            // It's not a reversible scheme, so we can't get the clear-text
-            // password to test.  Skip it and go on.
-            continue;
-          }
-          else
-          {
-            ASN1OctetString encodedPassword =
-                 new ASN1OctetString(valueStr.substring(closePos+1));
-            ByteString clearPassword;
+        generatedDigest =
+             generateResponseDigest(responseUserName, responseAuthzID,
+                                    clearPassword.value(), responseRealm,
+                                    responseNonce, responseCNonce,
+                                    responseNonceCountStr, responseDigestURI,
+                                    responseQoP, responseCharset);
+      }
+      catch (Exception e)
+      {
+        assert debugException(CLASS_NAME, "processSASLBind", e);
 
-            try
-            {
-              clearPassword   = scheme.getPlaintextValue(encodedPassword);
-              reversibleFound = true;
-            }
-            catch (DirectoryException de)
-            {
-              assert debugException(CLASS_NAME, "processSASLBind", de);
-
-              int    msgID   = MSGID_SASLDIGESTMD5_CANNOT_GET_CLEAR_PASSWORD;
-              String message = getMessage(msgID,
-                                          String.valueOf(userEntry.getDN()),
-                                          schemeName, de.getErrorMessage());
-              logError(ErrorLogCategory.EXTENSIONS,
-                       ErrorLogSeverity.SEVERE_WARNING, message, msgID);
-              continue;
-            }
-
-            byte[] generatedDigest;
-            try
-            {
-              generatedDigest =
-                   generateResponseDigest(responseUserName, responseAuthzID,
-                                          clearPassword.value(), responseRealm,
-                                          responseNonce, responseCNonce,
-                                          responseNonceCountStr,
-                                          responseDigestURI, responseQoP,
-                                          responseCharset);
-            }
-            catch (Exception e)
-            {
-              assert debugException(CLASS_NAME, "processSASLBind", e);
-
-              logError(ErrorLogCategory.EXTENSIONS,
-                       ErrorLogSeverity.SEVERE_WARNING,
-                       MSGID_SASLDIGESTMD5_CANNOT_GENERATE_RESPONSE_DIGEST,
-                       stackTraceToSingleLineString(e));
-              continue;
-            }
-
-
-            if (Arrays.equals(responseDigest, generatedDigest))
-            {
-              matchFound    = true;
-              passwordBytes = clearPassword.value();
-              break;
-            }
-          }
-        }
-        else
-        {
-          reversibleFound = true;
-          byte[] generatedDigest;
-          try
-          {
-            generatedDigest =
-                 generateResponseDigest(responseUserName, responseAuthzID,
-                                        v.getValue().value(), responseRealm,
-                                        responseNonce, responseCNonce,
-                                        responseNonceCountStr,
-                                        responseDigestURI, responseQoP,
-                                        responseCharset);
-          }
-          catch (Exception e)
-          {
-            assert debugException(CLASS_NAME, "processSASLBind", e);
-
-            logError(ErrorLogCategory.EXTENSIONS,
-                     ErrorLogSeverity.SEVERE_WARNING,
-                     MSGID_SASLDIGESTMD5_CANNOT_GENERATE_RESPONSE_DIGEST,
-                     stackTraceToSingleLineString(e));
-            continue;
-          }
-
-          if (Arrays.equals(responseDigest, generatedDigest))
-          {
-            matchFound    = true;
-            passwordBytes = v.getValue().value();
-            break;
-          }
-        }
+        logError(ErrorLogCategory.EXTENSIONS,
+                 ErrorLogSeverity.SEVERE_WARNING,
+                 MSGID_SASLDIGESTMD5_CANNOT_GENERATE_RESPONSE_DIGEST,
+                 stackTraceToSingleLineString(e));
+        continue;
       }
 
-      if (matchFound)
+      if (Arrays.equals(responseDigest, generatedDigest))
       {
+        matchFound    = true;
+        passwordBytes = clearPassword.value();
         break;
       }
     }
@@ -1069,20 +979,10 @@
     {
       bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
 
-      if (reversibleFound)
-      {
-        int    msgID   = MSGID_SASLDIGESTMD5_INVALID_CREDENTIALS;
-        String message = getMessage(msgID);
-        bindOperation.setAuthFailureReason(msgID, message);
-        return;
-      }
-      else
-      {
-        int    msgID   = MSGID_SASLDIGESTMD5_NO_REVERSIBLE_PASSWORDS;
-        String message = getMessage(msgID);
-        bindOperation.setAuthFailureReason(msgID, message);
-        return;
-      }
+      int    msgID   = MSGID_SASLDIGESTMD5_INVALID_CREDENTIALS;
+      String message = getMessage(msgID);
+      bindOperation.setAuthFailureReason(msgID, message);
+      return;
     }
 
 

--
Gitblit v1.10.0