From bef34ff8af56487e6c60462d1870ab6dff138d7a Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Mon, 10 Sep 2007 00:56:52 +0000
Subject: [PATCH] Add support for password storage schemes using AES, 3DES, RC4, and Blowfish. The AES, RC4, and Blowfish implementations all use 128-bit ciphers, and the 3DES implementation uses a 168-bit cipher.

---
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/BlowfishPasswordStorageSchemeTestCase.java  |   75 ++
 opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/BlowfishPasswordStorageSchemeConfiguration.xml                   |   63 +
 opendj-sdk/opends/src/messages/messages/extension.properties                                                                  |    5 
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/TripleDESPasswordStorageSchemeTestCase.java |   76 ++
 opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/RC4PasswordStorageSchemeConfiguration.xml                        |   63 +
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/RC4PasswordStorageSchemeTestCase.java       |   75 ++
 opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/TripleDESPasswordStorageSchemeConfiguration.xml                  |   63 +
 opendj-sdk/opends/src/server/org/opends/server/extensions/BlowfishPasswordStorageScheme.java                                  |  310 +++++++++
 opendj-sdk/opends/src/server/org/opends/server/extensions/TripleDESPasswordStorageScheme.java                                 |  310 +++++++++
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/AESPasswordStorageSchemeTestCase.java       |   75 ++
 opendj-sdk/opends/src/server/org/opends/server/extensions/RC4PasswordStorageScheme.java                                       |  310 +++++++++
 opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/AESPasswordStorageSchemeConfiguration.xml                        |   63 +
 opendj-sdk/opends/src/server/org/opends/server/extensions/ExtensionsConstants.java                                            |   98 ++
 opendj-sdk/opends/tests/unit-tests-testng/resource/config-changes.ldif                                                        |   36 +
 opendj-sdk/opends/src/server/org/opends/server/extensions/AESPasswordStorageScheme.java                                       |  310 +++++++++
 opendj-sdk/opends/resource/admin/abbreviations.xsl                                                                            |    1 
 opendj-sdk/opends/resource/schema/02-config.ldif                                                                              |   14 
 17 files changed, 1,946 insertions(+), 1 deletions(-)

diff --git a/opendj-sdk/opends/resource/admin/abbreviations.xsl b/opendj-sdk/opends/resource/admin/abbreviations.xsl
index def5a86..b8653d7 100644
--- a/opendj-sdk/opends/resource/admin/abbreviations.xsl
+++ b/opendj-sdk/opends/resource/admin/abbreviations.xsl
@@ -51,6 +51,7 @@
               or $value = 'fifo' or $value = 'vlv' or $value = 'uuid'
               or $value = 'md5' or $value = 'sha1' or $value = 'sha256'
               or $value = 'sha384' or $value = 'sha512' or $value = 'tls'
+              or $value = 'des' or $value = 'aes' or $value = 'rc4'
              "/>
   </xsl:template>
 </xsl:stylesheet>
diff --git a/opendj-sdk/opends/resource/schema/02-config.ldif b/opendj-sdk/opends/resource/schema/02-config.ldif
index 145aeae..5eafa48 100644
--- a/opendj-sdk/opends/resource/schema/02-config.ldif
+++ b/opendj-sdk/opends/resource/schema/02-config.ldif
@@ -2492,6 +2492,20 @@
   NAME 'ds-cfg-ldif-connection-handler' SUP ds-cfg-connection-handler
   MUST ( ds-cfg-ldif-directory $ ds-cfg-poll-interval )
   X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.169
+  NAME 'ds-cfg-triple-des-password-storage-scheme'
+  SUP ds-cfg-password-storage-scheme STRUCTURAL
+  X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.170
+  NAME 'ds-cfg-aes-password-storage-scheme' SUP ds-cfg-password-storage-scheme
+  STRUCTURAL X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.171
+  NAME 'ds-cfg-rc4-password-storage-scheme' SUP ds-cfg-password-storage-scheme
+  STRUCTURAL X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.172
+  NAME 'ds-cfg-blowfish-password-storage-scheme'
+  SUP ds-cfg-password-storage-scheme STRUCTURAL
+  X-ORIGIN 'OpenDS Directory Server' )
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.173
   NAME 'ds-cfg-entry-cache-monitor-provider' SUP ds-cfg-monitor-provider
   STRUCTURAL X-ORIGIN 'OpenDS Directory Server' )
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/AESPasswordStorageSchemeConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/AESPasswordStorageSchemeConfiguration.xml
new file mode 100644
index 0000000..e738bfa
--- /dev/null
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/AESPasswordStorageSchemeConfiguration.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+! CDDL HEADER START
+!
+! The contents of this file are subject to the terms of the
+! Common Development and Distribution License, Version 1.0 only
+! (the "License").  You may not use this file except in compliance
+! with the License.
+!
+! You can obtain a copy of the license at
+! trunk/opends/resource/legal-notices/OpenDS.LICENSE
+! or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+! See the License for the specific language governing permissions
+! and limitations under the License.
+!
+! When distributing Covered Code, include this CDDL HEADER in each
+! file and include the License file at
+! trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+! add the following below this CDDL HEADER, with the fields enclosed
+! by brackets "[]" replaced with your own identifying information:
+!      Portions Copyright [yyyy] [name of copyright owner]
+!
+! CDDL HEADER END
+!
+!
+!      Portions Copyright 2007 Sun Microsystems, Inc.
+! -->
+
+<adm:managed-object
+  name="aes-password-storage-scheme"
+  plural-name="aes-password-storage-schemes"
+  package="org.opends.server.admin.std"
+  extends="password-storage-scheme"
+  xmlns:adm="http://www.opends.org/admin"
+  xmlns:ldap="http://www.opends.org/admin-ldap">
+
+  <adm:synopsis>
+    The <adm:user-friendly-name /> provides a mechanism for encoding user
+    passwords using the AES reversible encryption mechanism.  This
+    implementation contains only an implementation for the user password syntax,
+    with a storage scheme name of "AES".
+  </adm:synopsis>
+
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:oid>1.3.6.1.4.1.26027.1.2.170</ldap:oid>
+      <ldap:name>ds-cfg-aes-password-storage-scheme</ldap:name>
+      <ldap:superior>ds-cfg-password-storage-scheme</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+
+  <adm:property-override name="scheme-class">
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>
+          org.opends.server.extensions.AESPasswordStorageScheme
+        </adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+  </adm:property-override>
+
+</adm:managed-object>
+
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/BlowfishPasswordStorageSchemeConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/BlowfishPasswordStorageSchemeConfiguration.xml
new file mode 100644
index 0000000..126d0fc
--- /dev/null
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/BlowfishPasswordStorageSchemeConfiguration.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+! CDDL HEADER START
+!
+! The contents of this file are subject to the terms of the
+! Common Development and Distribution License, Version 1.0 only
+! (the "License").  You may not use this file except in compliance
+! with the License.
+!
+! You can obtain a copy of the license at
+! trunk/opends/resource/legal-notices/OpenDS.LICENSE
+! or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+! See the License for the specific language governing permissions
+! and limitations under the License.
+!
+! When distributing Covered Code, include this CDDL HEADER in each
+! file and include the License file at
+! trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+! add the following below this CDDL HEADER, with the fields enclosed
+! by brackets "[]" replaced with your own identifying information:
+!      Portions Copyright [yyyy] [name of copyright owner]
+!
+! CDDL HEADER END
+!
+!
+!      Portions Copyright 2007 Sun Microsystems, Inc.
+! -->
+
+<adm:managed-object
+  name="blowfish-password-storage-scheme"
+  plural-name="blowfish-password-storage-schemes"
+  package="org.opends.server.admin.std"
+  extends="password-storage-scheme"
+  xmlns:adm="http://www.opends.org/admin"
+  xmlns:ldap="http://www.opends.org/admin-ldap">
+
+  <adm:synopsis>
+    The <adm:user-friendly-name /> provides a mechanism for encoding user
+    passwords using the Blowfish reversible encryption mechanism.  This
+    implementation contains only an implementation for the user password syntax,
+    with a storage scheme name of "BLOWFISH".
+  </adm:synopsis>
+
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:oid>1.3.6.1.4.1.26027.1.2.172</ldap:oid>
+      <ldap:name>ds-cfg-blowfish-password-storage-scheme</ldap:name>
+      <ldap:superior>ds-cfg-password-storage-scheme</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+
+  <adm:property-override name="scheme-class">
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>
+          org.opends.server.extensions.BlowfishPasswordStorageScheme
+        </adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+  </adm:property-override>
+
+</adm:managed-object>
+
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/RC4PasswordStorageSchemeConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/RC4PasswordStorageSchemeConfiguration.xml
new file mode 100644
index 0000000..824b35b
--- /dev/null
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/RC4PasswordStorageSchemeConfiguration.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+! CDDL HEADER START
+!
+! The contents of this file are subject to the terms of the
+! Common Development and Distribution License, Version 1.0 only
+! (the "License").  You may not use this file except in compliance
+! with the License.
+!
+! You can obtain a copy of the license at
+! trunk/opends/resource/legal-notices/OpenDS.LICENSE
+! or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+! See the License for the specific language governing permissions
+! and limitations under the License.
+!
+! When distributing Covered Code, include this CDDL HEADER in each
+! file and include the License file at
+! trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+! add the following below this CDDL HEADER, with the fields enclosed
+! by brackets "[]" replaced with your own identifying information:
+!      Portions Copyright [yyyy] [name of copyright owner]
+!
+! CDDL HEADER END
+!
+!
+!      Portions Copyright 2007 Sun Microsystems, Inc.
+! -->
+
+<adm:managed-object
+  name="rc4-password-storage-scheme"
+  plural-name="rc4-password-storage-schemes"
+  package="org.opends.server.admin.std"
+  extends="password-storage-scheme"
+  xmlns:adm="http://www.opends.org/admin"
+  xmlns:ldap="http://www.opends.org/admin-ldap">
+
+  <adm:synopsis>
+    The <adm:user-friendly-name /> provides a mechanism for encoding user
+    passwords using the RC4 reversible encryption mechanism.  This
+    implementation contains only an implementation for the user password syntax,
+    with a storage scheme name of "RC4".
+  </adm:synopsis>
+
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:oid>1.3.6.1.4.1.26027.1.2.171</ldap:oid>
+      <ldap:name>ds-cfg-rc4-password-storage-scheme</ldap:name>
+      <ldap:superior>ds-cfg-password-storage-scheme</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+
+  <adm:property-override name="scheme-class">
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>
+          org.opends.server.extensions.RC4PasswordStorageScheme
+        </adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+  </adm:property-override>
+
+</adm:managed-object>
+
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/TripleDESPasswordStorageSchemeConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/TripleDESPasswordStorageSchemeConfiguration.xml
new file mode 100644
index 0000000..d23057d
--- /dev/null
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/TripleDESPasswordStorageSchemeConfiguration.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+! CDDL HEADER START
+!
+! The contents of this file are subject to the terms of the
+! Common Development and Distribution License, Version 1.0 only
+! (the "License").  You may not use this file except in compliance
+! with the License.
+!
+! You can obtain a copy of the license at
+! trunk/opends/resource/legal-notices/OpenDS.LICENSE
+! or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+! See the License for the specific language governing permissions
+! and limitations under the License.
+!
+! When distributing Covered Code, include this CDDL HEADER in each
+! file and include the License file at
+! trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+! add the following below this CDDL HEADER, with the fields enclosed
+! by brackets "[]" replaced with your own identifying information:
+!      Portions Copyright [yyyy] [name of copyright owner]
+!
+! CDDL HEADER END
+!
+!
+!      Portions Copyright 2007 Sun Microsystems, Inc.
+! -->
+
+<adm:managed-object
+  name="triple-des-password-storage-scheme"
+  plural-name="triple-des-password-storage-schemes"
+  package="org.opends.server.admin.std"
+  extends="password-storage-scheme"
+  xmlns:adm="http://www.opends.org/admin"
+  xmlns:ldap="http://www.opends.org/admin-ldap">
+
+  <adm:synopsis>
+    The <adm:user-friendly-name /> provides a mechanism for encoding user
+    passwords using the triple-DES (DES/EDE) reversible encryption mechanism.
+    This implementation contains only an implementation for the user password
+    syntax, with a storage scheme name of "3DES".
+  </adm:synopsis>
+
+  <adm:profile name="ldap">
+    <ldap:object-class>
+      <ldap:oid>1.3.6.1.4.1.26027.1.2.169</ldap:oid>
+      <ldap:name>ds-cfg-triple-des-password-storage-scheme</ldap:name>
+      <ldap:superior>ds-cfg-password-storage-scheme</ldap:superior>
+    </ldap:object-class>
+  </adm:profile>
+
+  <adm:property-override name="scheme-class">
+    <adm:default-behavior>
+      <adm:defined>
+        <adm:value>
+          org.opends.server.extensions.TripleDESPasswordStorageScheme
+        </adm:value>
+      </adm:defined>
+    </adm:default-behavior>
+  </adm:property-override>
+
+</adm:managed-object>
+
diff --git a/opendj-sdk/opends/src/messages/messages/extension.properties b/opendj-sdk/opends/src/messages/messages/extension.properties
index dece0b6..dfb31a3 100644
--- a/opendj-sdk/opends/src/messages/messages/extension.properties
+++ b/opendj-sdk/opends/src/messages/messages/extension.properties
@@ -1585,4 +1585,7 @@
 SEVERE_ERR_SMTP_ASNH_CANNOT_SEND_MESSAGE_558=An error occurred while \
  attempting to send an account status notification message for notification \
  type %s for user entry %s:  %s
-
+SEVERE_ERR_PWSCHEME_CANNOT_ENCRYPT_559=An error occurred while trying to \
+ encrypt a value using password storage scheme %s:  %s
+SEVERE_ERR_PWSCHEME_CANNOT_DECRYPT_560=An error occurred while trying to \
+ decrypt a value using password storage scheme %s:  %s
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/AESPasswordStorageScheme.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/AESPasswordStorageScheme.java
new file mode 100644
index 0000000..183f0bc
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/AESPasswordStorageScheme.java
@@ -0,0 +1,310 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+
+
+import java.util.Arrays;
+
+import org.opends.messages.Message;
+import org.opends.server.admin.std.server.AESPasswordStorageSchemeCfg;
+import org.opends.server.api.PasswordStorageScheme;
+import org.opends.server.config.ConfigException;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.ByteStringFactory;
+import org.opends.server.types.CryptoManager;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.ResultCode;
+import org.opends.server.util.Base64;
+
+import static org.opends.messages.ExtensionMessages.*;
+import static org.opends.server.extensions.ExtensionsConstants.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.util.StaticUtils.*;
+
+
+
+/**
+ * This class defines a Directory Server password storage scheme that will
+ * encode values using the AES reversible encryption algorithm.  This
+ * implementation supports only the user password syntax and not the auth
+ * password syntax.
+ */
+public class AESPasswordStorageScheme
+       extends PasswordStorageScheme<AESPasswordStorageSchemeCfg>
+{
+  /**
+   * The tracer object for the debug logger.
+   */
+  private static final DebugTracer TRACER = getTracer();
+
+
+
+  // The reference to the Directory Server crypto manager that we will use to
+  // handle the encryption/decryption.
+  private CryptoManager cryptoManager;
+
+
+
+  /**
+   * Creates a new instance of this password storage scheme.  Note that no
+   * initialization should be performed here, as all initialization should be
+   * done in the {@code initializePasswordStorageScheme} method.
+   */
+  public AESPasswordStorageScheme()
+  {
+    super();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public void initializePasswordStorageScheme(
+                   AESPasswordStorageSchemeCfg configuration)
+         throws ConfigException, InitializationException
+  {
+    cryptoManager = DirectoryServer.getCryptoManager();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public String getStorageSchemeName()
+  {
+    return STORAGE_SCHEME_NAME_AES;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString encodePassword(ByteString plaintext)
+         throws DirectoryException
+  {
+    try
+    {
+      byte[] encodedBytes = cryptoManager.encrypt(CIPHER_TRANSFORMATION_AES,
+                                                  KEY_SIZE_AES,
+                                                  plaintext.value());
+      return ByteStringFactory.create(Base64.encode(encodedBytes));
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      Message m = ERR_PWSCHEME_CANNOT_ENCRYPT.get(STORAGE_SCHEME_NAME_AES,
+                                                  getExceptionMessage(e));
+      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+                                   m, e);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString encodePasswordWithScheme(ByteString plaintext)
+         throws DirectoryException
+  {
+    StringBuilder buffer = new StringBuilder();
+    buffer.append('{');
+    buffer.append(STORAGE_SCHEME_NAME_AES);
+    buffer.append('}');
+
+    try
+    {
+      byte[] encodedBytes = cryptoManager.encrypt(CIPHER_TRANSFORMATION_AES,
+                                                  KEY_SIZE_AES,
+                                                  plaintext.value());
+      buffer.append(Base64.encode(encodedBytes));
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      Message m = ERR_PWSCHEME_CANNOT_ENCRYPT.get(STORAGE_SCHEME_NAME_AES,
+                                                  getExceptionMessage(e));
+      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+                                   m, e);
+    }
+
+    return ByteStringFactory.create(buffer.toString());
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean passwordMatches(ByteString plaintextPassword,
+                                 ByteString storedPassword)
+  {
+    try
+    {
+      byte[] decryptedPassword =
+           cryptoManager.decrypt(Base64.decode(storedPassword.stringValue()));
+      return Arrays.equals(plaintextPassword.value(), decryptedPassword);
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      return false;
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean isReversible()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString getPlaintextValue(ByteString storedPassword)
+         throws DirectoryException
+  {
+    try
+    {
+      byte[] decryptedPassword =
+           cryptoManager.decrypt(Base64.decode(storedPassword.stringValue()));
+      return ByteStringFactory.create(decryptedPassword);
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      Message m = ERR_PWSCHEME_CANNOT_DECRYPT.get(STORAGE_SCHEME_NAME_AES,
+                                                  getExceptionMessage(e));
+      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+                                   m, e);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean supportsAuthPasswordSyntax()
+  {
+    // This storage scheme does not support the authentication password syntax.
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString encodeAuthPassword(ByteString plaintext)
+         throws DirectoryException
+  {
+    Message message =
+        ERR_PWSCHEME_DOES_NOT_SUPPORT_AUTH_PASSWORD.get(getStorageSchemeName());
+    throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean authPasswordMatches(ByteString plaintextPassword,
+                                     String authInfo, String authValue)
+  {
+    // This storage scheme does not support the authentication password syntax.
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString getAuthPasswordPlaintextValue(String authInfo,
+                                                  String authValue)
+         throws DirectoryException
+  {
+    Message message =
+        ERR_PWSCHEME_DOES_NOT_SUPPORT_AUTH_PASSWORD.get(getStorageSchemeName());
+    throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean isStorageSchemeSecure()
+  {
+    // This password storage scheme should be considered secure.
+    return true;
+  }
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/BlowfishPasswordStorageScheme.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/BlowfishPasswordStorageScheme.java
new file mode 100644
index 0000000..909668c
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/BlowfishPasswordStorageScheme.java
@@ -0,0 +1,310 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+
+
+import java.util.Arrays;
+
+import org.opends.messages.Message;
+import org.opends.server.admin.std.server.BlowfishPasswordStorageSchemeCfg;
+import org.opends.server.api.PasswordStorageScheme;
+import org.opends.server.config.ConfigException;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.ByteStringFactory;
+import org.opends.server.types.CryptoManager;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.ResultCode;
+import org.opends.server.util.Base64;
+
+import static org.opends.messages.ExtensionMessages.*;
+import static org.opends.server.extensions.ExtensionsConstants.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.util.StaticUtils.*;
+
+
+
+/**
+ * This class defines a Directory Server password storage scheme that will
+ * encode values using the Blowfish reversible encryption algorithm.  This
+ * implementation supports only the user password syntax and not the auth
+ * password syntax.
+ */
+public class BlowfishPasswordStorageScheme
+       extends PasswordStorageScheme<BlowfishPasswordStorageSchemeCfg>
+{
+  /**
+   * The tracer object for the debug logger.
+   */
+  private static final DebugTracer TRACER = getTracer();
+
+
+
+  // The reference to the Directory Server crypto manager that we will use to
+  // handle the encryption/decryption.
+  private CryptoManager cryptoManager;
+
+
+
+  /**
+   * Creates a new instance of this password storage scheme.  Note that no
+   * initialization should be performed here, as all initialization should be
+   * done in the {@code initializePasswordStorageScheme} method.
+   */
+  public BlowfishPasswordStorageScheme()
+  {
+    super();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public void initializePasswordStorageScheme(
+                   BlowfishPasswordStorageSchemeCfg configuration)
+         throws ConfigException, InitializationException
+  {
+    cryptoManager = DirectoryServer.getCryptoManager();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public String getStorageSchemeName()
+  {
+    return STORAGE_SCHEME_NAME_BLOWFISH;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString encodePassword(ByteString plaintext)
+         throws DirectoryException
+  {
+    try
+    {
+      byte[] encodedBytes =
+           cryptoManager.encrypt(CIPHER_TRANSFORMATION_BLOWFISH,
+                                 KEY_SIZE_BLOWFISH, plaintext.value());
+      return ByteStringFactory.create(Base64.encode(encodedBytes));
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      Message m = ERR_PWSCHEME_CANNOT_ENCRYPT.get(STORAGE_SCHEME_NAME_BLOWFISH,
+                                                  getExceptionMessage(e));
+      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+                                   m, e);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString encodePasswordWithScheme(ByteString plaintext)
+         throws DirectoryException
+  {
+    StringBuilder buffer = new StringBuilder();
+    buffer.append('{');
+    buffer.append(STORAGE_SCHEME_NAME_BLOWFISH);
+    buffer.append('}');
+
+    try
+    {
+      byte[] encodedBytes =
+           cryptoManager.encrypt(CIPHER_TRANSFORMATION_BLOWFISH,
+                                 KEY_SIZE_BLOWFISH, plaintext.value());
+      buffer.append(Base64.encode(encodedBytes));
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      Message m = ERR_PWSCHEME_CANNOT_ENCRYPT.get(STORAGE_SCHEME_NAME_BLOWFISH,
+                                                  getExceptionMessage(e));
+      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+                                   m, e);
+    }
+
+    return ByteStringFactory.create(buffer.toString());
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean passwordMatches(ByteString plaintextPassword,
+                                 ByteString storedPassword)
+  {
+    try
+    {
+      byte[] decryptedPassword =
+           cryptoManager.decrypt(Base64.decode(storedPassword.stringValue()));
+      return Arrays.equals(plaintextPassword.value(), decryptedPassword);
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      return false;
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean isReversible()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString getPlaintextValue(ByteString storedPassword)
+         throws DirectoryException
+  {
+    try
+    {
+      byte[] decryptedPassword =
+           cryptoManager.decrypt(Base64.decode(storedPassword.stringValue()));
+      return ByteStringFactory.create(decryptedPassword);
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      Message m = ERR_PWSCHEME_CANNOT_DECRYPT.get(STORAGE_SCHEME_NAME_BLOWFISH,
+                                                  getExceptionMessage(e));
+      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+                                   m, e);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean supportsAuthPasswordSyntax()
+  {
+    // This storage scheme does not support the authentication password syntax.
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString encodeAuthPassword(ByteString plaintext)
+         throws DirectoryException
+  {
+    Message message =
+        ERR_PWSCHEME_DOES_NOT_SUPPORT_AUTH_PASSWORD.get(getStorageSchemeName());
+    throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean authPasswordMatches(ByteString plaintextPassword,
+                                     String authInfo, String authValue)
+  {
+    // This storage scheme does not support the authentication password syntax.
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString getAuthPasswordPlaintextValue(String authInfo,
+                                                  String authValue)
+         throws DirectoryException
+  {
+    Message message =
+        ERR_PWSCHEME_DOES_NOT_SUPPORT_AUTH_PASSWORD.get(getStorageSchemeName());
+    throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean isStorageSchemeSecure()
+  {
+    // This password storage scheme should be considered secure.
+    return true;
+  }
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/ExtensionsConstants.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/ExtensionsConstants.java
index 2aaac17..aece32e 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/ExtensionsConstants.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/ExtensionsConstants.java
@@ -118,6 +118,88 @@
 
 
   /**
+   * The cipher transformation that should be used when performing 3DES
+   * encryption/decription.
+   */
+  public static final String CIPHER_TRANSFORMATION_3DES =
+       "DESede/CFB/NoPadding";
+
+
+
+  /**
+   * The cipher transformation that should be used when performing AES
+   * encryption/decription.
+   */
+  public static final String CIPHER_TRANSFORMATION_AES = "AES/CFB/NoPadding";
+
+
+
+  /**
+   * The cipher transformation that should be used when performing blowfish
+   * encryption/decription.
+   */
+  public static final String CIPHER_TRANSFORMATION_BLOWFISH =
+       "Blowfish/CFB/NoPadding";
+
+
+
+  /**
+   * The cipher transformation that should be used when performing RC4
+   * encryption/decription.
+   */
+  public static final String CIPHER_TRANSFORMATION_RC4 = "RC4";
+
+
+
+  /**
+   * The key size (in bits) that should be used for the encryption key when
+   * using the 3DES cipher.
+   */
+  public static final int KEY_SIZE_3DES = 168;
+
+
+
+  /**
+   * The key size (in bits) that should be used for the encryption key when
+   * using the AES cipher.
+   */
+  public static final int KEY_SIZE_AES = 128;
+
+
+
+  /**
+   * The key size (in bits) that should be used for the encryption key when
+   * using the Blowfish cipher.
+   */
+  public static final int KEY_SIZE_BLOWFISH = 128;
+
+
+
+  /**
+   * The key size (in bits) that should be used for the encryption key when
+   * using the RC4 cipher.
+   */
+  public static final int KEY_SIZE_RC4 = 128;
+
+
+
+  /**
+   * The password storage scheme name that will be used for passwords that are
+   * stored in 3DES-encrypted form.
+   */
+  public static final String STORAGE_SCHEME_NAME_3DES = "3DES";
+
+
+
+  /**
+   * The password storage scheme name that will be used for passwords that are
+   * stored in AES-encrypted form.
+   */
+  public static final String STORAGE_SCHEME_NAME_AES = "AES";
+
+
+
+  /**
    * The password storage scheme name that will be used for passwords that are
    * stored in base64-encoded form (virtually no protection, but the value is
    * reversible).
@@ -128,6 +210,14 @@
 
   /**
    * The password storage scheme name that will be used for passwords that are
+   * stored in Blowfish-encrypted form.
+   */
+  public static final String STORAGE_SCHEME_NAME_BLOWFISH = "BLOWFISH";
+
+
+
+  /**
+   * The password storage scheme name that will be used for passwords that are
    * not encoded or obscured in any way.
    */
   public static final String STORAGE_SCHEME_NAME_CLEAR = "CLEAR";
@@ -143,6 +233,14 @@
 
 
   /**
+   * The password storage scheme name that will be used for passwords that are
+   * stored in RC4-encrypted form.
+   */
+  public static final String STORAGE_SCHEME_NAME_RC4 = "RC4";
+
+
+
+  /**
    * The password storage scheme name that will be used for passwords stored in
    * a salted MD5 representation.
    */
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/RC4PasswordStorageScheme.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/RC4PasswordStorageScheme.java
new file mode 100644
index 0000000..e0f48a3
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/RC4PasswordStorageScheme.java
@@ -0,0 +1,310 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+
+
+import java.util.Arrays;
+
+import org.opends.messages.Message;
+import org.opends.server.admin.std.server.RC4PasswordStorageSchemeCfg;
+import org.opends.server.api.PasswordStorageScheme;
+import org.opends.server.config.ConfigException;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.ByteStringFactory;
+import org.opends.server.types.CryptoManager;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.ResultCode;
+import org.opends.server.util.Base64;
+
+import static org.opends.messages.ExtensionMessages.*;
+import static org.opends.server.extensions.ExtensionsConstants.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.util.StaticUtils.*;
+
+
+
+/**
+ * This class defines a Directory Server password storage scheme that will
+ * encode values using the RC4 reversible encryption algorithm.  This
+ * implementation supports only the user password syntax and not the auth
+ * password syntax.
+ */
+public class RC4PasswordStorageScheme
+       extends PasswordStorageScheme<RC4PasswordStorageSchemeCfg>
+{
+  /**
+   * The tracer object for the debug logger.
+   */
+  private static final DebugTracer TRACER = getTracer();
+
+
+
+  // The reference to the Directory Server crypto manager that we will use to
+  // handle the encryption/decryption.
+  private CryptoManager cryptoManager;
+
+
+
+  /**
+   * Creates a new instance of this password storage scheme.  Note that no
+   * initialization should be performed here, as all initialization should be
+   * done in the {@code initializePasswordStorageScheme} method.
+   */
+  public RC4PasswordStorageScheme()
+  {
+    super();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public void initializePasswordStorageScheme(
+                   RC4PasswordStorageSchemeCfg configuration)
+         throws ConfigException, InitializationException
+  {
+    cryptoManager = DirectoryServer.getCryptoManager();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public String getStorageSchemeName()
+  {
+    return STORAGE_SCHEME_NAME_RC4;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString encodePassword(ByteString plaintext)
+         throws DirectoryException
+  {
+    try
+    {
+      byte[] encodedBytes = cryptoManager.encrypt(CIPHER_TRANSFORMATION_RC4,
+                                                  KEY_SIZE_RC4,
+                                                  plaintext.value());
+      return ByteStringFactory.create(Base64.encode(encodedBytes));
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      Message m = ERR_PWSCHEME_CANNOT_ENCRYPT.get(STORAGE_SCHEME_NAME_RC4,
+                                                  getExceptionMessage(e));
+      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+                                   m, e);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString encodePasswordWithScheme(ByteString plaintext)
+         throws DirectoryException
+  {
+    StringBuilder buffer = new StringBuilder();
+    buffer.append('{');
+    buffer.append(STORAGE_SCHEME_NAME_RC4);
+    buffer.append('}');
+
+    try
+    {
+      byte[] encodedBytes = cryptoManager.encrypt(CIPHER_TRANSFORMATION_RC4,
+                                                  KEY_SIZE_RC4,
+                                                  plaintext.value());
+      buffer.append(Base64.encode(encodedBytes));
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      Message m = ERR_PWSCHEME_CANNOT_ENCRYPT.get(STORAGE_SCHEME_NAME_RC4,
+                                                  getExceptionMessage(e));
+      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+                                   m, e);
+    }
+
+    return ByteStringFactory.create(buffer.toString());
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean passwordMatches(ByteString plaintextPassword,
+                                 ByteString storedPassword)
+  {
+    try
+    {
+      byte[] decryptedPassword =
+           cryptoManager.decrypt(Base64.decode(storedPassword.stringValue()));
+      return Arrays.equals(plaintextPassword.value(), decryptedPassword);
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      return false;
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean isReversible()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString getPlaintextValue(ByteString storedPassword)
+         throws DirectoryException
+  {
+    try
+    {
+      byte[] decryptedPassword =
+           cryptoManager.decrypt(Base64.decode(storedPassword.stringValue()));
+      return ByteStringFactory.create(decryptedPassword);
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      Message m = ERR_PWSCHEME_CANNOT_DECRYPT.get(STORAGE_SCHEME_NAME_RC4,
+                                                  getExceptionMessage(e));
+      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+                                   m, e);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean supportsAuthPasswordSyntax()
+  {
+    // This storage scheme does not support the authentication password syntax.
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString encodeAuthPassword(ByteString plaintext)
+         throws DirectoryException
+  {
+    Message message =
+        ERR_PWSCHEME_DOES_NOT_SUPPORT_AUTH_PASSWORD.get(getStorageSchemeName());
+    throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean authPasswordMatches(ByteString plaintextPassword,
+                                     String authInfo, String authValue)
+  {
+    // This storage scheme does not support the authentication password syntax.
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString getAuthPasswordPlaintextValue(String authInfo,
+                                                  String authValue)
+         throws DirectoryException
+  {
+    Message message =
+        ERR_PWSCHEME_DOES_NOT_SUPPORT_AUTH_PASSWORD.get(getStorageSchemeName());
+    throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean isStorageSchemeSecure()
+  {
+    // This password storage scheme should be considered secure.
+    return true;
+  }
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/TripleDESPasswordStorageScheme.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/TripleDESPasswordStorageScheme.java
new file mode 100644
index 0000000..c3c0e2a
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/TripleDESPasswordStorageScheme.java
@@ -0,0 +1,310 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+
+
+import java.util.Arrays;
+
+import org.opends.messages.Message;
+import org.opends.server.admin.std.server.TripleDESPasswordStorageSchemeCfg;
+import org.opends.server.api.PasswordStorageScheme;
+import org.opends.server.config.ConfigException;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.ByteStringFactory;
+import org.opends.server.types.CryptoManager;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.ResultCode;
+import org.opends.server.util.Base64;
+
+import static org.opends.messages.ExtensionMessages.*;
+import static org.opends.server.extensions.ExtensionsConstants.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.util.StaticUtils.*;
+
+
+
+/**
+ * This class defines a Directory Server password storage scheme that will
+ * encode values using the triple-DES (DES/EDE) reversible encryption algorithm.
+ * This implementation supports only the user password syntax and not the auth
+ * password syntax.
+ */
+public class TripleDESPasswordStorageScheme
+       extends PasswordStorageScheme<TripleDESPasswordStorageSchemeCfg>
+{
+  /**
+   * The tracer object for the debug logger.
+   */
+  private static final DebugTracer TRACER = getTracer();
+
+
+
+  // The reference to the Directory Server crypto manager that we will use to
+  // handle the encryption/decryption.
+  private CryptoManager cryptoManager;
+
+
+
+  /**
+   * Creates a new instance of this password storage scheme.  Note that no
+   * initialization should be performed here, as all initialization should be
+   * done in the {@code initializePasswordStorageScheme} method.
+   */
+  public TripleDESPasswordStorageScheme()
+  {
+    super();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public void initializePasswordStorageScheme(
+                   TripleDESPasswordStorageSchemeCfg configuration)
+         throws ConfigException, InitializationException
+  {
+    cryptoManager = DirectoryServer.getCryptoManager();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public String getStorageSchemeName()
+  {
+    return STORAGE_SCHEME_NAME_3DES;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString encodePassword(ByteString plaintext)
+         throws DirectoryException
+  {
+    try
+    {
+      byte[] encodedBytes = cryptoManager.encrypt(CIPHER_TRANSFORMATION_3DES,
+                                                  KEY_SIZE_3DES,
+                                                  plaintext.value());
+      return ByteStringFactory.create(Base64.encode(encodedBytes));
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      Message m = ERR_PWSCHEME_CANNOT_ENCRYPT.get(STORAGE_SCHEME_NAME_3DES,
+                                                  getExceptionMessage(e));
+      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+                                   m, e);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString encodePasswordWithScheme(ByteString plaintext)
+         throws DirectoryException
+  {
+    StringBuilder buffer = new StringBuilder();
+    buffer.append('{');
+    buffer.append(STORAGE_SCHEME_NAME_3DES);
+    buffer.append('}');
+
+    try
+    {
+      byte[] encodedBytes = cryptoManager.encrypt(CIPHER_TRANSFORMATION_3DES,
+                                                  KEY_SIZE_3DES,
+                                                  plaintext.value());
+      buffer.append(Base64.encode(encodedBytes));
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      Message m = ERR_PWSCHEME_CANNOT_ENCRYPT.get(STORAGE_SCHEME_NAME_3DES,
+                                                  getExceptionMessage(e));
+      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+                                   m, e);
+    }
+
+    return ByteStringFactory.create(buffer.toString());
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean passwordMatches(ByteString plaintextPassword,
+                                 ByteString storedPassword)
+  {
+    try
+    {
+      byte[] decryptedPassword =
+           cryptoManager.decrypt(Base64.decode(storedPassword.stringValue()));
+      return Arrays.equals(plaintextPassword.value(), decryptedPassword);
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      return false;
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean isReversible()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString getPlaintextValue(ByteString storedPassword)
+         throws DirectoryException
+  {
+    try
+    {
+      byte[] decryptedPassword =
+           cryptoManager.decrypt(Base64.decode(storedPassword.stringValue()));
+      return ByteStringFactory.create(decryptedPassword);
+    }
+    catch (Exception e)
+    {
+      if (debugEnabled())
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      Message m = ERR_PWSCHEME_CANNOT_DECRYPT.get(STORAGE_SCHEME_NAME_3DES,
+                                                  getExceptionMessage(e));
+      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+                                   m, e);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean supportsAuthPasswordSyntax()
+  {
+    // This storage scheme does not support the authentication password syntax.
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString encodeAuthPassword(ByteString plaintext)
+         throws DirectoryException
+  {
+    Message message =
+        ERR_PWSCHEME_DOES_NOT_SUPPORT_AUTH_PASSWORD.get(getStorageSchemeName());
+    throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean authPasswordMatches(ByteString plaintextPassword,
+                                     String authInfo, String authValue)
+  {
+    // This storage scheme does not support the authentication password syntax.
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public ByteString getAuthPasswordPlaintextValue(String authInfo,
+                                                  String authValue)
+         throws DirectoryException
+  {
+    Message message =
+        ERR_PWSCHEME_DOES_NOT_SUPPORT_AUTH_PASSWORD.get(getStorageSchemeName());
+    throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean isStorageSchemeSecure()
+  {
+    // This password storage scheme should be considered secure.
+    return true;
+  }
+}
+
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/resource/config-changes.ldif b/opendj-sdk/opends/tests/unit-tests-testng/resource/config-changes.ldif
index ac3a9bb..7491871 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/resource/config-changes.ldif
+++ b/opendj-sdk/opends/tests/unit-tests-testng/resource/config-changes.ldif
@@ -819,3 +819,39 @@
 ds-cfg-alert-handler-class: org.opends.server.extensions.DummyAlertHandler
 ds-cfg-alert-handler-enabled: true
 
+dn: cn=3DES,cn=Password Storage Schemes,cn=config
+changetype: add
+objectClass: top
+objectClass: ds-cfg-password-storage-scheme
+objectClass: ds-cfg-triple-des-password-storage-scheme
+cn: 3DES
+ds-cfg-password-storage-scheme-class: org.opends.server.extensions.TripleDESPasswordStorageScheme
+ds-cfg-password-storage-scheme-enabled: true
+
+dn: cn=AES,cn=Password Storage Schemes,cn=config
+changetype: add
+objectClass: top
+objectClass: ds-cfg-password-storage-scheme
+objectClass: ds-cfg-aes-password-storage-scheme
+cn: AES
+ds-cfg-password-storage-scheme-class: org.opends.server.extensions.AESPasswordStorageScheme
+ds-cfg-password-storage-scheme-enabled: true
+
+dn: cn=Blowfish,cn=Password Storage Schemes,cn=config
+changetype: add
+objectClass: top
+objectClass: ds-cfg-password-storage-scheme
+objectClass: ds-cfg-blowfish-password-storage-scheme
+cn: Blowfish
+ds-cfg-password-storage-scheme-class: org.opends.server.extensions.BlowfishPasswordStorageScheme
+ds-cfg-password-storage-scheme-enabled: true
+
+dn: cn=RC4,cn=Password Storage Schemes,cn=config
+changetype: add
+objectClass: top
+objectClass: ds-cfg-password-storage-scheme
+objectClass: ds-cfg-rc4-password-storage-scheme
+cn: RC4
+ds-cfg-password-storage-scheme-class: org.opends.server.extensions.RC4PasswordStorageScheme
+ds-cfg-password-storage-scheme-enabled: true
+
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/AESPasswordStorageSchemeTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/AESPasswordStorageSchemeTestCase.java
new file mode 100644
index 0000000..93eea01
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/AESPasswordStorageSchemeTestCase.java
@@ -0,0 +1,75 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+
+
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.AESPasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.AESPasswordStorageSchemeCfg;
+import org.opends.server.api.PasswordStorageScheme;
+
+
+
+/**
+ * A set of test cases for the AES password storage scheme.
+ */
+public class AESPasswordStorageSchemeTestCase
+       extends PasswordStorageSchemeTestCase
+{
+  /**
+   * Creates a new instance of this storage scheme test case.
+   */
+  public AESPasswordStorageSchemeTestCase()
+  {
+    super("cn=AES,cn=Password Storage Schemes,cn=config");
+  }
+
+
+
+  /**
+   * 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
+  {
+    AESPasswordStorageScheme scheme = new AESPasswordStorageScheme();
+
+    AESPasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          AESPasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry());
+
+    scheme.initializePasswordStorageScheme(configuration);
+    return scheme;
+  }
+}
+
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/BlowfishPasswordStorageSchemeTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/BlowfishPasswordStorageSchemeTestCase.java
new file mode 100644
index 0000000..f294fc9
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/BlowfishPasswordStorageSchemeTestCase.java
@@ -0,0 +1,75 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+
+
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.BlowfishPasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.BlowfishPasswordStorageSchemeCfg;
+import org.opends.server.api.PasswordStorageScheme;
+
+
+
+/**
+ * A set of test cases for the Blowfish password storage scheme.
+ */
+public class BlowfishPasswordStorageSchemeTestCase
+       extends PasswordStorageSchemeTestCase
+{
+  /**
+   * Creates a new instance of this storage scheme test case.
+   */
+  public BlowfishPasswordStorageSchemeTestCase()
+  {
+    super("cn=Blowfish,cn=Password Storage Schemes,cn=config");
+  }
+
+
+
+  /**
+   * 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
+  {
+    BlowfishPasswordStorageScheme scheme = new BlowfishPasswordStorageScheme();
+
+    BlowfishPasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          BlowfishPasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry());
+
+    scheme.initializePasswordStorageScheme(configuration);
+    return scheme;
+  }
+}
+
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/RC4PasswordStorageSchemeTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/RC4PasswordStorageSchemeTestCase.java
new file mode 100644
index 0000000..6ab26d9
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/RC4PasswordStorageSchemeTestCase.java
@@ -0,0 +1,75 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+
+
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.RC4PasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.RC4PasswordStorageSchemeCfg;
+import org.opends.server.api.PasswordStorageScheme;
+
+
+
+/**
+ * A set of test cases for the RC4 password storage scheme.
+ */
+public class RC4PasswordStorageSchemeTestCase
+       extends PasswordStorageSchemeTestCase
+{
+  /**
+   * Creates a new instance of this storage scheme test case.
+   */
+  public RC4PasswordStorageSchemeTestCase()
+  {
+    super("cn=RC4,cn=Password Storage Schemes,cn=config");
+  }
+
+
+
+  /**
+   * 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
+  {
+    RC4PasswordStorageScheme scheme = new RC4PasswordStorageScheme();
+
+    RC4PasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          RC4PasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry());
+
+    scheme.initializePasswordStorageScheme(configuration);
+    return scheme;
+  }
+}
+
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/TripleDESPasswordStorageSchemeTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/TripleDESPasswordStorageSchemeTestCase.java
new file mode 100644
index 0000000..118883d
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/TripleDESPasswordStorageSchemeTestCase.java
@@ -0,0 +1,76 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+
+
+import org.opends.server.admin.server.AdminTestCaseUtils;
+import org.opends.server.admin.std.meta.TripleDESPasswordStorageSchemeCfgDefn;
+import org.opends.server.admin.std.server.TripleDESPasswordStorageSchemeCfg;
+import org.opends.server.api.PasswordStorageScheme;
+
+
+
+/**
+ * A set of test cases for the 3DES password storage scheme.
+ */
+public class TripleDESPasswordStorageSchemeTestCase
+       extends PasswordStorageSchemeTestCase
+{
+  /**
+   * Creates a new instance of this storage scheme test case.
+   */
+  public TripleDESPasswordStorageSchemeTestCase()
+  {
+    super("cn=3DES,cn=Password Storage Schemes,cn=config");
+  }
+
+
+
+  /**
+   * 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
+  {
+    TripleDESPasswordStorageScheme scheme =
+         new TripleDESPasswordStorageScheme();
+
+    TripleDESPasswordStorageSchemeCfg configuration =
+      AdminTestCaseUtils.getConfiguration(
+          TripleDESPasswordStorageSchemeCfgDefn.getInstance(),
+          configEntry.getEntry());
+
+    scheme.initializePasswordStorageScheme(configuration);
+    return scheme;
+  }
+}
+

--
Gitblit v1.10.0