From 0822ab47c5257481e39fd7fd7757246052672cce 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?

---
 opendj-sdk/opends/src/server/org/opends/server/extensions/CryptPasswordStorageScheme.java |   58 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 50 insertions(+), 8 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 fdfa06e..e7e060c 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
@@ -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);
+    }
   }
 
   /**

--
Gitblit v1.10.0