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

Reply via email to