ipa-kdb: handle dates up to 2106-02-07 06:28:16

krb5 uses the negative part of krb5_timestamp to store time values
after 2038:
https://k5wiki.kerberos.org/wiki/Projects/Timestamps_after_2038
In other words, krb5 uses krb5_timestamp (signed int) with
unsigned arithmetic for expanding the timestamp's upper bound.

This commit:
  - adds some helper functions for working with krb5_timestamp as
    unsigned (actually copied from
    https://github.com/krb5/krb5/blob/master/src/include/k5-int.h)
  - replaces operations with krb5_timestamp's by these new functions

Fixes: https://pagure.io/freeipa/issue/8028
Signed-off-by: Slava Aseev <ptrnine@altlinux.org>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
Reviewed-By: Robbie Harwood <rharwood@redhat.com>
This commit is contained in:
Slava Aseev
2020-11-23 18:23:01 +03:00
committed by Alexander Bokovoy
parent b46fa4e4b3
commit 18721cc830
7 changed files with 102 additions and 32 deletions

View File

@@ -103,13 +103,15 @@ void ipadb_audit_as_req(krb5_context kcontext,
}
if (ied->pol->lockout_duration != 0 &&
ied->pol->failcnt_interval != 0 &&
client->last_failed + ied->pol->failcnt_interval < authtime) {
!krb5_ts_after(krb5_ts_incr(client->last_failed,
ied->pol->failcnt_interval), authtime)) {
/* Reset fail_auth_count, the interval's expired already */
client->fail_auth_count = 0;
client->mask |= KMASK_FAIL_AUTH_COUNT;
}
if (client->last_failed + ied->pol->lockout_duration > authtime &&
if (krb5_ts_after(krb5_ts_incr(client->last_failed,
ied->pol->lockout_duration), authtime) &&
(client->fail_auth_count >= ied->pol->max_fail &&
ied->pol->max_fail != 0)) {
/* client already locked, nothing more to do */

View File

@@ -524,25 +524,11 @@ int ipadb_ldap_attr_to_krb5_timestamp(LDAP *lcontext, LDAPMessage *le,
char *attrname, krb5_timestamp *result)
{
time_t res_time;
long long res_long;
int ret = ipadb_ldap_attr_to_time_t(lcontext, le,
attrname, &res_time);
if (ret) return ret;
/* this will cast correctly maintaing sign to a 64bit variable */
res_long = res_time;
/* For dates beyond IPAPWD_END_OF_TIME, rest_time might oveflow
* on 32-bit platforms. This does not apply for 64-bit platforms.
* However, since krb5 uses 32-bit time representation, we need
* to limit the result.*/
if (res_long < 0 || res_long > IPAPWD_END_OF_TIME) {
*result = IPAPWD_END_OF_TIME; // 1 Jan 2038, 00:00 GMT
} else {
*result = (krb5_timestamp)res_long;
}
*result = (krb5_timestamp)res_time;
return 0;
}

View File

@@ -279,21 +279,18 @@ krb5_error_code ipadb_get_pwd_expiration(krb5_context context,
if (truexp) {
if (ied->pol) {
if (ied->pol->max_pwd_life) {
*expire_time = mod_time + ied->pol->max_pwd_life;
*expire_time = krb5_ts2tt(krb5_ts_incr(
mod_time, ied->pol->max_pwd_life));
} else {
*expire_time = 0;
}
} else {
*expire_time = mod_time + IPAPWD_DEFAULT_PWDLIFE;
*expire_time = krb5_ts2tt(krb5_ts_incr(
mod_time, IPAPWD_DEFAULT_PWDLIFE));
}
} else {
/* not 'self', so reset */
*expire_time = mod_time;
}
/* in the case of integer owerflow, set expiration to IPAPWD_END_OF_TIME */
if ((*expire_time) < 0 || (*expire_time) > IPAPWD_END_OF_TIME) {
*expire_time = IPAPWD_END_OF_TIME; // 1 Jan 2038, 00:00 GMT
*expire_time = krb5_ts2tt(mod_time);
}
kerr = 0;

View File

@@ -903,7 +903,7 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
goto done;
}
ied->last_pwd_change = restime;
ied->last_pwd_change = krb5_ts2tt(restime);
}
ret = ipadb_ldap_attr_to_krb5_timestamp(lcontext, lentry,
@@ -919,7 +919,7 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
goto done;
}
ied->last_admin_unlock = restime;
ied->last_admin_unlock = krb5_ts2tt(restime);
}
ret = ipadb_ldap_attr_to_strlist(lcontext, lentry,
@@ -1775,7 +1775,7 @@ static krb5_error_code ipadb_get_ldap_mod_time(struct ipadb_mods *imods,
time_t timeval;
char v[20];
timeval = (time_t)value;
timeval = krb5_ts2tt(value);
t = gmtime_r(&timeval, &date);
if (t == NULL) {
return EINVAL;

View File

@@ -367,7 +367,8 @@ krb5_error_code ipadb_check_policy_as(krb5_context kcontext,
}
if (ied->pol->lockout_duration == 0 ||
client->last_failed + ied->pol->lockout_duration > kdc_time) {
krb5_ts_after(krb5_ts_incr(
client->last_failed, ied->pol->lockout_duration), kdc_time)) {
/* ok client permanently locked, or within lockout period */
*status = "LOCKED_OUT";
return KRB5KDC_ERR_CLIENT_REVOKED;

View File

@@ -1,5 +1,72 @@
/*
* Kerberos related utils for FreeIPA
*
* Authors: Simo Sorce <ssorce@redhat.com>
*
* Copyright (C) 2011 Simo Sorce, Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Functions krb5_ts2tt, krb5_ts_incr, krb5_ts_after are taken from Kerberos 5:
* https://github.com/krb5/krb5/blob/master/src/include/k5-int.h
*
* Authors: Greg Hudson <ghudson@mit.edu>
*
* Copyright (C) 2017
*
* This software is being provided to you, the LICENSEE, by the
* Massachusetts Institute of Technology (M.I.T.) under the following
* license. By obtaining, using and/or copying this software, you agree
* that you have read, understood, and will comply with these terms and
* conditions:
*
* Export of this software from the United States of America may
* require a specific license from the United States Government.
* It is the responsibility of any person or organization contemplating
* export to obtain such a license before exporting.
*
* WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute
* this software and its documentation for any purpose and without fee or
* royalty is hereby granted, provided that you agree to comply with the
* following copyright notice and statements, including the disclaimer, and
* that the same appear on ALL copies of the software and documentation,
* including modifications that you make for internal use or for
* distribution:
*
* THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS
* OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not
* limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF
* MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
* THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
* PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
*
* The name of the Massachusetts Institute of Technology or M.I.T. may NOT
* be used in advertising or publicity pertaining to distribution of the
* software. Title to copyright in this software and any associated
* documentation shall at all times remain with M.I.T., and USER agrees to
* preserve same.
*
* Furthermore if you modify this software you must label
* your software as modified software and not distribute it in such a
* fashion that it might be confused with the original M.I.T. software.
*/
#pragma once
#include <stdbool.h>
#include <time.h>
#include <lber.h>
#include <krb5/krb5.h>
@@ -87,3 +154,23 @@ int create_keys(krb5_context krbctx,
char **err_msg);
int ipa_kstuples_to_string(krb5_key_salt_tuple *kst, int n_kst, char **str);
/* Convert a krb5_timestamp to a time_t value, treating the negative range of
* krb5_timestamp as times between 2038 and 2106 (if time_t is 64-bit). */
static inline time_t
krb5_ts2tt(krb5_timestamp timestamp) {
return (time_t)(uint32_t)timestamp;
}
/* Increment a timestamp by a signed 32-bit interval, without relying on
* undefined behavior. */
static inline krb5_timestamp
krb5_ts_incr(krb5_timestamp ts, krb5_deltat delta) {
return (krb5_timestamp)((uint32_t)ts + (uint32_t)delta);
}
/* Return true if a comes after b. */
static inline bool
krb5_ts_after(krb5_timestamp a, krb5_timestamp b) {
return (uint32_t)a > (uint32_t)b;
}

View File

@@ -30,9 +30,6 @@
#define IPAPWD_DEFAULT_PWDLIFE (90 * 24 *3600)
#define IPAPWD_DEFAULT_MINLEN 0
/* 1 Jan 2038, 00:00 GMT */
#define IPAPWD_END_OF_TIME 2145916800
/*
* IMPORTANT: please update error string table in ipa_pwd.c if you change this
* error code table.