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.
18 #include <ac/stdlib.h>
20 #include <ac/string.h>
21 #include <ac/unistd.h>
26 #include "lutil_md5.h"
27 #include "lutil_sha1.h"
39 typedef int (*PASSWD_CHK_FUNC)(
40 const struct pw_scheme *scheme,
44 typedef char * (*PASSWD_GEN_FUNC) (
45 const struct pw_scheme *scheme,
51 PASSWD_CHK_FUNC chk_fn;
52 PASSWD_GEN_FUNC gen_fn;
55 /* password check routines */
57 const struct pw_scheme *scheme,
62 const struct pw_scheme *scheme,
67 const struct pw_scheme *scheme,
72 const struct pw_scheme *scheme,
77 const struct pw_scheme *scheme,
82 const struct pw_scheme *scheme,
87 /* password generation routines */
88 static char *gen_sha1(
89 const struct pw_scheme *scheme,
92 static char *gen_ssha1(
93 const struct pw_scheme *scheme,
96 static char *gen_smd5(
97 const struct pw_scheme *scheme,
100 static char *gen_md5(
101 const struct pw_scheme *scheme,
102 const char *passwd );
104 static char *gen_crypt(
105 const struct pw_scheme *scheme,
106 const char *passwd );
109 static const struct pw_scheme pw_schemes[] =
111 { "{SSHA}", sizeof("{SSHA}")-1, chk_ssha1, gen_ssha1 },
112 { "{SHA}", sizeof("{SHA}")-1, chk_sha1, gen_sha1 },
114 { "{SMD5}", sizeof("{SMD5}")-1, chk_smd5, gen_smd5 },
115 { "{MD5}", sizeof("{MD5}")-1, chk_md5, gen_md5 },
118 { "{CRYPT}", sizeof("{CRYPT}")-1, chk_crypt, gen_crypt },
120 # if defined( HAVE_GETSPNAM ) \
121 || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
122 { "{UNIX}", sizeof("{UNIX}")-1, chk_unix, NULL },
125 #ifdef SLAPD_CLEARTEXT
127 { "{CLEARTEXT}", 0, NULL, NULL },
133 static const struct pw_scheme *get_scheme(
138 for( i=0; pw_schemes[i].name != NULL; i++) {
139 if( pw_schemes[i].namelen == 0 ) continue;
141 if( strncasecmp(scheme, pw_schemes[i].name,
142 pw_schemes[i].namelen) == 0 )
144 return &pw_schemes[i];
152 static int is_allowed_scheme(
154 const char** schemes )
158 if( schemes == NULL ) return 1;
160 for( i=0; schemes[i] != NULL; i++ ) {
161 if( strcasecmp( scheme, schemes[i] ) == 0 ) {
168 static const char *passwd_scheme(
169 const struct pw_scheme *scheme,
171 const char** allowed )
173 if( !is_allowed_scheme( scheme->name, allowed ) ) {
177 if( strncasecmp( passwd, scheme->name, scheme->namelen ) == 0 ) {
178 return &passwd[scheme->namelen];
185 * Return 0 if creds are good.
189 const char *passwd, /* stored passwd */
190 const char *cred, /* user cred */
191 const char **schemes )
195 if (cred == NULL || passwd == NULL) {
199 for( i=0; pw_schemes[i].name != NULL; i++ ) {
200 if( pw_schemes[i].chk_fn ) {
201 const char *p = passwd_scheme( &pw_schemes[i],
205 return (pw_schemes[i].chk_fn)( &pw_schemes[i], p, cred );
210 #ifdef SLAPD_CLEARTEXT
211 if( is_allowed_scheme("{CLEARTEXT}", schemes ) ) {
212 return strcmp( cred, passwd );
220 char * lutil_passwd_generate(
222 const char * method )
224 const struct pw_scheme *sc = get_scheme( method );
226 if( sc == NULL ) return NULL;
227 if( ! sc->gen_fn ) return NULL;
229 return (sc->gen_fn)( sc, passwd );
232 static char * pw_string(
233 const struct pw_scheme *sc,
236 size_t pwlen = strlen( passwd );
237 char *pw = ber_memalloc( sc->namelen + pwlen + 1 );
239 if( pw == NULL ) return NULL;
241 memcpy( pw, sc->name, sc->namelen );
242 memcpy( &pw[sc->namelen], passwd, pwlen );
243 pw[sc->namelen + pwlen] = '\0';
248 static char * pw_string64(
249 const struct pw_scheme *sc,
250 const unsigned char *hash, size_t hashlen,
251 const unsigned char *salt, size_t saltlen )
256 size_t len = hashlen + saltlen;
260 /* need to base64 combined string */
261 string = ber_memalloc( hashlen + saltlen );
263 if( string == NULL ) {
267 memcpy( string, hash, len );
268 memcpy( &string[len], salt, saltlen );
271 string = (char *) hash;
274 b64len = LUTIL_BASE64_ENCODE_LEN( len ) + 1;
275 b64 = ber_memalloc( b64len + sc->namelen );
278 if( saltlen ) ber_memfree( string );
282 memcpy(b64, sc->name, sc->namelen);
284 rc = lutil_b64_ntop( string, len, &b64[sc->namelen], b64len );
286 if( saltlen ) ber_memfree( string );
296 /* PASSWORD CHECK ROUTINES */
298 static int chk_ssha1(
299 const struct pw_scheme *sc,
303 lutil_SHA1_CTX SHA1context;
304 unsigned char SHA1digest[20];
305 int pw_len = strlen(passwd);
307 unsigned char *orig_pass = NULL;
309 /* base64 un-encode password */
310 orig_pass = (unsigned char *) malloc( (size_t) (
311 LUTIL_BASE64_DECODE_LEN(pw_len) + 1) );
313 if ((rc = lutil_b64_pton(passwd, orig_pass, pw_len)) < 0) {
318 /* hash credentials with salt */
319 lutil_SHA1Init(&SHA1context);
320 lutil_SHA1Update(&SHA1context,
321 (const unsigned char *) cred, strlen(cred));
322 lutil_SHA1Update(&SHA1context,
323 (const unsigned char *) &orig_pass[sizeof(SHA1digest)],
324 rc - sizeof(SHA1digest));
325 lutil_SHA1Final(SHA1digest, &SHA1context);
328 rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
334 const struct pw_scheme *sc,
338 lutil_SHA1_CTX SHA1context;
339 unsigned char SHA1digest[20];
340 char base64digest[LUTIL_BASE64_ENCODE_LEN(sizeof(SHA1digest))+1];
342 lutil_SHA1Init(&SHA1context);
343 lutil_SHA1Update(&SHA1context,
344 (const unsigned char *) cred, strlen(cred));
345 lutil_SHA1Final(SHA1digest, &SHA1context);
347 if (lutil_b64_ntop(SHA1digest, sizeof(SHA1digest),
348 base64digest, sizeof(base64digest)) < 0)
353 return strcmp(passwd, base64digest);
357 const struct pw_scheme *sc,
361 lutil_MD5_CTX MD5context;
362 unsigned char MD5digest[16];
363 int pw_len = strlen(passwd);
365 unsigned char *orig_pass = NULL;
367 /* base64 un-encode password */
368 orig_pass = (unsigned char *) malloc( (size_t) (
369 LUTIL_BASE64_DECODE_LEN(pw_len) + 1) );
371 if ((rc = lutil_b64_pton(passwd, orig_pass, pw_len)) < 0) {
376 /* hash credentials with salt */
377 lutil_MD5Init(&MD5context);
378 lutil_MD5Update(&MD5context,
379 (const unsigned char *) cred, strlen(cred));
380 lutil_MD5Update(&MD5context,
381 (const unsigned char *) &orig_pass[sizeof(MD5digest)],
382 rc - sizeof(MD5digest));
383 lutil_MD5Final(MD5digest, &MD5context);
386 rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
392 const struct pw_scheme *sc,
396 lutil_MD5_CTX MD5context;
397 unsigned char MD5digest[16];
398 char base64digest[LUTIL_BASE64_ENCODE_LEN(sizeof(MD5digest))+1];
400 lutil_MD5Init(&MD5context);
401 lutil_MD5Update(&MD5context,
402 (const unsigned char *)cred, strlen(cred));
403 lutil_MD5Final(MD5digest, &MD5context);
405 if ( lutil_b64_ntop(MD5digest, sizeof(MD5digest),
406 base64digest, sizeof(base64digest)) < 0 )
411 return strcmp(passwd, base64digest);
415 static int chk_crypt(
416 const struct pw_scheme *sc,
420 return strcmp(passwd, crypt(cred, passwd));
423 # if defined( HAVE_GETSPNAM ) \
424 || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
426 const struct pw_scheme *sc,
430 # ifdef HAVE_GETSPNAM
431 struct spwd *spwd = getspnam(p);
434 return 1; /* not found */
437 return strcmp(spwd->sp_pwdp, crypt(cred, spwd->sp_pwdp));
439 struct passwd *pwd = getpwnam(p);
442 return 1; /* not found */
445 return strcmp(pwd->pw_passwd, crypt(cred, pwd->pw_passwd));
451 /* PASSWORD CHECK ROUTINES */
452 static char *gen_ssha1(
453 const struct pw_scheme *scheme,
456 lutil_SHA1_CTX SHA1context;
457 unsigned char SHA1digest[20];
458 unsigned char salt[4];
460 if( lutil_entropy( salt, sizeof(salt)) < 0 ) {
464 lutil_SHA1Init( &SHA1context );
465 lutil_SHA1Update( &SHA1context,
466 (const unsigned char *)passwd, strlen(passwd) );
467 lutil_SHA1Update( &SHA1context,
468 (const unsigned char *)salt, sizeof(salt) );
469 lutil_SHA1Final( SHA1digest, &SHA1context );
471 return pw_string64( scheme,
472 SHA1digest, sizeof(SHA1digest),
476 static char *gen_sha1(
477 const struct pw_scheme *scheme,
480 lutil_SHA1_CTX SHA1context;
481 unsigned char SHA1digest[20];
483 lutil_SHA1Init( &SHA1context );
484 lutil_SHA1Update( &SHA1context,
485 (const unsigned char *)passwd, strlen(passwd) );
486 lutil_SHA1Final( SHA1digest, &SHA1context );
488 return pw_string64( scheme,
489 SHA1digest, sizeof(SHA1digest),
493 static char *gen_smd5(
494 const struct pw_scheme *scheme,
497 lutil_MD5_CTX MD5context;
498 unsigned char MD5digest[16];
499 unsigned char salt[4];
501 if( lutil_entropy( salt, sizeof(salt)) < 0 ) {
505 lutil_MD5Init( &MD5context );
506 lutil_MD5Update( &MD5context,
507 (const unsigned char *) passwd, strlen(passwd) );
509 lutil_MD5Update( &MD5context,
510 (const unsigned char *) salt, sizeof(salt) );
512 lutil_MD5Final( MD5digest, &MD5context );
514 return pw_string64( scheme,
515 MD5digest, sizeof(MD5digest),
516 salt, sizeof(salt) );
519 static char *gen_md5(
520 const struct pw_scheme *scheme,
523 lutil_MD5_CTX MD5context;
524 unsigned char MD5digest[16];
526 lutil_MD5Init( &MD5context );
527 lutil_MD5Update( &MD5context,
528 (const unsigned char *) passwd, strlen(passwd) );
530 lutil_MD5Final( MD5digest, &MD5context );
532 return pw_string64( scheme,
533 MD5digest, sizeof(MD5digest),
538 static char *gen_crypt(
539 const struct pw_scheme *scheme,
542 static const unsigned char crypt64[] =
543 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
546 unsigned char salt[2];
548 if( lutil_entropy( salt, sizeof(salt)) < 0 ) {
552 salt[0] = crypt64[ salt[0] % (sizeof(crypt64)-1) ];
553 salt[1] = crypt64[ salt[1] % (sizeof(crypt64)-1) ];
555 hash = crypt( passwd, salt );
557 if( hash = NULL ) return NULL;
559 return pw_string( scheme, hash );