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