summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYassir Elley <yelley@redhat.com>2014-09-07 23:23:26 -0400
committerJakub Hrozek <jhrozek@redhat.com>2014-09-08 20:49:06 +0200
commiteb0cde4e6dfdbda08588860534f7ece5776ec3af (patch)
tree78fbcff93cf8a9edcce7473fd6c4df4e6071e85b
parent53b6d6e82dbe52aa655f910e87eb3595584aa9c9 (diff)
downloadsssd-eb0cde4e6dfdbda08588860534f7ece5776ec3af.tar.gz
sssd-eb0cde4e6dfdbda08588860534f7ece5776ec3af.tar.xz
sssd-eb0cde4e6dfdbda08588860534f7ece5776ec3af.zip
AD-GPO: delete stale GPOs
https://fedorahosted.org/sssd/ticket/2431 Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-rw-r--r--src/db/sysdb.h5
-rw-r--r--src/db/sysdb_gpo.c93
-rw-r--r--src/providers/ad/ad_gpo.c36
3 files changed, 134 insertions, 0 deletions
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 295949cf4..901b6129b 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -908,4 +908,9 @@ errno_t sysdb_gpo_get_gpos(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
struct ldb_result **_result);
+errno_t sysdb_gpo_delete_stale_gpos(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ const char **gpo_guid_list,
+ int num_gpos);
+
#endif /* __SYS_DB_H__ */
diff --git a/src/db/sysdb_gpo.c b/src/db/sysdb_gpo.c
index 7dd31d81a..e0b9bb9f0 100644
--- a/src/db/sysdb_gpo.c
+++ b/src/db/sysdb_gpo.c
@@ -352,3 +352,96 @@ done:
talloc_free(tmp_ctx);
return ret;
}
+
+static inline bool
+sysdb_gpo_guid_in_list(const char **gpo_guid_list, int num_gpos, const char *gpo_guid)
+{
+ size_t i;
+
+ for (i = 0; i < num_gpos; i++) {
+ if (strcasecmp(gpo_guid_list[i], gpo_guid) == 0) {
+ break;
+ }
+ }
+
+ return (i < num_gpos) ? true : false;
+}
+
+errno_t
+sysdb_gpo_delete_stale_gpos(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ const char **gpo_guid_list,
+ int num_gpos)
+{
+ struct ldb_result *res;
+ errno_t ret, sret;
+ int i;
+ bool in_transaction = false;
+ const char *cached_gpo_guid;
+ bool stale_gpo_found = false;
+
+ ret = sysdb_transaction_start(domain->sysdb);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
+ goto done;
+ }
+
+ in_transaction = true;
+
+ ret = sysdb_gpo_get_gpos(mem_ctx, domain, &res);
+ if (ret != EOK && ret != ENOENT) {
+ goto done;
+ } else if (ret != ENOENT) {
+ for (i = 0; i < res->count; i++) {
+ cached_gpo_guid = ldb_msg_find_attr_as_string(res->msgs[i],
+ SYSDB_GPO_GUID_ATTR,
+ NULL);
+ if (cached_gpo_guid == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "No gpo_guid attribute found in gpo cache entry\n");
+ ret = EFAULT;
+ goto done;
+ }
+
+ if (sysdb_gpo_guid_in_list(gpo_guid_list, num_gpos, cached_gpo_guid)) {
+ /* the cached_gpo_guid is still applicable, skip it */
+ continue;
+ } else {
+ stale_gpo_found = true;
+ /* the cached_gpo_guid is no longer applicable, delete it */
+ DEBUG(SSSDBG_TRACE_FUNC, "Deleting stale GPO [gpo_guid:%s]\n",
+ cached_gpo_guid);
+
+ ret = sysdb_delete_entry(domain->sysdb, res->msgs[i]->dn, true);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "Could not delete GPO cache entry [gpo_guid:%s]\n",
+ cached_gpo_guid);
+ goto done;
+ }
+ }
+ }
+ }
+
+ if (!stale_gpo_found) {
+ DEBUG(SSSDBG_TRACE_FUNC, "No stale GPOs found\n");
+ }
+
+ ret = sysdb_transaction_commit(domain->sysdb);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Could not commit transaction: [%s]\n", strerror(ret));
+ goto done;
+ }
+ in_transaction = false;
+
+done:
+ if (in_transaction) {
+ sret = sysdb_transaction_cancel(domain->sysdb);
+ if (sret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n");
+ }
+ }
+ return ret;
+
+}
diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
index 9afb9ff89..de4d44166 100644
--- a/src/providers/ad/ad_gpo.c
+++ b/src/providers/ad/ad_gpo.c
@@ -1733,6 +1733,7 @@ ad_gpo_process_gpo_done(struct tevent_req *subreq)
struct gp_gpo **candidate_gpos = NULL;
int num_candidate_gpos = 0;
int i = 0;
+ const char **cse_filtered_gpo_guids;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_gpo_access_state);
@@ -1798,14 +1799,49 @@ ad_gpo_process_gpo_done(struct tevent_req *subreq)
goto done;
}
+ /* we create and populate an array of applicable gpo-guids */
+ cse_filtered_gpo_guids =
+ talloc_array(state, const char *, state->num_cse_filtered_gpos);
+ if (cse_filtered_gpo_guids == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
for (i = 0; i < state->num_cse_filtered_gpos; i++) {
DEBUG(SSSDBG_TRACE_FUNC, "cse_filtered_gpos[%d]->gpo_guid is %s\n", i,
state->cse_filtered_gpos[i]->gpo_guid);
+ cse_filtered_gpo_guids[i] = talloc_steal(cse_filtered_gpo_guids,
+ state->cse_filtered_gpos[i]->gpo_guid);
+ if (cse_filtered_gpo_guids[i] == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
}
DEBUG(SSSDBG_TRACE_FUNC, "num_cse_filtered_gpos: %d\n",
state->num_cse_filtered_gpos);
+ /*
+ * we now have the array of applicable gpos in hand; however, since we
+ * may have cached a larger set of gpo-guids previously, we delete
+ * all stale gpo cache entries (i.e. entries that have a gpo-guid that
+ * doesn't match any of the gpo-guids in the cse_filtered_gpo_guids list)
+ */
+ ret = sysdb_gpo_delete_stale_gpos(state, state->domain,
+ cse_filtered_gpo_guids,
+ state->num_cse_filtered_gpos);
+ if (ret != EOK) {
+ switch (ret) {
+ case ENOENT:
+ DEBUG(SSSDBG_OP_FAILURE, "No GPOs available in cache\n");
+ default:
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ "Could not delete stale GPOs from cache: [%s]\n",
+ strerror(ret));
+ goto done;
+ }
+ }
+
ret = ad_gpo_cse_step(req);
done: