eeac78
From 5f5f302e97560b05b154473f562410733e0b775b Mon Sep 17 00:00:00 2001
eeac78
From: Alexander Bokovoy <abokovoy@redhat.com>
eeac78
Date: Tue, 28 Oct 2014 11:16:50 +0200
eeac78
Subject: [PATCH 2/2] schema-compat: support ID overrides in bind callback
eeac78
eeac78
If RDN of the bind DN is overridden within the ID view, rewrite the
eeac78
target to use original value of the uid attribute.
eeac78
eeac78
If original uid attribute is not available, fail the search and thus
eeac78
the whole bind request by claiming that bind DN does not exist.
eeac78
---
eeac78
 src/back-sch-idview.c | 86 ++++++++++++++++++++++++++++++++++-----------------
eeac78
 src/back-sch.c        | 57 +++++++++++++++++++++++++++++-----
eeac78
 src/back-sch.h        |  4 +++
eeac78
 3 files changed, 111 insertions(+), 36 deletions(-)
eeac78
eeac78
diff --git a/src/back-sch-idview.c b/src/back-sch-idview.c
eeac78
index a56a9e9..f1150cd 100644
eeac78
--- a/src/back-sch-idview.c
eeac78
+++ b/src/back-sch-idview.c
eeac78
@@ -290,21 +290,15 @@ idview_replace_target_dn(char **target, char **idview)
eeac78
 	}
eeac78
 }
eeac78
 
eeac78
-static int
eeac78
-idview_process_filter_cb(Slapi_Filter *filter, const char *filter_type, struct berval *bval, struct backend_search_filter_config *config)
eeac78
+int
eeac78
+idview_replace_bval_by_override(const char *bval_usage, const char *attr_name,
eeac78
+				struct berval *bval, struct backend_search_cbdata *cbdata)
eeac78
 {
eeac78
 	int res, i;
eeac78
-	Slapi_Value *filter_val, *value, *anchor_val;
eeac78
+	Slapi_Value *attr_val, *value, *anchor_val;
eeac78
 	Slapi_Attr *anchor, *attr = NULL;
eeac78
-	struct backend_search_cbdata *cbdata = (struct backend_search_cbdata *) config->callback_data;
eeac78
-
eeac78
-	if (cbdata == NULL || cbdata->idview == NULL) {
eeac78
-		return SLAPI_FILTER_SCAN_CONTINUE;
eeac78
-	}
eeac78
-
eeac78
-	if (filter_type == NULL || config->name == NULL) {
eeac78
-		return SLAPI_FILTER_SCAN_CONTINUE;
eeac78
-	}
eeac78
+	bool_t uid_override_found = FALSE;
eeac78
+	bool_t anchor_override_found = FALSE;
eeac78
 
eeac78
 	if (cbdata->overrides == NULL) {
eeac78
 		/* Only retrieve overrides for the view first time when neccessary */
eeac78
@@ -312,31 +306,34 @@ idview_process_filter_cb(Slapi_Filter *filter, const char *filter_type, struct b
eeac78
 	}
eeac78
 
eeac78
 	if (cbdata->overrides == NULL) {
eeac78
-		return SLAPI_FILTER_SCAN_CONTINUE;
eeac78
+		return 0;
eeac78
 	}
eeac78
 
eeac78
-	filter_val = slapi_value_new_berval(bval);
eeac78
+	attr_val = slapi_value_new_berval(bval);
eeac78
+	slapi_log_error(SLAPI_LOG_FATAL, cbdata->state->plugin_desc->spd_id,
eeac78
+			"Searching for an override of the %s %s with %s=%*s from the overrides\n.",
eeac78
+			bval_usage, attr_name, attr_name, (int) bval->bv_len, bval->bv_val);
eeac78
 
eeac78
 	/* If filter contains an attribute name which is overridden in the view and filter value
eeac78
 	 * corresponds to the override, replace the filter by (ipaAnchorUUID=...) from the override
eeac78
 	 * to point to the original because otherwise an entry will not be found in the slapi-nis map */
eeac78
 	for(i=0; cbdata->overrides[i] != NULL; i++) {
eeac78
-		res = slapi_entry_attr_find(cbdata->overrides[i], filter_type, &attr);
eeac78
+		res = slapi_entry_attr_find(cbdata->overrides[i], attr_name, &attr);
eeac78
 		if ((res == 0) && (attr != NULL)) {
eeac78
 			res = slapi_attr_first_value(attr, &value);
eeac78
-			res = slapi_value_compare(attr, value, filter_val);
eeac78
+			res = slapi_value_compare(attr, value, attr_val);
eeac78
 			if (res == 0) {
eeac78
 				/* For uid overrides we should have ipaOriginalUID in the override */
eeac78
-				if (strcasecmp(filter_type, "uid") == 0) {
eeac78
+				if (strcasecmp(attr_name, "uid") == 0) {
eeac78
 					res = slapi_entry_attr_find(cbdata->overrides[i], IPA_IDVIEWS_ATTR_ORIGINALUID, &anchor);
eeac78
 					if (res == 0) {
eeac78
 						res = slapi_attr_first_value(anchor, &anchor_val);
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
+						uid_override_found = TRUE;
eeac78
+						slapi_log_error(SLAPI_LOG_FATAL, cbdata->state->plugin_desc->spd_id,
eeac78
+								"Overriding the %s %s with %s=%*s from the override %s\n.",
eeac78
+								bval_usage, attr_name, attr_name, (int) bval->bv_len, bval->bv_val,
eeac78
 								slapi_entry_get_dn_const(cbdata->overrides[i]));
eeac78
 						break;
eeac78
 					}
eeac78
@@ -346,14 +343,13 @@ idview_process_filter_cb(Slapi_Filter *filter, const char *filter_type, struct b
eeac78
 				res = slapi_entry_attr_find(cbdata->overrides[i], IPA_IDVIEWS_ATTR_ANCHORUUID, &anchor);
eeac78
 				if (res == 0) {
eeac78
 					res = slapi_attr_first_value(anchor, &anchor_val);
eeac78
-					slapi_filter_changetype(filter, IPA_IDVIEWS_ATTR_ANCHORUUID);
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
+					anchor_override_found = TRUE;
eeac78
+					slapi_log_error(SLAPI_LOG_FATAL, cbdata->state->plugin_desc->spd_id,
eeac78
+							"Overriding the %s %s with %s=%*s from the override %s\n.",
eeac78
+							bval_usage, attr_name, IPA_IDVIEWS_ATTR_ANCHORUUID,
eeac78
+							(int) bval->bv_len, bval->bv_val,
eeac78
 							slapi_entry_get_dn_const(cbdata->overrides[i]));
eeac78
 					break;
eeac78
 				}
eeac78
@@ -362,7 +358,41 @@ idview_process_filter_cb(Slapi_Filter *filter, const char *filter_type, struct b
eeac78
 		}
eeac78
 	}
eeac78
 
eeac78
-	slapi_value_free(&filter_val);
eeac78
+	slapi_value_free(&attr_val);
eeac78
+
eeac78
+	if (uid_override_found) {
eeac78
+		return 1;
eeac78
+	}
eeac78
+
eeac78
+	if (anchor_override_found) {
eeac78
+		return 2;
eeac78
+	}
eeac78
+
eeac78
+	return 0;
eeac78
+}
eeac78
+
eeac78
+static int
eeac78
+idview_process_filter_cb(Slapi_Filter *filter, const char *filter_type,
eeac78
+			 struct berval *bval, struct backend_search_filter_config *config)
eeac78
+{
eeac78
+	int res;
eeac78
+	struct backend_search_cbdata *cbdata = (struct backend_search_cbdata *) config->callback_data;
eeac78
+
eeac78
+	if (cbdata == NULL || cbdata->idview == NULL) {
eeac78
+		return SLAPI_FILTER_SCAN_CONTINUE;
eeac78
+	}
eeac78
+
eeac78
+	if (filter_type == NULL || config->name == NULL) {
eeac78
+		return SLAPI_FILTER_SCAN_CONTINUE;
eeac78
+	}
eeac78
+
eeac78
+	res = idview_replace_bval_by_override("filter", filter_type, bval, cbdata);
eeac78
+
eeac78
+	if (res == 2) {
eeac78
+		slapi_filter_changetype(filter, IPA_IDVIEWS_ATTR_ANCHORUUID);
eeac78
+	}
eeac78
+
eeac78
+	config->override_found = (res != 0);
eeac78
 
eeac78
 	return SLAPI_FILTER_SCAN_CONTINUE;
eeac78
 
eeac78
diff --git a/src/back-sch.c b/src/back-sch.c
eeac78
index 27ac24f..2388d2f 100644
eeac78
--- a/src/back-sch.c
eeac78
+++ b/src/back-sch.c
eeac78
@@ -1631,7 +1631,6 @@ static void
eeac78
 backend_locate(Slapi_PBlock *pb, struct backend_entry_data **data, const char **group, const char**set)
eeac78
 {
eeac78
 	struct backend_locate_cbdata cbdata;
eeac78
-	char *idview = NULL;
eeac78
 
eeac78
 	slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state);
eeac78
 	if (cbdata.state->plugin_base == NULL) {
eeac78
@@ -1640,22 +1639,64 @@ backend_locate(Slapi_PBlock *pb, struct backend_entry_data **data, const char **
eeac78
 		return;
eeac78
 	}
eeac78
 	slapi_pblock_get(pb, SLAPI_TARGET_DN, &cbdata.target);
eeac78
-#ifdef USE_IPA_IDVIEWS
eeac78
-	idview_replace_target_dn(&cbdata.target, &idview);
eeac78
-#endif
eeac78
+
eeac78
 	cbdata.target_dn = slapi_sdn_new_dn_byval(cbdata.target);
eeac78
 	cbdata.entry_data = NULL;
eeac78
 	cbdata.entry_group = NULL;
eeac78
 	cbdata.entry_set = NULL;
eeac78
 	map_data_foreach_map(cbdata.state, NULL, backend_locate_cb, &cbdata);
eeac78
+#ifdef USE_IPA_IDVIEWS
eeac78
+	/* In case nothing was found but we are operating on the ID override,
eeac78
+	 * rebuild the target's RDN to use original attribute's value */
eeac78
+	if (cbdata.entry_data == NULL) {
eeac78
+		char *idview = NULL;
eeac78
+		char *target, *original_target;
eeac78
+		target = original_target = slapi_ch_strdup(cbdata.target);
eeac78
+		idview_replace_target_dn(&target, &idview);
eeac78
+		if (target != original_target) {
eeac78
+			slapi_ch_free_string(&original_target);
eeac78
+		}
eeac78
+		if (idview != NULL) {
eeac78
+			char *rdnstr;
eeac78
+			char *val;
eeac78
+			struct berval bval;
eeac78
+			int res;
eeac78
+			struct backend_search_cbdata scbdata;
eeac78
+			Slapi_RDN *rdn = slapi_rdn_new_all_dn(target);
eeac78
+			if (rdn != NULL) {
eeac78
+				res = slapi_rdn_get_first(rdn, &rdnstr, &val;;
eeac78
+				if (res == 1) {
eeac78
+					bval.bv_len = strlen(val) + 1;
eeac78
+					bval.bv_val = slapi_ch_strdup(val);
eeac78
+					memset(&scbdata, 0, sizeof(scbdata));
eeac78
+					scbdata.idview = idview;
eeac78
+					scbdata.target = target;
eeac78
+					scbdata.pb = pb;
eeac78
+					scbdata.state = cbdata.state;
eeac78
+					scbdata.target_dn = slapi_sdn_new_dn_byval(target);
eeac78
+					res = idview_replace_bval_by_override("rdn", rdnstr, &bval, &scbdata);
eeac78
+					/* only accept uid overrides */
eeac78
+					if (res == 1) {
eeac78
+						slapi_rdn_remove_index(rdn, 1);
eeac78
+						slapi_rdn_add(rdn, "uid", bval.bv_val);
eeac78
+						slapi_sdn_free(&cbdata.target_dn);
eeac78
+						cbdata.target_dn = slapi_sdn_set_rdn(scbdata.target_dn, rdn);
eeac78
+						map_data_foreach_map(cbdata.state, NULL, backend_locate_cb, &cbdata);
eeac78
+					}
eeac78
+					slapi_ber_bvdone(&bval);
eeac78
+					slapi_rdn_free(&rdn;;
eeac78
+					idview_free_overrides(&scbdata);
eeac78
+				}
eeac78
+			}
eeac78
+		}
eeac78
+		slapi_ch_free_string(&target);
eeac78
+		slapi_ch_free_string(&idview);
eeac78
+	}
eeac78
+#endif
eeac78
 	*data = cbdata.entry_data;
eeac78
 	*group = cbdata.entry_group;
eeac78
 	*set = cbdata.entry_set;
eeac78
 	slapi_sdn_free(&cbdata.target_dn);
eeac78
-	if (idview != NULL) {
eeac78
-		slapi_ch_free_string(&cbdata.target);
eeac78
-	}
eeac78
-	slapi_ch_free_string(&idview);
eeac78
 }
eeac78
 
eeac78
 /* Check if the target DN is part of this group's tree.  If it is, return an
eeac78
diff --git a/src/back-sch.h b/src/back-sch.h
eeac78
index 9f0b201..26e12d1 100644
eeac78
--- a/src/back-sch.h
eeac78
+++ b/src/back-sch.h
eeac78
@@ -131,6 +131,10 @@ void idview_process_overrides(struct backend_search_cbdata *cbdata,
eeac78
 			      Slapi_Entry *entry);
eeac78
 void idview_replace_target_dn(char **target, char **idview);
eeac78
 void idview_replace_filter(struct backend_search_cbdata *cbdata);
eeac78
+/* Takes struct berval value of an attribute attr_name and replaces it with an override
eeac78
+ * Returns 0 if no override was found, 1 for 'uid' replacement, 2 for ipaAnchorUUID replacement */
eeac78
+int  idview_replace_bval_by_override(const char *bval_usage, const char *attr_name,
eeac78
+				     struct berval *bval, struct backend_search_cbdata *cbdata);
eeac78
 #endif
eeac78
 
eeac78
 #endif
eeac78
-- 
eeac78
2.1.0
eeac78