summaryrefslogtreecommitdiffstats
path: root/ldap/servers/plugins/rever/des.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/servers/plugins/rever/des.c')
-rw-r--r--ldap/servers/plugins/rever/des.c465
1 files changed, 465 insertions, 0 deletions
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);
+}