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

neil_a_wilson
21.01.2006 34451f14f9d4ef9efb313ecbdd22633eec5fd1ff
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;
    }