]> git.sur5r.net Git - openldap/blob - libraries/liblutil/passwd.c
8e727a4111bc91c2e85caf255cedbe7273e27c41
[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 #if defined(SLAPD_LMHASH)
45 #       include <openssl/des.h>
46 #endif /* SLAPD_LMHASH */
47
48 #include <ac/param.h>
49
50 #ifdef SLAPD_CRYPT
51 # include <ac/crypt.h>
52
53 # if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD )
54 #  ifdef HAVE_SHADOW_H
55 #       include <shadow.h>
56 #  endif
57 #  ifdef HAVE_PWD_H
58 #       include <pwd.h>
59 #  endif
60 #  ifdef HAVE_AIX_SECURITY
61 #       include <userpw.h>
62 #  endif
63 # endif
64 #endif
65
66 #include <lber.h>
67
68 #include "ldap_pvt.h"
69 #include "lber_pvt.h"
70
71 #include "lutil_md5.h"
72 #include "lutil_sha1.h"
73 #include "lutil.h"
74
75 static const unsigned char crypt64[] =
76         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
77
78 #ifdef SLAPD_CRYPT
79 static char *salt_format = NULL;
80 #endif
81
82 struct pw_scheme {
83         struct berval name;
84         LUTIL_PASSWD_CHK_FUNC *chk_fn;
85         LUTIL_PASSWD_HASH_FUNC *hash_fn;
86 };
87
88 struct pw_slist {
89         struct pw_slist *next;
90         struct pw_scheme s;
91 };
92
93 /* password check routines */
94
95 #define SALT_SIZE       4
96
97 static LUTIL_PASSWD_CHK_FUNC chk_md5;
98 static LUTIL_PASSWD_CHK_FUNC chk_smd5;
99 static LUTIL_PASSWD_HASH_FUNC hash_smd5;
100 static LUTIL_PASSWD_HASH_FUNC hash_md5;
101
102
103 #ifdef LUTIL_SHA1_BYTES
104 static LUTIL_PASSWD_CHK_FUNC chk_ssha1;
105 static LUTIL_PASSWD_CHK_FUNC chk_sha1;
106 static LUTIL_PASSWD_HASH_FUNC hash_sha1;
107 static LUTIL_PASSWD_HASH_FUNC hash_ssha1;
108 #endif
109
110 #ifdef SLAPD_LMHASH
111 static LUTIL_PASSWD_CHK_FUNC chk_lanman;
112 static LUTIL_PASSWD_HASH_FUNC hash_lanman;
113 #endif
114
115 #ifdef SLAPD_SPASSWD
116 static LUTIL_PASSWD_CHK_FUNC chk_sasl;
117 #endif
118
119 #ifdef SLAPD_CRYPT
120 static LUTIL_PASSWD_CHK_FUNC chk_crypt;
121 static LUTIL_PASSWD_HASH_FUNC hash_crypt;
122
123 #if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD )
124 static LUTIL_PASSWD_CHK_FUNC chk_unix;
125 #endif
126 #endif
127
128 /* password hash routines */
129
130 #ifdef SLAPD_CLEARTEXT
131 static LUTIL_PASSWD_HASH_FUNC hash_clear;
132 #endif
133
134 static struct pw_slist *pw_schemes;
135
136 static const struct pw_scheme pw_schemes_default[] =
137 {
138 #ifdef LUTIL_SHA1_BYTES
139         { BER_BVC("{SSHA}"),            chk_ssha1, hash_ssha1 },
140         { BER_BVC("{SHA}"),                     chk_sha1, hash_sha1 },
141 #endif
142
143         { BER_BVC("{SMD5}"),            chk_smd5, hash_smd5 },
144         { BER_BVC("{MD5}"),                     chk_md5, hash_md5 },
145
146 #ifdef SLAPD_LMHASH
147         { BER_BVC("{LANMAN}"),          chk_lanman, hash_lanman },
148 #endif /* SLAPD_LMHASH */
149
150 #ifdef SLAPD_SPASSWD
151         { BER_BVC("{SASL}"),            chk_sasl, NULL },
152 #endif
153
154 #ifdef SLAPD_CRYPT
155         { BER_BVC("{CRYPT}"),           chk_crypt, hash_crypt },
156 # if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD )
157         { BER_BVC("{UNIX}"),            chk_unix, NULL },
158 # endif
159 #endif
160
161 #ifdef SLAPD_CLEARTEXT
162         /* pseudo scheme */
163         { {0, "{CLEARTEXT}"},           NULL, hash_clear },
164 #endif
165
166         { BER_BVNULL, NULL, NULL }
167 };
168
169 int lutil_passwd_add(
170         struct berval *scheme,
171         LUTIL_PASSWD_CHK_FUNC *chk,
172         LUTIL_PASSWD_HASH_FUNC *hash )
173 {
174         struct pw_slist *ptr;
175
176         ptr = ber_memalloc( sizeof( struct pw_slist ));
177         if (!ptr) return -1;
178         ptr->next = pw_schemes;
179         ptr->s.name = *scheme;
180         ptr->s.chk_fn = chk;
181         ptr->s.hash_fn = hash;
182         pw_schemes = ptr;
183         return 0;
184 }
185
186 void lutil_passwd_init()
187 {
188         struct pw_slist *ptr;
189         struct pw_scheme *s;
190
191         for( s=(struct pw_scheme *)pw_schemes_default; s->name.bv_val; s++) {
192                 if ( lutil_passwd_add( &s->name, s->chk_fn, s->hash_fn )) break;
193         }
194 }
195
196 void lutil_passwd_destroy()
197 {
198         struct pw_slist *ptr, *next;
199
200         for( ptr=pw_schemes; ptr; ptr=next ) {
201                 next = ptr->next;
202                 ber_memfree( ptr );
203         }
204 }
205
206 static const struct pw_scheme *get_scheme(
207         const char* scheme )
208 {
209         struct pw_slist *pws;
210
211         if (!pw_schemes) lutil_passwd_init();
212
213         for( pws=pw_schemes; pws; pws=pws->next ) {
214                 if( strcasecmp(scheme, pws->s.name.bv_val ) == 0 ) {
215                         return &(pws->s);
216                 }
217         }
218
219         return NULL;
220 }
221
222 int lutil_passwd_scheme(
223         const char* scheme )
224 {
225         if( scheme == NULL ) {
226                 return 0;
227         }
228
229         return get_scheme(scheme) != NULL;
230 }
231
232
233 static int is_allowed_scheme( 
234         const char* scheme,
235         const char** schemes )
236 {
237         int i;
238
239         if( schemes == NULL ) return 1;
240
241         for( i=0; schemes[i] != NULL; i++ ) {
242                 if( strcasecmp( scheme, schemes[i] ) == 0 ) {
243                         return 1;
244                 }
245         }
246         return 0;
247 }
248
249 static struct berval *passwd_scheme(
250         const struct pw_scheme *scheme,
251         const struct berval * passwd,
252         struct berval *bv,
253         const char** allowed )
254 {
255         if( !is_allowed_scheme( scheme->name.bv_val, allowed ) ) {
256                 return NULL;
257         }
258
259         if( passwd->bv_len >= scheme->name.bv_len ) {
260                 if( strncasecmp( passwd->bv_val, scheme->name.bv_val, scheme->name.bv_len ) == 0 ) {
261                         bv->bv_val = &passwd->bv_val[scheme->name.bv_len];
262                         bv->bv_len = passwd->bv_len - scheme->name.bv_len;
263
264                         return bv;
265                 }
266         }
267
268         return NULL;
269 }
270
271 /*
272  * Return 0 if creds are good.
273  */
274 int
275 lutil_passwd(
276         const struct berval *passwd,    /* stored passwd */
277         const struct berval *cred,              /* user cred */
278         const char **schemes,
279         const char **text )
280 {
281         struct pw_slist *pws;
282
283         if ( text ) *text = NULL;
284
285         if (cred == NULL || cred->bv_len == 0 ||
286                 passwd == NULL || passwd->bv_len == 0 )
287         {
288                 return -1;
289         }
290
291         if (!pw_schemes) lutil_passwd_init();
292
293         for( pws=pw_schemes; pws; pws=pws->next ) {
294                 if( pws->s.chk_fn ) {
295                         struct berval x;
296                         struct berval *p = passwd_scheme( &(pws->s),
297                                 passwd, &x, schemes );
298
299                         if( p != NULL ) {
300                                 return (pws->s.chk_fn)( &(pws->s.name), p, cred, text );
301                         }
302                 }
303         }
304
305 #ifdef SLAPD_CLEARTEXT
306         if( is_allowed_scheme("{CLEARTEXT}", schemes ) ) {
307                 return (( passwd->bv_len == cred->bv_len ) &&
308                                 ( passwd->bv_val[0] != '{' /*'}'*/ ))
309                         ? memcmp( passwd->bv_val, cred->bv_val, passwd->bv_len )
310                         : 1;
311         }
312 #endif
313         return 1;
314 }
315
316 struct berval * lutil_passwd_generate( ber_len_t len )
317 {
318         struct berval *pw;
319
320         if( len < 1 ) return NULL;
321
322         pw = ber_memalloc( sizeof( struct berval ) );
323         if( pw == NULL ) return NULL;
324
325         pw->bv_len = len;
326         pw->bv_val = ber_memalloc( len + 1 );
327
328         if( pw->bv_val == NULL ) {
329                 ber_memfree( pw );
330                 return NULL;
331         }
332
333         if( lutil_entropy( (unsigned char *) pw->bv_val, pw->bv_len) < 0 ) {
334                 ber_bvfree( pw );
335                 return NULL; 
336         }
337
338         for( len = 0; len < pw->bv_len; len++ ) {
339                 pw->bv_val[len] = crypt64[
340                         pw->bv_val[len] % (sizeof(crypt64)-1) ];
341         }
342
343         pw->bv_val[len] = '\0';
344         
345         return pw;
346 }
347
348 struct berval * lutil_passwd_hash(
349         const struct berval * passwd,
350         const char * method,
351         const char **text )
352 {
353         const struct pw_scheme *sc = get_scheme( method );
354
355         if( sc == NULL ) {
356                 if( text ) *text = "scheme not recognized";
357                 return NULL;
358         }
359
360         if( ! sc->hash_fn ) {
361                 if( text ) *text = "scheme provided no hash function";
362                 return NULL;
363         }
364
365         if( text ) *text = NULL;
366
367         return (sc->hash_fn)( &sc->name, passwd, text );
368 }
369
370 /* pw_string is only called when SLAPD_LMHASH or SLAPD_CRYPT is defined */
371 #if defined(SLAPD_LMHASH) || defined(SLAPD_CRYPT)
372 static struct berval * pw_string(
373         const struct berval *sc,
374         const struct berval *passwd )
375 {
376         struct berval *pw = ber_memalloc( sizeof( struct berval ) );
377         if( pw == NULL ) return NULL;
378
379         pw->bv_len = sc->bv_len + passwd->bv_len;
380         pw->bv_val = ber_memalloc( pw->bv_len + 1 );
381
382         if( pw->bv_val == NULL ) {
383                 ber_memfree( pw );
384                 return NULL;
385         }
386
387         AC_MEMCPY( pw->bv_val, sc->bv_val, sc->bv_len );
388         AC_MEMCPY( &pw->bv_val[sc->bv_len], passwd->bv_val, passwd->bv_len );
389
390         pw->bv_val[pw->bv_len] = '\0';
391         return pw;
392 }
393 #endif /* SLAPD_LMHASH || SLAPD_CRYPT */
394
395 static struct berval * pw_string64(
396         const struct berval *sc,
397         const struct berval *hash,
398         const struct berval *salt )
399 {
400         int rc;
401         struct berval string;
402         struct berval *b64 = ber_memalloc( sizeof(struct berval) );
403         size_t b64len;
404
405         if( b64 == NULL ) return NULL;
406
407         if( salt ) {
408                 /* need to base64 combined string */
409                 string.bv_len = hash->bv_len + salt->bv_len;
410                 string.bv_val = ber_memalloc( string.bv_len + 1 );
411
412                 if( string.bv_val == NULL ) {
413                         ber_memfree( b64 );
414                         return NULL;
415                 }
416
417                 AC_MEMCPY( string.bv_val, hash->bv_val,
418                         hash->bv_len );
419                 AC_MEMCPY( &string.bv_val[hash->bv_len], salt->bv_val,
420                         salt->bv_len );
421                 string.bv_val[string.bv_len] = '\0';
422
423         } else {
424                 string = *hash;
425         }
426
427         b64len = LUTIL_BASE64_ENCODE_LEN( string.bv_len ) + 1;
428         b64->bv_len = b64len + sc->bv_len;
429         b64->bv_val = ber_memalloc( b64->bv_len + 1 );
430
431         if( b64->bv_val == NULL ) {
432                 if( salt ) ber_memfree( string.bv_val );
433                 ber_memfree( b64 );
434                 return NULL;
435         }
436
437         AC_MEMCPY(b64->bv_val, sc->bv_val, sc->bv_len);
438
439         rc = lutil_b64_ntop(
440                 (unsigned char *) string.bv_val, string.bv_len,
441                 &b64->bv_val[sc->bv_len], b64len );
442
443         if( salt ) ber_memfree( string.bv_val );
444         
445         if( rc < 0 ) {
446                 ber_bvfree( b64 );
447                 return NULL;
448         }
449
450         /* recompute length */
451         b64->bv_len = sc->bv_len + rc;
452         assert( strlen(b64->bv_val) == b64->bv_len );
453         return b64;
454 }
455
456 /* PASSWORD CHECK ROUTINES */
457
458 #ifdef LUTIL_SHA1_BYTES
459 static int chk_ssha1(
460         const struct berval *sc,
461         const struct berval * passwd,
462         const struct berval * cred,
463         const char **text )
464 {
465         lutil_SHA1_CTX SHA1context;
466         unsigned char SHA1digest[LUTIL_SHA1_BYTES];
467         int rc;
468         unsigned char *orig_pass = NULL;
469
470         /* safety check */
471         if (LUTIL_BASE64_DECODE_LEN(passwd->bv_len) <
472                 sizeof(SHA1digest)+SALT_SIZE) {
473                 return -1;
474         }
475
476         /* decode base64 password */
477         orig_pass = (unsigned char *) ber_memalloc( (size_t) (
478                 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
479
480         if( orig_pass == NULL ) return -1;
481
482         rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
483
484         if (rc < (int)(sizeof(SHA1digest)+SALT_SIZE)) {
485                 ber_memfree(orig_pass);
486                 return -1;
487         }
488  
489         /* hash credentials with salt */
490         lutil_SHA1Init(&SHA1context);
491         lutil_SHA1Update(&SHA1context,
492                 (const unsigned char *) cred->bv_val, cred->bv_len);
493         lutil_SHA1Update(&SHA1context,
494                 (const unsigned char *) &orig_pass[sizeof(SHA1digest)],
495                 rc - sizeof(SHA1digest));
496         lutil_SHA1Final(SHA1digest, &SHA1context);
497  
498         /* compare */
499         rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
500         ber_memfree(orig_pass);
501         return rc ? 1 : 0;
502 }
503
504 static int chk_sha1(
505         const struct berval *sc,
506         const struct berval * passwd,
507         const struct berval * cred,
508         const char **text )
509 {
510         lutil_SHA1_CTX SHA1context;
511         unsigned char SHA1digest[LUTIL_SHA1_BYTES];
512         int rc;
513         unsigned char *orig_pass = NULL;
514  
515         /* safety check */
516         if (LUTIL_BASE64_DECODE_LEN(passwd->bv_len) < sizeof(SHA1digest)) {
517                 return -1;
518         }
519
520         /* base64 un-encode password */
521         orig_pass = (unsigned char *) ber_memalloc( (size_t) (
522                 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
523
524         if( orig_pass == NULL ) return -1;
525
526         rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
527
528         if( rc != sizeof(SHA1digest) ) {
529                 ber_memfree(orig_pass);
530                 return -1;
531         }
532  
533         /* hash credentials with salt */
534         lutil_SHA1Init(&SHA1context);
535         lutil_SHA1Update(&SHA1context,
536                 (const unsigned char *) cred->bv_val, cred->bv_len);
537         lutil_SHA1Final(SHA1digest, &SHA1context);
538  
539         /* compare */
540         rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
541         ber_memfree(orig_pass);
542         return rc ? 1 : 0;
543 }
544 #endif
545
546 static int chk_smd5(
547         const struct berval *sc,
548         const struct berval * passwd,
549         const struct berval * cred,
550         const char **text )
551 {
552         lutil_MD5_CTX MD5context;
553         unsigned char MD5digest[LUTIL_MD5_BYTES];
554         int rc;
555         unsigned char *orig_pass = NULL;
556
557         /* safety check */
558         if (LUTIL_BASE64_DECODE_LEN(passwd->bv_len) <
559                 sizeof(MD5digest)+SALT_SIZE) {
560                 return -1;
561         }
562
563         /* base64 un-encode password */
564         orig_pass = (unsigned char *) ber_memalloc( (size_t) (
565                 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
566
567         if( orig_pass == NULL ) return -1;
568
569         rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
570
571         if (rc < (int)(sizeof(MD5digest)+SALT_SIZE)) {
572                 ber_memfree(orig_pass);
573                 return -1;
574         }
575
576         /* hash credentials with salt */
577         lutil_MD5Init(&MD5context);
578         lutil_MD5Update(&MD5context,
579                 (const unsigned char *) cred->bv_val,
580                 cred->bv_len );
581         lutil_MD5Update(&MD5context,
582                 &orig_pass[sizeof(MD5digest)],
583                 rc - sizeof(MD5digest));
584         lutil_MD5Final(MD5digest, &MD5context);
585
586         /* compare */
587         rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
588         ber_memfree(orig_pass);
589         return rc ? 1 : 0;
590 }
591
592 static int chk_md5(
593         const struct berval *sc,
594         const struct berval * passwd,
595         const struct berval * cred,
596         const char **text )
597 {
598         lutil_MD5_CTX MD5context;
599         unsigned char MD5digest[LUTIL_MD5_BYTES];
600         int rc;
601         unsigned char *orig_pass = NULL;
602
603         /* safety check */
604         if (LUTIL_BASE64_DECODE_LEN(passwd->bv_len) < sizeof(MD5digest)) {
605                 return -1;
606         }
607
608         /* base64 un-encode password */
609         orig_pass = (unsigned char *) ber_memalloc( (size_t) (
610                 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
611
612         if( orig_pass == NULL ) return -1;
613
614         rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
615         if ( rc != sizeof(MD5digest) ) {
616                 ber_memfree(orig_pass);
617                 return -1;
618         }
619
620         /* hash credentials with salt */
621         lutil_MD5Init(&MD5context);
622         lutil_MD5Update(&MD5context,
623                 (const unsigned char *) cred->bv_val,
624                 cred->bv_len );
625         lutil_MD5Final(MD5digest, &MD5context);
626
627         /* compare */
628         rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
629         ber_memfree(orig_pass);
630         return rc ? 1 : 0;
631 }
632
633 #ifdef SLAPD_LMHASH
634 /* pseudocode from RFC2433
635  * A.2 LmPasswordHash()
636  * 
637  *    LmPasswordHash(
638  *    IN  0-to-14-oem-char Password,
639  *    OUT 16-octet         PasswordHash )
640  *    {
641  *       Set UcasePassword to the uppercased Password
642  *       Zero pad UcasePassword to 14 characters
643  * 
644  *       DesHash( 1st 7-octets of UcasePassword,
645  *                giving 1st 8-octets of PasswordHash )
646  * 
647  *       DesHash( 2nd 7-octets of UcasePassword,
648  *                giving 2nd 8-octets of PasswordHash )
649  *    }
650  * 
651  * 
652  * A.3 DesHash()
653  * 
654  *    DesHash(
655  *    IN  7-octet Clear,
656  *    OUT 8-octet Cypher )
657  *    {
658  *        *
659  *        * Make Cypher an irreversibly encrypted form of Clear by
660  *        * encrypting known text using Clear as the secret key.
661  *        * The known text consists of the string
662  *        *
663  *        *              KGS!@#$%
664  *        *
665  * 
666  *       Set StdText to "KGS!@#$%"
667  *       DesEncrypt( StdText, Clear, giving Cypher )
668  *    }
669  * 
670  * 
671  * A.4 DesEncrypt()
672  * 
673  *    DesEncrypt(
674  *    IN  8-octet Clear,
675  *    IN  7-octet Key,
676  *    OUT 8-octet Cypher )
677  *    {
678  *        *
679  *        * Use the DES encryption algorithm [4] in ECB mode [9]
680  *        * to encrypt Clear into Cypher such that Cypher can
681  *        * only be decrypted back to Clear by providing Key.
682  *        * Note that the DES algorithm takes as input a 64-bit
683  *        * stream where the 8th, 16th, 24th, etc.  bits are
684  *        * parity bits ignored by the encrypting algorithm.
685  *        * Unless you write your own DES to accept 56-bit input
686  *        * without parity, you will need to insert the parity bits
687  *        * yourself.
688  *        *
689  *    }
690  */
691
692 static void lmPasswd_to_key(
693         const unsigned char *lmPasswd,
694         des_cblock *key)
695 {
696         /* make room for parity bits */
697         ((char *)key)[0] = lmPasswd[0];
698         ((char *)key)[1] = ((lmPasswd[0]&0x01)<<7) | (lmPasswd[1]>>1);
699         ((char *)key)[2] = ((lmPasswd[1]&0x03)<<6) | (lmPasswd[2]>>2);
700         ((char *)key)[3] = ((lmPasswd[2]&0x07)<<5) | (lmPasswd[3]>>3);
701         ((char *)key)[4] = ((lmPasswd[3]&0x0F)<<4) | (lmPasswd[4]>>4);
702         ((char *)key)[5] = ((lmPasswd[4]&0x1F)<<3) | (lmPasswd[5]>>5);
703         ((char *)key)[6] = ((lmPasswd[5]&0x3F)<<2) | (lmPasswd[6]>>6);
704         ((char *)key)[7] = ((lmPasswd[6]&0x7F)<<1);
705                 
706         des_set_odd_parity( key );
707 }       
708
709 static int chk_lanman(
710         const struct berval *scheme,
711         const struct berval *passwd,
712         const struct berval *cred,
713         const char **text )
714 {
715         int i;
716         char UcasePassword[15];
717         des_cblock key;
718         des_key_schedule schedule;
719         des_cblock StdText = "KGS!@#$%";
720         des_cblock PasswordHash1, PasswordHash2;
721         char PasswordHash[33], storedPasswordHash[33];
722         
723         for( i=0; i<cred->bv_len; i++) {
724                 if(cred->bv_val[i] == '\0') {
725                         return -1;      /* NUL character in password */
726                 }
727         }
728         
729         if( cred->bv_val[i] != '\0' ) {
730                 return -1;      /* passwd must behave like a string */
731         }
732         
733         strncpy( UcasePassword, cred->bv_val, 14 );
734         UcasePassword[14] = '\0';
735         ldap_pvt_str2upper( UcasePassword );
736         
737         lmPasswd_to_key( UcasePassword, &key );
738         des_set_key_unchecked( &key, schedule );
739         des_ecb_encrypt( &StdText, &PasswordHash1, schedule , DES_ENCRYPT );
740         
741         lmPasswd_to_key( &UcasePassword[7], &key );
742         des_set_key_unchecked( &key, schedule );
743         des_ecb_encrypt( &StdText, &PasswordHash2, schedule , DES_ENCRYPT );
744         
745         sprintf( PasswordHash, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 
746                 PasswordHash1[0],PasswordHash1[1],PasswordHash1[2],PasswordHash1[3],
747                 PasswordHash1[4],PasswordHash1[5],PasswordHash1[6],PasswordHash1[7],
748                 PasswordHash2[0],PasswordHash2[1],PasswordHash2[2],PasswordHash2[3],
749                 PasswordHash2[4],PasswordHash2[5],PasswordHash2[6],PasswordHash2[7] );
750         
751         /* as a precaution convert stored password hash to lower case */
752         strncpy( storedPasswordHash, passwd->bv_val, 32 );
753         storedPasswordHash[32] = '\0';
754         ldap_pvt_str2lower( storedPasswordHash );
755         
756         return memcmp( PasswordHash, storedPasswordHash, 32) ? 1 : 0;
757 }
758 #endif /* SLAPD_LMHASH */
759
760 #ifdef SLAPD_SPASSWD
761 #ifdef HAVE_CYRUS_SASL
762 sasl_conn_t *lutil_passwd_sasl_conn = NULL;
763 #endif
764
765 static int chk_sasl(
766         const struct berval *sc,
767         const struct berval * passwd,
768         const struct berval * cred,
769         const char **text )
770 {
771         unsigned int i;
772         int rtn;
773
774         for( i=0; i<cred->bv_len; i++) {
775                 if(cred->bv_val[i] == '\0') {
776                         return 1;       /* NUL character in password */
777                 }
778         }
779
780         if( cred->bv_val[i] != '\0' ) {
781                 return 1;       /* cred must behave like a string */
782         }
783
784         for( i=0; i<passwd->bv_len; i++) {
785                 if(passwd->bv_val[i] == '\0') {
786                         return 1;       /* NUL character in password */
787                 }
788         }
789
790         if( passwd->bv_val[i] != '\0' ) {
791                 return 1;       /* passwd must behave like a string */
792         }
793
794         rtn = 1;
795
796 #ifdef HAVE_CYRUS_SASL
797         if( lutil_passwd_sasl_conn != NULL ) {
798                 int sc;
799 # if SASL_VERSION_MAJOR < 2
800                 sc = sasl_checkpass( lutil_passwd_sasl_conn,
801                         passwd->bv_val, passwd->bv_len,
802                         cred->bv_val, cred->bv_len,
803                         text );
804 # else
805                 sc = sasl_checkpass( lutil_passwd_sasl_conn,
806                         passwd->bv_val, passwd->bv_len,
807                         cred->bv_val, cred->bv_len );
808 # endif
809                 rtn = ( sc != SASL_OK );
810         }
811 #endif
812
813         return rtn;
814 }
815 #endif
816
817 #ifdef SLAPD_CRYPT
818 static int chk_crypt(
819         const struct berval *sc,
820         const struct berval * passwd,
821         const struct berval * cred,
822         const char **text )
823 {
824         char *cr;
825         unsigned int i;
826
827         for( i=0; i<cred->bv_len; i++) {
828                 if(cred->bv_val[i] == '\0') {
829                         return 1;       /* NUL character in password */
830                 }
831         }
832
833         if( cred->bv_val[i] != '\0' ) {
834                 return -1;      /* cred must behave like a string */
835         }
836
837         if( passwd->bv_len < 2 ) {
838                 return -1;      /* passwd must be at least two characters long */
839         }
840
841         for( i=0; i<passwd->bv_len; i++) {
842                 if(passwd->bv_val[i] == '\0') {
843                         return -1;      /* NUL character in password */
844                 }
845         }
846
847         if( passwd->bv_val[i] != '\0' ) {
848                 return -1;      /* passwd must behave like a string */
849         }
850
851         cr = crypt( cred->bv_val, passwd->bv_val );
852
853         if( cr == NULL || cr[0] == '\0' ) {
854                 /* salt must have been invalid */
855                 return -1;
856         }
857
858         return strcmp( passwd->bv_val, cr ) ? 1 : 0;
859 }
860
861 # if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD )
862 static int chk_unix(
863         const struct berval *sc,
864         const struct berval * passwd,
865         const struct berval * cred,
866         const char **text )
867 {
868         unsigned int i;
869         char *pw,*cr;
870
871         for( i=0; i<cred->bv_len; i++) {
872                 if(cred->bv_val[i] == '\0') {
873                         return -1;      /* NUL character in password */
874                 }
875         }
876         if( cred->bv_val[i] != '\0' ) {
877                 return -1;      /* cred must behave like a string */
878         }
879
880         for( i=0; i<passwd->bv_len; i++) {
881                 if(passwd->bv_val[i] == '\0') {
882                         return -1;      /* NUL character in password */
883                 }
884         }
885
886         if( passwd->bv_val[i] != '\0' ) {
887                 return -1;      /* passwd must behave like a string */
888         }
889
890         {
891                 struct passwd *pwd = getpwnam(passwd->bv_val);
892
893                 if(pwd == NULL) {
894                         return -1;      /* not found */
895                 }
896
897                 pw = pwd->pw_passwd;
898         }
899 #  ifdef HAVE_GETSPNAM
900         {
901                 struct spwd *spwd = getspnam(passwd->bv_val);
902
903                 if(spwd != NULL) {
904                         pw = spwd->sp_pwdp;
905                 }
906         }
907 #  endif
908 #  ifdef HAVE_AIX_SECURITY
909         {
910                 struct userpw *upw = getuserpw(passwd->bv_val);
911
912                 if (upw != NULL) {
913                         pw = upw->upw_passwd;
914                 }
915         }
916 #  endif
917
918         if( pw == NULL || pw[0] == '\0' || pw[1] == '\0' ) {
919                 /* password must must be at least two characters long */
920                 return -1;
921         }
922
923         cr = crypt(cred->bv_val, pw);
924
925         if( cr == NULL || cr[0] == '\0' ) {
926                 /* salt must have been invalid */
927                 return -1;
928         }
929
930         return strcmp(pw, cr) ? 1 : 0;
931
932 }
933 # endif
934 #endif
935
936 /* PASSWORD GENERATION ROUTINES */
937
938 #ifdef LUTIL_SHA1_BYTES
939 static struct berval *hash_ssha1(
940         const struct berval *scheme,
941         const struct berval  *passwd,
942         const char **text )
943 {
944         lutil_SHA1_CTX  SHA1context;
945         unsigned char   SHA1digest[LUTIL_SHA1_BYTES];
946         char            saltdata[SALT_SIZE];
947         struct berval digest;
948         struct berval salt;
949
950         digest.bv_val = (char *) SHA1digest;
951         digest.bv_len = sizeof(SHA1digest);
952         salt.bv_val = saltdata;
953         salt.bv_len = sizeof(saltdata);
954
955         if( lutil_entropy( (unsigned char *) salt.bv_val, salt.bv_len) < 0 ) {
956                 return NULL; 
957         }
958
959         lutil_SHA1Init( &SHA1context );
960         lutil_SHA1Update( &SHA1context,
961                 (const unsigned char *)passwd->bv_val, passwd->bv_len );
962         lutil_SHA1Update( &SHA1context,
963                 (const unsigned char *)salt.bv_val, salt.bv_len );
964         lutil_SHA1Final( SHA1digest, &SHA1context );
965
966         return pw_string64( scheme, &digest, &salt);
967 }
968
969 static struct berval *hash_sha1(
970         const struct berval *scheme,
971         const struct berval  *passwd,
972         const char **text )
973 {
974         lutil_SHA1_CTX  SHA1context;
975         unsigned char   SHA1digest[LUTIL_SHA1_BYTES];
976         struct berval digest;
977         digest.bv_val = (char *) SHA1digest;
978         digest.bv_len = sizeof(SHA1digest);
979      
980         lutil_SHA1Init( &SHA1context );
981         lutil_SHA1Update( &SHA1context,
982                 (const unsigned char *)passwd->bv_val, passwd->bv_len );
983         lutil_SHA1Final( SHA1digest, &SHA1context );
984             
985         return pw_string64( scheme, &digest, NULL);
986 }
987 #endif
988
989 static struct berval *hash_smd5(
990         const struct berval *scheme,
991         const struct berval  *passwd,
992         const char **text )
993 {
994         lutil_MD5_CTX   MD5context;
995         unsigned char   MD5digest[LUTIL_MD5_BYTES];
996         char            saltdata[SALT_SIZE];
997         struct berval digest;
998         struct berval salt;
999
1000         digest.bv_val = (char *) MD5digest;
1001         digest.bv_len = sizeof(MD5digest);
1002         salt.bv_val = saltdata;
1003         salt.bv_len = sizeof(saltdata);
1004
1005         if( lutil_entropy( (unsigned char *) salt.bv_val, salt.bv_len) < 0 ) {
1006                 return NULL; 
1007         }
1008
1009         lutil_MD5Init( &MD5context );
1010         lutil_MD5Update( &MD5context,
1011                 (const unsigned char *) passwd->bv_val, passwd->bv_len );
1012         lutil_MD5Update( &MD5context,
1013                 (const unsigned char *) salt.bv_val, salt.bv_len );
1014         lutil_MD5Final( MD5digest, &MD5context );
1015
1016         return pw_string64( scheme, &digest, &salt );
1017 }
1018
1019 static struct berval *hash_md5(
1020         const struct berval *scheme,
1021         const struct berval  *passwd,
1022         const char **text )
1023 {
1024         lutil_MD5_CTX   MD5context;
1025         unsigned char   MD5digest[LUTIL_MD5_BYTES];
1026
1027         struct berval digest;
1028
1029         digest.bv_val = (char *) MD5digest;
1030         digest.bv_len = sizeof(MD5digest);
1031
1032         lutil_MD5Init( &MD5context );
1033         lutil_MD5Update( &MD5context,
1034                 (const unsigned char *) passwd->bv_val, passwd->bv_len );
1035         lutil_MD5Final( MD5digest, &MD5context );
1036
1037         return pw_string64( scheme, &digest, NULL );
1038 ;
1039 }
1040
1041 #ifdef SLAPD_LMHASH 
1042 static struct berval *hash_lanman(
1043         const struct berval *scheme,
1044         const struct berval *passwd,
1045         const char **text )
1046 {
1047
1048         int i;
1049         char UcasePassword[15];
1050         des_cblock key;
1051         des_key_schedule schedule;
1052         des_cblock StdText = "KGS!@#$%";
1053         des_cblock PasswordHash1, PasswordHash2;
1054         char PasswordHash[33];
1055         struct berval hash;
1056         
1057         for( i=0; i<passwd->bv_len; i++) {
1058                 if(passwd->bv_val[i] == '\0') {
1059                         return NULL;    /* NUL character in password */
1060                 }
1061         }
1062         
1063         if( passwd->bv_val[i] != '\0' ) {
1064                 return NULL;    /* passwd must behave like a string */
1065         }
1066         
1067         strncpy( UcasePassword, passwd->bv_val, 14 );
1068         UcasePassword[14] = '\0';
1069         ldap_pvt_str2upper( UcasePassword );
1070         
1071         lmPasswd_to_key( UcasePassword, &key );
1072         des_set_key_unchecked( &key, schedule );
1073         des_ecb_encrypt( &StdText, &PasswordHash1, schedule , DES_ENCRYPT );
1074         
1075         lmPasswd_to_key( &UcasePassword[7], &key );
1076         des_set_key_unchecked( &key, schedule );
1077         des_ecb_encrypt( &StdText, &PasswordHash2, schedule , DES_ENCRYPT );
1078         
1079         sprintf( PasswordHash, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 
1080                 PasswordHash1[0],PasswordHash1[1],PasswordHash1[2],PasswordHash1[3],
1081                 PasswordHash1[4],PasswordHash1[5],PasswordHash1[6],PasswordHash1[7],
1082                 PasswordHash2[0],PasswordHash2[1],PasswordHash2[2],PasswordHash2[3],
1083                 PasswordHash2[4],PasswordHash2[5],PasswordHash2[6],PasswordHash2[7] );
1084         
1085         hash.bv_val = PasswordHash;
1086         hash.bv_len = 32;
1087         
1088         return pw_string( scheme, &hash );
1089 }
1090 #endif /* SLAPD_LMHASH */
1091
1092 #ifdef SLAPD_CRYPT
1093 static struct berval *hash_crypt(
1094         const struct berval *scheme,
1095         const struct berval *passwd,
1096         const char **text )
1097 {
1098         struct berval hash;
1099         unsigned char salt[32]; /* salt suitable for most anything */
1100         unsigned int i;
1101
1102         for( i=0; i<passwd->bv_len; i++) {
1103                 if(passwd->bv_val[i] == '\0') {
1104                         return NULL;    /* NUL character in password */
1105                 }
1106         }
1107
1108         if( passwd->bv_val[i] != '\0' ) {
1109                 return NULL;    /* passwd must behave like a string */
1110         }
1111
1112         if( lutil_entropy( salt, sizeof( salt ) ) < 0 ) {
1113                 return NULL; 
1114         }
1115
1116         for( i=0; i< ( sizeof(salt) - 1 ); i++ ) {
1117                 salt[i] = crypt64[ salt[i] % (sizeof(crypt64)-1) ];
1118         }
1119         salt[sizeof( salt ) - 1 ] = '\0';
1120
1121         if( salt_format != NULL ) {
1122                 /* copy the salt we made into entropy before snprintfing
1123                    it back into the salt */
1124                 char entropy[sizeof(salt)];
1125                 strcpy( entropy, (char *) salt );
1126                 snprintf( (char *) salt, sizeof(entropy), salt_format, entropy );
1127         }
1128
1129         hash.bv_val = crypt( passwd->bv_val, (char *) salt );
1130
1131         if( hash.bv_val == NULL ) return NULL;
1132
1133         hash.bv_len = strlen( hash.bv_val );
1134
1135         if( hash.bv_len == 0 ) {
1136                 return NULL;
1137         }
1138
1139         return pw_string( scheme, &hash );
1140 }
1141 #endif
1142
1143 int lutil_salt_format(const char *format)
1144 {
1145 #ifdef SLAPD_CRYPT
1146         free( salt_format );
1147
1148         salt_format = format != NULL ? strdup( format ) : NULL;
1149 #endif
1150
1151         return 0;
1152 }
1153
1154 #ifdef SLAPD_CLEARTEXT
1155 static struct berval *hash_clear(
1156         const struct berval *scheme,
1157         const struct berval  *passwd,
1158         const char **text )
1159 {
1160         return ber_bvdup( (struct berval *) passwd );
1161 }
1162 #endif
1163