Samba passwords sync

Hello,

I need to mantain synchronized DS sambaPassword attributes with userPassword attribute. In other words I would everytime userPassword is updated by the user with a new password, then the same password should be stored into sambaNTPassword and sambaLMPassword attributes (od the same account).

I think the best way to do this is to have a post-op plugin which encrypts password according samba and updates sambaPasswords attributes.

Do You agree?

Is there such pluging anywhere?

TIA

[525 byte] By [rm102772] at [2007-11-26 11:59:25]
# 1

If it's in the same entry but additional attributes, I would write a pre-op entry plugin that will detect userPassword changes, encrypt the password according to Samba rules and add a couple of modifications to the current set of modifications.

This will avoid modifying the entry twice like a post-operation plugin would do.

Plus, the changes will be in the same transaction, thus atomic, consistent, isolated and durable.

I'm not aware of such plugin for Samba passwords, but it should be easy to write one based on the sample pre-operation plugin delivered by DS.

Watch out the memory management, this is the critical piece for the reliability of DS.

Regards,

Ludovic.

ludovicp at 2007-7-7 12:21:20 > top of Java-index,Web & Directory Servers,Directory Servers...
# 2

Yes: they are really additional attributes of the same DS entry (uid) and they could be updated only by our plugin when someone updates userPassword.

This is an example of such an entry for the same uid password:

uid: tstsnz27

userPassword: {SSHA}a/dthl7r7Gn1/8D3dTcVjVMeMasgd9UvCydrKA==

sambaLMPassword: B86C6E52363E9CFDF500944B53168930

sambaNTPassword: 844855BD44C20B4C57E370391A61179A

Thanks a lot for your advices.

"sample pre-operation plugin delivered by DS" is it included in base DS product or in DSRkit?

Thanks again.

-roberto

rm102772 at 2007-7-7 12:21:20 > top of Java-index,Web & Directory Servers,Directory Servers...
# 3
The sample plug-ins are in the Directory Server delivery, and documented in the plug-in programmer's guideRegards,Ludovic.
ludovicp at 2007-7-7 12:21:20 > top of Java-index,Web & Directory Servers,Directory Servers...
# 4

I thought post-op is better because you don't want to update sambaNTpassword unless update of userpassword succeed. I wrote post-op where I am checking SLAPI_RESULT_CODE. For some reason if the userpassword update failles due to password policy such as "password in history", min length etc then plugin should just exit and not update sambaNTpassword.

I wrote one that generates md4 hash of unicoded password for MSCHAPv2 using Radius server and built-in Microsoft 802.1x wireless clients to avoid buying AD server or third party wireless client :-). That hash is what exactly sambaNTpassword uses too.

Samba site below as code for both NT and LM password generation.

http://www.samba.org/cgi-bin/cvsweb/samba/examples/LDAP/smbldap-tools/mkntpwd/# dirlist

Thanks & Regards

Krishna Kusupudi

kusupudi at 2007-7-7 12:21:20 > top of Java-index,Web & Directory Servers,Directory Servers...
# 5

A post-op works but it makes the plug-in more complex and creates more load and processing on the server as each entry will be updated twice.

But this is my opinion and is mostly based on my 10+ years of development of Sun's Directory Servers :-)

If the plugin is a pre-op, the plugin should not try to do an modify internal, but just add the mods with the samba attributes to the client specified mods.

Then all mods are aborted or committed all together in a single transaction.

Regards,

Ludovic.

ludovicp at 2007-7-7 12:21:20 > top of Java-index,Web & Directory Servers,Directory Servers...
# 6
Assuming to follow Ludo's advise undoubtedly, Kusupudi could you even share your code with me? Infact I am just interested in auth&auth 802.1x wireless clients on DS...Thanks a lot.-roberto
rm102772 at 2007-7-7 12:21:20 > top of Java-index,Web & Directory Servers,Directory Servers...
# 7

Thanks Ludovic. I wish I would have asked your advise before writing. I will convert mine too pre-op also.

Roberto, I just grabed the md4 hash code from above samba web site and example post-op plugin code. It's going to be different since you will be writing pre-op. My code may not be that good since this is the only ldap plugin I wrote :-). If you are still interested let me know your email address.

For microsoft's 802.1x , VPN clients to work with sun's ldap, you need MSCHAPv2 supported Radius server such as steel belted etc and then configure radius server to look at sambaNTpassword for password verification.

Thanks & Regrds

Krishna Kusupudi

kkusupudi at 2007-7-7 12:21:20 > top of Java-index,Web & Directory Servers,Directory Servers...
# 8

Thanks Ludovic. I wish I would have asked your advise before writing. I will convert mine too pre-op also.

Roberto, I just grabed the md4 hash code from above samba web site and example post-op plugin code. It's going to be different since you will be writing pre-op. My code may not be that good since this is the only ldap plugin I wrote :-). If you are still interested let me know your email address.

For microsoft's 802.1x , VPN clients to work with sun's ldap, you need MSCHAPv2 supported Radius server such as steel belted etc and then configure radius server to look at sambaNTpassword for password verification.

kusupudi at 2007-7-7 12:21:20 > top of Java-index,Web & Directory Servers,Directory Servers...
# 9

Hello,

about Radius 802.1x sambaNTPassword verificarion, it is not clear to me if Radius uses a BIND ldap with the user's credentials who is trying to access the network, or if it uses a proxy authentication and simply looks for the attribute sambaNTPassword and then checks if the MD4 hash is correct. Do you know it?

In the first case I could use a role-based CoS which sets nsaccountlock to disable network access, otherwise...

Thanks.

-roberto

rm102772 at 2007-7-7 12:21:20 > top of Java-index,Web & Directory Servers,Directory Servers...
# 10
KirshnaI know some guys from a University looking for the same plugin. Is there any chance to share your plugin with them? :)Peter
Peter_Fabian at 2007-7-7 12:21:20 > top of Java-index,Web & Directory Servers,Directory Servers...
# 11
I would be interested in such a plugin for our department at a university. Thanks :-)
philforrest at 2007-7-7 12:21:20 > top of Java-index,Web & Directory Servers,Directory Servers...
# 12

Sorry I didn't look at this thread from a while. Following 4 files has source code, documentation, make file and LDIF file. This plugin is running in our servers from last 6 months only but never crashed or leaked memory so far :-). This was tested working for Microsoft VPN and/or 802.11x wireless clients using Steel Belted Radius server in the middle. If you guys want binary executable of this plugin for DS 5.2 Solaris or following 4 files transferred to you by FTP, HTTP or something, please send me that information to kusupudi@hotmail.com.

1. README

2. add_adpasshash_plugin.ldif

3. makefile_adpasshash

4. adpasshash.c

Thanks & Regrds

Krishna Kusupudi

$ cat README

INSTALLATION INSTRUCTIONS:

1. Add schema for adpwd attribute to all masters.

2. Update ACLs to assign same sensitivity level as userpassword to adpwd.

3. Copy plugin to master server as follows:

A. login to master Directory server as user server running as

B. cd <server-root>/lib/64

C. cp <your-dir>/adpasshash-plugin.so .

4. Add the configuration entry to the Master directory. For example:

ldapmodify -a -h <ldaphost> -D "cn=directory manager" -w <password> -f add_adpasshash_plugin.ldif

5. Restart the Directory server.

6. Repeat the above for each master server.

PLUGIN COMPILATION INSTRUCTIONS:

1. Install DS 5.2 first on any solaris server. example ldaphost

2. A. Login to Ldaphost

B. cd <server-root>/plugins/slapd/slapi/examples

C. cp <your-dir>/adpasshash.c .

D. cp <your-dir>/makefile_adpasshash .

E. make -f makefile_adpasshash

3. Now you have successfully created plugin .so file in Ldaphost under

/<server-root>/plugins/slapd/slapi/examples/64

Follow above Installation instructions to do Install

PLUGIN FUNCTIONALITY:

1. Purpose of this plugin is to support MSCHAP-v2 for Microsoft clients such as 802.11x and Microsoft VPN client which requires password to be in NT style MD4 hash.

2. This plugin intercepts password in clear text before it get hashed to SHA or SSHA into userpassword attribute and writes that password into another attribute with "MD4" hash or in "clear"

3. Take a look at add_adpasshash_plugin.ldif file. This plugin requires following 3 arguments:

nsslapd-pluginarg0: adpwd

nsslapd-pluginarg1: md4 [ or clear ]

nsslapd-pluginarg2: o=ad.com

arg0 is the name of the attribute you want to store password.

arg1 takes two values currently, either md4 or clear. Don't use clear for security reasons unless you really need to sync passwords from Meta directory

arg2 takes name of the suffix you want to run plugin against, set it to o=example.com. We added this argument because we don't want plugin to apply to "cn=changelog" or "o=netscaperoot" suffixes.

4. Plugin takes no action, if userpassword value coming across the wire is already hashed, such as if it begins with "{SHA}" or "{SSHA}"

TEST RESULTS:

A. 1000 password updates took 100 seconds with out plugin and 114 seconds with plugin. This is due to fact that this is a post-op plugin where each password update generates additional mod. I am thinking about converting this to pre-op when I have a free time.

B. Never crashed slapd, Running from last 6 months with no slapd crash or memory leaks so far.

- --

$ cat add_adpasshash_plugin.ldif

dn: cn=AD Passhash,cn=plugins,cn=config

objectClass: top

objectClass: nsSlapdPlugin

objectClass: extensibleObject

cn: AD Passhash

nsslapd-pluginPath: /opt/sunone/server5/lib/adpasshash-plugin.so

nsslapd-pluginInitfunc: postop_adpasshash_init

nsslapd-pluginType: postoperation

nsslapd-pluginEnabled: on

nsslapd-plugin-depends-on-type: database

nsslapd-pluginId: postop-adpasshash

nsslapd-pluginVersion: 1.0

nsslapd-pluginVendor: Krishna Kusupudi (kusupudi@hotmail.com)

nsslapd-pluginDescription: plug-in for hashing password with given hash type

nsslapd-pluginarg0: adpwd

nsslapd-pluginarg1: md4

nsslapd-pluginarg2: o=example.com

- --

$ cat makefile_adpasshash

#

# Copyright 2002 Sun Microsystems, Inc. All Rights Reserved

# Use of this product is subject to license terms.

#

# SOLARIS Makefile for 64-bit Directory Server plug-in examples

#

CC = cc

LD = ld

INCLUDE_FLAGS = -I../include

#CFLAGS = $(INCLUDE_FLAGS) -D_REENTRANT -KPIC -xarch=v9 -DUSE_64

CFLAGS = $(INCLUDE_FLAGS) -fPIC -m64

LDFLAGS = -G

#LDFLAGS = -shared

DIR64 = 64

OBJS = adpasshash.o

all: MKDIR64 $(DIR64)/adpasshash-plugin.so

MKDIR64:

@if [ ! -d $(DIR64) ]; then mkdir $(DIR64); fi

$(DIR64)/adpasshash-plugin.so: $(OBJS)

$(LD) $(LDFLAGS) -o $@ $(OBJS)

.c.o:

$(CC) $(CFLAGS) -c $<

clean:

-rm -f $(OBJS) adpasshash-plugin.so $(DIR64)/adpasshash-plugin.so

- -

$ cat adpasshash.c

/*

* Portions Copyright 2003 Sun Microsystems, Inc. All Rights Reserved

* Use is subject to license terms.

* Some preexisting portions Copyright 1997-2001 Netscape Communications Corp.

* All rights reserved.

* Rest of the code by krishna Kusupudi

* Created on: 02/15/2006, krishna Kusupudi

* Last modified: 09/20/2006

*/

/* ***************************************************************

Unix SMB/Netbios implementation.

Version 1.9.

a implementation of MD4 designed for use in the SMB authentication protocol

Copyright (C) Andrew Tridgell 1997

This program is free software; you can redistribute it and/or modify

it under the terms of the GNU General Public License as published by

the Free Software Foundation; either version 2 of the License, or

(at your option) any later version.

This program is distributed in the hope that it will be useful,

but WITHOUT ANY WARRANTY; without even the implied warranty of

MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

GNU General Public License for more details.

You should have received a copy of the GNU General Public License

along with this program; if not, write to the Free Software

Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

/************************************************************

adpasshash.c

This source file provides post-operation plug-in for capturing

password in clear text before it get hashed into "userPassword

attribute. It then copies that password to attribute you specify

as an argument to plugin in either md4 hash or in cleat text.

* postop_adpasshash_add(called after an LDAP add operation)

* postop_adpasshash_mod(called after an LDAP modify operation)

ACTIVATING THIS PLUG-IN

--

For more detailed information about this plugin, please read README file.

*************************************************************/

#include <stdio.h>

#include <string.h>

#include <ctype.h>

#include <time.h>

#ifndef _WIN32

#include <libgen.h>

#endif

#include "slapi-plugin.h"

Slapi_PluginDesc postop_desc = {

"postop-adpasshash", /* plug-in identifier */

"krishna Kusupudi.", /* vendor name*/

"1.0",/* plug-in revision number*/

"post-operation plug-in for generating hash password" /* plug-in description*/

};

static Slapi_ComponentId * postop_id; /* Used to set log, also called plugin_id */

typedef unsigned long int uint32;

static uint32 A, B, C, D;

static uint32 F(uint32 X, uint32 Y, uint32 Z)

{

return (X&Y) | ((~X)&Z);

}

static uint32 G(uint32 X, uint32 Y, uint32 Z)

{

return (X&Y) | (X&Z) | (Y&Z);

}

static uint32 H(uint32 X, uint32 Y, uint32 Z)

{

return X^Y^Z;

}

static uint32 lshift(uint32 x, int s)

{

x &= 0xFFFFFFFF;

return ((x<<s)&0xFFFFFFFF) | (x>>(32-s));

}

#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s)

#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32)0x5A827999,s)

#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s)

static void mdfour64(uint32 *M);

static void copy64(uint32 *M, unsigned char *in);

static void copy4(unsigned char *out,uint32 x);

int PutUniCode(char *dst,char *src);

void mdfour(unsigned char *out, unsigned char *in, int n);

int md4_hexa_hash(unsigned char *in, unsigned char *out);

int modify_secondpw(char *newpw_attrname, char *newpw, char *dn);

int issuffix_match(char * user_DN, char * plugin_suffix);

/* Capture clear text password for mod operation. */

int postop_adpasshash_mod(Slapi_PBlock * pb)

{

char* dn; /* DN of entry to modify*/

LDAPMod ** mods;/* Modifications to apply*/

intis_repl = 0;/* Is this replication?*/

intconnId, opId, rc = 0, rcode = 0;

longmsgId;

int iterator;

char * newpw = NULL;

char * newpw_md4 = NULL;

char ** argv; /* Args from configuration */

intargc; /* entry for plug-in.*/

rc |= slapi_pblock_get(pb, SLAPI_MODIFY_TARGET,&dn);

rc |= slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);

rc |= slapi_pblock_get(pb, SLAPI_OPERATION_MSGID, &msgId);

rc |= slapi_pblock_get(pb, SLAPI_CONN_ID,&connId);

rc |= slapi_pblock_get(pb, SLAPI_OPERATION_ID,&opId);

rc |= slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv);

rc |= slapi_pblock_get(pb, SLAPI_PLUGIN_ARGC, &argc);

rc |= slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rcode);

rc |= slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_repl);

/* if this is replicated event OR SLAPI_RESULT_CODE is not 0, ignore it */

if ((is_repl) || (rcode != 0) || (rc != 0)) {

return (rc);

}

/* Call this custom function to comapre user's suffix with plugins suffix */

if (issuffix_match(dn,argv[2]) != 0) {

return (0);

}

/* Cycle through the modifies and see if we have a password change */

for (iterator=0; mods[iterator] != NULL; iterator++)

{

if (strcasecmp(mods[iterator]->mod_type,"unhashed#user#password") == 0)

{

newpw = slapi_ch_malloc(strlen(mods[iterator]->mod_bvalues[0]->bv_val)* sizeof(char *));

newpw = slapi_ch_strdup(mods[iterator]->mod_bvalues[0]->bv_val);

/* Do nothing if the password is already hashed to SHA or SSHA */

if ((newpw == NULL) || (strncasecmp (newpw,"{SHA}",5) == 0) || (strncasecmp (newpw,"{SSHA}",6) == 0)) {

slapi_ch_free((void **)&newpw);

return (0);

}

if ( strcasecmp(argv[1],"clear") == 0 )

{

/* Call modify function to update second password attribute in clear */

rc = modify_secondpw(argv[0], newpw, dn);

}

else if ( strcasecmp(argv[1],"md4") == 0 )

{

newpw_md4 = slapi_ch_malloc(40); /* grab space for md4 hash */

/* call function md4_hexa_hash to get hash */

rc = md4_hexa_hash(newpw, newpw_md4);

if (rc == 0)

{

/* Call modify function to update second password attribute */

rc = modify_secondpw(argv[0], newpw_md4, dn);

}

/* Free the memory allocated by slapi_ch_malloc */

slapi_ch_free((void **) &newpw_md4);

} /* End of if ( strcasecmp(argv[1] */

slapi_ch_free((void **)&newpw);

} /* End of if (strcasecmp(mods[iterator] */

} /* End of for (iterator=0; */

return (0);

} /* End of postop_adpasshash_mod(Slapi_PBlock * pb) */

/* Capture clear text password for add operation. */

int postop_adpasshash_add(Slapi_PBlock * pb)

{

char* dn; /* DN of entry to modify*/

Slapi_Entry * entry;/* Entry to add*/

Slapi_Attr * attribute;/* Entry attributes*/

Slapi_Value * value;/* Attribute values*/

intis_repl = 0;/* Is this replication?*/

intconnId, opId, rc = 0, rcode = 0;

longmsgId;

const char * string; /* Holder for current password.*/

char * newpw = NULL;

char * newpw_md4 = NULL;

char ** argv; /* Args from configuration*/

intargc; /* entry for plug-in.*/

rc |= slapi_pblock_get(pb, SLAPI_ADD_TARGET,&dn);

rc |= slapi_pblock_get(pb, SLAPI_ADD_ENTRY,&entry);

rc |= slapi_pblock_get(pb, SLAPI_OPERATION_MSGID,&msgId);

rc |= slapi_pblock_get(pb, SLAPI_CONN_ID,&connId);

rc |= slapi_pblock_get(pb, SLAPI_OPERATION_ID,&opId);

rc |= slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv);

rc |= slapi_pblock_get(pb, SLAPI_PLUGIN_ARGC, &argc);

rc |= slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rcode);

rc |= slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_repl);

/* if this is replicated event OR SLAPI_RESULT_CODE is not 0, ignore it */

if ((is_repl) || (rcode != 0) || (rc != 0)) {

return (rc);

}

/* Call this custom function to comapre user's suffix with plugins suffix */

if (issuffix_match(dn,argv[2]) != 0) {

return (0);

}

/* Check in the entry to see if it has password in it */

newpw = slapi_entry_attr_get_charptr(entry, "unhashed#user#password");

/* Do nothing if the password is already hashed to SHA or SSHA or is null */

if ((newpw == NULL) || (strncasecmp (newpw,"{SHA}",5) == 0) || (strncasecmp (newpw,"{SSHA}",6) == 0)) {

slapi_ch_free((void **)&newpw);

return (0);

}

if ( strcasecmp(argv[1],"clear") == 0 ) {

/* Call modify function to update second password attribute in clear */

rc = modify_secondpw(argv[0], newpw, dn);

}

else if ( strcasecmp(argv[1],"md4") == 0 ) {

newpw_md4 = slapi_ch_malloc(40); /* grab space for md4 hash */

/* call function md4_hexa_hash to get hash */

rc = md4_hexa_hash(newpw, newpw_md4);

if (rc == 0) {

/* Call modify function to update second password attribute */

rc = modify_secondpw(argv[0], newpw_md4, dn);

}

/* Free the memory allocated by slapi_ch_malloc */

slapi_ch_free((void **) &newpw_md4);

} /* End of if strcasecmp(argv[1] */

slapi_ch_free((void **)&newpw);

return (0);

} /* End of postop_adpasshash_add(Slapi_PBlock * pb) */

/* Register the plug-in with the server. */

#ifdef _WIN32

__declspec(dllexport)

#endif

int

postop_adpasshash_init(Slapi_PBlock * pb)

{

int rc = 0;/* 0 means success*/

inti;

char ** argv; /* Args from configuration */

intargc; /* entry for plug-in.*/

rc |= slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv);

rc |= slapi_pblock_get(pb, SLAPI_PLUGIN_ARGC, &argc);

if (rc != 0 || argc !=3 || argv[0] == NULL || argv[1] == NULL || argv[2] == NULL) {

slapi_log_error_ex(

-1, /* errorId */

SLAPI_LOG_NO_MSGID,

SLAPI_LOG_NO_CONNID,

SLAPI_LOG_NO_OPID,

"postop_adpasshash_init",

"postop_adpasshash plug-in",

"Failed to get plugin arguments\n",

NULL

);

return (-1);

} /* End of if (rc != 0 */

rc |= slapi_pblock_set(/* Plug-in API version*/

pb,

SLAPI_PLUGIN_VERSION,

SLAPI_PLUGIN_CURRENT_VERSION

);

rc |= slapi_pblock_set(/* Plug-in description*/

pb,

SLAPI_PLUGIN_DESCRIPTION,

(void *) &postop_desc

);

rc |= slapi_pblock_set(/* Post-op add function*/

pb,

SLAPI_PLUGIN_POST_ADD_FN,

(void *) postop_adpasshash_add

);

rc |= slapi_pblock_set(/* Post-op modify function*/

pb,

SLAPI_PLUGIN_POST_MODIFY_FN,

(void *) postop_adpasshash_mod

);

/* Plug-in identifier is required for internal search.*/

rc |= slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &postop_id);

return (rc);

}

/* THis function checks if the suffix of an entry is the one provided in ARGV[2] */

int issuffix_match (char * user_DN, char * plugin_suffix)

{

Slapi_DN * comp_user_DN;/* Copy of user's DN that we normalize*/

Slapi_DN * comp_plugin_suffix;/* suffix of user's entry*/

comp_user_DN = slapi_sdn_new();

comp_plugin_suffix = slapi_sdn_new();

slapi_sdn_init_dn_byref(comp_user_DN,user_DN);

slapi_sdn_init_dn_byref(comp_plugin_suffix,plugin_suffix);

if (slapi_sdn_issuffix(comp_user_DN,comp_plugin_suffix) == 0)

{

slapi_sdn_free(&comp_user_DN);

slapi_sdn_free(&comp_plugin_suffix);

return (-1);

}

slapi_sdn_free(&comp_user_DN);

slapi_sdn_free(&comp_plugin_suffix);

return (0);

} /* End of int issuffix_match */

/* This function generates NT hash md4 in hexa format */

int md4_hexa_hash(unsigned char *in, unsigned char *out)

{

char *hold = NULL;

#define NTPASSWDLEN 128

char * prefix = "{md4}";

char passwd[NTPASSWDLEN+1];

int i,uni_len;

unsigned char *p16 = NULL;

char outbuffer[33];

unsigned char c;

hold = slapi_ch_malloc(NTPASSWDLEN * 2); /* grab space for unicode */

if (hold == NULL) return NULL;

strncpy(passwd,in,NTPASSWDLEN);

passwd[NTPASSWDLEN]='\0';

uni_len = PutUniCode(hold, passwd); /* convert to unicode and

return correct unicode length for md4 */

p16 = slapi_ch_malloc(17); /* grab space for md4 hash */

if (p16 == NULL) return NULL;

memset(p16,'\0',17);

mdfour(p16,hold, uni_len);

/* Convert hash from binary to hexa */

for(i=0;i<16;i++) {

c=p16;

sprintf(outbuffer+2*i,"%x",(c>>4) & 0x0f);

sprintf(outbuffer+2*i+1,"%x",c & 0x0f);

}

/* convert to uppercase */

for(i=0;i<32;i++)

outbuffer = toupper(outbuffer);

outbuffer[32]='\0';

/* Prefix {md4} to the hexa string to make it work with Steel Belted Radius */

sprintf (out, "%s%s", prefix, outbuffer);

/* Free the memory allocated by slapi_ch_malloc */

slapi_ch_free((void **) &hold);

slapi_ch_free((void **) &p16);

slapi_ch_free_string(&prefix);

return (0);

} /* End of md4_hexa_hash function */

/* This function adds second password attribute to server */

int modify_secondpw(char *newpw_attrname, char *newpw, char *dn)

{

Slapi_Entry* entry;/* Entry holder for internal ops */

Slapi_PBlock* pbin;/* PBlock for internal ops*/

LDAPMod mod_attr; /* Attribute to modify*/

LDAPMod* modsare[2]; /* Array of modifications*/

char* newpw_vals[] = { newpw, NULL}; /* second password attr value */

intrc = 0;

mod_attr.mod_type= newpw_attrname;

mod_attr.mod_op= LDAP_MOD_REPLACE;

mod_attr.mod_values = newpw_vals;

modsare[0] = &mod_attr;

modsare[1] = NULL;

pbin = slapi_pblock_new();/* Set up a PBlock... */

rc = slapi_modify_internal_set_pb(

pbin,

dn,

modsare,

NULL, /* No controls*/

NULL, /* DN rather than unique ID*/

postop_id,

SLAPI_OP_FLAG_NEVER_CHAIN/* Never chain this operation.*/

);

if (rc != 0) {

slapi_pblock_destroy(pbin);

return (-1);

}

rc = slapi_modify_internal_pb(pbin); /* Unlike internal add, */

/* nothing consumed here */

/* ... get status ...*/

slapi_pblock_get(pbin, SLAPI_PLUGIN_INTOP_RESULT, &rc);

if (rc != LDAP_SUCCESS) {

slapi_pblock_destroy(pbin);

return (-1);

}

slapi_pblock_destroy(pbin); /* ... clean up the PBlock.*/

return (0);

} /* End of modify_secondpw function */

/*******************************************************************

write a string in unicoode format

********************************************************************/

int PutUniCode(char *dst,char *src)

{

int ret = 0;

while (*src) {

dst[ret++] = src[0];

dst[ret++] = 0;

src++;

}

dst[ret++]=0;

dst[ret++]=0;

return(ret-2); /* the way they do the md4 hash they don't represent

the last null. ie 'A' becomes just 0x41 0x00 - not

0x41 0x00 0x00 0x00 */

}

/* End of function PutUniCode */

/* this applies md4 to 64 byte chunks */

static void mdfour64(uint32 *M)

{

int j;

uint32 AA, BB, CC, DD;

uint32 X[16];

for (j=0;j<16;j++)

X[j] = M[j];

AA = A; BB = B; CC = C; DD = D;

ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7);

ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19);

ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7);

ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19);

ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7);

ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19);

ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);

ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19);

ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);

ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13);

ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);

ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13);

ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5);

ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13);

ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5);

ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13);

ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9);

ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15);

ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9);

ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15);

ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9);

ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15);

ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);

ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15);

A += AA; B += BB; C += CC; D += DD;

A &= 0xFFFFFFFF; B &= 0xFFFFFFFF;

C &= 0xFFFFFFFF; D &= 0xFFFFFFFF;

for (j=0;j<16;j++)

X[j] = 0;

}

static void copy64(uint32 *M, unsigned char *in)

{

int i;

for (i=0;i<16;i++)

M = (in[i*4+3]<<24) | (in[i*4+2]<<16) |

(in[i*4+1]<<8) | (in[i*4+0]<<0);

}

static void copy4(unsigned char *out,uint32 x)

{

out[0] = x&0xFF;

out[1] = (x>>8)&0xFF;

out[2] = (x>>16)&0xFF;

out[3] = (x>>24)&0xFF;

}

/* produce a md4 message digest from data of length n bytes */

void mdfour(unsigned char *out, unsigned char *in, int n)

{

unsigned char buf[128];

uint32 M[16];

uint32 b = n * 8;

int i;

A = 0x67452301;

B = 0xefcdab89;

C = 0x98badcfe;

D = 0x10325476;

while (n > 64) {

copy64(M, in);

mdfour64(M);

in += 64;

n -= 64;

}

for (i=0;i<128;i++)

buf = 0;

memcpy(buf, in, n);

buf[n] = 0x80;

if (n <= 55) {

copy4(buf+56, b);

copy64(M, buf);

mdfour64(M);

} else {

copy4(buf+120, b);

copy64(M, buf);

mdfour64(M);

copy64(M, buf+64);

mdfour64(M);

}

for (i=0;i<128;i++)

buf = 0;

copy64(M, buf);

copy4(out, A);

copy4(out+4, B);

copy4(out+8, C);

copy4(out+12, D);

A = B = C = D = 0;

}

kusupudi at 2007-7-7 12:21:20 > top of Java-index,Web & Directory Servers,Directory Servers...