Bug 2193060 - IdM password policy undefined maxlife does not unset password expiration
Summary: IdM password policy undefined maxlife does not unset password expiration
Keywords:
Status: NEW
Alias: None
Product: Red Hat Enterprise Linux 9
Classification: Red Hat
Component: ipa
Version: 9.1
Hardware: All
OS: All
unspecified
low
Target Milestone: rc
: ---
Assignee: Florence Blanc-Renaud
QA Contact: ipa-qe
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2023-05-04 07:17 UTC by Sunny Wu
Modified: 2023-08-02 12:52 UTC (History)
2 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed:
Type: Bug
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Issue Tracker FREEIPA-9842 0 None None None 2023-05-04 07:18:17 UTC
Red Hat Issue Tracker RHELPLAN-156377 0 None None None 2023-05-04 07:18:20 UTC

Description Sunny Wu 2023-05-04 07:17:02 UTC
Description of problem:

If "maxlife" of password policy is undefined, password expiration is set to current day + 90. This value is undocumented. 

The behaviour should be align with (https://bugzilla.redhat.com/show_bug.cgi?id=826790) to disable password expiration. Alternatively, update product documentation to specify this default value (90).

========================

$ ipa pwpolicy-find
  Group: ipausers
  Priority: 10
  Grace login limit: -1

  Group: global_policy
  Max lifetime (days): 90
  Min lifetime (hours): 1
  History size: 0
  Character classes: 0
  Min length: 8
  Max failures: 6
  Failure reset interval: 60
  Lockout duration: 600
  Grace login limit: -1
----------------------------
Number of entries returned 2
----------------------------

$ ipa pwpolicy-show --user=user1
  Group: ipausers
  Grace login limit: -1

$ ipa user-show user1 --all
  dn: uid=user1,cn=users,cn=accounts,dc=<...>
  User login: user1
  First name: Userfirst
  Last name: Userlast
  Full name: Userfirst Userlast
  Display name: Userfirst Userlast
  Initials: UU
  Home directory: /home/user1
  GECOS: Userfirst Userlast
  Login shell: /bin/sh
  Principal name: user1@<...>
  Principal alias: user1@<...>
  User password expiration: 20230802062556Z             <<<<<=====
  Email address: user1@<...>
  UID: 1188200003
  GID: 1188200003
  Account disabled: False
  Preserved user: False
  Password: True
  Member of groups: ipausers
  Kerberos keys available: True
  ipantsecurityidentifier: S-1-5-21-<...>
  ipauniqueid: a4c2c5ce-<...>
  krbextradata: AAL0T1Nka2FkbWluZEBTVVdVUkhFTDlBLkxBQi5QU0kuUE5RMi5SRURIQVQuQ09NAA==
  krblastpwdchange: 20230504062556Z
  krbloginfailedcount: 0
  krbpwdpolicyreference: cn=ipausers,cn=<...>
  krbticketflags: 128
  mepmanagedentry: cn=user1,cn=groups,cn=accounts,dc=<...>
  objectclass: top, person, organizationalperson, inetorgperson, inetuser,
               posixaccount, krbprincipalaux, krbticketpolicyaux, ipaobject,
               ipasshuser, ipaSshGroupOfPubKeys, mepOriginEntry, ipantuserattrs

$ ipa user-mod user1 --password-expiration=20500101010000Z
---------------------
Modified user "user1"
---------------------
  User login: user1
  First name: Userfirst
  Last name: Userlast
  Home directory: /home/user1
  Login shell: /bin/sh
  Principal name: user1@<...>
  Principal alias: user1@<...>
  User password expiration: 20500101010000Z
  Email address: user1@<...>
  UID: 1188200003
  GID: 1188200003
  Account disabled: False
  Password: True
  Member of groups: ipausers
  Kerberos keys available: True

==========

$ id
uid=1188200003(user1) gid=1188200003(user1) groups=1188200003(user1) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

$ passwd
Changing password for user user1.
Current Password: 
New password: 
Retype new password: 
passwd: all authentication tokens updated successfully.

$ ipa user-show user1 --all
  dn: uid=user1,cn=users,cn=accounts,dc=<...>
  User login: user1
  First name: Userfirst
  Last name: Userlast
  Full name: Userfirst Userlast
  Display name: Userfirst Userlast
  Initials: UU
  Home directory: /home/user1
  GECOS: Userfirst Userlast
  Login shell: /bin/sh
  Principal name: user1@<...>
  Principal alias: user1@<...>
  User password expiration: 20230802063701Z     <<<<<=====
  Email address: user1@<...>
  UID: 1188200003
  GID: 1188200003
  Account disabled: False
  Preserved user: False
  Password: True
  Member of groups: ipausers
  Kerberos keys available: True
  ipantsecurityidentifier: S-1-5-21-<...>
  ipauniqueid: a4c2c5ce-<...>
  krblastpwdchange: 20230504063701Z
  objectclass: top, person, organizationalperson, inetorgperson, inetuser,
               posixaccount, krbprincipalaux, krbticketpolicyaux, ipaobject,
               ipasshuser, ipaSshGroupOfPubKeys, mepOriginEntry, ipantuserattrs


password expiration is disabled if maxlife=0
=============================================================

$ ipa pwpolicy-mod ipausers --maxlife=0 --minlife=0
  Group: ipausers
  Max lifetime (days): 0
  Min lifetime (hours): 0
  Priority: 10
  Grace login limit: -1

$ ipa pwpolicy-show --user=user1
  Group: ipausers
  Max lifetime (days): 0
  Min lifetime (hours): 0
  Grace login limit: -1

$ ipa user-mod user1 --password-expiration=20500101010000Z
---------------------
Modified user "user1"
---------------------
  User login: user1
  First name: Userfirst
  Last name: Userlast
  Home directory: /home/user1
  Login shell: /bin/sh
  Principal name: user1@<...>
  Principal alias: user1@<...>
  User password expiration: 20500101010000Z
  Email address: user1@<...>
  UID: 1188200003
  GID: 1188200003
  Account disabled: False
  Password: True
  Member of groups: ipausers
  Kerberos keys available: True

$ passwd
Changing password for user user1.
Current Password: 
New password: 
Retype new password: 
passwd: all authentication tokens updated successfully.


$ ipa user-show user1 --all
  dn: uid=user1,cn=users,cn=accounts,dc=<...>
  User login: user1
  First name: Userfirst
  Last name: Userlast
  Full name: Userfirst Userlast
  Display name: Userfirst Userlast
  Initials: UU
  Home directory: /home/user1
  GECOS: Userfirst Userlast
  Login shell: /bin/sh
  Principal name: user1@<...>
  Principal alias: user1@<...>
  Email address: user1@<...>
  UID: 1188200003
  GID: 1188200003
  Account disabled: False
  Preserved user: False
  Password: True
  Member of groups: ipausers
  Kerberos keys available: True
  ipantsecurityidentifier: S-1-5-21-<...>
  ipauniqueid: a4c2c5ce-<...>
  krblastpwdchange: 20230504065345Z
  objectclass: top, person, organizationalperson, inetorgperson, inetuser,
               posixaccount, krbprincipalaux, krbticketpolicyaux, ipaobject,
               ipasshuser, ipaSshGroupOfPubKeys, mepOriginEntry, ipantuserattrs

=============================================================

Version-Release number of selected component (if applicable):
# rpm -qa | grep ipa | sort
ipa-client-4.10.0-8.el9_1.x86_64
ipa-client-common-4.10.0-8.el9_1.noarch
ipa-common-4.10.0-8.el9_1.noarch
ipa-healthcheck-core-0.9-9.el9.noarch
ipa-selinux-4.10.0-8.el9_1.noarch
ipa-server-4.10.0-8.el9_1.x86_64
ipa-server-common-4.10.0-8.el9_1.noarch
ipa-server-dns-4.10.0-8.el9_1.noarch

How reproducible:
100%


Actual results:
If "maxlife" is undefined, password expiration is set to 90 days.

Expected results:
If "maxlife" is undefined, password expiration should be disabled.

Comment 1 Rob Crittenden 2023-05-08 12:42:51 UTC
There is a default 90-day expiration policy if maxlife is not explicitly defined in the password policy.

We can update the pwpolicy module built-in help to reflect this.

Comment 2 Sunny Wu 2023-05-09 04:39:57 UTC
90 days = 2160 (90 x 24) hours.

If maxlife is undefined, then default 90 will apply.

It is still not quite right...

# ipa pwpolicy-mod ipausers --maxlife=1 --minlife=25
ipa: ERROR: invalid 'maxlife': Maximum password life must be equal to or greater than the minimum.

# ipa pwpolicy-mod ipausers --maxlife=90 --minlife=2161
ipa: ERROR: invalid 'maxlife': Maximum password life must be equal to or greater than the minimum.

# ipa pwpolicy-mod ipausers --minlife=2161
  Group: ipausers
  Min lifetime (hours): 2161
  Priority: 10
  Grace login limit: -1

Comment 3 Sunny Wu 2023-05-09 04:44:34 UTC
(In reply to Rob Crittenden from comment #1)
> There is a default 90-day expiration policy if maxlife is not explicitly
> defined in the password policy.
> 
> We can update the pwpolicy module built-in help to reflect this.

Please include usage for both zero and NULL value.

Comment 4 Sunny Wu 2023-05-09 05:26:09 UTC
Further testing found that there is discrepancy when applying the default value:
1. User changes its password using `passwd`
2. User changes its password using `ipa user-mod --password <user>`

When maxlife is NULL, 90 days will apply in (#1), but unset in (#2). Behaviour of command line `ipa` and WebUI is identical.

# ipa pwpolicy-show --user=bob
  Group: ipausers
  Grace login limit: -1

=====
$ id
uid=1404800003(bob) gid=1404800003(bob) groups=1404800003(bob) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

$ klist
Ticket cache: KCM:1404800003:16132
Default principal: bob@<...>

Valid starting     Expires            Service principal
05/09/23 15:09:08  05/10/23 14:38:09  HTTP/node-0.<...>@<...>
05/09/23 15:09:04  05/10/23 14:38:09  krbtgt/<...>@<...>

$ passwd
Changing password for user bob.
Current Password: 
New password: 
Retype new password: 
passwd: all authentication tokens updated successfully.

$ ipa user-show bob --all
  dn: uid=bob,cn=users,cn=accounts,dc=<...>
  User login: bob
  First name: Bob
  Last name: User
  Full name: Bob User
  Display name: Bob User
  Initials: BU
  Home directory: /home/bob
  GECOS: Bob User
  Login shell: /bin/sh
  Principal name: bob@<...>
  Principal alias: bob@<...>
  User password expiration: 20230807051439Z                  <<<<<=====
  Email address: bob@<...>
  UID: 1404800003
  GID: 1404800003
  Account disabled: False
  Preserved user: False
  Password: True
  Member of groups: ipausers
  Kerberos keys available: True
  ipantsecurityidentifier: S-1-5-21-<...>
  ipauniqueid: 61c13ac8-<...>
  krblastpwdchange: 20230509051439Z
  objectclass: top, person, organizationalperson, inetorgperson, inetuser,
               posixaccount, krbprincipalaux, krbticketpolicyaux, ipaobject,
               ipasshuser, ipaSshGroupOfPubKeys, mepOriginEntry, ipantuserattrs

$ ipa user-mod --password bob
Password: 
Enter Password again to verify: 
-------------------
Modified user "bob"
-------------------
  User login: bob
  First name: Bob
  Last name: User
  Home directory: /home/bob
  Login shell: /bin/sh
  Principal name: bob@<...>
  Principal alias: bob@<...>
  Email address: bob@<...>
  UID: 1404800003
  GID: 1404800003
  Account disabled: False
  Password: True
  Member of groups: ipausers
  Kerberos keys available: True

$ ipa user-show bob --all
  dn: uid=bob,cn=users,cn=accounts,dc=<...>
  User login: bob
  First name: Bob
  Last name: User
  Full name: Bob User
  Display name: Bob User
  Initials: BU
  Home directory: /home/bob
  GECOS: Bob User
  Login shell: /bin/sh
  Principal name: bob@<...>
  Principal alias: bob@<...>
  Email address: bob@<...>
  UID: 1404800003
  GID: 1404800003
  Account disabled: False
  Preserved user: False
  Password: True
  Member of groups: ipausers
  Kerberos keys available: True
  ipantsecurityidentifier: S-1-5-21-<...>
  ipauniqueid: 61c13ac8-<...>
  krblastpwdchange: 20230509052130Z
  objectclass: top, person, organizationalperson, inetorgperson, inetuser,
               posixaccount, krbprincipalaux, krbticketpolicyaux, ipaobject,
               ipasshuser, ipaSshGroupOfPubKeys, mepOriginEntry, ipantuserattrs

$ passwd
Changing password for user bob.
Current Password: 
New password: 
Retype new password: 
passwd: all authentication tokens updated successfully.

$ ipa user-show bob --all
  dn: uid=bob,cn=users,cn=accounts,dc=<...>
  User login: bob
  First name: Bob
  Last name: User
  Full name: Bob User
  Display name: Bob User
  Initials: BU
  Home directory: /home/bob
  GECOS: Bob User
  Login shell: /bin/sh
  Principal name: bob@<...>
  Principal alias: bob@<...>
  User password expiration: 20230807052332Z                  <<<<<=====
  Email address: bob@<...>
  UID: 1404800003
  GID: 1404800003
  Account disabled: False
  Preserved user: False
  Password: True
  Member of groups: ipausers
  Kerberos keys available: True
  ipantsecurityidentifier: S-1-5-21-<...>
  ipauniqueid: 61c13ac8-<...>
  krblastpwdchange: 20230509052332Z
  objectclass: top, person, organizationalperson, inetorgperson, inetuser,
               posixaccount, krbprincipalaux, krbticketpolicyaux, ipaobject,
               ipasshuser, ipaSshGroupOfPubKeys, mepOriginEntry, ipantuseratt

Comment 5 Rob Crittenden 2023-05-17 15:23:18 UTC
The difference is the paths that passwd vs ipa passwd take. passwd goes through as a Kerberos password change and ipa passwd is done via LDAP. The backends are necessarily different.

The LDAP policy code treats a non-existent value as 0 and Kerberos defaults to 90.

I propose the LDAP code also default to 90 if no value is set but still honor if 0 is. And document the 90-day default.

Comment 6 Sunny Wu 2023-05-18 01:58:07 UTC
Thank you. Please also review issue described in "comment 2" that "ipa pwpolicy-mod" allows the implicit (default) value of 90 to be added.

Comment 7 Sunny Wu 2023-08-02 03:40:05 UTC
@rcritten 

I just wanted to point out the issue more explicit.

One of the constraints is: maxlife must be greater than or equal to minlife.

The first command is declined - OK. 
The second command was executed successfully - Not OK. 

As "maxlife" has a default value of "90", two commands should have identical effect. However, the latter command does not evaluate default value if omitted, and the constraint is circumvented.

(In reply to Sunny Wu from comment #2)
> 90 days = 2160 (90 x 24) hours.
> 
> # ipa pwpolicy-mod ipausers --maxlife=90 --minlife=2161
> ipa: ERROR: invalid 'maxlife': Maximum password life must be equal to or
> greater than the minimum.
> 
> # ipa pwpolicy-mod ipausers --minlife=2161
>   Group: ipausers
>   Min lifetime (hours): 2161
>   Priority: 10
>   Grace login limit: -1

Comment 8 Rob Crittenden 2023-08-02 12:52:30 UTC
Right. Since maxlife is treated as having a default value in the plugin it needs to be an explicit default value in all group policies. This may be disruptive to existing installs that have relied on the old behavior though.


Note You need to log in before you can comment on or make changes to this bug.