From a9021d3388e4471f938287b5f3d960fdbaf94325 Mon Sep 17 00:00:00 2001
From: Chris Ridd <chris.ridd@forgerock.com>
Date: Mon, 16 Jun 2014 10:36:34 +0000
Subject: [PATCH] Forward port fix OPENDJ-1451: Match non-default salt sizes in SMD5 passwords

---
 opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageSchemeTestCase.java |   31 +++++++++++++++++++++++++++++++
 opendj3-server-dev/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java                                 |   26 +++++++++++++++++---------
 2 files changed, 48 insertions(+), 9 deletions(-)

diff --git a/opendj3-server-dev/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java b/opendj3-server-dev/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java
index 82c6080..7fa254e 100644
--- a/opendj3-server-dev/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java
+++ b/opendj3-server-dev/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java
@@ -80,6 +80,8 @@
    */
   private static final int NUM_SALT_BYTES = 8;
 
+  // The number of bytes MD5 algorithm produces
+  private static final int MD5_LENGTH = 16;
 
 
   // The message digest that will actually be used to generate the MD5 hashes.
@@ -266,16 +268,22 @@
   {
     // Base64-decode the stored value and take the last 8 bytes as the salt.
     byte[] saltBytes = new byte[NUM_SALT_BYTES];
-    byte[] digestBytes;
+    byte[] digestBytes = new byte[MD5_LENGTH];
+    int saltLength = 0;
     try
     {
       byte[] decodedBytes = Base64.decode(storedPassword.toString());
 
-      int digestLength = decodedBytes.length - NUM_SALT_BYTES;
-      digestBytes = new byte[digestLength];
-      System.arraycopy(decodedBytes, 0, digestBytes, 0, digestLength);
-      System.arraycopy(decodedBytes, digestLength, saltBytes, 0,
-                       NUM_SALT_BYTES);
+      saltLength = decodedBytes.length - MD5_LENGTH;
+      if (saltLength <= 0)
+      {
+        logger.error(ERR_PWSCHEME_INVALID_BASE64_DECODED_STORED_PASSWORD, storedPassword);
+        return false;
+      }
+      saltBytes = new byte[saltLength];
+      System.arraycopy(decodedBytes, 0, digestBytes, 0, MD5_LENGTH);
+      System.arraycopy(decodedBytes, MD5_LENGTH, saltBytes, 0,
+                       saltLength);
     }
     catch (Exception e)
     {
@@ -287,10 +295,10 @@
 
     // Use the salt to generate a digest based on the provided plain-text value.
     int plainBytesLength = plaintextPassword.length();
-    byte[] plainPlusSalt = new byte[plainBytesLength + NUM_SALT_BYTES];
+    byte[] plainPlusSalt = new byte[plainBytesLength + saltLength];
     plaintextPassword.copyTo(plainPlusSalt);
-    System.arraycopy(saltBytes, 0,plainPlusSalt, plainBytesLength,
-                     NUM_SALT_BYTES);
+    System.arraycopy(saltBytes, 0, plainPlusSalt, plainBytesLength,
+                     saltLength);
 
     byte[] userDigestBytes;
 
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageSchemeTestCase.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageSchemeTestCase.java
index 2886ecf..fe182ed 100644
--- a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageSchemeTestCase.java
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageSchemeTestCase.java
@@ -22,16 +22,22 @@
  *
  *
  *      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.SaltedMD5PasswordStorageSchemeCfgDefn;
 import org.opends.server.admin.std.server.SaltedMD5PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
+import org.opends.server.schema.UserPasswordSyntax;
+import org.forgerock.opendj.ldap.ByteString;
 
+import static org.testng.Assert.*;
 
 
 /**
@@ -72,5 +78,30 @@
     scheme.initializePasswordStorageScheme(configuration);
     return scheme;
   }
+
+
+
+  /**
+   * Tests matching with a different salt size.
+   *
+   * @throws  Exception  If an unexpected problem occurs.
+   */
+  @Test
+  public void testDifferentSaltSize()
+    throws Exception {
+    SaltedMD5PasswordStorageScheme scheme =
+      new SaltedMD5PasswordStorageScheme();
+
+    SaltedMD5PasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+        SaltedMD5PasswordStorageSchemeCfgDefn.getInstance(),
+        configEntry.getEntry()
+      );
+
+    scheme.initializePasswordStorageScheme(configuration);
+    // The stored value has a 12 byte salt instead of the default 8
+    assertTrue(scheme.passwordMatches(ByteString.valueOf("password"),
+      ByteString.valueOf("so5s1vK3oEi4uL/oVY3bqs5LRlKjgMN+u4A4bw==")));
+  }
 }
 

--
Gitblit v1.10.0