From 2da2336ac69afd7ca3605d74c07b5c5d5ae15700 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Fri, 18 Mar 2005 06:06:38 +0000 Subject: [PATCH] Reorganiza SLAPD_CRYPT and SLAPD_SPASSWD support for better reentrancy --- include/lutil.h | 9 ++- libraries/liblutil/passwd.c | 124 ++++++++++-------------------------- servers/slapd/backend.c | 11 +--- servers/slapd/init.c | 7 +- servers/slapd/passwd.c | 83 +++++++++++++++--------- servers/slapd/proto-slap.h | 5 +- servers/slapd/sasl.c | 65 ++++++++++++++++++- 7 files changed, 164 insertions(+), 140 deletions(-) diff --git a/include/lutil.h b/include/lutil.h index ea2450c4a1..abfc595867 100644 --- a/include/lutil.h +++ b/include/lutil.h @@ -110,9 +110,12 @@ lutil_authpasswd_hash LDAP_P(( struct berval **salt, /* salt to store */ const char *method )); -#if defined( SLAPD_SPASSWD ) && defined( HAVE_CYRUS_SASL ) - /* cheat to avoid pulling in */ -LDAP_LUTIL_V( struct sasl_conn * ) lutil_passwd_sasl_conn; +#ifdef SLAPD_CRYPT +typedef int (lutil_cryptfunc) LDAP_P(( + const char *key, + const char *salt, + char **hash )); +LDAP_LUTIL_V (lutil_cryptfunc *) lutil_cryptptr; #endif LDAP_LUTIL_F( int ) diff --git a/libraries/liblutil/passwd.c b/libraries/liblutil/passwd.c index 8fe4673aad..5460b0376a 100644 --- a/libraries/liblutil/passwd.c +++ b/libraries/liblutil/passwd.c @@ -33,14 +33,6 @@ #include #include -#ifdef SLAPD_SPASSWD -# ifdef HAVE_SASL_SASL_H -# include -# else -# include -# endif -#endif - #if defined(SLAPD_LMHASH) # include #endif /* SLAPD_LMHASH */ @@ -77,6 +69,8 @@ static const unsigned char crypt64[] = #ifdef SLAPD_CRYPT static char *salt_format = NULL; +static lutil_cryptfunc lutil_crypt; +lutil_cryptfunc *lutil_cryptptr = lutil_crypt; #endif struct pw_scheme { @@ -112,10 +106,6 @@ static LUTIL_PASSWD_CHK_FUNC chk_lanman; static LUTIL_PASSWD_HASH_FUNC hash_lanman; #endif -#ifdef SLAPD_SPASSWD -static LUTIL_PASSWD_CHK_FUNC chk_sasl; -#endif - #ifdef SLAPD_CRYPT static LUTIL_PASSWD_CHK_FUNC chk_crypt; static LUTIL_PASSWD_HASH_FUNC hash_crypt; @@ -148,10 +138,6 @@ static const struct pw_scheme pw_schemes_default[] = { BER_BVC("{LANMAN}"), chk_lanman, hash_lanman }, #endif /* SLAPD_LMHASH */ -#ifdef SLAPD_SPASSWD - { BER_BVC("{SASL}"), chk_sasl, NULL }, -#endif - #ifdef SLAPD_CRYPT { BER_BVC("{CRYPT}"), chk_crypt, hash_crypt }, # if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) @@ -753,64 +739,29 @@ static int chk_lanman( } #endif /* SLAPD_LMHASH */ -#ifdef SLAPD_SPASSWD -#ifdef HAVE_CYRUS_SASL -sasl_conn_t *lutil_passwd_sasl_conn = NULL; -#endif - -static int chk_sasl( - const struct berval *sc, - const struct berval * passwd, - const struct berval * cred, - const char **text ) +#ifdef SLAPD_CRYPT +static int lutil_crypt( + const char *key, + const char *salt, + char **hash ) { - unsigned int i; - int rtn; - - for( i=0; ibv_len; i++) { - if(cred->bv_val[i] == '\0') { - return LUTIL_PASSWD_ERR; /* NUL character in password */ - } - } - - if( cred->bv_val[i] != '\0' ) { - return LUTIL_PASSWD_ERR; /* cred must behave like a string */ - } + char *cr = crypt( key, salt ); + int rc; - for( i=0; ibv_len; i++) { - if(passwd->bv_val[i] == '\0') { - return LUTIL_PASSWD_ERR; /* NUL character in password */ + if( cr == NULL || cr[0] == '\0' ) { + /* salt must have been invalid */ + rc = LUTIL_PASSWD_ERR; + } else { + if ( hash ) { + *hash = ber_strdup( cr ); + rc = LUTIL_PASSWD_OK; + } else { + rc = strcmp( salt, cr ) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; } } - - if( passwd->bv_val[i] != '\0' ) { - return LUTIL_PASSWD_ERR; /* passwd must behave like a string */ - } - - rtn = LUTIL_PASSWD_ERR; - -#ifdef HAVE_CYRUS_SASL - if( lutil_passwd_sasl_conn != NULL ) { - int sc; -# if SASL_VERSION_MAJOR < 2 - sc = sasl_checkpass( lutil_passwd_sasl_conn, - passwd->bv_val, passwd->bv_len, - cred->bv_val, cred->bv_len, - text ); -# else - sc = sasl_checkpass( lutil_passwd_sasl_conn, - passwd->bv_val, passwd->bv_len, - cred->bv_val, cred->bv_len ); -# endif - rtn = ( sc != SASL_OK ) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; - } -#endif - - return rtn; + return rc; } -#endif -#ifdef SLAPD_CRYPT static int chk_crypt( const struct berval *sc, const struct berval * passwd, @@ -819,6 +770,7 @@ static int chk_crypt( { char *cr; unsigned int i; + int rc; for( i=0; ibv_len; i++) { if(cred->bv_val[i] == '\0') { @@ -844,14 +796,7 @@ static int chk_crypt( return LUTIL_PASSWD_ERR; /* passwd must behave like a string */ } - cr = crypt( cred->bv_val, passwd->bv_val ); - - if( cr == NULL || cr[0] == '\0' ) { - /* salt must have been invalid */ - return LUTIL_PASSWD_ERR; - } - - return strcmp( passwd->bv_val, cr ) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; + return lutil_cryptptr( cred->bv_val, passwd->bv_val, NULL ); } # if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) @@ -916,15 +861,7 @@ static int chk_unix( return LUTIL_PASSWD_ERR; } - cr = crypt(cred->bv_val, pw); - - if( cr == NULL || cr[0] == '\0' ) { - /* salt must have been invalid */ - return LUTIL_PASSWD_ERR; - } - - return strcmp(pw, cr) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; - + return lutil_cryptptr( cred->bv_val, pw, NULL ); } # endif #endif @@ -1098,6 +1035,8 @@ static int hash_crypt( { unsigned char salt[32]; /* salt suitable for most anything */ unsigned int i; + char *save; + int rc; for( i=0; ibv_len; i++) { if(passwd->bv_val[i] == '\0') { @@ -1126,17 +1065,22 @@ static int hash_crypt( snprintf( (char *) salt, sizeof(entropy), salt_format, entropy ); } - hash->bv_val = crypt( passwd->bv_val, (char *) salt ); + rc = lutil_cryptptr( passwd->bv_val, (char *) salt, &hash->bv_val ); + if ( rc != LUTIL_PASSWD_OK ) return rc; if( hash->bv_val == NULL ) return -1; hash->bv_len = strlen( hash->bv_val ); + save = hash->bv_val; + if( hash->bv_len == 0 ) { - return LUTIL_PASSWD_ERR; + rc = LUTIL_PASSWD_ERR; + } else { + rc = pw_string( scheme, hash ); } - - return pw_string( scheme, hash ); + ber_memfree( save ); + return rc; } #endif @@ -1145,7 +1089,7 @@ int lutil_salt_format(const char *format) #ifdef SLAPD_CRYPT free( salt_format ); - salt_format = format != NULL ? strdup( format ) : NULL; + salt_format = format != NULL ? ber_strdup( format ) : NULL; #endif return 0; diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index f64e661ea7..1a0277f25c 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -747,20 +747,15 @@ be_isroot_pw( Operation *op ) return 0; } -#if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD ) - ldap_pvt_thread_mutex_lock( &passwd_mutex ); #ifdef SLAPD_SPASSWD - lutil_passwd_sasl_conn = op->o_conn->c_sasl_authctx; -#endif + ldap_pvt_thread_pool_setkey( op->o_threadctx, slap_sasl_bind, + op->o_conn->c_sasl_authctx, NULL ); #endif result = lutil_passwd( &op->o_bd->be_rootpw, &op->orb_cred, NULL, NULL ); -#if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD ) #ifdef SLAPD_SPASSWD - lutil_passwd_sasl_conn = NULL; -#endif - ldap_pvt_thread_mutex_unlock( &passwd_mutex ); + ldap_pvt_thread_pool_setkey( op->o_threadctx, slap_sasl_bind, NULL, NULL ); #endif return result == 0; diff --git a/servers/slapd/init.c b/servers/slapd/init.c index e606e3da9e..b711ef9840 100644 --- a/servers/slapd/init.c +++ b/servers/slapd/init.c @@ -68,9 +68,6 @@ int connection_pool_max = SLAP_MAX_WORKER_THREADS; #ifndef HAVE_GMTIME_R ldap_pvt_thread_mutex_t gmtime_mutex; #endif -#if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD ) -ldap_pvt_thread_mutex_t passwd_mutex; -#endif slap_counters_t slap_counters; @@ -139,9 +136,7 @@ slap_init( int mode, const char *name ) #ifndef HAVE_GMTIME_R ldap_pvt_thread_mutex_init( &gmtime_mutex ); #endif -#if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD ) - ldap_pvt_thread_mutex_init( &passwd_mutex ); -#endif + slap_passwd_init(); rc = slap_sasl_init(); diff --git a/servers/slapd/passwd.c b/servers/slapd/passwd.c index 265681c4a4..65710aaff5 100644 --- a/servers/slapd/passwd.c +++ b/servers/slapd/passwd.c @@ -23,6 +23,10 @@ #include #include +#ifdef SLAPD_CRYPT +#include +#endif + #include "slap.h" #include @@ -415,38 +419,30 @@ slap_passwd_check( struct berval *bv; AccessControlState acl_state = ACL_STATE_INIT; - for ( bv = a->a_vals; bv->bv_val != NULL; bv++ ) { - int rc; +#ifdef SLAPD_SPASSWD + ldap_pvt_thread_pool_setkey( op->o_threadctx, slap_sasl_bind, + op->o_conn->c_sasl_authctx, NULL ); +#endif + for ( bv = a->a_vals; bv->bv_val != NULL; bv++ ) { /* if e is provided, check access */ if ( e && access_allowed( op, e, a->a_desc, bv, ACL_AUTH, &acl_state ) == 0 ) { continue; } - -#if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD ) - ldap_pvt_thread_mutex_lock( &passwd_mutex ); -#ifdef SLAPD_SPASSWD - lutil_passwd_sasl_conn = op->o_conn->c_sasl_authctx; -#endif -#endif - - rc = lutil_passwd( bv, cred, NULL, text ); - -#if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD ) -#ifdef SLAPD_SPASSWD - lutil_passwd_sasl_conn = NULL; -#endif - ldap_pvt_thread_mutex_unlock( &passwd_mutex ); -#endif - - if ( !rc ) { + + if ( !lutil_passwd( bv, cred, NULL, text ) ) { result = 0; break; } } +#ifdef SLAPD_SPASSWD + ldap_pvt_thread_pool_setkey( op->o_threadctx, slap_sasl_bind, + NULL, NULL ); +#endif + return result; } @@ -476,16 +472,7 @@ slap_passwd_hash_type( assert( hash ); -#if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD ) - ldap_pvt_thread_mutex_lock( &passwd_mutex ); -#endif - lutil_passwd_hash( cred , hash, new, text ); - -#if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD ) - ldap_pvt_thread_mutex_unlock( &passwd_mutex ); -#endif - } void slap_passwd_hash( @@ -503,3 +490,41 @@ slap_passwd_hash( slap_passwd_hash_type( cred, new, hash, text ); } + +#ifdef SLAPD_CRYPT +static ldap_pvt_thread_mutex_t passwd_mutex; +static lutil_cryptfunc slapd_crypt; +#endif + +void slap_passwd_init() +{ +#ifdef SLAPD_CRYPT + ldap_pvt_thread_mutex_init( &passwd_mutex ); + lutil_cryptptr = slapd_crypt; +#endif +} +#ifdef SLAPD_CRYPT +int slapd_crypt( const char *key, const char *salt, char **hash ) +{ + char *cr; + int rc; + + ldap_pvt_thread_mutex_lock( &passwd_mutex ); + + cr = crypt( key, salt ); + if ( cr == NULL || cr[0] == '\0' ) { + /* salt must have been invalid */ + rc = LUTIL_PASSWD_ERR; + } else { + if ( hash ) { + *hash = ber_strdup( cr ); + rc = LUTIL_PASSWD_OK; + } + rc = strcmp( salt, cr ) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; + } + + ldap_pvt_thread_mutex_unlock( &passwd_mutex ); + return rc; +} +#endif /* SLAPD_CRYPT */ + diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index f91874a5ae..bedbb5a36e 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -1071,6 +1071,8 @@ LDAP_SLAPD_F (int) slap_passwd_parse( struct berval *newpass, const char **text ); +LDAP_SLAPD_F (void) slap_passwd_init (void); + /* * phonetic.c */ @@ -1463,9 +1465,6 @@ LDAP_SLAPD_V (int) connection_pool_max; LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) entry2str_mutex; LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) replog_mutex; -#if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD ) -LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) passwd_mutex; -#endif #ifndef HAVE_GMTIME_R LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) gmtime_mutex; #endif diff --git a/servers/slapd/sasl.c b/servers/slapd/sasl.c index 975df3755f..bf068e85c1 100644 --- a/servers/slapd/sasl.c +++ b/servers/slapd/sasl.c @@ -768,7 +768,66 @@ slap_sasl_err2ldap( int saslerr ) return rc; } -#endif + +#ifdef SLAPD_SPASSWD + +static struct berval sasl_pwscheme = BER_BVC("{SASL}"); + +static int chk_sasl( + const struct berval *sc, + const struct berval * passwd, + const struct berval * cred, + const char **text ) +{ + unsigned int i; + int rtn; + void *ctx, *sconn = NULL; + + for( i=0; ibv_len; i++) { + if(cred->bv_val[i] == '\0') { + return LUTIL_PASSWD_ERR; /* NUL character in password */ + } + } + + if( cred->bv_val[i] != '\0' ) { + return LUTIL_PASSWD_ERR; /* cred must behave like a string */ + } + + for( i=0; ibv_len; i++) { + if(passwd->bv_val[i] == '\0') { + return LUTIL_PASSWD_ERR; /* NUL character in password */ + } + } + + if( passwd->bv_val[i] != '\0' ) { + return LUTIL_PASSWD_ERR; /* passwd must behave like a string */ + } + + rtn = LUTIL_PASSWD_ERR; + + ctx = ldap_pvt_thread_pool_context(); + ldap_pvt_thread_pool_getkey( ctx, slap_sasl_bind, &sconn, NULL ); + + if( sconn != NULL ) { + int sc; +# if SASL_VERSION_MAJOR < 2 + sc = sasl_checkpass( sconn, + passwd->bv_val, passwd->bv_len, + cred->bv_val, cred->bv_len, + text ); +# else + sc = sasl_checkpass( sconn, + passwd->bv_val, passwd->bv_len, + cred->bv_val, cred->bv_len ); +# endif + rtn = ( sc != SASL_OK ) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; + } + + return rtn; +} +#endif /* SLAPD_SPASSWD */ + +#endif /* HAVE_CYRUS_SASL */ int slap_sasl_init( void ) { @@ -840,6 +899,10 @@ int slap_sasl_init( void ) return -1; } +#ifdef SLAPD_SPASSWD + lutil_passwd_add( &sasl_pwscheme, chk_sasl, NULL ); +#endif + Debug( LDAP_DEBUG_TRACE, "slap_sasl_init: initialized!\n", 0, 0, 0 ); -- 2.39.5