Bug 1813698

Summary: krbPwdHistoryLength not honoured: passwordHistory gets updated even if password change is rejected
Product: Red Hat Enterprise Linux 8 Reporter: rmitra
Component: ipaAssignee: Florence Blanc-Renaud <frenaud>
Status: ASSIGNED --- QA Contact: ipa-qe <ipa-qe>
Severity: medium Docs Contact:
Priority: high    
Version: ---CC: engops-jira, pasik, rcritten, spichugi, tbordaz, tscherf, vashirov
Target Milestone: rcKeywords: Triaged
Target Release: 8.0   
Hardware: Unspecified   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description rmitra 2020-03-15 15:23:38 UTC
Description of problem
======================

The "passwordHistory" attribute for a user gets updated even if a password change fails due to password repetition.

Version-Release number of selected component (if applicable):
RHEL 7.7, also applicable to lower RHEL7 versions.


How reproducible
================

The issue can be reproduced for the following condition:

1. Create an IPA user and set its password history = 3.

2. Using "ldapmodify", set the user password to:

password1,
password2,
password3

All 3 passwords are stored in history.

3. Change password to:

password2 (or password 3)

This fails as expected, however, the passwordHistory is still updated.

4. Then change to:

password1

This succeeds even though its among the last 3 used passwords. The reason is because the "passwordHistory" update in step 3 has replaced the "password1" entry.

--------

Basically this can be generalized to the condition:

1. Set history=n for LDAP user.

2. Change to: password1

3. Try "n" password change attempts, either successful, or failed attempts due to repeating passwords.

4. Change to: password1, this succeeds though password is within "n" last used passwords.


Steps to Reproduce
==================
TBD



Actual results
==============
The "passwordHistory" attribute for a user gets updated even if a password change fails due to password repetition.


Expected results
================

Ideally the "passwordHistory" attribute is expected to not get updated if the password change has failed due to any reason, in this case due to password repetition.

Comment 2 rmitra 2020-03-15 17:21:28 UTC
Steps to Reproduce
==================

1. Create an IPA user and set its password history = 3.

# ipa user-add ipauser
# ipa passwd ipauser

# ipa group-add newpolicy
# ipa pwpolicy-mod newpolicy --history=3 --priority=2 --maxlife=0 --minlife=0
# ipa group-add-member newpolicy --users=ipauser

========

2. Update user password as follows:

passwordA, passwordB, passwordC

# ldapmodify -D "cn=Directory Manager" -W -f moda.ldif    (PasswordA)
# ldapmodify -D "cn=Directory Manager" -W -f modb.ldif    (attempt 1 after passwordA)
# ldapmodify -D "cn=Directory Manager" -W -f modc.ldif    (attempt 2 after passwordA)

==> All 3 passwords are stored in history as verified from the updated passwordHistory attribute.

# ldapsearch -x -LLL -h localhost  -D 'cn=directory manager' -w RedHat1! -b "uid=ipauser,cn=users,cn=accounts,<base_dn>" passwordHistory

--------

==> Here, moda.ldif, modb.ldif and modc.ldif have the following contents:

dn: uid=ipauser,cn=users,cn=accounts,<base_dn>
changetype: modify
replace: userpassword
userpassword: PasswordA

dn: uid=ipauser,cn=users,cn=accounts,<base_dn>
changetype: modify
replace: userpassword
userpassword: PasswordB

dn: uid=ipauser,cn=users,cn=accounts,<base_dn>
changetype: modify
replace: userpassword
userpassword: PasswordC

========

3. Then change password to passwordB or passwordC, i.e. any used password except PasswordA.

# ldapmodify -D "cn=Directory Manager" -W -f modb.ldif    (attempt 3 after passwordA)

or,

# ldapmodify -D "cn=Directory Manager" -W -f modb.ldif

==> This fails as expected with the following error:

modifying entry "uid=ipauser,cn=users,cn=accounts,<base_dn>"
ldap_modify: Constraint violation (19)
	additional info: Password reuse not permitted


==> However, passwordHistory gets updated in spite of password rejection, as verified by the following:

# ldapsearch -x -LLL -h localhost  -D 'cn=directory manager' -w RedHat1! -b "uid=ipauser,cn=users,cn=accounts,<base_dn>" passwordHistory

========

4. Change password to passwordA, i.e. this comes after 3 password change attempts, whether successful or failed due to repeated passwords.

# ldapmodify -D "cn=Directory Manager" -W -f moda.ldif    (attempt has exceeded history=3)

==> This succeeds even though passwordA is among the last 3 used passwords. This is because passwordHistory entry for PasswordA had been overwritten in step 3, though the password change didn't happen.

==> Ideally this step should also throw the "Constraint violation (19): Password reuse not permitted" LDAP error. Is this a correct expectation ?

Comment 3 Simon Pichugin 2020-04-16 14:21:22 UTC
https://pagure.io/389-ds-base/issue/51027

Comment 5 Simon Pichugin 2020-04-21 16:56:29 UTC
Hi,
after more investigation, I found that the issue happens in IPA Password Policy code. 
passwordHistory in RHDS is okay and doesn't have the bug (I'll add a test to our codebase that I wrote while investigating).


I've tried to look into IPA's code and got only to this point:

- passwordHistory is set in two places:
https://github.com/freeipa/freeipa/blob/dbf5df4a66b68f62a9e063c43a30b46e539c603b/daemons/ipa-slapi-plugins/ipa-pwd-extop/common.c#L895
https://github.com/freeipa/freeipa/blob/dbf5df4a66b68f62a9e063c43a30b46e539c603b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c#L1132

- passwordHistory is checked here:
https://github.com/freeipa/freeipa/blob/6907a0cef7f22293c16df17aa486f7ec2d8a0899/util/ipa_pwd.c#L528
https://github.com/freeipa/freeipa/blob/dbf5df4a66b68f62a9e063c43a30b46e539c603b/daemons/ipa-slapi-plugins/ipa-pwd-extop/common.c#L646

I hope that helps! Changing the component to IPA...

Comment 7 Rob Crittenden 2020-04-23 22:36:16 UTC
This is also reproducible as a user and that should really be the target case. It is a separate but related bug that password policy is applied at all to the DM.

The issue seems to be in prepost.c in ipapwd_pre_mod. The mods are calculated and policy checked but on exit if there are mods they are stored using:

slapi_pblock_set(pb, SLAPI_MODIFY_MODS, mods);

Which then carries onto the rest of the request and the password is updated. I'm not sure if the the right move here is to skip saving the mods if rc != 0 or if needs to be caught elsewhere.

Comment 9 Petr Čech 2020-05-19 07:27:56 UTC
Thank you taking your time and submitting this request for Red Hat Enterprise Linux 7. Unfortunately, this bug cannot be kept even as a stretch goal and was postponed to RHEL8.