From 7fc458b7be71111b4c4a6e91f7b3ed6642b104a1 Mon Sep 17 00:00:00 2001
From: Chris Ridd <chris.ridd@forgerock.com>
Date: Tue, 16 Jul 2013 14:12:20 +0000
Subject: [PATCH] CR-2005 Fix OPENDJ-1036 Cleanup passwords in memory?

---
 opends/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java |   30 +++
 opends/src/server/org/opends/server/extensions/BlowfishPasswordStorageScheme.java     |   19 ++
 opends/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageScheme.java |   29 +++
 opends/src/server/org/opends/server/extensions/CryptPasswordStorageScheme.java        |   58 +++++++-
 opends/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageScheme.java |   29 +++
 opends/src/server/org/opends/server/extensions/TripleDESPasswordStorageScheme.java    |   19 ++
 opends/src/server/org/opends/server/extensions/RC4PasswordStorageScheme.java          |   19 ++
 opends/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java   |   30 +++
 opends/src/server/org/opends/server/extensions/PBKDF2PasswordStorageScheme.java       |   57 ++++++-
 opends/src/server/org/opends/server/extensions/SHA1PasswordStorageScheme.java         |   26 +++
 opends/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java    |   26 +++
 opends/src/server/org/opends/server/extensions/AESPasswordStorageScheme.java          |   20 ++
 opends/src/server/org/opends/server/extensions/MD5PasswordStorageScheme.java          |   30 +++
 13 files changed, 343 insertions(+), 49 deletions(-)

diff --git a/opends/src/server/org/opends/server/extensions/AESPasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/AESPasswordStorageScheme.java
index 2a7326f..e07afbe 100644
--- a/opends/src/server/org/opends/server/extensions/AESPasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/AESPasswordStorageScheme.java
@@ -23,6 +23,7 @@
  *
  *
  *      Copyright 2008 Sun Microsystems, Inc.
+ *      Portions Copyright 2013 ForgeRock, AS
  */
 package org.opends.server.extensions;
 
@@ -37,6 +38,8 @@
 import org.opends.server.types.*;
 import org.opends.server.util.Base64;
 
+import java.util.Arrays;
+
 import static org.opends.messages.ExtensionMessages.*;
 import static org.opends.server.extensions.ExtensionsConstants.*;
 import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -109,10 +112,11 @@
   public ByteString encodePassword(ByteSequence plaintext)
          throws DirectoryException
   {
+    byte[] plaintextBytes = null;
     try
     {
       // TODO: Can we avoid this copy?
-      byte[] plaintextBytes = plaintext.toByteArray();
+      plaintextBytes = plaintext.toByteArray();
       byte[] encodedBytes = cryptoManager.encrypt(CIPHER_TRANSFORMATION_AES,
                                                   KEY_SIZE_AES,
                                                   plaintextBytes);
@@ -130,6 +134,11 @@
       throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                    m, e);
     }
+    finally
+    {
+      if (plaintextBytes != null)
+        Arrays.fill(plaintextBytes, (byte) 0);
+    }
   }
 
 
@@ -145,11 +154,11 @@
     buffer.append('{');
     buffer.append(STORAGE_SCHEME_NAME_AES);
     buffer.append('}');
-
+    byte[] plaintextBytes = null;
     try
     {
       // TODO: Can we avoid this copy?
-      byte[] plaintextBytes = plaintext.toByteArray();
+      plaintextBytes = plaintext.toByteArray();
       byte[] encodedBytes = cryptoManager.encrypt(CIPHER_TRANSFORMATION_AES,
                                                   KEY_SIZE_AES,
                                                   plaintextBytes);
@@ -167,6 +176,11 @@
       throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                    m, e);
     }
+    finally
+    {
+      if (plaintextBytes != null)
+        Arrays.fill(plaintextBytes, (byte) 0);
+    }
 
     return ByteString.valueOf(buffer.toString());
   }
diff --git a/opends/src/server/org/opends/server/extensions/BlowfishPasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/BlowfishPasswordStorageScheme.java
index 889088f..4cfd38b 100644
--- a/opends/src/server/org/opends/server/extensions/BlowfishPasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/BlowfishPasswordStorageScheme.java
@@ -23,6 +23,7 @@
  *
  *
  *      Copyright 2008 Sun Microsystems, Inc.
+ *      Portions Copyright 2013 ForgeRock AS
  */
 package org.opends.server.extensions;
 
@@ -37,6 +38,8 @@
 import org.opends.server.types.*;
 import org.opends.server.util.Base64;
 
+import java.util.Arrays;
+
 import static org.opends.messages.ExtensionMessages.*;
 import static org.opends.server.extensions.ExtensionsConstants.*;
 import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -109,10 +112,11 @@
   public ByteString encodePassword(ByteSequence plaintext)
          throws DirectoryException
   {
+    byte[] plaintextBytes = null;
     try
     {
       // TODO: Can we avoid this copy?
-      byte[] plaintextBytes = plaintext.toByteArray();
+      plaintextBytes = plaintext.toByteArray();
       byte[] encodedBytes =
            cryptoManager.encrypt(CIPHER_TRANSFORMATION_BLOWFISH,
                                  KEY_SIZE_BLOWFISH, plaintextBytes);
@@ -130,6 +134,11 @@
       throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                    m, e);
     }
+    finally
+    {
+      if (plaintextBytes != null)
+        Arrays.fill(plaintextBytes, (byte) 0);
+    }
   }
 
 
@@ -145,11 +154,12 @@
     buffer.append('{');
     buffer.append(STORAGE_SCHEME_NAME_BLOWFISH);
     buffer.append('}');
+    byte[] plaintextBytes = null;
 
     try
     {
       // TODO: Can we avoid this copy?
-      byte[] plaintextBytes = plaintext.toByteArray();
+      plaintextBytes = plaintext.toByteArray();
       byte[] encodedBytes =
            cryptoManager.encrypt(CIPHER_TRANSFORMATION_BLOWFISH,
                                  KEY_SIZE_BLOWFISH, plaintextBytes);
@@ -167,6 +177,11 @@
       throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                    m, e);
     }
+    finally
+    {
+      if (plaintextBytes != null)
+        Arrays.fill(plaintextBytes, (byte) 0);
+    }
 
     return ByteString.valueOf(buffer.toString());
   }
diff --git a/opends/src/server/org/opends/server/extensions/CryptPasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/CryptPasswordStorageScheme.java
index fdfa06e..e7e060c 100644
--- a/opends/src/server/org/opends/server/extensions/CryptPasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/CryptPasswordStorageScheme.java
@@ -31,6 +31,7 @@
 package org.opends.server.extensions;
 
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.ArrayList;
 import java.util.Random;
@@ -131,13 +132,13 @@
   private ByteString unixCryptEncodePassword(ByteSequence plaintext)
          throws DirectoryException
   {
-
+    byte[] plaintextBytes = null;
     byte[] digestBytes;
 
     try
     {
-      // TODO: Can we avoid this copy?
-      byte[] plaintextBytes = plaintext.toByteArray();
+      // TODO: can we avoid this copy?
+      plaintextBytes = plaintext.toByteArray();
       digestBytes = crypt.crypt(plaintextBytes, randomSalt());
     }
     catch (Exception e)
@@ -147,6 +148,11 @@
       throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                    message, e);
     }
+    finally
+    {
+      if (plaintextBytes != null)
+        Arrays.fill(plaintextBytes, (byte) 0);
+    }
 
     return ByteString.wrap(digestBytes);
   }
@@ -190,9 +196,12 @@
   private ByteString sha256CryptEncodePassword(ByteSequence plaintext)
       throws DirectoryException {
     String output;
+    byte[] plaintextBytes = null;
+
     try
     {
-      output = Sha2Crypt.sha256Crypt(plaintext.toByteArray());
+      plaintextBytes = plaintext.toByteArray();
+      output = Sha2Crypt.sha256Crypt(plaintextBytes);
     }
     catch (Exception e)
     {
@@ -201,15 +210,23 @@
       throw new DirectoryException(
           DirectoryServer.getServerErrorResultCode(), message, e);
     }
+    finally
+    {
+      if (plaintextBytes != null)
+        Arrays.fill(plaintextBytes, (byte) 0);
+    }
     return ByteString.valueOf(output);
   }
 
   private ByteString sha512CryptEncodePassword(ByteSequence plaintext)
       throws DirectoryException {
     String output;
+    byte[] plaintextBytes = null;
+
     try
     {
-      output = Sha2Crypt.sha512Crypt(plaintext.toByteArray());
+      plaintextBytes = plaintext.toByteArray();
+      output = Sha2Crypt.sha512Crypt(plaintextBytes);
     }
     catch (Exception e)
     {
@@ -218,6 +235,11 @@
       throw new DirectoryException(
           DirectoryServer.getServerErrorResultCode(), message, e);
     }
+    finally
+    {
+      if (plaintextBytes != null)
+        Arrays.fill(plaintextBytes, (byte) 0);
+    }
     return ByteString.valueOf(output);
   }
 
@@ -273,11 +295,12 @@
                                  ByteSequence storedPassword)
   {
     // TODO: Can we avoid this copy?
-    byte[] plaintextPasswordBytes = plaintextPassword.toByteArray();
+    byte[] plaintextPasswordBytes = null;
 
     ByteString userPWDigestBytes;
     try
     {
+      plaintextPasswordBytes = plaintextPassword.toByteArray();
       // The salt is stored as the first two bytes of the storedPassword
       // value, and crypt.crypt() only looks at the first two bytes, so
       // we can pass it in directly.
@@ -289,6 +312,11 @@
     {
       return false;
     }
+    finally
+    {
+      if (plaintextPasswordBytes != null)
+        Arrays.fill(plaintextPasswordBytes, (byte) 0);
+    }
 
     return userPWDigestBytes.equals(storedPassword);
   }
@@ -311,32 +339,46 @@
 
   private boolean sha256CryptPasswordMatches(ByteSequence plaintextPassword,
       ByteSequence storedPassword) {
+    byte[] plaintextPasswordBytes = null;
     String storedString = storedPassword.toString();
     try
     {
+      plaintextPasswordBytes = plaintextPassword.toByteArray();
       String userString = Sha2Crypt.sha256Crypt(
-          plaintextPassword.toByteArray(), storedString);
+          plaintextPasswordBytes, storedString);
       return userString.equals(storedString);
     }
     catch (Exception e)
     {
       return false;
     }
+    finally
+    {
+      if (plaintextPasswordBytes != null)
+        Arrays.fill(plaintextPasswordBytes, (byte) 0);
+    }
   }
 
   private boolean sha512CryptPasswordMatches(ByteSequence plaintextPassword,
       ByteSequence storedPassword) {
+    byte[] plaintextPasswordBytes = null;
     String storedString = storedPassword.toString();
     try
     {
+      plaintextPasswordBytes = plaintextPassword.toByteArray();
       String userString = Sha2Crypt.sha512Crypt(
-          plaintextPassword.toByteArray(), storedString);
+          plaintextPasswordBytes, storedString);
       return userString.equals(storedString);
     }
     catch (Exception e)
     {
       return false;
     }
+    finally
+    {
+      if (plaintextPasswordBytes != null)
+        Arrays.fill(plaintextPasswordBytes, (byte) 0);
+    }
   }
 
   /**
diff --git a/opends/src/server/org/opends/server/extensions/MD5PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/MD5PasswordStorageScheme.java
index aae5497..0f37d1e 100644
--- a/opends/src/server/org/opends/server/extensions/MD5PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/MD5PasswordStorageScheme.java
@@ -23,12 +23,14 @@
  *
  *
  *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Portions Copyright 2013 ForgeRock AS
  */
 package org.opends.server.extensions;
 
 
 
 import java.security.MessageDigest;
+import java.util.Arrays;
 
 import org.opends.messages.Message;
 import org.opends.server.admin.std.server.MD5PasswordStorageSchemeCfg;
@@ -141,13 +143,14 @@
          throws DirectoryException
   {
     byte[] digestBytes;
+    byte[] plaintextBytes = null;
 
     synchronized (digestLock)
     {
       try
       {
         // TODO: Can we avoid this copy?
-        byte[] plaintextBytes = plaintext.toByteArray();
+        plaintextBytes = plaintext.toByteArray();
         digestBytes = messageDigest.digest(plaintextBytes);
       }
       catch (Exception e)
@@ -162,6 +165,11 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        if (plaintextBytes != null)
+          Arrays.fill(plaintextBytes, (byte) 0);
+      }
     }
 
     return ByteString.valueOf(Base64.encode(digestBytes));
@@ -181,14 +189,15 @@
     buffer.append(STORAGE_SCHEME_NAME_MD5);
     buffer.append('}');
 
-    // TODO: Can we avoid this copy?
-    byte[] plaintextBytes = plaintext.toByteArray();
+    byte[] plaintextBytes = null;
     byte[] digestBytes;
 
     synchronized (digestLock)
     {
       try
       {
+        // TODO: Can we avoid this copy?
+        plaintextBytes = plaintext.toByteArray();
         digestBytes = messageDigest.digest(plaintextBytes);
       }
       catch (Exception e)
@@ -203,6 +212,11 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        if (plaintextBytes != null)
+          Arrays.fill(plaintextBytes, (byte) 0);
+      }
     }
 
     buffer.append(Base64.encode(digestBytes));
@@ -220,14 +234,15 @@
   public boolean passwordMatches(ByteSequence plaintextPassword,
                                  ByteSequence storedPassword)
   {
-    // TODO: Can we avoid this copy?
-    byte[] plaintextPasswordBytes = plaintextPassword.toByteArray();
+    byte[] plaintextPasswordBytes = null;
     ByteString userPWDigestBytes;
 
     synchronized (digestLock)
     {
       try
       {
+        // TODO: Can we avoid this copy?
+        plaintextPasswordBytes = plaintextPassword.toByteArray();
         userPWDigestBytes =
             ByteString.wrap(messageDigest.digest(plaintextPasswordBytes));
       }
@@ -240,6 +255,11 @@
 
         return false;
       }
+      finally
+      {
+        if (plaintextPasswordBytes != null)
+          Arrays.fill(plaintextPasswordBytes, (byte) 0);
+      }
     }
 
     ByteString storedPWDigestBytes;
diff --git a/opends/src/server/org/opends/server/extensions/PBKDF2PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/PBKDF2PasswordStorageScheme.java
index 37dbf7c..6c7b98a 100644
--- a/opends/src/server/org/opends/server/extensions/PBKDF2PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/PBKDF2PasswordStorageScheme.java
@@ -177,9 +177,10 @@
   public ByteString encodePassword(ByteSequence plaintext)
          throws DirectoryException
   {
-    byte[] saltBytes     = new byte[NUM_SALT_BYTES];
+    byte[] saltBytes      = new byte[NUM_SALT_BYTES];
     byte[] digestBytes;
-    int    iterations    = config.getPBKDF2Iterations();
+    char[] plaintextChars = null;
+    int    iterations     = config.getPBKDF2Iterations();
 
     synchronized(factoryLock)
     {
@@ -187,7 +188,8 @@
       {
         random.nextBytes(saltBytes);
 
-        KeySpec spec = new PBEKeySpec(plaintext.toString().toCharArray(),
+        plaintextChars = plaintext.toString().toCharArray();
+        KeySpec spec = new PBEKeySpec(plaintextChars,
             saltBytes, iterations, SHA1_LENGTH * 8);
         digestBytes = factory.generateSecret(spec).getEncoded();
       }
@@ -203,6 +205,11 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        if (plaintextChars != null)
+          Arrays.fill(plaintextChars, '0');
+      }
     }
     // Append the salt to the hashed value and base64-the whole thing.
     byte[] hashPlusSalt = new byte[digestBytes.length + NUM_SALT_BYTES];
@@ -304,13 +311,15 @@
                      saltLength);
 
     byte[] userDigestBytes;
+    char[] plaintextChars = null;
 
     synchronized (factoryLock)
     {
       try
       {
+        plaintextChars = plaintextPassword.toString().toCharArray();
         KeySpec spec = new PBEKeySpec(
-            plaintextPassword.toString().toCharArray(), saltBytes,
+            plaintextChars, saltBytes,
             iterations, SHA1_LENGTH * 8);
         userDigestBytes = factory.generateSecret(spec).getEncoded();
       }
@@ -323,6 +332,11 @@
 
         return false;
       }
+      finally
+      {
+        if (plaintextChars != null)
+          Arrays.fill(plaintextChars, '0');
+      }
     }
 
     return Arrays.equals(digestBytes, userDigestBytes);
@@ -360,9 +374,10 @@
   public ByteString encodeAuthPassword(ByteSequence plaintext)
          throws DirectoryException
   {
-    byte[] saltBytes     = new byte[NUM_SALT_BYTES];
+    byte[] saltBytes      = new byte[NUM_SALT_BYTES];
     byte[] digestBytes;
-    int    iterations    = config.getPBKDF2Iterations();
+    char[] plaintextChars = null;
+    int    iterations     = config.getPBKDF2Iterations();
 
     synchronized(factoryLock)
     {
@@ -370,8 +385,9 @@
       {
         random.nextBytes(saltBytes);
 
+        plaintextChars = plaintext.toString().toCharArray();
         KeySpec spec = new PBEKeySpec(
-            plaintext.toString().toCharArray(), saltBytes,
+            plaintextChars, saltBytes,
             iterations, SHA1_LENGTH * 8);
         digestBytes = factory.generateSecret(spec).getEncoded();
       }
@@ -387,6 +403,11 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        if (plaintextChars != null)
+          Arrays.fill(plaintextChars, '0');
+      }
     }
     // Encode and return the value.
     StringBuilder authPWValue = new StringBuilder();
@@ -446,13 +467,15 @@
                      saltBytes.length);
 
     byte[] userDigestBytes;
+    char[] plaintextChars = null;
 
     synchronized (factoryLock)
     {
       try
       {
+        plaintextChars = plaintextPassword.toString().toCharArray();
         KeySpec spec = new PBEKeySpec(
-            plaintextPassword.toString().toCharArray(), saltBytes,
+            plaintextChars, saltBytes,
             iterations, SHA1_LENGTH * 8);
         userDigestBytes = factory.generateSecret(spec).getEncoded();
       }
@@ -465,6 +488,11 @@
 
         return false;
       }
+      finally
+      {
+        if (plaintextChars != null)
+          Arrays.fill(plaintextChars, '0');
+      }
     }
 
     return Arrays.equals(digestBytes, userDigestBytes);
@@ -540,16 +568,18 @@
   public static String encodeOffline(byte[] passwordBytes)
          throws DirectoryException
   {
-    byte[] saltBytes     = new byte[NUM_SALT_BYTES];
+    byte[] saltBytes      = new byte[NUM_SALT_BYTES];
     byte[] digestBytes;
-    int    iterations    = 10000;
+    char[] plaintextChars = null;
+    int    iterations     = 10000;
 
     try
     {
       SecureRandom.getInstance(SECURE_PRNG_SHA1).nextBytes(saltBytes);
 
+      plaintextChars = passwordBytes.toString().toCharArray();
       KeySpec spec = new PBEKeySpec(
-          passwordBytes.toString().toCharArray(), saltBytes,
+          plaintextChars, saltBytes,
           iterations, SHA1_LENGTH * 8);
       digestBytes = SecretKeyFactory
           .getInstance(MESSAGE_DIGEST_ALGORITHM_PBKDF2)
@@ -567,6 +597,11 @@
       throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
           message, e);
     }
+    finally
+    {
+      if (plaintextChars != null)
+        Arrays.fill(plaintextChars, '0');
+    }
 
     // Append the salt to the hashed value and base64-the whole thing.
     byte[] hashPlusSalt = new byte[digestBytes.length + NUM_SALT_BYTES];
diff --git a/opends/src/server/org/opends/server/extensions/RC4PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/RC4PasswordStorageScheme.java
index 06f963c..6e513a0 100644
--- a/opends/src/server/org/opends/server/extensions/RC4PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/RC4PasswordStorageScheme.java
@@ -23,6 +23,7 @@
  *
  *
  *      Copyright 2008 Sun Microsystems, Inc.
+ *      Portions Copyright 2013 ForgeRock AS
  */
 package org.opends.server.extensions;
 
@@ -37,6 +38,8 @@
 import org.opends.server.types.*;
 import org.opends.server.util.Base64;
 
+import java.util.Arrays;
+
 import static org.opends.messages.ExtensionMessages.*;
 import static org.opends.server.extensions.ExtensionsConstants.*;
 import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -108,10 +111,11 @@
   public ByteString encodePassword(ByteSequence plaintext)
          throws DirectoryException
   {
+    byte[] plaintextBytes = null;
     try
     {
       // TODO: Can we avoid this copy?
-      byte[] plaintextBytes = plaintext.toByteArray();
+      plaintextBytes = plaintext.toByteArray();
       byte[] encodedBytes = cryptoManager.encrypt(CIPHER_TRANSFORMATION_RC4,
                                                   KEY_SIZE_RC4,
                                                   plaintextBytes);
@@ -129,6 +133,11 @@
       throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                    m, e);
     }
+    finally
+    {
+      if (plaintextBytes != null)
+        Arrays.fill(plaintextBytes, (byte) 0);
+    }
   }
 
 
@@ -144,11 +153,12 @@
     buffer.append('{');
     buffer.append(STORAGE_SCHEME_NAME_RC4);
     buffer.append('}');
+    byte[] plaintextBytes = null;
 
     try
     {
       // TODO: Can we avoid this copy?
-      byte[] plaintextBytes = plaintext.toByteArray();
+      plaintextBytes = plaintext.toByteArray();
       byte[] encodedBytes = cryptoManager.encrypt(CIPHER_TRANSFORMATION_RC4,
                                                   KEY_SIZE_RC4,
                                                   plaintextBytes);
@@ -166,6 +176,11 @@
       throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                    m, e);
     }
+    finally
+    {
+      if (plaintextBytes != null)
+        Arrays.fill(plaintextBytes, (byte) 0);
+    }
 
     return ByteString.valueOf(buffer.toString());
   }
diff --git a/opends/src/server/org/opends/server/extensions/SHA1PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/SHA1PasswordStorageScheme.java
index 569c24d..69ec9c9 100644
--- a/opends/src/server/org/opends/server/extensions/SHA1PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/SHA1PasswordStorageScheme.java
@@ -23,12 +23,14 @@
  *
  *
  *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Portions Copyright 2013 ForgeRock AS.
  */
 package org.opends.server.extensions;
 
 
 
 import java.security.MessageDigest;
+import java.util.Arrays;
 
 import org.opends.messages.Message;
 import org.opends.server.admin.std.server.SHA1PasswordStorageSchemeCfg;
@@ -140,13 +142,14 @@
          throws DirectoryException
   {
     byte[] digestBytes;
+    byte[] plaintextBytes = null;
 
     synchronized (digestLock)
     {
       try
       {
         // TODO: Can we avoid this copy?
-        byte[] plaintextBytes = plaintext.toByteArray();
+        plaintextBytes = plaintext.toByteArray();
         digestBytes = messageDigest.digest(plaintextBytes);
       }
       catch (Exception e)
@@ -161,6 +164,11 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        if (plaintextBytes != null)
+          Arrays.fill(plaintextBytes, (byte) 0);
+      }
     }
 
     return ByteString.valueOf(Base64.encode(digestBytes));
@@ -181,13 +189,14 @@
     buffer.append('}');
 
     // TODO: Can we avoid this copy?
-    byte[] plaintextBytes = plaintext.toByteArray();
+    byte[] plaintextBytes = null;
     byte[] digestBytes;
 
     synchronized (digestLock)
     {
       try
       {
+        plaintextBytes = plaintext.toByteArray();
         digestBytes = messageDigest.digest(plaintextBytes);
       }
       catch (Exception e)
@@ -202,6 +211,11 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        if (plaintextBytes != null)
+          Arrays.fill(plaintextBytes, (byte) 0);
+      }
     }
 
     buffer.append(Base64.encode(digestBytes));
@@ -219,13 +233,14 @@
                                  ByteSequence storedPassword)
   {
     // TODO: Can we avoid this copy?
-    byte[] plaintextPasswordBytes = plaintextPassword.toByteArray();
+    byte[] plaintextPasswordBytes = null;
     ByteString userPWDigestBytes;
 
     synchronized (digestLock)
     {
       try
       {
+        plaintextPasswordBytes = plaintextPassword.toByteArray();
         userPWDigestBytes =
             ByteString.wrap(messageDigest.digest(plaintextPasswordBytes));
       }
@@ -238,6 +253,11 @@
 
         return false;
       }
+      finally
+      {
+        if (plaintextPasswordBytes != null)
+          Arrays.fill(plaintextPasswordBytes, (byte) 0);
+      }
     }
 
     ByteString storedPWDigestBytes;
diff --git a/opends/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java
index 38194f4..baafd41 100644
--- a/opends/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageScheme.java
@@ -23,6 +23,7 @@
  *
  *
  *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Portions Copyright 2013 ForgeRock AS
  */
 package org.opends.server.extensions;
 
@@ -189,6 +190,10 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
     // Append the salt to the hashed value and base64-the whole thing.
@@ -247,6 +252,10 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
     // Append the salt to the hashed value and base64-the whole thing.
@@ -320,6 +329,10 @@
 
         return false;
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
     return Arrays.equals(digestBytes, userDigestBytes);
@@ -389,6 +402,10 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
 
@@ -438,8 +455,15 @@
 
     synchronized (digestLock)
     {
-      return Arrays.equals(digestBytes,
+      try
+      {
+        return Arrays.equals(digestBytes,
                                 messageDigest.digest(plainPlusSaltBytes));
+      }
+      finally
+      {
+        Arrays.fill(plainPlusSaltBytes, (byte) 0);
+      }
     }
   }
 
diff --git a/opends/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java
index 49bd575..d3278e1 100644
--- a/opends/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/SaltedSHA1PasswordStorageScheme.java
@@ -23,7 +23,7 @@
  *
  *
  *      Copyright 2006-2010 Sun Microsystems, Inc.
- *      Portions Copyright 2010 ForgeRock AS.
+ *      Portions Copyright 2010-2013 ForgeRock AS.
  */
 package org.opends.server.extensions;
 
@@ -190,6 +190,10 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
     // Append the salt to the hashed value and base64-the whole thing.
@@ -248,6 +252,10 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
     // Append the salt to the hashed value and base64-the whole thing.
@@ -330,6 +338,10 @@
 
         return false;
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
     return Arrays.equals(digestBytes, userDigestBytes);
@@ -399,6 +411,10 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
 
@@ -448,8 +464,15 @@
 
     synchronized (digestLock)
     {
-      return Arrays.equals(digestBytes,
-                                messageDigest.digest(plainPlusSaltBytes));
+      try
+      {
+        return Arrays.equals(digestBytes,
+                messageDigest.digest(plainPlusSaltBytes));
+      }
+      finally
+      {
+        Arrays.fill(plainPlusSaltBytes, (byte) 0);
+      }
     }
   }
 
@@ -550,6 +573,7 @@
     System.arraycopy(digestBytes, 0, digestPlusSalt, 0, digestBytes.length);
     System.arraycopy(saltBytes, 0, digestPlusSalt, digestBytes.length,
                      NUM_SALT_BYTES);
+    Arrays.fill(passwordPlusSalt, (byte) 0);
 
     return "{" + STORAGE_SCHEME_NAME_SALTED_SHA_1 + "}" +
            Base64.encode(digestPlusSalt);
diff --git a/opends/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageScheme.java
index b51327d..385da73 100644
--- a/opends/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/SaltedSHA256PasswordStorageScheme.java
@@ -23,7 +23,7 @@
  *
  *
  *      Copyright 2006-2008 Sun Microsystems, Inc.
- *      Portions Copyright 2010 ForgeRock AS.
+ *      Portions Copyright 2010-2013 ForgeRock AS.
  */
 package org.opends.server.extensions;
 
@@ -192,6 +192,10 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
     // Append the salt to the hashed value and base64-the whole thing.
@@ -250,6 +254,10 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
     // Append the salt to the hashed value and base64-the whole thing.
@@ -334,6 +342,10 @@
 
         return false;
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
     return Arrays.equals(digestBytes, userDigestBytes);
@@ -403,6 +415,10 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
 
@@ -452,8 +468,15 @@
 
     synchronized (digestLock)
     {
-      return Arrays.equals(digestBytes,
-                                messageDigest.digest(plainPlusSaltBytes));
+      try
+      {
+        return Arrays.equals(digestBytes,
+                                  messageDigest.digest(plainPlusSaltBytes));
+      }
+      finally
+      {
+        Arrays.fill(plainPlusSaltBytes, (byte) 0);
+      }
     }
   }
 
diff --git a/opends/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageScheme.java
index ebbb8bd..d854ae8 100644
--- a/opends/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/SaltedSHA384PasswordStorageScheme.java
@@ -23,7 +23,7 @@
  *
  *
  *      Copyright 2006-2008 Sun Microsystems, Inc.
- *      Portions Copyright 2010 ForgeRock AS.
+ *      Portions Copyright 2010-2013 ForgeRock AS.
  */
 package org.opends.server.extensions;
 
@@ -193,6 +193,10 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
     // Append the salt to the hashed value and base64-the whole thing.
@@ -251,6 +255,10 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
     // Append the salt to the hashed value and base64-the whole thing.
@@ -335,6 +343,10 @@
 
         return false;
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
     return Arrays.equals(digestBytes, userDigestBytes);
@@ -404,6 +416,10 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
 
@@ -453,8 +469,15 @@
 
     synchronized (digestLock)
     {
-      return Arrays.equals(digestBytes,
-                                messageDigest.digest(plainPlusSaltBytes));
+      try
+      {
+        return Arrays.equals(digestBytes,
+                                  messageDigest.digest(plainPlusSaltBytes));
+      }
+      finally
+      {
+        Arrays.fill(plainPlusSaltBytes, (byte) 0);
+      }
     }
   }
 
diff --git a/opends/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java
index 8e553a9..e3d5460 100644
--- a/opends/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/SaltedSHA512PasswordStorageScheme.java
@@ -23,7 +23,7 @@
  *
  *
  *      Copyright 2006-2008 Sun Microsystems, Inc.
- *      Portions Copyright 2010 ForgeRock AS.
+ *      Portions Copyright 2010-2013 ForgeRock AS.
  */
 package org.opends.server.extensions;
 
@@ -192,6 +192,10 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
     // Append the salt to the hashed value and base64-the whole thing.
@@ -250,6 +254,10 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
     // Append the salt to the hashed value and base64-the whole thing.
@@ -334,6 +342,10 @@
 
         return false;
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
     return Arrays.equals(digestBytes, userDigestBytes);
@@ -403,6 +415,10 @@
         throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                      message, e);
       }
+      finally
+      {
+        Arrays.fill(plainPlusSalt, (byte) 0);
+      }
     }
 
 
@@ -452,8 +468,15 @@
 
     synchronized (digestLock)
     {
-      return Arrays.equals(digestBytes,
-                                messageDigest.digest(plainPlusSaltBytes));
+      try
+      {
+        return Arrays.equals(digestBytes,
+                                  messageDigest.digest(plainPlusSaltBytes));
+      }
+      finally
+      {
+        Arrays.fill(plainPlusSaltBytes, (byte) 0);
+      }
     }
   }
 
@@ -555,6 +578,7 @@
     System.arraycopy(digestBytes, 0, digestPlusSalt, 0, digestBytes.length);
     System.arraycopy(saltBytes, 0, digestPlusSalt, digestBytes.length,
                      NUM_SALT_BYTES);
+    Arrays.fill(passwordPlusSalt, (byte) 0);
 
     return "{" + STORAGE_SCHEME_NAME_SALTED_SHA_512 + "}" +
            Base64.encode(digestPlusSalt);
diff --git a/opends/src/server/org/opends/server/extensions/TripleDESPasswordStorageScheme.java b/opends/src/server/org/opends/server/extensions/TripleDESPasswordStorageScheme.java
index 61a94e4..bc85618 100644
--- a/opends/src/server/org/opends/server/extensions/TripleDESPasswordStorageScheme.java
+++ b/opends/src/server/org/opends/server/extensions/TripleDESPasswordStorageScheme.java
@@ -23,6 +23,7 @@
  *
  *
  *      Copyright 2008 Sun Microsystems, Inc.
+ *      Portions Copyright 2013 ForgeRock AS.
  */
 package org.opends.server.extensions;
 
@@ -37,6 +38,8 @@
 import org.opends.server.types.*;
 import org.opends.server.util.Base64;
 
+import java.util.Arrays;
+
 import static org.opends.messages.ExtensionMessages.*;
 import static org.opends.server.extensions.ExtensionsConstants.*;
 import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -109,10 +112,11 @@
   public ByteString encodePassword(ByteSequence plaintext)
          throws DirectoryException
   {
+    byte[] plaintextBytes = null;
     try
     {
       // TODO: Can we avoid this copy?
-      byte[] plaintextBytes = plaintext.toByteArray();
+      plaintextBytes = plaintext.toByteArray();
       byte[] encodedBytes = cryptoManager.encrypt(CIPHER_TRANSFORMATION_3DES,
                                                   KEY_SIZE_3DES,
                                                   plaintextBytes);
@@ -130,6 +134,11 @@
       throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                    m, e);
     }
+    finally
+    {
+      if (plaintextBytes != null)
+        Arrays.fill(plaintextBytes, (byte) 0);
+    }
   }
 
 
@@ -145,11 +154,12 @@
     buffer.append('{');
     buffer.append(STORAGE_SCHEME_NAME_3DES);
     buffer.append('}');
+    byte[] plaintextBytes = null;
 
     try
     {
       // TODO: Can we avoid this copy?
-      byte[] plaintextBytes = plaintext.toByteArray();
+      plaintextBytes = plaintext.toByteArray();
       byte[] encodedBytes = cryptoManager.encrypt(CIPHER_TRANSFORMATION_3DES,
                                                   KEY_SIZE_3DES,
                                                   plaintextBytes);
@@ -167,6 +177,11 @@
       throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                    m, e);
     }
+    finally
+    {
+      if (plaintextBytes != null)
+        Arrays.fill(plaintextBytes, (byte) 0);
+    }
 
     return ByteString.valueOf(buffer.toString());
   }

--
Gitblit v1.10.0