]> git.sur5r.net Git - openldap/blob - libraries/liblutil/passwd.c
739c833bc6db2fa7883084f7e1b2afa8415556b3
[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 /* pw_string is only called when SLAPD_LMHASH or SLAPD_CRYPT is defined */
377 #if defined(SLAPD_LMHASH) || defined(SLAPD_CRYPT)
378 static struct berval * pw_string(
379         const struct pw_scheme *sc,
380         const struct berval *passwd )
381 {
382         struct berval *pw = ber_memalloc( sizeof( struct berval ) );
383         if( pw == NULL ) return NULL;
384
385         pw->bv_len = sc->name.bv_len + passwd->bv_len;
386         pw->bv_val = ber_memalloc( pw->bv_len + 1 );
387
388         if( pw->bv_val == NULL ) {
389                 ber_memfree( pw );
390                 return NULL;
391         }
392
393         AC_MEMCPY( pw->bv_val, sc->name.bv_val, sc->name.bv_len );
394         AC_MEMCPY( &pw->bv_val[sc->name.bv_len], passwd->bv_val, passwd->bv_len );
395
396         pw->bv_val[pw->bv_len] = '\0';
397         return pw;
398 }
399 #endif /* SLAPD_LMHASH || SLAPD_CRYPT */
400
401 static struct berval * pw_string64(
402         const struct pw_scheme *sc,
403         const struct berval *hash,
404         const struct berval *salt )
405 {
406         int rc;
407         struct berval string;
408         struct berval *b64 = ber_memalloc( sizeof(struct berval) );
409         size_t b64len;
410
411         if( b64 == NULL ) return NULL;
412
413         if( salt ) {
414                 /* need to base64 combined string */
415                 string.bv_len = hash->bv_len + salt->bv_len;
416                 string.bv_val = ber_memalloc( string.bv_len + 1 );
417
418                 if( string.bv_val == NULL ) {
419                         ber_memfree( b64 );
420                         return NULL;
421                 }
422
423                 AC_MEMCPY( string.bv_val, hash->bv_val,
424                         hash->bv_len );
425                 AC_MEMCPY( &string.bv_val[hash->bv_len], salt->bv_val,
426                         salt->bv_len );
427                 string.bv_val[string.bv_len] = '\0';
428
429         } else {
430                 string = *hash;
431         }
432
433         b64len = LUTIL_BASE64_ENCODE_LEN( string.bv_len ) + 1;
434         b64->bv_len = b64len + sc->name.bv_len;
435         b64->bv_val = ber_memalloc( b64->bv_len + 1 );
436
437         if( b64->bv_val == NULL ) {
438                 if( salt ) ber_memfree( string.bv_val );
439                 ber_memfree( b64 );
440                 return NULL;
441         }
442
443         AC_MEMCPY(b64->bv_val, sc->name.bv_val, sc->name.bv_len);
444
445         rc = lutil_b64_ntop(
446                 string.bv_val, string.bv_len,
447                 &b64->bv_val[sc->name.bv_len], b64len );
448
449         if( salt ) ber_memfree( string.bv_val );
450         
451         if( rc < 0 ) {
452                 ber_bvfree( b64 );
453                 return NULL;
454         }
455
456         /* recompute length */
457         b64->bv_len = sc->name.bv_len + rc;
458         assert( strlen(b64->bv_val) == b64->bv_len );
459         return b64;
460 }
461
462 /* PASSWORD CHECK ROUTINES */
463
464 #ifdef LUTIL_SHA1_BYTES
465 static int chk_ssha1(
466         const struct pw_scheme *sc,
467         const struct berval * passwd,
468         const struct berval * cred )
469 {
470         lutil_SHA1_CTX SHA1context;
471         unsigned char SHA1digest[LUTIL_SHA1_BYTES];
472         int rc;
473         unsigned char *orig_pass = NULL;
474  
475         /* decode base64 password */
476         orig_pass = (unsigned char *) ber_memalloc( (size_t) (
477                 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
478
479         if( orig_pass == NULL ) return -1;
480
481         rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
482
483         if(rc < 0) {
484                 ber_memfree(orig_pass);
485                 return -1;
486         }
487  
488         /* hash credentials with salt */
489         lutil_SHA1Init(&SHA1context);
490         lutil_SHA1Update(&SHA1context,
491                 (const unsigned char *) cred->bv_val, cred->bv_len);
492         lutil_SHA1Update(&SHA1context,
493                 (const unsigned char *) &orig_pass[sizeof(SHA1digest)],
494                 rc - sizeof(SHA1digest));
495         lutil_SHA1Final(SHA1digest, &SHA1context);
496  
497         /* compare */
498         rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
499         ber_memfree(orig_pass);
500         return rc ? 1 : 0;
501 }
502
503 static int chk_sha1(
504         const struct pw_scheme *sc,
505         const struct berval * passwd,
506         const struct berval * cred )
507 {
508         lutil_SHA1_CTX SHA1context;
509         unsigned char SHA1digest[LUTIL_SHA1_BYTES];
510         int rc;
511         unsigned char *orig_pass = NULL;
512  
513         /* base64 un-encode password */
514         orig_pass = (unsigned char *) ber_memalloc( (size_t) (
515                 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
516
517         if( orig_pass == NULL ) return -1;
518
519         rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
520
521         if( rc != sizeof(SHA1digest) ) {
522                 ber_memfree(orig_pass);
523                 return -1;
524         }
525  
526         /* hash credentials with salt */
527         lutil_SHA1Init(&SHA1context);
528         lutil_SHA1Update(&SHA1context,
529                 (const unsigned char *) cred->bv_val, cred->bv_len);
530         lutil_SHA1Final(SHA1digest, &SHA1context);
531  
532         /* compare */
533         rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
534         ber_memfree(orig_pass);
535         return rc ? 1 : 0;
536 }
537 #endif
538
539 static int chk_smd5(
540         const struct pw_scheme *sc,
541         const struct berval * passwd,
542         const struct berval * cred )
543 {
544         lutil_MD5_CTX MD5context;
545         unsigned char MD5digest[LUTIL_MD5_BYTES];
546         int rc;
547         unsigned char *orig_pass = NULL;
548
549         /* base64 un-encode password */
550         orig_pass = (unsigned char *) ber_memalloc( (size_t) (
551                 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
552
553         if( orig_pass == NULL ) return -1;
554
555         rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
556         if ( rc < 0 ) {
557                 ber_memfree(orig_pass);
558                 return -1;
559         }
560
561         /* hash credentials with salt */
562         lutil_MD5Init(&MD5context);
563         lutil_MD5Update(&MD5context,
564                 (const unsigned char *) cred->bv_val,
565                 cred->bv_len );
566         lutil_MD5Update(&MD5context,
567                 &orig_pass[sizeof(MD5digest)],
568                 rc - sizeof(MD5digest));
569         lutil_MD5Final(MD5digest, &MD5context);
570
571         /* compare */
572         rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
573         ber_memfree(orig_pass);
574         return rc ? 1 : 0;
575 }
576
577 static int chk_md5(
578         const struct pw_scheme *sc,
579         const struct berval * passwd,
580         const struct berval * cred )
581 {
582         lutil_MD5_CTX MD5context;
583         unsigned char MD5digest[LUTIL_MD5_BYTES];
584         int rc;
585         unsigned char *orig_pass = NULL;
586
587         /* base64 un-encode password */
588         orig_pass = (unsigned char *) ber_memalloc( (size_t) (
589                 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
590
591         if( orig_pass == NULL ) return -1;
592
593         rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
594         if ( rc != sizeof(MD5digest) ) {
595                 ber_memfree(orig_pass);
596                 return -1;
597         }
598
599         /* hash credentials with salt */
600         lutil_MD5Init(&MD5context);
601         lutil_MD5Update(&MD5context,
602                 (const unsigned char *) cred->bv_val,
603                 cred->bv_len );
604         lutil_MD5Final(MD5digest, &MD5context);
605
606         /* compare */
607         rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
608         ber_memfree(orig_pass);
609         return rc ? 1 : 0;
610 }
611
612 #ifdef SLAPD_LMHASH
613 static int chk_lanman(
614         const struct pw_scheme *scheme,
615         const struct berval *passwd,
616         const struct berval *cred )
617 {
618         struct berval *hash;
619
620         hash = hash_lanman( scheme, cred );
621         return memcmp( &hash->bv_val[scheme->name.bv_len], passwd->bv_val, 32);
622 }
623 #endif /* SLAPD_LMHASH */
624
625 #ifdef SLAPD_SPASSWD
626 #ifdef HAVE_CYRUS_SASL
627 sasl_conn_t *lutil_passwd_sasl_conn = NULL;
628 #endif
629
630 static int chk_sasl(
631         const struct pw_scheme *sc,
632         const struct berval * passwd,
633         const struct berval * cred )
634 {
635         int i;
636         int rtn;
637
638         for( i=0; i<cred->bv_len; i++) {
639                 if(cred->bv_val[i] == '\0') {
640                         return 1;       /* NUL character in password */
641                 }
642         }
643
644         if( cred->bv_val[i] != '\0' ) {
645                 return 1;       /* cred must behave like a string */
646         }
647
648         for( i=0; i<passwd->bv_len; i++) {
649                 if(passwd->bv_val[i] == '\0') {
650                         return 1;       /* NUL character in password */
651                 }
652         }
653
654         if( passwd->bv_val[i] != '\0' ) {
655                 return 1;       /* passwd must behave like a string */
656         }
657
658         rtn = 1;
659
660 #ifdef HAVE_CYRUS_SASL
661         if( lutil_passwd_sasl_conn != NULL ) {
662                 const char *errstr = NULL;
663                 int sc;
664
665                 sc = sasl_checkpass( lutil_passwd_sasl_conn,
666                         passwd->bv_val, passwd->bv_len,
667                         cred->bv_val, cred->bv_len,
668                         &errstr );
669
670                 rtn = ( sc != SASL_OK );
671         }
672 #endif
673
674         return rtn;
675 }
676 #endif
677
678 #ifdef SLAPD_KPASSWD
679 static int chk_kerberos(
680         const struct pw_scheme *sc,
681         const struct berval * passwd,
682         const struct berval * cred )
683 {
684         int i;
685         int rtn;
686
687         for( i=0; i<cred->bv_len; i++) {
688                 if(cred->bv_val[i] == '\0') {
689                         return 1;       /* NUL character in password */
690                 }
691         }
692
693         if( cred->bv_val[i] != '\0' ) {
694                 return 1;       /* cred must behave like a string */
695         }
696
697         for( i=0; i<passwd->bv_len; i++) {
698                 if(passwd->bv_val[i] == '\0') {
699                         return 1;       /* NUL character in password */
700                 }
701         }
702
703         if( passwd->bv_val[i] != '\0' ) {
704                 return 1;       /* passwd must behave like a string */
705         }
706
707         rtn = 1;
708
709 #ifdef HAVE_KRB5 /* HAVE_HEIMDAL_KRB5 */
710         {
711 /* Portions:
712  * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H\xf6gskolan
713  * (Royal Institute of Technology, Stockholm, Sweden).
714  * All rights reserved.
715  *
716  * Redistribution and use in source and binary forms, with or without
717  * modification, are permitted provided that the following conditions
718  * are met:
719  *
720  * 1. Redistributions of source code must retain the above copyright
721  *    notice, this list of conditions and the following disclaimer.
722  *
723  * 2. Redistributions in binary form must reproduce the above copyright
724  *    notice, this list of conditions and the following disclaimer in the
725  *    documentation and/or other materials provided with the distribution.
726  *
727  * 3. Neither the name of the Institute nor the names of its contributors
728  *    may be used to endorse or promote products derived from this software
729  *    without specific prior written permission.
730  *
731  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
732  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
733  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
734  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
735  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
736  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
737  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
738  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
739  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
740  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
741  * SUCH DAMAGE.
742  */
743
744                 krb5_context context;
745                 krb5_error_code ret;
746                 krb5_creds creds;
747                 krb5_get_init_creds_opt get_options;
748                 krb5_verify_init_creds_opt verify_options;
749                 krb5_principal client, server;
750 #ifdef notdef
751                 krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP};
752 #endif
753
754                 ret = krb5_init_context( &context );
755                 if (ret) {
756                         return 1;
757                 }
758
759 #ifdef notdef
760                 krb5_get_init_creds_opt_set_preauth_list(&get_options,
761                         pre_auth_types, 1);
762 #endif
763
764                 krb5_get_init_creds_opt_init( &get_options );
765
766                 krb5_verify_init_creds_opt_init( &verify_options );
767         
768                 ret = krb5_parse_name( context, passwd->bv_val, &client );
769
770                 if (ret) {
771                         krb5_free_context( context );
772                         return 1;
773                 }
774
775                 ret = krb5_get_init_creds_password( context,
776                         &creds, client, cred->bv_val, NULL,
777                         NULL, 0, NULL, &get_options );
778
779                 if (ret) {
780                         krb5_free_principal( context, client );
781                         krb5_free_context( context );
782                         return 1;
783                 }
784
785                 {
786                         char *host = ldap_pvt_get_fqdn( NULL );
787
788                         if( host == NULL ) {
789                                 krb5_free_principal( context, client );
790                                 krb5_free_context( context );
791                                 return 1;
792                         }
793
794                         ret = krb5_sname_to_principal( context,
795                                 host, "ldap", KRB5_NT_SRV_HST, &server );
796
797                         ber_memfree( host );
798                 }
799
800                 if (ret) {
801                         krb5_free_principal( context, client );
802                         krb5_free_context( context );
803                         return 1;
804                 }
805
806                 ret = krb5_verify_init_creds( context,
807                         &creds, server, NULL, NULL, &verify_options );
808
809                 krb5_free_principal( context, client );
810                 krb5_free_principal( context, server );
811                 krb5_free_cred_contents( context, &creds );
812                 krb5_free_context( context );
813
814                 rtn = !!ret;
815         }
816 #elif   defined(HAVE_KRB4)
817         {
818                 /* Borrowed from Heimdal kpopper */
819 /* Portions:
820  * Copyright (c) 1989 Regents of the University of California.
821  * All rights reserved.  The Berkeley software License Agreement
822  * specifies the terms and conditions for redistribution.
823  */
824
825                 int status;
826                 char lrealm[REALM_SZ];
827                 char tkt[MAXHOSTNAMELEN];
828
829                 status = krb_get_lrealm(lrealm,1);
830                 if (status == KFAILURE) {
831                         return 1;
832                 }
833
834                 snprintf(tkt, sizeof(tkt), "%s_slapd.%u",
835                         TKT_ROOT, (unsigned)getpid());
836                 krb_set_tkt_string (tkt);
837
838                 status = krb_verify_user( passwd->bv_val, "", lrealm,
839                         cred->bv_val, 1, "ldap");
840
841                 dest_tkt(); /* no point in keeping the tickets */
842
843                 return status == KFAILURE;
844         }
845 #endif
846
847         return rtn;
848 }
849 #endif /* SLAPD_KPASSWD */
850
851 #ifdef SLAPD_CRYPT
852 static int chk_crypt(
853         const struct pw_scheme *sc,
854         const struct berval * passwd,
855         const struct berval * cred )
856 {
857         char *cr;
858         int i;
859
860         for( i=0; i<cred->bv_len; i++) {
861                 if(cred->bv_val[i] == '\0') {
862                         return 1;       /* NUL character in password */
863                 }
864         }
865
866         if( cred->bv_val[i] != '\0' ) {
867                 return -1;      /* cred must behave like a string */
868         }
869
870         if( passwd->bv_len < 2 ) {
871                 return -1;      /* passwd must be at least two characters long */
872         }
873
874         for( i=0; i<passwd->bv_len; i++) {
875                 if(passwd->bv_val[i] == '\0') {
876                         return -1;      /* NUL character in password */
877                 }
878         }
879
880         if( passwd->bv_val[i] != '\0' ) {
881                 return -1;      /* passwd must behave like a string */
882         }
883
884         cr = crypt( cred->bv_val, passwd->bv_val );
885
886         if( cr == NULL || cr[0] == '\0' ) {
887                 /* salt must have been invalid */
888                 return -1;
889         }
890
891         return strcmp( passwd->bv_val, cr ) ? 1 : 0;
892 }
893
894 # if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD )
895 static int chk_unix(
896         const struct pw_scheme *sc,
897         const struct berval * passwd,
898         const struct berval * cred )
899 {
900         int i;
901         char *pw,*cr;
902
903         for( i=0; i<cred->bv_len; i++) {
904                 if(cred->bv_val[i] == '\0') {
905                         return -1;      /* NUL character in password */
906                 }
907         }
908         if( cred->bv_val[i] != '\0' ) {
909                 return -1;      /* cred must behave like a string */
910         }
911
912         for( i=0; i<passwd->bv_len; i++) {
913                 if(passwd->bv_val[i] == '\0') {
914                         return -1;      /* NUL character in password */
915                 }
916         }
917
918         if( passwd->bv_val[i] != '\0' ) {
919                 return -1;      /* passwd must behave like a string */
920         }
921
922         {
923                 struct passwd *pwd = getpwnam(passwd->bv_val);
924
925                 if(pwd == NULL) {
926                         return -1;      /* not found */
927                 }
928
929                 pw = pwd->pw_passwd;
930         }
931 #  ifdef HAVE_GETSPNAM
932         {
933                 struct spwd *spwd = getspnam(passwd->bv_val);
934
935                 if(spwd != NULL) {
936                         pw = spwd->sp_pwdp;
937                 }
938         }
939 #  endif
940 #  ifdef HAVE_AIX_SECURITY
941         {
942                 struct userpw *upw = getuserpw(passwd->bv_val);
943
944                 if (upw != NULL) {
945                         pw = upw->upw_passwd;
946                 }
947         }
948 #  endif
949
950         if( pw == NULL || pw[0] == '\0' || pw[1] == '\0' ) {
951                 /* password must must be at least two characters long */
952                 return -1;
953         }
954
955         cr = crypt(cred->bv_val, pw);
956
957         if( cr == NULL || cr[0] == '\0' ) {
958                 /* salt must have been invalid */
959                 return -1;
960         }
961
962         return strcmp(pw, cr) ? 1 : 0;
963
964 }
965 # endif
966 #endif
967
968 /* PASSWORD GENERATION ROUTINES */
969
970 #ifdef LUTIL_SHA1_BYTES
971 static struct berval *hash_ssha1(
972         const struct pw_scheme *scheme,
973         const struct berval  *passwd )
974 {
975         lutil_SHA1_CTX  SHA1context;
976         unsigned char   SHA1digest[LUTIL_SHA1_BYTES];
977         unsigned char   saltdata[4];
978         struct berval digest;
979         struct berval salt;
980
981         digest.bv_val = SHA1digest;
982         digest.bv_len = sizeof(SHA1digest);
983         salt.bv_val = saltdata;
984         salt.bv_len = sizeof(saltdata);
985
986         if( lutil_entropy( salt.bv_val, salt.bv_len) < 0 ) {
987                 return NULL; 
988         }
989
990         lutil_SHA1Init( &SHA1context );
991         lutil_SHA1Update( &SHA1context,
992                 (const unsigned char *)passwd->bv_val, passwd->bv_len );
993         lutil_SHA1Update( &SHA1context,
994                 (const unsigned char *)salt.bv_val, salt.bv_len );
995         lutil_SHA1Final( SHA1digest, &SHA1context );
996
997         return pw_string64( scheme, &digest, &salt);
998 }
999
1000 static struct berval *hash_sha1(
1001         const struct pw_scheme *scheme,
1002         const struct berval  *passwd )
1003 {
1004         lutil_SHA1_CTX  SHA1context;
1005         unsigned char   SHA1digest[LUTIL_SHA1_BYTES];
1006         struct berval digest;
1007         digest.bv_val = SHA1digest;
1008         digest.bv_len = sizeof(SHA1digest);
1009      
1010         lutil_SHA1Init( &SHA1context );
1011         lutil_SHA1Update( &SHA1context,
1012                 (const unsigned char *)passwd->bv_val, passwd->bv_len );
1013         lutil_SHA1Final( SHA1digest, &SHA1context );
1014             
1015         return pw_string64( scheme, &digest, NULL);
1016 }
1017 #endif
1018
1019 static struct berval *hash_smd5(
1020         const struct pw_scheme *scheme,
1021         const struct berval  *passwd )
1022 {
1023         lutil_MD5_CTX   MD5context;
1024         unsigned char   MD5digest[LUTIL_MD5_BYTES];
1025         unsigned char   saltdata[4];
1026         struct berval digest;
1027         struct berval salt;
1028
1029         digest.bv_val = MD5digest;
1030         digest.bv_len = sizeof(MD5digest);
1031         salt.bv_val = saltdata;
1032         salt.bv_len = sizeof(saltdata);
1033
1034         if( lutil_entropy( salt.bv_val, salt.bv_len) < 0 ) {
1035                 return NULL; 
1036         }
1037
1038         lutil_MD5Init( &MD5context );
1039         lutil_MD5Update( &MD5context,
1040                 (const unsigned char *) passwd->bv_val, passwd->bv_len );
1041         lutil_MD5Update( &MD5context,
1042                 (const unsigned char *) salt.bv_val, salt.bv_len );
1043         lutil_MD5Final( MD5digest, &MD5context );
1044
1045         return pw_string64( scheme, &digest, &salt );
1046 }
1047
1048 static struct berval *hash_md5(
1049         const struct pw_scheme *scheme,
1050         const struct berval  *passwd )
1051 {
1052         lutil_MD5_CTX   MD5context;
1053         unsigned char   MD5digest[LUTIL_MD5_BYTES];
1054
1055         struct berval digest;
1056
1057         digest.bv_val = MD5digest;
1058         digest.bv_len = sizeof(MD5digest);
1059
1060         lutil_MD5Init( &MD5context );
1061         lutil_MD5Update( &MD5context,
1062                 (const unsigned char *) passwd->bv_val, passwd->bv_len );
1063         lutil_MD5Final( MD5digest, &MD5context );
1064
1065         return pw_string64( scheme, &digest, NULL );
1066 ;
1067 }
1068
1069 #ifdef SLAPD_LMHASH 
1070 /* pseudocode from RFC2433
1071  * A.2 LmPasswordHash()
1072  * 
1073  *    LmPasswordHash(
1074  *    IN  0-to-14-oem-char Password,
1075  *    OUT 16-octet         PasswordHash )
1076  *    {
1077  *       Set UcasePassword to the uppercased Password
1078  *       Zero pad UcasePassword to 14 characters
1079  * 
1080  *       DesHash( 1st 7-octets of UcasePassword,
1081  *                giving 1st 8-octets of PasswordHash )
1082  * 
1083  *       DesHash( 2nd 7-octets of UcasePassword,
1084  *                giving 2nd 8-octets of PasswordHash )
1085  *    }
1086  * 
1087  * 
1088  * A.3 DesHash()
1089  * 
1090  *    DesHash(
1091  *    IN  7-octet Clear,
1092  *    OUT 8-octet Cypher )
1093  *    {
1094  *        *
1095  *        * Make Cypher an irreversibly encrypted form of Clear by
1096  *        * encrypting known text using Clear as the secret key.
1097  *        * The known text consists of the string
1098  *        *
1099  *        *              KGS!@#$%
1100  *        *
1101  * 
1102  *       Set StdText to "KGS!@#$%"
1103  *       DesEncrypt( StdText, Clear, giving Cypher )
1104  *    }
1105  * 
1106  * 
1107  * A.4 DesEncrypt()
1108  * 
1109  *    DesEncrypt(
1110  *    IN  8-octet Clear,
1111  *    IN  7-octet Key,
1112  *    OUT 8-octet Cypher )
1113  *    {
1114  *        *
1115  *        * Use the DES encryption algorithm [4] in ECB mode [9]
1116  *        * to encrypt Clear into Cypher such that Cypher can
1117  *        * only be decrypted back to Clear by providing Key.
1118  *        * Note that the DES algorithm takes as input a 64-bit
1119  *        * stream where the 8th, 16th, 24th, etc.  bits are
1120  *        * parity bits ignored by the encrypting algorithm.
1121  *        * Unless you write your own DES to accept 56-bit input
1122  *        * without parity, you will need to insert the parity bits
1123  *        * yourself.
1124  *        *
1125  *    }
1126  */
1127
1128 static void lmPasswd_to_key(
1129         const unsigned char *lmPasswd,
1130         des_cblock *key)
1131 {
1132         /* make room for parity bits */
1133         ((char *)key)[0] = lmPasswd[0];
1134         ((char *)key)[1] = ((lmPasswd[0]&0x01)<<7) | (lmPasswd[1]>>1);
1135         ((char *)key)[2] = ((lmPasswd[1]&0x03)<<6) | (lmPasswd[2]>>2);
1136         ((char *)key)[3] = ((lmPasswd[2]&0x07)<<5) | (lmPasswd[3]>>3);
1137         ((char *)key)[4] = ((lmPasswd[3]&0x0F)<<4) | (lmPasswd[4]>>4);
1138         ((char *)key)[5] = ((lmPasswd[4]&0x1F)<<3) | (lmPasswd[5]>>5);
1139         ((char *)key)[6] = ((lmPasswd[5]&0x3F)<<2) | (lmPasswd[6]>>6);
1140         ((char *)key)[7] = ((lmPasswd[6]&0x7F)<<1);
1141                 
1142         des_set_odd_parity( key );
1143 }       
1144
1145 static struct berval *hash_lanman(
1146         const struct pw_scheme *scheme,
1147         const struct berval *passwd )
1148 {
1149
1150         int i;
1151         char UcasePassword[15];
1152         des_cblock key;
1153         des_key_schedule schedule;
1154         des_cblock StdText = "KGS!@#$%";
1155         des_cblock hash1, hash2;
1156         char lmhash[33];
1157         struct berval hash;
1158         
1159         for( i=0; i<passwd->bv_len; i++) {
1160                 if(passwd->bv_val[i] == '\0') {
1161                         return NULL;    /* NUL character in password */
1162                 }
1163         }
1164         
1165         if( passwd->bv_val[i] != '\0' ) {
1166                 return NULL;    /* passwd must behave like a string */
1167         }
1168         
1169         strncpy( UcasePassword, passwd->bv_val, 14 );
1170         UcasePassword[14] = '\0';
1171         ldap_pvt_str2upper( UcasePassword );
1172         
1173         lmPasswd_to_key( UcasePassword, &key );
1174         des_set_key_unchecked( &key, schedule );
1175         des_ecb_encrypt( &StdText, &hash1, schedule , DES_ENCRYPT );
1176         
1177         lmPasswd_to_key( &UcasePassword[7], &key );
1178         des_set_key_unchecked( &key, schedule );
1179         des_ecb_encrypt( &StdText, &hash2, schedule , DES_ENCRYPT );
1180         
1181         sprintf( lmhash, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 
1182                 hash1[0],hash1[1],hash1[2],hash1[3],hash1[4],hash1[5],hash1[6],hash1[7],
1183                 hash2[0],hash2[1],hash2[2],hash2[3],hash2[4],hash2[5],hash2[6],hash2[7] );
1184         
1185         hash.bv_val = lmhash;
1186         hash.bv_len = 32;
1187         
1188         return pw_string( scheme, &hash );
1189 }
1190 #endif /* SLAPD_LMHASH */
1191
1192 #ifdef SLAPD_CRYPT
1193 static struct berval *hash_crypt(
1194         const struct pw_scheme *scheme,
1195         const struct berval *passwd )
1196 {
1197         struct berval hash;
1198         unsigned char salt[32]; /* salt suitable for most anything */
1199         int i;
1200
1201         for( i=0; i<passwd->bv_len; i++) {
1202                 if(passwd->bv_val[i] == '\0') {
1203                         return NULL;    /* NUL character in password */
1204                 }
1205         }
1206
1207         if( passwd->bv_val[i] != '\0' ) {
1208                 return NULL;    /* passwd must behave like a string */
1209         }
1210
1211         if( lutil_entropy( salt, sizeof( salt ) ) < 0 ) {
1212                 return NULL; 
1213         }
1214
1215         for( i=0; i< ( sizeof(salt) - 1 ); i++ ) {
1216                 salt[i] = crypt64[ salt[i] % (sizeof(crypt64)-1) ];
1217         }
1218         salt[sizeof( salt ) - 1 ] = '\0';
1219
1220         if( salt_format != NULL ) {
1221                 /* copy the salt we made into entropy before snprintfing
1222                    it back into the salt */
1223                 char entropy[sizeof(salt)];
1224                 strcpy( entropy, salt );
1225                 snprintf( salt, sizeof(entropy), salt_format, entropy );
1226         }
1227
1228         hash.bv_val = crypt( passwd->bv_val, salt );
1229
1230         if( hash.bv_val == NULL ) return NULL;
1231
1232         hash.bv_len = strlen( hash.bv_val );
1233
1234         if( hash.bv_len == 0 ) {
1235                 return NULL;
1236         }
1237
1238         return pw_string( scheme, &hash );
1239 }
1240 #endif
1241
1242 int lutil_salt_format(const char *format)
1243 {
1244 #ifdef SLAPD_CRYPT
1245         free( salt_format );
1246
1247         salt_format = format != NULL ? strdup( format ) : NULL;
1248 #endif
1249
1250         return 0;
1251 }