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

Jean-Noel Rouvignac
11.47.2014 84271e9c4d5ee9c50bb4158c6e00d6dcc7fdb939
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
1013 ■■■■■ changed files
opends/src/server/org/opends/server/extensions/PBKDF2PasswordStorageScheme.java 204 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageScheme.java 140 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/CryptPasswordStorageSchemeTestCase.java 264 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PBKDF2PasswordStorageSchemeTestCase.java 6 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageSchemeTestCase.java 38 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PasswordStorageSchemeTestCase.java 135 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageSchemeTestCase.java 49 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageSchemeTestCase.java 55 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageSchemeTestCase.java 59 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageSchemeTestCase.java 63 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/PBKDF2PasswordStorageScheme.java
@@ -91,7 +91,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
@@ -155,13 +154,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));
  }
@@ -184,8 +178,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();
@@ -224,46 +218,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)
      {
        if (debugEnabled())
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }
        return false;
      }
      finally
      {
        if (plaintextChars != null)
        {
          Arrays.fill(plaintextChars, '0');
        }
      }
    }
  }
  /** {@inheritDoc} */
  @Override
  public boolean supportsAuthPasswordSyntax()
@@ -285,7 +239,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 + '$'
@@ -293,44 +247,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)
      {
        if (debugEnabled())
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }
        Message 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,
@@ -402,10 +318,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)
@@ -414,45 +328,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)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      throw cannotEncodePassword(e);
    }
      }
      Message 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
    {
@@ -463,4 +378,57 @@
    }
  }
  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)
  {
    if (debugEnabled())
    {
      TRACER.debugCaught(DebugLogLevel.ERROR, e);
    }
    Message 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;
  }
}
opends/src/server/org/opends/server/extensions/PKCS5S2PasswordStorageScheme.java
@@ -89,7 +89,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
@@ -130,8 +129,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));
@@ -155,7 +153,6 @@
    try
    {
      String stored = storedPassword.toString();
      byte[] decodedBytes = Base64.decode(stored);
      if (decodedBytes.length != NUM_SALT_BYTES + SHA1_LENGTH)
@@ -168,8 +165,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);
@@ -208,7 +205,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) + '$'
@@ -225,7 +222,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));
@@ -286,94 +283,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)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      Message 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)
    {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      Message message = ERR_PWSCHEME_CANNOT_ENCODE_PASSWORD.get(
          CLASS_NAME, getExceptionMessage(e));
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
          message, e);
      throw cannotEncodePassword(e);
    }
    finally
    {
@@ -384,12 +340,56 @@
    }
  }
  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)
  {
    if (debugEnabled())
    {
      TRACER.debugCaught(DebugLogLevel.ERROR, e);
    }
    Message 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;
  }
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/CryptPasswordStorageSchemeTestCase.java
@@ -22,56 +22,31 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2010-2013 ForgeRock AS.
 *      Portions Copyright 2010-2014 ForgeRock AS.
 *      Portions Copyright 2012 Dariusz Janny <dariusz.janny@gmail.com>
 */
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.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.config.ConfigEntry;
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.opends.server.types.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.opends.server.types.ModificationType;
import org.opends.server.types.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
{
  // The configuration entry for this password storage scheme.
  private ConfigEntry configEntry;
  // The string representation of the DN of the configuration entry for this
  // password storage scheme.
  private static final String configDNString =
          "cn=Crypt,cn=Password Storage Schemes,cn=config";
  // Names of all the crypt algorithms we want to test.
  private static final String[] names = { "unix", "md5", "sha256", "sha512" };
@@ -82,7 +57,6 @@
  public CryptPasswordStorageSchemeTestCase()
  {
    super();
    this.configEntry    = null;
  }
@@ -90,13 +64,10 @@
   * 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();
    configEntry = DirectoryServer.getConfigEntry(DN.decode(configDNString));
  }
@@ -111,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();
  }
@@ -144,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")
@@ -153,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();
  }
@@ -255,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.decode("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
@@ -373,38 +162,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);
  }
  /**
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PBKDF2PasswordStorageSchemeTestCase.java
@@ -29,6 +29,7 @@
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;
/**
@@ -85,4 +86,9 @@
    return scheme;
  }
  @Override
  protected String encodeOffline(final byte[] plaintextBytes) throws DirectoryException
  {
    return PBKDF2PasswordStorageScheme.encodeOffline(plaintextBytes);
  }
}
opends/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);
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PasswordStorageSchemeTestCase.java
@@ -22,14 +22,10 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2010-2011 ForgeRock AS.
 *      Portions Copyright 2010-2014 ForgeRock AS.
 */
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;
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageSchemeTestCase.java
@@ -22,23 +22,15 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2014 ForgeRock AS.
 */
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.opends.server.types.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.
@@ -60,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();
@@ -79,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);
  }
}
opends/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,6 +57,7 @@
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Override
  protected PasswordStorageScheme getScheme()
         throws Exception
  {
@@ -89,10 +83,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 +97,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);
  }
}
opends/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);
  }
}
opends/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);
}
}