3 * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
7 * lutil_password(credentials, password)
9 * Returns true if user supplied credentials matches
10 * the stored password.
12 * Due to the use of the crypt(3) function
13 * this routine is NOT thread-safe.
19 #include <ac/stdlib.h>
21 #include <ac/string.h>
22 #include <ac/unistd.h>
27 #include "lutil_md5.h"
28 #include "lutil_sha1.h"
38 static const unsigned char crypt64[] =
39 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
43 typedef int (*PASSWD_CHK_FUNC)(
44 const struct pw_scheme *scheme,
45 const struct berval *passwd,
46 const struct berval *cred );
48 typedef struct berval * (*PASSWD_HASH_FUNC) (
49 const struct pw_scheme *scheme,
50 const struct berval *passwd );
54 PASSWD_CHK_FUNC chk_fn;
55 PASSWD_HASH_FUNC hash_fn;
58 /* password check routines */
60 const struct pw_scheme *scheme,
61 const struct berval *passwd,
62 const struct berval *cred );
65 const struct pw_scheme *scheme,
66 const struct berval *passwd,
67 const struct berval *cred );
70 const struct pw_scheme *scheme,
71 const struct berval *passwd,
72 const struct berval *cred );
75 const struct pw_scheme *scheme,
76 const struct berval *passwd,
77 const struct berval *cred );
80 const struct pw_scheme *scheme,
81 const struct berval *passwd,
82 const struct berval *cred );
85 const struct pw_scheme *scheme,
86 const struct berval *passwd,
87 const struct berval *cred );
90 /* password hash routines */
91 static struct berval *hash_sha1(
92 const struct pw_scheme *scheme,
93 const struct berval *passwd );
95 static struct berval *hash_ssha1(
96 const struct pw_scheme *scheme,
97 const struct berval *passwd );
99 static struct berval *hash_smd5(
100 const struct pw_scheme *scheme,
101 const struct berval *passwd );
103 static struct berval *hash_md5(
104 const struct pw_scheme *scheme,
105 const struct berval *passwd );
107 static struct berval *hash_crypt(
108 const struct pw_scheme *scheme,
109 const struct berval *passwd );
112 static const struct pw_scheme pw_schemes[] =
114 { {sizeof("{SSHA}")-1, "{SSHA}"}, chk_ssha1, hash_ssha1 },
115 { {sizeof("{SHA}")-1, "{SHA}"}, chk_sha1, hash_sha1 },
117 { {sizeof("{SMD5}")-1, "{SMD5}"}, chk_smd5, hash_smd5 },
118 { {sizeof("{MD5}")-1, "{MD5}"}, chk_md5, hash_md5 },
121 { {sizeof("{CRYPT}")-1, "{CRYPT}"}, chk_crypt, hash_crypt },
123 # if defined( HAVE_GETSPNAM ) \
124 || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
125 { {sizeof("{UNIX}")-1, "{UNIX}"}, chk_unix, NULL },
128 #ifdef SLAPD_CLEARTEXT
130 { {0, "{CLEARTEXT}"}, NULL, NULL },
133 { {0, NULL}, NULL, NULL }
136 static const struct pw_scheme *get_scheme(
141 for( i=0; pw_schemes[i].name.bv_val; i++) {
142 if( pw_schemes[i].name.bv_len == 0 ) continue;
144 if( strncasecmp(scheme, pw_schemes[i].name.bv_val,
145 pw_schemes[i].name.bv_len) == 0 )
147 return &pw_schemes[i];
154 int lutil_passwd_scheme(
157 if( scheme == NULL ) {
161 return get_scheme(scheme) != NULL;
165 static int is_allowed_scheme(
167 const char** schemes )
171 if( schemes == NULL ) return 1;
173 for( i=0; schemes[i] != NULL; i++ ) {
174 if( strcasecmp( scheme, schemes[i] ) == 0 ) {
181 static struct berval *passwd_scheme(
182 const struct pw_scheme *scheme,
183 const struct berval * passwd,
184 const char** allowed )
186 if( !is_allowed_scheme( scheme->name.bv_val, allowed ) ) {
190 if( passwd->bv_len >= scheme->name.bv_len ) {
191 if( strncasecmp( passwd->bv_val, scheme->name.bv_val, scheme->name.bv_len ) == 0 ) {
192 struct berval *bv = ber_memalloc( sizeof(struct berval) );
194 if( bv == NULL ) return NULL;
196 bv->bv_val = &passwd->bv_val[scheme->name.bv_len];
197 bv->bv_len = passwd->bv_len - scheme->name.bv_len;
207 * Return 0 if creds are good.
211 const struct berval *passwd, /* stored passwd */
212 const struct berval *cred, /* user cred */
213 const char **schemes )
217 if (cred == NULL || cred->bv_len == 0 ||
218 passwd == NULL || passwd->bv_len == 0 )
223 for( i=0; pw_schemes[i].name.bv_val != NULL; i++ ) {
224 if( pw_schemes[i].chk_fn ) {
225 struct berval *p = passwd_scheme( &pw_schemes[i],
229 int rc = (pw_schemes[i].chk_fn)( &pw_schemes[i], p, cred );
231 /* only free the berval structure as the bv_val points
232 * into passwd->bv_val
241 #ifdef SLAPD_CLEARTEXT
242 if( is_allowed_scheme("{CLEARTEXT}", schemes ) ) {
243 return passwd->bv_len == cred->bv_len
244 ? memcmp( passwd->bv_val, cred->bv_val, passwd->bv_len )
253 struct berval * lutil_passwd_generate( ber_len_t len )
257 if( len < 1 ) return NULL;
259 pw = ber_memalloc( sizeof( struct berval ) );
260 if( pw == NULL ) return NULL;
263 pw->bv_val = ber_memalloc( len + 1 );
265 if( pw->bv_val == NULL ) {
270 if( lutil_entropy( pw->bv_val, pw->bv_len) < 0 ) {
275 for( len = 0; len < pw->bv_len; len++ ) {
276 pw->bv_val[len] = crypt64[
277 pw->bv_val[len] % (sizeof(crypt64)-1) ];
280 pw->bv_val[len] = '\0';
285 struct berval * lutil_passwd_hash(
286 const struct berval * passwd,
287 const char * method )
289 const struct pw_scheme *sc = get_scheme( method );
291 if( sc == NULL ) return NULL;
292 if( ! sc->hash_fn ) return NULL;
294 return (sc->hash_fn)( sc, passwd );
297 static struct berval * pw_string(
298 const struct pw_scheme *sc,
299 const struct berval *passwd )
301 struct berval *pw = ber_memalloc( sizeof( struct berval ) );
302 if( pw == NULL ) return NULL;
304 pw->bv_len = sc->name.bv_len + passwd->bv_len;
305 pw->bv_val = ber_memalloc( pw->bv_len + 1 );
307 if( pw->bv_val == NULL ) {
312 memcpy( pw->bv_val, sc->name.bv_val, sc->name.bv_len );
313 memcpy( &pw->bv_val[sc->name.bv_len], passwd->bv_val, passwd->bv_len );
315 pw->bv_val[pw->bv_len] = '\0';
319 static struct berval * pw_string64(
320 const struct pw_scheme *sc,
321 const struct berval *hash,
322 const struct berval *salt )
325 struct berval string;
326 struct berval *b64 = ber_memalloc( sizeof(struct berval) );
329 if( b64 == NULL ) return NULL;
332 /* need to base64 combined string */
333 string.bv_len = hash->bv_len + salt->bv_len;
334 string.bv_val = ber_memalloc( string.bv_len + 1 );
336 if( string.bv_val == NULL ) {
341 memcpy( string.bv_val, hash->bv_val,
343 memcpy( &string.bv_val[hash->bv_len], salt->bv_val,
345 string.bv_val[string.bv_len] = '\0';
351 b64len = LUTIL_BASE64_ENCODE_LEN( string.bv_len ) + 1;
352 b64->bv_len = b64len + sc->name.bv_len;
353 b64->bv_val = ber_memalloc( b64->bv_len + 1 );
355 if( b64->bv_val == NULL ) {
356 if( salt ) ber_memfree( string.bv_val );
361 memcpy(b64->bv_val, sc->name.bv_val, sc->name.bv_len);
364 string.bv_val, string.bv_len,
365 &b64->bv_val[sc->name.bv_len], b64len );
367 b64->bv_val[b64->bv_len] = '\0';
369 if( salt ) ber_memfree( string.bv_val );
379 /* PASSWORD CHECK ROUTINES */
381 static int chk_ssha1(
382 const struct pw_scheme *sc,
383 const struct berval * passwd,
384 const struct berval * cred )
386 lutil_SHA1_CTX SHA1context;
387 unsigned char SHA1digest[LUTIL_SHA1_BYTES];
389 unsigned char *orig_pass = NULL;
391 /* base64 un-encode password */
392 orig_pass = (unsigned char *) ber_memalloc( (size_t) (
393 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
395 if( orig_pass == NULL ) return -1;
397 rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
400 ber_memfree(orig_pass);
404 /* hash credentials with salt */
405 lutil_SHA1Init(&SHA1context);
406 lutil_SHA1Update(&SHA1context,
407 (const unsigned char *) cred->bv_val, cred->bv_len);
408 lutil_SHA1Update(&SHA1context,
409 (const unsigned char *) &orig_pass[sizeof(SHA1digest)],
410 rc - sizeof(SHA1digest));
411 lutil_SHA1Final(SHA1digest, &SHA1context);
414 rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
415 ber_memfree(orig_pass);
420 const struct pw_scheme *sc,
421 const struct berval * passwd,
422 const struct berval * cred )
424 lutil_SHA1_CTX SHA1context;
425 unsigned char SHA1digest[LUTIL_SHA1_BYTES];
427 unsigned char *orig_pass = NULL;
429 /* base64 un-encode password */
430 orig_pass = (unsigned char *) ber_memalloc( (size_t) (
431 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
433 if( orig_pass == NULL ) return -1;
435 rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
437 if( rc != sizeof(SHA1digest) ) {
438 ber_memfree(orig_pass);
442 /* hash credentials with salt */
443 lutil_SHA1Init(&SHA1context);
444 lutil_SHA1Update(&SHA1context,
445 (const unsigned char *) cred->bv_val, cred->bv_len);
446 lutil_SHA1Final(SHA1digest, &SHA1context);
449 rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
450 ber_memfree(orig_pass);
455 const struct pw_scheme *sc,
456 const struct berval * passwd,
457 const struct berval * cred )
459 lutil_MD5_CTX MD5context;
460 unsigned char MD5digest[LUTIL_MD5_BYTES];
462 unsigned char *orig_pass = NULL;
464 /* base64 un-encode password */
465 orig_pass = (unsigned char *) ber_memalloc( (size_t) (
466 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
468 if( orig_pass == NULL ) return -1;
470 rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
472 ber_memfree(orig_pass);
476 /* hash credentials with salt */
477 lutil_MD5Init(&MD5context);
478 lutil_MD5Update(&MD5context,
479 (const unsigned char *) cred->bv_val, cred->bv_len );
480 lutil_MD5Update(&MD5context,
481 (const unsigned char *) &orig_pass[sizeof(MD5digest)],
482 rc - sizeof(MD5digest));
483 lutil_MD5Final(MD5digest, &MD5context);
486 rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
487 ber_memfree(orig_pass);
492 const struct pw_scheme *sc,
493 const struct berval * passwd,
494 const struct berval * cred )
496 lutil_MD5_CTX MD5context;
497 unsigned char MD5digest[LUTIL_MD5_BYTES];
499 unsigned char *orig_pass = NULL;
501 /* base64 un-encode password */
502 orig_pass = (unsigned char *) ber_memalloc( (size_t) (
503 LUTIL_BASE64_DECODE_LEN(passwd->bv_len) + 1) );
505 if( orig_pass == NULL ) return -1;
507 rc = lutil_b64_pton(passwd->bv_val, orig_pass, passwd->bv_len);
508 if ( rc != sizeof(MD5digest) ) {
509 ber_memfree(orig_pass);
513 /* hash credentials with salt */
514 lutil_MD5Init(&MD5context);
515 lutil_MD5Update(&MD5context,
516 (const unsigned char *) cred->bv_val, cred->bv_len );
517 lutil_MD5Final(MD5digest, &MD5context);
520 rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
521 ber_memfree(orig_pass);
526 static int chk_crypt(
527 const struct pw_scheme *sc,
528 const struct berval * passwd,
529 const struct berval * cred )
533 for( i=0; i<cred->bv_len; i++) {
534 if(cred->bv_val[i] == '\0') {
535 return 1; /* NUL character in password */
539 if( cred->bv_val[i] != '\0' ) {
540 return 1; /* cred must behave like a string */
543 for( i=0; i<passwd->bv_len; i++) {
544 if(passwd->bv_val[i] == '\0') {
545 return 1; /* NUL character in password */
549 if( passwd->bv_val[i] != '\0' ) {
550 return 1; /* passwd must behave like a string */
553 return strcmp(passwd->bv_val, crypt(cred->bv_val, passwd->bv_val));
556 # if defined( HAVE_GETSPNAM ) \
557 || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
559 const struct pw_scheme *sc,
560 const struct berval * passwd,
561 const struct berval * cred )
566 for( i=0; i<cred->bv_len; i++) {
567 if(cred->bv_val[i] == '\0') {
568 return 1; /* NUL character in password */
571 if( cred->bv_val[i] != '\0' ) {
572 return 1; /* cred must behave like a string */
575 for( i=0; i<passwd->bv_len; i++) {
576 if(passwd->bv_val[i] == '\0') {
577 return 1; /* NUL character in password */
581 if( passwd->bv_val[i] != '\0' ) {
582 return 1; /* passwd must behave like a string */
585 # ifdef HAVE_GETSPNAM
587 struct spwd *spwd = getspnam(passwd->bv_val);
590 return 1; /* not found */
598 struct passwd *pwd = getpwnam(passwd->bv_val);
601 return 1; /* not found */
608 if( pw == NULL || *pw == '\0' ) return 1;
610 return strcmp(pw, crypt(cred->bv_val, pw));
616 /* PASSWORD CHECK ROUTINES */
617 static struct berval *hash_ssha1(
618 const struct pw_scheme *scheme,
619 const struct berval *passwd )
621 lutil_SHA1_CTX SHA1context;
622 unsigned char SHA1digest[LUTIL_SHA1_BYTES];
623 unsigned char saltdata[4];
624 struct berval digest;
627 digest.bv_val = SHA1digest;
628 digest.bv_len = sizeof(SHA1digest);
629 salt.bv_val = saltdata;
630 salt.bv_len = sizeof(saltdata);
632 if( lutil_entropy( salt.bv_val, salt.bv_len) < 0 ) {
636 lutil_SHA1Init( &SHA1context );
637 lutil_SHA1Update( &SHA1context,
638 (const unsigned char *)passwd->bv_val, passwd->bv_len );
639 lutil_SHA1Update( &SHA1context,
640 (const unsigned char *)salt.bv_val, salt.bv_len );
641 lutil_SHA1Final( SHA1digest, &SHA1context );
643 return pw_string64( scheme, &digest, &salt);
646 static struct berval *hash_sha1(
647 const struct pw_scheme *scheme,
648 const struct berval *passwd )
650 lutil_SHA1_CTX SHA1context;
651 unsigned char SHA1digest[20];
652 struct berval digest;
653 digest.bv_val = SHA1digest;
654 digest.bv_len = sizeof(SHA1digest);
656 lutil_SHA1Init( &SHA1context );
657 lutil_SHA1Update( &SHA1context,
658 (const unsigned char *)passwd->bv_val, passwd->bv_len );
659 lutil_SHA1Final( SHA1digest, &SHA1context );
661 return pw_string64( scheme, &digest, NULL);
664 static struct berval *hash_smd5(
665 const struct pw_scheme *scheme,
666 const struct berval *passwd )
668 lutil_MD5_CTX MD5context;
669 unsigned char MD5digest[16];
670 unsigned char saltdata[4];
671 struct berval digest;
674 digest.bv_val = MD5digest;
675 digest.bv_len = sizeof(MD5digest);
676 salt.bv_val = saltdata;
677 salt.bv_len = sizeof(saltdata);
679 if( lutil_entropy( salt.bv_val, salt.bv_len) < 0 ) {
683 lutil_MD5Init( &MD5context );
684 lutil_MD5Update( &MD5context,
685 (const unsigned char *) passwd->bv_val, passwd->bv_len );
686 lutil_MD5Update( &MD5context,
687 (const unsigned char *) salt.bv_val, salt.bv_len );
688 lutil_MD5Final( MD5digest, &MD5context );
690 return pw_string64( scheme, &digest, &salt );
693 static struct berval *hash_md5(
694 const struct pw_scheme *scheme,
695 const struct berval *passwd )
697 lutil_MD5_CTX MD5context;
698 unsigned char MD5digest[16];
700 struct berval digest;
702 digest.bv_val = MD5digest;
703 digest.bv_len = sizeof(MD5digest);
705 lutil_MD5Init( &MD5context );
706 lutil_MD5Update( &MD5context,
707 (const unsigned char *) passwd->bv_val, passwd->bv_len );
708 lutil_MD5Final( MD5digest, &MD5context );
710 return pw_string64( scheme, &digest, NULL );
715 static struct berval *hash_crypt(
716 const struct pw_scheme *scheme,
717 const struct berval *passwd )
720 unsigned char salt[3];
723 for( i=0; i<passwd->bv_len; i++) {
724 if(passwd->bv_val[i] == '\0') {
725 return NULL; /* NUL character in password */
729 if( passwd->bv_val[i] != '\0' ) {
730 return NULL; /* passwd must behave like a string */
733 if( lutil_entropy( salt, sizeof(salt)) < 0 ) {
737 salt[0] = crypt64[ salt[0] % (sizeof(crypt64)-1) ];
738 salt[1] = crypt64[ salt[1] % (sizeof(crypt64)-1) ];
741 hash.bv_val = crypt( passwd->bv_val, salt );
743 if( hash.bv_val = NULL ) return NULL;
744 hash.bv_len = strlen( hash.bv_val );
746 return pw_string( scheme, &hash );