From 5da9b6a8c2e1a0014d589cb2143614a9fab73c15 Mon Sep 17 00:00:00 2001
From: Chris Ridd <chris.ridd@forgerock.com>
Date: Mon, 22 Jul 2013 13:10:15 +0000
Subject: [PATCH] CR-2009 Fix OPENDJ-1036 Cleanup passwords in memory?

---
 opendj-sdk/opends/src/server/org/opends/server/extensions/CryptPasswordStorageScheme.java |    4 ++--
 opendj-sdk/opends/src/server/org/opends/server/util/BSDMD5Crypt.java                      |   48 +++++++++++++++++++++++-------------------------
 2 files changed, 25 insertions(+), 27 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/CryptPasswordStorageScheme.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/CryptPasswordStorageScheme.java
index e7e060c..c395693 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/CryptPasswordStorageScheme.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/CryptPasswordStorageScheme.java
@@ -181,7 +181,7 @@
     String output;
     try
     {
-      output = BSDMD5Crypt.crypt(plaintext.toString());
+      output = BSDMD5Crypt.crypt(plaintext);
     }
     catch (Exception e)
     {
@@ -327,7 +327,7 @@
     String storedString = storedPassword.toString();
     try
     {
-      String userString   = BSDMD5Crypt.crypt(plaintextPassword.toString(),
+      String userString   = BSDMD5Crypt.crypt(plaintextPassword,
         storedString);
       return userString.equals(storedString);
     }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/BSDMD5Crypt.java b/opendj-sdk/opends/src/server/org/opends/server/util/BSDMD5Crypt.java
index a0582f9..c262ddb 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/util/BSDMD5Crypt.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/BSDMD5Crypt.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- * Copyright 2010 ForgeRock AS
+ * Copyright 2010-2013 ForgeRock AS
  *
  * BSD-compatible md5 password crypt
  * Ported to Java from C based on crypt-md5.c by Poul-Henning Kamp,
@@ -36,9 +36,13 @@
  */
 package org.opends.server.util;
 
+import org.opends.server.types.ByteSequence;
+import org.opends.server.types.ByteString;
+
 import java.security.MessageDigest;
 import java.security.SecureRandom;
 import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
 
 /**
  * BSD MD5 Crypt algorithm, ported from C.
@@ -62,19 +66,10 @@
       value >>= 6;
     }
 
-    return (output.toString());
+    return output.toString();
   }
 
-  /* Clear bytes, equivalent of memset */
-  static private void clearBytes(byte bytes[])
-  {
-    for (int i = 0; i < bytes.length; i++)
-    {
-      bytes[i] = 0;
-    }
-  }
-
-  /**
+    /**
    * Encode the supplied password in BSD MD5 crypt form, using
    * a random salt.
    *
@@ -85,7 +80,7 @@
    * @throws NoSuchAlgorithmException If the MD5 algorithm is not supported.
    *
    */
-  static public String crypt(String password)
+  static public String crypt(ByteSequence password)
           throws NoSuchAlgorithmException
   {
     SecureRandom randomGenerator = new SecureRandom();
@@ -115,11 +110,12 @@
    * @throws NoSuchAlgorithmException If the MD5 algorithm is not supported.
    *
    */
-  static public String crypt(String password, String salt)
+  static public String crypt(ByteSequence password, String salt)
           throws NoSuchAlgorithmException
   {
     MessageDigest ctx, ctx1;
     byte digest1[], digest[];
+    byte[] plaintextBytes = password.toByteArray();
 
     /* First skip the magic string */
     if (salt.startsWith(magic))
@@ -142,7 +138,7 @@
     ctx = MessageDigest.getInstance("MD5");
 
     /* The password first, since that is what is most unknown */
-    ctx.update(password.getBytes());
+    ctx.update(plaintextBytes);
 
     /* Then our magic string */
     ctx.update(magic.getBytes());
@@ -152,9 +148,9 @@
 
     /* Then just as many characters of the MD5(password,salt,password) */
     ctx1 = MessageDigest.getInstance("MD5");
-    ctx1.update(password.getBytes());
+    ctx1.update(plaintextBytes);
     ctx1.update(salt.getBytes());
-    ctx1.update(password.getBytes());
+    ctx1.update(plaintextBytes);
     digest1 = ctx1.digest();
 
 
@@ -164,7 +160,7 @@
     }
 
     /* Don't leave anything around in vm they could use. */
-    clearBytes(digest1);
+    Arrays.fill(digest1, (byte) 0);
 
     /* Then something really weird... */
     for (int i = password.length(); i != 0; i >>= 1)
@@ -174,7 +170,7 @@
         ctx.update(digest1[0]);
       } else
       {
-        ctx.update(password.getBytes()[0]);
+        ctx.update(plaintextBytes[0]);
       }
     }
 
@@ -197,7 +193,7 @@
 
       if ((i & 1) != 0)
       {
-        ctx1.update(password.getBytes());
+        ctx1.update(plaintextBytes);
       } else
       {
         ctx1.update(digest);
@@ -208,14 +204,14 @@
       }
       if ((i % 7) != 0)
       {
-        ctx1.update(password.getBytes());
+        ctx1.update(plaintextBytes);
       }
       if ((i & 1) != 0)
       {
         ctx1.update(digest);
       } else
       {
-        ctx1.update(password.getBytes());
+        ctx1.update(plaintextBytes);
       }
       digest = ctx1.digest();
     }
@@ -241,7 +237,8 @@
     output.append(intTo64(l, 2));
 
     /* Don't leave anything around in vm they could use. */
-    clearBytes(digest);
+    Arrays.fill(digest, (byte) 0);
+    Arrays.fill(plaintextBytes, (byte) 0);
     ctx = null;
     ctx1 = null;
 
@@ -276,10 +273,11 @@
     {
       if (argv.length == 2)
       {
-        System.out.println(BSDMD5Crypt.crypt(argv[0], argv[1]));
+        System.out.println(BSDMD5Crypt.crypt(ByteString.valueOf(argv[0]),
+                argv[1]));
       } else
       {
-        System.out.println(BSDMD5Crypt.crypt(argv[0]));
+        System.out.println(BSDMD5Crypt.crypt(ByteString.valueOf(argv[0])));
       }
     } catch (Exception e)
     {

--
Gitblit v1.10.0