From 396c9320f51c751e040da97ba8396c0f36de88f1 Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Apr 06 2012 02:40:01 +0000 Subject: Ticket #183 - passwordMaxFailure should lockout password one sooner - and should be configurable to avoid regressions Bug Description: DS doesn't return error LDAP_CONSTRAINT_VIOLATION until after the retry limit is exceeded Fix Description: DS has essentially locked the account, but we didn't log the error until the next bind. Added a new config option "passwordLegacyPolicy: on|off" that will trigger the error LDAP_CONSTRAINT_VIOLATION, if "legacy" is off, when the limit is actually reached. The default is to continue to do things the "old" way, or legacy "on". https://fedorahosted.org/389/ticket/183 reviewed by: Noriko (Thanks!) --- diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c index 8bcd544..d5b8faf 100644 --- a/ldap/servers/slapd/libglobs.c +++ b/ldap/servers/slapd/libglobs.c @@ -373,6 +373,9 @@ static struct config_get_and_set { {CONFIG_PW_ISGLOBAL_ATTRIBUTE, config_set_pw_is_global_policy, NULL, 0, (void**)&global_slapdFrontendConfig.pw_is_global_policy, CONFIG_ON_OFF, NULL}, + {CONFIG_PW_IS_LEGACY, config_set_pw_is_legacy_policy, + NULL, 0, + (void**)&global_slapdFrontendConfig.pw_policy.pw_is_legacy, CONFIG_ON_OFF, NULL}, {CONFIG_AUDITLOG_MAXNUMOFLOGSPERDIR_ATTRIBUTE, NULL, log_set_numlogsperdir, SLAPD_AUDIT_LOG, (void**)&global_slapdFrontendConfig.auditlog_maxnumlogs, CONFIG_INT, NULL}, @@ -1017,6 +1020,7 @@ FrontendConfig_init () { cfg->pw_policy.pw_lockduration = 3600; /* 60 minutes */ cfg->pw_policy.pw_resetfailurecount = 600; /* 10 minutes */ cfg->pw_policy.pw_gracelimit = 0; + cfg->pw_policy.pw_is_legacy = LDAP_ON; cfg->pw_is_global_policy = LDAP_OFF; cfg->accesslog_logging_enabled = LDAP_ON; @@ -2417,6 +2421,20 @@ config_set_pw_is_global_policy( const char *attrname, char *value, char *errorbu } int +config_set_pw_is_legacy_policy( const char *attrname, char *value, char *errorbuf, int apply ) { + int retVal = LDAP_SUCCESS; + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + + retVal = config_set_onoff ( attrname, + value, + &(slapdFrontendConfig->pw_policy.pw_is_legacy), + errorbuf, + apply); + + return retVal; +} + +int config_set_pw_exp( const char *attrname, char *value, char *errorbuf, int apply ) { int retVal = LDAP_SUCCESS; slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); @@ -4235,6 +4253,18 @@ config_get_pw_is_global_policy() { } int +config_get_pw_is_legacy_policy() { + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + int retVal; + + CFG_LOCK_READ(slapdFrontendConfig); + retVal = slapdFrontendConfig->pw_policy.pw_is_legacy; + CFG_UNLOCK_READ(slapdFrontendConfig); + + return retVal; +} + +int config_get_pw_exp() { slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); int retVal; diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h index 9bbcf53..d291be3 100644 --- a/ldap/servers/slapd/proto-slap.h +++ b/ldap/servers/slapd/proto-slap.h @@ -340,6 +340,7 @@ int config_set_pw_unlock(const char *attrname, char *value, char *errorbuf, int int config_set_pw_lockduration(const char *attrname, char *value, char *errorbuf, int apply ); int config_set_pw_resetfailurecount(const char *attrname, char *value, char *errorbuf, int apply ); int config_set_pw_is_global_policy(const char *attrname, char *value, char *errorbuf, int apply ); +int config_set_pw_is_legacy_policy(const char *attrname, char *value, char *errorbuf, int apply ); int config_set_pw_gracelimit(const char *attrname, char *value, char *errorbuf, int apply ); int config_set_useroc(const char *attrname, char *value, char *errorbuf, int apply ); int config_set_return_exact_case(const char *attrname, char *value, char *errorbuf, int apply ); diff --git a/ldap/servers/slapd/pw.h b/ldap/servers/slapd/pw.h index 83f0003..a470fdd 100644 --- a/ldap/servers/slapd/pw.h +++ b/ldap/servers/slapd/pw.h @@ -96,6 +96,6 @@ int check_pw_storagescheme_value( const char *attr_name, char *value, long minva * Public functions from pw_retry.c: */ Slapi_Entry *get_entry ( Slapi_PBlock *pb, const char *dn ); -void set_retry_cnt_mods ( Slapi_PBlock *pb, Slapi_Mods *smods, int count); +int set_retry_cnt_mods ( Slapi_PBlock *pb, Slapi_Mods *smods, int count); #endif /* _SLAPD_PW_H_ */ diff --git a/ldap/servers/slapd/pw_retry.c b/ldap/servers/slapd/pw_retry.c index 5244622..09d0ed0 100644 --- a/ldap/servers/slapd/pw_retry.c +++ b/ldap/servers/slapd/pw_retry.c @@ -50,8 +50,8 @@ /* prototypes */ /****************************************************************************/ /* Slapi_Entry *get_entry ( Slapi_PBlock *pb, const char *dn ); */ -static void set_retry_cnt ( Slapi_PBlock *pb, int count); -static void set_retry_cnt_and_time ( Slapi_PBlock *pb, int count, time_t cur_time); +static int set_retry_cnt ( Slapi_PBlock *pb, int count); +static int set_retry_cnt_and_time ( Slapi_PBlock *pb, int count, time_t cur_time); /* * update_pw_retry() is called when bind operation fails @@ -72,6 +72,7 @@ int update_pw_retry ( Slapi_PBlock *pb ) char *cur_time_str = NULL; char *retryCountResetTime; int passwordRetryCount; + int rc = 0; /* get the entry */ e = get_entry ( pb, NULL ); @@ -93,18 +94,18 @@ int update_pw_retry ( Slapi_PBlock *pb ) { /* set passwordRetryCount to 1 */ /* reset retryCountResetTime */ - set_retry_cnt_and_time ( pb, 1, cur_time ); + rc = set_retry_cnt_and_time ( pb, 1, cur_time ); slapi_ch_free((void **) &cur_time_str ); slapi_entry_free( e ); - return ( 0 ); /* success */ + return ( rc ); /* success */ } else { slapi_ch_free((void **) &cur_time_str ); } } else { /* initialize passwordRetryCount and retryCountResetTime */ - set_retry_cnt_and_time ( pb, 1, cur_time ); + rc = set_retry_cnt_and_time ( pb, 1, cur_time ); slapi_entry_free( e ); - return ( 0 ); /* success */ + return ( rc ); /* success */ } passwordRetryCount = slapi_entry_attr_get_int(e, "passwordRetryCount"); if (passwordRetryCount >= 0) @@ -112,24 +113,25 @@ int update_pw_retry ( Slapi_PBlock *pb ) retry_cnt = passwordRetryCount + 1; if ( retry_cnt == 1 ) { /* set retryCountResetTime */ - set_retry_cnt_and_time ( pb, retry_cnt, cur_time ); + rc = set_retry_cnt_and_time ( pb, retry_cnt, cur_time ); } else { /* set passwordRetryCount to retry_cnt */ - set_retry_cnt ( pb, retry_cnt ); + rc = set_retry_cnt ( pb, retry_cnt ); } } slapi_entry_free( e ); - return 0; /* success */ + return rc; /* success */ } static -void set_retry_cnt_and_time ( Slapi_PBlock *pb, int count, time_t cur_time ) { +int set_retry_cnt_and_time ( Slapi_PBlock *pb, int count, time_t cur_time ) { const char *dn = NULL; Slapi_DN *sdn = NULL; Slapi_Mods smods; time_t reset_time; char *timestr; passwdPolicy *pwpolicy = NULL; + int rc = 0; slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn ); dn = slapi_sdn_get_dn(sdn); @@ -144,14 +146,16 @@ void set_retry_cnt_and_time ( Slapi_PBlock *pb, int count, time_t cur_time ) { slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "retryCountResetTime", timestr); slapi_ch_free((void **)×tr); - set_retry_cnt_mods(pb, &smods, count); + rc = set_retry_cnt_mods(pb, &smods, count); pw_apply_mods(sdn, &smods); slapi_mods_done(&smods); delete_passwdPolicy(&pwpolicy); + + return rc; } -void set_retry_cnt_mods(Slapi_PBlock *pb, Slapi_Mods *smods, int count) +int set_retry_cnt_mods(Slapi_PBlock *pb, Slapi_Mods *smods, int count) { char *timestr; time_t unlock_time; @@ -159,6 +163,7 @@ void set_retry_cnt_mods(Slapi_PBlock *pb, Slapi_Mods *smods, int count) const char *dn = NULL; Slapi_DN *sdn = NULL; passwdPolicy *pwpolicy = NULL; + int rc = 0; slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn ); dn = slapi_sdn_get_dn(sdn); @@ -182,23 +187,26 @@ void set_retry_cnt_mods(Slapi_PBlock *pb, Slapi_Mods *smods, int count) timestr= format_genTime ( unlock_time ); slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "accountUnlockTime", timestr); slapi_ch_free((void **)×tr); + rc = LDAP_CONSTRAINT_VIOLATION; } } delete_passwdPolicy(&pwpolicy); - return; + return rc; } static -void set_retry_cnt ( Slapi_PBlock *pb, int count) +int set_retry_cnt ( Slapi_PBlock *pb, int count) { Slapi_DN *sdn = NULL; Slapi_Mods smods; + int rc = 0; slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn ); slapi_mods_init(&smods, 0); - set_retry_cnt_mods(pb, &smods, count); + rc = set_retry_cnt_mods(pb, &smods, count); pw_apply_mods(sdn, &smods); slapi_mods_done(&smods); + return rc; } diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c index 6f36a60..4712ea1 100644 --- a/ldap/servers/slapd/result.c +++ b/ldap/servers/slapd/result.c @@ -377,7 +377,15 @@ send_ldap_result_ext( dn = slapi_sdn_get_dn(sdn); pwpolicy = new_passwdPolicy(pb, dn); if (pwpolicy && (pwpolicy->pw_lockout == 1)) { - update_pw_retry ( pb ); + if(update_pw_retry( pb ) == LDAP_CONSTRAINT_VIOLATION && !pwpolicy->pw_is_legacy){ + /* + * If we are not using the legacy pw policy behavior, + * convert the error 49 to 19 (constraint violation) + * and log a message + */ + err = LDAP_CONSTRAINT_VIOLATION; + text = "Invalid credentials, you now have exceeded the password retry limit."; + } } } diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h index f7c0bf2..669e304 100644 --- a/ldap/servers/slapd/slap.h +++ b/ldap/servers/slapd/slap.h @@ -1952,6 +1952,7 @@ typedef struct _slapdEntryPoints { #define CONFIG_PW_RESETFAILURECOUNT_ATTRIBUTE "passwordResetFailureCount" #define CONFIG_PW_ISGLOBAL_ATTRIBUTE "passwordIsGlobalPolicy" #define CONFIG_PW_GRACELIMIT_ATTRIBUTE "passwordGraceLimit" +#define CONFIG_PW_IS_LEGACY "passwordLegacyPolicy" #define CONFIG_ACCESSLOG_BUFFERING_ATTRIBUTE "nsslapd-accesslog-logbuffering" #define CONFIG_CSNLOGGING_ATTRIBUTE "nsslapd-csnlogging" #define CONFIG_RETURN_EXACT_CASE_ATTRIBUTE "nsslapd-return-exact-case" @@ -2039,6 +2040,7 @@ typedef struct passwordpolicyarray { long pw_lockduration; long pw_resetfailurecount; int pw_gracelimit; + int pw_is_legacy; struct pw_scheme *pw_storagescheme; } passwdPolicy;