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