3 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
7 * lutil_authpassword(authpasswd, cred)
9 * Returns true if user supplied credentials (cred) matches
10 * the stored authentication password (authpasswd).
12 * Due to the use of the crypt(3) function
13 * this routine is NOT thread-safe.
19 #include <ac/stdlib.h>
20 #include <ac/string.h>
29 #include <ac/unistd.h>
41 #include "lutil_md5.h"
42 #include "lutil_sha1.h"
45 static const unsigned char crypt64[] =
46 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
50 typedef int (*PASSWD_CHK_FUNC)(
51 const struct pw_scheme *scheme,
52 const struct berval *passwd,
53 const struct berval *salt,
54 const struct berval *cred );
56 typedef int (*PASSWD_HASH_FUNC) (
57 const struct pw_scheme *scheme,
58 const struct berval *cred,
59 const struct berval *salt,
60 struct berval **passwd_out,
61 struct berval **salt_out );
63 /* password check routines */
65 const struct pw_scheme *scheme,
66 const struct berval *passwd,
67 const struct berval *salt,
68 const struct berval *cred );
70 #ifdef LUTIL_SHA1_BYTES
72 const struct pw_scheme *scheme,
73 const struct berval *passwd,
74 const struct berval *salt,
75 const struct berval *cred );
79 const struct pw_scheme *scheme,
80 const struct berval *passwd,
81 const struct berval *salt,
82 const struct berval *cred );
85 const struct pw_scheme *scheme,
86 const struct berval *passwd,
87 const struct berval *salt,
88 const struct berval *cred );
90 static int chk_ext_kerberos(
91 const struct pw_scheme *scheme,
92 const struct berval *passwd,
93 const struct berval *cred );
95 static int chk_ext_unix(
96 const struct pw_scheme *scheme,
97 const struct berval *passwd,
98 const struct berval *cred );
100 #ifdef LUTIL_SHA1_BYTES
101 /* password hash routines */
102 static int *hash_sha1(
103 const struct pw_scheme *scheme,
104 const struct berval *cred,
105 const struct berval *salt,
106 struct berval **passwd_out,
107 struct berval **salt_out );
110 static int *hash_md5(
111 const struct pw_scheme *scheme,
112 const struct berval *cred,
113 const struct berval *salt,
114 struct berval **passwd_out,
115 struct berval **salt_out );
117 static int *hash_crypt(
118 const struct pw_scheme *scheme,
119 const struct berval *cred,
120 const struct berval *salt,
121 struct berval **passwd_out,
122 struct berval **salt_out );
127 PASSWD_CHK_FUNC chk_fn;
128 PASSWD_HASH_FUNC hash_fn;
132 static const struct pw_scheme pw_schemes[] =
134 #ifdef LUTIL_SHA1_BYTES
135 { {sizeof("SHA1")-1, "SHA1"}, chk_sha1, 0 /* hash_sha1 */, 4 },
137 { {sizeof("MD5")-1, "MD5"}, chk_md5, 0 /* hash_md5 */, 4 },
140 { {sizeof("CRYPT")-1, "CRYPT"}, chk_crypt, hash_crypt, 2 },
144 { {sizeof("EXTERNAL")-1, "EXTERNAL"}, chk_ext, NULL, 0 },
147 { {0, NULL}, NULL, NULL, 0 }
156 static const struct ext_scheme ext_schemes[] =
158 { {0, NULL}, NULL, NULL, 0 }
162 static const struct pw_scheme *get_scheme(
167 if( scheme == NULL || *scheme == '\0' ) return NULL;
169 for( i=0; pw_schemes[i].name.bv_val; i++) {
170 if( pw_schemes[i].name.bv_len == 0 ) continue;
172 if( strncasecmp( scheme,
173 pw_schemes[i].name.bv_val,
174 pw_schemes[i].name.bv_len) == 0 )
176 return &pw_schemes[i];
183 int lutil_authpasswd_scheme(
186 return get_scheme( scheme ) != NULL;
190 static int is_allowed_scheme(
192 const char** schemes )
196 if( scheme == NULL || *scheme == '\0' ) return 1;
198 for( i=0; schemes[i] != NULL; i++ ) {
199 if( strcasecmp( scheme, schemes[i] ) == 0 ) {
206 static int parse_authpasswd(
209 struct berval *passwd )
216 * Return 0 if creds are good.
220 const struct berval *value, /* stored authpasswd */
221 const struct berval *cred, /* user cred */
222 const char **schemes )
225 struct berval salt, passwd;
226 const struct pw_scheme *pws;
229 if (cred == NULL || cred->bv_len == 0 ||
230 value == NULL || value->bv_len == 0 )
235 rc = parse_authpasswd( &scheme, &salt, &passwd );
237 if( rc != 0 ) return -1;
239 if( !is_allowed_scheme( scheme, schemes ) ) {
243 pws = get_scheme( scheme );
245 if( pws == NULL || !pws->chk_fn ) {
249 rc = (pws->chk_fn)( pws, &salt, &passwd, cred );
252 if( scheme != NULL ) {
253 ber_memfree( scheme );
254 ber_memfree( salt.bv_val );
255 ber_memfree( passwd.bv_val );
261 struct berval * lutil_authpasswd_generate( ber_len_t len )
265 if( len < 1 ) return NULL;
267 pw = ber_memalloc( sizeof( struct berval ) );
268 if( pw == NULL ) return NULL;
271 pw->bv_val = ber_memalloc( len + 1 );
273 if( pw->bv_val == NULL ) {
278 if( lutil_entropy( pw->bv_val, pw->bv_len) < 0 ) {
283 for( len = 0; len < pw->bv_len; len++ ) {
284 pw->bv_val[len] = crypt64[
285 pw->bv_val[len] % (sizeof(crypt64)-1) ];
288 pw->bv_val[len] = '\0';
293 int lutil_authpasswd_hash(
294 const struct berval * cred,
295 struct berval ** passwd_out,
296 struct berval ** salt_out,
297 const char * method )
299 const struct pw_scheme *sc;
302 if( passwd_out == NULL ) return -1;
304 sc = get_scheme( method );
305 if( sc == NULL || !sc->hash_fn ) return -1;
307 if( sc->saltbytes && salt_out != NULL ) {
309 salt.bv_val = ber_memalloc( sc->saltbytes );
311 if( salt.bv_val == NULL ) {
314 salt.bv_len = sc->saltbytes;
316 if( lutil_entropy( salt.bv_val, salt.bv_len ) < 0 ) {
317 ber_memfree( salt.bv_val );
321 rc = (sc->hash_fn)( sc, cred, &salt, passwd_out, NULL );
322 ber_memfree( salt.bv_val );
324 } else if ( sc->saltbytes ) {
325 /* wants salt, disallow */
329 rc = (sc->hash_fn)( sc, cred, NULL, passwd_out, salt_out );
335 static struct berval * base64(
336 const struct berval *value )
341 assert( value != NULL );
343 if( value == NULL || value->bv_len == 0 ) return NULL;
345 b64 = ber_memalloc( sizeof(struct berval) );
346 if( b64 == NULL ) return NULL;
348 b64->bv_len = LUTIL_BASE64_ENCODE_LEN( value->bv_len );
349 b64->bv_val = ber_memalloc( b64->bv_len + 1 );
351 if( b64->bv_val == NULL ) {
357 value->bv_val, value->bv_len,
358 b64->bv_val, b64->bv_len );
360 b64->bv_val[b64->bv_len] = '\0';
370 /* PASSWORD CHECK ROUTINES */
372 #ifdef LUTIL_SHA1_BYTES
374 const struct pw_scheme *sc,
375 const struct berval * passwd,
376 const struct berval * salt,
377 const struct berval * cred )
379 lutil_SHA1_CTX SHA1context;
380 unsigned char SHA1digest[LUTIL_SHA1_BYTES];
382 unsigned char *orig_pass = NULL;
383 unsigned char *orig_salt = NULL;
386 if( passwd == NULL || passwd->bv_len == 0 ) {
390 /* decode base64 password */
391 orig_pass = (unsigned char *) ber_memalloc( (size_t) (
392 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
394 if( orig_pass == NULL ) {
399 rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
405 /* decode base64 salt */
406 if( salt != NULL && salt->bv_len > 0 ) {
407 orig_salt = (unsigned char *) ber_memalloc( (size_t) (
408 LUTIL_BASE64_DECODE_LEN(salt->bv_len) + 1) );
410 if( orig_salt == NULL ) {
415 saltlen = lutil_b64_pton(passwd->bv_val, orig_salt, passwd->bv_len);
422 /* hash credentials with salt */
423 lutil_SHA1Init(&SHA1context);
424 lutil_SHA1Update(&SHA1context,
425 (const unsigned char *) cred->bv_val, cred->bv_len);
426 if( orig_salt != NULL ) {
427 lutil_SHA1Update(&SHA1context,
428 orig_salt, saltlen );
430 lutil_SHA1Final(SHA1digest, &SHA1context);
433 rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
436 ber_memfree(orig_pass);
437 ber_memfree(orig_salt);
443 const struct pw_scheme *sc,
444 const struct berval * passwd,
445 const struct berval * salt,
446 const struct berval * cred )
448 lutil_MD5_CTX MD5context;
449 unsigned char MD5digest[LUTIL_MD5_BYTES];
451 unsigned char *orig_pass = NULL;
452 unsigned char *orig_salt = NULL;
455 if( passwd == NULL || passwd->bv_len == 0 ) {
459 /* decode base64 password */
460 orig_pass = (unsigned char *) ber_memalloc( (size_t) (
461 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
463 if( orig_pass == NULL ) {
468 rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
474 /* decode base64 salt */
475 if( salt != NULL && salt->bv_len > 0 ) {
476 orig_salt = (unsigned char *) ber_memalloc( (size_t) (
477 LUTIL_BASE64_DECODE_LEN(salt->bv_len) + 1) );
479 if( orig_salt == NULL ) {
484 saltlen = lutil_b64_pton(passwd->bv_val, orig_salt, passwd->bv_len);
491 /* hash credentials with salt */
492 lutil_MD5Init(&MD5context);
493 lutil_MD5Update(&MD5context,
494 (const unsigned char *) cred->bv_val, cred->bv_len);
495 if( orig_salt != NULL ) {
496 lutil_MD5Update(&MD5context,
497 orig_salt, saltlen );
499 lutil_MD5Final(MD5digest, &MD5context);
502 rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
505 ber_memfree(orig_pass);
506 ber_memfree(orig_salt);
511 static int chk_kerberos(
512 const struct pw_scheme *sc,
513 const struct berval * passwd,
514 const struct berval * cred,
515 const struct berval * salt )
520 for( i=0; i<cred->bv_len; i++) {
521 if(cred->bv_val[i] == '\0') {
522 return 1; /* NUL character in password */
526 if( cred->bv_val[i] != '\0' ) {
527 return 1; /* cred must behave like a string */
530 for( i=0; i<passwd->bv_len; i++) {
531 if(passwd->bv_val[i] == '\0') {
532 return 1; /* NUL character in password */
536 if( passwd->bv_val[i] != '\0' ) {
537 return 1; /* passwd must behave like a string */
542 #ifdef HAVE_KRB5 /* HAVE_HEIMDAL_KRB5 */
545 * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H\xf6gskolan
546 * (Royal Institute of Technology, Stockholm, Sweden).
547 * All rights reserved.
549 * Redistribution and use in source and binary forms, with or without
550 * modification, are permitted provided that the following conditions
553 * 1. Redistributions of source code must retain the above copyright
554 * notice, this list of conditions and the following disclaimer.
556 * 2. Redistributions in binary form must reproduce the above copyright
557 * notice, this list of conditions and the following disclaimer in the
558 * documentation and/or other materials provided with the distribution.
560 * 3. Neither the name of the Institute nor the names of its contributors
561 * may be used to endorse or promote products derived from this software
562 * without specific prior written permission.
564 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
565 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
566 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
567 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
568 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
569 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
570 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
571 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
572 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
573 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
577 krb5_context context;
580 krb5_get_init_creds_opt get_options;
581 krb5_verify_init_creds_opt verify_options;
582 krb5_principal client, server;
584 krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP};
587 ret = krb5_init_context( &context );
593 krb5_get_init_creds_opt_set_preauth_list(&get_options,
597 krb5_get_init_creds_opt_init( &get_options );
599 krb5_verify_init_creds_opt_init( &verify_options );
601 ret = krb5_parse_name( context, passwd->bv_val, &client );
604 krb5_free_context( context );
608 ret = krb5_get_init_creds_password( context,
609 &creds, client, cred->bv_val, NULL,
610 NULL, 0, NULL, &get_options );
613 krb5_free_principal( context, client );
614 krb5_free_context( context );
619 char *host = ldap_pvt_get_fqdn( NULL );
622 krb5_free_principal( context, client );
623 krb5_free_context( context );
627 ret = krb5_sname_to_principal( context,
628 host, "ldap", KRB5_NT_SRV_HST, &server );
634 krb5_free_principal( context, client );
635 krb5_free_context( context );
639 ret = krb5_verify_init_creds( context,
640 &creds, server, NULL, NULL, &verify_options );
642 krb5_free_principal( context, client );
643 krb5_free_principal( context, server );
644 krb5_free_creds_contents( context, &creds );
645 krb5_free_context( context );
649 #elif defined(HAVE_KRB4)
651 /* Borrowed from Heimdal kpopper */
653 * Copyright (c) 1989 Regents of the University of California.
654 * All rights reserved. The Berkeley software License Agreement
655 * specifies the terms and conditions for redistribution.
659 char lrealm[REALM_SZ];
660 char tkt[MAXHOSTNAMELEN];
662 status = krb_get_lrealm(lrealm,1);
663 if (status == KFAILURE) {
667 snprintf(tkt, sizeof(tkt), "%s_slapd.%u",
668 TKT_ROOT, (unsigned)getpid());
669 krb_set_tkt_string (tkt);
671 status = krb_verify_user( passwd->bv_val, "", lrealm,
672 cred->bv_val, 1, "ldap");
674 dest_tkt(); /* no point in keeping the tickets */
676 return status == KFAILURE;
682 #endif /* SLAPD_KPASSWD */
685 static int chk_crypt(
686 const struct pw_scheme *sc,
687 const struct berval * passwd,
688 const struct berval * cred )
693 for( i=0; i<cred->bv_len; i++) {
694 if(cred->bv_val[i] == '\0') {
695 return 1; /* NUL character in password */
699 if( cred->bv_val[i] != '\0' ) {
700 return 1; /* cred must behave like a string */
703 if( passwd->bv_len < 2 ) {
704 return 1; /* passwd must be at least two characters long */
707 for( i=0; i<passwd->bv_len; i++) {
708 if(passwd->bv_val[i] == '\0') {
709 return 1; /* NUL character in password */
713 if( passwd->bv_val[i] != '\0' ) {
714 return 1; /* passwd must behave like a string */
717 cr = crypt( cred->bv_val, passwd->bv_val );
719 if( cr == NULL || cr[0] == '\0' ) {
720 /* salt must have been invalid */
724 return strcmp( passwd->bv_val, cr );
727 # if defined( HAVE_GETSPNAM ) \
728 || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
730 const struct pw_scheme *sc,
731 const struct berval * passwd,
732 const struct berval * cred )
737 for( i=0; i<cred->bv_len; i++) {
738 if(cred->bv_val[i] == '\0') {
739 return 1; /* NUL character in password */
742 if( cred->bv_val[i] != '\0' ) {
743 return 1; /* cred must behave like a string */
746 for( i=0; i<passwd->bv_len; i++) {
747 if(passwd->bv_val[i] == '\0') {
748 return 1; /* NUL character in password */
752 if( passwd->bv_val[i] != '\0' ) {
753 return 1; /* passwd must behave like a string */
756 # ifdef HAVE_GETSPNAM
758 struct spwd *spwd = getspnam(passwd->bv_val);
761 return 1; /* not found */
769 struct passwd *pwd = getpwnam(passwd->bv_val);
772 return 1; /* not found */
779 if( pw == NULL || pw[0] == '\0' || pw[1] == '\0' ) {
780 /* password must must be at least two characters long */
784 cr = crypt(cred->bv_val, pw);
786 if( cr == NULL || cr[0] == '\0' ) {
787 /* salt must have been invalid */
791 return strcmp(pw, cr);
797 /* PASSWORD GENERATION ROUTINES */
799 #ifdef SLAPD_GENERATE
801 #ifdef LUTIL_SHA1_BYTES
802 static struct berval *hash_ssha1(
803 const struct pw_scheme *scheme,
804 const struct berval *passwd )
806 lutil_SHA1_CTX SHA1context;
807 unsigned char SHA1digest[LUTIL_SHA1_BYTES];
808 unsigned char saltdata[4];
809 struct berval digest;
812 digest.bv_val = SHA1digest;
813 digest.bv_len = sizeof(SHA1digest);
814 salt.bv_val = saltdata;
815 salt.bv_len = sizeof(saltdata);
817 if( lutil_entropy( salt.bv_val, salt.bv_len) < 0 ) {
821 lutil_SHA1Init( &SHA1context );
822 lutil_SHA1Update( &SHA1context,
823 (const unsigned char *)passwd->bv_val, passwd->bv_len );
824 lutil_SHA1Update( &SHA1context,
825 (const unsigned char *)salt.bv_val, salt.bv_len );
826 lutil_SHA1Final( SHA1digest, &SHA1context );
828 return pw_string64( scheme, &digest, &salt);
831 static struct berval *hash_sha1(
832 const struct pw_scheme *scheme,
833 const struct berval *passwd )
835 lutil_SHA1_CTX SHA1context;
836 unsigned char SHA1digest[LUTIL_SHA1_BYTES];
837 struct berval digest;
838 digest.bv_val = SHA1digest;
839 digest.bv_len = sizeof(SHA1digest);
841 lutil_SHA1Init( &SHA1context );
842 lutil_SHA1Update( &SHA1context,
843 (const unsigned char *)passwd->bv_val, passwd->bv_len );
844 lutil_SHA1Final( SHA1digest, &SHA1context );
846 return pw_string64( scheme, &digest, NULL);
850 static struct berval *hash_smd5(
851 const struct pw_scheme *scheme,
852 const struct berval *passwd )
854 lutil_MD5_CTX MD5context;
855 unsigned char MD5digest[LUTIL_MD5_BYTES];
856 unsigned char saltdata[4];
857 struct berval digest;
860 digest.bv_val = MD5digest;
861 digest.bv_len = sizeof(MD5digest);
862 salt.bv_val = saltdata;
863 salt.bv_len = sizeof(saltdata);
865 if( lutil_entropy( salt.bv_val, salt.bv_len) < 0 ) {
869 lutil_MD5Init( &MD5context );
870 lutil_MD5Update( &MD5context,
871 (const unsigned char *) passwd->bv_val, passwd->bv_len );
872 lutil_MD5Update( &MD5context,
873 (const unsigned char *) salt.bv_val, salt.bv_len );
874 lutil_MD5Final( MD5digest, &MD5context );
876 return pw_string64( scheme, &digest, &salt );
879 static struct berval *hash_md5(
880 const struct pw_scheme *scheme,
881 const struct berval *passwd )
883 lutil_MD5_CTX MD5context;
884 unsigned char MD5digest[LUTIL_MD5_BYTES];
886 struct berval digest;
888 digest.bv_val = MD5digest;
889 digest.bv_len = sizeof(MD5digest);
891 lutil_MD5Init( &MD5context );
892 lutil_MD5Update( &MD5context,
893 (const unsigned char *) passwd->bv_val, passwd->bv_len );
894 lutil_MD5Final( MD5digest, &MD5context );
896 return pw_string64( scheme, &digest, NULL );
901 static struct berval *hash_crypt(
902 const struct pw_scheme *scheme,
903 const struct berval *passwd )
906 unsigned char salt[3];
909 for( i=0; i<passwd->bv_len; i++) {
910 if(passwd->bv_val[i] == '\0') {
911 return NULL; /* NUL character in password */
915 if( passwd->bv_val[i] != '\0' ) {
916 return NULL; /* passwd must behave like a string */
919 if( lutil_entropy( salt, sizeof(salt)) < 0 ) {
923 salt[0] = crypt64[ salt[0] % (sizeof(crypt64)-1) ];
924 salt[1] = crypt64[ salt[1] % (sizeof(crypt64)-1) ];
927 hash.bv_val = crypt( passwd->bv_val, salt );
929 if( hash.bv_val == NULL ) return NULL;
931 hash.bv_len = strlen( hash.bv_val );
933 if( hash.bv_len == 0 ) {
937 return pw_string( scheme, &hash );