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

Jean-Noel Rouvignac
12.36.2014 e3deb8b9b6b1e1fbf53309380f5b30da848c507f
CR-4097 Big code cleanup of some storage schemes.

PBKDF2PasswordStorageScheme.java, PKCS5S2PasswordStorageScheme.java:
Fixed a bug in PBKF2 + PKCS5S2 encodeOffline() methods which did not know how to deal with a byte[]. The right way was to wrap it in a ByteString like SaltedSHA1PasswordStorageScheme was already doing. BTW these encodeOffline() methods are never called from production code.
Did more code factorization.
Removed dead code in both with plainPlusSalt local variable which was not used for anything.
Fixed a few bugs in PKCS5S2 where locks where not properly taken (or carefully avoided?).
Made both PBKF2 + PKCS5S2 code look very similar now.

PBKDF2PasswordStorageSchemeTestCase.java, PKCS5S2PasswordStorageSchemeTestCase.java, PasswordStorageSchemeTestCase.java, SaltedSHA1PasswordStorageSchemeTestCase.java, SaltedSHA256PasswordStorageSchemeTestCase.java, SaltedSHA384PasswordStorageSchemeTestCase.java, SaltedSHA512PasswordStorageSchemeTestCase.java:
Removed dead code.

CryptPasswordStorageSchemeTestCase.java:
Made it reuse more code from PasswordStorageSchemeTestCase.
10 files modified
979 ■■■■■ changed files
opendj3-server-dev/src/server/org/opends/server/extensions/PBKDF2PasswordStorageScheme.java 193 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageScheme.java 129 ●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/CryptPasswordStorageSchemeTestCase.java 251 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/PBKDF2PasswordStorageSchemeTestCase.java 7 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageSchemeTestCase.java 38 ●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/PasswordStorageSchemeTestCase.java 133 ●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageSchemeTestCase.java 48 ●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageSchemeTestCase.java 58 ●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageSchemeTestCase.java 59 ●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageSchemeTestCase.java 63 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/extensions/PBKDF2PasswordStorageScheme.java
@@ -93,7 +93,6 @@
  /** The current configuration for this storage scheme. */
  private volatile PBKDF2PasswordStorageSchemeCfg config;
  /**
   * Creates a new instance of this password storage scheme.  Note that no
   * initialization should be performed here, as all initialization should be
@@ -157,13 +156,8 @@
    byte[] saltBytes      = new byte[NUM_SALT_BYTES];
    int    iterations     = config.getPBKDF2Iterations();
    byte[] digestBytes = getDigestBytes(plaintext, saltBytes, iterations);
    // Append the salt to the hashed value and base64-the whole thing.
    byte[] hashPlusSalt = new byte[digestBytes.length + NUM_SALT_BYTES];
    System.arraycopy(digestBytes, 0, hashPlusSalt, 0, digestBytes.length);
    System.arraycopy(saltBytes, 0, hashPlusSalt, digestBytes.length,
                     NUM_SALT_BYTES);
    byte[] digestBytes = encodeWithRandomSalt(plaintext, saltBytes, iterations);
    byte[] hashPlusSalt = concatenateHashPlusSalt(saltBytes, digestBytes);
    return ByteString.valueOf(iterations + ":" + Base64.encode(hashPlusSalt));
  }
@@ -186,8 +180,8 @@
    // Base64-decode the remaining value and take the last 8 bytes as the salt.
    try
    {
      String stored = storedPassword.toString();
      int pos = stored.indexOf(':');
      final String stored = storedPassword.toString();
      final int pos = stored.indexOf(':');
      if (pos == -1)
      {
        throw new Exception();
@@ -217,43 +211,6 @@
    }
  }
  private boolean encodeAndMatch(ByteSequence plaintextPassword,
      final byte[] saltBytes, byte[] digestBytes, int iterations)
  {
    // Use the salt to generate a digest based on the provided plain-text value.
    int plainBytesLength = plaintextPassword.length();
    byte[] plainPlusSalt = new byte[plainBytesLength + saltBytes.length];
    plaintextPassword.copyTo(plainPlusSalt);
    System.arraycopy(saltBytes, 0, plainPlusSalt, plainBytesLength, saltBytes.length);
    char[] plaintextChars = null;
    synchronized (factoryLock)
    {
      try
      {
        plaintextChars = plaintextPassword.toString().toCharArray();
        KeySpec spec = new PBEKeySpec(
            plaintextChars, saltBytes,
            iterations, SHA1_LENGTH * 8);
        final byte[] userDigestBytes = factory.generateSecret(spec).getEncoded();
        return Arrays.equals(digestBytes, userDigestBytes);
      }
      catch (Exception e)
      {
        logger.traceException(e);
        return false;
      }
      finally
      {
        if (plaintextChars != null)
        {
          Arrays.fill(plaintextChars, '0');
        }
      }
    }
  }
  /** {@inheritDoc} */
  @Override
  public boolean supportsAuthPasswordSyntax()
@@ -275,7 +232,7 @@
  {
    byte[] saltBytes      = new byte[NUM_SALT_BYTES];
    int    iterations     = config.getPBKDF2Iterations();
    byte[] digestBytes = getDigestBytes(plaintext, saltBytes, iterations);
    byte[] digestBytes = encodeWithRandomSalt(plaintext, saltBytes, iterations);
    // Encode and return the value.
    return ByteString.valueOf(AUTH_PASSWORD_SCHEME_NAME_PBKDF2 + '$'
@@ -283,41 +240,6 @@
        + Base64.encode(digestBytes));
  }
  private byte[] getDigestBytes(ByteSequence plaintext, byte[] saltBytes,
      int iterations) throws DirectoryException
  {
    char[] plaintextChars = null;
    synchronized (factoryLock)
    {
      try
      {
        random.nextBytes(saltBytes);
        plaintextChars = plaintext.toString().toCharArray();
        KeySpec spec = new PBEKeySpec(
            plaintextChars, saltBytes,
            iterations, SHA1_LENGTH * 8);
        return factory.generateSecret(spec).getEncoded();
      }
      catch (Exception e)
      {
        logger.traceException(e);
        LocalizableMessage message = ERR_PWSCHEME_CANNOT_ENCODE_PASSWORD.get(
            CLASS_NAME, getExceptionMessage(e));
        throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                     message, e);
      }
      finally
      {
        if (plaintextChars != null)
        {
          Arrays.fill(plaintextChars, '0');
        }
      }
    }
  }
  /** {@inheritDoc} */
  @Override
  public boolean authPasswordMatches(ByteSequence plaintextPassword,
@@ -386,10 +308,8 @@
   * user password).
   *
   * @param  passwordBytes  The bytes that make up the clear-text password.
   *
   * @return  The encoded password string, including the scheme name in curly
   *          braces.
   *
   * @throws  DirectoryException  If a problem occurs during processing.
   */
  public static String encodeOffline(byte[] passwordBytes)
@@ -398,42 +318,46 @@
    byte[] saltBytes      = new byte[NUM_SALT_BYTES];
    int    iterations     = 10000;
    byte[] digestBytes = getDigestBytes(passwordBytes, saltBytes, iterations);
    // Append the salt to the hashed value and base64-the whole thing.
    byte[] hashPlusSalt = new byte[digestBytes.length + NUM_SALT_BYTES];
    final ByteString password = ByteString.wrap(passwordBytes);
    byte[] digestBytes = encodeWithRandomSalt(password, saltBytes, iterations);
    byte[] hashPlusSalt = concatenateHashPlusSalt(saltBytes, digestBytes);
    System.arraycopy(digestBytes, 0, hashPlusSalt, 0, digestBytes.length);
    System.arraycopy(saltBytes, 0, hashPlusSalt, digestBytes.length,
                     NUM_SALT_BYTES);
    return '{' + STORAGE_SCHEME_NAME_PBKDF2 + '}' + iterations + ':' +
      Base64.encode(hashPlusSalt);
    return '{' + STORAGE_SCHEME_NAME_PBKDF2 + '}' + iterations + ':'
        + Base64.encode(hashPlusSalt);
  }
  private static byte[] getDigestBytes(byte[] plaintext, byte[] saltBytes,
  private static byte[] encodeWithRandomSalt(ByteString plaintext, byte[] saltBytes,
      int iterations) throws DirectoryException
  {
    char[] plaintextChars = null;
    try
    {
      SecureRandom.getInstance(SECURE_PRNG_SHA1).nextBytes(saltBytes);
      plaintextChars = plaintext.toString().toCharArray();
      KeySpec spec = new PBEKeySpec(
          plaintextChars, saltBytes,
          iterations, SHA1_LENGTH * 8);
      return SecretKeyFactory
          .getInstance(MESSAGE_DIGEST_ALGORITHM_PBKDF2)
          .generateSecret(spec).getEncoded();
      final SecureRandom random = SecureRandom.getInstance(SECURE_PRNG_SHA1);
      final SecretKeyFactory factory = SecretKeyFactory.getInstance(MESSAGE_DIGEST_ALGORITHM_PBKDF2);
      return encodeWithRandomSalt(plaintext, saltBytes, iterations, random, factory);
    }
    catch (DirectoryException e)
    {
      throw e;
    }
    catch (Exception e)
    {
      logger.traceException(e);
      throw cannotEncodePassword(e);
    }
  }
      LocalizableMessage message = ERR_PWSCHEME_CANNOT_ENCODE_PASSWORD.get(
          CLASS_NAME, getExceptionMessage(e));
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
          message, e);
  private static byte[] encodeWithSalt(ByteSequence plaintext, byte[] saltBytes,
      int iterations, final SecretKeyFactory factory) throws DirectoryException
  {
    final char[] plaintextChars = plaintext.toString().toCharArray();
    try
    {
      KeySpec spec =
          new PBEKeySpec(plaintextChars, saltBytes, iterations, SHA1_LENGTH * 8);
      return factory.generateSecret(spec).getEncoded();
    }
    catch (Exception e)
    {
      throw cannotEncodePassword(e);
    }
    finally
    {
@@ -444,4 +368,53 @@
    }
  }
  private boolean encodeAndMatch(ByteSequence plaintext, byte[] saltBytes,
      byte[] digestBytes, int iterations)
  {
    synchronized (factoryLock)
    {
      try
      {
        final byte[] userDigestBytes =
            encodeWithSalt(plaintext, saltBytes, iterations, factory);
        return Arrays.equals(digestBytes, userDigestBytes);
      }
      catch (Exception e)
      {
        return false;
      }
    }
  }
  private byte[] encodeWithRandomSalt(ByteSequence plaintext, byte[] saltBytes,
      int iterations) throws DirectoryException
  {
    synchronized (factoryLock)
    {
      return encodeWithRandomSalt(plaintext, saltBytes, iterations, random, factory);
    }
  }
  private static byte[] encodeWithRandomSalt(ByteSequence plaintext, byte[] saltBytes,
      int iterations, SecureRandom random, final SecretKeyFactory factory) throws DirectoryException
  {
    random.nextBytes(saltBytes);
    return encodeWithSalt(plaintext, saltBytes, iterations, factory);
  }
  private static DirectoryException cannotEncodePassword(Exception e)
  {
    logger.traceException(e);
    LocalizableMessage message = ERR_PWSCHEME_CANNOT_ENCODE_PASSWORD.get(CLASS_NAME, getExceptionMessage(e));
    return new DirectoryException(DirectoryServer.getServerErrorResultCode(), message, e);
  }
  private static byte[] concatenateHashPlusSalt(byte[] saltBytes, byte[] digestBytes) {
    final byte[] hashPlusSalt = new byte[digestBytes.length + NUM_SALT_BYTES];
    System.arraycopy(digestBytes, 0, hashPlusSalt, 0, digestBytes.length);
    System.arraycopy(saltBytes, 0, hashPlusSalt, digestBytes.length, NUM_SALT_BYTES);
    return hashPlusSalt;
  }
}
opendj3-server-dev/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageScheme.java
@@ -90,7 +90,6 @@
  /** The secure random number generator to use to generate the salt values. */
  private SecureRandom random;
  /**
   * Creates a new instance of this password storage scheme.  Note that no
   * initialization should be performed here, as all initialization should be
@@ -131,8 +130,7 @@
      throws DirectoryException
  {
    byte[] saltBytes      = new byte[NUM_SALT_BYTES];
    byte[] digestBytes = createRandomSaltAndEncode(plaintext, saltBytes);
    // Append the hashed value to the salt and base64-the whole thing.
    byte[] digestBytes = encodeWithRandomSalt(plaintext, saltBytes);
    byte[] hashPlusSalt = concatenateSaltPlusHash(saltBytes, digestBytes);
    return ByteString.valueOf(Base64.encode(hashPlusSalt));
@@ -156,7 +154,6 @@
    try
    {
      String stored = storedPassword.toString();
      byte[] decodedBytes = Base64.decode(stored);
      if (decodedBytes.length != NUM_SALT_BYTES + SHA1_LENGTH)
@@ -167,8 +164,8 @@
      }
      final int saltLength = NUM_SALT_BYTES;
      byte[] saltBytes = new byte[saltLength];
      byte[] digestBytes = new byte[SHA1_LENGTH];
      final byte[] digestBytes = new byte[SHA1_LENGTH];
      final byte[] saltBytes = new byte[saltLength];
      System.arraycopy(decodedBytes, 0, saltBytes, 0, saltLength);
      System.arraycopy(decodedBytes, saltLength, digestBytes, 0, SHA1_LENGTH);
      return encodeAndMatch(plaintextPassword, saltBytes, digestBytes, iterations);
@@ -202,7 +199,7 @@
      throws DirectoryException
  {
    byte[] saltBytes      = new byte[NUM_SALT_BYTES];
    byte[] digestBytes = createRandomSaltAndEncode(plaintext, saltBytes);
    byte[] digestBytes = encodeWithRandomSalt(plaintext, saltBytes);
    // Encode and return the value.
    return ByteString.valueOf(AUTH_PASSWORD_SCHEME_NAME_PKCS5S2 + '$'
        + iterations + ':' + Base64.encode(saltBytes) + '$'
@@ -219,7 +216,7 @@
      int pos = authInfo.indexOf(':');
      if (pos == -1)
      {
        return false;
        throw new Exception();
      }
      int iterations = Integer.parseInt(authInfo.substring(0, pos));
      byte[] saltBytes   = Base64.decode(authInfo.substring(pos + 1));
@@ -277,87 +274,53 @@
   * user password).
   *
   * @param  passwordBytes  The bytes that make up the clear-text password.
   *
   * @return  The encoded password string, including the scheme name in curly
   *          braces.
   *
   * @throws  DirectoryException  If a problem occurs during processing.
   */
  public static String encodeOffline(byte[] passwordBytes)
      throws DirectoryException
  {
    byte[] saltBytes = new byte[NUM_SALT_BYTES];
    byte[] digestBytes;
    try
    {
      SecureRandom.getInstance(SECURE_PRNG_SHA1).nextBytes(saltBytes);
      char[] plaintextChars = Arrays.toString(passwordBytes).toCharArray();
      KeySpec spec = new PBEKeySpec(plaintextChars, saltBytes,iterations,
          SHA1_LENGTH * 8);
      digestBytes = SecretKeyFactory
          .getInstance(MESSAGE_DIGEST_ALGORITHM_PBKDF2)
          .generateSecret(spec).getEncoded();
    }
    catch (Exception e)
    {
      logger.traceException(e);
      LocalizableMessage message = ERR_PWSCHEME_CANNOT_ENCODE_PASSWORD.get(
          CLASS_NAME, getExceptionMessage(e));
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
          message, e);
    }
    // Append the hashed value to the salt and base64-the whole thing.
    byte[] digestBytes = encodeWithRandomSalt(ByteString.wrap(passwordBytes), saltBytes);
    byte[] hashPlusSalt = concatenateSaltPlusHash(saltBytes, digestBytes);
    return '{' + STORAGE_SCHEME_NAME_PKCS5S2 + '}' +
        Base64.encode(hashPlusSalt);
  }
  private boolean encodeAndMatch(ByteSequence plaintext,
                                 byte[] saltBytes, byte[] digestBytes, int iterations)
  private static byte[] encodeWithRandomSalt(ByteString plaintext, byte[] saltBytes)
      throws DirectoryException
  {
    try
    {
      byte[] userDigestBytes = encodeWithSalt(plaintext, saltBytes, iterations);
      return Arrays.equals(digestBytes, userDigestBytes);
      final SecureRandom random = SecureRandom.getInstance(SECURE_PRNG_SHA1);
      final SecretKeyFactory factory = SecretKeyFactory.getInstance(MESSAGE_DIGEST_ALGORITHM_PBKDF2);
      return encodeWithRandomSalt(plaintext, saltBytes, random, factory);
    }
    catch (DirectoryException e)
    {
      throw e;
    }
    catch (Exception e)
    {
      return false;
      throw cannotEncodePassword(e);
    }
  }
  private byte[] createRandomSaltAndEncode(ByteSequence plaintext, byte[] saltBytes) throws DirectoryException {
    synchronized(factoryLock)
  private static byte[] encodeWithSalt(ByteSequence plaintext, byte[] saltBytes,
      int iterations, final SecretKeyFactory factory) throws DirectoryException
    {
      random.nextBytes(saltBytes);
      return encodeWithSalt(plaintext, saltBytes, iterations);
    }
  }
  private byte[] encodeWithSalt(ByteSequence plaintext, byte[] saltBytes, int iterations) throws DirectoryException {
    char[] plaintextChars = null;
    final char[] plaintextChars = plaintext.toString().toCharArray();
    try
    {
      plaintextChars = plaintext.toString().toCharArray();
      KeySpec spec = new PBEKeySpec(
          plaintextChars, saltBytes,
          iterations, SHA1_LENGTH * 8);
      KeySpec spec =
          new PBEKeySpec(plaintextChars, saltBytes, iterations, SHA1_LENGTH * 8);
      return factory.generateSecret(spec).getEncoded();
    }
    catch (Exception e)
    {
      logger.traceException(e);
      LocalizableMessage message = ERR_PWSCHEME_CANNOT_ENCODE_PASSWORD.get(
          CLASS_NAME, getExceptionMessage(e));
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
          message, e);
      throw cannotEncodePassword(e);
    }
    finally
    {
@@ -368,12 +331,52 @@
    }
  }
  private static byte[] concatenateSaltPlusHash(byte[] saltBytes, byte[] digestBytes) {
    byte[] hashPlusSalt = new byte[digestBytes.length + NUM_SALT_BYTES];
  private boolean encodeAndMatch(ByteSequence plaintext, byte[] saltBytes,
      byte[] digestBytes, int iterations)
  {
    synchronized (factoryLock)
    {
      try
      {
        final byte[] userDigestBytes =
            encodeWithSalt(plaintext, saltBytes, iterations, factory);
        return Arrays.equals(digestBytes, userDigestBytes);
      }
      catch (Exception e)
      {
        return false;
      }
    }
  }
  private byte[] encodeWithRandomSalt(ByteSequence plaintext, byte[] saltBytes)
      throws DirectoryException
  {
    synchronized (factoryLock)
    {
      return encodeWithRandomSalt(plaintext, saltBytes, random, factory);
    }
  }
  private static byte[] encodeWithRandomSalt(ByteSequence plaintext, byte[] saltBytes,
      SecureRandom random, final SecretKeyFactory factory) throws DirectoryException
  {
    random.nextBytes(saltBytes);
    return encodeWithSalt(plaintext, saltBytes, iterations, factory);
  }
  private static DirectoryException cannotEncodePassword(Exception e)
  {
    logger.traceException(e);
    LocalizableMessage message = ERR_PWSCHEME_CANNOT_ENCODE_PASSWORD.get(CLASS_NAME, getExceptionMessage(e));
    return new DirectoryException(DirectoryServer.getServerErrorResultCode(), message, e);
  }
  private static byte[] concatenateSaltPlusHash(byte[] saltBytes, byte[] digestBytes) {
    final byte[] hashPlusSalt = new byte[digestBytes.length + NUM_SALT_BYTES];
    System.arraycopy(saltBytes, 0, hashPlusSalt, 0, NUM_SALT_BYTES);
    System.arraycopy(digestBytes, 0, hashPlusSalt, NUM_SALT_BYTES,
        digestBytes.length);
    System.arraycopy(digestBytes, 0, hashPlusSalt, NUM_SALT_BYTES, digestBytes.length);
    return hashPlusSalt;
  }
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/CryptPasswordStorageSchemeTestCase.java
@@ -27,43 +27,26 @@
 */
package org.opends.server.extensions;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.util.ArrayList;
import org.forgerock.opendj.ldap.ByteString;
import org.opends.server.TestCaseUtils;
import org.opends.server.admin.server.AdminTestCaseUtils;
import org.opends.server.admin.std.meta.CryptPasswordStorageSchemeCfgDefn;
import org.opends.server.admin.std.server.CryptPasswordStorageSchemeCfg;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyOperation;
import org.opends.server.core.PasswordPolicy;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.schema.AuthPasswordSyntax;
import org.opends.server.schema.UserPasswordSyntax;
import org.opends.server.types.Attributes;
import org.forgerock.opendj.ldap.ByteString;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
import org.forgerock.opendj.ldap.ModificationType;
import org.forgerock.opendj.ldap.ResultCode;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.opends.server.extensions.PasswordStorageSchemeTestCase.*;
/**
 * A set of test cases for the crypt password storage scheme.
 */
@SuppressWarnings("javadoc")
public class CryptPasswordStorageSchemeTestCase
       extends ExtensionsTestCase
{
  // Names of all the crypt algorithms we want to test.
  private static final String[] names = { "unix", "md5", "sha256", "sha512" };
@@ -81,7 +64,7 @@
   * Ensures that the Directory Server is started before running any of these
   * tests.
   */
  @BeforeClass()
  @BeforeClass
  public void startServer() throws Exception
  {
    TestCaseUtils.startServer();
@@ -99,31 +82,7 @@
  @DataProvider(name = "testPasswords")
  public Object[][] getTestPasswords()
  {
    return new Object[][]
    {
      new Object[] { ByteString.empty() },
      new Object[] { ByteString.valueOf("") },
      new Object[] { ByteString.valueOf("\u0000") },
      new Object[] { ByteString.valueOf("\t") },
      new Object[] { ByteString.valueOf("\n") },
      new Object[] { ByteString.valueOf("\r\n") },
      new Object[] { ByteString.valueOf(" ") },
      new Object[] { ByteString.valueOf("Test1\tTest2\tTest3") },
      new Object[] { ByteString.valueOf("Test1\nTest2\nTest3") },
      new Object[] { ByteString.valueOf("Test1\r\nTest2\r\nTest3") },
      new Object[] { ByteString.valueOf("a") },
      new Object[] { ByteString.valueOf("ab") },
      new Object[] { ByteString.valueOf("abc") },
      new Object[] { ByteString.valueOf("abcd") },
      new Object[] { ByteString.valueOf("abcde") },
      new Object[] { ByteString.valueOf("abcdef") },
      new Object[] { ByteString.valueOf("abcdefg") },
      new Object[] { ByteString.valueOf("abcdefgh") },
      new Object[] { ByteString.valueOf("The Quick Brown Fox Jumps Over " +
                                         "The Lazy Dog") },
      new Object[] { ByteString.valueOf("\u00BFD\u00F3nde est\u00E1 el " +
                                         "ba\u00F1o?") }
    };
    return getTestPasswordsStatic();
  }
@@ -132,7 +91,6 @@
   * provided password, and ensures that the encoded value is correct.
   *
   * @param  plaintext  The plain-text version of the password to encode.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "testPasswords")
@@ -141,94 +99,15 @@
  {
    for (String name : names)
    {
      CryptPasswordStorageScheme scheme = getScheme(name);
      assertNotNull(scheme);
      assertNotNull(scheme.getStorageSchemeName());
      ByteString encodedPassword = scheme.encodePassword(plaintext);
      assertNotNull(encodedPassword);
      assertTrue(scheme.passwordMatches(plaintext, encodedPassword));
      assertFalse(scheme.passwordMatches(plaintext,
                                         ByteString.valueOf("garbage")));
      ByteString schemeEncodedPassword =
           scheme.encodePasswordWithScheme(plaintext);
      String[] pwComponents = UserPasswordSyntax.decodeUserPassword(
                                   schemeEncodedPassword.toString());
      assertNotNull(pwComponents);
      if (scheme.supportsAuthPasswordSyntax())
      {
        assertNotNull(scheme.getAuthPasswordSchemeName());
        ByteString encodedAuthPassword = scheme.encodeAuthPassword(plaintext);
        StringBuilder[] authPWComponents =
             AuthPasswordSyntax.decodeAuthPassword(
                  encodedAuthPassword.toString());
        assertTrue(scheme.authPasswordMatches(plaintext,
                                              authPWComponents[1].toString(),
                                              authPWComponents[2].toString()));
        assertFalse(scheme.authPasswordMatches(plaintext, ",", "foo"));
        assertFalse(scheme.authPasswordMatches(plaintext, "foo", ","));
      }
      else
      {
        try
        {
          scheme.encodeAuthPassword(plaintext);
          throw new Exception("Expected encodedAuthPassword to fail for scheme " +
                              scheme.getStorageSchemeName() +
                              " because it doesn't support auth passwords.");
        }
        catch (DirectoryException de)
        {
          // This was expected.
        }
        assertFalse(scheme.authPasswordMatches(plaintext, "foo", "bar"));
      }
      if (scheme.isReversible())
      {
        assertEquals(scheme.getPlaintextValue(encodedPassword), plaintext);
      }
      else
      {
        try
        {
          scheme.getPlaintextValue(encodedPassword);
          throw new Exception("Expected getPlaintextValue to fail for scheme " +
                              scheme.getStorageSchemeName() +
                              " because it is not reversible.");
        }
        catch (DirectoryException de)
        {
          // This was expected.
      testStorageScheme(plaintext, getScheme(name));
        }
      }
      scheme.isStorageSchemeSecure();
    }
  }
  @DataProvider
  public Object[][] passwordsForBinding()
  {
    return new Object[][]
    {
      // In the case of a clear-text password, these values will be shoved
      // un-excaped into an LDIF file, so make sure they don't include \n
      // or other characters that will cause LDIF parsing errors.
      // We really don't need many test cases here, since that functionality
      // is tested above.
      new Object[] { ByteString.valueOf("a") },
      new Object[] { ByteString.valueOf("abcdefgh") },
      new Object[] { ByteString.valueOf("abcdefghi") },
    };
    return PasswordStorageSchemeTestCase.passwordsForBinding();
  }
@@ -243,88 +122,10 @@
  {
    for (String name: names)
    {
      // Start/clear-out the memory backend
      TestCaseUtils.initializeTestBackend(true);
      setAllowPreencodedPasswords(true);
      CryptPasswordStorageScheme scheme = getScheme(name);
      ByteString schemeEncodedPassword =
          scheme.encodePasswordWithScheme(plainPassword);
      //
      // This code creates a user with the encoded password,
      // and then verifies that they can bind with the raw password.
      //
      Entry userEntry = TestCaseUtils.makeEntry(
          "dn: uid=test.user,o=test",
          "objectClass: top",
          "objectClass: person",
          "objectClass: organizationalPerson",
          "objectClass: inetOrgPerson",
          "uid: test.user",
          "givenName: Test",
          "sn: User",
          "cn: Test User",
          "ds-privilege-name: bypass-acl",
          "userPassword: " + schemeEncodedPassword.toString());
      // Add the entry
      TestCaseUtils.addEntry(userEntry);
      assertTrue(TestCaseUtils.canBind("uid=test.user,o=test",
          plainPassword.toString()),
          "Failed to bind when pre-encoded password = \"" +
              schemeEncodedPassword.toString() + "\" and " +
              "plaintext password = \"" +
              plainPassword.toString() + "\"");
      testSettingEncodedPassword(plainPassword, getScheme(name));
    }
  }
  /**
   * Sets whether or not to allow pre-encoded password values for the
   * current password storage scheme and returns the previous value so that
   * it can be restored.
   *
   * @param allowPreencoded whether or not to allow pre-encoded passwords
   * @return the previous value for the allow preencoded passwords
   */
  private boolean setAllowPreencodedPasswords(boolean allowPreencoded)
          throws Exception
  {
    // This code was borrowed from
    // PasswordPolicyTestCase.testAllowPreEncodedPasswordsAuth
    boolean previousValue = false;
    try {
      DN dn = DN.valueOf("cn=Default Password Policy,cn=Password Policies,cn=config");
      PasswordPolicy p = (PasswordPolicy) DirectoryServer.getAuthenticationPolicy(dn);
      previousValue = p.isAllowPreEncodedPasswords();
      String attr  = "ds-cfg-allow-pre-encoded-passwords";
      ArrayList<Modification> mods = new ArrayList<Modification>();
      mods.add(new Modification(ModificationType.REPLACE,
          Attributes.create(attr, String.valueOf(allowPreencoded))));
      InternalClientConnection conn =
           InternalClientConnection.getRootConnection();
      ModifyOperation modifyOperation = conn.processModify(dn, mods);
      assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
      p = (PasswordPolicy) DirectoryServer.getAuthenticationPolicy(dn);
      assertEquals(p.isAllowPreEncodedPasswords(), allowPreencoded);
    } catch (Exception e) {
      System.err.println("Failed to set ds-cfg-allow-pre-encoded-passwords " +
                         " to " + allowPreencoded);
      e.printStackTrace();
      throw e;
    }
    return previousValue;
  }
  /**
   * Retrieves a set of passwords (plain and variously hashed) that may
   * be used to test the different Unix "crypt" algorithms used by the Crypt
@@ -337,7 +138,6 @@
   *          may be used to test the different algorithms used by the Crypt
   *          password storage scheme.
   */
  @DataProvider(name = "testCryptPasswords")
  public Object[][] getTestCryptPasswords()
         throws Exception
@@ -361,38 +161,7 @@
          String plaintextPassword,
          String encodedPassword) throws Exception
  {
      // Start/clear-out the memory backend
    TestCaseUtils.initializeTestBackend(true);
    boolean allowPreencodedDefault = setAllowPreencodedPasswords(true);
    try {
      Entry userEntry = TestCaseUtils.makeEntry(
       "dn: uid=testCrypt.user,o=test",
       "objectClass: top",
       "objectClass: person",
       "objectClass: organizationalPerson",
       "objectClass: inetOrgPerson",
       "uid: testCrypt.user",
       "givenName: TestCrypt",
       "sn: User",
       "cn: TestCrypt User",
       "userPassword: " + encodedPassword);
      // Add the entry
      TestCaseUtils.addEntry(userEntry);
      assertTrue(TestCaseUtils.canBind("uid=testCrypt.user,o=test",
                  plaintextPassword),
               "Failed to bind when pre-encoded password = \"" +
               encodedPassword + "\" and " +
               "plaintext password = \"" +
               plaintextPassword + "\"" );
    } finally {
      setAllowPreencodedPasswords(allowPreencodedDefault);
    }
    testAuthPasswords("TestCrypt", plaintextPassword, encodedPassword);
  }
  /**
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/PBKDF2PasswordStorageSchemeTestCase.java
@@ -29,11 +29,13 @@
import org.opends.server.admin.std.meta.PBKDF2PasswordStorageSchemeCfgDefn;
import org.opends.server.admin.std.server.PBKDF2PasswordStorageSchemeCfg;
import org.opends.server.api.PasswordStorageScheme;
import org.opends.server.types.DirectoryException;
import org.testng.annotations.DataProvider;
/**
 * A set of test cases for the PBKDF2 password storage scheme.
 */
@SuppressWarnings("javadoc")
public class PBKDF2PasswordStorageSchemeTestCase
       extends PasswordStorageSchemeTestCase
{
@@ -84,4 +86,9 @@
    return scheme;
  }
  @Override
  protected String encodeOffline(final byte[] plaintextBytes) throws DirectoryException
  {
    return PBKDF2PasswordStorageScheme.encodeOffline(plaintextBytes);
  }
}
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageSchemeTestCase.java
@@ -25,17 +25,14 @@
 */
package org.opends.server.extensions;
import org.opends.server.TestCaseUtils;
import org.opends.server.admin.server.AdminTestCaseUtils;
import org.opends.server.admin.std.meta.PKCS5S2PasswordStorageSchemeCfgDefn;
import org.opends.server.admin.std.server.PKCS5S2PasswordStorageSchemeCfg;
import org.opends.server.api.PasswordStorageScheme;
import org.opends.server.types.Entry;
import org.opends.server.types.DirectoryException;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
/**
 * A set of test cases for the PKCS5S2 password storage scheme.
 */
@@ -138,34 +135,13 @@
          String plaintextPassword,
          String encodedPassword) throws Exception
  {
    // Start/clear-out the memory backend
    TestCaseUtils.initializeTestBackend(true);
    boolean allowPreencodedDefault = setAllowPreencodedPasswords(true);
    try {
      Entry userEntry = TestCaseUtils.makeEntry(
       "dn: uid=testPKCS5S2.user,o=test",
       "objectClass: top",
       "objectClass: person",
       "objectClass: organizationalPerson",
       "objectClass: inetOrgPerson",
       "uid: testPKCS5S2.user",
       "givenName: TestPKCS5S2",
       "sn: User",
       "cn: TestPKCS5S2 User",
       "userPassword: " + encodedPassword);
      TestCaseUtils.addEntry(userEntry);
      assertTrue(TestCaseUtils.canBind("uid=testPKCS5S2.user,o=test", plaintextPassword),
               "Failed to bind when pre-encoded password = \"" +
               encodedPassword + "\" and " +
               "plaintext password = \"" +
               plaintextPassword + "\"" );
    } finally {
      setAllowPreencodedPasswords(allowPreencodedDefault);
    testAuthPasswords("TestPKCS5S2", plaintextPassword, encodedPassword);
    }
  @Override
  protected String encodeOffline(final byte[] plaintextBytes) throws DirectoryException
  {
    return PKCS5S2PasswordStorageScheme.encodeOffline(plaintextBytes);
  }
}
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/PasswordStorageSchemeTestCase.java
@@ -26,10 +26,6 @@
 */
package org.opends.server.extensions;
import static org.testng.Assert.*;
import java.util.ArrayList;
import org.opends.server.TestCaseUtils;
@@ -53,18 +49,22 @@
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
/**
 * A set of generic test cases for password storage schemes.
 */
@SuppressWarnings("javadoc")
public abstract class PasswordStorageSchemeTestCase
       extends ExtensionsTestCase
{
  // The configuration entry for this password storage scheme.
  /** The configuration entry for this password storage scheme. */
  protected ConfigEntry configEntry;
  // The string representation of the DN of the configuration entry for this
  // password storage scheme.
  /**
   * The string representation of the DN of the configuration entry for this
   * password storage scheme.
   */
  private String configDNString;
@@ -91,9 +91,8 @@
   * Ensures that the Directory Server is started before running any of these
   * tests.
   */
  @BeforeClass()
  public void startServer()
         throws Exception
  @BeforeClass
  public void startServer() throws Exception
  {
    TestCaseUtils.startServer();
@@ -115,6 +114,11 @@
  @DataProvider(name = "testPasswords")
  public Object[][] getTestPasswords()
  {
    return getTestPasswordsStatic();
  }
  static Object[][] getTestPasswordsStatic()
  {
    return new Object[][]
    {
      new Object[] { ByteString.empty() },
@@ -149,14 +153,18 @@
   * provided password, and ensures that the encoded value is correct.
   *
   * @param  plaintext  The plain-text version of the password to encode.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "testPasswords")
  public void testStorageScheme(ByteString plaintext)
         throws Exception
  {
    PasswordStorageScheme scheme = getScheme();
    testStorageScheme(plaintext, getScheme());
  }
  static void testStorageScheme(ByteString plaintext,
      PasswordStorageScheme<?> scheme) throws Exception
  {
    assertNotNull(scheme);
    assertNotNull(scheme.getStorageSchemeName());
@@ -228,7 +236,7 @@
  @DataProvider
  public Object[][] passwordsForBinding()
  public static Object[][] passwordsForBinding()
  {
    return new Object[][]
    {
@@ -250,21 +258,23 @@
  @Test(dataProvider = "passwordsForBinding")
  public void testSettingEncodedPassword(ByteString plainPassword) throws Exception
  {
    testSettingEncodedPassword(plainPassword, getScheme());
  }
  static void testSettingEncodedPassword(ByteString plainPassword,
      PasswordStorageScheme<?> scheme) throws Exception, DirectoryException
  {
    // Start/clear-out the memory backend
    TestCaseUtils.initializeTestBackend(true);
    boolean allowPreencodedDefault = setAllowPreencodedPasswords(true);
    try {
      PasswordStorageScheme scheme = getScheme();
      ByteString schemeEncodedPassword =
           scheme.encodePasswordWithScheme(plainPassword);
      //
      // This code creates a user with the encoded password,
      // and then verifies that they can bind with the raw password.
      //
      Entry userEntry = TestCaseUtils.makeEntry(
           "dn: uid=test.user,o=test",
           "objectClass: top",
@@ -276,17 +286,16 @@
           "sn: User",
           "cn: Test User",
           "ds-privilege-name: bypass-acl",
           "userPassword: " + schemeEncodedPassword.toString());
           "userPassword: " + schemeEncodedPassword);
      // Add the entry
      TestCaseUtils.addEntry(userEntry);
      assertTrue(TestCaseUtils.canBind("uid=test.user,o=test",
                 plainPassword.toString()),
                 "Failed to bind when pre-encoded password = \"" +
                         schemeEncodedPassword.toString() + "\" and " +
                         schemeEncodedPassword + "\" and " +
                         "plaintext password = \"" +
                         plainPassword.toString() + "\"");
                         plainPassword + "\"");
    } finally {
      setAllowPreencodedPasswords(allowPreencodedDefault);
    }
@@ -301,7 +310,7 @@
   * @param allowPreencoded whether or not to allow pre-encoded passwords
   * @return the previous value for the allow preencoded passwords
   */
  protected boolean setAllowPreencodedPasswords(boolean allowPreencoded)
  protected static boolean setAllowPreencodedPasswords(boolean allowPreencoded)
          throws Exception
  {
    // This code was borrowed from
@@ -335,14 +344,86 @@
    return previousValue;
  }
  protected static void testAuthPasswords(final String upperName,
      String plaintextPassword, String encodedPassword) throws Exception
  {
    // Start/clear-out the memory backend
    TestCaseUtils.initializeTestBackend(true);
    boolean allowPreencodedDefault = setAllowPreencodedPasswords(true);
    try
    {
      final String lowerName =
          Character.toLowerCase(upperName.charAt(0)) + upperName.substring(1);
      Entry userEntry = TestCaseUtils.makeEntry(
          "dn: uid=" + lowerName + ".user,o=test",
          "objectClass: top",
          "objectClass: person",
          "objectClass: organizationalPerson",
          "objectClass: inetOrgPerson",
          "uid: " + lowerName + ".user",
          "givenName: " + upperName,
          "sn: User",
          "cn: " + upperName + " User",
          "userPassword: " + encodedPassword);
      TestCaseUtils.addEntry(userEntry);
      assertTrue(TestCaseUtils.canBind(
          "uid=" + lowerName + ".user,o=test", plaintextPassword),
          "Failed to bind when pre-encoded password = \"" + encodedPassword
          + "\" and " + "plaintext password = \"" + plaintextPassword + "\"");
    }
    finally
    {
      setAllowPreencodedPasswords(allowPreencodedDefault);
    }
  }
  /**
   * Tests the <CODE>encodeOffline</CODE> method.
   *
   * @param plaintext
   *          The plaintext password to use for the test.
   * @throws Exception
   *           If an unexpected problem occurs.
   */
  @Test(dataProvider = "testPasswords")
  public void testEncodeOffline(ByteString plaintext) throws Exception
  {
    PasswordStorageScheme<?> scheme = getScheme();
    String passwordString = encodeOffline(plaintext.toByteArray());
    if (passwordString != null)
    {
      String[] pwComps = UserPasswordSyntax.decodeUserPassword(passwordString);
      ByteString encodedPassword = ByteString.valueOf(pwComps[1]);
      assertTrue(scheme.passwordMatches(plaintext, encodedPassword));
    }
  }
  /**
   * Retrieves an initialized instance of this password storage scheme.
   *
   * @return  An initialized instance of this password storage scheme.
   *
   * @throws  Exception  If an unexpected problem occurs.
   * @throws Exception
   *           If an unexpected problem occurs.
   */
  protected abstract PasswordStorageScheme getScheme()
         throws Exception;
  protected abstract PasswordStorageScheme<?> getScheme() throws Exception;
  /**
   * Encodes the provided plaintext password while offline.
   *
   * @param plaintextBytes
   *          The plaintext password in bytes to use for the test.
   * @throws DirectoryException
   *           If an unexpected problem occurs.
   */
  protected String encodeOffline(byte[] plaintextBytes) throws DirectoryException
  {
    return null;
  }
}
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageSchemeTestCase.java
@@ -26,20 +26,11 @@
 */
package org.opends.server.extensions;
import org.testng.annotations.Test;
import org.opends.server.admin.server.AdminTestCaseUtils;
import org.opends.server.admin.std.meta.SaltedSHA1PasswordStorageSchemeCfgDefn;
import org.opends.server.admin.std.server.SaltedSHA1PasswordStorageSchemeCfg;
import org.opends.server.api.PasswordStorageScheme;
import org.opends.server.schema.UserPasswordSyntax;
import org.forgerock.opendj.ldap.ByteString;
import static org.testng.Assert.*;
import org.opends.server.types.DirectoryException;
/**
 * A set of test cases for the salted SHA-1 password storage scheme.
@@ -61,11 +52,10 @@
   * Retrieves an initialized instance of this password storage scheme.
   *
   * @return  An initialized instance of this password storage scheme.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  protected PasswordStorageScheme getScheme()
         throws Exception
  @Override
  protected PasswordStorageScheme<?> getScheme() throws Exception
  {
    SaltedSHA1PasswordStorageScheme scheme =
         new SaltedSHA1PasswordStorageScheme();
@@ -80,35 +70,11 @@
    return scheme;
  }
  /**
   * Tests the <CODE>encodeOffline</CODE> method.
   *
   * @param  plaintext  The plaintext password to use for the test.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "testPasswords")
  public void testEncodeOffline(ByteString plaintext)
         throws Exception
  /** {@inheritDoc} */
  @Override
  protected String encodeOffline(final byte[] plaintextBytes) throws DirectoryException
  {
    SaltedSHA1PasswordStorageScheme scheme =
         new SaltedSHA1PasswordStorageScheme();
    SaltedSHA1PasswordStorageSchemeCfg configuration =
      AdminTestCaseUtils.getConfiguration(
          SaltedSHA1PasswordStorageSchemeCfgDefn.getInstance(),
          configEntry.getEntry()
          );
    scheme.initializePasswordStorageScheme(configuration);
    String passwordString = SaltedSHA1PasswordStorageScheme.encodeOffline(plaintext.toByteArray());
    String[] pwComps = UserPasswordSyntax.decodeUserPassword(passwordString);
    ByteString encodedPassword = ByteString.valueOf(pwComps[1]);
    assertTrue(scheme.passwordMatches(plaintext, encodedPassword));
    return SaltedSHA1PasswordStorageScheme.encodeOffline(plaintextBytes);
  }
}
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageSchemeTestCase.java
@@ -22,28 +22,21 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2010 ForgeRock AS.
 *      Portions Copyright 2010-2014 ForgeRock AS.
 */
package org.opends.server.extensions;
import static org.testng.Assert.*;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.opends.server.TestCaseUtils;
import org.opends.server.admin.server.AdminTestCaseUtils;
import org.opends.server.admin.std.meta.
            SaltedSHA256PasswordStorageSchemeCfgDefn;
import org.opends.server.admin.std.meta.SaltedSHA256PasswordStorageSchemeCfgDefn;
import org.opends.server.admin.std.server.SaltedSHA256PasswordStorageSchemeCfg;
import org.opends.server.api.PasswordStorageScheme;
import org.opends.server.types.Entry;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
 * A set of test cases for the salted SHA-256 password storage scheme.
 */
@SuppressWarnings("javadoc")
public class SaltedSHA256PasswordStorageSchemeTestCase
       extends PasswordStorageSchemeTestCase
{
@@ -64,8 +57,8 @@
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  protected PasswordStorageScheme getScheme()
         throws Exception
  @Override
  protected PasswordStorageScheme<?> getScheme() throws Exception
  {
    SaltedSHA256PasswordStorageScheme scheme =
         new SaltedSHA256PasswordStorageScheme();
@@ -89,10 +82,8 @@
   * @return  A set of couple (cleartext, encrypted) passwords that
   *          may be used to test the SSHA256 password storage scheme
   */
  @DataProvider(name = "testSSHA256Passwords")
  public Object[][] getTestSSHA256Passwords()
         throws Exception
  public Object[][] getTestSSHA256Passwords() throws Exception
  {
    return new Object[][]
    {
@@ -105,38 +96,7 @@
          String plaintextPassword,
          String encodedPassword) throws Exception
  {
    // Start/clear-out the memory backend
    TestCaseUtils.initializeTestBackend(true);
    boolean allowPreencodedDefault = setAllowPreencodedPasswords(true);
    try {
      Entry userEntry = TestCaseUtils.makeEntry(
       "dn: uid=testSSHA256.user,o=test",
       "objectClass: top",
       "objectClass: person",
       "objectClass: organizationalPerson",
       "objectClass: inetOrgPerson",
       "uid: testSSHA256.user",
       "givenName: TestSSHA256",
       "sn: User",
       "cn: TestSSHA256 User",
       "userPassword: " + encodedPassword);
      // Add the entry
      TestCaseUtils.addEntry(userEntry);
      assertTrue(TestCaseUtils.canBind("uid=testSSHA256.user,o=test",
                  plaintextPassword),
               "Failed to bind when pre-encoded password = \"" +
               encodedPassword + "\" and " +
               "plaintext password = \"" +
               plaintextPassword + "\"" );
    } finally {
      setAllowPreencodedPasswords(allowPreencodedDefault);
    }
    testAuthPasswords("TestSSHA256", plaintextPassword, encodedPassword);
  }
}
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageSchemeTestCase.java
@@ -22,29 +22,21 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2010 ForgeRock AS.
 *      Portions Copyright 2010-2014 ForgeRock AS.
 */
package org.opends.server.extensions;
import static org.testng.Assert.*;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.opends.server.TestCaseUtils;
import org.opends.server.admin.server.AdminTestCaseUtils;
import org.opends.server.admin.std.meta.
            SaltedSHA384PasswordStorageSchemeCfgDefn;
import org.opends.server.admin.std.meta.SaltedSHA384PasswordStorageSchemeCfgDefn;
import org.opends.server.admin.std.server.SaltedSHA384PasswordStorageSchemeCfg;
import org.opends.server.api.PasswordStorageScheme;
import org.opends.server.types.Entry;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
 * A set of test cases for the salted SHA-384 password storage scheme.
 */
@SuppressWarnings("javadoc")
public class SaltedSHA384PasswordStorageSchemeTestCase
       extends PasswordStorageSchemeTestCase
{
@@ -65,8 +57,8 @@
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  protected PasswordStorageScheme getScheme()
         throws Exception
  @Override
  protected PasswordStorageScheme<?> getScheme() throws Exception
  {
    SaltedSHA384PasswordStorageScheme scheme =
         new SaltedSHA384PasswordStorageScheme();
@@ -90,10 +82,8 @@
   * @return  A set of couple (cleartext, encrypted) passwords that
   *          may be used to test the SSHA384 password storage scheme
   */
  @DataProvider(name = "testSSHA384Passwords")
  public Object[][] getTestSSHA384Passwords()
         throws Exception
  public Object[][] getTestSSHA384Passwords() throws Exception
  {
    return new Object[][]
    {
@@ -108,38 +98,7 @@
          String plaintextPassword,
          String encodedPassword) throws Exception
  {
    // Start/clear-out the memory backend
    TestCaseUtils.initializeTestBackend(true);
    boolean allowPreencodedDefault = setAllowPreencodedPasswords(true);
    try {
      Entry userEntry = TestCaseUtils.makeEntry(
       "dn: uid=testSSHA384.user,o=test",
       "objectClass: top",
       "objectClass: person",
       "objectClass: organizationalPerson",
       "objectClass: inetOrgPerson",
       "uid: testSSHA384.user",
       "givenName: TestSSHA384",
       "sn: User",
       "cn: TestSSHA384 User",
       "userPassword: " + encodedPassword);
      // Add the entry
      TestCaseUtils.addEntry(userEntry);
      assertTrue(TestCaseUtils.canBind("uid=testSSHA384.user,o=test",
                  plaintextPassword),
               "Failed to bind when pre-encoded password = \"" +
               encodedPassword + "\" and " +
               "plaintext password = \"" +
               plaintextPassword + "\"" );
    } finally {
      setAllowPreencodedPasswords(allowPreencodedDefault);
    }
    testAuthPasswords("TestSSHA384", plaintextPassword, encodedPassword);
  }
}
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageSchemeTestCase.java
@@ -22,29 +22,22 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2010 ForgeRock AS.
 *      Portions Copyright 2010-2014 ForgeRock AS.
 */
package org.opends.server.extensions;
import static org.testng.Assert.*;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.opends.server.TestCaseUtils;
import org.opends.server.admin.server.AdminTestCaseUtils;
import org.opends.server.admin.std.meta.
            SaltedSHA512PasswordStorageSchemeCfgDefn;
import org.opends.server.admin.std.meta.SaltedSHA512PasswordStorageSchemeCfgDefn;
import org.opends.server.admin.std.server.SaltedSHA512PasswordStorageSchemeCfg;
import org.opends.server.api.PasswordStorageScheme;
import org.opends.server.types.Entry;
import org.opends.server.types.DirectoryException;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
 * A set of test cases for the salted SHA-512 password storage scheme.
 */
@SuppressWarnings("javadoc")
public class SaltedSHA512PasswordStorageSchemeTestCase
       extends PasswordStorageSchemeTestCase
{
@@ -65,8 +58,8 @@
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  protected PasswordStorageScheme getScheme()
         throws Exception
  @Override
  protected PasswordStorageScheme<?> getScheme() throws Exception
  {
    SaltedSHA512PasswordStorageScheme scheme =
         new SaltedSHA512PasswordStorageScheme();
@@ -106,39 +99,13 @@
          String plaintextPassword,
          String encodedPassword) throws Exception
  {
    // Start/clear-out the memory backend
    TestCaseUtils.initializeTestBackend(true);
    boolean allowPreencodedDefault = setAllowPreencodedPasswords(true);
    try {
      Entry userEntry = TestCaseUtils.makeEntry(
       "dn: uid=testSSHA512.user,o=test",
       "objectClass: top",
       "objectClass: person",
       "objectClass: organizationalPerson",
       "objectClass: inetOrgPerson",
       "uid: testSSHA512.user",
       "givenName: TestSSHA512",
       "sn: User",
       "cn: TestSSHA512 User",
       "userPassword: " + encodedPassword);
      // Add the entry
      TestCaseUtils.addEntry(userEntry);
      assertTrue(TestCaseUtils.canBind("uid=testSSHA512.user,o=test",
                  plaintextPassword),
               "Failed to bind when pre-encoded password = \"" +
               encodedPassword + "\" and " +
               "plaintext password = \"" +
               plaintextPassword + "\"" );
    } finally {
      setAllowPreencodedPasswords(allowPreencodedDefault);
    }
    testAuthPasswords("TestSSHA512", plaintextPassword, encodedPassword);
  }
  /** {@inheritDoc} */
  @Override
  protected String encodeOffline(byte[] plaintextBytes) throws DirectoryException
  {
    return SaltedSHA512PasswordStorageScheme.encodeOffline(plaintextBytes);
}
}