>From 70d87cf945fadb2b9d8cd89ec4b2908d116707ab Mon Sep 17 00:00:00 2001
From: Michal Zidek <mzidek@redhat.com>
Date: Wed, 27 Feb 2013 15:31:00 +0100
Subject: [PATCH 2/3] Reuse cached SELinux mappings.

Reuse cached SELinux maps when they are requested
within time interval (in this patch it is hardcoded to
be 5 seconds).

https://fedorahosted.org/sssd/ticket/1744
---
 src/providers/ipa/ipa_selinux.c | 31 ++++++++++++++++++++++++++++---
 src/providers/ipa/ipa_selinux.h |  1 +
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c
index b5f5039..034287b 100644
--- a/src/providers/ipa/ipa_selinux.c
+++ b/src/providers/ipa/ipa_selinux.c
@@ -56,7 +56,8 @@ static struct ipa_selinux_op_ctx *
 ipa_selinux_create_op_ctx(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
                           struct sss_domain_info *domain,
                           struct be_req *be_req, const char *username,
-                          const char *hostname);
+                          const char *hostname,
+                          struct ipa_selinux_ctx *selinux_ctx);
 static void ipa_selinux_handler_done(struct tevent_req *subreq);
 
 static void ipa_get_selinux_connect_done(struct tevent_req *subreq);
@@ -81,6 +82,7 @@ static errno_t prepare_selinux_file_content(struct sysdb_attrs **usermaps,
 struct ipa_selinux_op_ctx {
     struct be_req *be_req;
     struct sss_domain_info *domain;
+    struct ipa_selinux_ctx *selinux_ctx;
 
     struct sysdb_attrs *user;
     struct sysdb_attrs *host;
@@ -109,7 +111,8 @@ void ipa_selinux_handler(struct be_req *be_req)
 
     op_ctx = ipa_selinux_create_op_ctx(be_req, be_ctx->domain->sysdb,
                                        be_ctx->domain,
-                                       be_req, pd->user, hostname);
+                                       be_req, pd->user, hostname,
+                                       selinux_ctx);
     if (op_ctx == NULL) {
         DEBUG(SSSDBG_OP_FAILURE, ("Cannot create op context\n"));
         goto fail;
@@ -133,7 +136,8 @@ static struct ipa_selinux_op_ctx *
 ipa_selinux_create_op_ctx(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
                           struct sss_domain_info *domain,
                           struct be_req *be_req, const char *username,
-                          const char *hostname)
+                          const char *hostname,
+                          struct ipa_selinux_ctx *selinux_ctx)
 {
     struct ipa_selinux_op_ctx *op_ctx;
     struct ldb_dn *host_dn;
@@ -151,6 +155,7 @@ ipa_selinux_create_op_ctx(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
     }
     op_ctx->be_req = be_req;
     op_ctx->domain = domain;
+    op_ctx->selinux_ctx = selinux_ctx;
 
     ret = sss_selinux_extract_user(op_ctx, sysdb, domain, username, &op_ctx->user);
     if (ret != EOK) {
@@ -194,6 +199,7 @@ static void ipa_selinux_handler_done(struct tevent_req *req)
 {
     struct ipa_selinux_op_ctx *op_ctx = tevent_req_callback_data(req, struct ipa_selinux_op_ctx);
     struct be_req *breq = op_ctx->be_req;
+    struct be_ctx *be_ctx = be_req_get_be_ctx(breq);
     struct sysdb_ctx *sysdb = op_ctx->domain->sysdb;
     errno_t ret, sret;
     size_t map_count = 0;
@@ -264,6 +270,11 @@ static void ipa_selinux_handler_done(struct tevent_req *req)
     }
     in_transaction = false;
 
+    /* If we got here in online mode, set last_update to current time */
+    if (!be_is_offline(be_ctx)) {
+        op_ctx->selinux_ctx->last_update = time(NULL);
+    }
+
     pd->pam_status = PAM_SUCCESS;
     be_req_terminate(breq, DP_ERR_OK, EOK, "Success");
     return;
@@ -763,6 +774,8 @@ ipa_get_selinux_send(TALLOC_CTX *mem_ctx,
     struct ipa_get_selinux_state *state;
     bool offline;
     int ret = EOK;
+    time_t now;
+    time_t refresh_interval;
 
     DEBUG(SSSDBG_TRACE_FUNC, ("Retrieving SELinux user mapping\n"));
     req = tevent_req_create(mem_ctx, &state, struct ipa_get_selinux_state);
@@ -780,6 +793,18 @@ ipa_get_selinux_send(TALLOC_CTX *mem_ctx,
                                   offline ? "offline" : "online"));
 
     if (!offline) {
+        /* FIXME: Make the interval configurable */
+        refresh_interval = 5;
+        now = time(NULL);
+        if (now < selinux_ctx->last_update + refresh_interval) {
+            /* SELinux maps were recently updated -> force offline */
+            DEBUG(SSSDBG_TRACE_INTERNAL,
+                  ("Performing cached SELinux processing\n"));
+            offline = true;
+        }
+    }
+
+    if (!offline) {
         state->op = sdap_id_op_create(state, selinux_ctx->id_ctx->sdap_id_ctx->conn_cache);
         if (!state->op) {
             DEBUG(SSSDBG_OP_FAILURE, ("sdap_id_op_create failed\n"));
diff --git a/src/providers/ipa/ipa_selinux.h b/src/providers/ipa/ipa_selinux.h
index 60c2211..38a9e6f 100644
--- a/src/providers/ipa/ipa_selinux.h
+++ b/src/providers/ipa/ipa_selinux.h
@@ -29,6 +29,7 @@
 
 struct ipa_selinux_ctx {
     struct ipa_id_ctx *id_ctx;
+    time_t last_update;
 
     struct sdap_search_base **selinux_search_bases;
     struct sdap_search_base **host_search_bases;
-- 
1.7.11.2

