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