Blame SOURCES/slapi-nis-ID-views-ignore-searches-for-views-outside-the-subtrees.patch

eeac78
From 79391fda05fba164af577bd0e08a2807643b7b48 Mon Sep 17 00:00:00 2001
eeac78
From: Alexander Bokovoy <abokovoy@redhat.com>
eeac78
Date: Tue, 28 Oct 2014 10:09:47 +0200
eeac78
Subject: [PATCH 1/2] ID views: ignore searches for views outside the subtrees
eeac78
 of schema-compat sets
eeac78
eeac78
schema-compat plugin may provide multiple disjoint subtrees which
eeac78
can be used to request overridden entries by prefixing the subtree
eeac78
suffix with a
eeac78
eeac78
  cn=<name of view>,cn=views,<subtree suffix>
eeac78
eeac78
As subtrees may be disjoint, we cannot rely on the common suffix. Thus,
eeac78
any attempt to replace target DN and update filter terms must only be
eeac78
done once we are sure the search will be done in the subtree.
eeac78
eeac78
This optimization prevents mistakenly changing the search filter when
eeac78
FreeIPA and SSSD search for the ID overrides themselves, as the same
eeac78
structure of the target DN is used for  cn=views,cn=accounts,$SUFFIX
eeac78
subtree in FreeIPA. This subtree is never handled by slapi-nis and
eeac78
should be ignored.
eeac78
eeac78
https://bugzilla.redhat.com/show_bug.cgi?id=1157989
eeac78
---
eeac78
 src/back-sch-idview.c | 11 +++++--
eeac78
 src/back-sch.c        | 81 +++++++++++++++++++++++++++++++++++++++++++++------
eeac78
 2 files changed, 81 insertions(+), 11 deletions(-)
eeac78
eeac78
diff --git a/src/back-sch-idview.c b/src/back-sch-idview.c
eeac78
index 5a2b450..a56a9e9 100644
eeac78
--- a/src/back-sch-idview.c
eeac78
+++ b/src/back-sch-idview.c
eeac78
@@ -334,6 +334,10 @@ idview_process_filter_cb(Slapi_Filter *filter, const char *filter_type, struct b
eeac78
 						slapi_ber_bvdone(bval);
eeac78
 						slapi_ber_bvcpy(bval, slapi_value_get_berval(anchor_val));
eeac78
 						config->override_found = TRUE;
eeac78
+						slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id,
eeac78
+								"Overriding the filter %s with %s=%*s from the override %s\n.",
eeac78
+								filter_type, filter_type, bval->bv_len, bval->bv_val,
eeac78
+								slapi_entry_get_dn_const(cbdata->overrides[i]));
eeac78
 						break;
eeac78
 					}
eeac78
 				}
eeac78
@@ -346,6 +350,11 @@ idview_process_filter_cb(Slapi_Filter *filter, const char *filter_type, struct b
eeac78
 					slapi_ber_bvdone(bval);
eeac78
 					slapi_ber_bvcpy(bval, slapi_value_get_berval(anchor_val));
eeac78
 					config->override_found = TRUE;
eeac78
+					slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id,
eeac78
+							"Overriding the filter %s with %s=%*s from the override %s\n.",
eeac78
+							filter_type, IPA_IDVIEWS_ATTR_ANCHORUUID,
eeac78
+							bval->bv_len, bval->bv_val,
eeac78
+							slapi_entry_get_dn_const(cbdata->overrides[i]));
eeac78
 					break;
eeac78
 				}
eeac78
 
eeac78
@@ -366,8 +375,6 @@ idview_process_filter_cb(Slapi_Filter *filter, const char *filter_type, struct b
eeac78
  *
eeac78
  * Note that in reality we don't use original value of the uid/cn attribue. Instead, we use ipaAnchorUUID
eeac78
  * to refer to the original entry. */
eeac78
-extern char *
eeac78
-slapi_filter_to_string( const struct slapi_filter *f, char *buf, size_t bufsize );
eeac78
 void
eeac78
 idview_replace_filter(struct backend_search_cbdata *cbdata)
eeac78
 {
eeac78
diff --git a/src/back-sch.c b/src/back-sch.c
eeac78
index 27d5101..27ac24f 100644
eeac78
--- a/src/back-sch.c
eeac78
+++ b/src/back-sch.c
eeac78
@@ -1166,6 +1166,44 @@ backend_search_set_cb(const char *group, const char *set, bool_t flag,
eeac78
 	return TRUE;
eeac78
 }
eeac78
 
eeac78
+/* Routines to search if a target DN is within any of the sets we handle */
eeac78
+static bool_t
eeac78
+backend_search_find_set_dn_in_group_cb(const char *group, const char *set, bool_t flag,
eeac78
+					 void *backend_data, void *cb_data)
eeac78
+{
eeac78
+	struct backend_search_cbdata *cbdata;
eeac78
+	struct backend_set_data *set_data;
eeac78
+
eeac78
+	cbdata = cb_data;
eeac78
+	set_data = backend_data;
eeac78
+
eeac78
+	if (slapi_sdn_scope_test(cbdata->target_dn,
eeac78
+				 set_data->container_sdn,
eeac78
+				 cbdata->scope) == 1) {
eeac78
+		cbdata->answer = TRUE;
eeac78
+	}
eeac78
+
eeac78
+	if (slapi_sdn_compare(set_data->container_sdn,
eeac78
+			      cbdata->target_dn) == 0) {
eeac78
+		cbdata->answer = TRUE;
eeac78
+	}
eeac78
+
eeac78
+	return TRUE;
eeac78
+
eeac78
+}
eeac78
+
eeac78
+static bool_t
eeac78
+backend_search_find_set_dn_cb(const char *group, void *cb_data)
eeac78
+{
eeac78
+	struct backend_search_cbdata *cbdata;
eeac78
+
eeac78
+	cbdata = cb_data;
eeac78
+	map_data_foreach_map(cbdata->state, group,
eeac78
+			     backend_search_find_set_dn_in_group_cb, cb_data);
eeac78
+	return TRUE;
eeac78
+}
eeac78
+
eeac78
+/* Routines to find out the set that has the same group as requested */
eeac78
 static bool_t
eeac78
 backend_search_find_set_data_in_group_cb(const char *group, const char *set, bool_t flag,
eeac78
 					 void *backend_data, void *cb_data)
eeac78
@@ -1340,9 +1378,6 @@ backend_search_cb(Slapi_PBlock *pb)
eeac78
 			"searching from \"%s\" for \"%s\" with scope %d%s\n",
eeac78
 			cbdata.target, cbdata.strfilter, cbdata.scope,
eeac78
 			backend_sch_scope_as_string(cbdata.scope));
eeac78
-#ifdef USE_IPA_IDVIEWS
eeac78
-	idview_replace_target_dn(&cbdata.target, &cbdata.idview);
eeac78
-#endif
eeac78
 	cbdata.target_dn = slapi_sdn_new_dn_byval(cbdata.target);
eeac78
 	/* Check if there's a backend handling this search. */
eeac78
 	if (!slapi_be_exist(cbdata.target_dn)) {
eeac78
@@ -1351,19 +1386,47 @@ backend_search_cb(Slapi_PBlock *pb)
eeac78
 				"slapi_be_exists(\"%s\") = 0, "
eeac78
 				"ignoring search\n", cbdata.target);
eeac78
 		slapi_sdn_free(&cbdata.target_dn);
eeac78
+		return 0;
eeac78
+	}
eeac78
+
eeac78
+#ifdef USE_IPA_IDVIEWS
eeac78
+	/* We may have multiple disjoint trees in the sets, search if the target matches any of them
eeac78
+	 * as in general there don't have to be a single subtree (cn=compat,$SUFFIX) for all trees to easily
eeac78
+	 * detect the ID view use. Unless the ID view is within the set we control, don't consider the override */
eeac78
+	map_data_foreach_domain(cbdata.state, backend_search_find_set_dn_cb, &cbdata);
eeac78
+	if (cbdata.answer == FALSE) {
eeac78
+		idview_replace_target_dn(&cbdata.target, &cbdata.idview);
eeac78
 		if (cbdata.idview != NULL) {
eeac78
-			slapi_ch_free_string(&cbdata.target);
eeac78
+			slapi_sdn_free(&cbdata.target_dn);
eeac78
+			/* Perform another check, now for rewritten DN */
eeac78
+			cbdata.target_dn = slapi_sdn_new_dn_byval(cbdata.target);
eeac78
+			map_data_foreach_domain(cbdata.state, backend_search_find_set_dn_cb, &cbdata);
eeac78
+			/* Rewritten DN might still be outside of our trees */
eeac78
+			if (cbdata.answer == TRUE) {
eeac78
+				slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id,
eeac78
+						"Use of ID view '%s' is detected, searching from \"%s\" "
eeac78
+						"for \"%s\" with scope %d%s. Filter may get overridden later.\n",
eeac78
+						cbdata.idview, cbdata.target, cbdata.strfilter, cbdata.scope,
eeac78
+						backend_sch_scope_as_string(cbdata.scope));
eeac78
+			} else {
eeac78
+				slapi_sdn_free(&cbdata.target_dn);
eeac78
+				slapi_ch_free_string(&cbdata.target);
eeac78
+				slapi_ch_free_string(&cbdata.idview);
eeac78
+				slapi_log_error(SLAPI_LOG_PLUGIN,
eeac78
+						cbdata.state->plugin_desc->spd_id,
eeac78
+						"The search base didn't match any of the containers, "
eeac78
+						"ignoring search\n");
eeac78
+				return 0;
eeac78
+			}
eeac78
 		}
eeac78
-		slapi_ch_free_string(&cbdata.idview);
eeac78
-#ifdef USE_IPA_IDVIEWS
eeac78
-		idview_free_overrides(&cbdata);
eeac78
-#endif
eeac78
-		return 0;
eeac78
 	}
eeac78
+	cbdata.answer = FALSE;
eeac78
+#endif
eeac78
 
eeac78
 	/* Walk the list of groups. */
eeac78
 	wrap_inc_call_level();
eeac78
 #ifdef USE_IPA_IDVIEWS
eeac78
+	/* Filter replacement requires increased call level as we may fetch overrides and thus come back here */
eeac78
 	idview_replace_filter(&cbdata);
eeac78
 #endif
eeac78
 	if (map_rdlock() == 0) {
eeac78
-- 
eeac78
2.1.0
eeac78