ldap/servers/plugins/pam_passthru/pam_ptimpl.c | 17 ++-
ldap/servers/slapd/bind.c | 8 -
ldap/servers/slapd/daemon.c | 10 +
ldap/servers/slapd/libslapd.def | 1
ldap/servers/slapd/pw.c | 138 +++++++++++++++++++++++++
ldap/servers/slapd/pw_mgmt.c | 136 ------------------------
ldap/servers/slapd/saslbind.c | 2
ldap/servers/slapd/slapi-plugin.h | 2
8 files changed, 167 insertions(+), 147 deletions(-)
New commits:
commit c987b35350b4fffc338f5654452493d253bd23cf
Author: Endi S. Dewata <edewata(a)redhat.com>
Date: Thu Mar 11 14:26:56 2010 -0600
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: Directory_Server_8_2_Branch
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.
(cherry picked from commit 1ef0ec98b6c91471454647e5f613d26fa015c619)
diff --git a/ldap/servers/plugins/pam_passthru/pam_ptimpl.c
b/ldap/servers/plugins/pam_passthru/pam_ptimpl.c
index 6e5fc9f..662239f 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 4236530..1ddbfe8 100644
--- a/ldap/servers/slapd/bind.c
+++ b/ldap/servers/slapd/bind.c
@@ -469,8 +469,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;
@@ -674,10 +674,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 fcd8049..39b1522 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -1944,11 +1944,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)
@@ -2003,11 +2004,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 c2bdfbe..c5fd242 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 7014079..bf98877 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 34afa15..97b51c8 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 6d85fc0..5870365 100644
--- a/ldap/servers/slapd/saslbind.c
+++ b/ldap/servers/slapd/saslbind.c
@@ -968,7 +968,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 039f7e5..045f164 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -5749,6 +5749,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