From 86efa0314c59550f0660c8d143a52a57b1dffb96 Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Thu, 18 Jan 2018 09:56:17 -0500 Subject: [PATCH] Ticket 49370 - Add all the password policy defaults to a new local policy Bug Description: When processing a local password policy we were not pulling in the defaults for the "on/off" settings. This patch addresses that. Fix Description: Create common default init functions for all password policies https://pagure.io/389-ds-base/issue/49370 Reviewed by: tbordaz, wibrown, and spichugi (Thanks!!!) (cherry picked from commit c8b388bf9f5269e1e1dc8c7c70ec8e58e825204a) --- .../tests/suites/password/regression_test.py | 58 +++++++++++++-- ldap/servers/slapd/libglobs.c | 84 ++++++++++++++-------- ldap/servers/slapd/pw.c | 29 ++------ ldap/servers/slapd/slap.h | 2 + 4 files changed, 113 insertions(+), 60 deletions(-) diff --git a/dirsrvtests/tests/suites/password/regression_test.py b/dirsrvtests/tests/suites/password/regression_test.py index f6ee16773..800294057 100644 --- a/dirsrvtests/tests/suites/password/regression_test.py +++ b/dirsrvtests/tests/suites/password/regression_test.py @@ -6,9 +6,10 @@ # --- END COPYRIGHT BLOCK --- # import pytest -from lib389._constants import SUFFIX, PASSWORD +import time +from lib389._constants import SUFFIX, PASSWORD, DN_DM from lib389.idm.user import UserAccounts -from lib389.utils import ldap, os, logging +from lib389.utils import ldap, os, logging, ensure_bytes from lib389.topologies import topology_st as topo DEBUGGING = os.getenv("DEBUGGING", default=False) @@ -20,6 +21,7 @@ log = logging.getLogger(__name__) user_data = {'cn': 'CNpwtest1', 'sn': 'SNpwtest1', 'uid': 'UIDpwtest1', 'mail': 'MAILpwtest1@redhat.com', 'givenname': 'GNpwtest1'} + TEST_PASSWORDS = list(user_data.values()) # Add substring/token values of "CNpwtest1" TEST_PASSWORDS += ['CNpwtest1ZZZZ', 'ZZZZZCNpwtest1', @@ -37,13 +39,20 @@ def passw_policy(topo, request): """Configure password policy with PasswordCheckSyntax attribute set to on""" log.info('Configure Pwpolicy with PasswordCheckSyntax and nsslapd-pwpolicy-local set to on') + topo.standalone.simple_bind_s(DN_DM, PASSWORD) topo.standalone.config.set('PasswordExp', 'on') topo.standalone.config.set('PasswordCheckSyntax', 'off') topo.standalone.config.set('nsslapd-pwpolicy-local', 'on') subtree = 'ou=people,{}'.format(SUFFIX) log.info('Configure subtree password policy for {}'.format(subtree)) - topo.standalone.subtreePwdPolicy(subtree, {'passwordchange': 'on', 'passwordCheckSyntax': 'on'}) + topo.standalone.subtreePwdPolicy(subtree, {'passwordchange': ensure_bytes('on'), + 'passwordCheckSyntax': ensure_bytes('on'), + 'passwordLockout': ensure_bytes('on'), + 'passwordResetFailureCount': ensure_bytes('3'), + 'passwordLockoutDuration': ensure_bytes('3'), + 'passwordMaxFailure': ensure_bytes('2')}) + time.sleep(1) def fin(): log.info('Reset pwpolicy configuration settings') @@ -76,6 +85,47 @@ def test_user(topo, request): return tuser +def test_pwp_local_unlock(topo, passw_policy, test_user): + """Test subtree policies use the same global default for passwordUnlock + + :id: 741a8417-5f65-4012-b9ed-87987ce3ca1b + :setup: Standalone instance + :steps: + 1. Test user can bind + 2. Bind with bad passwords to lockout account, and verify account is locked + 3. Wait for lockout interval, and bind with valid password + :expectedresults: + 1. Bind successful + 2. Entry is locked + 3. Entry can bind with correct password + """ + + log.info("Verify user can bind...") + test_user.bind(PASSWORD) + + log.info('Test passwordUnlock default - user should be able to reset password after lockout') + for i in range(0,2): + try: + test_user.bind("bad-password") + except ldap.INVALID_CREDENTIALS: + # expected + pass + except ldap.LDAPError as e: + log.fatal("Got unexpected failure: " + atr(e)) + raise e + + + log.info('Verify account is locked') + with pytest.raises(ldap.CONSTRAINT_VIOLATION): + test_user.bind(PASSWORD) + + log.info('Wait for lockout duration...') + time.sleep(4) + + log.info('Check if user can now bind with correct password') + test_user.bind(PASSWORD) + + @pytest.mark.bz1465600 @pytest.mark.parametrize("user_pasw", TEST_PASSWORDS) def test_trivial_passw_check(topo, passw_policy, test_user, user_pasw): @@ -143,4 +193,4 @@ if __name__ == '__main__': # Run isolated # -s for DEBUG mode CURRENT_FILE = os.path.realpath(__file__) - pytest.main("-s {}".format(CURRENT_FILE)) + pytest.main(["-s", CURRENT_FILE]) diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c index 1ba30002f..c1a765aca 100644 --- a/ldap/servers/slapd/libglobs.c +++ b/ldap/servers/slapd/libglobs.c @@ -1401,6 +1401,56 @@ getFrontendConfig(void) */ void +pwpolicy_init_defaults (passwdPolicy *pw_policy) +{ + pw_policy->pw_change = LDAP_ON; + pw_policy->pw_must_change = LDAP_OFF; + pw_policy->pw_syntax = LDAP_OFF; + pw_policy->pw_exp = LDAP_OFF; + pw_policy->pw_send_expiring = LDAP_OFF; + pw_policy->pw_minlength = SLAPD_DEFAULT_PW_MINLENGTH; + pw_policy->pw_mindigits = SLAPD_DEFAULT_PW_MINDIGITS; + pw_policy->pw_minalphas = SLAPD_DEFAULT_PW_MINALPHAS; + pw_policy->pw_minuppers = SLAPD_DEFAULT_PW_MINUPPERS; + pw_policy->pw_minlowers = SLAPD_DEFAULT_PW_MINLOWERS; + pw_policy->pw_minspecials = SLAPD_DEFAULT_PW_MINSPECIALS; + pw_policy->pw_min8bit = SLAPD_DEFAULT_PW_MIN8BIT; + pw_policy->pw_maxrepeats = SLAPD_DEFAULT_PW_MAXREPEATS; + pw_policy->pw_mincategories = SLAPD_DEFAULT_PW_MINCATEGORIES; + pw_policy->pw_mintokenlength = SLAPD_DEFAULT_PW_MINTOKENLENGTH; + pw_policy->pw_maxage = SLAPD_DEFAULT_PW_MAXAGE; + pw_policy->pw_minage = SLAPD_DEFAULT_PW_MINAGE; + pw_policy->pw_warning = SLAPD_DEFAULT_PW_WARNING; + pw_policy->pw_history = LDAP_OFF; + pw_policy->pw_inhistory = SLAPD_DEFAULT_PW_INHISTORY; + pw_policy->pw_lockout = LDAP_OFF; + pw_policy->pw_maxfailure = SLAPD_DEFAULT_PW_MAXFAILURE; + pw_policy->pw_unlock = LDAP_ON; + pw_policy->pw_lockduration = SLAPD_DEFAULT_PW_LOCKDURATION; + pw_policy->pw_resetfailurecount = SLAPD_DEFAULT_PW_RESETFAILURECOUNT; + pw_policy->pw_gracelimit = SLAPD_DEFAULT_PW_GRACELIMIT; + pw_policy->pw_admin = NULL; + pw_policy->pw_admin_user = NULL; + pw_policy->pw_is_legacy = LDAP_ON; + pw_policy->pw_track_update_time = LDAP_OFF; +} + +static void +pwpolicy_fe_init_onoff(passwdPolicy *pw_policy) +{ + init_pw_change = pw_policy->pw_change; + init_pw_must_change = pw_policy->pw_must_change; + init_pw_syntax = pw_policy->pw_syntax; + init_pw_exp = pw_policy->pw_exp; + init_pw_send_expiring = pw_policy->pw_send_expiring; + init_pw_history = pw_policy->pw_history; + init_pw_lockout = pw_policy->pw_lockout; + init_pw_unlock = pw_policy->pw_unlock; + init_pw_is_legacy = pw_policy->pw_is_legacy; + init_pw_track_update_time = pw_policy->pw_track_update_time; +} + +void FrontendConfig_init(void) { slapdFrontendConfig_t *cfg = getFrontendConfig(); @@ -1511,41 +1561,13 @@ FrontendConfig_init(void) * let clients abide by the LDAP standards and send us a SASL/EXTERNAL bind * if that's what they want to do */ init_force_sasl_external = cfg->force_sasl_external = LDAP_OFF; - init_readonly = cfg->readonly = LDAP_OFF; + + pwpolicy_init_defaults(&cfg->pw_policy); + pwpolicy_fe_init_onoff(&cfg->pw_policy); init_pwpolicy_local = cfg->pwpolicy_local = LDAP_OFF; init_pwpolicy_inherit_global = cfg->pwpolicy_inherit_global = LDAP_OFF; - init_pw_change = cfg->pw_policy.pw_change = LDAP_ON; - init_pw_must_change = cfg->pw_policy.pw_must_change = LDAP_OFF; init_allow_hashed_pw = cfg->allow_hashed_pw = LDAP_OFF; - init_pw_syntax = cfg->pw_policy.pw_syntax = LDAP_OFF; - init_pw_exp = cfg->pw_policy.pw_exp = LDAP_OFF; - init_pw_send_expiring = cfg->pw_policy.pw_send_expiring = LDAP_OFF; - cfg->pw_policy.pw_minlength = SLAPD_DEFAULT_PW_MINLENGTH; - cfg->pw_policy.pw_mindigits = SLAPD_DEFAULT_PW_MINDIGITS; - cfg->pw_policy.pw_minalphas = SLAPD_DEFAULT_PW_MINALPHAS; - cfg->pw_policy.pw_minuppers = SLAPD_DEFAULT_PW_MINUPPERS; - cfg->pw_policy.pw_minlowers = SLAPD_DEFAULT_PW_MINLOWERS; - cfg->pw_policy.pw_minspecials = SLAPD_DEFAULT_PW_MINSPECIALS; - cfg->pw_policy.pw_min8bit = SLAPD_DEFAULT_PW_MIN8BIT; - cfg->pw_policy.pw_maxrepeats = SLAPD_DEFAULT_PW_MAXREPEATS; - cfg->pw_policy.pw_mincategories = SLAPD_DEFAULT_PW_MINCATEGORIES; - cfg->pw_policy.pw_mintokenlength = SLAPD_DEFAULT_PW_MINTOKENLENGTH; - cfg->pw_policy.pw_maxage = SLAPD_DEFAULT_PW_MAXAGE; - cfg->pw_policy.pw_minage = SLAPD_DEFAULT_PW_MINAGE; - cfg->pw_policy.pw_warning = SLAPD_DEFAULT_PW_WARNING; - init_pw_history = cfg->pw_policy.pw_history = LDAP_OFF; - cfg->pw_policy.pw_inhistory = SLAPD_DEFAULT_PW_INHISTORY; - init_pw_lockout = cfg->pw_policy.pw_lockout = LDAP_OFF; - cfg->pw_policy.pw_maxfailure = SLAPD_DEFAULT_PW_MAXFAILURE; - init_pw_unlock = cfg->pw_policy.pw_unlock = LDAP_ON; - cfg->pw_policy.pw_lockduration = SLAPD_DEFAULT_PW_LOCKDURATION; - cfg->pw_policy.pw_resetfailurecount = SLAPD_DEFAULT_PW_RESETFAILURECOUNT; - cfg->pw_policy.pw_gracelimit = SLAPD_DEFAULT_PW_GRACELIMIT; - cfg->pw_policy.pw_admin = NULL; - cfg->pw_policy.pw_admin_user = NULL; - init_pw_is_legacy = cfg->pw_policy.pw_is_legacy = LDAP_ON; - init_pw_track_update_time = cfg->pw_policy.pw_track_update_time = LDAP_OFF; init_pw_is_global_policy = cfg->pw_is_global_policy = LDAP_OFF; init_accesslog_logging_enabled = cfg->accesslog_logging_enabled = LDAP_ON; diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c index 53464c64a..3a545e12e 100644 --- a/ldap/servers/slapd/pw.c +++ b/ldap/servers/slapd/pw.c @@ -1730,32 +1730,11 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn) goto done; } - /* Set the default values */ - pwdpolicy->pw_mintokenlength = SLAPD_DEFAULT_PW_MINTOKENLENGTH; - pwdpolicy->pw_minlength = SLAPD_DEFAULT_PW_MINLENGTH; - pwdpolicy->pw_mindigits = SLAPD_DEFAULT_PW_MINDIGITS; - pwdpolicy->pw_minalphas = SLAPD_DEFAULT_PW_MINALPHAS; - pwdpolicy->pw_minuppers = SLAPD_DEFAULT_PW_MINUPPERS; - pwdpolicy->pw_minlowers = SLAPD_DEFAULT_PW_MINLOWERS; - pwdpolicy->pw_minspecials = SLAPD_DEFAULT_PW_MINSPECIALS; - pwdpolicy->pw_min8bit = SLAPD_DEFAULT_PW_MIN8BIT; - pwdpolicy->pw_maxrepeats = SLAPD_DEFAULT_PW_MAXREPEATS; - pwdpolicy->pw_mincategories = SLAPD_DEFAULT_PW_MINCATEGORIES; - pwdpolicy->pw_maxage = SLAPD_DEFAULT_PW_MAXAGE; - pwdpolicy->pw_minage = SLAPD_DEFAULT_PW_MINAGE; - pwdpolicy->pw_warning = SLAPD_DEFAULT_PW_WARNING; - pwdpolicy->pw_inhistory = SLAPD_DEFAULT_PW_INHISTORY; - pwdpolicy->pw_maxfailure = SLAPD_DEFAULT_PW_MAXFAILURE; - pwdpolicy->pw_lockduration = SLAPD_DEFAULT_PW_LOCKDURATION; - pwdpolicy->pw_resetfailurecount = SLAPD_DEFAULT_PW_RESETFAILURECOUNT; - pwdpolicy->pw_gracelimit = SLAPD_DEFAULT_PW_GRACELIMIT; - - /* set the default passwordLegacyPolicy setting */ - pwdpolicy->pw_is_legacy = 1; - - /* set passwordTrackUpdateTime */ - pwdpolicy->pw_track_update_time = slapdFrontendConfig->pw_policy.pw_track_update_time; + /* Set the default values (from libglobs.c) */ + pwpolicy_init_defaults(pwdpolicy); + pwdpolicy->pw_storagescheme = slapdFrontendConfig->pw_storagescheme; + /* Set the defined values now */ for (slapi_entry_first_attr(pw_entry, &attr); attr; slapi_entry_next_attr(pw_entry, attr, &attr)) { slapi_attr_get_type(attr, &attr_name); diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h index 08754d8fb..f6fc374a4 100644 --- a/ldap/servers/slapd/slap.h +++ b/ldap/servers/slapd/slap.h @@ -1773,6 +1773,8 @@ typedef struct passwordpolicyarray Slapi_DN **pw_admin_user; } passwdPolicy; +void pwpolicy_init_defaults (passwdPolicy *pw_policy); + Slapi_PBlock *slapi_pblock_clone(Slapi_PBlock *pb); /* deprecated */ passwdPolicy *slapi_pblock_get_pwdpolicy(Slapi_PBlock *pb); -- 2.13.6