[Date Prev][Date Next] [Chronological] [Thread] [Top]

R: Patch for NT 4.0 SAM MD4 password support (ITS#2099)



This is a multi-part message in MIME format.

------=_NextPart_000_0000_01C26364.32FA7770
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Ok,

I rewrote the whole ntmd4.c file, which is, of course, included in the
attached diff file.

I also changed the license stuff to meet OpenLDAP requirements.

Is it enough or I have to repost it from scratch?

Regards,

----------------------------------
Giampaolo Tomassoni
Assistenza rete e sistemi
Arezzo Telecomunicazione Srl
Via del Saracino, 57
I-52100 Arezzo - Italy
e-mail: g.tomassoni@ar-tel.it
   tel: +39-0575-301530
   fax: +39-0575-301570


> -----Messaggio originale-----
> Da: Kurt Zeilenga [mailto:openldap-its@OpenLDAP.org]
> Inviato: domenica 22 settembre 2002 17.54
> A: g.tomassoni@ar-tel.it
> Oggetto: Re: Patch for NT 4.0 SAM MD4 password support (ITS#2099)
>
>
> Your patch does not meet our contributing guidelines and, hence,
> cannot be accepted.  In particular, we require:
>   Patches MUST be redistributable and usable under the terms
>   of the OpenLDAP Public License.
>   http://www.openldap.org/devel/contributing.html#copyright
>
> Your patch is only distributable under the terms of the GNU GPL.
>
> Kurt
>

------=_NextPart_000_0000_01C26364.32FA7770
Content-Type: application/octet-stream;
	name="openldap-2.1.4+ntpasswd.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="openldap-2.1.4+ntpasswd.diff"

diff -urdN ../openldap-2.1.4/configure ./configure=0A=
--- ../openldap-2.1.4/configure	Thu Aug 22 02:37:55 2002=0A=
+++ ./configure	Sun Sep 22 12:14:36 2002=0A=
@@ -75,6 +75,8 @@=0A=
 ac_help=3D"$ac_help=0A=
     --enable-lmpasswd	  enable LAN Manager passwords [no]"=0A=
 ac_help=3D"$ac_help=0A=
+    --enable-ntpasswd	  enable NT SAM password [no]"=0A=
+ac_help=3D"$ac_help=0A=
     --enable-spasswd	  enable (Cyrus) SASL password verification [no]"=0A=
 ac_help=3D"$ac_help=0A=
     --enable-modules	  enable dynamic module support [no]"=0A=
@@ -1845,11 +1847,28 @@=0A=
   	ol_enable_lmpasswd=3D"no"=0A=
 fi=0A=
 # end --enable-lmpasswd=0A=
+# OpenLDAP --enable-ntpasswd=0A=
+	# Check whether --enable-ntpasswd or --disable-ntpasswd was given.=0A=
+if test "${enable_ntpasswd+set}" =3D set; then=0A=
+	enableval=3D"$enable_ntpasswd"=0A=
+	ol_arg=3Dinvalid=0A=
+	for ol_val in auto yes no ; do=0A=
+		if test "$enableval" =3D "$ol_val" ; then=0A=
+			ol_arg=3D"$ol_val"=0A=
+		fi=0A=
+	done=0A=
+	if test "$ol_arg" =3D "invalid" ; then=0A=
+		{ echo "configure: error: bad value $enableval for --enable-ntpasswd" =
1>&2; exit 1; }=0A=
+	fi=0A=
+	ol_enable_ntpasswd=3D"$ol_arg"=0A=
+else=0A=
+  	ol_enable_ntpasswd=3D"no"=0A=
+fi=0A=
+# end --enable-ntpasswd=0A=
 # OpenLDAP --enable-spasswd=0A=
 	# Check whether --enable-spasswd or --disable-spasswd was given.=0A=
 if test "${enable_spasswd+set}" =3D set; then=0A=
   enableval=3D"$enable_spasswd"=0A=
-  =0A=
 	ol_arg=3Dinvalid=0A=
 	for ol_val in auto yes no ; do=0A=
 		if test "$enableval" =3D "$ol_val" ; then=0A=
@@ -1860,7 +1879,6 @@=0A=
 		{ echo "configure: error: bad value $enableval for --enable-spasswd" =
1>&2; exit 1; }=0A=
 	fi=0A=
 	ol_enable_spasswd=3D"$ol_arg"=0A=
-=0A=
 else=0A=
   	ol_enable_spasswd=3D"no"=0A=
 fi=0A=
@@ -11153,6 +11171,13 @@=0A=
 =0A=
 	cat >> confdefs.h <<\EOF=0A=
 #define SLAPD_LMHASH 1=0A=
+EOF=0A=
+=0A=
+fi=0A=
+=0A=
+if test $ol_enable_ntpasswd !=3D no; then=0A=
+	cat >> confdefs.h <<\EOF=0A=
+#define SLAPD_NTMD4 1=0A=
 EOF=0A=
 =0A=
 fi=0A=
diff -urdN ../openldap-2.1.4/configure.in ./configure.in=0A=
--- ../openldap-2.1.4/configure.in	Thu Aug 22 02:38:21 2002=0A=
+++ ./configure.in	Sun Sep 22 12:14:36 2002=0A=
@@ -1268,6 +1268,12 @@=0A=
 fi=0A=
 =0A=
 dnl ----------------------------------------------------------------=0A=
+dnl NT SAM MD4 password checking=0A=
+if test $ol_enable_lmpasswd !=3D no; then=0A=
+	AC_DEFINE(SLAPD_NTMD4, 1, [define to support NT 4.0 SAM passwords])=0A=
+fi=0A=
+=0A=
+dnl ----------------------------------------------------------------=0A=
 dnl Tests for reentrant functions necessary to build a=0A=
 dnl thread_safe -lldap.=0A=
 AC_CHECK_FUNCS(		\=0A=
diff -urdN ../openldap-2.1.4/include/portable.h.in =
./include/portable.h.in=0A=
--- ../openldap-2.1.4/include/portable.h.in	Thu Jun 20 22:12:27 2002=0A=
+++ ./include/portable.h.in	Sun Sep 22 12:14:36 2002=0A=
@@ -686,6 +686,9 @@=0A=
 /* define to support LAN Manager passwords */=0A=
 #undef SLAPD_LMHASH=0A=
 =0A=
+/* define to support NT SAM passwords */=0A=
+#undef SLAPD_NTMD4=0A=
+=0A=
 /* set to the number of arguments ctime_r() expects */=0A=
 #undef CTIME_R_NARGS=0A=
 =0A=
diff -urdN ../openldap-2.1.4/libraries/liblutil/Makefile.in =
./libraries/liblutil/Makefile.in=0A=
--- ../openldap-2.1.4/libraries/liblutil/Makefile.in	Sun Jul 28 21:18:14 =
2002=0A=
+++ ./libraries/liblutil/Makefile.in	Sun Sep 22 12:14:36 2002=0A=
@@ -15,10 +15,12 @@=0A=
 =0A=
 SRCS	=3D base64.c csn.c entropy.c sasl.c signal.c hash.c \=0A=
 	md5.c passwd.c sha1.c getpass.c lockf.c utils.c uuid.c sockpair.c \=0A=
+	ntmd4.c \=0A=
 	@LIBSRCS@ $(@PLAT@_SRCS)=0A=
 =0A=
 OBJS	=3D base64.o csn.o entropy.o sasl.o signal.o hash.o \=0A=
 	md5.o passwd.o sha1.o getpass.o lockf.o utils.o uuid.o sockpair.o \=0A=
+	ntmd4.o \=0A=
 	@LIBOBJS@ $(@PLAT@_OBJS)=0A=
 =0A=
 LDAP_INCDIR=3D ../../include       =0A=
@@ -33,4 +35,3 @@=0A=
 =0A=
 clean-local:=0A=
 	$(RM) *.res=0A=
-=0A=
diff -urdN ../openldap-2.1.4/libraries/liblutil/ntmd4.c =
./libraries/liblutil/ntmd4.c=0A=
--- ../openldap-2.1.4/libraries/liblutil/ntmd4.c	Thu Jan  1 01:00:00 1970=0A=
+++ ./libraries/liblutil/ntmd4.c	Mon Sep 23 22:30:13 2002=0A=
@@ -0,0 +1,345 @@=0A=
+/*=0A=
+   MD4 hashing for NT 4.0 passwords.=0A=
+=0A=
+   Copyright 2002 by Giampaolo Tomassoni, All rights reserved.=0A=
+   This software is not subject to any license.=0A=
+=0A=
+   Redistribution and use in source and binary forms are permitted=0A=
+   without restriction or fee of any kind as long as this notice=0A=
+   is preserved.=0A=
+*/=0A=
+=0A=
+/*=0A=
+   This file exports the function:=0A=
+=0A=
+	int ntmd4hash(uchar p16[16], const uchar* passwd)=0A=
+=0A=
+   The function gets a null-terminated password -which is assumed=0A=
+   to be a multibyte string according to the application's current=0A=
+   locale-, converts it to a UCS-2 string, pads it with nulls to fit=0A=
+   a 128 uint16 buffer, and finally computes its 16-bytes md4 hash.=0A=
+=0A=
+   The function yields FALSE (=3D0) if one or more characters in passwd=0A=
+   can't be converted to UCS-2 or if the conversion results in more=0A=
+   than 128 UCS-2 characters. Otherwise the function returns TRUE (=3D1)=0A=
+   and the p16[16] buffer contains the 16-bytes md4 hash.=0A=
+=0A=
+   At the time of this writing, ntmd4hash() is called by=0A=
+   passwd.c:hash_ntmd4().=0A=
+=0A=
+   A porting test may be accomplished making an executable of this=0A=
+   file specifing the option -DTEST at compile time.=0A=
+=0A=
+   Enjoy moving your NT 4.0 Domain to OpenLDAP!=0A=
+=0A=
+	2002-09-23 Giampaolo Tomassoni <g.tomassoni@ar-tel.it>=0A=
+*/=0A=
+=0A=
+#include "portable.h"=0A=
+=0A=
+#include <stdio.h>=0A=
+#include <wchar.h>=0A=
+=0A=
+typedef	unsigned long	uint32;=0A=
+typedef	unsigned short	uint16;=0A=
+typedef	unsigned char	uchar;=0A=
+=0A=
+=0A=
+/* NOTE: This code makes no attempt to be fast! =0A=
+   It assumes that a int is at least 32 bits long=0A=
+*/=0A=
+=0A=
+static uint32 	F(uint32 X, uint32 Y, uint32 Z)=0A=
+{ return((X&Y) | ((~X)&Z)); }=0A=
+=0A=
+static uint32 	G(uint32 X, uint32 Y, uint32 Z)=0A=
+{ return((X&Y) | (X&Z) | (Y&Z)); }=0A=
+=0A=
+static uint32 	H(uint32 X, uint32 Y, uint32 Z)=0A=
+{ return(X^Y^Z); }=0A=
+=0A=
+static uint32 	lshift(uint32 x, int s)=0A=
+{ return(((x<<s)&0xFFFFFFFF) | ((x&0xFFFFFFFF)>>(32-s))); }=0A=
+=0A=
+/* this applies md4 to 64 byte chunks */=0A=
+static void	mdfour64(uint32 V[4], const uint32 M[16])=0A=
+{=0A=
+	uint32	A =3D V[0],=0A=
+		B =3D V[1],=0A=
+		C =3D V[2],=0A=
+		D =3D V[3];=0A=
+=0A=
+#define ROUND1(a,b,c,d,k,s) a =3D lshift(a + F(b,c,d) + M[k], s)=0A=
+#define ROUND2(a,b,c,d,k,s) a =3D lshift(a + G(b,c,d) + M[k] + \=0A=
+		(uint32)0x5A827999, s)=0A=
+#define ROUND3(a,b,c,d,k,s) a =3D lshift(a + H(b,c,d) + M[k] + \=0A=
+		(uint32)0x6ED9EBA1, s)=0A=
+=0A=
+	ROUND1(A,B,C,D,  0,  3);  ROUND1(D,A,B,C,  1,  7);=0A=
+	ROUND1(C,D,A,B,  2, 11);  ROUND1(B,C,D,A,  3, 19);=0A=
+	ROUND1(A,B,C,D,  4,  3);  ROUND1(D,A,B,C,  5,  7);=0A=
+	ROUND1(C,D,A,B,  6, 11);  ROUND1(B,C,D,A,  7, 19);=0A=
+	ROUND1(A,B,C,D,  8,  3);  ROUND1(D,A,B,C,  9,  7);=0A=
+	ROUND1(C,D,A,B, 10, 11);  ROUND1(B,C,D,A, 11, 19);=0A=
+	ROUND1(A,B,C,D, 12,  3);  ROUND1(D,A,B,C, 13,  7);=0A=
+	ROUND1(C,D,A,B, 14, 11);  ROUND1(B,C,D,A, 15, 19);	=0A=
+=0A=
+	ROUND2(A,B,C,D,  0,  3);  ROUND2(D,A,B,C,  4,  5);=0A=
+	ROUND2(C,D,A,B,  8,  9);  ROUND2(B,C,D,A, 12, 13);=0A=
+	ROUND2(A,B,C,D,  1,  3);  ROUND2(D,A,B,C,  5,  5);=0A=
+	ROUND2(C,D,A,B,  9,  9);  ROUND2(B,C,D,A, 13, 13);=0A=
+	ROUND2(A,B,C,D,  2,  3);  ROUND2(D,A,B,C,  6,  5);=0A=
+	ROUND2(C,D,A,B, 10,  9);  ROUND2(B,C,D,A, 14, 13);=0A=
+	ROUND2(A,B,C,D,  3,  3);  ROUND2(D,A,B,C,  7,  5);=0A=
+	ROUND2(C,D,A,B, 11,  9);  ROUND2(B,C,D,A, 15, 13);=0A=
+=0A=
+	ROUND3(A,B,C,D,  0,  3);  ROUND3(D,A,B,C,  8,  9);=0A=
+	ROUND3(C,D,A,B,  4, 11);  ROUND3(B,C,D,A, 12, 15);=0A=
+	ROUND3(A,B,C,D,  2,  3);  ROUND3(D,A,B,C, 10,  9);=0A=
+	ROUND3(C,D,A,B,  6, 11);  ROUND3(B,C,D,A, 14, 15);=0A=
+	ROUND3(A,B,C,D,  1,  3);  ROUND3(D,A,B,C,  9,  9);=0A=
+	ROUND3(C,D,A,B,  5, 11);  ROUND3(B,C,D,A, 13, 15);=0A=
+	ROUND3(A,B,C,D,  3,  3);  ROUND3(D,A,B,C, 11,  9);=0A=
+	ROUND3(C,D,A,B,  7, 11);  ROUND3(B,C,D,A, 15, 15);=0A=
+=0A=
+#undef	ROUND3=0A=
+#undef	ROUND2=0A=
+#undef	ROUND1=0A=
+=0A=
+	V[0] =3D (V[0] + A) & 0xFFFFFFFF;=0A=
+	V[1] =3D (V[1] + B) & 0xFFFFFFFF;=0A=
+	V[2] =3D (V[2] + C) & 0xFFFFFFFF;=0A=
+	V[3] =3D (V[3] + D) & 0xFFFFFFFF;=0A=
+}=0A=
+=0A=
+static void	copy64(uint32* M, const uchar* in)=0A=
+{=0A=
+	int	i;=0A=
+	for(i =3D 0; i < 16; i++) {=0A=
+		M[i] =3D (in[3]<<24) | (in[2]<<16) | (in[1]<<8) | in[0];=0A=
+		in  +=3D 4;=0A=
+	}=0A=
+}=0A=
+=0A=
+static void	copy4(uchar* out, uint32 x)=0A=
+{=0A=
+	out[0] =3D (x>> 0)&0xFF;=0A=
+	out[1] =3D (x>> 8)&0xFF;=0A=
+	out[2] =3D (x>>16)&0xFF;=0A=
+	out[3] =3D (x>>24)&0xFF;=0A=
+}=0A=
+=0A=
+/* produce a md4 message digest from data of length n bytes */=0A=
+void 	mdfour(uchar out[16], const uchar* in, int n)=0A=
+{=0A=
+	uchar 	buf[128];=0A=
+	uint32	M[16];=0A=
+	uint32	V[4];=0A=
+	uint32 	b =3D n * 8;=0A=
+	int 	i;=0A=
+=0A=
+	V[0] =3D 0x67452301;=0A=
+	V[1] =3D 0xefcdab89;=0A=
+	V[2] =3D 0x98badcfe;=0A=
+	V[3] =3D 0x10325476;=0A=
+=0A=
+	while(n > 64) {=0A=
+		copy64(M, in);=0A=
+		mdfour64(V, M);=0A=
+		in +=3D 64;=0A=
+		n  -=3D 64;=0A=
+	}=0A=
+=0A=
+	memset(buf, 0, sizeof(buf));=0A=
+	memcpy(buf, in, n);=0A=
+	buf[n] =3D 0x80;=0A=
+=0A=
+	if(n <=3D 55) {=0A=
+		copy4(buf+56, b);=0A=
+		copy64(M, buf);=0A=
+		mdfour64(V, M);=0A=
+	} else {=0A=
+		copy4(buf+120, b); =0A=
+		copy64(M, buf);=0A=
+		mdfour64(V, M);=0A=
+		copy64(M, buf+64);=0A=
+		mdfour64(V, M);=0A=
+	}=0A=
+=0A=
+	memset(buf, 0, sizeof(buf));=0A=
+	copy64(M, buf);=0A=
+=0A=
+	copy4(&out[ 0], V[0]);=0A=
+	copy4(&out[ 4], V[1]);=0A=
+	copy4(&out[ 8], V[2]);=0A=
+	copy4(&out[12], V[3]);=0A=
+=0A=
+	memset(V, 0, sizeof(V));=0A=
+}=0A=
+=0A=
+/* =0A=
+ * Creates the MD4 Hash of the users password in NT UNICODE.=0A=
+ */=0A=
+#define	CWMAX	128=0A=
+int	ntmd4hash(uchar p16[16], const char* passwd)=0A=
+{=0A=
+	uint16	wpwd[CWMAX];=0A=
+	uint16*	pwpwd;=0A=
+	int 	wlen;=0A=
+	int	n;=0A=
+=0A=
+	/* Password must be converted to NT unicode (i.e.: UCS-2) */=0A=
+	n =3D strlen(passwd);=0A=
+	for(pwpwd =3D wpwd; pwpwd < &wpwd[CWMAX] && n > 0; ++pwpwd) {=0A=
+		wchar_t		wc;=0A=
+		const int	nc =3D mbtowc(&wc, passwd, n);=0A=
+=0A=
+		if(nc <=3D 0 || (wc>>16) !=3D 0) {=0A=
+			/* The password failed unicode conversion or	*=0A=
+			* is too long.					*/=0A=
+			memset(wpwd, 0, sizeof(wpwd));=0A=
+			return(0);=0A=
+		}=0A=
+=0A=
+		passwd	+=3D nc;=0A=
+		n	-=3D nc;=0A=
+		*pwpwd	=3D (uint16)wc;=0A=
+	}=0A=
+=0A=
+	/* Computes final size of the UCS-2 version of passwd */=0A=
+	wlen =3D (int)(pwpwd - wpwd);=0A=
+=0A=
+	/* Right-pads with null */=0A=
+	memset(pwpwd, 0, (CWMAX - wlen) * sizeof(*wpwd));=0A=
+=0A=
+	/* Inits hashed output and starts MD4 hash computing */=0A=
+	memset(p16, 0, sizeof(p16));=0A=
+	mdfour(p16, (uchar*)wpwd, wlen * sizeof(*wpwd));=0A=
+=0A=
+	/* Security reasons impose to clear the UCS-2 version of the	*=0A=
+	* cleartext password...						*/=0A=
+	memset(wpwd, 0, sizeof(wpwd));=0A=
+=0A=
+	/* Conversion successfully accomplished */=0A=
+	return(1);=0A=
+}=0A=
+=0A=
+#ifdef	TEST=0A=
+static void	PrintIt(const uchar p[16])=0A=
+{=0A=
+	int	i;=0A=
+=0A=
+	for(i =3D 0; i < 16; ++i)=0A=
+		printf("%02X", p[i]);=0A=
+}=0A=
+=0A=
+#ifndef	LC_CTYPE=0A=
+#	include	<locale.h>=0A=
+#endif=0A=
+=0A=
+int	main(int argc, char** argv)=0A=
+{=0A=
+	static const char*	nmLocale     =3D "it_IT";	/* Locale for test */=0A=
+	static const char*	aPasswords[] =3D {=0A=
+		"",=0A=
+		"test",=0A=
+		"SiMpLeMiNdEd",=0A=
+		"\305-unit",=0A=
+		"\340ncora",		/* IT for anchor		*/=0A=
+		"anc\362ra",		/* IT for again			*/=0A=
+		"stra\337e",		/* GE for street		*/=0A=
+		"t\351l\351ph\351rique"	/* FR for IT teleferica :)	*/=0A=
+	};=0A=
+	static const uchar	aHashes[] =3D {=0A=
+		/* "" */=0A=
+		0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,=0A=
+		0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0,=0A=
+=0A=
+		/* "test" */=0A=
+		0x0C, 0xB6, 0x94, 0x88, 0x05, 0xF7, 0x97, 0xBF,=0A=
+		0x2A, 0x82, 0x80, 0x79, 0x73, 0xB8, 0x95, 0x37,=0A=
+=0A=
+		/* "SiMpLeMiNdEd" */=0A=
+		0xDF, 0x81, 0x06, 0xDB, 0x08, 0x84, 0x85, 0x0A,=0A=
+		0xE7, 0xE9, 0xF8, 0xEF, 0x0B, 0x7C, 0xC9, 0x0F,=0A=
+=0A=
+		/* "\305-unit" */=0A=
+		0x24, 0xBA, 0x2C, 0xF6, 0xF1, 0xC8, 0x70, 0x24,=0A=
+		0x19, 0x8F, 0xA5, 0x08, 0x09, 0x30, 0xBC, 0xB6,=0A=
+=0A=
+		/* "\340ncora" */=0A=
+		0xEC, 0x02, 0x38, 0xD8, 0xF0, 0x85, 0x96, 0x7B,=0A=
+		0xAF, 0x24, 0x0E, 0xE1, 0xD2, 0x6C, 0x54, 0x0C,=0A=
+=0A=
+		/* "anc\362ra" */=0A=
+		0x99, 0x53, 0x70, 0xEE, 0xE5, 0xB3, 0xD0, 0x2D,=0A=
+		0x70, 0x53, 0xB9, 0xB2, 0x28, 0x11, 0x98, 0x27,=0A=
+=0A=
+		/* "stra\337e" */=0A=
+		0x68, 0xF0, 0x84, 0x7D, 0xE0, 0x5B, 0xDE, 0xFE,=0A=
+		0xF9, 0x80, 0xC8, 0x45, 0x98, 0x76, 0x3A, 0x71,=0A=
+=0A=
+		/* "t\351l\351ph\351rique" */=0A=
+		0xEB, 0xFE, 0x00, 0x6C, 0x00, 0x66, 0xA4, 0x9F,=0A=
+		0xEE, 0xF9, 0xD6, 0xA9, 0x35, 0x23, 0x17, 0x42=0A=
+	};=0A=
+	uchar	p[16];=0A=
+	int	rv =3D 0;=0A=
+	int	i;=0A=
+=0A=
+	if(setlocale(LC_ALL, "") =3D=3D NULL) {=0A=
+		perror("setting user-defined locale");=0A=
+		fputs("Test can't be performed.\n", stderr);=0A=
+		return(2);=0A=
+	}=0A=
+=0A=
+	if(argc > 1) {=0A=
+		for(i =3D 1; i < argc; ++i) {=0A=
+			putchar('"');=0A=
+			fputs(argv[1], stdout);=0A=
+			putchar('"');=0A=
+=0A=
+			if(ntmd4hash(p, argv[1])) {=0A=
+				PrintIt(p);=0A=
+				putchar('\n');=0A=
+			} else {=0A=
+				puts(": UCS-2 conversion FAILED!!!");=0A=
+				rv =3D 1;=0A=
+			}=0A=
+		}=0A=
+	} else {=0A=
+		if(setlocale(LC_CTYPE, nmLocale) =3D=3D NULL) {=0A=
+			perror("setting locale");=0A=
+			fprintf(=0A=
+				stderr,=0A=
+				"Test can't be performed without setting locale %s.\n",=0A=
+				nmLocale=0A=
+			);=0A=
+			return(2);=0A=
+		}=0A=
+=0A=
+		for(i =3D 0 ; i < sizeof(aPasswords)/sizeof(*aPasswords); ++i) {=0A=
+			putchar('"');=0A=
+			fputs(aPasswords[i], stdout);=0A=
+			putchar('"');=0A=
+=0A=
+			if(ntmd4hash(p, aPasswords[i])) {=0A=
+				fputs(" -> 0x", stdout);=0A=
+				PrintIt(p);=0A=
+=0A=
+				if(memcmp(p, &aHashes[16*i], sizeof(p)) =3D=3D 0)=0A=
+					puts(": Ok\n");=0A=
+				else {=0A=
+					puts(": MISMATCH!!!");=0A=
+					rv =3D 1;=0A=
+				}=0A=
+			} else {=0A=
+				puts(": UCS-2 conversion FAILED!!!");=0A=
+				rv =3D 1;=0A=
+			}=0A=
+		}=0A=
+	}=0A=
+=0A=
+	return(rv);=0A=
+}=0A=
+#endif	/* TEST */=0A=
diff -urdN ../openldap-2.1.4/libraries/liblutil/passwd.c =
./libraries/liblutil/passwd.c=0A=
--- ../openldap-2.1.4/libraries/liblutil/passwd.c	Fri Aug 16 19:30:47 =
2002=0A=
+++ ./libraries/liblutil/passwd.c	Mon Sep 23 22:25:05 2002=0A=
@@ -124,6 +124,82 @@=0A=
 	const struct berval *cred );=0A=
 #endif=0A=
 =0A=
+/* pw_string is only called when SLAPD_LMHASH, SLAPD_CRYPT or =
SLAPD_NTMD4=0A=
+   is defined */=0A=
+#if defined(SLAPD_LMHASH) || defined(SLAPD_CRYPT) || =
defined(SLAPD_NTMD4)=0A=
+static struct berval*	pw_string(=0A=
+	const struct pw_scheme*	sc,=0A=
+	const struct berval*	passwd=0A=
+) {=0A=
+	struct berval *pw =3D ber_memalloc( sizeof( struct berval ) );=0A=
+	if( pw =3D=3D NULL ) return NULL;=0A=
+=0A=
+	pw->bv_len =3D sc->name.bv_len + passwd->bv_len;=0A=
+	pw->bv_val =3D ber_memalloc( pw->bv_len + 1 );=0A=
+=0A=
+	if( pw->bv_val =3D=3D NULL ) {=0A=
+		ber_memfree( pw );=0A=
+		return NULL;=0A=
+	}=0A=
+=0A=
+	AC_MEMCPY( pw->bv_val, sc->name.bv_val, sc->name.bv_len );=0A=
+	AC_MEMCPY( &pw->bv_val[sc->name.bv_len], passwd->bv_val, =
passwd->bv_len );=0A=
+=0A=
+	pw->bv_val[pw->bv_len] =3D '\0';=0A=
+	return pw;=0A=
+}=0A=
+#endif /* SLAPD_LMHASH || SLAPD_CRYPT || SLAPD_NTMD4 */=0A=
+=0A=
+#ifdef	SLAPD_NTMD4=0A=
+static struct berval*	hash_ntmd4(=0A=
+	const struct pw_scheme*	scheme,=0A=
+	const struct berval*	passwd=0A=
+) {=0A=
+	extern int		ntmd4hash(=0A=
+		unsigned char	p16[16],=0A=
+		const char*	passwd=0A=
+	);=0A=
+	static const char	a16s[] =3D "0123456789abcdef";=0A=
+	struct berval		hash;=0A=
+	unsigned char		p16[16];=0A=
+	char			mdhash[2*sizeof(p16) + 1];=0A=
+	int			i;=0A=
+=0A=
+	for(i =3D 0; i < passwd->bv_len; i++)=0A=
+		if(passwd->bv_val[i] =3D=3D '\0')=0A=
+			/* NUL character in password */=0A=
+			return(NULL);=0A=
+=0A=
+	if(passwd->bv_val[i] !=3D '\0')=0A=
+		/* passwd must behave like a string */=0A=
+		return(NULL);=0A=
+=0A=
+	if(!ntmd4hash(p16, passwd->bv_val))=0A=
+		/* Password must be convertible to UCS-2 */=0A=
+		return(NULL);=0A=
+=0A=
+	for(i =3D 0; i < sizeof(p16)/sizeof(*p16); ++i) {=0A=
+		unsigned char	c =3D p16[i];=0A=
+		mdhash[2*i + 0] =3D a16s[c >> 4];=0A=
+		mdhash[2*i + 1] =3D a16s[c & 0x0f];=0A=
+	}=0A=
+	mdhash[2*i + 0] =3D '\0';=0A=
+=0A=
+	hash.bv_val =3D mdhash;=0A=
+	hash.bv_len =3D sizeof(mdhash) - 1;=0A=
+	return(pw_string(scheme, &hash));=0A=
+}=0A=
+=0A=
+static int	chk_ntmd4(=0A=
+	const struct pw_scheme*	scheme,=0A=
+	const struct berval*	passwd,=0A=
+	const struct berval*	cred=0A=
+) {=0A=
+	struct berval*	hash =3D hash_ntmd4(scheme, cred);=0A=
+	return(memcmp(&hash->bv_val[scheme->name.bv_len], passwd->bv_val, 32));=0A=
+}=0A=
+#endif	/* SLAPD_NTMD4 */=0A=
+=0A=
 #ifdef SLAPD_SPASSWD=0A=
 static int chk_sasl(=0A=
 	const struct pw_scheme *scheme,=0A=
@@ -204,6 +280,10 @@=0A=
 	{ {sizeof("{LANMAN}")-1, "{LANMAN}"},	chk_lanman, hash_lanman },=0A=
 #endif /* SLAPD_LMHASH */=0A=
 =0A=
+#ifdef SLAPD_NTMD4=0A=
+	{ {sizeof("{NT}")-1, "{NT}"},		chk_ntmd4, hash_ntmd4 },=0A=
+#endif /* SLAPD_NTMD4 */=0A=
+=0A=
 #ifdef SLAPD_SPASSWD=0A=
 	{ {sizeof("{SASL}")-1, "{SASL}"}, chk_sasl, NULL },=0A=
 #endif=0A=
@@ -375,31 +455,6 @@=0A=
 =0A=
 	return (sc->hash_fn)( sc, passwd );=0A=
 }=0A=
-=0A=
-/* pw_string is only called when SLAPD_LMHASH or SLAPD_CRYPT is defined =
*/=0A=
-#if defined(SLAPD_LMHASH) || defined(SLAPD_CRYPT)=0A=
-static struct berval * pw_string(=0A=
-	const struct pw_scheme *sc,=0A=
-	const struct berval *passwd )=0A=
-{=0A=
-	struct berval *pw =3D ber_memalloc( sizeof( struct berval ) );=0A=
-	if( pw =3D=3D NULL ) return NULL;=0A=
-=0A=
-	pw->bv_len =3D sc->name.bv_len + passwd->bv_len;=0A=
-	pw->bv_val =3D ber_memalloc( pw->bv_len + 1 );=0A=
-=0A=
-	if( pw->bv_val =3D=3D NULL ) {=0A=
-		ber_memfree( pw );=0A=
-		return NULL;=0A=
-	}=0A=
-=0A=
-	AC_MEMCPY( pw->bv_val, sc->name.bv_val, sc->name.bv_len );=0A=
-	AC_MEMCPY( &pw->bv_val[sc->name.bv_len], passwd->bv_val, =
passwd->bv_len );=0A=
-=0A=
-	pw->bv_val[pw->bv_len] =3D '\0';=0A=
-	return pw;=0A=
-}=0A=
-#endif /* SLAPD_LMHASH || SLAPD_CRYPT */=0A=
 =0A=
 static struct berval * pw_string64(=0A=
 	const struct pw_scheme *sc,=0A=

------=_NextPart_000_0000_01C26364.32FA7770--