Blob Blame History Raw
From 16625978bc25d9fe26218d92b4b8fde0516f63c6 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Mon, 8 Jun 2020 14:55:38 +0300
Subject: [PATCH] ipa-pwd-extop: use timegm() instead of mktime() to preserve
 timezone offset

"Kerberos principal expiration" is set in UTC and when server is in
different timezone, the time difference between timezone is respected by
the IPA server/client for Kerberos authentication.

The problem is due to mktime() assuming default time zone but since we
parse the time using Zulu (UTC+0) timezone, mktime() forces current time
zone offset added.

The method is using mktime() and comparing to the current time obtained
with time(NULL). According to its man page, mktime is considering the
time as local time:

   The mktime() function converts a broken-down time structure,  expressed
   as  local  time, to calendar time representation.

Instead mktime() we should use timegm(). The problem is that it is
non-standard GNU extension and it is recommended (in the man page for
timegm(3)) to avoid its use. An alternative is to set TZ=UTC, call
mktime(), unset TZ, but since we are running in a multi-threaded
environment this is problematic.

On the other hand, we already rely on GNU extensions and enable them
with -D_DEFAULT_SOURCE=1, so use of timegm() is enabled already.

The fix, therefore, is to use timegm() instead of mktime() in
daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c in two places where we
first do 'strptime()' with Zulu time zone (in ipapwd_pre_bind() and
ipapwd_write_krb_keys()).

Fixes: https://pagure.io/freeipa/issue/8362

Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
Reviewed-by: Simo Sorce <simo@redhat.com>
Reviewed-By: Christian Heimes <cheimes@redhat.com>
---
 daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c | 6 +++---
 server.m4                                         | 2 ++
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
index 04cd2b10f3ba4375e6a278afe87cbd9d257d528f..ee5be3eba02b219f13e8771ce8ba6d510f1c397b 100644
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
@@ -1362,7 +1362,7 @@ static void ipapwd_write_krb_keys(Slapi_PBlock *pb, char *dn,
     if (expire) {
         memset(&expire_tm, 0, sizeof (expire_tm));
         if (strptime(expire, "%Y%m%d%H%M%SZ", &expire_tm))
-            pwdata.expireTime = mktime(&expire_tm);
+            pwdata.expireTime = timegm(&expire_tm);
     }
 
     /* check password policy */
@@ -1464,10 +1464,10 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
         memset(&expire_tm, 0, sizeof (expire_tm));
 
         if (strptime(principal_expire, "%Y%m%d%H%M%SZ", &expire_tm)) {
-            expire_time = mktime(&expire_tm);
+            expire_time = timegm(&expire_tm);
             current_time = time(NULL);
 
-            /* mktime returns -1 if the tm struct cannot be represented as
+            /* timegm returns -1 if the tm struct cannot be represented as
              * as calendar time (seconds since the Epoch). This might
              * happen with tm structs that are ill-formated or on 32-bit
              * platforms with dates that would cause overflow
diff --git a/server.m4 b/server.m4
index f0a8bbcc778596dade89d9332abb2939b8a44143..f70354818241da29a60072b58c18828ebde495c7 100644
--- a/server.m4
+++ b/server.m4
@@ -21,6 +21,8 @@ if test "x$ac_cv_header_dirsrv_slapi_plugin_h" = "xno" ; then
     AC_MSG_ERROR([Required DS slapi plugin header not available (fedora-ds-base-devel)])
 fi
 
+AC_CHECK_FUNC(timegm, [], [AC_MSG_ERROR([timegm not found])])
+
 dnl -- dirsrv is needed for the extdom unit tests --
 PKG_CHECK_MODULES([DIRSRV], [dirsrv  >= 1.3.0])
 # slapi-plugin.h includes nspr.h
-- 
2.25.4