Hi,

The attached patch adds support for an "entry_cache_gpo_timeout" option, which 
allows an admin to specify how many seconds the backend should consider locally 
stored gpo policy files to be valid before asking the backend again. This is an 
additional performance enhancement (along with comparing gpo versions to avoid 
unnecessary downloads). The timeout is set when a gpo entry is stored in the 
cache (which only happens after policy files have been downloaded). 

During the processing of a gpo, if the gpo's cache timeout has not elapsed, the 
backend does not interact with the gpo_child at all (and therefore doesn't 
download any files from the smb server). Rather, it re-uses the policy files 
that are already stored locally. Obviously, no gpo version comparisons need to 
be made in this case. If the timeout has elapsed (or there is no gpo entry in 
the cache), then the backend does interact with the gpo child in the usual 
manner (including comparing gpo versions to avoid unnecessary downloads). Note 
that the entry_cache_gpo_timeout option is *not* an expiration for the data in 
the gpo cache entry (which includes the cached_gpt_version). Indeed, the 
cached_gpt_version is never considered to be "expired".

Note that this patch does not add support for offline mode, which will be 
implemented in a subsequent patch.

Regards,
Yassir.
From 8aff4445df5cf42e09cd8b521cbd5ff4d6e1a666 Mon Sep 17 00:00:00 2001
From: Yassir Elley <[email protected]>
Date: Tue, 22 Jul 2014 14:19:35 -0400
Subject: [PATCH] AD-GPO: add entry_cache_gpo_timeout option

---
 src/confdb/confdb.c                  |  11 ++
 src/confdb/confdb.h                  |   2 +
 src/config/SSSDConfig/__init__.py.in |   1 +
 src/config/SSSDConfigTest.py         |   2 +
 src/config/etc/sssd.api.conf         |   1 +
 src/db/sysdb.h                       |  14 +-
 src/db/sysdb_gpo.c                   |  46 +++++-
 src/man/sssd.conf.5.xml              |  13 ++
 src/providers/ad/ad_gpo.c            | 292 +++++++++++++++++++++++------------
 9 files changed, 271 insertions(+), 111 deletions(-)

diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c
index 15de9616ffdddf640f29e6b816c246ee05da48c7..5fbf31b822bc100f4e266212c0ab3e52bbc247bd 100644
--- a/src/confdb/confdb.c
+++ b/src/confdb/confdb.c
@@ -1040,6 +1040,17 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb,
         goto done;
     }
 
+    /* Override the gpo cache timeout, if specified */
+    ret = get_entry_as_uint32(res->msgs[0], &domain->gpo_timeout,
+                              CONFDB_DOMAIN_GPO_CACHE_TIMEOUT,
+                              entry_cache_timeout);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              "Invalid value for [%s]\n",
+               CONFDB_DOMAIN_SUDO_CACHE_TIMEOUT);
+        goto done;
+    }
+
     /* Set refresh_expired_interval, if specified */
     ret = get_entry_as_uint32(res->msgs[0], &domain->refresh_expired_interval,
                               CONFDB_DOMAIN_REFRESH_EXPIRED_INTERVAL,
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index ba33ea5d7123c6e799f13529b60c5938ad20e411..52063dd56fcc2d24d106b380d41b394b44187a8e 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -175,6 +175,7 @@
 #define CONFDB_DOMAIN_SERVICE_CACHE_TIMEOUT "entry_cache_service_timeout"
 #define CONFDB_DOMAIN_AUTOFS_CACHE_TIMEOUT "entry_cache_autofs_timeout"
 #define CONFDB_DOMAIN_SUDO_CACHE_TIMEOUT "entry_cache_sudo_timeout"
+#define CONFDB_DOMAIN_GPO_CACHE_TIMEOUT "entry_cache_gpo_timeout"
 #define CONFDB_DOMAIN_PWD_EXPIRATION_WARNING "pwd_expiration_warning"
 #define CONFDB_DOMAIN_REFRESH_EXPIRED_INTERVAL "refresh_expired_interval"
 #define CONFDB_DOMAIN_OFFLINE_TIMEOUT "offline_timeout"
@@ -232,6 +233,7 @@ struct sss_domain_info {
     uint32_t service_timeout;
     uint32_t autofsmap_timeout;
     uint32_t sudo_timeout;
+    uint32_t gpo_timeout;
 
     uint32_t refresh_expired_interval;
     uint32_t subdomain_refresh_interval;
diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
index 439378ff86d07311f67d51ed775e2d973cd93869..b027e2ba60b09912d076c1727960413e9f297af8 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -130,6 +130,7 @@ option_strings = {
     'entry_cache_service_timeout' : _('Entry cache timeout length (seconds)'),
     'entry_cache_autofs_timeout' : _('Entry cache timeout length (seconds)'),
     'entry_cache_sudo_timeout' : _('Entry cache timeout length (seconds)'),
+    'entry_cache_gpo_timeout' : _('Entry cache timeout length (seconds)'),
     'refresh_expired_interval' : _('How often should expired entries be refreshed in background'),
     'dyndns_update' : _("Whether to automatically update the client's DNS entry"),
     'dyndns_ttl' : _("The TTL to apply to the client's DNS entry after updating it"),
diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py
index 14500031beca7b621eb6a77011e1a48fa22c2f9a..b8dd56b94fee9ada3d86c1cb649aed9122f39820 100755
--- a/src/config/SSSDConfigTest.py
+++ b/src/config/SSSDConfigTest.py
@@ -505,6 +505,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
             'entry_cache_service_timeout',
             'entry_cache_autofs_timeout',
             'entry_cache_sudo_timeout',
+            'entry_cache_gpo_timeout',
             'refresh_expired_interval',
             'lookup_family_order',
             'account_cache_expiration',
@@ -863,6 +864,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
             'entry_cache_service_timeout',
             'entry_cache_autofs_timeout',
             'entry_cache_sudo_timeout',
+            'entry_cache_gpo_timeout',
             'refresh_expired_interval',
             'account_cache_expiration',
             'lookup_family_order',
diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
index 5e5a9284e9ad80d822fe1db4269353aeb7925682..14863b90bae5a8bdb0246960d26ed0f370ea8f8e 100644
--- a/src/config/etc/sssd.api.conf
+++ b/src/config/etc/sssd.api.conf
@@ -133,6 +133,7 @@ entry_cache_netgroup_timeout = int, None, false
 entry_cache_service_timeout = int, None, false
 entry_cache_autofs_timeout = int, None, false
 entry_cache_sudo_timeout = int, None, false
+entry_cache_gpo_timeout = int, None, false
 refresh_expired_interval = int, None, false
 
 # Dynamic DNS updates
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 63f596007cdf53c5ebbdccf37f3c4bcc7830a205..addf13196352825009a4a4a0ebaed7e343c72a14 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -873,6 +873,7 @@ errno_t sysdb_search_object_by_sid(TALLOC_CTX *mem_ctx,
 #define SYSDB_GPO_FILTER "(&(objectClass="SYSDB_GPO_OC")("SYSDB_GPO_GUID_ATTR"=%s))"
 #define SYSDB_GPO_GUID_ATTR "gpoGUID"
 #define SYSDB_GPO_VERSION_ATTR "gpoVersion"
+#define SYSDB_GPO_TIMEOUT_ATTR "gpoPolicyFileTimeout"
 
 #define SYSDB_TMPL_GPO_BASE SYSDB_GPO_CONTAINER","SYSDB_DOM_BASE
 #define SYSDB_TMPL_GPO SYSDB_GPO_GUID_ATTR"=%s,"SYSDB_TMPL_GPO_BASE
@@ -881,15 +882,18 @@ errno_t sysdb_search_object_by_sid(TALLOC_CTX *mem_ctx,
         SYSDB_NAME, \
         SYSDB_GPO_GUID_ATTR, \
         SYSDB_GPO_VERSION_ATTR, \
+        SYSDB_GPO_TIMEOUT_ATTR, \
         NULL }
 
 errno_t sysdb_gpo_store_gpo(struct sss_domain_info *domain,
                             const char *gpo_guid,
-                            int gpo_version);
+                            int gpo_version,
+                            int cache_timeout,
+                            time_t now);
 
-errno_t sysdb_gpo_get_gpo(TALLOC_CTX *mem_ctx,
-                          struct sss_domain_info *domain,
-                          const char *gpo_guid,
-                          struct ldb_result **_result);
+errno_t sysdb_gpo_get_gpo_by_guid(TALLOC_CTX *mem_ctx,
+                                  struct sss_domain_info *domain,
+                                  const char *gpo_guid,
+                                  struct ldb_result **_result);
 
 #endif /* __SYS_DB_H__ */
diff --git a/src/db/sysdb_gpo.c b/src/db/sysdb_gpo.c
index 3c23c5b8fae6aaa41168b1466f4b3e520231e7e2..228f131ace761909c98e0c02fffc889599f86c07 100644
--- a/src/db/sysdb_gpo.c
+++ b/src/db/sysdb_gpo.c
@@ -49,7 +49,9 @@ sysdb_gpo_dn(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain,
 errno_t
 sysdb_gpo_store_gpo(struct sss_domain_info *domain,
                     const char *gpo_guid,
-                    int gpo_version)
+                    int gpo_version,
+                    int cache_timeout,
+                    time_t now)
 {
     errno_t ret, sret;
     int lret;
@@ -81,6 +83,10 @@ sysdb_gpo_store_gpo(struct sss_domain_info *domain,
         goto done;
     }
 
+    if (!now) {
+        now = time(NULL);
+    }
+
     in_transaction = true;
 
     /* Check for an existing gpo_guid entry */
@@ -140,6 +146,21 @@ sysdb_gpo_store_gpo(struct sss_domain_info *domain,
             goto done;
         }
 
+        /* Add the Policy File Timeout */
+        lret = ldb_msg_add_empty(update_msg, SYSDB_GPO_TIMEOUT_ATTR,
+                                 LDB_FLAG_MOD_ADD, NULL);
+        if (lret != LDB_SUCCESS) {
+            ret = sysdb_error_to_errno(lret);
+            goto done;
+        }
+
+        lret = ldb_msg_add_fmt(update_msg, SYSDB_GPO_TIMEOUT_ATTR, "%lu",
+                               ((cache_timeout) ? (now + cache_timeout) : 0));
+        if (lret != LDB_SUCCESS) {
+            ret = sysdb_error_to_errno(lret);
+            goto done;
+        }
+
         lret = ldb_add(domain->sysdb->ldb, update_msg);
         if (lret != LDB_SUCCESS) {
             DEBUG(SSSDBG_MINOR_FAILURE,
@@ -170,6 +191,21 @@ sysdb_gpo_store_gpo(struct sss_domain_info *domain,
             goto done;
         }
 
+        /* Add the Policy File Timeout */
+        lret = ldb_msg_add_empty(update_msg, SYSDB_GPO_TIMEOUT_ATTR,
+                                 LDB_FLAG_MOD_REPLACE, NULL);
+        if (lret != LDB_SUCCESS) {
+            ret = sysdb_error_to_errno(lret);
+            goto done;
+        }
+
+        lret = ldb_msg_add_fmt(update_msg, SYSDB_GPO_TIMEOUT_ATTR, "%lu",
+                               ((cache_timeout) ? (now + cache_timeout) : 0));
+        if (lret != LDB_SUCCESS) {
+            ret = sysdb_error_to_errno(lret);
+            goto done;
+        }
+
         lret = ldb_modify(domain->sysdb->ldb, update_msg);
         if (lret != LDB_SUCCESS) {
             DEBUG(SSSDBG_MINOR_FAILURE,
@@ -202,10 +238,10 @@ done:
 }
 
 errno_t
-sysdb_gpo_get_gpo(TALLOC_CTX *mem_ctx,
-                  struct sss_domain_info *domain,
-                  const char *gpo_guid,
-                  struct ldb_result **_result)
+sysdb_gpo_get_gpo_by_guid(TALLOC_CTX *mem_ctx,
+                          struct sss_domain_info *domain,
+                          const char *gpo_guid,
+                          struct ldb_result **_result)
 {
     errno_t ret;
     int lret;
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 27d22f44ef4449ef9cad026757ff54dd5083672b..9c7a33dab2469a488d5a2b54d7f69e18bac23a15 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -1176,6 +1176,19 @@ fallback_homedir = /home/%u
                 </varlistentry>
 
                 <varlistentry>
+                    <term>entry_cache_gpo_timeout (integer)</term>
+                    <listitem>
+                        <para>
+                            How many seconds should gpo consider
+                            policy files valid before asking the backend again
+                        </para>
+                        <para>
+                            Default: entry_cache_timeout
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry>
                     <term>refresh_expired_interval (integer)</term>
                     <listitem>
                         <para>
diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
index a1cce057ef874ea84c8a0312ce32f8b437ff5c78..31d820fbda79d3ea1d464c76cfaae85815194826 100644
--- a/src/providers/ad/ad_gpo.c
+++ b/src/providers/ad/ad_gpo.c
@@ -123,6 +123,7 @@ struct gp_gpo {
     int num_gpo_cse_guids;
     int gpo_func_version;
     int gpo_flags;
+    bool send_to_child;
 };
 
 enum ace_eval_status {
@@ -157,19 +158,18 @@ int ad_gpo_process_gpo_recv(struct tevent_req *req,
                             int *num_candidate_gpos);
 struct tevent_req *ad_gpo_process_cse_send(TALLOC_CTX *mem_ctx,
                                            struct tevent_context *ev,
-                                           struct sss_domain_info *domain,
+                                           bool send_to_child,
+                                           const char *domain_name,
+                                           const char *gpo_guid,
                                            const char *smb_server,
                                            const char *smb_share,
                                            const char *smb_path,
                                            const char *smb_cse_suffix,
-                                           const char *gpo_guid);
+                                           int cached_gpt_version);
 int ad_gpo_process_cse_recv(struct tevent_req *req,
                             TALLOC_CTX *mem_ctx,
                             int *_sysvol_gpt_version,
-                            int *_allowed_size,
-                            char ***_allowed_sids,
-                            int *_denied_size,
-                            char ***_denied_sids);
+                            const char **_policy_filename);
 
 /* == ad_gpo_access_send/recv helpers =======================================*/
 
@@ -881,6 +881,12 @@ static void ad_gpo_process_som_done(struct tevent_req *subreq);
 static void ad_gpo_process_gpo_done(struct tevent_req *subreq);
 
 static errno_t ad_gpo_cse_step(struct tevent_req *req);
+static errno_t ad_gpo_parse_policy_file(TALLOC_CTX *mem_ctx,
+                                        const char *filename,
+                                        char ***allowed_sids,
+                                        int *allowed_size,
+                                        char ***denied_sids,
+                                        int *denied_size);
 static void ad_gpo_cse_done(struct tevent_req *subreq);
 
 struct tevent_req *
@@ -1305,6 +1311,12 @@ ad_gpo_cse_step(struct tevent_req *req)
     struct tevent_req *subreq;
     struct ad_gpo_access_state *state;
     int i = 0;
+    struct ldb_result *res;
+    errno_t ret;
+    bool found_in_cache = false;
+    bool send_to_child = true;
+    int cached_gpt_version = 0;
+    time_t policy_file_timeout = 0;
 
     state = tevent_req_data(req, struct ad_gpo_access_state);
 
@@ -1327,14 +1339,69 @@ ad_gpo_cse_step(struct tevent_req *req)
     DEBUG(SSSDBG_TRACE_FUNC, "smb_path: %s\n", cse_filtered_gpo->smb_path);
     DEBUG(SSSDBG_TRACE_FUNC, "gpo_guid: %s\n", cse_filtered_gpo->gpo_guid);
 
+    /* retrieve gpo cache entry; set cached_gpt_version to -1 if unavailable */
+    DEBUG(SSSDBG_TRACE_FUNC, "retrieving GPO from cache [%s]\n",
+          cse_filtered_gpo->gpo_guid);
+    ret = sysdb_gpo_get_gpo_by_guid(state,
+                                    state->domain,
+                                    cse_filtered_gpo->gpo_guid,
+                                    &res);
+    if (ret == EOK) {
+        found_in_cache = true;
+    } else {
+        switch (ret) {
+        case ENOENT:
+            DEBUG(SSSDBG_TRACE_FUNC, "ENOENT\n");
+            cached_gpt_version = -1;
+            break;
+        default:
+            DEBUG(SSSDBG_FATAL_FAILURE, "Could not read GPO from cache: [%s]\n",
+                  strerror(ret));
+            return ret;
+        }
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC, "found_in_cache: %d\n", found_in_cache);
+    if (found_in_cache) {
+
+        /*
+         * Note: if the timeout is valid, then we can later avoid downloading
+         * the GPT.INI file, as well as any policy files (i.e. we don't need
+         * to interact with the gpo_child at all). However, even if the timeout
+         * is not valid, while we will have to interact with the gpo child to
+         * download the GPT.INI file, we may still be able to avoid downloading
+         * the policy files (if the cached_gpt_version is the same as the
+         * GPT.INI version). In other words, the timeout is *not* an expiration
+         * for the entire cache entry; the cached_gpt_version never expires.
+         */
+
+        cached_gpt_version = ldb_msg_find_attr_as_int(res->msgs[0],
+                                                      SYSDB_GPO_VERSION_ATTR,
+                                                      0);
+
+        policy_file_timeout = ldb_msg_find_attr_as_uint64
+            (res->msgs[0], SYSDB_GPO_TIMEOUT_ATTR, 0);
+
+        if (policy_file_timeout >= time(NULL)) {
+            send_to_child = false;
+        }
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC, "send_to_child: %d\n", send_to_child);
+    DEBUG(SSSDBG_TRACE_FUNC, "cached_gpt_version: %d\n", cached_gpt_version);
+
+    cse_filtered_gpo->send_to_child = send_to_child;
+
     subreq = ad_gpo_process_cse_send(state,
                                      state->ev,
-                                     state->domain,
+                                     send_to_child,
+                                     state->domain->name,
+                                     cse_filtered_gpo->gpo_guid,
                                      cse_filtered_gpo->smb_server,
                                      cse_filtered_gpo->smb_share,
                                      cse_filtered_gpo->smb_path,
                                      GP_EXT_GUID_SECURITY_SUFFIX,
-                                     cse_filtered_gpo->gpo_guid);
+                                     cached_gpt_version);
 
     tevent_req_set_callback(subreq, ad_gpo_cse_done, req);
     return EAGAIN;
@@ -1356,10 +1423,12 @@ ad_gpo_cse_done(struct tevent_req *subreq)
     struct ad_gpo_access_state *state;
     int ret;
     int sysvol_gpt_version;
+    const char *policy_filename = NULL;
     char **allowed_sids;
     int allowed_size;
     char **denied_sids;
     int denied_size;
+    time_t now;
 
     req = tevent_req_callback_data(subreq, struct tevent_req);
     state = tevent_req_data(req, struct ad_gpo_access_state);
@@ -1372,8 +1441,7 @@ ad_gpo_cse_done(struct tevent_req *subreq)
     DEBUG(SSSDBG_TRACE_FUNC, "gpo_guid: %s\n", gpo_guid);
 
     ret = ad_gpo_process_cse_recv(subreq, state, &sysvol_gpt_version,
-                                  &allowed_size, &allowed_sids,
-                                  &denied_size, &denied_sids);
+                                  &policy_filename);
 
     talloc_zfree(subreq);
 
@@ -1383,17 +1451,35 @@ ad_gpo_cse_done(struct tevent_req *subreq)
         goto done;
     }
 
-    DEBUG(SSSDBG_TRACE_FUNC, "sysvol_gpt_version: %d\n", sysvol_gpt_version);
+    /* only store to cache (and refresh timeout) if we interacted with child */
+    if (cse_filtered_gpo->send_to_child) {
 
-    ret = sysdb_gpo_store_gpo(state->domain, gpo_guid, sysvol_gpt_version);
+        DEBUG(SSSDBG_TRACE_FUNC, "sysvol_gpt_version: %d\n", sysvol_gpt_version);
+
+        now = time(NULL);
+        ret = sysdb_gpo_store_gpo(state->domain, gpo_guid, sysvol_gpt_version,
+                                  state->domain->gpo_timeout, now);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, "Unable to store gpo cache entry: [%d](%s}\n",
+                  ret, sss_strerror(ret));
+            goto done;
+        }
+    }
+
+    ret = ad_gpo_parse_policy_file(state,
+                                   policy_filename,
+                                   &allowed_sids,
+                                   &allowed_size,
+                                   &denied_sids,
+                                   &denied_size);
 
     if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE, "Unable to store gpo cache entry: [%d](%s}\n",
-              ret, sss_strerror(ret));
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Cannot parse policy file: [%s][%d][%s]\n",
+              policy_filename, ret, strerror(ret));
         goto done;
     }
 
-    /* TBD: allowed/denied_sids/size, should be retrieved from cache */
     ret = ad_gpo_access_check
         (state, state->gpo_mode, state->user, state->domain,
          allowed_sids, allowed_size, denied_sids, denied_size);
@@ -2380,8 +2466,22 @@ ad_gpo_extract_smb_components(TALLOC_CTX *mem_ctx,
     *_smb_server = talloc_asprintf(mem_ctx, "%s%s",
                                    SMB_STANDARD_URI,
                                    server_hostname);
+    if (*_smb_server == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
     *_smb_share = talloc_asprintf(mem_ctx, "/%s", smb_share);
+    if (*_smb_share == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
     *_smb_path = talloc_asprintf(mem_ctx, "/%s", smb_path);
+    if (*_smb_path == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
 
     ret = EOK;
 
@@ -3136,6 +3236,8 @@ struct ad_gpo_process_cse_state {
     struct tevent_context *ev;
     const char *smb_path;
     const char *smb_cse_suffix;
+    int sysvol_gpt_version;
+    const char *policy_filename;
     pid_t child_pid;
     uint8_t *buf;
     ssize_t len;
@@ -3191,19 +3293,19 @@ static void gpo_cse_done(struct tevent_req *subreq);
 struct tevent_req *
 ad_gpo_process_cse_send(TALLOC_CTX *mem_ctx,
                         struct tevent_context *ev,
-                        struct sss_domain_info *domain,
+                        bool send_to_child,
+                        const char *domain_name,
+                        const char *gpo_guid,
                         const char *smb_server,
                         const char *smb_share,
                         const char *smb_path,
                         const char *smb_cse_suffix,
-                        const char *gpo_guid)
+                        int cached_gpt_version)
 {
     struct tevent_req *req;
     struct tevent_req *subreq;
     struct ad_gpo_process_cse_state *state;
-    struct ldb_result *res;
     struct io_buffer *buf = NULL;
-    int cached_gpt_version = 0;
     errno_t ret;
 
     req = tevent_req_create(mem_ctx, &state, struct ad_gpo_process_cse_state);
@@ -3212,6 +3314,29 @@ ad_gpo_process_cse_send(TALLOC_CTX *mem_ctx,
         return NULL;
     }
 
+    state->sysvol_gpt_version = -1;
+
+    if (!send_to_child) {
+        /*
+         * if we don't need to talk to child (b/c cache timeout is valid),
+         * we simply set the policy_filename and complete the request
+         */
+        state->policy_filename =
+            talloc_asprintf(state,
+                            GPO_CACHE_PATH"/%s/Policies/%s%s",
+                            domain_name,
+                            gpo_guid,
+                            GP_EXT_GUID_SECURITY_SUFFIX);
+        if (state->policy_filename == NULL) {
+            ret = ENOMEM;
+            goto immediately;
+        }
+
+        DEBUG(SSSDBG_TRACE_FUNC, "policy_filename:%s\n", state->policy_filename);
+        ret = EOK;
+        goto immediately;
+    }
+
     state->ev = ev;
     state->buf = NULL;
     state->len = 0;
@@ -3221,64 +3346,47 @@ ad_gpo_process_cse_send(TALLOC_CTX *mem_ctx,
     if (state->io == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
         ret = ENOMEM;
-        goto fail;
+        goto immediately;
     }
 
     state->io->write_to_child_fd = -1;
     state->io->read_from_child_fd = -1;
     talloc_set_destructor((void *) state->io, gpo_child_io_destructor);
 
-    /* retrieve cached gpt version (or set it to -1 if unavailable) */
-    DEBUG(SSSDBG_TRACE_FUNC, "retrieving GPO from cache [%s]\n", gpo_guid);
-    ret = sysdb_gpo_get_gpo(state, domain, gpo_guid, &res);
-    if (ret != EOK) {
-        switch (ret) {
-        case ENOENT:
-            DEBUG(SSSDBG_TRACE_FUNC, "ENOENT\n");
-            cached_gpt_version = -1;
-            break;
-        default:
-            DEBUG(SSSDBG_FATAL_FAILURE, "Could not read GPO from cache: [%s]\n",
-                  strerror(ret));
-            goto fail;
-        }
-    }
-
-    if (cached_gpt_version != -1) {
-        /* cached_gpt_version is in cache, so retrieve it from cache */
-        cached_gpt_version = ldb_msg_find_attr_as_int(res->msgs[0],
-                                                      SYSDB_GPO_VERSION_ATTR,
-                                                      0);
-    }
-    DEBUG(SSSDBG_TRACE_FUNC, "cached_gpt_version: %d\n", cached_gpt_version);
-
     /* prepare the data to pass to child */
     ret = create_cse_send_buffer(state, smb_server, smb_share, smb_path,
                                  smb_cse_suffix, cached_gpt_version, &buf);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE, "create_cse_send_buffer failed.\n");
-        goto fail;
+        goto immediately;
     }
 
     ret = gpo_fork_child(req);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE, "gpo_fork_child failed.\n");
-        goto fail;
+        goto immediately;
     }
 
     subreq = write_pipe_send(state, ev, buf->data, buf->size,
                              state->io->write_to_child_fd);
     if (subreq == NULL) {
         ret = ENOMEM;
-        goto fail;
+        goto immediately;
     }
     tevent_req_set_callback(subreq, gpo_cse_step, req);
 
     return req;
 
-fail:
-    tevent_req_error(req, ret);
-    tevent_req_post(req, ev);
+immediately:
+
+    if (ret == EOK) {
+        tevent_req_done(req);
+        tevent_req_post(req, ev);
+    } else {
+        tevent_req_error(req, ret);
+        tevent_req_post(req, ev);
+    }
+
     return req;
 }
 
@@ -3314,6 +3422,8 @@ static void gpo_cse_done(struct tevent_req *subreq)
 {
     struct tevent_req *req;
     struct ad_gpo_process_cse_state *state;
+    uint32_t sysvol_gpt_version = -1;
+    uint32_t child_result;
 
     req = tevent_req_callback_data(subreq, struct tevent_req);
     state = tevent_req_data(req, struct ad_gpo_process_cse_state);
@@ -3329,69 +3439,49 @@ static void gpo_cse_done(struct tevent_req *subreq)
     close(state->io->read_from_child_fd);
     state->io->read_from_child_fd = -1;
 
-    tevent_req_done(req);
-    return;
-}
-
-int ad_gpo_process_cse_recv(struct tevent_req *req,
-                            TALLOC_CTX *mem_ctx,
-                            int *_sysvol_gpt_version,
-                            int *_allowed_size,
-                            char ***_allowed_sids,
-                            int *_denied_size,
-                            char ***_denied_sids)
-{
-    int ret;
-    uint32_t sysvol_gpt_version;
-    uint32_t result;
-    char **allowed_sids;
-    int allowed_size;
-    char **denied_sids;
-    int denied_size;
-    struct ad_gpo_process_cse_state *state;
-    const char *policy_filename = NULL;
-
-    state = tevent_req_data(req, struct ad_gpo_process_cse_state);
-
-    TEVENT_REQ_RETURN_ON_ERROR(req);
-
     ret = ad_gpo_parse_gpo_child_response(state, state->buf, state->len,
-                                          &sysvol_gpt_version, &result);
+                                          &sysvol_gpt_version, &child_result);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE,
               "ad_gpo_parse_gpo_child_response failed: [%d][%s]\n",
               ret, strerror(ret));
-        return ret;
-    } else if (result != 0){
+        tevent_req_error(req, ret);
+    } else if (child_result != 0){
         DEBUG(SSSDBG_CRIT_FAILURE,
-              "Error in gpo_child: [%d][%s]\n", result, strerror(result));
-        return result;
+              "Error in gpo_child: [%d][%s]\n",
+              child_result, strerror(child_result));
+        tevent_req_error(req, child_result);
     }
 
-    policy_filename = talloc_asprintf(mem_ctx, GPO_CACHE_PATH"%s%s",
-                               state->smb_path, state->smb_cse_suffix);
+    state->sysvol_gpt_version = sysvol_gpt_version;
+    state->policy_filename = talloc_asprintf(state,
+                                             GPO_CACHE_PATH"%s%s",
+                                             state->smb_path,
+                                             state->smb_cse_suffix);
+    if (state->policy_filename == NULL) {
+        tevent_req_error(req, ENOMEM);
+    }
 
-    DEBUG(SSSDBG_TRACE_FUNC, "policy_filename:%s\n", policy_filename);
 
-    ret = ad_gpo_parse_policy_file(state,
-                                   policy_filename,
-                                   &allowed_sids,
-                                   &allowed_size,
-                                   &denied_sids,
-                                   &denied_size);
+    DEBUG(SSSDBG_TRACE_FUNC, "policy_filename:%s\n", state->policy_filename);
 
-    if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Cannot parse policy file: [%s][%d][%s]\n",
-              policy_filename, ret, strerror(ret));
-        return ret;
-    }
+    tevent_req_done(req);
+    return;
+}
+
+int ad_gpo_process_cse_recv(struct tevent_req *req,
+                            TALLOC_CTX *mem_ctx,
+                            int *_sysvol_gpt_version,
+                            const char **_policy_filename)
+{
+    struct ad_gpo_process_cse_state *state;
+
+    state = tevent_req_data(req, struct ad_gpo_process_cse_state);
+
+    TEVENT_REQ_RETURN_ON_ERROR(req);
 
-    *_sysvol_gpt_version = sysvol_gpt_version;
-    *_allowed_size = allowed_size;
-    *_allowed_sids = talloc_steal(mem_ctx, allowed_sids);
-    *_denied_size = denied_size;
-    *_denied_sids = talloc_steal(mem_ctx, denied_sids);
+    *_sysvol_gpt_version = state->sysvol_gpt_version;
+    *_policy_filename = talloc_steal(mem_ctx, state->policy_filename);
 
     return EOK;
 }
-- 
1.8.5.3

_______________________________________________
sssd-devel mailing list
[email protected]
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to