Bug 2121099

Summary: Incorrect password expiration handling [rhel-9]
Product: Red Hat Enterprise Linux 9 Reporter: Marko Myllynen <myllynen>
Component: krb5Assignee: Julien Rische <jrische>
Status: CLOSED ERRATA QA Contact: Filip Dvorak <fdvorak>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 9.0CC: fdvorak, ftrivino, rcritten, tscherf
Target Milestone: rcKeywords: Triaged
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: krb5-1.20.1-3.el9 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of:
: 2125318 2129113 (view as bug list) Environment:
Last Closed: 2023-05-09 08:25:24 UTC 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:
Bug Depends On:    
Bug Blocks: 2129113    

Description Marko Myllynen 2022-08-24 12:57:53 UTC
Description of problem:
Trying to prevent admin password to expire I set it to 2099-12-13 23:59:59 (with ansible-freeipa/ipauser). This date is now displayed on the Web UI but when doing kinit this warning is printed:

# kinit admin                            
Password for admin.COM:   
Warning: Your password will expire in less than one hour on Mon Dec 14 01:59:59 2099

If the given date is too distant in the future then I would have expected it to be rejected. However, this does not look like a 2038 issue as e.g. 2089-12-31 23:59:59 does not cause such a warning.

Version-Release number of selected component (if applicable):
ipa-common-4.9.8-7.module+el8.6.0+14337+19b76db2.noarch

Comment 1 Marko Myllynen 2022-08-24 13:05:13 UTC
It is also unclear what is the timezone in use here, perhaps that should be filed as another bug? Consider a case of 4 IdM servers where two of them are on different timezone than the others. What is the UTC time when the password will actually expire? Thanks.

Comment 2 Florence Blanc-Renaud 2022-08-24 17:08:36 UTC
The issue is easily reproduced by setting the expiration date using ipa user-mod --password-expiration=DATE.

(In reply to Marko Myllynen from comment #0)
> If the given date is too distant in the future then I would have expected it
> to be rejected. However, this does not look like a 2038 issue as e.g.
> 2089-12-31 23:59:59 does not cause such a warning.

It is a similar issue because the check is evaluating a delta between 2 timestamps, now and the expiration date, and if the delta overflows the buffer we have unpredictable behavior. The delta is also represented as a signed 32 bit integer, meaning the buffer overflow happens if the 2 dates are distant of more than ~68 years, which fits nicely with the behavior described here (2022 + 68 = 2090 is the pivot point).


Relevant code:
--------------
https://github.com/krb5/krb5/blob/70f61d417261ca17efe3d60d180033bea2da60b0/src/lib/krb5/krb/get_in_tkt.c#L1567-L1571
    delta = ts_delta(pw_exp, now);
    if (delta < 3600) {
        snprintf(banner, sizeof(banner),
                 _("Warning: Your password will expire in less than one hour "
                   "on %s"), ts);

and the definition of ts_delta:
https://github.com/krb5/krb5/blob/70f61d417261ca17efe3d60d180033bea2da60b0/src/include/k5-int.h#L2319-L2325
/* Return the delta between two timestamps (a - b) as a signed 32-bit value,
 * without relying on undefined behavior. */
static inline krb5_deltat
ts_delta(krb5_timestamp a, krb5_timestamp b)
{
    return (krb5_deltat)((uint32_t)a - (uint32_t)b);
}


krb5_deltat is defined in https://github.com/krb5/krb5/blob/70f61d417261ca17efe3d60d180033bea2da60b0/src/include/krb5/krb5.hin:

typedef int32_t krb5_int32;
typedef krb5_int32      krb5_deltat;


Moving the issue to krb5 component.

Comment 3 Julien Rische 2022-09-07 12:16:16 UTC
I guess either we switch the type of krb5_deltat from int32_t to int64_t, or we add an extra test to detect integer wrapping before the delta is calculated.

I think the first option is better, but it may have some implications in the rest of the code. We will discuss this issue upstream.

Comment 6 Julien Rische 2022-09-09 16:22:30 UTC
The krb5_timestamp and krb5_deltat types are widely used in the MIT krb5 codebase. Their underlying type is int32_t, but krb5_timestamp is actually used as an unsigned 32-bit integer to support later dates in the future. Changing the underlying type would definitely require a lot of changes, including in the ABI, so I simply opened a PR to cast the delta as uint32_t:

https://github.com/krb5/krb5/pull/1266

Comment 18 errata-xmlrpc 2023-05-09 08:25:24 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (Moderate: krb5 security, bug fix, and enhancement update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHSA-2023:2570