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

neil_a_wilson
13.11.2007 eb121a5b40ed017168b87a52428b1f41ff47915f
Update the DIGEST-MD5 processing code to properly degrade to an initial
authentication whenever a client requests subsequent authentication. The
current implementation does not support subsequent authentication (which is an
optional part of the spec), but we were previously incorrectly rejecting
attempts to use it when instead we should have treated it as a completely new
DIGEST-MD5 session.

OpenDS Issue Number: 2098
2 files modified
69 ■■■■■ changed files
opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java 49 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/messages/ExtensionsMessages.java 20 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/DigestMD5SASLMechanismHandler.java
@@ -212,12 +212,22 @@
    String realm = config.getRealm();
    // The DIGEST-MD5 bind process uses two stages.  See if the client provided
    // any credentials.  If not, then this is an initial authentication so we
    // will send a challenge to the client.
    ByteString       clientCredentials = bindOperation.getSASLCredentials();
    // The DIGEST-MD5 bind process uses two stages.  See if we have any state
    // information from the first stage to determine whether this is a
    // continuation of an existing bind or an initial authentication.  Note that
    // this implementation does not support subsequent authentication, so even
    // if the client provided credentials for the bind, it will be treated as an
    // initial authentication if there is no existing state.
    boolean initialAuth = true;
    ClientConnection clientConnection  = bindOperation.getClientConnection();
    if ((clientCredentials == null) || (clientCredentials.value().length == 0))
    Object saslStateInfo = clientConnection.getSASLAuthStateInfo();
    if ((saslStateInfo != null) &&
        (saslStateInfo instanceof DigestMD5StateInfo))
    {
      initialAuth = false;
    }
    if (initialAuth)
    {
      // Create a buffer to hold the challenge.
      StringBuilder challengeBuffer = new StringBuilder();
@@ -310,32 +320,29 @@
    }
    // If we've gotten here, then the client did provide credentials.  This can
    // be either an initial or subsequent authentication, but they will both be
    // handled identically.  First, get the stored client SASL state.  If it's
    // not there, then fail.
    Object saslStateInfo = clientConnection.getSASLAuthStateInfo();
    if (saslStateInfo == null)
    // If we've gotten here, then we have existing SASL state information for
    // this client.  Make sure that the client also provided credentials.
    ASN1OctetString clientCredentials = bindOperation.getSASLCredentials();
    if ((clientCredentials == null) || (clientCredentials.value().length == 0))
    {
      bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
      int    msgID   = MSGID_SASLDIGESTMD5_NO_STORED_STATE;
      int    msgID   = MSGID_SASLDIGESTMD5_NO_CREDENTIALS;
      String message = getMessage(msgID);
      bindOperation.setAuthFailureReason(msgID, message);
      return;
    }
    if (! (saslStateInfo instanceof DigestMD5StateInfo))
    {
      bindOperation.setResultCode(ResultCode.INVALID_CREDENTIALS);
      int    msgID   = MSGID_SASLDIGESTMD5_INVALID_STORED_STATE;
      String message = getMessage(msgID);
      bindOperation.setAuthFailureReason(msgID, message);
      return;
    }
    // Parse the SASL state information.  Also, since there are only ever two
    // stages of a DIGEST-MD5 bind, clear the SASL state information stored in
    // the client connection because it shouldn't be used anymore regardless of
    // whether the bind succeeds or fails.  Note that if we do add support for
    // subsequent authentication in the future, then we will probably need to
    // keep state information in the client connection, but even then it will
    // be different from what's already there.
    DigestMD5StateInfo stateInfo = (DigestMD5StateInfo) saslStateInfo;
    clientConnection.setSASLAuthStateInfo(null);
    // Create variables to hold values stored in the client's response.  We'll
opends/src/server/org/opends/server/messages/ExtensionsMessages.java
@@ -2149,11 +2149,12 @@
  /**
   * The message ID for the message that will be used if the client provides
   * SASL credentials but the server doesn't have any previous SASL state for
   * that client.  This does not take any arguments.
   * The message ID for the message that will be used if the bind request
   * did not contain any credentials when the client connection already had
   * DIGEST-MD5 state information, indicating that it was not an initial
   * authentication.  This does not take any arguments.
   */
  public static final int MSGID_SASLDIGESTMD5_NO_STORED_STATE =
  public static final int MSGID_SASLDIGESTMD5_NO_CREDENTIALS =
       CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 201;
@@ -6836,12 +6837,11 @@
    registerMessage(MSGID_SASLDIGESTMD5_CHALLENGE_TOO_LONG,
                    "The initial DIGEST-MD5 must be less than 2048 bytes, " +
                    "but the generated challenge was %d bytes");
    registerMessage(MSGID_SASLDIGESTMD5_NO_STORED_STATE,
                    "The SASL DIGEST-MD5 bind request contained SASL " +
                    "credentials but there is no stored SASL state " +
                    "information for this client connection.  If this is " +
                    "an initial authentication, then the client must not " +
                    "provide any SASL credentials");
    registerMessage(MSGID_SASLDIGESTMD5_NO_CREDENTIALS,
                    "The client connection included DIGEST-MD5 state " +
                    "information, indicating that the client was in the " +
                    "process of performing a DIGEST-MD5 bind, but the " +
                    "bind request did not include any credentials");
    registerMessage(MSGID_SASLDIGESTMD5_INVALID_STORED_STATE,
                    "The SASL DIGEST-MD5 bind request contained SASL " +
                    "credentials, but the stored SASL state information for " +