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