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