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