]> git.sur5r.net Git - openldap/blob - libraries/liblutil/passwd.c
ac780b9d4b743e5ae1c73bbfa200bc06f89a6ca9
[openldap] / libraries / liblutil / passwd.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2004 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15
16 /*
17  * int lutil_passwd(
18  *      const struct berval *passwd,
19  *      const struct berval *cred,
20  *      const char **schemes )
21  *
22  * Returns true if user supplied credentials (cred) matches
23  * the stored password (passwd). 
24  *
25  * Due to the use of the crypt(3) function 
26  * this routine is NOT thread-safe.
27  */
28
29 #include "portable.h"
30
31 #include <stdio.h>
32 #include <ac/stdlib.h>
33 #include <ac/string.h>
34 #include <ac/unistd.h>
35
36 #ifdef SLAPD_SPASSWD
37 #       ifdef HAVE_SASL_SASL_H
38 #               include <sasl/sasl.h>
39 #       else
40 #               include <sasl.h>
41 #       endif
42 #endif
43
44 #ifdef SLAPD_KPASSWD
45 #       include <ac/krb.h>
46 #       include <ac/krb5.h>
47 #endif
48
49 /* KPASSWD/krb.h brings in a conflicting des.h so don't use both.
50  * configure currently requires OpenSSL to enable LMHASH. Obviously
51  * this requirement can be fulfilled by the KRB DES library as well.
52  */
53 #if defined(SLAPD_LMHASH) && !defined(DES_ENCRYPT)
54 #       include <openssl/des.h>
55 #endif /* SLAPD_LMHASH */
56
57 #include <ac/param.h>
58
59 #ifdef SLAPD_CRYPT
60 # include <ac/crypt.h>
61
62 # if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD )
63 #  ifdef HAVE_SHADOW_H
64 #       include <shadow.h>
65 #  endif
66 #  ifdef HAVE_PWD_H
67 #       include <pwd.h>
68 #  endif
69 #  ifdef HAVE_AIX_SECURITY
70 #       include <userpw.h>
71 #  endif
72 # endif
73 #endif
74
75 #include <lber.h>
76
77 #include "ldap_pvt.h"
78 #include "lber_pvt.h"
79
80 #include "lutil_md5.h"
81 #include "lutil_sha1.h"
82 #include "lutil.h"
83
84 static const unsigned char crypt64[] =
85         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
86
87 #ifdef SLAPD_CRYPT
88 static char *salt_format = NULL;
89 #endif
90
91 struct pw_scheme {
92         struct berval name;
93         LUTIL_PASSWD_CHK_FUNC *chk_fn;
94         LUTIL_PASSWD_HASH_FUNC *hash_fn;
95 };
96
97 struct pw_slist {
98         struct pw_slist *next;
99         struct pw_scheme s;
100 };
101
102 /* password check routines */
103
104 #define SALT_SIZE       4
105
106 static LUTIL_PASSWD_CHK_FUNC chk_md5;
107 static LUTIL_PASSWD_CHK_FUNC chk_smd5;
108 static LUTIL_PASSWD_HASH_FUNC hash_smd5;
109 static LUTIL_PASSWD_HASH_FUNC hash_md5;
110
111
112 #ifdef LUTIL_SHA1_BYTES
113 static LUTIL_PASSWD_CHK_FUNC chk_ssha1;
114 static LUTIL_PASSWD_CHK_FUNC chk_sha1;
115 static LUTIL_PASSWD_HASH_FUNC hash_sha1;
116 static LUTIL_PASSWD_HASH_FUNC hash_ssha1;
117 #endif
118
119 #ifdef SLAPD_LMHASH
120 static LUTIL_PASSWD_CHK_FUNC chk_lanman;
121 static LUTIL_PASSWD_HASH_FUNC hash_lanman;
122 #endif
123
124 #ifdef SLAPD_NS_MTA_MD5
125 static LUTIL_PASSWD_CHK_FUNC chk_ns_mta_md5;
126 #endif
127
128 #ifdef SLAPD_SPASSWD
129 static LUTIL_PASSWD_CHK_FUNC chk_sasl;
130 #endif
131
132 #ifdef SLAPD_KPASSWD
133 static LUTIL_PASSWD_CHK_FUNC chk_kerberos;
134 #endif
135
136 #ifdef SLAPD_CRYPT
137 static LUTIL_PASSWD_CHK_FUNC chk_crypt;
138 static LUTIL_PASSWD_HASH_FUNC hash_crypt;
139
140 #if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD )
141 static LUTIL_PASSWD_CHK_FUNC chk_unix;
142 #endif
143 #endif
144
145 /* password hash routines */
146
147 #ifdef SLAPD_CLEARTEXT
148 static LUTIL_PASSWD_HASH_FUNC hash_clear;
149 #endif
150
151 static struct pw_slist *pw_schemes;
152
153 static const struct pw_scheme pw_schemes_default[] =
154 {
155 #ifdef LUTIL_SHA1_BYTES
156         { BER_BVC("{SSHA}"),            chk_ssha1, hash_ssha1 },
157         { BER_BVC("{SHA}"),                     chk_sha1, hash_sha1 },
158 #endif
159
160         { BER_BVC("{SMD5}"),            chk_smd5, hash_smd5 },
161         { BER_BVC("{MD5}"),                     chk_md5, hash_md5 },
162
163 #ifdef SLAPD_LMHASH
164         { BER_BVC("{LANMAN}"),          chk_lanman, hash_lanman },
165 #endif /* SLAPD_LMHASH */
166
167 #ifdef SLAPD_NS_MTA_MD5
168         { BER_BVC("{NS-MTA-MD5}"),      chk_ns_mta_md5, NULL },
169 #endif /* SLAPD_NS_MTA_MD5 */
170
171 #ifdef SLAPD_SPASSWD
172         { BER_BVC("{SASL}"),            chk_sasl, NULL },
173 #endif
174
175 #ifdef SLAPD_KPASSWD
176         { BER_BVC("{KERBEROS}"),        chk_kerberos, NULL },
177 #endif
178
179 #ifdef SLAPD_CRYPT
180         { BER_BVC("{CRYPT}"),           chk_crypt, hash_crypt },
181 # if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD )
182         { BER_BVC("{UNIX}"),            chk_unix, NULL },
183 # endif
184 #endif
185
186 #ifdef SLAPD_CLEARTEXT
187         /* pseudo scheme */
188         { {0, "{CLEARTEXT}"},           NULL, hash_clear },
189 #endif
190
191         { BER_BVNULL, NULL, NULL }
192 };
193
194 int lutil_passwd_add(
195         struct berval *scheme,
196         LUTIL_PASSWD_CHK_FUNC *chk,
197         LUTIL_PASSWD_HASH_FUNC *hash )
198 {
199         struct pw_slist *ptr;
200
201         ptr = ber_memalloc( sizeof( struct pw_slist ));
202         if (!ptr) return -1;
203         ptr->next = pw_schemes;
204         ptr->s.name = *scheme;
205         ptr->s.chk_fn = chk;
206         ptr->s.hash_fn = hash;
207         pw_schemes = ptr;
208         return 0;
209 }
210
211 void lutil_passwd_init()
212 {
213         struct pw_slist *ptr;
214         struct pw_scheme *s;
215
216         for( s=(struct pw_scheme *)pw_schemes_default; s->name.bv_val; s++) {
217                 if ( lutil_passwd_add( &s->name, s->chk_fn, s->hash_fn )) break;
218         }
219 }
220
221 void lutil_passwd_destroy()
222 {
223         struct pw_slist *ptr, *next;
224
225         for( ptr=pw_schemes; ptr; ptr=next ) {
226                 next = ptr->next;
227                 ber_memfree( ptr );
228         }
229 }
230
231 static const struct pw_scheme *get_scheme(
232         const char* scheme )
233 {
234         struct pw_slist *pws;
235
236         if (!pw_schemes) lutil_passwd_init();
237
238         for( pws=pw_schemes; pws; pws=pws->next ) {
239                 if( strcasecmp(scheme, pws->s.name.bv_val ) == 0 ) {
240                         return &(pws->s);
241                 }
242         }
243
244         return NULL;
245 }
246
247 int lutil_passwd_scheme(
248         const char* scheme )
249 {
250         if( scheme == NULL ) {
251                 return 0;
252         }
253
254         return get_scheme(scheme) != NULL;
255 }
256
257
258 static int is_allowed_scheme( 
259         const char* scheme,
260         const char** schemes )
261 {
262         int i;
263
264         if( schemes == NULL ) return 1;
265
266         for( i=0; schemes[i] != NULL; i++ ) {
267                 if( strcasecmp( scheme, schemes[i] ) == 0 ) {
268                         return 1;
269                 }
270         }
271         return 0;
272 }
273
274 static struct berval *passwd_scheme(
275         const struct pw_scheme *scheme,
276         const struct berval * passwd,
277         struct berval *bv,
278         const char** allowed )
279 {
280         if( !is_allowed_scheme( scheme->name.bv_val, allowed ) ) {
281                 return NULL;
282         }
283
284         if( passwd->bv_len >= scheme->name.bv_len ) {
285                 if( strncasecmp( passwd->bv_val, scheme->name.bv_val, scheme->name.bv_len ) == 0 ) {
286                         bv->bv_val = &passwd->bv_val[scheme->name.bv_len];
287                         bv->bv_len = passwd->bv_len - scheme->name.bv_len;
288
289                         return bv;
290                 }
291         }
292
293         return NULL;
294 }
295
296 /*
297  * Return 0 if creds are good.
298  */
299 int
300 lutil_passwd(
301         const struct berval *passwd,    /* stored passwd */
302         const struct berval *cred,              /* user cred */
303         const char **schemes,
304         const char **text )
305 {
306         struct pw_slist *pws;
307
308         if ( text ) *text = NULL;
309
310         if (cred == NULL || cred->bv_len == 0 ||
311                 passwd == NULL || passwd->bv_len == 0 )
312         {
313                 return -1;
314         }
315
316         if (!pw_schemes) lutil_passwd_init();
317
318         for( pws=pw_schemes; pws; pws=pws->next ) {
319                 if( pws->s.chk_fn ) {
320                         struct berval x;
321                         struct berval *p = passwd_scheme( &(pws->s),
322                                 passwd, &x, schemes );
323
324                         if( p != NULL ) {
325                                 return (pws->s.chk_fn)( &(pws->s.name), p, cred, text );
326                         }
327                 }
328         }
329
330 #ifdef SLAPD_CLEARTEXT
331         if( is_allowed_scheme("{CLEARTEXT}", schemes ) ) {
332                 return (( passwd->bv_len == cred->bv_len ) &&
333                                 ( passwd->bv_val[0] != '{' /*'}'*/ ))
334                         ? memcmp( passwd->bv_val, cred->bv_val, passwd->bv_len )
335                         : 1;
336         }
337 #endif
338         return 1;
339 }
340
341 struct berval * lutil_passwd_generate( ber_len_t len )
342 {
343         struct berval *pw;
344
345         if( len < 1 ) return NULL;
346
347         pw = ber_memalloc( sizeof( struct berval ) );
348         if( pw == NULL ) return NULL;
349
350         pw->bv_len = len;
351         pw->bv_val = ber_memalloc( len + 1 );
352
353         if( pw->bv_val == NULL ) {
354                 ber_memfree( pw );
355                 return NULL;
356         }
357
358         if( lutil_entropy( (unsigned char *) pw->bv_val, pw->bv_len) < 0 ) {
359                 ber_bvfree( pw );
360                 return NULL; 
361         }
362
363         for( len = 0; len < pw->bv_len; len++ ) {
364                 pw->bv_val[len] = crypt64[
365                         pw->bv_val[len] % (sizeof(crypt64)-1) ];
366         }
367
368         pw->bv_val[len] = '\0';
369         
370         return pw;
371 }
372
373 struct berval * lutil_passwd_hash(
374         const struct berval * passwd,
375         const char * method,
376         const char **text )
377 {
378         const struct pw_scheme *sc = get_scheme( method );
379
380         if( sc == NULL ) {
381                 if( text ) *text = "scheme not recognized";
382                 return NULL;
383         }
384
385         if( ! sc->hash_fn ) {
386                 if( text ) *text = "scheme provided no hash function";
387                 return NULL;
388         }
389
390         if( text ) *text = NULL;
391
392         return (sc->hash_fn)( &sc->name, passwd, text );
393 }
394
395 /* pw_string is only called when SLAPD_LMHASH or SLAPD_CRYPT is defined */
396 #if defined(SLAPD_LMHASH) || defined(SLAPD_CRYPT)
397 static struct berval * pw_string(
398         const struct berval *sc,
399         const struct berval *passwd )
400 {
401         struct berval *pw = ber_memalloc( sizeof( struct berval ) );
402         if( pw == NULL ) return NULL;
403
404         pw->bv_len = sc->bv_len + passwd->bv_len;
405         pw->bv_val = ber_memalloc( pw->bv_len + 1 );
406
407         if( pw->bv_val == NULL ) {
408                 ber_memfree( pw );
409                 return NULL;
410         }
411
412         AC_MEMCPY( pw->bv_val, sc->bv_val, sc->bv_len );
413         AC_MEMCPY( &pw->bv_val[sc->bv_len], passwd->bv_val, passwd->bv_len );
414
415         pw->bv_val[pw->bv_len] = '\0';
416         return pw;
417 }
418 #endif /* SLAPD_LMHASH || SLAPD_CRYPT */
419
420 static struct berval * pw_string64(
421         const struct berval *sc,
422         const struct berval *hash,
423         const struct berval *salt )
424 {
425         int rc;
426         struct berval string;
427         struct berval *b64 = ber_memalloc( sizeof(struct berval) );
428         size_t b64len;
429
430         if( b64 == NULL ) return NULL;
431
432         if( salt ) {
433                 /* need to base64 combined string */
434                 string.bv_len = hash->bv_len + salt->bv_len;
435                 string.bv_val = ber_memalloc( string.bv_len + 1 );
436
437                 if( string.bv_val == NULL ) {
438                         ber_memfree( b64 );
439                         return NULL;
440                 }
441
442                 AC_MEMCPY( string.bv_val, hash->bv_val,
443                         hash->bv_len );
444                 AC_MEMCPY( &string.bv_val[hash->bv_len], salt->bv_val,
445                         salt->bv_len );
446                 string.bv_val[string.bv_len] = '\0';
447
448         } else {
449                 string = *hash;
450         }
451
452         b64len = LUTIL_BASE64_ENCODE_LEN( string.bv_len ) + 1;
453         b64->bv_len = b64len + sc->bv_len;
454         b64->bv_val = ber_memalloc( b64->bv_len + 1 );
455
456         if( b64->bv_val == NULL ) {
457                 if( salt ) ber_memfree( string.bv_val );
458                 ber_memfree( b64 );
459                 return NULL;
460         }
461
462         AC_MEMCPY(b64->bv_val, sc->bv_val, sc->bv_len);
463
464         rc = lutil_b64_ntop(
465                 (unsigned char *) string.bv_val, string.bv_len,
466                 &b64->bv_val[sc->bv_len], b64len );
467
468         if( salt ) ber_memfree( string.bv_val );
469         
470         if( rc < 0 ) {
471                 ber_bvfree( b64 );
472                 return NULL;
473         }
474
475         /* recompute length */
476         b64->bv_len = sc->bv_len + rc;
477         assert( strlen(b64->bv_val) == b64->bv_len );
478         return b64;
479 }
480
481 /* PASSWORD CHECK ROUTINES */
482
483 #ifdef LUTIL_SHA1_BYTES
484 static int chk_ssha1(
485         const struct berval *sc,
486         const struct berval * passwd,
487         const struct berval * cred,
488         const char **text )
489 {
490         lutil_SHA1_CTX SHA1context;
491         unsigned char SHA1digest[LUTIL_SHA1_BYTES];
492         int rc;
493         unsigned char *orig_pass = NULL;
494
495         /* safety check */
496         if (LUTIL_BASE64_DECODE_LEN(passwd->bv_len) <
497                 sizeof(SHA1digest)+SALT_SIZE) {
498                 return -1;
499         }
500
501         /* decode base64 password */
502         orig_pass = (unsigned char *) ber_memalloc( (size_t) (
503                 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
504
505         if( orig_pass == NULL ) return -1;
506
507         rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
508
509         if (rc < (int)(sizeof(SHA1digest)+SALT_SIZE)) {
510                 ber_memfree(orig_pass);
511                 return -1;
512         }
513  
514         /* hash credentials with salt */
515         lutil_SHA1Init(&SHA1context);
516         lutil_SHA1Update(&SHA1context,
517                 (const unsigned char *) cred->bv_val, cred->bv_len);
518         lutil_SHA1Update(&SHA1context,
519                 (const unsigned char *) &orig_pass[sizeof(SHA1digest)],
520                 rc - sizeof(SHA1digest));
521         lutil_SHA1Final(SHA1digest, &SHA1context);
522  
523         /* compare */
524         rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
525         ber_memfree(orig_pass);
526         return rc ? 1 : 0;
527 }
528
529 static int chk_sha1(
530         const struct berval *sc,
531         const struct berval * passwd,
532         const struct berval * cred,
533         const char **text )
534 {
535         lutil_SHA1_CTX SHA1context;
536         unsigned char SHA1digest[LUTIL_SHA1_BYTES];
537         int rc;
538         unsigned char *orig_pass = NULL;
539  
540         /* safety check */
541         if (LUTIL_BASE64_DECODE_LEN(passwd->bv_len) < sizeof(SHA1digest)) {
542                 return -1;
543         }
544
545         /* base64 un-encode password */
546         orig_pass = (unsigned char *) ber_memalloc( (size_t) (
547                 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
548
549         if( orig_pass == NULL ) return -1;
550
551         rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
552
553         if( rc != sizeof(SHA1digest) ) {
554                 ber_memfree(orig_pass);
555                 return -1;
556         }
557  
558         /* hash credentials with salt */
559         lutil_SHA1Init(&SHA1context);
560         lutil_SHA1Update(&SHA1context,
561                 (const unsigned char *) cred->bv_val, cred->bv_len);
562         lutil_SHA1Final(SHA1digest, &SHA1context);
563  
564         /* compare */
565         rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
566         ber_memfree(orig_pass);
567         return rc ? 1 : 0;
568 }
569 #endif
570
571 static int chk_smd5(
572         const struct berval *sc,
573         const struct berval * passwd,
574         const struct berval * cred,
575         const char **text )
576 {
577         lutil_MD5_CTX MD5context;
578         unsigned char MD5digest[LUTIL_MD5_BYTES];
579         int rc;
580         unsigned char *orig_pass = NULL;
581
582         /* safety check */
583         if (LUTIL_BASE64_DECODE_LEN(passwd->bv_len) <
584                 sizeof(MD5digest)+SALT_SIZE) {
585                 return -1;
586         }
587
588         /* base64 un-encode password */
589         orig_pass = (unsigned char *) ber_memalloc( (size_t) (
590                 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
591
592         if( orig_pass == NULL ) return -1;
593
594         rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
595
596         if (rc < (int)(sizeof(MD5digest)+SALT_SIZE)) {
597                 ber_memfree(orig_pass);
598                 return -1;
599         }
600
601         /* hash credentials with salt */
602         lutil_MD5Init(&MD5context);
603         lutil_MD5Update(&MD5context,
604                 (const unsigned char *) cred->bv_val,
605                 cred->bv_len );
606         lutil_MD5Update(&MD5context,
607                 &orig_pass[sizeof(MD5digest)],
608                 rc - sizeof(MD5digest));
609         lutil_MD5Final(MD5digest, &MD5context);
610
611         /* compare */
612         rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
613         ber_memfree(orig_pass);
614         return rc ? 1 : 0;
615 }
616
617 static int chk_md5(
618         const struct berval *sc,
619         const struct berval * passwd,
620         const struct berval * cred,
621         const char **text )
622 {
623         lutil_MD5_CTX MD5context;
624         unsigned char MD5digest[LUTIL_MD5_BYTES];
625         int rc;
626         unsigned char *orig_pass = NULL;
627
628         /* safety check */
629         if (LUTIL_BASE64_DECODE_LEN(passwd->bv_len) < sizeof(MD5digest)) {
630                 return -1;
631         }
632
633         /* base64 un-encode password */
634         orig_pass = (unsigned char *) ber_memalloc( (size_t) (
635                 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
636
637         if( orig_pass == NULL ) return -1;
638
639         rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
640         if ( rc != sizeof(MD5digest) ) {
641                 ber_memfree(orig_pass);
642                 return -1;
643         }
644
645         /* hash credentials with salt */
646         lutil_MD5Init(&MD5context);
647         lutil_MD5Update(&MD5context,
648                 (const unsigned char *) cred->bv_val,
649                 cred->bv_len );
650         lutil_MD5Final(MD5digest, &MD5context);
651
652         /* compare */
653         rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
654         ber_memfree(orig_pass);
655         return rc ? 1 : 0;
656 }
657
658 #ifdef SLAPD_LMHASH
659 /* pseudocode from RFC2433
660  * A.2 LmPasswordHash()
661  * 
662  *    LmPasswordHash(
663  *    IN  0-to-14-oem-char Password,
664  *    OUT 16-octet         PasswordHash )
665  *    {
666  *       Set UcasePassword to the uppercased Password
667  *       Zero pad UcasePassword to 14 characters
668  * 
669  *       DesHash( 1st 7-octets of UcasePassword,
670  *                giving 1st 8-octets of PasswordHash )
671  * 
672  *       DesHash( 2nd 7-octets of UcasePassword,
673  *                giving 2nd 8-octets of PasswordHash )
674  *    }
675  * 
676  * 
677  * A.3 DesHash()
678  * 
679  *    DesHash(
680  *    IN  7-octet Clear,
681  *    OUT 8-octet Cypher )
682  *    {
683  *        *
684  *        * Make Cypher an irreversibly encrypted form of Clear by
685  *        * encrypting known text using Clear as the secret key.
686  *        * The known text consists of the string
687  *        *
688  *        *              KGS!@#$%
689  *        *
690  * 
691  *       Set StdText to "KGS!@#$%"
692  *       DesEncrypt( StdText, Clear, giving Cypher )
693  *    }
694  * 
695  * 
696  * A.4 DesEncrypt()
697  * 
698  *    DesEncrypt(
699  *    IN  8-octet Clear,
700  *    IN  7-octet Key,
701  *    OUT 8-octet Cypher )
702  *    {
703  *        *
704  *        * Use the DES encryption algorithm [4] in ECB mode [9]
705  *        * to encrypt Clear into Cypher such that Cypher can
706  *        * only be decrypted back to Clear by providing Key.
707  *        * Note that the DES algorithm takes as input a 64-bit
708  *        * stream where the 8th, 16th, 24th, etc.  bits are
709  *        * parity bits ignored by the encrypting algorithm.
710  *        * Unless you write your own DES to accept 56-bit input
711  *        * without parity, you will need to insert the parity bits
712  *        * yourself.
713  *        *
714  *    }
715  */
716
717 static void lmPasswd_to_key(
718         const unsigned char *lmPasswd,
719         des_cblock *key)
720 {
721         /* make room for parity bits */
722         ((char *)key)[0] = lmPasswd[0];
723         ((char *)key)[1] = ((lmPasswd[0]&0x01)<<7) | (lmPasswd[1]>>1);
724         ((char *)key)[2] = ((lmPasswd[1]&0x03)<<6) | (lmPasswd[2]>>2);
725         ((char *)key)[3] = ((lmPasswd[2]&0x07)<<5) | (lmPasswd[3]>>3);
726         ((char *)key)[4] = ((lmPasswd[3]&0x0F)<<4) | (lmPasswd[4]>>4);
727         ((char *)key)[5] = ((lmPasswd[4]&0x1F)<<3) | (lmPasswd[5]>>5);
728         ((char *)key)[6] = ((lmPasswd[5]&0x3F)<<2) | (lmPasswd[6]>>6);
729         ((char *)key)[7] = ((lmPasswd[6]&0x7F)<<1);
730                 
731         des_set_odd_parity( key );
732 }       
733
734 static int chk_lanman(
735         const struct berval *scheme,
736         const struct berval *passwd,
737         const struct berval *cred,
738         const char **text )
739 {
740         int i;
741         char UcasePassword[15];
742         des_cblock key;
743         des_key_schedule schedule;
744         des_cblock StdText = "KGS!@#$%";
745         des_cblock PasswordHash1, PasswordHash2;
746         char PasswordHash[33], storedPasswordHash[33];
747         
748         for( i=0; i<cred->bv_len; i++) {
749                 if(cred->bv_val[i] == '\0') {
750                         return -1;      /* NUL character in password */
751                 }
752         }
753         
754         if( cred->bv_val[i] != '\0' ) {
755                 return -1;      /* passwd must behave like a string */
756         }
757         
758         strncpy( UcasePassword, cred->bv_val, 14 );
759         UcasePassword[14] = '\0';
760         ldap_pvt_str2upper( UcasePassword );
761         
762         lmPasswd_to_key( UcasePassword, &key );
763         des_set_key_unchecked( &key, schedule );
764         des_ecb_encrypt( &StdText, &PasswordHash1, schedule , DES_ENCRYPT );
765         
766         lmPasswd_to_key( &UcasePassword[7], &key );
767         des_set_key_unchecked( &key, schedule );
768         des_ecb_encrypt( &StdText, &PasswordHash2, schedule , DES_ENCRYPT );
769         
770         sprintf( PasswordHash, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 
771                 PasswordHash1[0],PasswordHash1[1],PasswordHash1[2],PasswordHash1[3],
772                 PasswordHash1[4],PasswordHash1[5],PasswordHash1[6],PasswordHash1[7],
773                 PasswordHash2[0],PasswordHash2[1],PasswordHash2[2],PasswordHash2[3],
774                 PasswordHash2[4],PasswordHash2[5],PasswordHash2[6],PasswordHash2[7] );
775         
776         /* as a precaution convert stored password hash to lower case */
777         strncpy( storedPasswordHash, passwd->bv_val, 32 );
778         storedPasswordHash[32] = '\0';
779         ldap_pvt_str2lower( storedPasswordHash );
780         
781         return memcmp( PasswordHash, storedPasswordHash, 32) ? 1 : 0;
782 }
783 #endif /* SLAPD_LMHASH */
784
785 #ifdef SLAPD_NS_MTA_MD5
786 static int chk_ns_mta_md5(
787         const struct berval *scheme,
788         const struct berval *passwd,
789         const struct berval *cred,
790         const char **text )
791 {
792         lutil_MD5_CTX MD5context;
793         unsigned char MD5digest[LUTIL_MD5_BYTES], c;
794         char buffer[LUTIL_MD5_BYTES*2];
795         int i;
796
797         if( passwd->bv_len != LUTIL_MD5_BYTES*2 ) {
798                 return 1;
799         }
800
801         /* hash credentials with salt */
802         lutil_MD5Init(&MD5context);
803         lutil_MD5Update(&MD5context,
804                 (const unsigned char *) &passwd->bv_val[32],
805                 32 );
806
807         c = 0x59;
808         lutil_MD5Update(&MD5context,
809                 (const unsigned char *) &c,
810                 1 );
811
812         lutil_MD5Update(&MD5context,
813                 (const unsigned char *) cred->bv_val,
814                 cred->bv_len );
815
816         c = 0xF7;
817         lutil_MD5Update(&MD5context,
818                 (const unsigned char *) &c,
819                 1 );
820
821         lutil_MD5Update(&MD5context,
822                 (const unsigned char *) &passwd->bv_val[32],
823                 32 );
824
825         lutil_MD5Final(MD5digest, &MD5context);
826
827         for( i=0; i < sizeof( MD5digest ); i++ ) {
828                 buffer[i+i]   = "0123456789abcdef"[(MD5digest[i]>>4) & 0x0F]; 
829                 buffer[i+i+1] = "0123456789abcdef"[ MD5digest[i] & 0x0F]; 
830         }
831
832         /* compare */
833         return memcmp((char *)passwd->bv_val,
834                 (char *)buffer, sizeof(buffer)) ? 1 : 0;
835 }
836 #endif
837
838 #ifdef SLAPD_SPASSWD
839 #ifdef HAVE_CYRUS_SASL
840 sasl_conn_t *lutil_passwd_sasl_conn = NULL;
841 #endif
842
843 static int chk_sasl(
844         const struct berval *sc,
845         const struct berval * passwd,
846         const struct berval * cred,
847         const char **text )
848 {
849         unsigned int i;
850         int rtn;
851
852         for( i=0; i<cred->bv_len; i++) {
853                 if(cred->bv_val[i] == '\0') {
854                         return 1;       /* NUL character in password */
855                 }
856         }
857
858         if( cred->bv_val[i] != '\0' ) {
859                 return 1;       /* cred must behave like a string */
860         }
861
862         for( i=0; i<passwd->bv_len; i++) {
863                 if(passwd->bv_val[i] == '\0') {
864                         return 1;       /* NUL character in password */
865                 }
866         }
867
868         if( passwd->bv_val[i] != '\0' ) {
869                 return 1;       /* passwd must behave like a string */
870         }
871
872         rtn = 1;
873
874 #ifdef HAVE_CYRUS_SASL
875         if( lutil_passwd_sasl_conn != NULL ) {
876                 int sc;
877 # if SASL_VERSION_MAJOR < 2
878                 sc = sasl_checkpass( lutil_passwd_sasl_conn,
879                         passwd->bv_val, passwd->bv_len,
880                         cred->bv_val, cred->bv_len,
881                         text );
882 # else
883                 sc = sasl_checkpass( lutil_passwd_sasl_conn,
884                         passwd->bv_val, passwd->bv_len,
885                         cred->bv_val, cred->bv_len );
886 # endif
887                 rtn = ( sc != SASL_OK );
888         }
889 #endif
890
891         return rtn;
892 }
893 #endif
894
895 #ifdef SLAPD_KPASSWD
896 static int chk_kerberos(
897         const struct berval *sc,
898         const struct berval * passwd,
899         const struct berval * cred,
900         const char **text )
901 {
902         unsigned int i;
903         int rtn;
904
905         for( i=0; i<cred->bv_len; i++) {
906                 if(cred->bv_val[i] == '\0') {
907                         return 1;       /* NUL character in password */
908                 }
909         }
910
911         if( cred->bv_val[i] != '\0' ) {
912                 return 1;       /* cred must behave like a string */
913         }
914
915         for( i=0; i<passwd->bv_len; i++) {
916                 if(passwd->bv_val[i] == '\0') {
917                         return 1;       /* NUL character in password */
918                 }
919         }
920
921         if( passwd->bv_val[i] != '\0' ) {
922                 return 1;       /* passwd must behave like a string */
923         }
924
925         rtn = 1;
926
927 #ifdef HAVE_KRB5 /* HAVE_HEIMDAL_KRB5 */
928         {
929 /* Portions:
930  * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H\xf6gskolan
931  * (Royal Institute of Technology, Stockholm, Sweden).
932  * All rights reserved.
933  *
934  * Redistribution and use in source and binary forms, with or without
935  * modification, are permitted provided that the following conditions
936  * are met:
937  *
938  * 1. Redistributions of source code must retain the above copyright
939  *    notice, this list of conditions and the following disclaimer.
940  *
941  * 2. Redistributions in binary form must reproduce the above copyright
942  *    notice, this list of conditions and the following disclaimer in the
943  *    documentation and/or other materials provided with the distribution.
944  *
945  * 3. Neither the name of the Institute nor the names of its contributors
946  *    may be used to endorse or promote products derived from this software
947  *    without specific prior written permission.
948  *
949  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
950  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
951  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
952  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
953  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
954  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
955  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
956  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
957  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
958  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
959  * SUCH DAMAGE.
960  */
961
962                 krb5_context context;
963                 krb5_error_code ret;
964                 krb5_creds creds;
965                 krb5_get_init_creds_opt get_options;
966                 krb5_verify_init_creds_opt verify_options;
967                 krb5_principal client, server;
968 #ifdef notdef
969                 krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP};
970 #endif
971
972                 ret = krb5_init_context( &context );
973                 if (ret) {
974                         return 1;
975                 }
976
977 #ifdef notdef
978                 krb5_get_init_creds_opt_set_preauth_list(&get_options,
979                         pre_auth_types, 1);
980 #endif
981
982                 krb5_get_init_creds_opt_init( &get_options );
983
984                 krb5_verify_init_creds_opt_init( &verify_options );
985         
986                 ret = krb5_parse_name( context, passwd->bv_val, &client );
987
988                 if (ret) {
989                         krb5_free_context( context );
990                         return 1;
991                 }
992
993                 ret = krb5_get_init_creds_password( context,
994                         &creds, client, cred->bv_val, NULL,
995                         NULL, 0, NULL, &get_options );
996
997                 if (ret) {
998                         krb5_free_principal( context, client );
999                         krb5_free_context( context );
1000                         return 1;
1001                 }
1002
1003                 {
1004                         char *host = ldap_pvt_get_fqdn( NULL );
1005
1006                         if( host == NULL ) {
1007                                 krb5_free_principal( context, client );
1008                                 krb5_free_context( context );
1009                                 return 1;
1010                         }
1011
1012                         ret = krb5_sname_to_principal( context,
1013                                 host, "ldap", KRB5_NT_SRV_HST, &server );
1014
1015                         ber_memfree( host );
1016                 }
1017
1018                 if (ret) {
1019                         krb5_free_principal( context, client );
1020                         krb5_free_context( context );
1021                         return 1;
1022                 }
1023
1024                 ret = krb5_verify_init_creds( context,
1025                         &creds, server, NULL, NULL, &verify_options );
1026
1027                 krb5_free_principal( context, client );
1028                 krb5_free_principal( context, server );
1029                 krb5_free_cred_contents( context, &creds );
1030                 krb5_free_context( context );
1031
1032                 rtn = !!ret;
1033         }
1034 #elif   defined(HAVE_KRB4)
1035         {
1036                 /* Borrowed from Heimdal kpopper */
1037 /* Portions:
1038  * Copyright (c) 1989 Regents of the University of California.
1039  * All rights reserved.  The Berkeley software License Agreement
1040  * specifies the terms and conditions for redistribution.
1041  */
1042
1043                 int status;
1044                 char lrealm[REALM_SZ];
1045                 char tkt[MAXHOSTNAMELEN];
1046
1047                 status = krb_get_lrealm(lrealm,1);
1048                 if (status == KFAILURE) {
1049                         return 1;
1050                 }
1051
1052                 snprintf(tkt, sizeof(tkt), "%s_slapd.%u",
1053                         TKT_ROOT, (unsigned)getpid());
1054                 krb_set_tkt_string (tkt);
1055
1056                 status = krb_verify_user( passwd->bv_val, "", lrealm,
1057                         cred->bv_val, 1, "ldap");
1058
1059                 dest_tkt(); /* no point in keeping the tickets */
1060
1061                 return status == KFAILURE;
1062         }
1063 #endif
1064
1065         return rtn;
1066 }
1067 #endif /* SLAPD_KPASSWD */
1068
1069 #ifdef SLAPD_CRYPT
1070 static int chk_crypt(
1071         const struct berval *sc,
1072         const struct berval * passwd,
1073         const struct berval * cred,
1074         const char **text )
1075 {
1076         char *cr;
1077         unsigned int i;
1078
1079         for( i=0; i<cred->bv_len; i++) {
1080                 if(cred->bv_val[i] == '\0') {
1081                         return 1;       /* NUL character in password */
1082                 }
1083         }
1084
1085         if( cred->bv_val[i] != '\0' ) {
1086                 return -1;      /* cred must behave like a string */
1087         }
1088
1089         if( passwd->bv_len < 2 ) {
1090                 return -1;      /* passwd must be at least two characters long */
1091         }
1092
1093         for( i=0; i<passwd->bv_len; i++) {
1094                 if(passwd->bv_val[i] == '\0') {
1095                         return -1;      /* NUL character in password */
1096                 }
1097         }
1098
1099         if( passwd->bv_val[i] != '\0' ) {
1100                 return -1;      /* passwd must behave like a string */
1101         }
1102
1103         cr = crypt( cred->bv_val, passwd->bv_val );
1104
1105         if( cr == NULL || cr[0] == '\0' ) {
1106                 /* salt must have been invalid */
1107                 return -1;
1108         }
1109
1110         return strcmp( passwd->bv_val, cr ) ? 1 : 0;
1111 }
1112
1113 # if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD )
1114 static int chk_unix(
1115         const struct berval *sc,
1116         const struct berval * passwd,
1117         const struct berval * cred,
1118         const char **text )
1119 {
1120         unsigned int i;
1121         char *pw,*cr;
1122
1123         for( i=0; i<cred->bv_len; i++) {
1124                 if(cred->bv_val[i] == '\0') {
1125                         return -1;      /* NUL character in password */
1126                 }
1127         }
1128         if( cred->bv_val[i] != '\0' ) {
1129                 return -1;      /* cred must behave like a string */
1130         }
1131
1132         for( i=0; i<passwd->bv_len; i++) {
1133                 if(passwd->bv_val[i] == '\0') {
1134                         return -1;      /* NUL character in password */
1135                 }
1136         }
1137
1138         if( passwd->bv_val[i] != '\0' ) {
1139                 return -1;      /* passwd must behave like a string */
1140         }
1141
1142         {
1143                 struct passwd *pwd = getpwnam(passwd->bv_val);
1144
1145                 if(pwd == NULL) {
1146                         return -1;      /* not found */
1147                 }
1148
1149                 pw = pwd->pw_passwd;
1150         }
1151 #  ifdef HAVE_GETSPNAM
1152         {
1153                 struct spwd *spwd = getspnam(passwd->bv_val);
1154
1155                 if(spwd != NULL) {
1156                         pw = spwd->sp_pwdp;
1157                 }
1158         }
1159 #  endif
1160 #  ifdef HAVE_AIX_SECURITY
1161         {
1162                 struct userpw *upw = getuserpw(passwd->bv_val);
1163
1164                 if (upw != NULL) {
1165                         pw = upw->upw_passwd;
1166                 }
1167         }
1168 #  endif
1169
1170         if( pw == NULL || pw[0] == '\0' || pw[1] == '\0' ) {
1171                 /* password must must be at least two characters long */
1172                 return -1;
1173         }
1174
1175         cr = crypt(cred->bv_val, pw);
1176
1177         if( cr == NULL || cr[0] == '\0' ) {
1178                 /* salt must have been invalid */
1179                 return -1;
1180         }
1181
1182         return strcmp(pw, cr) ? 1 : 0;
1183
1184 }
1185 # endif
1186 #endif
1187
1188 /* PASSWORD GENERATION ROUTINES */
1189
1190 #ifdef LUTIL_SHA1_BYTES
1191 static struct berval *hash_ssha1(
1192         const struct berval *scheme,
1193         const struct berval  *passwd,
1194         const char **text )
1195 {
1196         lutil_SHA1_CTX  SHA1context;
1197         unsigned char   SHA1digest[LUTIL_SHA1_BYTES];
1198         char            saltdata[SALT_SIZE];
1199         struct berval digest;
1200         struct berval salt;
1201
1202         digest.bv_val = (char *) SHA1digest;
1203         digest.bv_len = sizeof(SHA1digest);
1204         salt.bv_val = saltdata;
1205         salt.bv_len = sizeof(saltdata);
1206
1207         if( lutil_entropy( (unsigned char *) salt.bv_val, salt.bv_len) < 0 ) {
1208                 return NULL; 
1209         }
1210
1211         lutil_SHA1Init( &SHA1context );
1212         lutil_SHA1Update( &SHA1context,
1213                 (const unsigned char *)passwd->bv_val, passwd->bv_len );
1214         lutil_SHA1Update( &SHA1context,
1215                 (const unsigned char *)salt.bv_val, salt.bv_len );
1216         lutil_SHA1Final( SHA1digest, &SHA1context );
1217
1218         return pw_string64( scheme, &digest, &salt);
1219 }
1220
1221 static struct berval *hash_sha1(
1222         const struct berval *scheme,
1223         const struct berval  *passwd,
1224         const char **text )
1225 {
1226         lutil_SHA1_CTX  SHA1context;
1227         unsigned char   SHA1digest[LUTIL_SHA1_BYTES];
1228         struct berval digest;
1229         digest.bv_val = (char *) SHA1digest;
1230         digest.bv_len = sizeof(SHA1digest);
1231      
1232         lutil_SHA1Init( &SHA1context );
1233         lutil_SHA1Update( &SHA1context,
1234                 (const unsigned char *)passwd->bv_val, passwd->bv_len );
1235         lutil_SHA1Final( SHA1digest, &SHA1context );
1236             
1237         return pw_string64( scheme, &digest, NULL);
1238 }
1239 #endif
1240
1241 static struct berval *hash_smd5(
1242         const struct berval *scheme,
1243         const struct berval  *passwd,
1244         const char **text )
1245 {
1246         lutil_MD5_CTX   MD5context;
1247         unsigned char   MD5digest[LUTIL_MD5_BYTES];
1248         char            saltdata[SALT_SIZE];
1249         struct berval digest;
1250         struct berval salt;
1251
1252         digest.bv_val = (char *) MD5digest;
1253         digest.bv_len = sizeof(MD5digest);
1254         salt.bv_val = saltdata;
1255         salt.bv_len = sizeof(saltdata);
1256
1257         if( lutil_entropy( (unsigned char *) salt.bv_val, salt.bv_len) < 0 ) {
1258                 return NULL; 
1259         }
1260
1261         lutil_MD5Init( &MD5context );
1262         lutil_MD5Update( &MD5context,
1263                 (const unsigned char *) passwd->bv_val, passwd->bv_len );
1264         lutil_MD5Update( &MD5context,
1265                 (const unsigned char *) salt.bv_val, salt.bv_len );
1266         lutil_MD5Final( MD5digest, &MD5context );
1267
1268         return pw_string64( scheme, &digest, &salt );
1269 }
1270
1271 static struct berval *hash_md5(
1272         const struct berval *scheme,
1273         const struct berval  *passwd,
1274         const char **text )
1275 {
1276         lutil_MD5_CTX   MD5context;
1277         unsigned char   MD5digest[LUTIL_MD5_BYTES];
1278
1279         struct berval digest;
1280
1281         digest.bv_val = (char *) MD5digest;
1282         digest.bv_len = sizeof(MD5digest);
1283
1284         lutil_MD5Init( &MD5context );
1285         lutil_MD5Update( &MD5context,
1286                 (const unsigned char *) passwd->bv_val, passwd->bv_len );
1287         lutil_MD5Final( MD5digest, &MD5context );
1288
1289         return pw_string64( scheme, &digest, NULL );
1290 ;
1291 }
1292
1293 #ifdef SLAPD_LMHASH 
1294 static struct berval *hash_lanman(
1295         const struct berval *scheme,
1296         const struct berval *passwd,
1297         const char **text )
1298 {
1299
1300         int i;
1301         char UcasePassword[15];
1302         des_cblock key;
1303         des_key_schedule schedule;
1304         des_cblock StdText = "KGS!@#$%";
1305         des_cblock PasswordHash1, PasswordHash2;
1306         char PasswordHash[33];
1307         struct berval hash;
1308         
1309         for( i=0; i<passwd->bv_len; i++) {
1310                 if(passwd->bv_val[i] == '\0') {
1311                         return NULL;    /* NUL character in password */
1312                 }
1313         }
1314         
1315         if( passwd->bv_val[i] != '\0' ) {
1316                 return NULL;    /* passwd must behave like a string */
1317         }
1318         
1319         strncpy( UcasePassword, passwd->bv_val, 14 );
1320         UcasePassword[14] = '\0';
1321         ldap_pvt_str2upper( UcasePassword );
1322         
1323         lmPasswd_to_key( UcasePassword, &key );
1324         des_set_key_unchecked( &key, schedule );
1325         des_ecb_encrypt( &StdText, &PasswordHash1, schedule , DES_ENCRYPT );
1326         
1327         lmPasswd_to_key( &UcasePassword[7], &key );
1328         des_set_key_unchecked( &key, schedule );
1329         des_ecb_encrypt( &StdText, &PasswordHash2, schedule , DES_ENCRYPT );
1330         
1331         sprintf( PasswordHash, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 
1332                 PasswordHash1[0],PasswordHash1[1],PasswordHash1[2],PasswordHash1[3],
1333                 PasswordHash1[4],PasswordHash1[5],PasswordHash1[6],PasswordHash1[7],
1334                 PasswordHash2[0],PasswordHash2[1],PasswordHash2[2],PasswordHash2[3],
1335                 PasswordHash2[4],PasswordHash2[5],PasswordHash2[6],PasswordHash2[7] );
1336         
1337         hash.bv_val = PasswordHash;
1338         hash.bv_len = 32;
1339         
1340         return pw_string( scheme, &hash );
1341 }
1342 #endif /* SLAPD_LMHASH */
1343
1344 #ifdef SLAPD_CRYPT
1345 static struct berval *hash_crypt(
1346         const struct berval *scheme,
1347         const struct berval *passwd,
1348         const char **text )
1349 {
1350         struct berval hash;
1351         unsigned char salt[32]; /* salt suitable for most anything */
1352         unsigned int i;
1353
1354         for( i=0; i<passwd->bv_len; i++) {
1355                 if(passwd->bv_val[i] == '\0') {
1356                         return NULL;    /* NUL character in password */
1357                 }
1358         }
1359
1360         if( passwd->bv_val[i] != '\0' ) {
1361                 return NULL;    /* passwd must behave like a string */
1362         }
1363
1364         if( lutil_entropy( salt, sizeof( salt ) ) < 0 ) {
1365                 return NULL; 
1366         }
1367
1368         for( i=0; i< ( sizeof(salt) - 1 ); i++ ) {
1369                 salt[i] = crypt64[ salt[i] % (sizeof(crypt64)-1) ];
1370         }
1371         salt[sizeof( salt ) - 1 ] = '\0';
1372
1373         if( salt_format != NULL ) {
1374                 /* copy the salt we made into entropy before snprintfing
1375                    it back into the salt */
1376                 char entropy[sizeof(salt)];
1377                 strcpy( entropy, (char *) salt );
1378                 snprintf( (char *) salt, sizeof(entropy), salt_format, entropy );
1379         }
1380
1381         hash.bv_val = crypt( passwd->bv_val, (char *) salt );
1382
1383         if( hash.bv_val == NULL ) return NULL;
1384
1385         hash.bv_len = strlen( hash.bv_val );
1386
1387         if( hash.bv_len == 0 ) {
1388                 return NULL;
1389         }
1390
1391         return pw_string( scheme, &hash );
1392 }
1393 #endif
1394
1395 int lutil_salt_format(const char *format)
1396 {
1397 #ifdef SLAPD_CRYPT
1398         free( salt_format );
1399
1400         salt_format = format != NULL ? strdup( format ) : NULL;
1401 #endif
1402
1403         return 0;
1404 }
1405
1406 #ifdef SLAPD_CLEARTEXT
1407 static struct berval *hash_clear(
1408         const struct berval *scheme,
1409         const struct berval  *passwd,
1410         const char **text )
1411 {
1412         return ber_bvdup( (struct berval *) passwd );
1413 }
1414 #endif
1415