dc4945
From 16625978bc25d9fe26218d92b4b8fde0516f63c6 Mon Sep 17 00:00:00 2001
dc4945
From: Alexander Bokovoy <abokovoy@redhat.com>
dc4945
Date: Mon, 8 Jun 2020 14:55:38 +0300
dc4945
Subject: [PATCH] ipa-pwd-extop: use timegm() instead of mktime() to preserve
dc4945
 timezone offset
dc4945
dc4945
"Kerberos principal expiration" is set in UTC and when server is in
dc4945
different timezone, the time difference between timezone is respected by
dc4945
the IPA server/client for Kerberos authentication.
dc4945
dc4945
The problem is due to mktime() assuming default time zone but since we
dc4945
parse the time using Zulu (UTC+0) timezone, mktime() forces current time
dc4945
zone offset added.
dc4945
dc4945
The method is using mktime() and comparing to the current time obtained
dc4945
with time(NULL). According to its man page, mktime is considering the
dc4945
time as local time:
dc4945
dc4945
   The mktime() function converts a broken-down time structure,  expressed
dc4945
   as  local  time, to calendar time representation.
dc4945
dc4945
Instead mktime() we should use timegm(). The problem is that it is
dc4945
non-standard GNU extension and it is recommended (in the man page for
dc4945
timegm(3)) to avoid its use. An alternative is to set TZ=UTC, call
dc4945
mktime(), unset TZ, but since we are running in a multi-threaded
dc4945
environment this is problematic.
dc4945
dc4945
On the other hand, we already rely on GNU extensions and enable them
dc4945
with -D_DEFAULT_SOURCE=1, so use of timegm() is enabled already.
dc4945
dc4945
The fix, therefore, is to use timegm() instead of mktime() in
dc4945
daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c in two places where we
dc4945
first do 'strptime()' with Zulu time zone (in ipapwd_pre_bind() and
dc4945
ipapwd_write_krb_keys()).
dc4945
dc4945
Fixes: https://pagure.io/freeipa/issue/8362
dc4945
dc4945
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
dc4945
Reviewed-by: Simo Sorce <simo@redhat.com>
dc4945
Reviewed-By: Christian Heimes <cheimes@redhat.com>
dc4945
---
dc4945
 daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c | 6 +++---
dc4945
 server.m4                                         | 2 ++
dc4945
 2 files changed, 5 insertions(+), 3 deletions(-)
dc4945
dc4945
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
dc4945
index 04cd2b10f3ba4375e6a278afe87cbd9d257d528f..ee5be3eba02b219f13e8771ce8ba6d510f1c397b 100644
dc4945
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
dc4945
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
dc4945
@@ -1362,7 +1362,7 @@ static void ipapwd_write_krb_keys(Slapi_PBlock *pb, char *dn,
dc4945
     if (expire) {
dc4945
         memset(&expire_tm, 0, sizeof (expire_tm));
dc4945
         if (strptime(expire, "%Y%m%d%H%M%SZ", &expire_tm))
dc4945
-            pwdata.expireTime = mktime(&expire_tm);
dc4945
+            pwdata.expireTime = timegm(&expire_tm);
dc4945
     }
dc4945
 
dc4945
     /* check password policy */
dc4945
@@ -1464,10 +1464,10 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
dc4945
         memset(&expire_tm, 0, sizeof (expire_tm));
dc4945
 
dc4945
         if (strptime(principal_expire, "%Y%m%d%H%M%SZ", &expire_tm)) {
dc4945
-            expire_time = mktime(&expire_tm);
dc4945
+            expire_time = timegm(&expire_tm);
dc4945
             current_time = time(NULL);
dc4945
 
dc4945
-            /* mktime returns -1 if the tm struct cannot be represented as
dc4945
+            /* timegm returns -1 if the tm struct cannot be represented as
dc4945
              * as calendar time (seconds since the Epoch). This might
dc4945
              * happen with tm structs that are ill-formated or on 32-bit
dc4945
              * platforms with dates that would cause overflow
dc4945
diff --git a/server.m4 b/server.m4
dc4945
index f0a8bbcc778596dade89d9332abb2939b8a44143..f70354818241da29a60072b58c18828ebde495c7 100644
dc4945
--- a/server.m4
dc4945
+++ b/server.m4
dc4945
@@ -21,6 +21,8 @@ if test "x$ac_cv_header_dirsrv_slapi_plugin_h" = "xno" ; then
dc4945
     AC_MSG_ERROR([Required DS slapi plugin header not available (fedora-ds-base-devel)])
dc4945
 fi
dc4945
 
dc4945
+AC_CHECK_FUNC(timegm, [], [AC_MSG_ERROR([timegm not found])])
dc4945
+
dc4945
 dnl -- dirsrv is needed for the extdom unit tests --
dc4945
 PKG_CHECK_MODULES([DIRSRV], [dirsrv  >= 1.3.0])
dc4945
 # slapi-plugin.h includes nspr.h
dc4945
-- 
dc4945
2.25.4
dc4945