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