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