diff options
author | Endi S. Dewata <edewata@redhat.com> | 2010-03-11 14:26:56 -0600 |
---|---|---|
committer | Rich Megginson <rmeggins@redhat.com> | 2010-03-12 19:51:21 -0700 |
commit | 1ef0ec98b6c91471454647e5f613d26fa015c619 (patch) | |
tree | fa7a1da28b15e074bc79307cb765ddfde9f1a300 | |
parent | ed463407ead1f63ba26f64740a1e5cd1d79a03ee (diff) | |
download | ds-1ef0ec98b6c91471454647e5f613d26fa015c619.tar.gz ds-1ef0ec98b6c91471454647e5f613d26fa015c619.tar.xz ds-1ef0ec98b6c91471454647e5f613d26fa015c619.zip |
Bug 470684 - Pam_passthru plugin doesn't verify account activation
https://bugzilla.redhat.com/show_bug.cgi?id=470684
Resolves: bug 470684
Bug Description: Pam passthrough doesn't verify account activation
Reviewed by: rmeggins
Branch: HEAD
Fix Description: The check_account_lock() has been renamed to
slapi_check_account_lock() and moved into libslapd.so so any plugins
can use it. The account_inactivation_only parameter has been replaced
by check_password_policy. A new parameter send_result has been added
to determine whether to send LDAP results.
The pam_passthru plugin has been modified to use this function to
check account activation when the pamIDMapMethod is set to ENTRY.
The plugin will not check password policy.
-rw-r--r-- | ldap/servers/plugins/pam_passthru/pam_ptimpl.c | 17 | ||||
-rw-r--r-- | ldap/servers/slapd/bind.c | 8 | ||||
-rw-r--r-- | ldap/servers/slapd/daemon.c | 10 | ||||
-rw-r--r-- | ldap/servers/slapd/libslapd.def | 1 | ||||
-rw-r--r-- | ldap/servers/slapd/pw.c | 138 | ||||
-rw-r--r-- | ldap/servers/slapd/pw_mgmt.c | 136 | ||||
-rw-r--r-- | ldap/servers/slapd/saslbind.c | 2 | ||||
-rw-r--r-- | ldap/servers/slapd/slapi-plugin.h | 2 |
8 files changed, 167 insertions, 147 deletions
diff --git a/ldap/servers/plugins/pam_passthru/pam_ptimpl.c b/ldap/servers/plugins/pam_passthru/pam_ptimpl.c index 6e5fc9fc..662239f3 100644 --- a/ldap/servers/plugins/pam_passthru/pam_ptimpl.c +++ b/ldap/servers/plugins/pam_passthru/pam_ptimpl.c @@ -106,7 +106,7 @@ derive_from_bind_dn(Slapi_PBlock *pb, char *binddn, MyStrBuf *pam_id) } static char * -derive_from_bind_entry(Slapi_PBlock *pb, char *binddn, MyStrBuf *pam_id, char *map_ident_attr) +derive_from_bind_entry(Slapi_PBlock *pb, char *binddn, MyStrBuf *pam_id, char *map_ident_attr, int *locked) { char buf[BUFSIZ]; Slapi_Entry *entry = NULL; @@ -128,6 +128,12 @@ derive_from_bind_entry(Slapi_PBlock *pb, char *binddn, MyStrBuf *pam_id, char *m "Could not find entry for BIND dn %s\n", escape_string(binddn, buf)); init_my_str_buf(pam_id, NULL); + } else if (slapi_check_account_lock( pb, entry, 0, 0, 0 ) == 1) { + slapi_log_error(SLAPI_LOG_FATAL, PAM_PASSTHRU_PLUGIN_SUBSYSTEM, + "Account %s inactivated.\n", + escape_string(binddn, buf)); + init_my_str_buf(pam_id, NULL); + *locked = 1; } else { char *val = slapi_entry_attr_get_charptr(entry, map_ident_attr); init_my_str_buf(pam_id, val); @@ -266,17 +272,24 @@ do_one_pam_auth( struct pam_conv my_pam_conv = {pam_conv_func, NULL}; char buf[BUFSIZ]; /* for error messages */ char *errmsg = NULL; /* free with PR_smprintf_free */ + int locked = 0; slapi_pblock_get( pb, SLAPI_BIND_TARGET, &binddn ); if (method == PAMPT_MAP_METHOD_RDN) { derive_from_bind_dn(pb, binddn, &pam_id); } else if (method == PAMPT_MAP_METHOD_ENTRY) { - derive_from_bind_entry(pb, binddn, &pam_id, map_ident_attr); + derive_from_bind_entry(pb, binddn, &pam_id, map_ident_attr, &locked); } else { init_my_str_buf(&pam_id, binddn); } + if (locked) { + errmsg = PR_smprintf("Account inactivated. Contact system administrator."); + retcode = LDAP_UNWILLING_TO_PERFORM; /* user inactivated */ + goto done; /* skip the pam stuff */ + } + if (!pam_id.str) { errmsg = PR_smprintf("Bind DN [%s] is invalid or not found", escape_string(binddn, buf)); diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c index d3e90091..f0bdbae4 100644 --- a/ldap/servers/slapd/bind.c +++ b/ldap/servers/slapd/bind.c @@ -441,8 +441,8 @@ do_bind( Slapi_PBlock *pb ) if (!isroot ) { /* check if the account is locked */ bind_target_entry = get_entry(pb, pb->pb_conn->c_external_dn); - if ( bind_target_entry != NULL && check_account_lock(pb, bind_target_entry, - pw_response_requested, 0 /*not account_inactivation_only*/ ) == 1) { + if ( bind_target_entry != NULL && slapi_check_account_lock(pb, bind_target_entry, + pw_response_requested, 1 /*check password policy*/, 1 /*send ldap result*/) == 1) { /* call postop plugins */ plugin_call_plugins( pb, SLAPI_PLUGIN_POST_BIND_FN ); goto free_and_return; @@ -642,10 +642,10 @@ do_bind( Slapi_PBlock *pb ) * */ - /* get the entry now, so that we can give it to check_account_lock and reslimit_update_from_dn */ + /* get the entry now, so that we can give it to slapi_check_account_lock and reslimit_update_from_dn */ if (! slapi_be_is_flag_set(be, SLAPI_BE_FLAG_REMOTE_DATA)) { bind_target_entry = get_entry(pb, slapi_sdn_get_ndn(&sdn)); - rc = check_account_lock ( pb, bind_target_entry, pw_response_requested,0); + rc = slapi_check_account_lock ( pb, bind_target_entry, pw_response_requested, 1, 1); } slapi_pblock_set( pb, SLAPI_PLUGIN, be->be_database ); diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c index 0db7f136..672a9a4d 100644 --- a/ldap/servers/slapd/daemon.c +++ b/ldap/servers/slapd/daemon.c @@ -1922,11 +1922,12 @@ slapd_bind_local_user(Connection *conn) if(entries[0] && 0 == entries[1]) { /* observe account locking */ - ret = check_account_lock( + ret = slapi_check_account_lock( 0, /* pb not req */ entries[0], 0, /* no response control */ - 1 /* inactivation only */ + 0, /* don't check password policy */ + 0 /* don't send ldap result */ ); if(0 == ret) @@ -1981,11 +1982,12 @@ entry_map_free: if(0 == ret && e) { - ret = check_account_lock( + ret = slapi_check_account_lock( 0, /* pb not req */ e, 0, /* no response control */ - 1 /* inactivation only */ + 0, /* don't check password policy */ + 0 /* don't send ldap result */ ); if(1 == ret) diff --git a/ldap/servers/slapd/libslapd.def b/ldap/servers/slapd/libslapd.def index c2bdfbef..c5fd242e 100644 --- a/ldap/servers/slapd/libslapd.def +++ b/ldap/servers/slapd/libslapd.def @@ -1198,3 +1198,4 @@ EXPORTS config_get_pw_maxrepeats @1205 config_get_pw_mincategories @1206 config_get_pw_mintokenlength @1207 + slapi_check_account_lock @1208 diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c index f1e87a38..15add061 100644 --- a/ldap/servers/slapd/pw.c +++ b/ldap/servers/slapd/pw.c @@ -1982,3 +1982,141 @@ check_pw_storagescheme_value( const char *attr_name, char *value, long minval, l return retVal; } +/* check_account_lock is called before bind opeation; this could be a pre-op. */ +int +slapi_check_account_lock ( Slapi_PBlock *pb, Slapi_Entry * bind_target_entry, int pwresponse_req, int check_password_policy, int send_result) { + + time_t unlock_time; + time_t cur_time; + char *cur_time_str = NULL; + char *accountUnlockTime; + passwdPolicy *pwpolicy = NULL; + char *dn = NULL; + + /* kexcoff: account inactivation */ + int rc = 0; + Slapi_ValueSet *values = NULL; + int type_name_disposition = 0; + char *actual_type_name = NULL; + int attr_free_flags = 0; + /* kexcoff - end */ + + if ( bind_target_entry == NULL ) + return -1; + + if(check_password_policy) + { + dn = slapi_entry_get_ndn(bind_target_entry); + pwpolicy = new_passwdPolicy(pb, dn); + } + + /* kexcoff: account inactivation */ + /* check if the entry is locked by nsAccountLock attribute - account inactivation feature */ + + rc = slapi_vattr_values_get(bind_target_entry, "nsAccountLock", + &values, + &type_name_disposition, &actual_type_name, + SLAPI_VIRTUALATTRS_REQUEST_POINTERS, + &attr_free_flags); + if ( rc == 0 ) + { + Slapi_Value *v = NULL; + const struct berval *bvp = NULL; + + if ( (slapi_valueset_first_value( values, &v ) != -1) && + ( bvp = slapi_value_get_berval( v )) != NULL ) + { + if ( (bvp != NULL) && (strcasecmp(bvp->bv_val, "true") == 0) ) + { + /* account inactivated */ + if (check_password_policy && pwresponse_req) { + slapi_pwpolicy_make_response_control ( pb, -1, -1, + LDAP_PWPOLICY_ACCTLOCKED ); + } + if (send_result) + send_ldap_result ( pb, LDAP_UNWILLING_TO_PERFORM, NULL, + "Account inactivated. Contact system administrator.", + 0, NULL ); + slapi_vattr_values_free(&values, &actual_type_name, attr_free_flags); + goto locked; + } + } /* else, account "activated", keep on the process */ + + if ( values != NULL ) + slapi_vattr_values_free(&values, &actual_type_name, attr_free_flags); + } + /* kexcoff - end */ + + /* + * Check if the password policy has to be checked or not + */ + if ( !check_password_policy || pwpolicy->pw_lockout == 0 ) { + goto notlocked; + } + + /* + * Check the attribute of the password policy + */ + + /* check if account is locked out. If so, send result and return 1 */ + { + unsigned int maxfailure= pwpolicy->pw_maxfailure; + /* It's locked if passwordRetryCount >= maxfailure */ + if ( slapi_entry_attr_get_uint(bind_target_entry,"passwordRetryCount") < maxfailure ) + { + /* Not locked */ + goto notlocked; + } + } + + /* locked but maybe it's time to unlock it */ + accountUnlockTime= slapi_entry_attr_get_charptr(bind_target_entry, "accountUnlockTime"); + if (accountUnlockTime != NULL) + { + unlock_time = parse_genTime(accountUnlockTime); + slapi_ch_free((void **) &accountUnlockTime ); + + if ( pwpolicy->pw_unlock == 0 && + unlock_time == NO_TIME ) { + + /* account is locked forever. contact admin to reset */ + if (pwresponse_req) { + slapi_pwpolicy_make_response_control ( pb, -1, -1, + LDAP_PWPOLICY_ACCTLOCKED ); + } + if (send_result) + send_ldap_result ( pb, LDAP_CONSTRAINT_VIOLATION, NULL, + "Exceed password retry limit. Contact system administrator to reset.", + 0, NULL ); + goto locked; + } + cur_time = current_time(); + cur_time_str = format_genTime( cur_time); + if ( difftime ( parse_genTime( cur_time_str ), unlock_time ) < 0 ) { + + /* account is locked, cannot do anything */ + if (pwresponse_req) { + slapi_pwpolicy_make_response_control ( pb, -1, -1, + LDAP_PWPOLICY_ACCTLOCKED ); + } + if (send_result) + send_ldap_result ( pb, LDAP_CONSTRAINT_VIOLATION, NULL, + "Exceed password retry limit. Please try later.", + 0, NULL ); + slapi_ch_free((void **) &cur_time_str ); + goto locked; + } + slapi_ch_free((void **) &cur_time_str ); + } + +notlocked: + /* account is not locked. */ + if(check_password_policy) + delete_passwdPolicy(&pwpolicy); + return ( 0 ); +locked: + if(check_password_policy) + delete_passwdPolicy(&pwpolicy); + return (1); + +} diff --git a/ldap/servers/slapd/pw_mgmt.c b/ldap/servers/slapd/pw_mgmt.c index 34afa15b..97b51c8b 100644 --- a/ldap/servers/slapd/pw_mgmt.c +++ b/ldap/servers/slapd/pw_mgmt.c @@ -291,142 +291,6 @@ skip: return( 0 ); } -/* check_account_lock is called before bind opeation; this could be a pre-op. */ -int -check_account_lock ( Slapi_PBlock *pb, Slapi_Entry * bind_target_entry, int pwresponse_req, int account_inactivation_only) { - - time_t unlock_time; - time_t cur_time; - char *cur_time_str = NULL; - char *accountUnlockTime; - passwdPolicy *pwpolicy = NULL; - char *dn = NULL; - - /* kexcoff: account inactivation */ - int rc = 0; - Slapi_ValueSet *values = NULL; - int type_name_disposition = 0; - char *actual_type_name = NULL; - int attr_free_flags = 0; - /* kexcoff - end */ - - if ( bind_target_entry == NULL ) - return -1; - - if(!account_inactivation_only) - { - dn = slapi_entry_get_ndn(bind_target_entry); - pwpolicy = new_passwdPolicy(pb, dn); - } - - /* kexcoff: account inactivation */ - /* check if the entry is locked by nsAccountLock attribute - account inactivation feature */ - - rc = slapi_vattr_values_get(bind_target_entry, "nsAccountLock", - &values, - &type_name_disposition, &actual_type_name, - SLAPI_VIRTUALATTRS_REQUEST_POINTERS, - &attr_free_flags); - if ( rc == 0 ) - { - Slapi_Value *v = NULL; - const struct berval *bvp = NULL; - - if ( (slapi_valueset_first_value( values, &v ) != -1) && - ( bvp = slapi_value_get_berval( v )) != NULL ) - { - if ( (bvp != NULL) && (strcasecmp(bvp->bv_val, "true") == 0) ) - { - /* account inactivated */ - if (!account_inactivation_only && pwresponse_req) { - slapi_pwpolicy_make_response_control ( pb, -1, -1, - LDAP_PWPOLICY_ACCTLOCKED ); - } - if(!account_inactivation_only) - send_ldap_result ( pb, LDAP_UNWILLING_TO_PERFORM, NULL, - "Account inactivated. Contact system administrator.", - 0, NULL ); - slapi_vattr_values_free(&values, &actual_type_name, attr_free_flags); - goto locked; - } - } /* else, account "activated", keep on the process */ - - if ( values != NULL ) - slapi_vattr_values_free(&values, &actual_type_name, attr_free_flags); - } - /* kexcoff - end */ - - /* - * Check if the password policy has to be checked or not - */ - if ( account_inactivation_only || pwpolicy->pw_lockout == 0 ) { - goto notlocked; - } - - /* - * Check the attribute of the password policy - */ - - /* check if account is locked out. If so, send result and return 1 */ - { - unsigned int maxfailure= pwpolicy->pw_maxfailure; - /* It's locked if passwordRetryCount >= maxfailure */ - if ( slapi_entry_attr_get_uint(bind_target_entry,"passwordRetryCount") < maxfailure ) - { - /* Not locked */ - goto notlocked; - } - } - - /* locked but maybe it's time to unlock it */ - accountUnlockTime= slapi_entry_attr_get_charptr(bind_target_entry, "accountUnlockTime"); - if (accountUnlockTime != NULL) - { - unlock_time = parse_genTime(accountUnlockTime); - slapi_ch_free((void **) &accountUnlockTime ); - - if ( pwpolicy->pw_unlock == 0 && - unlock_time == NO_TIME ) { - - /* account is locked forever. contact admin to reset */ - if (pwresponse_req) { - slapi_pwpolicy_make_response_control ( pb, -1, -1, - LDAP_PWPOLICY_ACCTLOCKED ); - } - send_ldap_result ( pb, LDAP_CONSTRAINT_VIOLATION, NULL, - "Exceed password retry limit. Contact system administrator to reset." - , 0, NULL ); - goto locked; - } - cur_time = current_time(); - cur_time_str = format_genTime( cur_time); - if ( difftime ( parse_genTime( cur_time_str ), unlock_time ) < 0 ) { - - /* account is locked, cannot do anything */ - if (pwresponse_req) { - slapi_pwpolicy_make_response_control ( pb, -1, -1, - LDAP_PWPOLICY_ACCTLOCKED ); - } - send_ldap_result ( pb, LDAP_CONSTRAINT_VIOLATION, NULL, - "Exceed password retry limit. Please try later." , 0, NULL ); - slapi_ch_free((void **) &cur_time_str ); - goto locked; - } - slapi_ch_free((void **) &cur_time_str ); - } - -notlocked: - /* account is not locked. */ - if(!account_inactivation_only) - delete_passwdPolicy(&pwpolicy); - return ( 0 ); -locked: - if(!account_inactivation_only) - delete_passwdPolicy(&pwpolicy); - return (1); - -} - void pw_init ( void ) { slapdFrontendConfig_t *slapdFrontendConfig; diff --git a/ldap/servers/slapd/saslbind.c b/ldap/servers/slapd/saslbind.c index 42d289a8..1ed9942d 100644 --- a/ldap/servers/slapd/saslbind.c +++ b/ldap/servers/slapd/saslbind.c @@ -936,7 +936,7 @@ void ids_sasl_check_bind(Slapi_PBlock *pb) { break; } - if ( check_account_lock(pb, bind_target_entry, pwresponse_requested, 0) == 1) { + if ( slapi_check_account_lock(pb, bind_target_entry, pwresponse_requested, 1, 1) == 1) { slapi_entry_free(bind_target_entry); break; } diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h index 5f97c055..47fc7b86 100644 --- a/ldap/servers/slapd/slapi-plugin.h +++ b/ldap/servers/slapd/slapi-plugin.h @@ -5953,6 +5953,8 @@ int slapi_set_plugin_default_config(const char *type, Slapi_Value *value); * */ int slapi_get_plugin_default_config(char *type, Slapi_ValueSet **valueset); +int slapi_check_account_lock( Slapi_PBlock *pb, Slapi_Entry *bind_target_entry, int pwresponse_req, int check_password_policy, int send_result); + #ifdef __cplusplus } #endif |