Home | History | Annotate | Line # | Download | only in liblutil
      1   1.9  christos /*	$NetBSD: passwd.c,v 1.10 2025/09/05 21:16:23 christos Exp $	*/
      2   1.2     lukem 
      3   1.4      tron /* $OpenLDAP$ */
      4   1.1     lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5   1.1     lukem  *
      6  1.10  christos  * Copyright 1998-2024 The OpenLDAP Foundation.
      7   1.1     lukem  * All rights reserved.
      8   1.1     lukem  *
      9   1.1     lukem  * Redistribution and use in source and binary forms, with or without
     10   1.1     lukem  * modification, are permitted only as authorized by the OpenLDAP
     11   1.1     lukem  * Public License.
     12   1.1     lukem  *
     13   1.1     lukem  * A copy of this license is available in the file LICENSE in the
     14   1.1     lukem  * top-level directory of the distribution or, alternatively, at
     15   1.1     lukem  * <http://www.OpenLDAP.org/license.html>.
     16   1.1     lukem  */
     17   1.1     lukem 
     18   1.1     lukem /*
     19   1.1     lukem  * int lutil_passwd(
     20   1.1     lukem  *	const struct berval *passwd,
     21   1.1     lukem  *	const struct berval *cred,
     22   1.1     lukem  *	const char **schemes )
     23   1.1     lukem  *
     24   1.1     lukem  * Returns true if user supplied credentials (cred) matches
     25   1.1     lukem  * the stored password (passwd).
     26   1.1     lukem  *
     27   1.1     lukem  * Due to the use of the crypt(3) function
     28   1.1     lukem  * this routine is NOT thread-safe.
     29   1.1     lukem  */
     30   1.1     lukem 
     31   1.5  christos #include <sys/cdefs.h>
     32   1.9  christos __RCSID("$NetBSD: passwd.c,v 1.10 2025/09/05 21:16:23 christos Exp $");
     33   1.5  christos 
     34   1.1     lukem #include "portable.h"
     35   1.1     lukem 
     36   1.1     lukem #include <stdio.h>
     37   1.1     lukem #include <ac/stdlib.h>
     38   1.1     lukem #include <ac/string.h>
     39   1.2     lukem #include <ac/time.h>
     40   1.1     lukem #include <ac/unistd.h>
     41   1.1     lukem #include <ac/param.h>
     42   1.1     lukem 
     43   1.1     lukem #ifdef SLAPD_CRYPT
     44   1.1     lukem # include <ac/crypt.h>
     45   1.1     lukem 
     46   1.1     lukem # if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD )
     47   1.1     lukem #  ifdef HAVE_SHADOW_H
     48   1.1     lukem #	include <shadow.h>
     49   1.1     lukem #  endif
     50   1.1     lukem #  ifdef HAVE_PWD_H
     51   1.1     lukem #	include <pwd.h>
     52   1.1     lukem #  endif
     53   1.1     lukem #  ifdef HAVE_AIX_SECURITY
     54   1.1     lukem #	include <userpw.h>
     55   1.1     lukem #  endif
     56   1.1     lukem # endif
     57   1.1     lukem #endif
     58   1.1     lukem 
     59   1.1     lukem #include <lber.h>
     60   1.1     lukem 
     61   1.1     lukem #include "ldap_pvt.h"
     62   1.1     lukem #include "lber_pvt.h"
     63   1.1     lukem 
     64   1.1     lukem #include "lutil_md5.h"
     65   1.1     lukem #include "lutil_sha1.h"
     66   1.1     lukem #include "lutil.h"
     67   1.1     lukem 
     68   1.1     lukem static const unsigned char crypt64[] =
     69   1.1     lukem 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
     70   1.1     lukem 
     71   1.1     lukem #ifdef SLAPD_CRYPT
     72   1.1     lukem static char *salt_format = NULL;
     73   1.1     lukem static lutil_cryptfunc lutil_crypt;
     74   1.1     lukem lutil_cryptfunc *lutil_cryptptr = lutil_crypt;
     75   1.1     lukem #endif
     76   1.1     lukem 
     77   1.1     lukem /* KLUDGE:
     78   1.1     lukem  *  chk_fn is NULL iff name is {CLEARTEXT}
     79   1.1     lukem  *	otherwise, things will break
     80   1.1     lukem  */
     81   1.1     lukem struct pw_scheme {
     82   1.1     lukem 	struct berval name;
     83   1.1     lukem 	LUTIL_PASSWD_CHK_FUNC *chk_fn;
     84   1.1     lukem 	LUTIL_PASSWD_HASH_FUNC *hash_fn;
     85   1.1     lukem };
     86   1.1     lukem 
     87   1.1     lukem struct pw_slist {
     88   1.1     lukem 	struct pw_slist *next;
     89   1.1     lukem 	struct pw_scheme s;
     90   1.1     lukem };
     91   1.1     lukem 
     92   1.1     lukem /* password check routines */
     93   1.1     lukem 
     94   1.1     lukem #define	SALT_SIZE	4
     95   1.1     lukem 
     96   1.1     lukem static LUTIL_PASSWD_CHK_FUNC chk_md5;
     97   1.1     lukem static LUTIL_PASSWD_CHK_FUNC chk_smd5;
     98   1.1     lukem static LUTIL_PASSWD_HASH_FUNC hash_smd5;
     99   1.1     lukem static LUTIL_PASSWD_HASH_FUNC hash_md5;
    100   1.1     lukem 
    101   1.1     lukem 
    102   1.1     lukem #ifdef LUTIL_SHA1_BYTES
    103   1.1     lukem static LUTIL_PASSWD_CHK_FUNC chk_ssha1;
    104   1.1     lukem static LUTIL_PASSWD_CHK_FUNC chk_sha1;
    105   1.1     lukem static LUTIL_PASSWD_HASH_FUNC hash_sha1;
    106   1.1     lukem static LUTIL_PASSWD_HASH_FUNC hash_ssha1;
    107   1.1     lukem #endif
    108   1.1     lukem 
    109   1.1     lukem 
    110   1.1     lukem #ifdef SLAPD_CRYPT
    111   1.1     lukem static LUTIL_PASSWD_CHK_FUNC chk_crypt;
    112   1.1     lukem static LUTIL_PASSWD_HASH_FUNC hash_crypt;
    113   1.1     lukem 
    114   1.1     lukem #if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD )
    115   1.1     lukem static LUTIL_PASSWD_CHK_FUNC chk_unix;
    116   1.1     lukem #endif
    117   1.1     lukem #endif
    118   1.1     lukem 
    119   1.1     lukem /* password hash routines */
    120   1.1     lukem 
    121   1.1     lukem #ifdef SLAPD_CLEARTEXT
    122   1.1     lukem static LUTIL_PASSWD_HASH_FUNC hash_clear;
    123   1.1     lukem #endif
    124   1.1     lukem 
    125   1.1     lukem static struct pw_slist *pw_schemes;
    126   1.1     lukem static int pw_inited;
    127   1.1     lukem 
    128   1.1     lukem static const struct pw_scheme pw_schemes_default[] =
    129   1.1     lukem {
    130   1.1     lukem #ifdef LUTIL_SHA1_BYTES
    131   1.1     lukem 	{ BER_BVC("{SSHA}"),		chk_ssha1, hash_ssha1 },
    132   1.1     lukem 	{ BER_BVC("{SHA}"),			chk_sha1, hash_sha1 },
    133   1.1     lukem #endif
    134   1.1     lukem 
    135   1.1     lukem 	{ BER_BVC("{SMD5}"),		chk_smd5, hash_smd5 },
    136   1.1     lukem 	{ BER_BVC("{MD5}"),			chk_md5, hash_md5 },
    137   1.1     lukem 
    138   1.1     lukem #ifdef SLAPD_CRYPT
    139   1.1     lukem 	{ BER_BVC("{CRYPT}"),		chk_crypt, hash_crypt },
    140   1.1     lukem # if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD )
    141   1.1     lukem 	{ BER_BVC("{UNIX}"),		chk_unix, NULL },
    142   1.1     lukem # endif
    143   1.1     lukem #endif
    144   1.1     lukem 
    145   1.1     lukem #ifdef SLAPD_CLEARTEXT
    146   1.1     lukem 	/* pseudo scheme */
    147   1.1     lukem 	{ BER_BVC("{CLEARTEXT}"),	NULL, hash_clear },
    148   1.1     lukem #endif
    149   1.1     lukem 
    150   1.1     lukem 	{ BER_BVNULL, NULL, NULL }
    151   1.1     lukem };
    152   1.1     lukem 
    153   1.1     lukem int lutil_passwd_add(
    154   1.1     lukem 	struct berval *scheme,
    155   1.1     lukem 	LUTIL_PASSWD_CHK_FUNC *chk,
    156   1.1     lukem 	LUTIL_PASSWD_HASH_FUNC *hash )
    157   1.1     lukem {
    158   1.1     lukem 	struct pw_slist *ptr;
    159   1.1     lukem 
    160   1.1     lukem 	if (!pw_inited) lutil_passwd_init();
    161   1.1     lukem 
    162   1.1     lukem 	ptr = ber_memalloc( sizeof( struct pw_slist ));
    163   1.1     lukem 	if (!ptr) return -1;
    164   1.1     lukem 	ptr->next = pw_schemes;
    165   1.1     lukem 	ptr->s.name = *scheme;
    166   1.1     lukem 	ptr->s.chk_fn = chk;
    167   1.1     lukem 	ptr->s.hash_fn = hash;
    168   1.1     lukem 	pw_schemes = ptr;
    169   1.1     lukem 	return 0;
    170   1.1     lukem }
    171   1.1     lukem 
    172   1.1     lukem void lutil_passwd_init()
    173   1.1     lukem {
    174   1.1     lukem 	struct pw_scheme *s;
    175   1.1     lukem 
    176   1.1     lukem 	pw_inited = 1;
    177   1.1     lukem 
    178   1.1     lukem 	for( s=(struct pw_scheme *)pw_schemes_default; s->name.bv_val; s++) {
    179   1.1     lukem 		if ( lutil_passwd_add( &s->name, s->chk_fn, s->hash_fn ) ) break;
    180   1.1     lukem 	}
    181   1.1     lukem }
    182   1.1     lukem 
    183   1.1     lukem void lutil_passwd_destroy()
    184   1.1     lukem {
    185   1.1     lukem 	struct pw_slist *ptr, *next;
    186   1.1     lukem 
    187   1.1     lukem 	for( ptr=pw_schemes; ptr; ptr=next ) {
    188   1.1     lukem 		next = ptr->next;
    189   1.1     lukem 		ber_memfree( ptr );
    190   1.1     lukem 	}
    191   1.1     lukem }
    192   1.1     lukem 
    193   1.1     lukem static const struct pw_scheme *get_scheme(
    194   1.1     lukem 	const char* scheme )
    195   1.1     lukem {
    196   1.1     lukem 	struct pw_slist *pws;
    197   1.1     lukem 	struct berval bv;
    198   1.1     lukem 
    199   1.1     lukem 	if (!pw_inited) lutil_passwd_init();
    200   1.1     lukem 
    201   1.1     lukem 	bv.bv_val = strchr( scheme, '}' );
    202   1.1     lukem 	if ( !bv.bv_val )
    203   1.1     lukem 		return NULL;
    204   1.1     lukem 
    205   1.1     lukem 	bv.bv_len = bv.bv_val - scheme + 1;
    206   1.1     lukem 	bv.bv_val = (char *) scheme;
    207   1.1     lukem 
    208   1.1     lukem 	for( pws=pw_schemes; pws; pws=pws->next ) {
    209   1.1     lukem 		if ( ber_bvstrcasecmp(&bv, &pws->s.name ) == 0 ) {
    210   1.1     lukem 			return &(pws->s);
    211   1.1     lukem 		}
    212   1.1     lukem 	}
    213   1.1     lukem 
    214   1.1     lukem 	return NULL;
    215   1.1     lukem }
    216   1.1     lukem 
    217   1.1     lukem int lutil_passwd_scheme(
    218   1.1     lukem 	const char* scheme )
    219   1.1     lukem {
    220   1.1     lukem 	if( scheme == NULL ) {
    221   1.1     lukem 		return 0;
    222   1.1     lukem 	}
    223   1.1     lukem 
    224   1.1     lukem 	return get_scheme(scheme) != NULL;
    225   1.1     lukem }
    226   1.1     lukem 
    227   1.1     lukem 
    228   1.1     lukem static int is_allowed_scheme(
    229   1.1     lukem 	const char* scheme,
    230   1.1     lukem 	const char** schemes )
    231   1.1     lukem {
    232   1.1     lukem 	int i;
    233   1.1     lukem 
    234   1.1     lukem 	if( schemes == NULL ) return 1;
    235   1.1     lukem 
    236   1.1     lukem 	for( i=0; schemes[i] != NULL; i++ ) {
    237   1.1     lukem 		if( strcasecmp( scheme, schemes[i] ) == 0 ) {
    238   1.1     lukem 			return 1;
    239   1.1     lukem 		}
    240   1.1     lukem 	}
    241   1.1     lukem 	return 0;
    242   1.1     lukem }
    243   1.1     lukem 
    244   1.1     lukem static struct berval *passwd_scheme(
    245   1.1     lukem 	const struct pw_scheme *scheme,
    246   1.1     lukem 	const struct berval * passwd,
    247   1.1     lukem 	struct berval *bv,
    248   1.1     lukem 	const char** allowed )
    249   1.1     lukem {
    250   1.1     lukem 	if( !is_allowed_scheme( scheme->name.bv_val, allowed ) ) {
    251   1.1     lukem 		return NULL;
    252   1.1     lukem 	}
    253   1.1     lukem 
    254   1.1     lukem 	if( passwd->bv_len >= scheme->name.bv_len ) {
    255   1.1     lukem 		if( strncasecmp( passwd->bv_val, scheme->name.bv_val, scheme->name.bv_len ) == 0 ) {
    256   1.1     lukem 			bv->bv_val = &passwd->bv_val[scheme->name.bv_len];
    257   1.1     lukem 			bv->bv_len = passwd->bv_len - scheme->name.bv_len;
    258   1.1     lukem 
    259   1.1     lukem 			return bv;
    260   1.1     lukem 		}
    261   1.1     lukem 	}
    262   1.1     lukem 
    263   1.1     lukem 	return NULL;
    264   1.1     lukem }
    265   1.1     lukem 
    266   1.1     lukem /*
    267   1.1     lukem  * Return 0 if creds are good.
    268   1.1     lukem  */
    269   1.1     lukem int
    270   1.1     lukem lutil_passwd(
    271   1.1     lukem 	const struct berval *passwd,	/* stored passwd */
    272   1.1     lukem 	const struct berval *cred,		/* user cred */
    273   1.1     lukem 	const char **schemes,
    274   1.1     lukem 	const char **text )
    275   1.1     lukem {
    276   1.1     lukem 	struct pw_slist *pws;
    277   1.1     lukem 
    278   1.1     lukem 	if ( text ) *text = NULL;
    279   1.1     lukem 
    280   1.1     lukem 	if (cred == NULL || cred->bv_len == 0 ||
    281   1.1     lukem 		passwd == NULL || passwd->bv_len == 0 )
    282   1.1     lukem 	{
    283   1.1     lukem 		return -1;
    284   1.1     lukem 	}
    285   1.1     lukem 
    286   1.1     lukem 	if (!pw_inited) lutil_passwd_init();
    287   1.1     lukem 
    288   1.1     lukem 	for( pws=pw_schemes; pws; pws=pws->next ) {
    289   1.1     lukem 		if( pws->s.chk_fn ) {
    290   1.1     lukem 			struct berval x;
    291   1.1     lukem 			struct berval *p = passwd_scheme( &(pws->s),
    292   1.1     lukem 				passwd, &x, schemes );
    293   1.1     lukem 
    294   1.1     lukem 			if( p != NULL ) {
    295   1.1     lukem 				return (pws->s.chk_fn)( &(pws->s.name), p, cred, text );
    296   1.1     lukem 			}
    297   1.1     lukem 		}
    298   1.1     lukem 	}
    299   1.1     lukem 
    300   1.1     lukem #ifdef SLAPD_CLEARTEXT
    301   1.1     lukem 	/* Do we think there is a scheme specifier here that we
    302   1.1     lukem 	 * didn't recognize? Assume a scheme name is at least 1 character.
    303   1.1     lukem 	 */
    304   1.1     lukem 	if (( passwd->bv_val[0] == '{' ) &&
    305   1.1     lukem 		( ber_bvchr( passwd, '}' ) > passwd->bv_val+1 ))
    306   1.1     lukem 	{
    307   1.1     lukem 		return 1;
    308   1.1     lukem 	}
    309   1.1     lukem 	if( is_allowed_scheme("{CLEARTEXT}", schemes ) ) {
    310   1.1     lukem 		return ( passwd->bv_len == cred->bv_len ) ?
    311   1.1     lukem 			memcmp( passwd->bv_val, cred->bv_val, passwd->bv_len )
    312   1.1     lukem 			: 1;
    313   1.1     lukem 	}
    314   1.1     lukem #endif
    315   1.1     lukem 	return 1;
    316   1.1     lukem }
    317   1.1     lukem 
    318   1.1     lukem int lutil_passwd_generate( struct berval *pw, ber_len_t len )
    319   1.1     lukem {
    320   1.1     lukem 
    321   1.1     lukem 	if( len < 1 ) return -1;
    322   1.1     lukem 
    323   1.1     lukem 	pw->bv_len = len;
    324   1.1     lukem 	pw->bv_val = ber_memalloc( len + 1 );
    325   1.1     lukem 
    326   1.1     lukem 	if( pw->bv_val == NULL ) {
    327   1.1     lukem 		return -1;
    328   1.1     lukem 	}
    329   1.1     lukem 
    330   1.1     lukem 	if( lutil_entropy( (unsigned char *) pw->bv_val, pw->bv_len) < 0 ) {
    331   1.1     lukem 		return -1;
    332   1.1     lukem 	}
    333   1.1     lukem 
    334   1.1     lukem 	for( len = 0; len < pw->bv_len; len++ ) {
    335   1.1     lukem 		pw->bv_val[len] = crypt64[
    336   1.1     lukem 			pw->bv_val[len] % (sizeof(crypt64)-1) ];
    337   1.1     lukem 	}
    338   1.1     lukem 
    339   1.1     lukem 	pw->bv_val[len] = '\0';
    340   1.1     lukem 
    341   1.1     lukem 	return 0;
    342   1.1     lukem }
    343   1.1     lukem 
    344   1.1     lukem int lutil_passwd_hash(
    345   1.1     lukem 	const struct berval * passwd,
    346   1.1     lukem 	const char * method,
    347   1.1     lukem 	struct berval *hash,
    348   1.1     lukem 	const char **text )
    349   1.1     lukem {
    350   1.1     lukem 	const struct pw_scheme *sc = get_scheme( method );
    351   1.1     lukem 
    352   1.1     lukem 	hash->bv_val = NULL;
    353   1.1     lukem 	hash->bv_len = 0;
    354   1.1     lukem 
    355   1.1     lukem 	if( sc == NULL ) {
    356   1.1     lukem 		if( text ) *text = "scheme not recognized";
    357   1.1     lukem 		return -1;
    358   1.1     lukem 	}
    359   1.1     lukem 
    360   1.1     lukem 	if( ! sc->hash_fn ) {
    361   1.1     lukem 		if( text ) *text = "scheme provided no hash function";
    362   1.1     lukem 		return -1;
    363   1.1     lukem 	}
    364   1.1     lukem 
    365   1.1     lukem 	if( text ) *text = NULL;
    366   1.1     lukem 
    367   1.1     lukem 	return (sc->hash_fn)( &sc->name, passwd, hash, text );
    368   1.1     lukem }
    369   1.1     lukem 
    370   1.9  christos /* pw_string is only called when SLAPD_CRYPT is defined */
    371   1.9  christos #if defined(SLAPD_CRYPT)
    372   1.1     lukem static int pw_string(
    373   1.1     lukem 	const struct berval *sc,
    374   1.1     lukem 	struct berval *passwd )
    375   1.1     lukem {
    376   1.1     lukem 	struct berval pw;
    377   1.1     lukem 
    378   1.1     lukem 	pw.bv_len = sc->bv_len + passwd->bv_len;
    379   1.1     lukem 	pw.bv_val = ber_memalloc( pw.bv_len + 1 );
    380   1.1     lukem 
    381   1.1     lukem 	if( pw.bv_val == NULL ) {
    382   1.1     lukem 		return LUTIL_PASSWD_ERR;
    383   1.1     lukem 	}
    384   1.1     lukem 
    385   1.1     lukem 	AC_MEMCPY( pw.bv_val, sc->bv_val, sc->bv_len );
    386   1.1     lukem 	AC_MEMCPY( &pw.bv_val[sc->bv_len], passwd->bv_val, passwd->bv_len );
    387   1.1     lukem 
    388   1.1     lukem 	pw.bv_val[pw.bv_len] = '\0';
    389   1.1     lukem 	*passwd = pw;
    390   1.1     lukem 
    391   1.1     lukem 	return LUTIL_PASSWD_OK;
    392   1.1     lukem }
    393   1.9  christos #endif /* SLAPD_CRYPT */
    394   1.1     lukem 
    395   1.4      tron int lutil_passwd_string64(
    396   1.1     lukem 	const struct berval *sc,
    397   1.1     lukem 	const struct berval *hash,
    398   1.1     lukem 	struct berval *b64,
    399   1.1     lukem 	const struct berval *salt )
    400   1.1     lukem {
    401   1.1     lukem 	int rc;
    402   1.1     lukem 	struct berval string;
    403   1.1     lukem 	size_t b64len;
    404   1.1     lukem 
    405   1.1     lukem 	if( salt ) {
    406   1.1     lukem 		/* need to base64 combined string */
    407   1.1     lukem 		string.bv_len = hash->bv_len + salt->bv_len;
    408   1.1     lukem 		string.bv_val = ber_memalloc( string.bv_len + 1 );
    409   1.1     lukem 
    410   1.1     lukem 		if( string.bv_val == NULL ) {
    411   1.1     lukem 			return LUTIL_PASSWD_ERR;
    412   1.1     lukem 		}
    413   1.1     lukem 
    414   1.1     lukem 		AC_MEMCPY( string.bv_val, hash->bv_val,
    415   1.1     lukem 			hash->bv_len );
    416   1.1     lukem 		AC_MEMCPY( &string.bv_val[hash->bv_len], salt->bv_val,
    417   1.1     lukem 			salt->bv_len );
    418   1.1     lukem 		string.bv_val[string.bv_len] = '\0';
    419   1.1     lukem 
    420   1.1     lukem 	} else {
    421   1.1     lukem 		string = *hash;
    422   1.1     lukem 	}
    423   1.1     lukem 
    424   1.1     lukem 	b64len = LUTIL_BASE64_ENCODE_LEN( string.bv_len ) + 1;
    425   1.1     lukem 	b64->bv_len = b64len + sc->bv_len;
    426   1.1     lukem 	b64->bv_val = ber_memalloc( b64->bv_len + 1 );
    427   1.1     lukem 
    428   1.1     lukem 	if( b64->bv_val == NULL ) {
    429   1.1     lukem 		if( salt ) ber_memfree( string.bv_val );
    430   1.1     lukem 		return LUTIL_PASSWD_ERR;
    431   1.1     lukem 	}
    432   1.1     lukem 
    433   1.1     lukem 	AC_MEMCPY(b64->bv_val, sc->bv_val, sc->bv_len);
    434   1.1     lukem 
    435   1.1     lukem 	rc = lutil_b64_ntop(
    436   1.1     lukem 		(unsigned char *) string.bv_val, string.bv_len,
    437   1.1     lukem 		&b64->bv_val[sc->bv_len], b64len );
    438   1.1     lukem 
    439   1.1     lukem 	if( salt ) ber_memfree( string.bv_val );
    440   1.1     lukem 
    441   1.1     lukem 	if( rc < 0 ) {
    442   1.1     lukem 		return LUTIL_PASSWD_ERR;
    443   1.1     lukem 	}
    444   1.1     lukem 
    445   1.1     lukem 	/* recompute length */
    446   1.1     lukem 	b64->bv_len = sc->bv_len + rc;
    447   1.1     lukem 	assert( strlen(b64->bv_val) == b64->bv_len );
    448   1.1     lukem 	return LUTIL_PASSWD_OK;
    449   1.1     lukem }
    450   1.1     lukem 
    451   1.1     lukem /* PASSWORD CHECK ROUTINES */
    452   1.1     lukem 
    453   1.1     lukem #ifdef LUTIL_SHA1_BYTES
    454   1.1     lukem static int chk_ssha1(
    455   1.1     lukem 	const struct berval *sc,
    456   1.1     lukem 	const struct berval * passwd,
    457   1.1     lukem 	const struct berval * cred,
    458   1.1     lukem 	const char **text )
    459   1.1     lukem {
    460   1.1     lukem 	lutil_SHA1_CTX SHA1context;
    461   1.1     lukem 	unsigned char SHA1digest[LUTIL_SHA1_BYTES];
    462   1.1     lukem 	int rc;
    463   1.1     lukem 	unsigned char *orig_pass = NULL;
    464   1.5  christos 	size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len);
    465   1.1     lukem 
    466   1.1     lukem 	/* safety check -- must have some salt */
    467   1.5  christos 	if (decode_len <= sizeof(SHA1digest)) {
    468   1.1     lukem 		return LUTIL_PASSWD_ERR;
    469   1.1     lukem 	}
    470   1.1     lukem 
    471   1.1     lukem 	/* decode base64 password */
    472   1.5  christos 	orig_pass = (unsigned char *) ber_memalloc(decode_len + 1);
    473   1.1     lukem 
    474   1.1     lukem 	if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
    475   1.1     lukem 
    476   1.5  christos 	rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len);
    477   1.1     lukem 
    478   1.1     lukem 	/* safety check -- must have some salt */
    479   1.1     lukem 	if (rc <= (int)(sizeof(SHA1digest))) {
    480   1.1     lukem 		ber_memfree(orig_pass);
    481   1.1     lukem 		return LUTIL_PASSWD_ERR;
    482   1.1     lukem 	}
    483   1.1     lukem 
    484   1.1     lukem 	/* hash credentials with salt */
    485   1.1     lukem 	lutil_SHA1Init(&SHA1context);
    486   1.1     lukem 	lutil_SHA1Update(&SHA1context,
    487   1.1     lukem 		(const unsigned char *) cred->bv_val, cred->bv_len);
    488   1.1     lukem 	lutil_SHA1Update(&SHA1context,
    489   1.1     lukem 		(const unsigned char *) &orig_pass[sizeof(SHA1digest)],
    490   1.1     lukem 		rc - sizeof(SHA1digest));
    491   1.1     lukem 	lutil_SHA1Final(SHA1digest, &SHA1context);
    492   1.1     lukem 
    493   1.1     lukem 	/* compare */
    494   1.1     lukem 	rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
    495   1.1     lukem 	ber_memfree(orig_pass);
    496   1.1     lukem 	return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
    497   1.1     lukem }
    498   1.1     lukem 
    499   1.1     lukem static int chk_sha1(
    500   1.1     lukem 	const struct berval *sc,
    501   1.1     lukem 	const struct berval * passwd,
    502   1.1     lukem 	const struct berval * cred,
    503   1.1     lukem 	const char **text )
    504   1.1     lukem {
    505   1.1     lukem 	lutil_SHA1_CTX SHA1context;
    506   1.1     lukem 	unsigned char SHA1digest[LUTIL_SHA1_BYTES];
    507   1.1     lukem 	int rc;
    508   1.1     lukem 	unsigned char *orig_pass = NULL;
    509   1.5  christos 	size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len);
    510   1.1     lukem 
    511   1.1     lukem 	/* safety check */
    512   1.5  christos 	if (decode_len < sizeof(SHA1digest)) {
    513   1.1     lukem 		return LUTIL_PASSWD_ERR;
    514   1.1     lukem 	}
    515   1.1     lukem 
    516   1.1     lukem 	/* base64 un-encode password */
    517   1.5  christos 	orig_pass = (unsigned char *) ber_memalloc(decode_len + 1);
    518   1.1     lukem 
    519   1.1     lukem 	if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
    520   1.1     lukem 
    521   1.5  christos 	rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len);
    522   1.1     lukem 
    523   1.1     lukem 	if( rc != sizeof(SHA1digest) ) {
    524   1.1     lukem 		ber_memfree(orig_pass);
    525   1.1     lukem 		return LUTIL_PASSWD_ERR;
    526   1.1     lukem 	}
    527   1.1     lukem 
    528   1.1     lukem 	/* hash credentials with salt */
    529   1.1     lukem 	lutil_SHA1Init(&SHA1context);
    530   1.1     lukem 	lutil_SHA1Update(&SHA1context,
    531   1.1     lukem 		(const unsigned char *) cred->bv_val, cred->bv_len);
    532   1.1     lukem 	lutil_SHA1Final(SHA1digest, &SHA1context);
    533   1.1     lukem 
    534   1.1     lukem 	/* compare */
    535   1.1     lukem 	rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
    536   1.1     lukem 	ber_memfree(orig_pass);
    537   1.1     lukem 	return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
    538   1.1     lukem }
    539   1.1     lukem #endif
    540   1.1     lukem 
    541   1.1     lukem static int chk_smd5(
    542   1.1     lukem 	const struct berval *sc,
    543   1.1     lukem 	const struct berval * passwd,
    544   1.1     lukem 	const struct berval * cred,
    545   1.1     lukem 	const char **text )
    546   1.1     lukem {
    547   1.1     lukem 	lutil_MD5_CTX MD5context;
    548   1.1     lukem 	unsigned char MD5digest[LUTIL_MD5_BYTES];
    549   1.1     lukem 	int rc;
    550   1.1     lukem 	unsigned char *orig_pass = NULL;
    551   1.5  christos 	size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len);
    552   1.1     lukem 
    553   1.1     lukem 	/* safety check */
    554   1.5  christos 	if (decode_len <= sizeof(MD5digest)) {
    555   1.1     lukem 		return LUTIL_PASSWD_ERR;
    556   1.1     lukem 	}
    557   1.1     lukem 
    558   1.1     lukem 	/* base64 un-encode password */
    559   1.5  christos 	orig_pass = (unsigned char *) ber_memalloc(decode_len + 1);
    560   1.1     lukem 
    561   1.1     lukem 	if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
    562   1.1     lukem 
    563   1.5  christos 	rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len);
    564   1.1     lukem 
    565   1.1     lukem 	if (rc <= (int)(sizeof(MD5digest))) {
    566   1.1     lukem 		ber_memfree(orig_pass);
    567   1.1     lukem 		return LUTIL_PASSWD_ERR;
    568   1.1     lukem 	}
    569   1.1     lukem 
    570   1.1     lukem 	/* hash credentials with salt */
    571   1.1     lukem 	lutil_MD5Init(&MD5context);
    572   1.1     lukem 	lutil_MD5Update(&MD5context,
    573   1.1     lukem 		(const unsigned char *) cred->bv_val,
    574   1.1     lukem 		cred->bv_len );
    575   1.1     lukem 	lutil_MD5Update(&MD5context,
    576   1.1     lukem 		&orig_pass[sizeof(MD5digest)],
    577   1.1     lukem 		rc - sizeof(MD5digest));
    578   1.1     lukem 	lutil_MD5Final(MD5digest, &MD5context);
    579   1.1     lukem 
    580   1.1     lukem 	/* compare */
    581   1.1     lukem 	rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
    582   1.1     lukem 	ber_memfree(orig_pass);
    583   1.1     lukem 	return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
    584   1.1     lukem }
    585   1.1     lukem 
    586   1.1     lukem static int chk_md5(
    587   1.1     lukem 	const struct berval *sc,
    588   1.1     lukem 	const struct berval * passwd,
    589   1.1     lukem 	const struct berval * cred,
    590   1.1     lukem 	const char **text )
    591   1.1     lukem {
    592   1.1     lukem 	lutil_MD5_CTX MD5context;
    593   1.1     lukem 	unsigned char MD5digest[LUTIL_MD5_BYTES];
    594   1.1     lukem 	int rc;
    595   1.1     lukem 	unsigned char *orig_pass = NULL;
    596   1.5  christos 	size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len);
    597   1.1     lukem 
    598   1.1     lukem 	/* safety check */
    599   1.5  christos 	if (decode_len < sizeof(MD5digest)) {
    600   1.1     lukem 		return LUTIL_PASSWD_ERR;
    601   1.1     lukem 	}
    602   1.1     lukem 
    603   1.1     lukem 	/* base64 un-encode password */
    604   1.5  christos 	orig_pass = (unsigned char *) ber_memalloc(decode_len + 1);
    605   1.1     lukem 
    606   1.1     lukem 	if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
    607   1.1     lukem 
    608   1.5  christos 	rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len);
    609   1.1     lukem 	if ( rc != sizeof(MD5digest) ) {
    610   1.1     lukem 		ber_memfree(orig_pass);
    611   1.1     lukem 		return LUTIL_PASSWD_ERR;
    612   1.1     lukem 	}
    613   1.1     lukem 
    614   1.1     lukem 	/* hash credentials with salt */
    615   1.1     lukem 	lutil_MD5Init(&MD5context);
    616   1.1     lukem 	lutil_MD5Update(&MD5context,
    617   1.1     lukem 		(const unsigned char *) cred->bv_val,
    618   1.1     lukem 		cred->bv_len );
    619   1.1     lukem 	lutil_MD5Final(MD5digest, &MD5context);
    620   1.1     lukem 
    621   1.1     lukem 	/* compare */
    622   1.1     lukem 	rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
    623   1.1     lukem 	ber_memfree(orig_pass);
    624   1.1     lukem 	return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
    625   1.1     lukem }
    626   1.1     lukem 
    627   1.1     lukem #ifdef SLAPD_CRYPT
    628   1.1     lukem static int lutil_crypt(
    629   1.1     lukem 	const char *key,
    630   1.1     lukem 	const char *salt,
    631   1.1     lukem 	char **hash )
    632   1.1     lukem {
    633   1.1     lukem 	char *cr = crypt( key, salt );
    634   1.1     lukem 	int rc;
    635   1.1     lukem 
    636   1.1     lukem 	if( cr == NULL || cr[0] == '\0' ) {
    637   1.1     lukem 		/* salt must have been invalid */
    638   1.1     lukem 		rc = LUTIL_PASSWD_ERR;
    639   1.1     lukem 	} else {
    640   1.1     lukem 		if ( hash ) {
    641   1.1     lukem 			*hash = ber_strdup( cr );
    642   1.1     lukem 			rc = LUTIL_PASSWD_OK;
    643   1.1     lukem 		} else {
    644   1.1     lukem 			rc = strcmp( salt, cr ) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
    645   1.1     lukem 		}
    646   1.1     lukem 	}
    647   1.1     lukem 	return rc;
    648   1.1     lukem }
    649   1.1     lukem 
    650   1.1     lukem static int chk_crypt(
    651   1.1     lukem 	const struct berval *sc,
    652   1.1     lukem 	const struct berval * passwd,
    653   1.1     lukem 	const struct berval * cred,
    654   1.1     lukem 	const char **text )
    655   1.1     lukem {
    656   1.1     lukem 	unsigned int i;
    657   1.1     lukem 
    658   1.1     lukem 	for( i=0; i<cred->bv_len; i++) {
    659   1.1     lukem 		if(cred->bv_val[i] == '\0') {
    660   1.1     lukem 			return LUTIL_PASSWD_ERR;	/* NUL character in password */
    661   1.1     lukem 		}
    662   1.1     lukem 	}
    663   1.1     lukem 
    664   1.1     lukem 	if( cred->bv_val[i] != '\0' ) {
    665   1.1     lukem 		return LUTIL_PASSWD_ERR;	/* cred must behave like a string */
    666   1.1     lukem 	}
    667   1.1     lukem 
    668   1.1     lukem 	if( passwd->bv_len < 2 ) {
    669   1.1     lukem 		return LUTIL_PASSWD_ERR;	/* passwd must be at least two characters long */
    670   1.1     lukem 	}
    671   1.1     lukem 
    672   1.1     lukem 	for( i=0; i<passwd->bv_len; i++) {
    673   1.1     lukem 		if(passwd->bv_val[i] == '\0') {
    674   1.1     lukem 			return LUTIL_PASSWD_ERR;	/* NUL character in password */
    675   1.1     lukem 		}
    676   1.1     lukem 	}
    677   1.1     lukem 
    678   1.1     lukem 	if( passwd->bv_val[i] != '\0' ) {
    679   1.1     lukem 		return LUTIL_PASSWD_ERR;	/* passwd must behave like a string */
    680   1.1     lukem 	}
    681   1.1     lukem 
    682   1.1     lukem 	return lutil_cryptptr( cred->bv_val, passwd->bv_val, NULL );
    683   1.1     lukem }
    684   1.1     lukem 
    685   1.1     lukem # if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD )
    686   1.1     lukem static int chk_unix(
    687   1.1     lukem 	const struct berval *sc,
    688   1.1     lukem 	const struct berval * passwd,
    689   1.1     lukem 	const struct berval * cred,
    690   1.1     lukem 	const char **text )
    691   1.1     lukem {
    692   1.1     lukem 	unsigned int i;
    693   1.1     lukem 	char *pw;
    694   1.1     lukem 
    695   1.1     lukem 	for( i=0; i<cred->bv_len; i++) {
    696   1.1     lukem 		if(cred->bv_val[i] == '\0') {
    697   1.1     lukem 			return LUTIL_PASSWD_ERR;	/* NUL character in password */
    698   1.1     lukem 		}
    699   1.1     lukem 	}
    700   1.1     lukem 	if( cred->bv_val[i] != '\0' ) {
    701   1.1     lukem 		return LUTIL_PASSWD_ERR;	/* cred must behave like a string */
    702   1.1     lukem 	}
    703   1.1     lukem 
    704   1.1     lukem 	for( i=0; i<passwd->bv_len; i++) {
    705   1.1     lukem 		if(passwd->bv_val[i] == '\0') {
    706   1.1     lukem 			return LUTIL_PASSWD_ERR;	/* NUL character in password */
    707   1.1     lukem 		}
    708   1.1     lukem 	}
    709   1.1     lukem 
    710   1.1     lukem 	if( passwd->bv_val[i] != '\0' ) {
    711   1.1     lukem 		return LUTIL_PASSWD_ERR;	/* passwd must behave like a string */
    712   1.1     lukem 	}
    713   1.1     lukem 
    714   1.1     lukem 	{
    715   1.1     lukem 		struct passwd *pwd = getpwnam(passwd->bv_val);
    716   1.1     lukem 
    717   1.1     lukem 		if(pwd == NULL) {
    718   1.1     lukem 			return LUTIL_PASSWD_ERR;	/* not found */
    719   1.1     lukem 		}
    720   1.1     lukem 
    721   1.1     lukem 		pw = pwd->pw_passwd;
    722   1.1     lukem 	}
    723   1.1     lukem #  ifdef HAVE_GETSPNAM
    724   1.1     lukem 	{
    725   1.1     lukem 		struct spwd *spwd = getspnam(passwd->bv_val);
    726   1.1     lukem 
    727   1.1     lukem 		if(spwd != NULL) {
    728   1.1     lukem 			pw = spwd->sp_pwdp;
    729   1.1     lukem 		}
    730   1.1     lukem 	}
    731   1.1     lukem #  endif
    732   1.1     lukem #  ifdef HAVE_AIX_SECURITY
    733   1.1     lukem 	{
    734   1.1     lukem 		struct userpw *upw = getuserpw(passwd->bv_val);
    735   1.1     lukem 
    736   1.1     lukem 		if (upw != NULL) {
    737   1.1     lukem 			pw = upw->upw_passwd;
    738   1.1     lukem 		}
    739   1.1     lukem 	}
    740   1.1     lukem #  endif
    741   1.1     lukem 
    742   1.1     lukem 	if( pw == NULL || pw[0] == '\0' || pw[1] == '\0' ) {
    743   1.1     lukem 		/* password must must be at least two characters long */
    744   1.1     lukem 		return LUTIL_PASSWD_ERR;
    745   1.1     lukem 	}
    746   1.1     lukem 
    747   1.1     lukem 	return lutil_cryptptr( cred->bv_val, pw, NULL );
    748   1.1     lukem }
    749   1.1     lukem # endif
    750   1.1     lukem #endif
    751   1.1     lukem 
    752   1.1     lukem /* PASSWORD GENERATION ROUTINES */
    753   1.1     lukem 
    754   1.1     lukem #ifdef LUTIL_SHA1_BYTES
    755   1.1     lukem static int hash_ssha1(
    756   1.1     lukem 	const struct berval *scheme,
    757   1.1     lukem 	const struct berval  *passwd,
    758   1.1     lukem 	struct berval *hash,
    759   1.1     lukem 	const char **text )
    760   1.1     lukem {
    761   1.1     lukem 	lutil_SHA1_CTX  SHA1context;
    762   1.1     lukem 	unsigned char   SHA1digest[LUTIL_SHA1_BYTES];
    763   1.1     lukem 	char            saltdata[SALT_SIZE];
    764   1.1     lukem 	struct berval digest;
    765   1.1     lukem 	struct berval salt;
    766   1.1     lukem 
    767   1.1     lukem 	digest.bv_val = (char *) SHA1digest;
    768   1.1     lukem 	digest.bv_len = sizeof(SHA1digest);
    769   1.1     lukem 	salt.bv_val = saltdata;
    770   1.1     lukem 	salt.bv_len = sizeof(saltdata);
    771   1.1     lukem 
    772   1.1     lukem 	if( lutil_entropy( (unsigned char *) salt.bv_val, salt.bv_len) < 0 ) {
    773   1.1     lukem 		return LUTIL_PASSWD_ERR;
    774   1.1     lukem 	}
    775   1.1     lukem 
    776   1.1     lukem 	lutil_SHA1Init( &SHA1context );
    777   1.1     lukem 	lutil_SHA1Update( &SHA1context,
    778   1.1     lukem 		(const unsigned char *)passwd->bv_val, passwd->bv_len );
    779   1.1     lukem 	lutil_SHA1Update( &SHA1context,
    780   1.1     lukem 		(const unsigned char *)salt.bv_val, salt.bv_len );
    781   1.1     lukem 	lutil_SHA1Final( SHA1digest, &SHA1context );
    782   1.1     lukem 
    783   1.4      tron 	return lutil_passwd_string64( scheme, &digest, hash, &salt);
    784   1.1     lukem }
    785   1.1     lukem 
    786   1.1     lukem static int hash_sha1(
    787   1.1     lukem 	const struct berval *scheme,
    788   1.1     lukem 	const struct berval  *passwd,
    789   1.1     lukem 	struct berval *hash,
    790   1.1     lukem 	const char **text )
    791   1.1     lukem {
    792   1.1     lukem 	lutil_SHA1_CTX  SHA1context;
    793   1.1     lukem 	unsigned char   SHA1digest[LUTIL_SHA1_BYTES];
    794   1.1     lukem 	struct berval digest;
    795   1.1     lukem 	digest.bv_val = (char *) SHA1digest;
    796   1.1     lukem 	digest.bv_len = sizeof(SHA1digest);
    797   1.1     lukem 
    798   1.1     lukem 	lutil_SHA1Init( &SHA1context );
    799   1.1     lukem 	lutil_SHA1Update( &SHA1context,
    800   1.1     lukem 		(const unsigned char *)passwd->bv_val, passwd->bv_len );
    801   1.1     lukem 	lutil_SHA1Final( SHA1digest, &SHA1context );
    802   1.1     lukem 
    803   1.4      tron 	return lutil_passwd_string64( scheme, &digest, hash, NULL);
    804   1.1     lukem }
    805   1.1     lukem #endif
    806   1.1     lukem 
    807   1.1     lukem static int hash_smd5(
    808   1.1     lukem 	const struct berval *scheme,
    809   1.1     lukem 	const struct berval  *passwd,
    810   1.1     lukem 	struct berval *hash,
    811   1.1     lukem 	const char **text )
    812   1.1     lukem {
    813   1.1     lukem 	lutil_MD5_CTX   MD5context;
    814   1.1     lukem 	unsigned char   MD5digest[LUTIL_MD5_BYTES];
    815   1.1     lukem 	char            saltdata[SALT_SIZE];
    816   1.1     lukem 	struct berval digest;
    817   1.1     lukem 	struct berval salt;
    818   1.1     lukem 
    819   1.1     lukem 	digest.bv_val = (char *) MD5digest;
    820   1.1     lukem 	digest.bv_len = sizeof(MD5digest);
    821   1.1     lukem 	salt.bv_val = saltdata;
    822   1.1     lukem 	salt.bv_len = sizeof(saltdata);
    823   1.1     lukem 
    824   1.1     lukem 	if( lutil_entropy( (unsigned char *) salt.bv_val, salt.bv_len) < 0 ) {
    825   1.1     lukem 		return LUTIL_PASSWD_ERR;
    826   1.1     lukem 	}
    827   1.1     lukem 
    828   1.1     lukem 	lutil_MD5Init( &MD5context );
    829   1.1     lukem 	lutil_MD5Update( &MD5context,
    830   1.1     lukem 		(const unsigned char *) passwd->bv_val, passwd->bv_len );
    831   1.1     lukem 	lutil_MD5Update( &MD5context,
    832   1.1     lukem 		(const unsigned char *) salt.bv_val, salt.bv_len );
    833   1.1     lukem 	lutil_MD5Final( MD5digest, &MD5context );
    834   1.1     lukem 
    835   1.4      tron 	return lutil_passwd_string64( scheme, &digest, hash, &salt );
    836   1.1     lukem }
    837   1.1     lukem 
    838   1.1     lukem static int hash_md5(
    839   1.1     lukem 	const struct berval *scheme,
    840   1.1     lukem 	const struct berval  *passwd,
    841   1.1     lukem 	struct berval *hash,
    842   1.1     lukem 	const char **text )
    843   1.1     lukem {
    844   1.1     lukem 	lutil_MD5_CTX   MD5context;
    845   1.1     lukem 	unsigned char   MD5digest[LUTIL_MD5_BYTES];
    846   1.1     lukem 
    847   1.1     lukem 	struct berval digest;
    848   1.1     lukem 
    849   1.1     lukem 	digest.bv_val = (char *) MD5digest;
    850   1.1     lukem 	digest.bv_len = sizeof(MD5digest);
    851   1.1     lukem 
    852   1.1     lukem 	lutil_MD5Init( &MD5context );
    853   1.1     lukem 	lutil_MD5Update( &MD5context,
    854   1.1     lukem 		(const unsigned char *) passwd->bv_val, passwd->bv_len );
    855   1.1     lukem 	lutil_MD5Final( MD5digest, &MD5context );
    856   1.1     lukem 
    857   1.4      tron 	return lutil_passwd_string64( scheme, &digest, hash, NULL );
    858   1.1     lukem ;
    859   1.1     lukem }
    860   1.1     lukem 
    861   1.1     lukem #ifdef SLAPD_CRYPT
    862   1.1     lukem static int hash_crypt(
    863   1.1     lukem 	const struct berval *scheme,
    864   1.1     lukem 	const struct berval *passwd,
    865   1.1     lukem 	struct berval *hash,
    866   1.1     lukem 	const char **text )
    867   1.1     lukem {
    868   1.1     lukem 	unsigned char salt[32];	/* salt suitable for most anything */
    869   1.1     lukem 	unsigned int i;
    870   1.1     lukem 	char *save;
    871   1.1     lukem 	int rc;
    872   1.1     lukem 
    873   1.1     lukem 	for( i=0; i<passwd->bv_len; i++) {
    874   1.1     lukem 		if(passwd->bv_val[i] == '\0') {
    875   1.1     lukem 			return LUTIL_PASSWD_ERR;	/* NUL character in password */
    876   1.1     lukem 		}
    877   1.1     lukem 	}
    878   1.1     lukem 
    879   1.1     lukem 	if( passwd->bv_val[i] != '\0' ) {
    880   1.1     lukem 		return LUTIL_PASSWD_ERR;	/* passwd must behave like a string */
    881   1.1     lukem 	}
    882   1.1     lukem 
    883   1.1     lukem 	if( lutil_entropy( salt, sizeof( salt ) ) < 0 ) {
    884   1.1     lukem 		return LUTIL_PASSWD_ERR;
    885   1.1     lukem 	}
    886   1.1     lukem 
    887   1.1     lukem 	for( i=0; i< ( sizeof(salt) - 1 ); i++ ) {
    888   1.1     lukem 		salt[i] = crypt64[ salt[i] % (sizeof(crypt64)-1) ];
    889   1.1     lukem 	}
    890   1.1     lukem 	salt[sizeof( salt ) - 1 ] = '\0';
    891   1.1     lukem 
    892   1.1     lukem 	if( salt_format != NULL ) {
    893   1.1     lukem 		/* copy the salt we made into entropy before snprintfing
    894   1.1     lukem 		   it back into the salt */
    895   1.1     lukem 		char entropy[sizeof(salt)];
    896   1.1     lukem 		strcpy( entropy, (char *) salt );
    897   1.1     lukem 		snprintf( (char *) salt, sizeof(entropy), salt_format, entropy );
    898   1.1     lukem 	}
    899   1.1     lukem 
    900   1.1     lukem 	rc = lutil_cryptptr( passwd->bv_val, (char *) salt, &hash->bv_val );
    901   1.1     lukem 	if ( rc != LUTIL_PASSWD_OK ) return rc;
    902   1.1     lukem 
    903   1.1     lukem 	if( hash->bv_val == NULL ) return -1;
    904   1.1     lukem 
    905   1.1     lukem 	hash->bv_len = strlen( hash->bv_val );
    906   1.1     lukem 
    907   1.1     lukem 	save = hash->bv_val;
    908   1.1     lukem 
    909   1.1     lukem 	if( hash->bv_len == 0 ) {
    910   1.1     lukem 		rc = LUTIL_PASSWD_ERR;
    911   1.1     lukem 	} else {
    912   1.1     lukem 		rc = pw_string( scheme, hash );
    913   1.1     lukem 	}
    914   1.1     lukem 	ber_memfree( save );
    915   1.1     lukem 	return rc;
    916   1.1     lukem }
    917   1.1     lukem #endif
    918   1.1     lukem 
    919   1.1     lukem int lutil_salt_format(const char *format)
    920   1.1     lukem {
    921   1.1     lukem #ifdef SLAPD_CRYPT
    922   1.2     lukem 	ber_memfree( salt_format );
    923   1.1     lukem 
    924   1.1     lukem 	salt_format = format != NULL ? ber_strdup( format ) : NULL;
    925   1.1     lukem #endif
    926   1.1     lukem 
    927   1.1     lukem 	return 0;
    928   1.1     lukem }
    929   1.1     lukem 
    930   1.1     lukem #ifdef SLAPD_CLEARTEXT
    931   1.1     lukem static int hash_clear(
    932   1.1     lukem 	const struct berval *scheme,
    933   1.1     lukem 	const struct berval  *passwd,
    934   1.1     lukem 	struct berval *hash,
    935   1.1     lukem 	const char **text )
    936   1.1     lukem {
    937   1.1     lukem 	ber_dupbv( hash, (struct berval *)passwd );
    938   1.1     lukem 	return LUTIL_PASSWD_OK;
    939   1.1     lukem }
    940   1.1     lukem #endif
    941   1.1     lukem 
    942