xref: /netbsd-src/external/bsd/openldap/dist/libraries/liblutil/passwd.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1*549b59edSchristos /*	$NetBSD: passwd.c,v 1.9 2021/08/14 16:14:58 christos Exp $	*/
24e6df137Slukem 
3cb54be06Stron /* $OpenLDAP$ */
42de962bdSlukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
52de962bdSlukem  *
6*549b59edSchristos  * Copyright 1998-2021 The OpenLDAP Foundation.
72de962bdSlukem  * All rights reserved.
82de962bdSlukem  *
92de962bdSlukem  * Redistribution and use in source and binary forms, with or without
102de962bdSlukem  * modification, are permitted only as authorized by the OpenLDAP
112de962bdSlukem  * Public License.
122de962bdSlukem  *
132de962bdSlukem  * A copy of this license is available in the file LICENSE in the
142de962bdSlukem  * top-level directory of the distribution or, alternatively, at
152de962bdSlukem  * <http://www.OpenLDAP.org/license.html>.
162de962bdSlukem  */
172de962bdSlukem 
182de962bdSlukem /*
192de962bdSlukem  * int lutil_passwd(
202de962bdSlukem  *	const struct berval *passwd,
212de962bdSlukem  *	const struct berval *cred,
222de962bdSlukem  *	const char **schemes )
232de962bdSlukem  *
242de962bdSlukem  * Returns true if user supplied credentials (cred) matches
252de962bdSlukem  * the stored password (passwd).
262de962bdSlukem  *
272de962bdSlukem  * Due to the use of the crypt(3) function
282de962bdSlukem  * this routine is NOT thread-safe.
292de962bdSlukem  */
302de962bdSlukem 
31915bea73Schristos #include <sys/cdefs.h>
32*549b59edSchristos __RCSID("$NetBSD: passwd.c,v 1.9 2021/08/14 16:14:58 christos Exp $");
33915bea73Schristos 
342de962bdSlukem #include "portable.h"
352de962bdSlukem 
362de962bdSlukem #include <stdio.h>
372de962bdSlukem #include <ac/stdlib.h>
382de962bdSlukem #include <ac/string.h>
39f8fd1d3cSlukem #include <ac/time.h>
402de962bdSlukem #include <ac/unistd.h>
412de962bdSlukem #include <ac/param.h>
422de962bdSlukem 
432de962bdSlukem #ifdef SLAPD_CRYPT
442de962bdSlukem # include <ac/crypt.h>
452de962bdSlukem 
462de962bdSlukem # if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD )
472de962bdSlukem #  ifdef HAVE_SHADOW_H
482de962bdSlukem #	include <shadow.h>
492de962bdSlukem #  endif
502de962bdSlukem #  ifdef HAVE_PWD_H
512de962bdSlukem #	include <pwd.h>
522de962bdSlukem #  endif
532de962bdSlukem #  ifdef HAVE_AIX_SECURITY
542de962bdSlukem #	include <userpw.h>
552de962bdSlukem #  endif
562de962bdSlukem # endif
572de962bdSlukem #endif
582de962bdSlukem 
592de962bdSlukem #include <lber.h>
602de962bdSlukem 
612de962bdSlukem #include "ldap_pvt.h"
622de962bdSlukem #include "lber_pvt.h"
632de962bdSlukem 
642de962bdSlukem #include "lutil_md5.h"
652de962bdSlukem #include "lutil_sha1.h"
662de962bdSlukem #include "lutil.h"
672de962bdSlukem 
682de962bdSlukem static const unsigned char crypt64[] =
692de962bdSlukem 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
702de962bdSlukem 
712de962bdSlukem #ifdef SLAPD_CRYPT
722de962bdSlukem static char *salt_format = NULL;
732de962bdSlukem static lutil_cryptfunc lutil_crypt;
742de962bdSlukem lutil_cryptfunc *lutil_cryptptr = lutil_crypt;
752de962bdSlukem #endif
762de962bdSlukem 
772de962bdSlukem /* KLUDGE:
782de962bdSlukem  *  chk_fn is NULL iff name is {CLEARTEXT}
792de962bdSlukem  *	otherwise, things will break
802de962bdSlukem  */
812de962bdSlukem struct pw_scheme {
822de962bdSlukem 	struct berval name;
832de962bdSlukem 	LUTIL_PASSWD_CHK_FUNC *chk_fn;
842de962bdSlukem 	LUTIL_PASSWD_HASH_FUNC *hash_fn;
852de962bdSlukem };
862de962bdSlukem 
872de962bdSlukem struct pw_slist {
882de962bdSlukem 	struct pw_slist *next;
892de962bdSlukem 	struct pw_scheme s;
902de962bdSlukem };
912de962bdSlukem 
922de962bdSlukem /* password check routines */
932de962bdSlukem 
942de962bdSlukem #define	SALT_SIZE	4
952de962bdSlukem 
962de962bdSlukem static LUTIL_PASSWD_CHK_FUNC chk_md5;
972de962bdSlukem static LUTIL_PASSWD_CHK_FUNC chk_smd5;
982de962bdSlukem static LUTIL_PASSWD_HASH_FUNC hash_smd5;
992de962bdSlukem static LUTIL_PASSWD_HASH_FUNC hash_md5;
1002de962bdSlukem 
1012de962bdSlukem 
1022de962bdSlukem #ifdef LUTIL_SHA1_BYTES
1032de962bdSlukem static LUTIL_PASSWD_CHK_FUNC chk_ssha1;
1042de962bdSlukem static LUTIL_PASSWD_CHK_FUNC chk_sha1;
1052de962bdSlukem static LUTIL_PASSWD_HASH_FUNC hash_sha1;
1062de962bdSlukem static LUTIL_PASSWD_HASH_FUNC hash_ssha1;
1072de962bdSlukem #endif
1082de962bdSlukem 
1092de962bdSlukem 
1102de962bdSlukem #ifdef SLAPD_CRYPT
1112de962bdSlukem static LUTIL_PASSWD_CHK_FUNC chk_crypt;
1122de962bdSlukem static LUTIL_PASSWD_HASH_FUNC hash_crypt;
1132de962bdSlukem 
1142de962bdSlukem #if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD )
1152de962bdSlukem static LUTIL_PASSWD_CHK_FUNC chk_unix;
1162de962bdSlukem #endif
1172de962bdSlukem #endif
1182de962bdSlukem 
1192de962bdSlukem /* password hash routines */
1202de962bdSlukem 
1212de962bdSlukem #ifdef SLAPD_CLEARTEXT
1222de962bdSlukem static LUTIL_PASSWD_HASH_FUNC hash_clear;
1232de962bdSlukem #endif
1242de962bdSlukem 
1252de962bdSlukem static struct pw_slist *pw_schemes;
1262de962bdSlukem static int pw_inited;
1272de962bdSlukem 
1282de962bdSlukem static const struct pw_scheme pw_schemes_default[] =
1292de962bdSlukem {
1302de962bdSlukem #ifdef LUTIL_SHA1_BYTES
1312de962bdSlukem 	{ BER_BVC("{SSHA}"),		chk_ssha1, hash_ssha1 },
1322de962bdSlukem 	{ BER_BVC("{SHA}"),			chk_sha1, hash_sha1 },
1332de962bdSlukem #endif
1342de962bdSlukem 
1352de962bdSlukem 	{ BER_BVC("{SMD5}"),		chk_smd5, hash_smd5 },
1362de962bdSlukem 	{ BER_BVC("{MD5}"),			chk_md5, hash_md5 },
1372de962bdSlukem 
1382de962bdSlukem #ifdef SLAPD_CRYPT
1392de962bdSlukem 	{ BER_BVC("{CRYPT}"),		chk_crypt, hash_crypt },
1402de962bdSlukem # if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD )
1412de962bdSlukem 	{ BER_BVC("{UNIX}"),		chk_unix, NULL },
1422de962bdSlukem # endif
1432de962bdSlukem #endif
1442de962bdSlukem 
1452de962bdSlukem #ifdef SLAPD_CLEARTEXT
1462de962bdSlukem 	/* pseudo scheme */
1472de962bdSlukem 	{ BER_BVC("{CLEARTEXT}"),	NULL, hash_clear },
1482de962bdSlukem #endif
1492de962bdSlukem 
1502de962bdSlukem 	{ BER_BVNULL, NULL, NULL }
1512de962bdSlukem };
1522de962bdSlukem 
lutil_passwd_add(struct berval * scheme,LUTIL_PASSWD_CHK_FUNC * chk,LUTIL_PASSWD_HASH_FUNC * hash)1532de962bdSlukem int lutil_passwd_add(
1542de962bdSlukem 	struct berval *scheme,
1552de962bdSlukem 	LUTIL_PASSWD_CHK_FUNC *chk,
1562de962bdSlukem 	LUTIL_PASSWD_HASH_FUNC *hash )
1572de962bdSlukem {
1582de962bdSlukem 	struct pw_slist *ptr;
1592de962bdSlukem 
1602de962bdSlukem 	if (!pw_inited) lutil_passwd_init();
1612de962bdSlukem 
1622de962bdSlukem 	ptr = ber_memalloc( sizeof( struct pw_slist ));
1632de962bdSlukem 	if (!ptr) return -1;
1642de962bdSlukem 	ptr->next = pw_schemes;
1652de962bdSlukem 	ptr->s.name = *scheme;
1662de962bdSlukem 	ptr->s.chk_fn = chk;
1672de962bdSlukem 	ptr->s.hash_fn = hash;
1682de962bdSlukem 	pw_schemes = ptr;
1692de962bdSlukem 	return 0;
1702de962bdSlukem }
1712de962bdSlukem 
lutil_passwd_init()1722de962bdSlukem void lutil_passwd_init()
1732de962bdSlukem {
1742de962bdSlukem 	struct pw_scheme *s;
1752de962bdSlukem 
1762de962bdSlukem 	pw_inited = 1;
1772de962bdSlukem 
1782de962bdSlukem 	for( s=(struct pw_scheme *)pw_schemes_default; s->name.bv_val; s++) {
1792de962bdSlukem 		if ( lutil_passwd_add( &s->name, s->chk_fn, s->hash_fn ) ) break;
1802de962bdSlukem 	}
1812de962bdSlukem }
1822de962bdSlukem 
lutil_passwd_destroy()1832de962bdSlukem void lutil_passwd_destroy()
1842de962bdSlukem {
1852de962bdSlukem 	struct pw_slist *ptr, *next;
1862de962bdSlukem 
1872de962bdSlukem 	for( ptr=pw_schemes; ptr; ptr=next ) {
1882de962bdSlukem 		next = ptr->next;
1892de962bdSlukem 		ber_memfree( ptr );
1902de962bdSlukem 	}
1912de962bdSlukem }
1922de962bdSlukem 
get_scheme(const char * scheme)1932de962bdSlukem static const struct pw_scheme *get_scheme(
1942de962bdSlukem 	const char* scheme )
1952de962bdSlukem {
1962de962bdSlukem 	struct pw_slist *pws;
1972de962bdSlukem 	struct berval bv;
1982de962bdSlukem 
1992de962bdSlukem 	if (!pw_inited) lutil_passwd_init();
2002de962bdSlukem 
2012de962bdSlukem 	bv.bv_val = strchr( scheme, '}' );
2022de962bdSlukem 	if ( !bv.bv_val )
2032de962bdSlukem 		return NULL;
2042de962bdSlukem 
2052de962bdSlukem 	bv.bv_len = bv.bv_val - scheme + 1;
2062de962bdSlukem 	bv.bv_val = (char *) scheme;
2072de962bdSlukem 
2082de962bdSlukem 	for( pws=pw_schemes; pws; pws=pws->next ) {
2092de962bdSlukem 		if ( ber_bvstrcasecmp(&bv, &pws->s.name ) == 0 ) {
2102de962bdSlukem 			return &(pws->s);
2112de962bdSlukem 		}
2122de962bdSlukem 	}
2132de962bdSlukem 
2142de962bdSlukem 	return NULL;
2152de962bdSlukem }
2162de962bdSlukem 
lutil_passwd_scheme(const char * scheme)2172de962bdSlukem int lutil_passwd_scheme(
2182de962bdSlukem 	const char* scheme )
2192de962bdSlukem {
2202de962bdSlukem 	if( scheme == NULL ) {
2212de962bdSlukem 		return 0;
2222de962bdSlukem 	}
2232de962bdSlukem 
2242de962bdSlukem 	return get_scheme(scheme) != NULL;
2252de962bdSlukem }
2262de962bdSlukem 
2272de962bdSlukem 
is_allowed_scheme(const char * scheme,const char ** schemes)2282de962bdSlukem static int is_allowed_scheme(
2292de962bdSlukem 	const char* scheme,
2302de962bdSlukem 	const char** schemes )
2312de962bdSlukem {
2322de962bdSlukem 	int i;
2332de962bdSlukem 
2342de962bdSlukem 	if( schemes == NULL ) return 1;
2352de962bdSlukem 
2362de962bdSlukem 	for( i=0; schemes[i] != NULL; i++ ) {
2372de962bdSlukem 		if( strcasecmp( scheme, schemes[i] ) == 0 ) {
2382de962bdSlukem 			return 1;
2392de962bdSlukem 		}
2402de962bdSlukem 	}
2412de962bdSlukem 	return 0;
2422de962bdSlukem }
2432de962bdSlukem 
passwd_scheme(const struct pw_scheme * scheme,const struct berval * passwd,struct berval * bv,const char ** allowed)2442de962bdSlukem static struct berval *passwd_scheme(
2452de962bdSlukem 	const struct pw_scheme *scheme,
2462de962bdSlukem 	const struct berval * passwd,
2472de962bdSlukem 	struct berval *bv,
2482de962bdSlukem 	const char** allowed )
2492de962bdSlukem {
2502de962bdSlukem 	if( !is_allowed_scheme( scheme->name.bv_val, allowed ) ) {
2512de962bdSlukem 		return NULL;
2522de962bdSlukem 	}
2532de962bdSlukem 
2542de962bdSlukem 	if( passwd->bv_len >= scheme->name.bv_len ) {
2552de962bdSlukem 		if( strncasecmp( passwd->bv_val, scheme->name.bv_val, scheme->name.bv_len ) == 0 ) {
2562de962bdSlukem 			bv->bv_val = &passwd->bv_val[scheme->name.bv_len];
2572de962bdSlukem 			bv->bv_len = passwd->bv_len - scheme->name.bv_len;
2582de962bdSlukem 
2592de962bdSlukem 			return bv;
2602de962bdSlukem 		}
2612de962bdSlukem 	}
2622de962bdSlukem 
2632de962bdSlukem 	return NULL;
2642de962bdSlukem }
2652de962bdSlukem 
2662de962bdSlukem /*
2672de962bdSlukem  * Return 0 if creds are good.
2682de962bdSlukem  */
2692de962bdSlukem int
lutil_passwd(const struct berval * passwd,const struct berval * cred,const char ** schemes,const char ** text)2702de962bdSlukem lutil_passwd(
2712de962bdSlukem 	const struct berval *passwd,	/* stored passwd */
2722de962bdSlukem 	const struct berval *cred,		/* user cred */
2732de962bdSlukem 	const char **schemes,
2742de962bdSlukem 	const char **text )
2752de962bdSlukem {
2762de962bdSlukem 	struct pw_slist *pws;
2772de962bdSlukem 
2782de962bdSlukem 	if ( text ) *text = NULL;
2792de962bdSlukem 
2802de962bdSlukem 	if (cred == NULL || cred->bv_len == 0 ||
2812de962bdSlukem 		passwd == NULL || passwd->bv_len == 0 )
2822de962bdSlukem 	{
2832de962bdSlukem 		return -1;
2842de962bdSlukem 	}
2852de962bdSlukem 
2862de962bdSlukem 	if (!pw_inited) lutil_passwd_init();
2872de962bdSlukem 
2882de962bdSlukem 	for( pws=pw_schemes; pws; pws=pws->next ) {
2892de962bdSlukem 		if( pws->s.chk_fn ) {
2902de962bdSlukem 			struct berval x;
2912de962bdSlukem 			struct berval *p = passwd_scheme( &(pws->s),
2922de962bdSlukem 				passwd, &x, schemes );
2932de962bdSlukem 
2942de962bdSlukem 			if( p != NULL ) {
2952de962bdSlukem 				return (pws->s.chk_fn)( &(pws->s.name), p, cred, text );
2962de962bdSlukem 			}
2972de962bdSlukem 		}
2982de962bdSlukem 	}
2992de962bdSlukem 
3002de962bdSlukem #ifdef SLAPD_CLEARTEXT
3012de962bdSlukem 	/* Do we think there is a scheme specifier here that we
3022de962bdSlukem 	 * didn't recognize? Assume a scheme name is at least 1 character.
3032de962bdSlukem 	 */
3042de962bdSlukem 	if (( passwd->bv_val[0] == '{' ) &&
3052de962bdSlukem 		( ber_bvchr( passwd, '}' ) > passwd->bv_val+1 ))
3062de962bdSlukem 	{
3072de962bdSlukem 		return 1;
3082de962bdSlukem 	}
3092de962bdSlukem 	if( is_allowed_scheme("{CLEARTEXT}", schemes ) ) {
3102de962bdSlukem 		return ( passwd->bv_len == cred->bv_len ) ?
3112de962bdSlukem 			memcmp( passwd->bv_val, cred->bv_val, passwd->bv_len )
3122de962bdSlukem 			: 1;
3132de962bdSlukem 	}
3142de962bdSlukem #endif
3152de962bdSlukem 	return 1;
3162de962bdSlukem }
3172de962bdSlukem 
lutil_passwd_generate(struct berval * pw,ber_len_t len)3182de962bdSlukem int lutil_passwd_generate( struct berval *pw, ber_len_t len )
3192de962bdSlukem {
3202de962bdSlukem 
3212de962bdSlukem 	if( len < 1 ) return -1;
3222de962bdSlukem 
3232de962bdSlukem 	pw->bv_len = len;
3242de962bdSlukem 	pw->bv_val = ber_memalloc( len + 1 );
3252de962bdSlukem 
3262de962bdSlukem 	if( pw->bv_val == NULL ) {
3272de962bdSlukem 		return -1;
3282de962bdSlukem 	}
3292de962bdSlukem 
3302de962bdSlukem 	if( lutil_entropy( (unsigned char *) pw->bv_val, pw->bv_len) < 0 ) {
3312de962bdSlukem 		return -1;
3322de962bdSlukem 	}
3332de962bdSlukem 
3342de962bdSlukem 	for( len = 0; len < pw->bv_len; len++ ) {
3352de962bdSlukem 		pw->bv_val[len] = crypt64[
3362de962bdSlukem 			pw->bv_val[len] % (sizeof(crypt64)-1) ];
3372de962bdSlukem 	}
3382de962bdSlukem 
3392de962bdSlukem 	pw->bv_val[len] = '\0';
3402de962bdSlukem 
3412de962bdSlukem 	return 0;
3422de962bdSlukem }
3432de962bdSlukem 
lutil_passwd_hash(const struct berval * passwd,const char * method,struct berval * hash,const char ** text)3442de962bdSlukem int lutil_passwd_hash(
3452de962bdSlukem 	const struct berval * passwd,
3462de962bdSlukem 	const char * method,
3472de962bdSlukem 	struct berval *hash,
3482de962bdSlukem 	const char **text )
3492de962bdSlukem {
3502de962bdSlukem 	const struct pw_scheme *sc = get_scheme( method );
3512de962bdSlukem 
3522de962bdSlukem 	hash->bv_val = NULL;
3532de962bdSlukem 	hash->bv_len = 0;
3542de962bdSlukem 
3552de962bdSlukem 	if( sc == NULL ) {
3562de962bdSlukem 		if( text ) *text = "scheme not recognized";
3572de962bdSlukem 		return -1;
3582de962bdSlukem 	}
3592de962bdSlukem 
3602de962bdSlukem 	if( ! sc->hash_fn ) {
3612de962bdSlukem 		if( text ) *text = "scheme provided no hash function";
3622de962bdSlukem 		return -1;
3632de962bdSlukem 	}
3642de962bdSlukem 
3652de962bdSlukem 	if( text ) *text = NULL;
3662de962bdSlukem 
3672de962bdSlukem 	return (sc->hash_fn)( &sc->name, passwd, hash, text );
3682de962bdSlukem }
3692de962bdSlukem 
370*549b59edSchristos /* pw_string is only called when SLAPD_CRYPT is defined */
371*549b59edSchristos #if defined(SLAPD_CRYPT)
pw_string(const struct berval * sc,struct berval * passwd)3722de962bdSlukem static int pw_string(
3732de962bdSlukem 	const struct berval *sc,
3742de962bdSlukem 	struct berval *passwd )
3752de962bdSlukem {
3762de962bdSlukem 	struct berval pw;
3772de962bdSlukem 
3782de962bdSlukem 	pw.bv_len = sc->bv_len + passwd->bv_len;
3792de962bdSlukem 	pw.bv_val = ber_memalloc( pw.bv_len + 1 );
3802de962bdSlukem 
3812de962bdSlukem 	if( pw.bv_val == NULL ) {
3822de962bdSlukem 		return LUTIL_PASSWD_ERR;
3832de962bdSlukem 	}
3842de962bdSlukem 
3852de962bdSlukem 	AC_MEMCPY( pw.bv_val, sc->bv_val, sc->bv_len );
3862de962bdSlukem 	AC_MEMCPY( &pw.bv_val[sc->bv_len], passwd->bv_val, passwd->bv_len );
3872de962bdSlukem 
3882de962bdSlukem 	pw.bv_val[pw.bv_len] = '\0';
3892de962bdSlukem 	*passwd = pw;
3902de962bdSlukem 
3912de962bdSlukem 	return LUTIL_PASSWD_OK;
3922de962bdSlukem }
393*549b59edSchristos #endif /* SLAPD_CRYPT */
3942de962bdSlukem 
lutil_passwd_string64(const struct berval * sc,const struct berval * hash,struct berval * b64,const struct berval * salt)395cb54be06Stron int lutil_passwd_string64(
3962de962bdSlukem 	const struct berval *sc,
3972de962bdSlukem 	const struct berval *hash,
3982de962bdSlukem 	struct berval *b64,
3992de962bdSlukem 	const struct berval *salt )
4002de962bdSlukem {
4012de962bdSlukem 	int rc;
4022de962bdSlukem 	struct berval string;
4032de962bdSlukem 	size_t b64len;
4042de962bdSlukem 
4052de962bdSlukem 	if( salt ) {
4062de962bdSlukem 		/* need to base64 combined string */
4072de962bdSlukem 		string.bv_len = hash->bv_len + salt->bv_len;
4082de962bdSlukem 		string.bv_val = ber_memalloc( string.bv_len + 1 );
4092de962bdSlukem 
4102de962bdSlukem 		if( string.bv_val == NULL ) {
4112de962bdSlukem 			return LUTIL_PASSWD_ERR;
4122de962bdSlukem 		}
4132de962bdSlukem 
4142de962bdSlukem 		AC_MEMCPY( string.bv_val, hash->bv_val,
4152de962bdSlukem 			hash->bv_len );
4162de962bdSlukem 		AC_MEMCPY( &string.bv_val[hash->bv_len], salt->bv_val,
4172de962bdSlukem 			salt->bv_len );
4182de962bdSlukem 		string.bv_val[string.bv_len] = '\0';
4192de962bdSlukem 
4202de962bdSlukem 	} else {
4212de962bdSlukem 		string = *hash;
4222de962bdSlukem 	}
4232de962bdSlukem 
4242de962bdSlukem 	b64len = LUTIL_BASE64_ENCODE_LEN( string.bv_len ) + 1;
4252de962bdSlukem 	b64->bv_len = b64len + sc->bv_len;
4262de962bdSlukem 	b64->bv_val = ber_memalloc( b64->bv_len + 1 );
4272de962bdSlukem 
4282de962bdSlukem 	if( b64->bv_val == NULL ) {
4292de962bdSlukem 		if( salt ) ber_memfree( string.bv_val );
4302de962bdSlukem 		return LUTIL_PASSWD_ERR;
4312de962bdSlukem 	}
4322de962bdSlukem 
4332de962bdSlukem 	AC_MEMCPY(b64->bv_val, sc->bv_val, sc->bv_len);
4342de962bdSlukem 
4352de962bdSlukem 	rc = lutil_b64_ntop(
4362de962bdSlukem 		(unsigned char *) string.bv_val, string.bv_len,
4372de962bdSlukem 		&b64->bv_val[sc->bv_len], b64len );
4382de962bdSlukem 
4392de962bdSlukem 	if( salt ) ber_memfree( string.bv_val );
4402de962bdSlukem 
4412de962bdSlukem 	if( rc < 0 ) {
4422de962bdSlukem 		return LUTIL_PASSWD_ERR;
4432de962bdSlukem 	}
4442de962bdSlukem 
4452de962bdSlukem 	/* recompute length */
4462de962bdSlukem 	b64->bv_len = sc->bv_len + rc;
4472de962bdSlukem 	assert( strlen(b64->bv_val) == b64->bv_len );
4482de962bdSlukem 	return LUTIL_PASSWD_OK;
4492de962bdSlukem }
4502de962bdSlukem 
4512de962bdSlukem /* PASSWORD CHECK ROUTINES */
4522de962bdSlukem 
4532de962bdSlukem #ifdef LUTIL_SHA1_BYTES
chk_ssha1(const struct berval * sc,const struct berval * passwd,const struct berval * cred,const char ** text)4542de962bdSlukem static int chk_ssha1(
4552de962bdSlukem 	const struct berval *sc,
4562de962bdSlukem 	const struct berval * passwd,
4572de962bdSlukem 	const struct berval * cred,
4582de962bdSlukem 	const char **text )
4592de962bdSlukem {
4602de962bdSlukem 	lutil_SHA1_CTX SHA1context;
4612de962bdSlukem 	unsigned char SHA1digest[LUTIL_SHA1_BYTES];
4622de962bdSlukem 	int rc;
4632de962bdSlukem 	unsigned char *orig_pass = NULL;
464915bea73Schristos 	size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len);
4652de962bdSlukem 
4662de962bdSlukem 	/* safety check -- must have some salt */
467915bea73Schristos 	if (decode_len <= sizeof(SHA1digest)) {
4682de962bdSlukem 		return LUTIL_PASSWD_ERR;
4692de962bdSlukem 	}
4702de962bdSlukem 
4712de962bdSlukem 	/* decode base64 password */
472915bea73Schristos 	orig_pass = (unsigned char *) ber_memalloc(decode_len + 1);
4732de962bdSlukem 
4742de962bdSlukem 	if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
4752de962bdSlukem 
476915bea73Schristos 	rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len);
4772de962bdSlukem 
4782de962bdSlukem 	/* safety check -- must have some salt */
4792de962bdSlukem 	if (rc <= (int)(sizeof(SHA1digest))) {
4802de962bdSlukem 		ber_memfree(orig_pass);
4812de962bdSlukem 		return LUTIL_PASSWD_ERR;
4822de962bdSlukem 	}
4832de962bdSlukem 
4842de962bdSlukem 	/* hash credentials with salt */
4852de962bdSlukem 	lutil_SHA1Init(&SHA1context);
4862de962bdSlukem 	lutil_SHA1Update(&SHA1context,
4872de962bdSlukem 		(const unsigned char *) cred->bv_val, cred->bv_len);
4882de962bdSlukem 	lutil_SHA1Update(&SHA1context,
4892de962bdSlukem 		(const unsigned char *) &orig_pass[sizeof(SHA1digest)],
4902de962bdSlukem 		rc - sizeof(SHA1digest));
4912de962bdSlukem 	lutil_SHA1Final(SHA1digest, &SHA1context);
4922de962bdSlukem 
4932de962bdSlukem 	/* compare */
4942de962bdSlukem 	rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
4952de962bdSlukem 	ber_memfree(orig_pass);
4962de962bdSlukem 	return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
4972de962bdSlukem }
4982de962bdSlukem 
chk_sha1(const struct berval * sc,const struct berval * passwd,const struct berval * cred,const char ** text)4992de962bdSlukem static int chk_sha1(
5002de962bdSlukem 	const struct berval *sc,
5012de962bdSlukem 	const struct berval * passwd,
5022de962bdSlukem 	const struct berval * cred,
5032de962bdSlukem 	const char **text )
5042de962bdSlukem {
5052de962bdSlukem 	lutil_SHA1_CTX SHA1context;
5062de962bdSlukem 	unsigned char SHA1digest[LUTIL_SHA1_BYTES];
5072de962bdSlukem 	int rc;
5082de962bdSlukem 	unsigned char *orig_pass = NULL;
509915bea73Schristos 	size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len);
5102de962bdSlukem 
5112de962bdSlukem 	/* safety check */
512915bea73Schristos 	if (decode_len < sizeof(SHA1digest)) {
5132de962bdSlukem 		return LUTIL_PASSWD_ERR;
5142de962bdSlukem 	}
5152de962bdSlukem 
5162de962bdSlukem 	/* base64 un-encode password */
517915bea73Schristos 	orig_pass = (unsigned char *) ber_memalloc(decode_len + 1);
5182de962bdSlukem 
5192de962bdSlukem 	if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
5202de962bdSlukem 
521915bea73Schristos 	rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len);
5222de962bdSlukem 
5232de962bdSlukem 	if( rc != sizeof(SHA1digest) ) {
5242de962bdSlukem 		ber_memfree(orig_pass);
5252de962bdSlukem 		return LUTIL_PASSWD_ERR;
5262de962bdSlukem 	}
5272de962bdSlukem 
5282de962bdSlukem 	/* hash credentials with salt */
5292de962bdSlukem 	lutil_SHA1Init(&SHA1context);
5302de962bdSlukem 	lutil_SHA1Update(&SHA1context,
5312de962bdSlukem 		(const unsigned char *) cred->bv_val, cred->bv_len);
5322de962bdSlukem 	lutil_SHA1Final(SHA1digest, &SHA1context);
5332de962bdSlukem 
5342de962bdSlukem 	/* compare */
5352de962bdSlukem 	rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
5362de962bdSlukem 	ber_memfree(orig_pass);
5372de962bdSlukem 	return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
5382de962bdSlukem }
5392de962bdSlukem #endif
5402de962bdSlukem 
chk_smd5(const struct berval * sc,const struct berval * passwd,const struct berval * cred,const char ** text)5412de962bdSlukem static int chk_smd5(
5422de962bdSlukem 	const struct berval *sc,
5432de962bdSlukem 	const struct berval * passwd,
5442de962bdSlukem 	const struct berval * cred,
5452de962bdSlukem 	const char **text )
5462de962bdSlukem {
5472de962bdSlukem 	lutil_MD5_CTX MD5context;
5482de962bdSlukem 	unsigned char MD5digest[LUTIL_MD5_BYTES];
5492de962bdSlukem 	int rc;
5502de962bdSlukem 	unsigned char *orig_pass = NULL;
551915bea73Schristos 	size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len);
5522de962bdSlukem 
5532de962bdSlukem 	/* safety check */
554915bea73Schristos 	if (decode_len <= sizeof(MD5digest)) {
5552de962bdSlukem 		return LUTIL_PASSWD_ERR;
5562de962bdSlukem 	}
5572de962bdSlukem 
5582de962bdSlukem 	/* base64 un-encode password */
559915bea73Schristos 	orig_pass = (unsigned char *) ber_memalloc(decode_len + 1);
5602de962bdSlukem 
5612de962bdSlukem 	if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
5622de962bdSlukem 
563915bea73Schristos 	rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len);
5642de962bdSlukem 
5652de962bdSlukem 	if (rc <= (int)(sizeof(MD5digest))) {
5662de962bdSlukem 		ber_memfree(orig_pass);
5672de962bdSlukem 		return LUTIL_PASSWD_ERR;
5682de962bdSlukem 	}
5692de962bdSlukem 
5702de962bdSlukem 	/* hash credentials with salt */
5712de962bdSlukem 	lutil_MD5Init(&MD5context);
5722de962bdSlukem 	lutil_MD5Update(&MD5context,
5732de962bdSlukem 		(const unsigned char *) cred->bv_val,
5742de962bdSlukem 		cred->bv_len );
5752de962bdSlukem 	lutil_MD5Update(&MD5context,
5762de962bdSlukem 		&orig_pass[sizeof(MD5digest)],
5772de962bdSlukem 		rc - sizeof(MD5digest));
5782de962bdSlukem 	lutil_MD5Final(MD5digest, &MD5context);
5792de962bdSlukem 
5802de962bdSlukem 	/* compare */
5812de962bdSlukem 	rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
5822de962bdSlukem 	ber_memfree(orig_pass);
5832de962bdSlukem 	return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
5842de962bdSlukem }
5852de962bdSlukem 
chk_md5(const struct berval * sc,const struct berval * passwd,const struct berval * cred,const char ** text)5862de962bdSlukem static int chk_md5(
5872de962bdSlukem 	const struct berval *sc,
5882de962bdSlukem 	const struct berval * passwd,
5892de962bdSlukem 	const struct berval * cred,
5902de962bdSlukem 	const char **text )
5912de962bdSlukem {
5922de962bdSlukem 	lutil_MD5_CTX MD5context;
5932de962bdSlukem 	unsigned char MD5digest[LUTIL_MD5_BYTES];
5942de962bdSlukem 	int rc;
5952de962bdSlukem 	unsigned char *orig_pass = NULL;
596915bea73Schristos 	size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len);
5972de962bdSlukem 
5982de962bdSlukem 	/* safety check */
599915bea73Schristos 	if (decode_len < sizeof(MD5digest)) {
6002de962bdSlukem 		return LUTIL_PASSWD_ERR;
6012de962bdSlukem 	}
6022de962bdSlukem 
6032de962bdSlukem 	/* base64 un-encode password */
604915bea73Schristos 	orig_pass = (unsigned char *) ber_memalloc(decode_len + 1);
6052de962bdSlukem 
6062de962bdSlukem 	if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
6072de962bdSlukem 
608915bea73Schristos 	rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len);
6092de962bdSlukem 	if ( rc != sizeof(MD5digest) ) {
6102de962bdSlukem 		ber_memfree(orig_pass);
6112de962bdSlukem 		return LUTIL_PASSWD_ERR;
6122de962bdSlukem 	}
6132de962bdSlukem 
6142de962bdSlukem 	/* hash credentials with salt */
6152de962bdSlukem 	lutil_MD5Init(&MD5context);
6162de962bdSlukem 	lutil_MD5Update(&MD5context,
6172de962bdSlukem 		(const unsigned char *) cred->bv_val,
6182de962bdSlukem 		cred->bv_len );
6192de962bdSlukem 	lutil_MD5Final(MD5digest, &MD5context);
6202de962bdSlukem 
6212de962bdSlukem 	/* compare */
6222de962bdSlukem 	rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
6232de962bdSlukem 	ber_memfree(orig_pass);
6242de962bdSlukem 	return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
6252de962bdSlukem }
6262de962bdSlukem 
6272de962bdSlukem #ifdef SLAPD_CRYPT
lutil_crypt(const char * key,const char * salt,char ** hash)6282de962bdSlukem static int lutil_crypt(
6292de962bdSlukem 	const char *key,
6302de962bdSlukem 	const char *salt,
6312de962bdSlukem 	char **hash )
6322de962bdSlukem {
6332de962bdSlukem 	char *cr = crypt( key, salt );
6342de962bdSlukem 	int rc;
6352de962bdSlukem 
6362de962bdSlukem 	if( cr == NULL || cr[0] == '\0' ) {
6372de962bdSlukem 		/* salt must have been invalid */
6382de962bdSlukem 		rc = LUTIL_PASSWD_ERR;
6392de962bdSlukem 	} else {
6402de962bdSlukem 		if ( hash ) {
6412de962bdSlukem 			*hash = ber_strdup( cr );
6422de962bdSlukem 			rc = LUTIL_PASSWD_OK;
6432de962bdSlukem 		} else {
6442de962bdSlukem 			rc = strcmp( salt, cr ) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
6452de962bdSlukem 		}
6462de962bdSlukem 	}
6472de962bdSlukem 	return rc;
6482de962bdSlukem }
6492de962bdSlukem 
chk_crypt(const struct berval * sc,const struct berval * passwd,const struct berval * cred,const char ** text)6502de962bdSlukem static int chk_crypt(
6512de962bdSlukem 	const struct berval *sc,
6522de962bdSlukem 	const struct berval * passwd,
6532de962bdSlukem 	const struct berval * cred,
6542de962bdSlukem 	const char **text )
6552de962bdSlukem {
6562de962bdSlukem 	unsigned int i;
6572de962bdSlukem 
6582de962bdSlukem 	for( i=0; i<cred->bv_len; i++) {
6592de962bdSlukem 		if(cred->bv_val[i] == '\0') {
6602de962bdSlukem 			return LUTIL_PASSWD_ERR;	/* NUL character in password */
6612de962bdSlukem 		}
6622de962bdSlukem 	}
6632de962bdSlukem 
6642de962bdSlukem 	if( cred->bv_val[i] != '\0' ) {
6652de962bdSlukem 		return LUTIL_PASSWD_ERR;	/* cred must behave like a string */
6662de962bdSlukem 	}
6672de962bdSlukem 
6682de962bdSlukem 	if( passwd->bv_len < 2 ) {
6692de962bdSlukem 		return LUTIL_PASSWD_ERR;	/* passwd must be at least two characters long */
6702de962bdSlukem 	}
6712de962bdSlukem 
6722de962bdSlukem 	for( i=0; i<passwd->bv_len; i++) {
6732de962bdSlukem 		if(passwd->bv_val[i] == '\0') {
6742de962bdSlukem 			return LUTIL_PASSWD_ERR;	/* NUL character in password */
6752de962bdSlukem 		}
6762de962bdSlukem 	}
6772de962bdSlukem 
6782de962bdSlukem 	if( passwd->bv_val[i] != '\0' ) {
6792de962bdSlukem 		return LUTIL_PASSWD_ERR;	/* passwd must behave like a string */
6802de962bdSlukem 	}
6812de962bdSlukem 
6822de962bdSlukem 	return lutil_cryptptr( cred->bv_val, passwd->bv_val, NULL );
6832de962bdSlukem }
6842de962bdSlukem 
6852de962bdSlukem # if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD )
chk_unix(const struct berval * sc,const struct berval * passwd,const struct berval * cred,const char ** text)6862de962bdSlukem static int chk_unix(
6872de962bdSlukem 	const struct berval *sc,
6882de962bdSlukem 	const struct berval * passwd,
6892de962bdSlukem 	const struct berval * cred,
6902de962bdSlukem 	const char **text )
6912de962bdSlukem {
6922de962bdSlukem 	unsigned int i;
6932de962bdSlukem 	char *pw;
6942de962bdSlukem 
6952de962bdSlukem 	for( i=0; i<cred->bv_len; i++) {
6962de962bdSlukem 		if(cred->bv_val[i] == '\0') {
6972de962bdSlukem 			return LUTIL_PASSWD_ERR;	/* NUL character in password */
6982de962bdSlukem 		}
6992de962bdSlukem 	}
7002de962bdSlukem 	if( cred->bv_val[i] != '\0' ) {
7012de962bdSlukem 		return LUTIL_PASSWD_ERR;	/* cred must behave like a string */
7022de962bdSlukem 	}
7032de962bdSlukem 
7042de962bdSlukem 	for( i=0; i<passwd->bv_len; i++) {
7052de962bdSlukem 		if(passwd->bv_val[i] == '\0') {
7062de962bdSlukem 			return LUTIL_PASSWD_ERR;	/* NUL character in password */
7072de962bdSlukem 		}
7082de962bdSlukem 	}
7092de962bdSlukem 
7102de962bdSlukem 	if( passwd->bv_val[i] != '\0' ) {
7112de962bdSlukem 		return LUTIL_PASSWD_ERR;	/* passwd must behave like a string */
7122de962bdSlukem 	}
7132de962bdSlukem 
7142de962bdSlukem 	{
7152de962bdSlukem 		struct passwd *pwd = getpwnam(passwd->bv_val);
7162de962bdSlukem 
7172de962bdSlukem 		if(pwd == NULL) {
7182de962bdSlukem 			return LUTIL_PASSWD_ERR;	/* not found */
7192de962bdSlukem 		}
7202de962bdSlukem 
7212de962bdSlukem 		pw = pwd->pw_passwd;
7222de962bdSlukem 	}
7232de962bdSlukem #  ifdef HAVE_GETSPNAM
7242de962bdSlukem 	{
7252de962bdSlukem 		struct spwd *spwd = getspnam(passwd->bv_val);
7262de962bdSlukem 
7272de962bdSlukem 		if(spwd != NULL) {
7282de962bdSlukem 			pw = spwd->sp_pwdp;
7292de962bdSlukem 		}
7302de962bdSlukem 	}
7312de962bdSlukem #  endif
7322de962bdSlukem #  ifdef HAVE_AIX_SECURITY
7332de962bdSlukem 	{
7342de962bdSlukem 		struct userpw *upw = getuserpw(passwd->bv_val);
7352de962bdSlukem 
7362de962bdSlukem 		if (upw != NULL) {
7372de962bdSlukem 			pw = upw->upw_passwd;
7382de962bdSlukem 		}
7392de962bdSlukem 	}
7402de962bdSlukem #  endif
7412de962bdSlukem 
7422de962bdSlukem 	if( pw == NULL || pw[0] == '\0' || pw[1] == '\0' ) {
7432de962bdSlukem 		/* password must must be at least two characters long */
7442de962bdSlukem 		return LUTIL_PASSWD_ERR;
7452de962bdSlukem 	}
7462de962bdSlukem 
7472de962bdSlukem 	return lutil_cryptptr( cred->bv_val, pw, NULL );
7482de962bdSlukem }
7492de962bdSlukem # endif
7502de962bdSlukem #endif
7512de962bdSlukem 
7522de962bdSlukem /* PASSWORD GENERATION ROUTINES */
7532de962bdSlukem 
7542de962bdSlukem #ifdef LUTIL_SHA1_BYTES
hash_ssha1(const struct berval * scheme,const struct berval * passwd,struct berval * hash,const char ** text)7552de962bdSlukem static int hash_ssha1(
7562de962bdSlukem 	const struct berval *scheme,
7572de962bdSlukem 	const struct berval  *passwd,
7582de962bdSlukem 	struct berval *hash,
7592de962bdSlukem 	const char **text )
7602de962bdSlukem {
7612de962bdSlukem 	lutil_SHA1_CTX  SHA1context;
7622de962bdSlukem 	unsigned char   SHA1digest[LUTIL_SHA1_BYTES];
7632de962bdSlukem 	char            saltdata[SALT_SIZE];
7642de962bdSlukem 	struct berval digest;
7652de962bdSlukem 	struct berval salt;
7662de962bdSlukem 
7672de962bdSlukem 	digest.bv_val = (char *) SHA1digest;
7682de962bdSlukem 	digest.bv_len = sizeof(SHA1digest);
7692de962bdSlukem 	salt.bv_val = saltdata;
7702de962bdSlukem 	salt.bv_len = sizeof(saltdata);
7712de962bdSlukem 
7722de962bdSlukem 	if( lutil_entropy( (unsigned char *) salt.bv_val, salt.bv_len) < 0 ) {
7732de962bdSlukem 		return LUTIL_PASSWD_ERR;
7742de962bdSlukem 	}
7752de962bdSlukem 
7762de962bdSlukem 	lutil_SHA1Init( &SHA1context );
7772de962bdSlukem 	lutil_SHA1Update( &SHA1context,
7782de962bdSlukem 		(const unsigned char *)passwd->bv_val, passwd->bv_len );
7792de962bdSlukem 	lutil_SHA1Update( &SHA1context,
7802de962bdSlukem 		(const unsigned char *)salt.bv_val, salt.bv_len );
7812de962bdSlukem 	lutil_SHA1Final( SHA1digest, &SHA1context );
7822de962bdSlukem 
783cb54be06Stron 	return lutil_passwd_string64( scheme, &digest, hash, &salt);
7842de962bdSlukem }
7852de962bdSlukem 
hash_sha1(const struct berval * scheme,const struct berval * passwd,struct berval * hash,const char ** text)7862de962bdSlukem static int hash_sha1(
7872de962bdSlukem 	const struct berval *scheme,
7882de962bdSlukem 	const struct berval  *passwd,
7892de962bdSlukem 	struct berval *hash,
7902de962bdSlukem 	const char **text )
7912de962bdSlukem {
7922de962bdSlukem 	lutil_SHA1_CTX  SHA1context;
7932de962bdSlukem 	unsigned char   SHA1digest[LUTIL_SHA1_BYTES];
7942de962bdSlukem 	struct berval digest;
7952de962bdSlukem 	digest.bv_val = (char *) SHA1digest;
7962de962bdSlukem 	digest.bv_len = sizeof(SHA1digest);
7972de962bdSlukem 
7982de962bdSlukem 	lutil_SHA1Init( &SHA1context );
7992de962bdSlukem 	lutil_SHA1Update( &SHA1context,
8002de962bdSlukem 		(const unsigned char *)passwd->bv_val, passwd->bv_len );
8012de962bdSlukem 	lutil_SHA1Final( SHA1digest, &SHA1context );
8022de962bdSlukem 
803cb54be06Stron 	return lutil_passwd_string64( scheme, &digest, hash, NULL);
8042de962bdSlukem }
8052de962bdSlukem #endif
8062de962bdSlukem 
hash_smd5(const struct berval * scheme,const struct berval * passwd,struct berval * hash,const char ** text)8072de962bdSlukem static int hash_smd5(
8082de962bdSlukem 	const struct berval *scheme,
8092de962bdSlukem 	const struct berval  *passwd,
8102de962bdSlukem 	struct berval *hash,
8112de962bdSlukem 	const char **text )
8122de962bdSlukem {
8132de962bdSlukem 	lutil_MD5_CTX   MD5context;
8142de962bdSlukem 	unsigned char   MD5digest[LUTIL_MD5_BYTES];
8152de962bdSlukem 	char            saltdata[SALT_SIZE];
8162de962bdSlukem 	struct berval digest;
8172de962bdSlukem 	struct berval salt;
8182de962bdSlukem 
8192de962bdSlukem 	digest.bv_val = (char *) MD5digest;
8202de962bdSlukem 	digest.bv_len = sizeof(MD5digest);
8212de962bdSlukem 	salt.bv_val = saltdata;
8222de962bdSlukem 	salt.bv_len = sizeof(saltdata);
8232de962bdSlukem 
8242de962bdSlukem 	if( lutil_entropy( (unsigned char *) salt.bv_val, salt.bv_len) < 0 ) {
8252de962bdSlukem 		return LUTIL_PASSWD_ERR;
8262de962bdSlukem 	}
8272de962bdSlukem 
8282de962bdSlukem 	lutil_MD5Init( &MD5context );
8292de962bdSlukem 	lutil_MD5Update( &MD5context,
8302de962bdSlukem 		(const unsigned char *) passwd->bv_val, passwd->bv_len );
8312de962bdSlukem 	lutil_MD5Update( &MD5context,
8322de962bdSlukem 		(const unsigned char *) salt.bv_val, salt.bv_len );
8332de962bdSlukem 	lutil_MD5Final( MD5digest, &MD5context );
8342de962bdSlukem 
835cb54be06Stron 	return lutil_passwd_string64( scheme, &digest, hash, &salt );
8362de962bdSlukem }
8372de962bdSlukem 
hash_md5(const struct berval * scheme,const struct berval * passwd,struct berval * hash,const char ** text)8382de962bdSlukem static int hash_md5(
8392de962bdSlukem 	const struct berval *scheme,
8402de962bdSlukem 	const struct berval  *passwd,
8412de962bdSlukem 	struct berval *hash,
8422de962bdSlukem 	const char **text )
8432de962bdSlukem {
8442de962bdSlukem 	lutil_MD5_CTX   MD5context;
8452de962bdSlukem 	unsigned char   MD5digest[LUTIL_MD5_BYTES];
8462de962bdSlukem 
8472de962bdSlukem 	struct berval digest;
8482de962bdSlukem 
8492de962bdSlukem 	digest.bv_val = (char *) MD5digest;
8502de962bdSlukem 	digest.bv_len = sizeof(MD5digest);
8512de962bdSlukem 
8522de962bdSlukem 	lutil_MD5Init( &MD5context );
8532de962bdSlukem 	lutil_MD5Update( &MD5context,
8542de962bdSlukem 		(const unsigned char *) passwd->bv_val, passwd->bv_len );
8552de962bdSlukem 	lutil_MD5Final( MD5digest, &MD5context );
8562de962bdSlukem 
857cb54be06Stron 	return lutil_passwd_string64( scheme, &digest, hash, NULL );
8582de962bdSlukem ;
8592de962bdSlukem }
8602de962bdSlukem 
8612de962bdSlukem #ifdef SLAPD_CRYPT
hash_crypt(const struct berval * scheme,const struct berval * passwd,struct berval * hash,const char ** text)8622de962bdSlukem static int hash_crypt(
8632de962bdSlukem 	const struct berval *scheme,
8642de962bdSlukem 	const struct berval *passwd,
8652de962bdSlukem 	struct berval *hash,
8662de962bdSlukem 	const char **text )
8672de962bdSlukem {
8682de962bdSlukem 	unsigned char salt[32];	/* salt suitable for most anything */
8692de962bdSlukem 	unsigned int i;
8702de962bdSlukem 	char *save;
8712de962bdSlukem 	int rc;
8722de962bdSlukem 
8732de962bdSlukem 	for( i=0; i<passwd->bv_len; i++) {
8742de962bdSlukem 		if(passwd->bv_val[i] == '\0') {
8752de962bdSlukem 			return LUTIL_PASSWD_ERR;	/* NUL character in password */
8762de962bdSlukem 		}
8772de962bdSlukem 	}
8782de962bdSlukem 
8792de962bdSlukem 	if( passwd->bv_val[i] != '\0' ) {
8802de962bdSlukem 		return LUTIL_PASSWD_ERR;	/* passwd must behave like a string */
8812de962bdSlukem 	}
8822de962bdSlukem 
8832de962bdSlukem 	if( lutil_entropy( salt, sizeof( salt ) ) < 0 ) {
8842de962bdSlukem 		return LUTIL_PASSWD_ERR;
8852de962bdSlukem 	}
8862de962bdSlukem 
8872de962bdSlukem 	for( i=0; i< ( sizeof(salt) - 1 ); i++ ) {
8882de962bdSlukem 		salt[i] = crypt64[ salt[i] % (sizeof(crypt64)-1) ];
8892de962bdSlukem 	}
8902de962bdSlukem 	salt[sizeof( salt ) - 1 ] = '\0';
8912de962bdSlukem 
8922de962bdSlukem 	if( salt_format != NULL ) {
8932de962bdSlukem 		/* copy the salt we made into entropy before snprintfing
8942de962bdSlukem 		   it back into the salt */
8952de962bdSlukem 		char entropy[sizeof(salt)];
8962de962bdSlukem 		strcpy( entropy, (char *) salt );
8972de962bdSlukem 		snprintf( (char *) salt, sizeof(entropy), salt_format, entropy );
8982de962bdSlukem 	}
8992de962bdSlukem 
9002de962bdSlukem 	rc = lutil_cryptptr( passwd->bv_val, (char *) salt, &hash->bv_val );
9012de962bdSlukem 	if ( rc != LUTIL_PASSWD_OK ) return rc;
9022de962bdSlukem 
9032de962bdSlukem 	if( hash->bv_val == NULL ) return -1;
9042de962bdSlukem 
9052de962bdSlukem 	hash->bv_len = strlen( hash->bv_val );
9062de962bdSlukem 
9072de962bdSlukem 	save = hash->bv_val;
9082de962bdSlukem 
9092de962bdSlukem 	if( hash->bv_len == 0 ) {
9102de962bdSlukem 		rc = LUTIL_PASSWD_ERR;
9112de962bdSlukem 	} else {
9122de962bdSlukem 		rc = pw_string( scheme, hash );
9132de962bdSlukem 	}
9142de962bdSlukem 	ber_memfree( save );
9152de962bdSlukem 	return rc;
9162de962bdSlukem }
9172de962bdSlukem #endif
9182de962bdSlukem 
lutil_salt_format(const char * format)9192de962bdSlukem int lutil_salt_format(const char *format)
9202de962bdSlukem {
9212de962bdSlukem #ifdef SLAPD_CRYPT
9224e6df137Slukem 	ber_memfree( salt_format );
9232de962bdSlukem 
9242de962bdSlukem 	salt_format = format != NULL ? ber_strdup( format ) : NULL;
9252de962bdSlukem #endif
9262de962bdSlukem 
9272de962bdSlukem 	return 0;
9282de962bdSlukem }
9292de962bdSlukem 
9302de962bdSlukem #ifdef SLAPD_CLEARTEXT
hash_clear(const struct berval * scheme,const struct berval * passwd,struct berval * hash,const char ** text)9312de962bdSlukem static int hash_clear(
9322de962bdSlukem 	const struct berval *scheme,
9332de962bdSlukem 	const struct berval  *passwd,
9342de962bdSlukem 	struct berval *hash,
9352de962bdSlukem 	const char **text )
9362de962bdSlukem {
9372de962bdSlukem 	ber_dupbv( hash, (struct berval *)passwd );
9382de962bdSlukem 	return LUTIL_PASSWD_OK;
9392de962bdSlukem }
9402de962bdSlukem #endif
9412de962bdSlukem 
942