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