From ca19d110274e2551674b26f3f8fbf9bd6d70688d Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Tue, 16 May 2023 11:25:41 -0400 Subject: [PATCH] Issue 5770 - RFE - Extend Password Adminstrators to allow skipping password info updates Description: Add new config setting to state that password admin updates should not update entry's password state attributes. relates: https://github.com/389ds/389-ds-base/issues/5770 Reviewed by: progier, tbordaz, spichugi (Thanks!) --- .../tests/suites/password/pwdAdmin_test.py | 88 +++++++++++++++++- ldap/schema/02common.ldif | 3 +- ldap/servers/slapd/add.c | 2 +- ldap/servers/slapd/libglobs.c | 31 ++++++- ldap/servers/slapd/modify.c | 4 +- ldap/servers/slapd/proto-slap.h | 1 + ldap/servers/slapd/pw.c | 16 +++- ldap/servers/slapd/pw.h | 5 +- ldap/servers/slapd/slap.h | 3 + src/Cargo.lock | 48 +++++----- .../src/lib/database/globalPwp.jsx | 55 +++++++---- .../389-console/src/lib/database/localPwp.jsx | 92 +++++++++++++++++-- src/lib389/lib389/cli_conf/pwpolicy.py | 3 + src/lib389/lib389/pwpolicy.py | 1 + 14 files changed, 291 insertions(+), 61 deletions(-) diff --git a/dirsrvtests/tests/suites/password/pwdAdmin_test.py b/dirsrvtests/tests/suites/password/pwdAdmin_test.py index e5552f5632..3a2924b793 100644 --- a/dirsrvtests/tests/suites/password/pwdAdmin_test.py +++ b/dirsrvtests/tests/suites/password/pwdAdmin_test.py @@ -60,7 +60,6 @@ def password_policy(topology_st): }) # Add Password Admin 2 - admin2_user = users.create(properties={ 'uid': 'admin2', 'cn' : 'admin2', @@ -72,7 +71,6 @@ def password_policy(topology_st): }) # Add Password Admin Group - admin_group = groups.create(properties={ 'cn': 'password admin group' }) @@ -81,7 +79,6 @@ def password_policy(topology_st): admin_group.add_member(admin2_user.dn) # Configure password policy - log.info('test_pwdAdmin_init: Configuring password policy...') topology_st.standalone.config.replace_many( @@ -91,7 +88,10 @@ def password_policy(topology_st): ('passwordMinTokenLength', '2'), ('passwordExp', 'on'), ('passwordMinDigits', '1'), - ('passwordMinSpecials', '1') + ('passwordMinSpecials', '1'), + ('passwordHistory', 'on'), + ('passwordStorageScheme', 'clear'), + ('nsslapd-enable-upgrade-hash', 'off') ) # @@ -140,6 +140,7 @@ def password_policy(topology_st): return (admin_group, admin1_user, admin2_user) + def test_pwdAdmin_bypass(topology_st, password_policy): """Test that password administrators/root DN can bypass password syntax/policy @@ -288,6 +289,7 @@ def test_pwdAdmin_modify(topology_st, password_policy): for passwd in INVALID_PWDS: u3.replace('userPassword', passwd) + def test_pwdAdmin_group(topology_st, password_policy): """Test that password admin group can bypass policy. @@ -356,6 +358,84 @@ def test_pwdAdmin_config_validation(topology_st, password_policy): with pytest.raises(ldap.INVALID_SYNTAX): topology_st.standalone.config.set('passwordAdminDN', 'zzzzzzzzzzzz') + +def test_pwd_admin_config_test_skip_updates(topology_st, password_policy): + """Check passwordAdminDN does not update entry password state attributes + + :id: 964f1430-795b-4f4d-85b2-abaffe66ddcb + + :setup: Standalone instance + :steps: + 1. Add test entry + 2. Update password + 3. Password history updated + 4. Enable "skip info update" + 5. Update password again + 6. New password not in history + :expectedresults: + 1. Success + 2. Success + 3. Success + 4. Success + 5. Success + 6. Success + """ + + inst = topology_st.standalone + passwd_in_history = "Secret123" + password_not_in_history = "ShouldNotBeInHistory" + (admin_group, admin1_user, admin2_user) = password_policy + + # Update config + inst.config.set('passwordAdminDN', admin_group.dn) + + # Add test entry + admin_conn = admin1_user.bind(ADMIN_PWD) + admin_users = UserAccounts(admin_conn, DEFAULT_SUFFIX) + admin_users.create(properties={ + 'uid': 'skipInfoUpdate', + 'cn': 'skipInfoUpdate', + 'sn': 'skipInfoUpdate', + 'uidNumber': '1001', + 'gidNumber': '2002', + 'homeDirectory': '/home/skipInfoUpdate', + 'userPassword': "abdcefghijk" + }) + + # Update password to populate history + user = admin_users.get('skipInfoUpdate') + user.replace('userPassword', passwd_in_history) + user.replace('userPassword', passwd_in_history) + time.sleep(1) + + # Check password history was updated + passwords = user.get_attr_vals_utf8('passwordHistory') + log.debug(f"passwords in history for {user.dn}: {str(passwords)}") + found = False + for passwd in passwords: + if passwd_in_history in passwd: + found = True + assert found + + # Disable password state info updates + inst.config.set('passwordAdminSkipInfoUpdate', 'on') + time.sleep(1) + + # Update password + user.replace('userPassword', password_not_in_history) + user.replace('userPassword', password_not_in_history) + time.sleep(1) + + # Check it is not in password history + passwords = user.get_attr_vals_utf8('passwordHistory') + log.debug(f"Part 2: passwords in history for {user.dn}: {str(passwords)}") + found = False + for passwd in passwords: + if password_not_in_history in passwd: + found = True + assert not found + + if __name__ == '__main__': # Run isolated # -s for DEBUG mode diff --git a/ldap/schema/02common.ldif b/ldap/schema/02common.ldif index 57be87a44a..00c3c79af9 100644 --- a/ldap/schema/02common.ldif +++ b/ldap/schema/02common.ldif @@ -155,6 +155,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2358 NAME 'nsTaskTotalItems' DESC 'Slapi attributeTypes: ( 2.16.840.1.113730.3.1.2359 NAME 'nsTaskCreated' DESC 'Slapi Task creation date' SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE X-ORIGIN '389 Directory Server' ) attributeTypes: ( 2.16.840.1.113730.3.1.2375 NAME 'nsTaskWarning' DESC 'Slapi Task warning code' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN '389 Directory Server' ) attributeTypes: ( 2.16.840.1.113730.3.1.2389 NAME 'winSyncFlattenTree' DESC 'When set to on, will flatten tree structure in AD replication' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN '389 Directory Server' ) +attributeTypes: ( 2.16.840.1.113730.3.1.2395 NAME ( 'passwordAdminSkipInfoUpdate' 'pwdAdminSkipInfoUpdate' ) DESC 'Netscape defined password policy attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) # # objectclasses: # @@ -167,7 +168,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.7 NAME 'nsLicenseUser' DESC 'Netscape def objectClasses: ( 2.16.840.1.113730.3.2.1 NAME 'changeLogEntry' DESC 'LDAP changelog objectclass' SUP top MUST ( targetdn $ changeTime $ changenumber $ changeType ) MAY ( changes $ newrdn $ deleteoldrdn $ newsuperior ) X-ORIGIN 'Changelog Internet Draft' ) objectClasses: ( 2.16.840.1.113730.3.2.6 NAME 'referral' DESC 'LDAP referrals objectclass' SUP top MAY ( ref ) X-ORIGIN 'LDAPv3 referrals Internet Draft' ) objectClasses: ( 2.16.840.1.113730.3.2.12 NAME 'passwordObject' DESC 'Netscape defined password policy objectclass' SUP top MAY ( pwdpolicysubentry $ passwordExpirationTime $ passwordExpWarned $ passwordRetryCount $ retryCountResetTime $ accountUnlockTime $ passwordHistory $ passwordAllowChangeTime $ passwordGraceUserTime $ pwdReset $ pwdTPRReset $ pwdTPRUseCount $ pwdTPRValidFrom $ pwdTPRExpireAt ) X-ORIGIN 'Netscape Directory Server' ) -objectClasses: ( 2.16.840.1.113730.3.2.13 NAME 'passwordPolicy' DESC 'Netscape defined password policy objectclass' SUP top MAY ( passwordMaxAge $ passwordExp $ passwordMinLength $ passwordKeepHistory $ passwordInHistory $ passwordChange $ passwordWarning $ passwordLockout $ passwordMaxFailure $ passwordResetDuration $ passwordUnlock $ passwordLockoutDuration $ passwordCheckSyntax $ passwordMustChange $ passwordStorageScheme $ passwordMinAge $ passwordResetFailureCount $ passwordGraceLimit $ passwordMinDigits $ passwordMinAlphas $ passwordMinUppers $ passwordMinLowers $ passwordMinSpecials $ passwordMin8bit $ passwordMaxRepeats $ passwordMinCategories $ passwordMinTokenLength $ passwordTrackUpdateTime $ passwordAdminDN $ passwordDictCheck $ passwordDictPath $ passwordPalindrome $ passwordMaxSequence $ passwordMaxClassChars $ passwordMaxSeqSets $ passwordBadWords $ passwordUserAttributes $ passwordSendExpiringTime $ passwordTPRMaxUse $ passwordTPRDelayExpireAt $ passwordTPRDelayValidFrom ) X-ORIGIN 'Netscape Directory Server' ) +objectClasses: ( 2.16.840.1.113730.3.2.13 NAME 'passwordPolicy' DESC 'Netscape defined password policy objectclass' SUP top MAY ( passwordMaxAge $ passwordExp $ passwordMinLength $ passwordKeepHistory $ passwordInHistory $ passwordChange $ passwordWarning $ passwordLockout $ passwordMaxFailure $ passwordResetDuration $ passwordUnlock $ passwordLockoutDuration $ passwordCheckSyntax $ passwordMustChange $ passwordStorageScheme $ passwordMinAge $ passwordResetFailureCount $ passwordGraceLimit $ passwordMinDigits $ passwordMinAlphas $ passwordMinUppers $ passwordMinLowers $ passwordMinSpecials $ passwordMin8bit $ passwordMaxRepeats $ passwordMinCategories $ passwordMinTokenLength $ passwordTrackUpdateTime $ passwordAdminDN $ passwordDictCheck $ passwordDictPath $ passwordPalindrome $ passwordMaxSequence $ passwordMaxClassChars $ passwordMaxSeqSets $ passwordBadWords $ passwordUserAttributes $ passwordSendExpiringTime $ passwordTPRMaxUse $ passwordTPRDelayExpireAt $ passwordTPRDelayValidFrom $ passwordAdminSkipInfoUpdate ) X-ORIGIN 'Netscape Directory Server' ) objectClasses: ( 2.16.840.1.113730.3.2.30 NAME 'glue' DESC 'Netscape defined objectclass' SUP top X-ORIGIN 'Netscape Directory Server' ) objectClasses: ( 2.16.840.1.113730.3.2.32 NAME 'netscapeMachineData' DESC 'Netscape defined objectclass' SUP top X-ORIGIN 'Netscape Directory Server' ) objectClasses: ( 2.16.840.1.113730.3.2.38 NAME 'vlvSearch' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ vlvBase $ vlvScope $ vlvFilter ) MAY ( multiLineDescription ) X-ORIGIN 'Netscape Directory Server' ) diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c index b73ca00ccc..6914060653 100644 --- a/ldap/servers/slapd/add.c +++ b/ldap/servers/slapd/add.c @@ -630,7 +630,7 @@ op_shared_add(Slapi_PBlock *pb) * Check password syntax, unless this is a pwd admin/rootDN */ present_values = attr_get_present_values(attr); - if (!pw_is_pwp_admin(pb, pwpolicy) && + if (!pw_is_pwp_admin(pb, pwpolicy, PWP_ADMIN_OR_ROOTDN) && check_pw_syntax(pb, slapi_entry_get_sdn_const(e), present_values, NULL, e, 0) != 0) { /* error result is sent from check_pw_syntax */ diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c index 2dbd3e6434..9f62afd835 100644 --- a/ldap/servers/slapd/libglobs.c +++ b/ldap/servers/slapd/libglobs.c @@ -266,6 +266,7 @@ slapi_onoff_t init_enable_upgrade_hash; slapi_special_filter_verify_t init_verify_filter_schema; slapi_onoff_t init_enable_ldapssotoken; slapi_onoff_t init_return_orig_dn; +slapi_onoff_t init_pw_admin_skip_info; static int isInt(ConfigVarType type) @@ -419,6 +420,11 @@ static struct config_get_and_set NULL, 0, NULL, CONFIG_STRING, (ConfigGetFunc)config_get_pw_admin_dn, "", NULL}, + {CONFIG_PW_ADMIN_SKIP_INFO_ATTRIBUTE, config_set_pw_admin_skip_info, + NULL, 0, + (void **)&global_slapdFrontendConfig.pw_policy.pw_admin_skip_info, + CONFIG_ON_OFF, (ConfigGetFunc)config_get_pw_admin_dn, + &init_pw_admin_skip_info, NULL}, {CONFIG_ACCESSLOG_LOGROTATIONSYNCENABLED_ATTRIBUTE, NULL, log_set_rotationsync_enabled, SLAPD_ACCESS_LOG, (void **)&global_slapdFrontendConfig.accesslog_rotationsync_enabled, @@ -1681,6 +1687,7 @@ pwpolicy_init_defaults (passwdPolicy *pw_policy) pw_policy->pw_tpr_delay_valid_from = SLAPD_DEFAULT_PW_TPR_DELAY_VALID_FROM; pw_policy->pw_gracelimit = SLAPD_DEFAULT_PW_GRACELIMIT; pw_policy->pw_admin = NULL; + pw_policy->pw_admin_skip_info = LDAP_OFF; pw_policy->pw_admin_user = NULL; pw_policy->pw_is_legacy = LDAP_ON; pw_policy->pw_track_update_time = LDAP_OFF; @@ -1836,6 +1843,7 @@ FrontendConfig_init(void) init_pwpolicy_inherit_global = cfg->pwpolicy_inherit_global = LDAP_OFF; init_allow_hashed_pw = cfg->allow_hashed_pw = LDAP_OFF; init_pw_is_global_policy = cfg->pw_is_global_policy = LDAP_OFF; + init_pw_admin_skip_info = cfg->pw_admin_skip_info = LDAP_OFF; init_accesslog_logging_enabled = cfg->accesslog_logging_enabled = LDAP_ON; cfg->accesslog_mode = slapi_ch_strdup(SLAPD_INIT_LOG_MODE); @@ -4148,6 +4156,21 @@ config_set_pw_admin_dn(const char *attrname __attribute__((unused)), char *value return retVal; } +int32_t +config_set_pw_admin_skip_info(const char *attrname, char *value, char *errorbuf, int apply) +{ + int32_t retVal = LDAP_SUCCESS; + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + + retVal = config_set_onoff(attrname, + value, + &(slapdFrontendConfig->pw_policy.pw_admin_skip_info), + errorbuf, + apply); + + return retVal; +} + int32_t config_set_pw_track_last_update_time(const char *attrname, char *value, char *errorbuf, int apply) { @@ -4208,7 +4231,6 @@ config_set_pw_unlock(const char *attrname, char *value, char *errorbuf, int appl return retVal; } - int32_t config_set_pw_lockout(const char *attrname, char *value, char *errorbuf, int apply) { @@ -6013,6 +6035,13 @@ config_get_pw_admin_dn(void) return retVal; } +int +config_get_pw_admin_skip_update(void) +{ + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + return (int)slapdFrontendConfig->pw_policy.pw_admin_skip_info; +} + char * config_get_pw_storagescheme(void) { diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c index e017799f7c..a20984e0b8 100644 --- a/ldap/servers/slapd/modify.c +++ b/ldap/servers/slapd/modify.c @@ -1207,7 +1207,7 @@ op_shared_allow_pw_change(Slapi_PBlock *pb, LDAPMod *mod, char **old_pw, Slapi_M slapi_pblock_set(pb, SLAPI_BACKEND, slapi_be_select(&sdn)); /* Check if ACIs allow password to be changed */ - if (!pw_is_pwp_admin(pb, pwpolicy) && (res = slapi_acl_check_mods(pb, e, mods, &errtxt)) != LDAP_SUCCESS) { + if (!pw_is_pwp_admin(pb, pwpolicy, PWP_ADMIN_OR_ROOTDN) && (res = slapi_acl_check_mods(pb, e, mods, &errtxt)) != LDAP_SUCCESS) { if (operation_is_flag_set(operation, OP_FLAG_ACTION_LOG_ACCESS)) { if (proxydn) { proxystr = slapi_ch_smprintf(" authzid=\"%s\"", proxydn); @@ -1234,7 +1234,7 @@ op_shared_allow_pw_change(Slapi_PBlock *pb, LDAPMod *mod, char **old_pw, Slapi_M * If this mod is being performed by a password administrator/rootDN, * just return success. */ - if (pw_is_pwp_admin(pb, pwpolicy)) { + if (pw_is_pwp_admin(pb, pwpolicy, PWP_ADMIN_OR_ROOTDN)) { if (!SLAPI_IS_MOD_DELETE(mod->mod_op) && pwpolicy->pw_history) { /* Updating pw history, get the old password */ get_old_pw(pb, &sdn, old_pw); diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h index 3e773e222d..cb69a1b501 100644 --- a/ldap/servers/slapd/proto-slap.h +++ b/ldap/servers/slapd/proto-slap.h @@ -348,6 +348,7 @@ int config_set_pw_is_legacy_policy(const char *attrname, char *value, char *erro int config_set_pw_track_last_update_time(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_pw_admin_dn(const char *attrname, char *value, char *errorbuf, int apply); +int32_t config_set_pw_admin_skip_info(const char *attrname, char *value, char *errorbuf, int apply); int config_set_pw_send_expiring(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.c b/ldap/servers/slapd/pw.c index 26d584bdd2..24c2dc3893 100644 --- a/ldap/servers/slapd/pw.c +++ b/ldap/servers/slapd/pw.c @@ -667,6 +667,9 @@ update_pw_info(Slapi_PBlock *pb, char *old_pw) internal_op = slapi_operation_is_flag_set(operation, SLAPI_OP_FLAG_INTERNAL); target_dn = slapi_sdn_get_ndn(sdn); pwpolicy = new_passwdPolicy(pb, target_dn); + if (pw_is_pwp_admin(pb, pwpolicy, PWP_ADMIN_ONLY) && pwpolicy->pw_admin_skip_info) { + return 0; + } cur_time = slapi_current_utc_time(); slapi_mods_init(&smods, 0); @@ -744,7 +747,7 @@ update_pw_info(Slapi_PBlock *pb, char *old_pw) */ if ((internal_op && pwpolicy->pw_must_change && (!pb_conn || strcasecmp(target_dn, pb_conn->c_dn))) || (!internal_op && pwpolicy->pw_must_change && - ((target_dn && bind_dn && strcasecmp(target_dn, bind_dn)) && pw_is_pwp_admin(pb, pwpolicy)))) + ((target_dn && bind_dn && strcasecmp(target_dn, bind_dn)) && pw_is_pwp_admin(pb, pwpolicy, PWP_ADMIN_OR_ROOTDN)))) { pw_exp_date = NO_TIME; slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "pwdReset", "TRUE"); @@ -1116,7 +1119,7 @@ check_pw_syntax_ext(Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals, c if (slapi_is_encoded((char *)slapi_value_get_string(vals[i]))) { if (!is_replication && !config_get_allow_hashed_pw() && ((internal_op && pb_conn && !slapi_dn_isroot(pb_conn->c_dn)) || - (!internal_op && !pw_is_pwp_admin(pb, pwpolicy)))) + (!internal_op && !pw_is_pwp_admin(pb, pwpolicy, PWP_ADMIN_OR_ROOTDN)))) { report_pw_violation(pb, dn, pwresponse_req, "invalid password syntax - passwords with storage scheme are not allowed"); return (1); @@ -1894,7 +1897,7 @@ check_trivial_words(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Value **vals, char * } int -pw_is_pwp_admin(Slapi_PBlock *pb, passwdPolicy *pwp) +pw_is_pwp_admin(Slapi_PBlock *pb, passwdPolicy *pwp, int rootdn_flag) { Slapi_DN *bind_sdn = NULL; int i; @@ -1903,7 +1906,7 @@ pw_is_pwp_admin(Slapi_PBlock *pb, passwdPolicy *pwp) slapi_pblock_get(pb, SLAPI_REQUESTOR_ISROOT, &is_requestor_root); /* first check if it's root */ - if (is_requestor_root) { + if (is_requestor_root && rootdn_flag == PWP_ADMIN_OR_ROOTDN) { return 1; } /* now check if it's a Password Policy Administrator */ @@ -2323,6 +2326,11 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn) pwdpolicy->pw_admin = slapi_sdn_new_dn_byval(slapi_value_get_string(*sval)); pw_get_admin_users(pwdpolicy); } + } else if (!strcasecmp(attr_name, "passwordAdminSkipInfoUpdate")) { + if ((sval = attr_get_present_values(attr))) { + pwdpolicy->pw_admin_skip_info = + pw_boolean_str2value(slapi_value_get_string(*sval)); + } } else if (!strcasecmp(attr_name, "passwordPalindrome")) { if ((sval = attr_get_present_values(attr))) { pwdpolicy->pw_palindrome = diff --git a/ldap/servers/slapd/pw.h b/ldap/servers/slapd/pw.h index 8b3fb368cc..b2fd7c7842 100644 --- a/ldap/servers/slapd/pw.h +++ b/ldap/servers/slapd/pw.h @@ -41,7 +41,10 @@ int check_pw_duration_value(const char *attr_name, char *value, long minval, lon int check_pw_resetfailurecount_value(const char *attr_name, char *value, long minval, long maxval, char *errorbuf, size_t ebuflen); int check_pw_storagescheme_value(const char *attr_name, char *value, long minval, long maxval, char *errorbuf, size_t ebuflen); -int pw_is_pwp_admin(Slapi_PBlock *pb, struct passwordpolicyarray *pwp); +int pw_is_pwp_admin(Slapi_PBlock *pb, struct passwordpolicyarray *pwp, int rootdn_flag); +#define PWP_ADMIN_OR_ROOTDN 0 +#define PWP_ADMIN_ONLY 1 + /* * Public functions from pw_retry.c: */ diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h index f56ddb378e..41d9315f72 100644 --- a/ldap/servers/slapd/slap.h +++ b/ldap/servers/slapd/slap.h @@ -1879,6 +1879,7 @@ typedef struct passwordpolicyarray struct pw_scheme *pw_storagescheme; Slapi_DN *pw_admin; Slapi_DN **pw_admin_user; + slapi_onoff_t pw_admin_skip_info; /* Skip updating password information in target entry */ char *pw_local_dn; /* DN of the subtree/user policy */ } passwdPolicy; @@ -2287,6 +2288,7 @@ typedef struct _slapdEntryPoints #define CONFIG_PW_IS_LEGACY "passwordLegacyPolicy" #define CONFIG_PW_TRACK_LAST_UPDATE_TIME "passwordTrackUpdateTime" #define CONFIG_PW_ADMIN_DN_ATTRIBUTE "passwordAdminDN" +#define CONFIG_PW_ADMIN_SKIP_INFO_ATTRIBUTE "passwordAdminSkipInfoUpdate" #define CONFIG_PW_SEND_EXPIRING "passwordSendExpiringTime" #define CONFIG_ACCESSLOG_BUFFERING_ATTRIBUTE "nsslapd-accesslog-logbuffering" #define CONFIG_SECURITYLOG_BUFFERING_ATTRIBUTE "nsslapd-securitylog-logbuffering" @@ -2709,6 +2711,7 @@ typedef struct _slapdFrontendConfig slapi_int_t tcp_keepalive_time; int32_t referral_check_period; slapi_onoff_t return_orig_dn; + slapi_onoff_t pw_admin_skip_info; char *auditlog_display_attrs; } slapdFrontendConfig_t; diff --git a/src/Cargo.lock b/src/Cargo.lock index d1ae4ebcdf..b1dd53ea79 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -340,9 +340,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.142" +version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "librnsslapd" @@ -365,9 +365,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.3.4" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf" +checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" [[package]] name = "lock_api" @@ -435,7 +435,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -502,9 +502,9 @@ checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "ppv-lite86" @@ -520,9 +520,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8" dependencies = [ "unicode-ident", ] @@ -542,9 +542,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" dependencies = [ "proc-macro2", ] @@ -599,9 +599,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.15" +version = "0.37.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0661814f891c57c930a610266415528da53c4933e6dea5fb350cbfe048a9ece" +checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" dependencies = [ "bitflags", "errno", @@ -625,22 +625,22 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.160" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.160" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -695,9 +695,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" dependencies = [ "proc-macro2", "quote", @@ -728,9 +728,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.28.0" +version = "1.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f" +checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" dependencies = [ "autocfg", "pin-project-lite", @@ -746,7 +746,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -974,5 +974,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] diff --git a/src/cockpit/389-console/src/lib/database/globalPwp.jsx b/src/cockpit/389-console/src/lib/database/globalPwp.jsx index 8814d919f0..13157383cf 100644 --- a/src/cockpit/389-console/src/lib/database/globalPwp.jsx +++ b/src/cockpit/389-console/src/lib/database/globalPwp.jsx @@ -34,6 +34,7 @@ const general_attrs = [ "nsslapd-pwpolicy-local", "passwordstoragescheme", "passwordadmindn", + "passwordadminskipinfoupdate", "passwordtrackupdatetime", "nsslapd-allow-hashed-passwords", "nsslapd-pwpolicy-inherit-global", @@ -623,60 +624,64 @@ export class GlobalPwPolicy extends React.Component { let pwDictCheck = false; let pwAllowHashed = false; let pwInheritGlobal = false; + let pwAdminSkipUpdates = false; let pwUserAttrs = []; - if (attrs['nsslapd-pwpolicy-local'][0] == "on") { + if (attrs['nsslapd-pwpolicy-local'][0] === "on") { pwpLocal = true; } - if (attrs.passwordchange[0] == "on") { + if (attrs.passwordchange[0] === "on") { pwChange = true; } - if (attrs.passwordmustchange[0] == "on") { + if (attrs.passwordmustchange[0] === "on") { pwMustChange = true; } - if (attrs.passwordhistory[0] == "on") { + if (attrs.passwordhistory[0] === "on") { pwHistory = true; } - if (attrs.passwordtrackupdatetime[0] == "on") { + if (attrs.passwordtrackupdatetime[0] === "on") { pwTrackUpdate = true; } - if (attrs.passwordisglobalpolicy[0] == "on") { + if (attrs.passwordisglobalpolicy[0] === "on") { pwIsGlobal = true; } - if (attrs.passwordsendexpiringtime[0] == "on") { + if (attrs.passwordsendexpiringtime[0] === "on") { pwSendExpire = true; } - if (attrs.passwordlockout[0] == "on") { + if (attrs.passwordlockout[0] === "on") { pwLockout = true; } - if (attrs.passwordunlock[0] == "on") { + if (attrs.passwordunlock[0] === "on") { pwUnlock = true; } - if (attrs.passwordexp[0] == "on") { + if (attrs.passwordexp[0] === "on") { pwExpire = true; } - if (attrs.passwordchecksyntax[0] == "on") { + if (attrs.passwordchecksyntax[0] === "on") { pwCheckSyntax = true; } - if (attrs.passwordpalindrome[0] == "on") { + if (attrs.passwordpalindrome[0] === "on") { pwPalindrome = true; } - if (attrs.passworddictcheck[0] == "on") { + if (attrs.passworddictcheck[0] === "on") { pwDictCheck = true; } - if (attrs['nsslapd-allow-hashed-passwords'][0] == "on") { + if (attrs['nsslapd-allow-hashed-passwords'][0] === "on") { pwAllowHashed = true; } - if (attrs['nsslapd-pwpolicy-inherit-global'][0] == "on") { + if (attrs['nsslapd-pwpolicy-inherit-global'][0] === "on") { pwInheritGlobal = true; } - if (attrs.passwordbadwords[0] != "") { + if (attrs.passwordadminskipinfoupdate[0] === "on") { + pwAdminSkipUpdates = true; + } + if (attrs.passwordbadwords[0] !== "") { // Hack until this is fixed: https://github.com/389ds/389-ds-base/issues/3928 if (attrs.passwordbadwords.length > 1) { attrs.passwordbadwords[0] = attrs.passwordbadwords.join(' '); } } - if (attrs.passworduserattributes[0] != "") { + if (attrs.passworduserattributes[0] !== "") { if (attrs.passworduserattributes.length > 1) { // Hack until this is fixed: https://github.com/389ds/389-ds-base/issues/3928 attrs.passworduserattributes[0] = attrs.passworduserattributes.join(' '); @@ -741,6 +746,7 @@ export class GlobalPwPolicy extends React.Component { passwordbadwords: attrs.passwordbadwords[0], passworduserattributes: pwUserAttrs, passwordadmindn: attrs.passwordadmindn[0], + passwordadminskipinfoupdate: pwAdminSkipUpdates, passwordtprmaxuse: attrs.passwordtprmaxuse[0], passwordtprdelayexpireat: attrs.passwordtprdelayexpireat[0], passwordtprdelayvalidfrom: attrs.passwordtprdelayvalidfrom[0], @@ -785,6 +791,7 @@ export class GlobalPwPolicy extends React.Component { _passwordbadwords: attrs.passwordbadwords[0], _passworduserattributes: pwUserAttrs, _passwordadmindn: attrs.passwordadmindn[0], + _passwordadminskipinfoupdate: pwAdminSkipUpdates, _passwordtprmaxuse: attrs.passwordtprmaxuse[0], _passwordtprdelayexpireat: attrs.passwordtprdelayexpireat[0], _passwordtprdelayvalidfrom: attrs.passwordtprdelayvalidfrom[0], @@ -1412,6 +1419,20 @@ export class GlobalPwPolicy extends React.Component { /> + + + { + this.handleGeneralChange(e); + }} + label="Do not update target entry's password state attributes" + /> + +