]> git.sur5r.net Git - openldap/blob - libraries/liblutil/passwd.c
561750f69bda72e62fcf6d7130c2dfac6d323528
[openldap] / libraries / liblutil / passwd.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /*
7  * lutil_password(credentials, password)
8  *
9  * Returns true if user supplied credentials matches
10  * the stored password. 
11  *
12  * Due to the use of the crypt(3) function 
13  * this routine is NOT thread-safe.
14  */
15
16 #include "portable.h"
17
18 #include <stdio.h>
19 #include <ac/stdlib.h>
20 #include <ac/string.h>
21
22 #ifdef SLAPD_KPASSWD
23 #       include <ac/krb.h>
24 #       include <ac/krb5.h>
25 #endif
26
27 #include <ac/param.h>
28
29 #include <ac/unistd.h>
30 #include <ac/crypt.h>
31
32 #ifdef HAVE_SHADOW_H
33 #       include <shadow.h>
34 #endif
35 #ifdef HAVE_PWD_H
36 #       include <pwd.h>
37 #endif
38
39 #include <lber.h>
40
41 #include "lutil_md5.h"
42 #include "lutil_sha1.h"
43 #include "lutil.h"
44
45 static const unsigned char crypt64[] =
46         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
47
48 struct pw_scheme;
49
50 typedef int (*PASSWD_CHK_FUNC)(
51         const struct pw_scheme *scheme,
52         const struct berval *passwd,
53         const struct berval *cred );
54
55 typedef struct berval * (*PASSWD_HASH_FUNC) (
56         const struct pw_scheme *scheme,
57         const struct berval *passwd );
58
59 struct pw_scheme {
60         struct berval name;
61         PASSWD_CHK_FUNC chk_fn;
62         PASSWD_HASH_FUNC hash_fn;
63 };
64
65 /* password check routines */
66 static int chk_md5(
67         const struct pw_scheme *scheme,
68         const struct berval *passwd,
69         const struct berval *cred );
70
71 static int chk_smd5(
72         const struct pw_scheme *scheme,
73         const struct berval *passwd,
74         const struct berval *cred );
75
76 static int chk_ssha1(
77         const struct pw_scheme *scheme,
78         const struct berval *passwd,
79         const struct berval *cred );
80
81 static int chk_sha1(
82         const struct pw_scheme *scheme,
83         const struct berval *passwd,
84         const struct berval *cred );
85
86 static int chk_kerberos(
87         const struct pw_scheme *scheme,
88         const struct berval *passwd,
89         const struct berval *cred );
90
91 static int chk_crypt(
92         const struct pw_scheme *scheme,
93         const struct berval *passwd,
94         const struct berval *cred );
95
96 static int chk_unix(
97         const struct pw_scheme *scheme,
98         const struct berval *passwd,
99         const struct berval *cred );
100
101
102 /* password hash routines */
103 static struct berval *hash_sha1(
104         const struct pw_scheme *scheme,
105         const struct berval *passwd );
106
107 static struct berval *hash_ssha1(
108         const struct pw_scheme *scheme,
109         const struct berval *passwd );
110
111 static struct berval *hash_smd5(
112         const struct pw_scheme *scheme,
113         const struct berval *passwd );
114
115 static struct berval *hash_md5(
116         const struct pw_scheme *scheme,
117         const struct berval *passwd );
118
119 static struct berval *hash_crypt(
120         const struct pw_scheme *scheme,
121         const struct berval *passwd );
122
123
124 static const struct pw_scheme pw_schemes[] =
125 {
126         { {sizeof("{SSHA}")-1, "{SSHA}"},       chk_ssha1, hash_ssha1 },
127         { {sizeof("{SHA}")-1, "{SHA}"},         chk_sha1, hash_sha1 },
128
129         { {sizeof("{SMD5}")-1, "{SMD5}"},       chk_smd5, hash_smd5 },
130         { {sizeof("{MD5}")-1, "{MD5}"},         chk_md5, hash_md5 },
131
132 #ifdef SLAPD_KPASSWD
133         { {sizeof("{KERBEROS}")-1, "{KERBEROS}"}, chk_kerberos, NULL },
134 #endif
135
136 #ifdef SLAPD_CRYPT
137         { {sizeof("{CRYPT}")-1, "{CRYPT}"},     chk_crypt, hash_crypt },
138 #endif
139 # if defined( HAVE_GETSPNAM ) \
140   || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
141         { {sizeof("{UNIX}")-1, "{UNIX}"},       chk_unix, NULL },
142 #endif
143
144 #ifdef SLAPD_CLEARTEXT
145         /* psuedo scheme */
146         { {0, "{CLEARTEXT}"}, NULL, NULL },
147 #endif
148
149         { {0, NULL}, NULL, NULL }
150 };
151
152 static const struct pw_scheme *get_scheme(
153         const char* scheme )
154 {
155         int i;
156
157         for( i=0; pw_schemes[i].name.bv_val; i++) {
158                 if( pw_schemes[i].name.bv_len == 0 ) continue;
159
160                 if( strncasecmp(scheme, pw_schemes[i].name.bv_val,
161                         pw_schemes[i].name.bv_len) == 0 )
162                 {
163                         return &pw_schemes[i];
164                 }
165         }
166
167         return NULL;
168 }
169
170 int lutil_passwd_scheme(
171         const char* scheme )
172 {
173         if( scheme == NULL ) {
174                 return 0;
175         }
176
177         return get_scheme(scheme) != NULL;
178 }
179
180
181 static int is_allowed_scheme( 
182         const char* scheme,
183         const char** schemes )
184 {
185         int i;
186
187         if( schemes == NULL ) return 1;
188
189         for( i=0; schemes[i] != NULL; i++ ) {
190                 if( strcasecmp( scheme, schemes[i] ) == 0 ) {
191                         return 1;
192                 }
193         }
194         return 0;
195 }
196
197 static struct berval *passwd_scheme(
198         const struct pw_scheme *scheme,
199         const struct berval * passwd,
200         const char** allowed )
201 {
202         if( !is_allowed_scheme( scheme->name.bv_val, allowed ) ) {
203                 return NULL;
204         }
205
206         if( passwd->bv_len >= scheme->name.bv_len ) {
207                 if( strncasecmp( passwd->bv_val, scheme->name.bv_val, scheme->name.bv_len ) == 0 ) {
208                         struct berval *bv = ber_memalloc( sizeof(struct berval) );
209
210                         if( bv == NULL ) return NULL;
211
212                         bv->bv_val = &passwd->bv_val[scheme->name.bv_len];
213                         bv->bv_len = passwd->bv_len - scheme->name.bv_len;
214
215                         return bv;
216                 }
217         }
218
219         return NULL;
220 }
221
222 /*
223  * Return 0 if creds are good.
224  */
225 int
226 lutil_passwd(
227         const struct berval *passwd,    /* stored passwd */
228         const struct berval *cred,              /* user cred */
229         const char **schemes )
230 {
231         int i;
232
233         if (cred == NULL || cred->bv_len == 0 ||
234                 passwd == NULL || passwd->bv_len == 0 )
235         {
236                 return -1;
237         }
238
239         for( i=0; pw_schemes[i].name.bv_val != NULL; i++ ) {
240                 if( pw_schemes[i].chk_fn ) {
241                         struct berval *p = passwd_scheme( &pw_schemes[i],
242                                 passwd, schemes );
243
244                         if( p != NULL ) {
245                                 int rc = (pw_schemes[i].chk_fn)( &pw_schemes[i], p, cred );
246
247                                 /* only free the berval structure as the bv_val points
248                                  * into passwd->bv_val
249                                  */
250                                 ber_memfree( p );
251                                 
252                                 return rc;
253                         }
254                 }
255         }
256
257 #ifdef SLAPD_CLEARTEXT
258         if( is_allowed_scheme("{CLEARTEXT}", schemes ) ) {
259                 return passwd->bv_len == cred->bv_len
260                         ? memcmp( passwd->bv_val, cred->bv_val, passwd->bv_len )
261                         : 1;
262         }
263 #else
264         return 1;
265 #endif
266
267 }
268
269 struct berval * lutil_passwd_generate( ber_len_t len )
270 {
271         struct berval *pw;
272
273         if( len < 1 ) return NULL;
274
275         pw = ber_memalloc( sizeof( struct berval ) );
276         if( pw == NULL ) return NULL;
277
278         pw->bv_len = len;
279         pw->bv_val = ber_memalloc( len + 1 );
280
281         if( pw->bv_val == NULL ) {
282                 ber_memfree( pw );
283                 return NULL;
284         }
285
286         if( lutil_entropy( pw->bv_val, pw->bv_len) < 0 ) {
287                 ber_bvfree( pw );
288                 return NULL; 
289         }
290
291         for( len = 0; len < pw->bv_len; len++ ) {
292                 pw->bv_val[len] = crypt64[
293                         pw->bv_val[len] % (sizeof(crypt64)-1) ];
294         }
295
296         pw->bv_val[len] = '\0';
297         
298         return pw;
299 }
300
301 struct berval * lutil_passwd_hash(
302         const struct berval * passwd,
303         const char * method )
304 {
305         const struct pw_scheme *sc = get_scheme( method );
306
307         if( sc == NULL ) return NULL;
308         if( ! sc->hash_fn ) return NULL;
309
310         return (sc->hash_fn)( sc, passwd );
311 }
312
313 static struct berval * pw_string(
314         const struct pw_scheme *sc,
315         const struct berval *passwd )
316 {
317         struct berval *pw = ber_memalloc( sizeof( struct berval ) );
318         if( pw == NULL ) return NULL;
319
320         pw->bv_len = sc->name.bv_len + passwd->bv_len;
321         pw->bv_val = ber_memalloc( pw->bv_len + 1 );
322
323         if( pw->bv_val == NULL ) {
324                 ber_memfree( pw );
325                 return NULL;
326         }
327
328         memcpy( pw->bv_val, sc->name.bv_val, sc->name.bv_len );
329         memcpy( &pw->bv_val[sc->name.bv_len], passwd->bv_val, passwd->bv_len );
330
331         pw->bv_val[pw->bv_len] = '\0';
332         return pw;
333 }
334
335 static struct berval * pw_string64(
336         const struct pw_scheme *sc,
337         const struct berval *hash,
338         const struct berval *salt )
339 {
340         int rc;
341         struct berval string;
342         struct berval *b64 = ber_memalloc( sizeof(struct berval) );
343         size_t b64len;
344
345         if( b64 == NULL ) return NULL;
346
347         if( salt ) {
348                 /* need to base64 combined string */
349                 string.bv_len = hash->bv_len + salt->bv_len;
350                 string.bv_val = ber_memalloc( string.bv_len + 1 );
351
352                 if( string.bv_val == NULL ) {
353                         ber_memfree( b64 );
354                         return NULL;
355                 }
356
357                 memcpy( string.bv_val, hash->bv_val,
358                         hash->bv_len );
359                 memcpy( &string.bv_val[hash->bv_len], salt->bv_val,
360                         salt->bv_len );
361                 string.bv_val[string.bv_len] = '\0';
362
363         } else {
364                 string = *hash;
365         }
366
367         b64len = LUTIL_BASE64_ENCODE_LEN( string.bv_len ) + 1;
368         b64->bv_len = b64len + sc->name.bv_len;
369         b64->bv_val = ber_memalloc( b64->bv_len + 1 );
370
371         if( b64->bv_val == NULL ) {
372                 if( salt ) ber_memfree( string.bv_val );
373                 ber_memfree( b64 );
374                 return NULL;
375         }
376
377         memcpy(b64->bv_val, sc->name.bv_val, sc->name.bv_len);
378
379         rc = lutil_b64_ntop(
380                 string.bv_val, string.bv_len,
381                 &b64->bv_val[sc->name.bv_len], b64len );
382
383         b64->bv_val[b64->bv_len] = '\0';
384
385         if( salt ) ber_memfree( string.bv_val );
386
387         if( rc < 0 ) {
388                 ber_bvfree( b64 );
389                 return NULL;
390         }
391
392         return b64;
393 }
394
395 /* PASSWORD CHECK ROUTINES */
396
397 static int chk_ssha1(
398         const struct pw_scheme *sc,
399         const struct berval * passwd,
400         const struct berval * cred )
401 {
402         lutil_SHA1_CTX SHA1context;
403         unsigned char SHA1digest[LUTIL_SHA1_BYTES];
404         int rc;
405         unsigned char *orig_pass = NULL;
406  
407         /* base64 un-encode password */
408         orig_pass = (unsigned char *) ber_memalloc( (size_t) (
409                 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
410
411         if( orig_pass == NULL ) return -1;
412
413         rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
414
415         if(rc < 0) {
416                 ber_memfree(orig_pass);
417                 return 1;
418         }
419  
420         /* hash credentials with salt */
421         lutil_SHA1Init(&SHA1context);
422         lutil_SHA1Update(&SHA1context,
423                 (const unsigned char *) cred->bv_val, cred->bv_len);
424         lutil_SHA1Update(&SHA1context,
425                 (const unsigned char *) &orig_pass[sizeof(SHA1digest)],
426                 rc - sizeof(SHA1digest));
427         lutil_SHA1Final(SHA1digest, &SHA1context);
428  
429         /* compare */
430         rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
431         ber_memfree(orig_pass);
432         return rc;
433 }
434
435 static int chk_sha1(
436         const struct pw_scheme *sc,
437         const struct berval * passwd,
438         const struct berval * cred )
439 {
440         lutil_SHA1_CTX SHA1context;
441         unsigned char SHA1digest[LUTIL_SHA1_BYTES];
442         int rc;
443         unsigned char *orig_pass = NULL;
444  
445         /* base64 un-encode password */
446         orig_pass = (unsigned char *) ber_memalloc( (size_t) (
447                 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
448
449         if( orig_pass == NULL ) return -1;
450
451         rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
452
453         if( rc != sizeof(SHA1digest) ) {
454                 ber_memfree(orig_pass);
455                 return 1;
456         }
457  
458         /* hash credentials with salt */
459         lutil_SHA1Init(&SHA1context);
460         lutil_SHA1Update(&SHA1context,
461                 (const unsigned char *) cred->bv_val, cred->bv_len);
462         lutil_SHA1Final(SHA1digest, &SHA1context);
463  
464         /* compare */
465         rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
466         ber_memfree(orig_pass);
467         return rc;
468 }
469
470 static int chk_smd5(
471         const struct pw_scheme *sc,
472         const struct berval * passwd,
473         const struct berval * cred )
474 {
475         lutil_MD5_CTX MD5context;
476         unsigned char MD5digest[LUTIL_MD5_BYTES];
477         int rc;
478         unsigned char *orig_pass = NULL;
479
480         /* base64 un-encode password */
481         orig_pass = (unsigned char *) ber_memalloc( (size_t) (
482                 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
483
484         if( orig_pass == NULL ) return -1;
485
486         rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
487         if ( rc < 0 ) {
488                 ber_memfree(orig_pass);
489                 return 1;
490         }
491
492         /* hash credentials with salt */
493         lutil_MD5Init(&MD5context);
494         lutil_MD5Update(&MD5context,
495                 (const unsigned char *) cred->bv_val, cred->bv_len );
496         lutil_MD5Update(&MD5context,
497                 (const unsigned char *) &orig_pass[sizeof(MD5digest)],
498                 rc - sizeof(MD5digest));
499         lutil_MD5Final(MD5digest, &MD5context);
500
501         /* compare */
502         rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
503         ber_memfree(orig_pass);
504         return rc;
505 }
506
507 static int chk_md5(
508         const struct pw_scheme *sc,
509         const struct berval * passwd,
510         const struct berval * cred )
511 {
512         lutil_MD5_CTX MD5context;
513         unsigned char MD5digest[LUTIL_MD5_BYTES];
514         int rc;
515         unsigned char *orig_pass = NULL;
516
517         /* base64 un-encode password */
518         orig_pass = (unsigned char *) ber_memalloc( (size_t) (
519                 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
520
521         if( orig_pass == NULL ) return -1;
522
523         rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
524         if ( rc != sizeof(MD5digest) ) {
525                 ber_memfree(orig_pass);
526                 return 1;
527         }
528
529         /* hash credentials with salt */
530         lutil_MD5Init(&MD5context);
531         lutil_MD5Update(&MD5context,
532                 (const unsigned char *) cred->bv_val, cred->bv_len );
533         lutil_MD5Final(MD5digest, &MD5context);
534
535         /* compare */
536         rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
537         ber_memfree(orig_pass);
538         return rc;
539 }
540
541 #ifdef SLAPD_KPASSWD
542 static int chk_kerberos(
543         const struct pw_scheme *sc,
544         const struct berval * passwd,
545         const struct berval * cred )
546 {
547         int i;
548         int rtn;
549
550         for( i=0; i<cred->bv_len; i++) {
551                 if(cred->bv_val[i] == '\0') {
552                         return 1;       /* NUL character in password */
553                 }
554         }
555
556         if( cred->bv_val[i] != '\0' ) {
557                 return 1;       /* cred must behave like a string */
558         }
559
560         for( i=0; i<passwd->bv_len; i++) {
561                 if(passwd->bv_val[i] == '\0') {
562                         return 1;       /* NUL character in password */
563                 }
564         }
565
566         if( passwd->bv_val[i] != '\0' ) {
567                 return 1;       /* passwd must behave like a string */
568         }
569
570         rtn = 1;
571
572 #ifdef HAVE_KRB5 /* HAVE_HEIMDAL_KRB5 */
573         {
574 /* Portions:
575  * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H\xf6gskolan
576  * (Royal Institute of Technology, Stockholm, Sweden).
577  * All rights reserved.
578  *
579  * Redistribution and use in source and binary forms, with or without
580  * modification, are permitted provided that the following conditions
581  * are met:
582  *
583  * 1. Redistributions of source code must retain the above copyright
584  *    notice, this list of conditions and the following disclaimer.
585  *
586  * 2. Redistributions in binary form must reproduce the above copyright
587  *    notice, this list of conditions and the following disclaimer in the
588  *    documentation and/or other materials provided with the distribution.
589  *
590  * 3. Neither the name of the Institute nor the names of its contributors
591  *    may be used to endorse or promote products derived from this software
592  *    without specific prior written permission.
593  *
594  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
595  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
596  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
597  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
598  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
599  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
600  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
601  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
602  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
603  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
604  * SUCH DAMAGE.
605  */
606
607                 krb5_context context;
608                 krb5_error_code ret;
609                 krb5_creds creds;
610                 krb5_get_init_creds_opt get_options;
611                 krb5_verify_init_creds_opt verify_options;
612                 krb5_principal client, server;
613 #ifdef notdef
614                 krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP};
615 #endif
616
617                 krb5_init_context( &context );
618                 if (ret) {
619                         return 1;
620                 }
621
622 #ifdef notdef
623                 krb5_get_init_creds_opt_set_preauth_list(&get_options,
624                         pre_auth_types, 1);
625 #endif
626
627                 krb5_get_init_creds_opt_init( &get_options );
628
629                 krb5_verify_init_creds_opt_init( &verify_options );
630         
631                 ret = krb5_parse_name( context, passwd->bv_val, &client );
632
633                 if (ret) {
634                         krb5_free_context( context );
635                         return 1;
636                 }
637
638                 ret = krb5_get_init_creds_password( context,
639                         &creds, client, cred->bv_val, NULL,
640                         NULL, 0, NULL, &get_options );
641
642                 if (ret) {
643                         krb5_free_principal( context, client );
644                         krb5_free_context( context );
645                         return 1;
646                 }
647
648                 {
649                         char host[MAXHOSTNAMELEN];
650
651                         if( gethostname( host, MAXHOSTNAMELEN ) != 0 ) {
652                                 krb5_free_principal( context, client );
653                                 krb5_free_context( context );
654                                 return 1;
655                         }
656
657                         ret = krb5_sname_to_principal( context,
658                                 host, "ldap", KRB5_NT_SRV_HST, &server );
659                 }
660
661                 if (ret) {
662                         krb5_free_principal( context, client );
663                         krb5_free_context( context );
664                         return 1;
665                 }
666
667                 ret = krb5_verify_init_creds( context,
668                         &creds, server, NULL, NULL, &verify_options );
669
670                 krb5_free_principal( context, client );
671                 krb5_free_principal( context, server );
672                 krb5_free_creds_contents( context, &creds );
673                 krb5_free_context( context );
674
675                 rtn = !!ret;
676         }
677 #elif   defined(HAVE_KRB4)
678         {
679                 /* Borrowed from Heimdal kpopper */
680 /* Portions:
681  * Copyright (c) 1989 Regents of the University of California.
682  * All rights reserved.  The Berkeley software License Agreement
683  * specifies the terms and conditions for redistribution.
684  */
685
686                 int status;
687                 char lrealm[REALM_SZ];
688                 char tkt[MAXHOSTNAMELEN];
689
690                 status = krb_get_lrealm(lrealm,1);
691                 if (status == KFAILURE) {
692                         return 1;
693                 }
694
695                 snprintf(tkt, sizeof(tkt), "%s_slapd.%u",
696                         TKT_ROOT, (unsigned)getpid());
697                 krb_set_tkt_string (tkt);
698
699                 status = krb_verify_user( passwd->bv_val, "", lrealm,
700                         cred->bv_val, 1, "ldap");
701
702                 dest_tkt(); /* no point in keeping the tickets */
703
704                 return status == KFAILURE;
705         }
706 #endif
707
708         return rtn;
709 }
710 #endif /* SLAPD_KPASSWD */
711
712 #ifdef SLAPD_CRYPT
713 static int chk_crypt(
714         const struct pw_scheme *sc,
715         const struct berval * passwd,
716         const struct berval * cred )
717 {
718         int i;
719
720         for( i=0; i<cred->bv_len; i++) {
721                 if(cred->bv_val[i] == '\0') {
722                         return 1;       /* NUL character in password */
723                 }
724         }
725
726         if( cred->bv_val[i] != '\0' ) {
727                 return 1;       /* cred must behave like a string */
728         }
729
730         for( i=0; i<passwd->bv_len; i++) {
731                 if(passwd->bv_val[i] == '\0') {
732                         return 1;       /* NUL character in password */
733                 }
734         }
735
736         if( passwd->bv_val[i] != '\0' ) {
737                 return 1;       /* passwd must behave like a string */
738         }
739
740         return strcmp(passwd->bv_val, crypt(cred->bv_val, passwd->bv_val));
741 }
742
743 # if defined( HAVE_GETSPNAM ) \
744   || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
745 static int chk_unix(
746         const struct pw_scheme *sc,
747         const struct berval * passwd,
748         const struct berval * cred )
749 {
750         int i;
751         char *pw;
752
753         for( i=0; i<cred->bv_len; i++) {
754                 if(cred->bv_val[i] == '\0') {
755                         return 1;       /* NUL character in password */
756                 }
757         }
758         if( cred->bv_val[i] != '\0' ) {
759                 return 1;       /* cred must behave like a string */
760         }
761
762         for( i=0; i<passwd->bv_len; i++) {
763                 if(passwd->bv_val[i] == '\0') {
764                         return 1;       /* NUL character in password */
765                 }
766         }
767
768         if( passwd->bv_val[i] != '\0' ) {
769                 return 1;       /* passwd must behave like a string */
770         }
771
772 #  ifdef HAVE_GETSPNAM
773         {
774                 struct spwd *spwd = getspnam(passwd->bv_val);
775
776                 if(spwd == NULL) {
777                         return 1;       /* not found */
778                 }
779
780                 pw = spwd->sp_pwdp;
781         }
782
783 #  else
784         {
785                 struct passwd *pwd = getpwnam(passwd->bv_val);
786
787                 if(pwd == NULL) {
788                         return 1;       /* not found */
789                 }
790
791                 pw = pwd->pw_passwd;
792         }
793 #  endif
794
795         if( pw == NULL || *pw == '\0' ) return 1;
796
797         return strcmp(pw, crypt(cred->bv_val, pw));
798
799 }
800 # endif
801 #endif
802
803 /* PASSWORD CHECK ROUTINES */
804 static struct berval *hash_ssha1(
805         const struct pw_scheme *scheme,
806         const struct berval  *passwd )
807 {
808         lutil_SHA1_CTX  SHA1context;
809         unsigned char   SHA1digest[LUTIL_SHA1_BYTES];
810         unsigned char   saltdata[4];
811         struct berval digest;
812         struct berval salt;
813
814         digest.bv_val = SHA1digest;
815         digest.bv_len = sizeof(SHA1digest);
816         salt.bv_val = saltdata;
817         salt.bv_len = sizeof(saltdata);
818
819         if( lutil_entropy( salt.bv_val, salt.bv_len) < 0 ) {
820                 return NULL; 
821         }
822
823         lutil_SHA1Init( &SHA1context );
824         lutil_SHA1Update( &SHA1context,
825                 (const unsigned char *)passwd->bv_val, passwd->bv_len );
826         lutil_SHA1Update( &SHA1context,
827                 (const unsigned char *)salt.bv_val, salt.bv_len );
828         lutil_SHA1Final( SHA1digest, &SHA1context );
829
830         return pw_string64( scheme, &digest, &salt);
831 }
832
833 static struct berval *hash_sha1(
834         const struct pw_scheme *scheme,
835         const struct berval  *passwd )
836 {
837         lutil_SHA1_CTX  SHA1context;
838         unsigned char   SHA1digest[20];
839         struct berval digest;
840         digest.bv_val = SHA1digest;
841         digest.bv_len = sizeof(SHA1digest);
842      
843         lutil_SHA1Init( &SHA1context );
844         lutil_SHA1Update( &SHA1context,
845                 (const unsigned char *)passwd->bv_val, passwd->bv_len );
846         lutil_SHA1Final( SHA1digest, &SHA1context );
847             
848         return pw_string64( scheme, &digest, NULL);
849 }
850
851 static struct berval *hash_smd5(
852         const struct pw_scheme *scheme,
853         const struct berval  *passwd )
854 {
855         lutil_MD5_CTX   MD5context;
856         unsigned char   MD5digest[16];
857         unsigned char   saltdata[4];
858         struct berval digest;
859         struct berval salt;
860
861         digest.bv_val = MD5digest;
862         digest.bv_len = sizeof(MD5digest);
863         salt.bv_val = saltdata;
864         salt.bv_len = sizeof(saltdata);
865
866         if( lutil_entropy( salt.bv_val, salt.bv_len) < 0 ) {
867                 return NULL; 
868         }
869
870         lutil_MD5Init( &MD5context );
871         lutil_MD5Update( &MD5context,
872                 (const unsigned char *) passwd->bv_val, passwd->bv_len );
873         lutil_MD5Update( &MD5context,
874                 (const unsigned char *) salt.bv_val, salt.bv_len );
875         lutil_MD5Final( MD5digest, &MD5context );
876
877         return pw_string64( scheme, &digest, &salt );
878 }
879
880 static struct berval *hash_md5(
881         const struct pw_scheme *scheme,
882         const struct berval  *passwd )
883 {
884         lutil_MD5_CTX   MD5context;
885         unsigned char   MD5digest[16];
886
887         struct berval digest;
888
889         digest.bv_val = MD5digest;
890         digest.bv_len = sizeof(MD5digest);
891
892         lutil_MD5Init( &MD5context );
893         lutil_MD5Update( &MD5context,
894                 (const unsigned char *) passwd->bv_val, passwd->bv_len );
895         lutil_MD5Final( MD5digest, &MD5context );
896
897         return pw_string64( scheme, &digest, NULL );
898 ;
899 }
900
901 #ifdef SLAPD_CRYPT
902 static struct berval *hash_crypt(
903         const struct pw_scheme *scheme,
904         const struct berval *passwd )
905 {
906         struct berval hash;
907         unsigned char salt[3];
908         int i;
909
910         for( i=0; i<passwd->bv_len; i++) {
911                 if(passwd->bv_val[i] == '\0') {
912                         return NULL;    /* NUL character in password */
913                 }
914         }
915
916         if( passwd->bv_val[i] != '\0' ) {
917                 return NULL;    /* passwd must behave like a string */
918         }
919
920         if( lutil_entropy( salt, sizeof(salt)) < 0 ) {
921                 return NULL; 
922         }
923
924         salt[0] = crypt64[ salt[0] % (sizeof(crypt64)-1) ];
925         salt[1] = crypt64[ salt[1] % (sizeof(crypt64)-1) ];
926         salt[2] = '\0';
927
928         hash.bv_val = crypt( passwd->bv_val, salt );
929
930         if( hash.bv_val == NULL ) return NULL;
931         hash.bv_len = strlen( hash.bv_val );
932
933         return pw_string( scheme, &hash );
934 }
935 #endif