From 5a2cce34cf8843613b0b9dfde054b3d471dd5f3a Mon Sep 17 00:00:00 2001 From: Pavel Březina Date: Wed, 12 Dec 2012 14:11:11 +0100 Subject: sudo: support generalized time format https://fedorahosted.org/sssd/ticket/1712 The timestamp doesn't have to be in the form yyyymmddHHMMSSZ any more. It can be in any form of generalized time format. --- src/db/sysdb_sudo.c | 45 ++++++++++++++++++++++++++++++++++----------- src/db/sysdb_sudo.h | 2 -- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/db/sysdb_sudo.c b/src/db/sysdb_sudo.c index c1845f9b..519a3aa7 100644 --- a/src/db/sysdb_sudo.c +++ b/src/db/sysdb_sudo.c @@ -36,6 +36,36 @@ /* ==================== Utility functions ==================== */ +static errno_t sysdb_sudo_convert_time(const char *str, time_t *time) +{ + struct tm tm; + char *tret = NULL; + + /* SUDO requires times to be in generalized time format: + * YYYYMMDDHHMMSS[.|,fraction][(+|-HHMM)|Z] + * + * We need to use more format strings to parse this with strptime(). + */ + const char **format = NULL; + const char *formats[] = {"%Y%m%d%H%M%SZ", /* 201212121300Z */ + "%Y%m%d%H%M%S%z", /* 201212121300+-0200 */ + "%Y%m%d%H%M%S.0Z", + "%Y%m%d%H%M%S.0%z", + "%Y%m%d%H%M%S,0Z", + "%Y%m%d%H%M%S,0%z", + NULL}; + + for (format = formats; *format != NULL; format++) { + tret = strptime(str, *format, &tm); + if (tret != NULL && *tret == '\0') { + *time = mktime(&tm); + return EOK; + } + } + + return EINVAL; +} + static errno_t sysdb_sudo_check_time(struct sysdb_attrs *rule, time_t now, bool *result) @@ -43,11 +73,9 @@ static errno_t sysdb_sudo_check_time(struct sysdb_attrs *rule, TALLOC_CTX *tmp_ctx = NULL; const char **values = NULL; const char *name = NULL; - char *tret = NULL; time_t notBefore = 0; time_t notAfter = 0; time_t converted; - struct tm tm; errno_t ret; int i; @@ -67,7 +95,6 @@ static errno_t sysdb_sudo_check_time(struct sysdb_attrs *rule, /* * From man sudoers.ldap: * - * A timestamp is in the form yyyymmddHHMMSSZ. * If multiple sudoNotBefore entries are present, the *earliest* is used. * If multiple sudoNotAfter entries are present, the *last one* is used. * @@ -91,14 +118,12 @@ static errno_t sysdb_sudo_check_time(struct sysdb_attrs *rule, } for (i=0; values[i] ; i++) { - tret = strptime(values[i], SYSDB_SUDO_TIME_FORMAT, &tm); - if (tret == NULL || *tret != '\0') { + ret = sysdb_sudo_convert_time(values[i], &converted); + if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, ("Invalid time format in rule [%s]!\n", name)); - ret = EINVAL; goto done; } - converted = mktime(&tm); /* Grab the earliest */ if (!notBefore) { @@ -123,14 +148,12 @@ static errno_t sysdb_sudo_check_time(struct sysdb_attrs *rule, } for (i=0; values[i] ; i++) { - tret = strptime(values[i], SYSDB_SUDO_TIME_FORMAT, &tm); - if (tret == NULL || *tret != '\0') { + ret = sysdb_sudo_convert_time(values[i], &converted); + if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, ("Invalid time format in rule [%s]!\n", name)); - ret = EINVAL; goto done; } - converted = mktime(&tm); /* Grab the latest */ if (!notAfter) { diff --git a/src/db/sysdb_sudo.h b/src/db/sysdb_sudo.h index 35b350c6..f37afff8 100644 --- a/src/db/sysdb_sudo.h +++ b/src/db/sysdb_sudo.h @@ -45,8 +45,6 @@ #define SYSDB_SUDO_CACHE_AT_NOTAFTER "sudoNotAfter" #define SYSDB_SUDO_CACHE_AT_ORDER "sudoOrder" -#define SYSDB_SUDO_TIME_FORMAT "%Y%m%d%H%M%SZ" - /* When constructing a sysdb filter, OR these values to include.. */ #define SYSDB_SUDO_FILTER_NONE 0x00 /* no additional filter */ #define SYSDB_SUDO_FILTER_USERNAME 0x01 /* username */ -- cgit