summaryrefslogtreecommitdiffstats
path: root/ldap/servers/plugins/rever
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/servers/plugins/rever')
-rw-r--r--ldap/servers/plugins/rever/Makefile111
-rw-r--r--ldap/servers/plugins/rever/des.c465
-rw-r--r--ldap/servers/plugins/rever/dllmain.c91
-rw-r--r--ldap/servers/plugins/rever/libdes.def13
-rw-r--r--ldap/servers/plugins/rever/rever.c77
-rw-r--r--ldap/servers/plugins/rever/rever.h34
6 files changed, 791 insertions, 0 deletions
diff --git a/ldap/servers/plugins/rever/Makefile b/ldap/servers/plugins/rever/Makefile
new file mode 100644
index 00000000..76203a9c
--- /dev/null
+++ b/ldap/servers/plugins/rever/Makefile
@@ -0,0 +1,111 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright 2001 Sun Microsystems, Inc.
+# Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+#
+# GNU Makefile for Directory Server password_storaged-plugin.so password storage scheme plugins
+#
+
+LDAP_SRC = ../../..
+MCOM_ROOT = ../../../../..
+
+NOSTDCLEAN=true # don't let nsconfig.mk define target clean
+NOSTDSTRIP=true # don't let nsconfig.mk define target strip
+NSPR20=true # probably should be defined somewhere else (not sure where)
+
+OBJDEST = $(OBJDIR)/lib/libdes
+LIBDIR = $(LIB_RELDIR)
+
+include $(MCOM_ROOT)/ldapserver/nsconfig.mk
+include $(MCOM_ROOT)/ldapserver/ns_usepurify.mk
+include $(LDAP_SRC)/nsldap.mk
+
+ifeq ($(ARCH), WINNT)
+DEF_FILE:=./libdes.def
+endif
+
+CFLAGS+=$(SLCFLAGS)
+
+INCLUDES += -I$(LDAP_SRC)/servers/slapd
+INCLUDES += -I$(MCOM_ROOT)/ldapserver/ldap/include
+
+REVER_OBJS= \
+ rever.o des.o
+
+OBJS = $(addprefix $(OBJDEST)/, $(REVER_OBJS))
+
+ifeq ($(ARCH), WINNT)
+LIBREVER_DLL_OBJ = $(addprefix $(OBJDEST)/, dllmain.o)
+endif
+
+REVER_DLL = des-plugin
+LIBREVER = $(addprefix $(LIBDIR)/, $(REVER_DLL).$(DLL_SUFFIX))
+
+ifeq ($(ARCH), WINNT)
+EXTRA_LIBS_DEP += \
+ $(LIBSLAPD_DEP) \
+ $(LDAP_LIBUTIL_DEP) \
+ $(LDAP_COMMON_LIBS_DEP)
+EXTRA_LIBS_DEP += \
+ $(LDAPSDK_DEP) \
+ $(SECURITY_DEP)
+EXTRA_LIBS += \
+ $(LIBSLAPD) \
+ $(LDAP_SDK_LIBLDAP_DLL) \
+ $(LIBUTIL) \
+ $(NSPRLINK) \
+ $(LDAP_COMMON_LIBS) \
+ $(SECURITYLINK)
+endif
+ifeq ($(ARCH), AIX)
+EXTRA_LIBS_DEP += \
+ $(LIBSLAPD_DEP) \
+ $(LDAP_LIBUTIL_DEP) \
+ $(LDAP_COMMON_LIBS_DEP)
+EXTRA_LIBS_DEP += \
+ $(LDAPSDK_DEP) \
+ $(SECURITY_DEP)
+EXTRA_LIBS += \
+ $(LIBSLAPDLINK) \
+ $(LDAP_SDK_LIBLDAP_DLL) \
+ $(LIBUTIL) \
+ $(NSPRLINK) \
+ $(LDAP_COMMON_LIBS) \
+ $(SECURITYLINK)
+endif
+
+ifeq ($(ARCH), HPUX)
+EXTRA_LIBS_DEP += $(LIBSLAPD_DEP) $(LDAPSDK_DEP) $(NSPR_DEP) $(SECURITY_DEP)
+EXTRA_LIBS += $(DYN_NSHTTPD) $(ADMINUTIL_LINK) $(LDAPLINK) $(SECURITYLINK) $(NSPRLINK) $(ICULINK)
+endif
+
+ifeq ($(ARCH), WINNT)
+DLL_LDFLAGS += -def:"./libdes.def"
+CFLAGS+= /WX
+endif # WINNT
+
+ifeq ($(ARCH), AIX)
+LD=ld
+endif
+
+clientSDK:
+
+all: $(OBJDEST) $(LIBDIR) $(LIBREVER)
+
+$(LIBREVER): $(OBJS) $(LIBREVER_DLL_OBJ) $(DEF_FILE)
+ $(LINK_DLL) $(LIBREVER_DLL_OBJ) $(EXTRA_LIBS)
+
+veryclean: clean
+
+clean:
+ $(RM) $(OBJS)
+ifeq ($(ARCH), WINNT)
+ $(RM) $(LIBREVER_DLL_OBJ)
+endif
+ $(RM) $(LIBREVER)
+
+$(OBJDEST):
+ $(MKDIR) $(OBJDEST)
diff --git a/ldap/servers/plugins/rever/des.c b/ldap/servers/plugins/rever/des.c
new file mode 100644
index 00000000..4b70c91d
--- /dev/null
+++ b/ldap/servers/plugins/rever/des.c
@@ -0,0 +1,465 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/* from /usr/project/iplanet/ws/ds5.ke/ns/svrcore/pkcs7/tstarchive.c */
+
+#include <string.h>
+#include <stdio.h>
+
+#include <ldap.h>
+#include <nspr.h>
+#include <nss.h>
+#include <secmod.h>
+/*
+#include <secasn1.h>
+#include <secpkcs7.h>
+*/
+#include <key.h>
+#include <certdb.h>
+#include <cert.h>
+#include <svrcore.h>
+#include <secmodt.h>
+#include <prtypes.h>
+#include <seccomon.h>
+#include <pk11func.h>
+
+#include "rever.h"
+#include <slap.h>
+#include "slapi-plugin.h"
+#include <uuid.h>
+
+
+struct pk11MechItem
+{
+ CK_MECHANISM_TYPE type;
+ const char *mechName;
+};
+static const struct pk11MechItem mymech = { CKM_DES_CBC, "DES CBC encryption" };
+
+
+static Slapi_Mutex *mylock = NULL;
+
+struct pk11ContextStore
+{
+ PK11SlotInfo *slot;
+ const struct pk11MechItem *mech;
+
+ PK11SymKey *key;
+ SECItem *params;
+
+ int length;
+ unsigned char *crypt;
+};
+
+static int encode_path(char *inPlain, char **outCipher, char *path);
+static int decode_path(char *inCipher, char **outPlain, char *path);
+static SVRCOREError genKey(struct pk11ContextStore **out, const char *token, char *path);
+static SVRCOREError cryptPassword(struct pk11ContextStore *store, char * clear, unsigned char **out);
+static SVRCOREError decryptPassword(struct pk11ContextStore *store, unsigned char *cipher, char **out, int len);
+static void freeDes(struct pk11ContextStore *out);
+
+static int init = 0;
+
+void
+init_des_plugin()
+{
+ mylock = slapi_new_mutex();
+}
+
+int
+encode(char *inPlain, char **outCipher)
+{
+ return encode_path(inPlain, outCipher, NULL);
+}
+
+static int
+encode_path(char *inPlain, char **outCipher, char *path)
+{
+ struct pk11ContextStore *context = NULL;
+ int err;
+
+ unsigned char *cipher = NULL;
+ char *tmp = NULL;
+ char *base = NULL;
+
+
+ *outCipher = NULL;
+ err = 1;
+
+ if ( genKey(&context, tokDes, path) == SVRCORE_Success )
+ {
+ /* Try an encryption */
+ if ( cryptPassword(context, inPlain, &cipher) == SVRCORE_Success )
+ {
+ base = BTOA_DataToAscii(cipher, context->length);
+ if ( base != NULL )
+ {
+ tmp = slapi_ch_malloc( 3 + strlen(REVER_SCHEME_NAME) + strlen(base));
+ if ( tmp != NULL )
+ {
+ sprintf( tmp, "%c%s%c%s", PWD_HASH_PREFIX_START, REVER_SCHEME_NAME, PWD_HASH_PREFIX_END, base);
+ *outCipher = tmp;
+ tmp = NULL;
+ err = 0;
+ }
+ PORT_Free(base);
+ }
+ }
+ }
+
+ freeDes(context);
+ slapi_ch_free((void **) &context);
+ return(err);
+}
+
+int
+decode(char *inCipher, char **outPlain)
+{
+ return decode_path(inCipher, outPlain, NULL);
+}
+
+
+static int
+decode_path(char *inCipher, char **outPlain, char *path)
+{
+ struct pk11ContextStore *context = NULL;
+ char *plain= NULL;
+ int err;
+
+ unsigned char *base = NULL;
+ int len = 0;
+
+
+ *outPlain = NULL;
+ err = 1;
+
+ if ( genKey(&context, tokDes, path) == SVRCORE_Success )
+ {
+ /* it seems that there is memory leak in that function: bug 400170 */
+
+ base = ATOB_AsciiToData(inCipher, (unsigned int*)&len);
+ if ( base != NULL )
+ {
+ if ( decryptPassword(context, base, &plain, len) == SVRCORE_Success )
+ {
+ *outPlain = plain;
+ err = 0;
+ }
+ }
+ }
+
+ PORT_Free(base);
+ freeDes(context);
+ slapi_ch_free((void **) &context);
+ return(err);
+}
+
+static void freeDes(struct pk11ContextStore *out)
+{
+ if (out)
+ {
+ if (out->slot)
+ slapd_pk11_freeSlot(out->slot);
+ if (out->key)
+ slapd_pk11_freeSymKey(out->key);
+ if (out->params)
+ SECITEM_FreeItem(out->params,PR_TRUE);
+ if (out->crypt)
+ free(out->crypt);
+ }
+}
+
+static SVRCOREError genKey(struct pk11ContextStore **out, const char *token, char *path)
+{
+ SVRCOREError err = SVRCORE_Success;
+ struct pk11ContextStore *store = NULL;
+ SECItem *pwitem = NULL;
+ SECItem *result = NULL;
+ SECAlgorithmID *algid = NULL;
+ SECOidTag algoid;
+ SECItem *salt = NULL;
+ CK_MECHANISM pbeMech;
+ CK_MECHANISM cryptoMech;
+
+ char *instancedir = NULL;
+ char *iv = NULL;
+
+ store = (struct pk11ContextStore*)slapi_ch_malloc(sizeof(*store));
+ if (store == NULL)
+ {
+ return (err = SVRCORE_NoMemory_Error);
+ }
+ *out = store;
+
+ /* Low-level init */
+ store->slot = NULL;
+ store->key = NULL;
+ store->params = NULL;
+ store->crypt = NULL;
+
+ /* Use the tokenName to find a PKCS11 slot */
+ store->slot = slapd_pk11_findSlotByName((char *)token);
+ if (store->slot == NULL)
+ {
+ return (err = SVRCORE_NoSuchToken_Error);
+ }
+
+ /* Generate a key and parameters to do the encryption */
+ store->mech = &mymech;
+
+ /* Generate a unique id, used as salt for the key generation */
+ if ( path == NULL )
+ {
+ instancedir = config_get_instancedir();
+ if ( instancedir == NULL )
+ {
+ return (err = SVRCORE_System_Error);
+ }
+ }
+ else
+ {
+ instancedir = slapi_ch_strdup(path);
+ }
+ if ( slapi_uniqueIDGenerateFromNameString (&iv, NULL, instancedir, strlen(instancedir)) != UID_SUCCESS )
+ {
+ slapi_ch_free((void**)&instancedir);
+ return (err = SVRCORE_System_Error);
+ }
+ slapi_ch_free((void**)&instancedir);
+
+ pwitem = (SECItem *) PORT_Alloc(sizeof(SECItem));
+ if (pwitem == NULL)
+ {
+ return (err = SVRCORE_NoMemory_Error);
+ }
+ pwitem->type = siBuffer;
+ pwitem->data = (unsigned char *)PORT_Alloc(strlen(iv)+1);
+ if (pwitem->data == NULL)
+ {
+ return (err = SVRCORE_NoMemory_Error);
+ }
+ strcpy((char*)pwitem->data, iv);
+ pwitem->len = strlen(iv) + 1;
+
+ algoid = SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC;
+
+ salt = (SECItem *) PORT_Alloc(sizeof(SECItem));
+ if (salt == NULL)
+ {
+ return (err = SVRCORE_NoMemory_Error);
+ }
+ salt->type = siBuffer;
+ salt->data = (unsigned char *)PORT_Alloc(strlen(iv)+1);
+ if ( salt->data == NULL )
+ {
+ return (err = SVRCORE_NoMemory_Error);
+ }
+ strcpy((char*)salt->data, iv);
+ salt->len = strlen(iv) + 1;
+ slapi_ch_free((void**)&iv);
+
+ algid = slapd_pk11_createPBEAlgorithmID(algoid, 2, salt);
+
+ slapi_lock_mutex(mylock);
+ store->key = slapd_pk11_pbeKeyGen(store->slot, algid, pwitem, 0, 0);
+ if (store->key == 0)
+ {
+ slapi_unlock_mutex(mylock);
+ return (err = SVRCORE_System_Error);
+ }
+
+ slapi_unlock_mutex(mylock);
+ pbeMech.mechanism = slapd_pk11_algtagToMechanism(algoid);
+ result = slapd_pk11_paramFromAlgid(algid);
+ secoid_destroyAlgorithmID(algid, PR_TRUE);
+ pbeMech.pParameter = result->data;
+ pbeMech.ulParameterLen = result->len;
+ if(slapd_pk11_mapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, pwitem,
+ PR_FALSE) != CKR_OK)
+ {
+ SECITEM_FreeItem(result, PR_TRUE);
+ return (err = SVRCORE_System_Error);
+ }
+ SECITEM_FreeItem(result, PR_TRUE);
+ SECITEM_FreeItem(pwitem, PR_TRUE);
+ SECITEM_FreeItem(salt, PR_TRUE);
+ store->params = (SECItem *) PORT_Alloc(sizeof(SECItem));
+ if (store->params == NULL)
+ {
+ return (err = SVRCORE_System_Error);
+ }
+ store->params->type = store->mech->type;
+ store->params->data = (unsigned char *)PORT_Alloc(cryptoMech.ulParameterLen);
+ if (store->params->data == NULL)
+ {
+ return (err = SVRCORE_System_Error);
+ }
+ memcpy(store->params->data, (unsigned char *)cryptoMech.pParameter, cryptoMech.ulParameterLen);
+ store->params->len = cryptoMech.ulParameterLen;
+ PORT_Free(cryptoMech.pParameter);
+ return (err);
+}
+
+static SVRCOREError decryptPassword(struct pk11ContextStore *store, unsigned char *cipher, char **out, int len)
+{
+ SVRCOREError err = SVRCORE_Success;
+ unsigned char *plain = NULL;
+ unsigned char *cipher_with_padding = NULL;
+ SECStatus rv;
+ PK11Context *ctx = 0;
+ int outLen = 0;
+ int blocksize = 0;
+
+ blocksize = slapd_pk11_getBlockSize(store->mech->type, 0);
+ store->length = len;
+
+ /* store->length is the max. length of the returned clear text -
+ must be >= length of crypted bytes - also must be a multiple
+ of blocksize */
+ if (blocksize != 0)
+ {
+ store->length += blocksize - (store->length % blocksize);
+ }
+
+ /* plain will hold the returned clear text */
+ plain = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char),
+ store->length+1);
+ if (!plain)
+ {
+ return (err = SVRCORE_NoMemory_Error);
+ }
+
+ /* create a buffer holding the original cipher bytes, padded with
+ zeros to a multiple of blocksize - do not need +1 since buffer is not
+ a string */
+ cipher_with_padding = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char),
+ store->length);
+ if (!cipher_with_padding)
+ {
+ return (err = SVRCORE_NoMemory_Error);
+ }
+ memcpy(cipher_with_padding, cipher, len);
+
+ ctx = slapd_pk11_createContextBySymKey(store->mech->type, CKA_DECRYPT,
+ store->key, store->params);
+ if (!ctx)
+ {
+ return (err = SVRCORE_System_Error);
+ }
+
+ /* warning - there is a purify UMR in the NSS des code - you may see it when the
+ password is not a multiple of 8 bytes long */
+ rv = slapd_pk11_cipherOp(ctx, plain, &outLen, store->length,
+ cipher_with_padding, store->length);
+ if (rv)
+ {
+ err = SVRCORE_System_Error;
+ }
+
+ rv = slapd_pk11_finalize(ctx);
+ /* we must do the finalize, but we only want to set the err return
+ code if it is not already set */
+ if (rv && (SVRCORE_Success == err))
+ err = SVRCORE_System_Error;
+
+ if (err == SVRCORE_Success)
+ *out = (char *)plain;
+
+ slapi_ch_free((void **)&cipher_with_padding);
+ /* We should free the PK11Context... Something like : */
+ slapd_pk11_destroyContext(ctx, PR_TRUE);
+ return err;
+}
+
+static SVRCOREError cryptPassword(struct pk11ContextStore *store, char * clear, unsigned char **out)
+{
+ SVRCOREError err = SVRCORE_Success;
+ SECStatus rv;
+ PK11Context *ctx = 0;
+ int outLen = 0;
+ int blocksize = 0;
+ unsigned char *clear_with_padding = NULL; /* clear with padding up to blocksize */
+
+ blocksize = slapd_pk11_getBlockSize(store->mech->type, 0);
+ store->length = strlen(clear);
+
+ /* the size of the clear text buffer passed to the des encryption functions
+ must be a multiple of blocksize (usually 8 bytes) - we allocate a buffer
+ of this size, copy the clear text password into it, and pad the rest with
+ zeros */
+ if (blocksize != 0)
+ {
+ store->length += blocksize - (store->length % blocksize);
+ }
+
+ /* store->crypt will hold the crypted password - it must be >= clear length */
+ store->crypt = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char),
+ store->length+1);
+ if (!store->crypt)
+ {
+ return (err = SVRCORE_NoMemory_Error);
+ }
+
+ /* create a buffer big enough to hold the clear text password and padding */
+ clear_with_padding = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char),
+ store->length+1);
+ if (!clear_with_padding)
+ {
+ return (err = SVRCORE_NoMemory_Error);
+ }
+ /* copy the clear text password into the buffer - the calloc insures the
+ remainder is zero padded */
+ strcpy((char *)clear_with_padding, clear);
+
+ ctx = slapd_pk11_createContextBySymKey(store->mech->type, CKA_ENCRYPT,
+ store->key, store->params);
+ if (!ctx)
+ {
+ return (err = SVRCORE_System_Error);
+ }
+
+ rv = slapd_pk11_cipherOp(ctx, store->crypt, &outLen, store->length,
+ clear_with_padding, store->length);
+ if (rv)
+ {
+ err = SVRCORE_System_Error;
+ }
+
+ rv = slapd_pk11_finalize(ctx);
+ /* we must do the finalize, but we only want to set the err return
+ code if it is not already set */
+ if (rv && (SVRCORE_Success == err))
+ err = SVRCORE_System_Error;
+
+ if (err == SVRCORE_Success)
+ *out = store->crypt;
+
+ slapi_ch_free((void **)&clear_with_padding);
+ /* We should free the PK11Context... Something like : */
+ slapd_pk11_destroyContext(ctx, PR_TRUE);
+ return err;
+}
+
+char *
+migrateCredentials(char *oldpath, char *newpath, char *oldcred)
+{
+ char *plain = NULL;
+ char *cipher = NULL;
+
+ init_des_plugin();
+
+ slapd_pk11_configurePKCS11(NULL, NULL, tokDes, ptokDes, NULL, NULL, NULL, NULL, 0, 0 );
+ NSS_NoDB_Init(NULL);
+
+ if ( decode_path(oldcred, &plain, oldpath) == 0 )
+ {
+ if ( encode_path(plain, &cipher, newpath) != 0 )
+ return(NULL);
+ else
+ return(cipher);
+ }
+ else
+ return(NULL);
+}
diff --git a/ldap/servers/plugins/rever/dllmain.c b/ldap/servers/plugins/rever/dllmain.c
new file mode 100644
index 00000000..0bb85815
--- /dev/null
+++ b/ldap/servers/plugins/rever/dllmain.c
@@ -0,0 +1,91 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+ /*
+ * Microsoft Windows specifics for LIBPWDSTORAGE DLL
+ */
+#include "rever.h"
+
+
+#ifdef _WIN32
+/* Lifted from Q125688
+ * How to Port a 16-bit DLL to a Win32 DLL
+ * on the MSVC 4.0 CD
+ */
+BOOL WINAPI DllMain (HANDLE hModule, DWORD fdwReason, LPVOID lpReserved)
+{
+
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ /* Code from LibMain inserted here. Return TRUE to keep the
+ DLL loaded or return FALSE to fail loading the DLL.
+
+ You may have to modify the code in your original LibMain to
+ account for the fact that it may be called more than once.
+ You will get one DLL_PROCESS_ATTACH for each process that
+ loads the DLL. This is different from LibMain which gets
+ called only once when the DLL is loaded. The only time this
+ is critical is when you are using shared data sections.
+ If you are using shared data sections for statically
+ allocated data, you will need to be careful to initialize it
+ only once. Check your code carefully.
+
+ Certain one-time initializations may now need to be done for
+ each process that attaches. You may also not need code from
+ your original LibMain because the operating system may now
+ be doing it for you.
+ */
+ /*
+ * 16 bit code calls UnlockData()
+ * which is mapped to UnlockSegment in windows.h
+ * in 32 bit world UnlockData is not defined anywhere
+ * UnlockSegment is mapped to GlobalUnfix in winbase.h
+ * and the docs for both UnlockSegment and GlobalUnfix say
+ * ".. function is oboslete. Segments have no meaning
+ * in the 32-bit environment". So we do nothing here.
+ */
+
+ break;
+
+ case DLL_THREAD_ATTACH:
+ /* Called each time a thread is created in a process that has
+ already loaded (attached to) this DLL. Does not get called
+ for each thread that exists in the process before it loaded
+ the DLL.
+
+ Do thread-specific initialization here.
+ */
+ break;
+
+ case DLL_THREAD_DETACH:
+ /* Same as above, but called when a thread in the process
+ exits.
+
+ Do thread-specific cleanup here.
+ */
+ break;
+
+ case DLL_PROCESS_DETACH:
+ /* Code from _WEP inserted here. This code may (like the
+ LibMain) not be necessary. Check to make certain that the
+ operating system is not doing it for you.
+ */
+
+ break;
+ }
+ /* The return value is only used for DLL_PROCESS_ATTACH; all other
+ conditions are ignored. */
+ return TRUE; /* successful DLL_PROCESS_ATTACH */
+}
+#else
+int CALLBACK
+LibMain( HINSTANCE hinst, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine )
+{
+ /*UnlockData( 0 );*/
+ return( 1 );
+}
+#endif
diff --git a/ldap/servers/plugins/rever/libdes.def b/ldap/servers/plugins/rever/libdes.def
new file mode 100644
index 00000000..048af6f4
--- /dev/null
+++ b/ldap/servers/plugins/rever/libdes.def
@@ -0,0 +1,13 @@
+; BEGIN COPYRIGHT BLOCK
+; Copyright 2001 Sun Microsystems, Inc.
+; Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+; All rights reserved.
+; END COPYRIGHT BLOCK
+;
+DESCRIPTION 'Directory Server 6.2.1 Local Credentials Reversible Encryption Plugin'
+EXPORTS
+ des_cmp @2
+ des_enc @3
+ des_dec @4
+ des_init @5
+ migrateCredentials @6
diff --git a/ldap/servers/plugins/rever/rever.c b/ldap/servers/plugins/rever/rever.c
new file mode 100644
index 00000000..10767944
--- /dev/null
+++ b/ldap/servers/plugins/rever/rever.c
@@ -0,0 +1,77 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "dirver.h"
+
+#include "rever.h"
+
+static Slapi_PluginDesc pdesc = { "des-storage-scheme", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, "DES storage scheme plugin" };
+
+static char *plugin_name = "ReverStoragePlugin";
+
+int
+des_cmp( char *userpwd, char *dbpwd )
+{
+ char *cipher = NULL;
+
+ if ( encode(userpwd, &cipher) != 0 )
+ return 1;
+ else
+ return( strcmp(cipher, dbpwd) );
+}
+
+char *
+des_enc( char *pwd )
+{
+ char *cipher = NULL;
+
+ if ( encode(pwd, &cipher) != 0 )
+ return(NULL);
+ else
+ return( cipher );
+}
+
+char *
+des_dec( char *pwd )
+{
+ char *plain = NULL;
+
+ if ( decode(pwd, &plain) != 0 )
+ return(NULL);
+ else
+ return( plain );
+}
+
+int
+des_init( Slapi_PBlock *pb )
+{
+ int rc;
+ char *name;
+
+ slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, "=> des_init\n" );
+
+ rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
+ (void *) SLAPI_PLUGIN_VERSION_01 );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
+ (void *)&pdesc );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_ENC_FN,
+ (void *) des_enc);
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_CMP_FN,
+ (void *) des_cmp );
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_DEC_FN,
+ (void *) des_dec );
+ name = slapi_ch_strdup(REVER_SCHEME_NAME);
+ rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_NAME,
+ name );
+
+ init_des_plugin();
+
+ slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, "<= des_init %d\n\n", rc );
+
+ return( rc );
+}
diff --git a/ldap/servers/plugins/rever/rever.h b/ldap/servers/plugins/rever/rever.h
new file mode 100644
index 00000000..0992aea7
--- /dev/null
+++ b/ldap/servers/plugins/rever/rever.h
@@ -0,0 +1,34 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#ifndef _REVER_H
+#define _REVER_H
+
+#include "slapi-plugin.h"
+#include "nspr.h"
+#include "base64.h"
+#include "slap.h"
+#include "ldaplog.h"
+
+#include <dirlite_strings.h> /* PLUGIN_MAGIC_VENDOR_STR */
+
+#define REVER_SCHEME_NAME "DES"
+#define PWD_HASH_PREFIX_START '{'
+#define PWD_HASH_PREFIX_END '}'
+
+
+int rever_cmp( char *userpwd, char *dbpwd );
+char *rever_enc( char *pwd );
+char *rever_dec( char *pwd );
+int rever_init( Slapi_PBlock *pb );
+void init_des_plugin();
+
+int encode(char *inPlain, char ** outCipher);
+int decode(char *inCipher, char **outPlain);
+
+char *migrateCredentials(char *oldpath, char *newpath, char *oldcred);
+typedef char *(*migrate_fn_type)(char *, char *, char *);
+
+#endif