summaryrefslogtreecommitdiffstats
path: root/src/db/sysdb_sudo.c
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2012-01-27 10:53:51 +0100
committerStephen Gallagher <sgallagh@redhat.com>2012-02-04 08:27:16 -0500
commitc9aab1c04c399ca2d1abef74f6df22ced34983dc (patch)
treece72d312ed54242f0b3717112d0774e705408a02 /src/db/sysdb_sudo.c
parent41ef946f3f74a46b9e26118116e4811e259b30ef (diff)
downloadsssd-c9aab1c04c399ca2d1abef74f6df22ced34983dc.tar.gz
sssd-c9aab1c04c399ca2d1abef74f6df22ced34983dc.tar.xz
sssd-c9aab1c04c399ca2d1abef74f6df22ced34983dc.zip
SUDO Integration - responder 'sudo_timed' option
https://fedorahosted.org/sssd/ticket/1116
Diffstat (limited to 'src/db/sysdb_sudo.c')
-rw-r--r--src/db/sysdb_sudo.c159
1 files changed, 123 insertions, 36 deletions
diff --git a/src/db/sysdb_sudo.c b/src/db/sysdb_sudo.c
index 5adde76e7..cea4fcbaf 100644
--- a/src/db/sysdb_sudo.c
+++ b/src/db/sysdb_sudo.c
@@ -18,7 +18,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#define _XOPEN_SOURCE
+
#include <talloc.h>
+#include <time.h>
#include "db/sysdb.h"
#include "db/sysdb_private.h"
@@ -32,34 +35,131 @@
} while(0)
/* ==================== Utility functions ==================== */
-static char *
-get_sudo_time_filter(TALLOC_CTX *mem_ctx)
+
+static errno_t sysdb_sudo_check_time(struct sysdb_attrs *rule,
+ time_t now,
+ bool *result)
{
- time_t now;
- struct tm *tp;
- char timebuffer[64];
-
- /* Make sure we have a formatted timestamp for __now__. */
- time(&now);
- if ((tp = gmtime(&now)) == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("unable to get GMT time\n"));
- return NULL;
+ TALLOC_CTX *tmp_ctx = NULL;
+ const char **values = NULL;
+ char *tret = NULL;
+ time_t converted;
+ struct tm tm;
+ errno_t ret;
+ int i;
+
+ tmp_ctx = talloc_new(NULL);
+ NULL_CHECK(tmp_ctx, ret, done);
+
+ /*
+ * From man sudoers.ldap:
+ *
+ * A timestamp is in the form yyyymmddHHMMZ.
+ * If multiple sudoNotBefore entries are present, the *earliest* is used.
+ * If multiple sudoNotAfter entries are present, the *last one* is used.
+ */
+
+ /* check for sudoNotBefore */
+ ret = sysdb_attrs_get_string_array(rule, SYSDB_SUDO_CACHE_AT_NOTBEFORE,
+ tmp_ctx, &values);
+ if (ret != EOK) {
+ goto done;
+ }
+ if (values != NULL && values[0] != NULL) {
+ tret = strptime(values[0], SYSDB_SUDO_TIME_FORMAT, &tm);
+ if (tret == NULL || *tret != '\0') {
+ DEBUG(SSSDBG_FUNC_DATA, ("Invalid time format!\n"));
+ ret = EINVAL;
+ goto done;
+ }
+ converted = mktime(&tm);
+
+ if (now < converted) {
+ *result = false;
+ goto done;
+ }
+ }
+
+ /* check for sudoNotAfter */
+ ret = sysdb_attrs_get_string_array(rule, SYSDB_SUDO_CACHE_AT_NOTAFTER,
+ tmp_ctx, &values);
+ if (ret != EOK) {
+ goto done;
}
+ if (values != NULL && values[0] != NULL) {
+ /* find last value */
+ for (i = 0; values[i] != NULL; i++) {
+ // do nothing
+ }
+
+ tret = strptime(values[i - 1], SYSDB_SUDO_TIME_FORMAT, &tm);
+ if (tret == NULL || *tret != '\0') {
+ DEBUG(SSSDBG_FUNC_DATA, ("Invalid time format!\n"));
+ ret = EINVAL;
+ goto done;
+ }
+ converted = mktime(&tm);
- /* Format the timestamp according to the RFC. */
- if (strftime(timebuffer, sizeof(timebuffer), "%Y%m%d%H%M%SZ", tp) == 0) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("unable to format timestamp\n"));
- return NULL;
+ if (now > converted) {
+ *result = false;
+ goto done;
+ }
}
- return talloc_asprintf(mem_ctx, "(&(|(!(%s=*))(%s>=%s))"
- "(|(!(%s=*))(%s<=%s)))",
- SYSDB_SUDO_CACHE_AT_NOTAFTER,
- SYSDB_SUDO_CACHE_AT_NOTAFTER,
- timebuffer,
- SYSDB_SUDO_CACHE_AT_NOTBEFORE,
- SYSDB_SUDO_CACHE_AT_NOTBEFORE,
- timebuffer);
+ *result = true;
+ ret = EOK;
+
+done:
+ if (ret == ENOENT) {
+ *result = true;
+ ret = EOK;
+ }
+
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+errno_t sysdb_sudo_filter_rules_by_time(TALLOC_CTX *mem_ctx,
+ size_t in_num_rules,
+ struct sysdb_attrs **in_rules,
+ time_t now,
+ size_t *_num_rules,
+ struct sysdb_attrs ***_rules)
+{
+ size_t num_rules = 0;
+ struct sysdb_attrs **rules = NULL;
+ TALLOC_CTX *tmp_ctx = NULL;
+ bool allowed = false;
+ errno_t ret;
+ int i;
+
+ tmp_ctx = talloc_new(NULL);
+ NULL_CHECK(tmp_ctx, ret, done);
+
+ if (now == 0) {
+ now = time(NULL);
+ }
+
+ for (i = 0; i < in_num_rules; i++) {
+ ret = sysdb_sudo_check_time(in_rules[i], now, &allowed);
+ if (ret == EOK && allowed) {
+ num_rules++;
+ rules = talloc_realloc(tmp_ctx, rules, struct sysdb_attrs *,
+ num_rules);
+ NULL_CHECK(rules, ret, done);
+
+ rules[num_rules - 1] = in_rules[i];
+ }
+ }
+
+ *_num_rules = num_rules;
+ *_rules = talloc_steal(mem_ctx, rules);
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
}
errno_t
@@ -70,7 +170,6 @@ sysdb_get_sudo_filter(TALLOC_CTX *mem_ctx, const char *username,
TALLOC_CTX *tmp_ctx = NULL;
char *filter = NULL;
char *specific_filter = NULL;
- char *time_filter = NULL;
errno_t ret;
int i;
@@ -123,24 +222,12 @@ sysdb_get_sudo_filter(TALLOC_CTX *mem_ctx, const char *username,
NULL_CHECK(specific_filter, ret, done);
}
- /* build time filter */
-
- if (flags & SYSDB_SUDO_FILTER_TIMED) {
- time_filter = get_sudo_time_filter(tmp_ctx);
- NULL_CHECK(time_filter, ret, done);
- }
-
/* build global filter */
filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)",
SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_AT_OC);
NULL_CHECK(filter, ret, done);
- if (time_filter != NULL) {
- filter = talloc_strdup_append(filter, time_filter);
- NULL_CHECK(filter, ret, done);
- }
-
if (specific_filter[0] != '\0') {
filter = talloc_asprintf_append(filter, "(|%s)", specific_filter);
NULL_CHECK(filter, ret, done);