URL: https://github.com/freeipa/freeipa/pull/5364 Author: abbra Title: #5364: [Backport][ipa-4-9] ipa-kdb: handle dates up to 2106-02-07 06:28:16 Action: opened
PR body: """ This PR was opened automatically because PR #5288 was pushed to master and backport to ipa-4-9 is required. """ To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/5364/head:pr5364 git checkout pr5364
From aba2a4d5dbefb900d7cfc21e4e56f24c8841f765 Mon Sep 17 00:00:00 2001 From: Slava Aseev <ptrn...@altlinux.org> Date: Mon, 23 Nov 2020 18:23:01 +0300 Subject: [PATCH] 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 <ptrn...@altlinux.org> --- daemons/ipa-kdb/ipa_kdb_audit_as.c | 6 +- daemons/ipa-kdb/ipa_kdb_common.c | 16 +---- daemons/ipa-kdb/ipa_kdb_passwords.c | 13 ++--- daemons/ipa-kdb/ipa_kdb_principals.c | 6 +- daemons/ipa-kdb/ipa_kdb_pwdpolicy.c | 3 +- util/ipa_krb5.h | 87 ++++++++++++++++++++++++++++ util/ipa_pwd.h | 3 - 7 files changed, 102 insertions(+), 32 deletions(-) diff --git a/daemons/ipa-kdb/ipa_kdb_audit_as.c b/daemons/ipa-kdb/ipa_kdb_audit_as.c index a60bc82b6d5..ed48ea758e7 100644 --- a/daemons/ipa-kdb/ipa_kdb_audit_as.c +++ b/daemons/ipa-kdb/ipa_kdb_audit_as.c @@ -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 */ diff --git a/daemons/ipa-kdb/ipa_kdb_common.c b/daemons/ipa-kdb/ipa_kdb_common.c index d86f4f5307b..42e0856d09f 100644 --- a/daemons/ipa-kdb/ipa_kdb_common.c +++ b/daemons/ipa-kdb/ipa_kdb_common.c @@ -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; } diff --git a/daemons/ipa-kdb/ipa_kdb_passwords.c b/daemons/ipa-kdb/ipa_kdb_passwords.c index adfefb3a2e2..83d7919d47b 100644 --- a/daemons/ipa-kdb/ipa_kdb_passwords.c +++ b/daemons/ipa-kdb/ipa_kdb_passwords.c @@ -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; diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c index 56c27b82a0d..d1fa5157899 100644 --- a/daemons/ipa-kdb/ipa_kdb_principals.c +++ b/daemons/ipa-kdb/ipa_kdb_principals.c @@ -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; diff --git a/daemons/ipa-kdb/ipa_kdb_pwdpolicy.c b/daemons/ipa-kdb/ipa_kdb_pwdpolicy.c index 03d742b5c38..4965e6d7f74 100644 --- a/daemons/ipa-kdb/ipa_kdb_pwdpolicy.c +++ b/daemons/ipa-kdb/ipa_kdb_pwdpolicy.c @@ -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; diff --git a/util/ipa_krb5.h b/util/ipa_krb5.h index e01f1e8748e..7d2ebae9840 100644 --- a/util/ipa_krb5.h +++ b/util/ipa_krb5.h @@ -1,5 +1,72 @@ +/* + * Kerberos related utils for FreeIPA + * + * Authors: Simo Sorce <sso...@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 <ghud...@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; +} diff --git a/util/ipa_pwd.h b/util/ipa_pwd.h index b3bb2be6e23..4bd3a70d4c4 100644 --- a/util/ipa_pwd.h +++ b/util/ipa_pwd.h @@ -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.
_______________________________________________ FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/freeipa-devel@lists.fedorahosted.org