Blame SOURCES/0094-SUDO-Fix-timezone-issues-with-sudoNotBefore-and-sudo.patch

5ddef6
From 1bb93f70de9907d88b2ebc5c6ffee14417d90fee Mon Sep 17 00:00:00 2001
5ddef6
From: Anton Bobrov <antbob@users.noreply.github.com>
5ddef6
Date: Mon, 19 Sep 2022 17:51:07 +0200
5ddef6
Subject: [PATCH] SUDO: Fix timezone issues with sudoNotBefore and sudoNotAfter
5ddef6
MIME-Version: 1.0
5ddef6
Content-Type: text/plain; charset=UTF-8
5ddef6
Content-Transfer-Encoding: 8bit
5ddef6
5ddef6
The current code does not respect generalized time as specified in related before/after attributes.
5ddef6
The problem with the current implementation is that it essentially treats them as local time,
5ddef6
with no regard to TZ and DST.
5ddef6
5ddef6
This patch is using timegm(3) instead of mktime(3) to address said timezone issues and some bare
5ddef6
minimum static unit tests with known verified values to make sure the API is consitent with them.
5ddef6
5ddef6
Resolves:
5ddef6
https://github.com/SSSD/sssd/issues/6354
5ddef6
5ddef6
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
5ddef6
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
5ddef6
(cherry picked from commit 0198f64ce231e9608b14152c64426fb9e015fd33)
5ddef6
---
5ddef6
 configure.ac                       |  3 +++
5ddef6
 src/db/sysdb_sudo.c                | 11 ++++++++++-
5ddef6
 src/tests/cmocka/test_sysdb_sudo.c | 29 +++++++++++++++++++++++++++++
5ddef6
 3 files changed, 42 insertions(+), 1 deletion(-)
5ddef6
5ddef6
diff --git a/configure.ac b/configure.ac
5ddef6
index 89abddef4..a90e16642 100644
5ddef6
--- a/configure.ac
5ddef6
+++ b/configure.ac
5ddef6
@@ -92,6 +92,9 @@ LIBS=$SAVE_LIBS
5ddef6
 AC_CHECK_FUNCS([ utimensat \
5ddef6
                  futimens ])
5ddef6
 
5ddef6
+# Check for the timegm() function (not part of POSIX / Open Group specs)
5ddef6
+AC_CHECK_FUNC([timegm], [], [AC_MSG_ERROR([timegm() function not found])])
5ddef6
+
5ddef6
 #Check for endian headers
5ddef6
 AC_CHECK_HEADERS([endian.h sys/endian.h byteswap.h])
5ddef6
 
5ddef6
diff --git a/src/db/sysdb_sudo.c b/src/db/sysdb_sudo.c
5ddef6
index 59d6824c0..3a918e9c6 100644
5ddef6
--- a/src/db/sysdb_sudo.c
5ddef6
+++ b/src/db/sysdb_sudo.c
5ddef6
@@ -60,9 +60,18 @@ static errno_t sysdb_sudo_convert_time(const char *str, time_t *unix_time)
5ddef6
     for (format = formats; *format != NULL; format++) {
5ddef6
         /* strptime() may leave some fields uninitialized */
5ddef6
         memset(&tm, 0, sizeof(struct tm));
5ddef6
+        /* Let underlying implementation figure out DST */
5ddef6
+        tm.tm_isdst = -1;
5ddef6
         tret = strptime(str, *format, &tm;;
5ddef6
         if (tret != NULL && *tret == '\0') {
5ddef6
-            *unix_time = mktime(&tm;;
5ddef6
+            /* Convert broken-down time to local time */
5ddef6
+            if (tm.tm_gmtoff == 0) {
5ddef6
+                *unix_time = timegm(&tm;;
5ddef6
+            } else {
5ddef6
+                long offset = tm.tm_gmtoff;
5ddef6
+                tm.tm_gmtoff = 0;
5ddef6
+                *unix_time = timegm(&tm) - offset;
5ddef6
+            }
5ddef6
             return EOK;
5ddef6
         }
5ddef6
     }
5ddef6
diff --git a/src/tests/cmocka/test_sysdb_sudo.c b/src/tests/cmocka/test_sysdb_sudo.c
5ddef6
index fc6a47a16..f852427fd 100644
5ddef6
--- a/src/tests/cmocka/test_sysdb_sudo.c
5ddef6
+++ b/src/tests/cmocka/test_sysdb_sudo.c
5ddef6
@@ -44,6 +44,12 @@
5ddef6
 #define OVERRIDE_GROUP_NAME "group_sudo_test"
5ddef6
 #define OVERRIDE_UID 2112
5ddef6
 
5ddef6
+/* sysdb_sudo_convert_time function is static */
5ddef6
+extern char *strptime(const char *__restrict __s,
5ddef6
+                      const char *__restrict __fmt,
5ddef6
+                      struct tm *__tp);
5ddef6
+#include "src/db/sysdb_sudo.c"
5ddef6
+
5ddef6
 struct test_user {
5ddef6
     const char *name;
5ddef6
     uid_t uid;
5ddef6
@@ -949,6 +955,26 @@ void test_filter_rules_by_time(void **state)
5ddef6
     talloc_zfree(_rules);
5ddef6
 }
5ddef6
 
5ddef6
+void test_sudo_convert_time(void **state)
5ddef6
+{
5ddef6
+    /* Each ctime should map to its corresponding utime */
5ddef6
+    const char *ctimes[] = {"20220715090000Z",
5ddef6
+                            "20220715090000+0200",
5ddef6
+                            "20220715090000-0200"};
5ddef6
+    const time_t utimes[] = {1657875600,
5ddef6
+                             1657868400,
5ddef6
+                             1657882800};
5ddef6
+    const int ntimes = sizeof(ctimes) / sizeof(ctimes[0]);
5ddef6
+    time_t converted;
5ddef6
+    errno_t ret;
5ddef6
+
5ddef6
+    for (int i = 0; i < ntimes; i++) {
5ddef6
+        ret = sysdb_sudo_convert_time(ctimes[i], &converted);
5ddef6
+        assert_int_equal(ret, EOK);
5ddef6
+        assert_int_equal(converted, utimes[i]);
5ddef6
+    }
5ddef6
+}
5ddef6
+
5ddef6
 int main(int argc, const char *argv[])
5ddef6
 {
5ddef6
     int rv;
5ddef6
@@ -1029,6 +1055,9 @@ int main(int argc, const char *argv[])
5ddef6
         cmocka_unit_test_setup_teardown(test_filter_rules_by_time,
5ddef6
                                         test_sysdb_setup,
5ddef6
                                         test_sysdb_teardown),
5ddef6
+
5ddef6
+        /* sysdb_sudo_convert_time() */
5ddef6
+        cmocka_unit_test(test_sudo_convert_time)
5ddef6
     };
5ddef6
 
5ddef6
     /* Set debug level to invalid value so we can decide if -d 0 was used. */
5ddef6
-- 
5ddef6
2.37.3
5ddef6