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