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 /ldap | |
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.
Diffstat (limited to 'ldap')
-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 |