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