|
|
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 |
|