|
|
9c73bd |
From bcdcb8e762c6a8824ff1dd67f7e068ef519b3952 Mon Sep 17 00:00:00 2001
|
|
|
9c73bd |
From: Alexander Bokovoy <abokovoy@redhat.com>
|
|
|
9c73bd |
Date: Mon, 11 Sep 2017 15:33:24 +0300
|
|
|
9c73bd |
Subject: [PATCH 13/17] track changes to ID overrides and evict map cache
|
|
|
9c73bd |
entries
|
|
|
9c73bd |
|
|
|
9c73bd |
Plug into a processing of LDAP add/delete/modify to see if an ID override entry
|
|
|
9c73bd |
was added/deleted/updated. ID overrides aren't directly used to produce
|
|
|
9c73bd |
map cache entries but when AD user or group is resolved, SSSD on IPA
|
|
|
9c73bd |
master amends that information with ID Override from a Default Trust
|
|
|
9c73bd |
View. Since nothing else would remove AD user or group entry from the map cache
|
|
|
9c73bd |
on ID override change, handle their removal here.
|
|
|
9c73bd |
|
|
|
9c73bd |
Check if we have any nssswitch-generated entry in a map cache that
|
|
|
9c73bd |
corresponds to this entry. Such entries would be evicted from the map
|
|
|
9c73bd |
cache to allow their refresh.
|
|
|
9c73bd |
|
|
|
9c73bd |
Allow backends to inspect entries related to a map set
|
|
|
9c73bd |
|
|
|
9c73bd |
Entries may be related to a map set content but not used directly to
|
|
|
9c73bd |
generate it. An example would be ID overrides in FreeIPA. An addition,
|
|
|
9c73bd |
removal or change of an ID override in the Default Trust View should be
|
|
|
9c73bd |
reflected by evicting an entry from the corresponding seti.
|
|
|
9c73bd |
|
|
|
9c73bd |
Let backends to handle exact logic. NIS backend does not support
|
|
|
9c73bd |
exposing AD users so it provides set of dummy callbacks that always
|
|
|
9c73bd |
return FALSE (entry is not related). Schema Compat backend, on other
|
|
|
9c73bd |
hand, does track ID overrides in a Default Trust View in FreeIPA.
|
|
|
9c73bd |
---
|
|
|
9c73bd |
src/back-sch.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
9c73bd |
src/back-shr.c | 55 ++++++++++++++----
|
|
|
9c73bd |
src/backend.h | 20 +++++++
|
|
|
9c73bd |
3 files changed, 239 insertions(+), 12 deletions(-)
|
|
|
9c73bd |
|
|
|
9c73bd |
diff --git a/src/back-sch.c b/src/back-sch.c
|
|
|
9c73bd |
index e15988f..f98b0b4 100644
|
|
|
9c73bd |
--- a/src/back-sch.c
|
|
|
9c73bd |
+++ b/src/back-sch.c
|
|
|
9c73bd |
@@ -33,6 +33,7 @@
|
|
|
9c73bd |
#ifdef HAVE_DIRSRV_SLAPI_PLUGIN_H
|
|
|
9c73bd |
#include <nspr.h>
|
|
|
9c73bd |
#include <plhash.h>
|
|
|
9c73bd |
+#include <plstr.h>
|
|
|
9c73bd |
#include <nss.h>
|
|
|
9c73bd |
#include <dirsrv/slapi-plugin.h>
|
|
|
9c73bd |
#else
|
|
|
9c73bd |
@@ -2099,6 +2100,181 @@ backend_write_cb(Slapi_PBlock *pb, struct plugin_state *state)
|
|
|
9c73bd |
return ret;
|
|
|
9c73bd |
}
|
|
|
9c73bd |
|
|
|
9c73bd |
+#ifdef USE_IPA_IDVIEWS
|
|
|
9c73bd |
+/* Check if ID override applies to an entry in our map cache
|
|
|
9c73bd |
+ * and remove the entry in case it does. */
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+static bool_t
|
|
|
9c73bd |
+backend__get_original_uid_and_ndn(Slapi_Entry *e,
|
|
|
9c73bd |
+ char **original_uid,
|
|
|
9c73bd |
+ const char **original_anchor)
|
|
|
9c73bd |
+{
|
|
|
9c73bd |
+ char **elem = NULL;
|
|
|
9c73bd |
+ char *v = NULL;
|
|
|
9c73bd |
+ char *ndn = NULL;
|
|
|
9c73bd |
+ char *view = NULL;
|
|
|
9c73bd |
+ int n_elem = 0;
|
|
|
9c73bd |
+ int i = 0;
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+ if (e == NULL) {
|
|
|
9c73bd |
+ return FALSE;
|
|
|
9c73bd |
+ }
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+ elem = slapi_entry_attr_get_charray_ext(e, "objectClass", &n_elem);
|
|
|
9c73bd |
+ if (elem == NULL) {
|
|
|
9c73bd |
+ /* weird, objectClass should be existing */
|
|
|
9c73bd |
+ return FALSE;
|
|
|
9c73bd |
+ }
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+ for (i=0; i < n_elem; i++) {
|
|
|
9c73bd |
+ if (strncasecmp(elem[i], "ipaOverrideAnchor", 17) == 0) {
|
|
|
9c73bd |
+ break;
|
|
|
9c73bd |
+ }
|
|
|
9c73bd |
+ }
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+ slapi_ch_array_free(elem);
|
|
|
9c73bd |
+ if (i == n_elem) {
|
|
|
9c73bd |
+ /* This is not an override, bail out */
|
|
|
9c73bd |
+ return FALSE;
|
|
|
9c73bd |
+ }
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+ ndn = slapi_entry_get_ndn(e);
|
|
|
9c73bd |
+ if (ndn == NULL) {
|
|
|
9c73bd |
+ return FALSE;
|
|
|
9c73bd |
+ }
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+ view = PL_strcasestr(ndn, "cn=Default Trust View,");
|
|
|
9c73bd |
+ if (view == NULL || view == ndn) {
|
|
|
9c73bd |
+ return FALSE;
|
|
|
9c73bd |
+ }
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+ /* This is an ID override, we need to search for a referenced ipaOriginalUid or cn in our maps */
|
|
|
9c73bd |
+ v = slapi_entry_attr_get_charptr(e, "ipaOriginalUid");
|
|
|
9c73bd |
+ if (v == NULL) {
|
|
|
9c73bd |
+ v = slapi_entry_attr_get_charptr(e, "cn");
|
|
|
9c73bd |
+ if (v == NULL) {
|
|
|
9c73bd |
+ return FALSE;
|
|
|
9c73bd |
+ }
|
|
|
9c73bd |
+ }
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+ *original_uid = v;
|
|
|
9c73bd |
+ *original_anchor = ndn;
|
|
|
9c73bd |
+ return TRUE;
|
|
|
9c73bd |
+}
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+bool_t
|
|
|
9c73bd |
+backend_entry_evict_if_related(const char *group, const char *set, bool_t flag,
|
|
|
9c73bd |
+ void *shared_set_data,
|
|
|
9c73bd |
+ Slapi_PBlock *pb,
|
|
|
9c73bd |
+ Slapi_Entry *e)
|
|
|
9c73bd |
+{
|
|
|
9c73bd |
+ struct backend_set_data *set_data;
|
|
|
9c73bd |
+ struct plugin_state *state = NULL;
|
|
|
9c73bd |
+ char *id = NULL;
|
|
|
9c73bd |
+ char *original_uid = NULL;
|
|
|
9c73bd |
+ const char *original_anchor = NULL;
|
|
|
9c73bd |
+ const char *rdn_attribute[] = {NULL, "uid=%s,%s,%s", "cn=%s,%s,%s"};
|
|
|
9c73bd |
+ bool_t result = FALSE;
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+ set_data = shared_set_data;
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+ /* We only interested in NSSWITCH-capable maps */
|
|
|
9c73bd |
+ if (set_data->check_nsswitch == SCH_NSSWITCH_NONE) {
|
|
|
9c73bd |
+ return FALSE;
|
|
|
9c73bd |
+ }
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+ /* See if the entry pre modification had original UID */
|
|
|
9c73bd |
+ if (!backend__get_original_uid_and_ndn(e,
|
|
|
9c73bd |
+ &original_uid,
|
|
|
9c73bd |
+ &original_anchor)) {
|
|
|
9c73bd |
+ return FALSE;
|
|
|
9c73bd |
+ }
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+ id = slapi_ch_smprintf(rdn_attribute[set_data->check_nsswitch],
|
|
|
9c73bd |
+ original_uid, set, group);
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+ if (id == NULL) {
|
|
|
9c73bd |
+ slapi_ch_free_string(&original_uid);
|
|
|
9c73bd |
+ return FALSE;
|
|
|
9c73bd |
+ }
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+ slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
|
|
|
9c73bd |
+ result = map_data_check_entry(state, group, set, id);
|
|
|
9c73bd |
+ if (result) {
|
|
|
9c73bd |
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
|
|
|
9c73bd |
+ "evicted entry %s due to changed content of ID override %s\n",
|
|
|
9c73bd |
+ id, original_anchor);
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+ /* An entry corresponding to our target is found, evict it */
|
|
|
9c73bd |
+ map_data_unset_entry(state, group, set, id);
|
|
|
9c73bd |
+ }
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+ slapi_ch_free_string(&id;;
|
|
|
9c73bd |
+ slapi_ch_free_string(&original_uid);
|
|
|
9c73bd |
+ return result;
|
|
|
9c73bd |
+}
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+bool_t
|
|
|
9c73bd |
+backend_entry_is_add_related(const char *group, const char *set, bool_t flag,
|
|
|
9c73bd |
+ void *shared_set_data,
|
|
|
9c73bd |
+ Slapi_PBlock *pb,
|
|
|
9c73bd |
+ Slapi_Entry *e)
|
|
|
9c73bd |
+{
|
|
|
9c73bd |
+ return backend_entry_evict_if_related(group, set, flag, shared_set_data, pb, e);
|
|
|
9c73bd |
+}
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+bool_t
|
|
|
9c73bd |
+backend_entry_is_modify_related(const char *group, const char *set, bool_t flag,
|
|
|
9c73bd |
+ void *shared_set_data,
|
|
|
9c73bd |
+ Slapi_PBlock *pb,
|
|
|
9c73bd |
+ Slapi_Entry *e_pre,
|
|
|
9c73bd |
+ Slapi_Entry *e_post)
|
|
|
9c73bd |
+{
|
|
|
9c73bd |
+ return backend_entry_evict_if_related(group, set, flag, shared_set_data, pb, e_pre);
|
|
|
9c73bd |
+}
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+bool_t
|
|
|
9c73bd |
+backend_entry_is_delete_related(const char *group, const char *set, bool_t flag,
|
|
|
9c73bd |
+ void *shared_set_data,
|
|
|
9c73bd |
+ Slapi_PBlock *pb,
|
|
|
9c73bd |
+ Slapi_Entry *e)
|
|
|
9c73bd |
+{
|
|
|
9c73bd |
+ return backend_entry_evict_if_related(group, set, flag, shared_set_data, pb, e);
|
|
|
9c73bd |
+}
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+#else
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+bool_t
|
|
|
9c73bd |
+backend_entry_is_add_related(const char *group, const char *set, bool_t flag,
|
|
|
9c73bd |
+ void *shared_set_data,
|
|
|
9c73bd |
+ Slapi_PBlock *pb,
|
|
|
9c73bd |
+ Slapi_Entry *e)
|
|
|
9c73bd |
+{
|
|
|
9c73bd |
+ return FALSE;
|
|
|
9c73bd |
+}
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+bool_t
|
|
|
9c73bd |
+backend_entry_is_modify_related(const char *group, const char *set, bool_t flag,
|
|
|
9c73bd |
+ void *shared_set_data,
|
|
|
9c73bd |
+ Slapi_PBlock *pb,
|
|
|
9c73bd |
+ Slapi_Entry *e_pre,
|
|
|
9c73bd |
+ Slapi_Entry *e_post)
|
|
|
9c73bd |
+{
|
|
|
9c73bd |
+ return FALSE;
|
|
|
9c73bd |
+}
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+bool_t
|
|
|
9c73bd |
+backend_entry_is_delete_related(const char *group, const char *set, bool_t flag,
|
|
|
9c73bd |
+ void *shared_set_data,
|
|
|
9c73bd |
+ Slapi_PBlock *pb,
|
|
|
9c73bd |
+ Slapi_Entry *e)
|
|
|
9c73bd |
+{
|
|
|
9c73bd |
+ return FALSE;
|
|
|
9c73bd |
+}
|
|
|
9c73bd |
+
|
|
|
9c73bd |
+#endif
|
|
|
9c73bd |
+
|
|
|
9c73bd |
static int
|
|
|
9c73bd |
backend_pre_write_cb(Slapi_PBlock *pb)
|
|
|
9c73bd |
{
|
|
|
9c73bd |
diff --git a/src/back-shr.c b/src/back-shr.c
|
|
|
9c73bd |
index 7842e05..a7ea92f 100644
|
|
|
9c73bd |
--- a/src/back-shr.c
|
|
|
9c73bd |
+++ b/src/back-shr.c
|
|
|
9c73bd |
@@ -1856,11 +1856,21 @@ backend_shr_add_entry_cb(const char *group, const char *set, bool_t secure,
|
|
|
9c73bd |
|
|
|
9c73bd |
/* If the entry doesn't match the set, skip it. */
|
|
|
9c73bd |
if (!backend_shr_entry_matches_set(set_data, cbdata->pb, cbdata->e)) {
|
|
|
9c73bd |
- slapi_log_error(SLAPI_LOG_PLUGIN,
|
|
|
9c73bd |
- cbdata->state->plugin_desc->spd_id,
|
|
|
9c73bd |
- "entry \"%s\" does not belong in "
|
|
|
9c73bd |
- "\"%s\"/\"%s\"\n",
|
|
|
9c73bd |
- cbdata->ndn, group, set);
|
|
|
9c73bd |
+ /* Give backend a chance to perform other operations on the add op.
|
|
|
9c73bd |
+ * For example, ID override addition in FreeIPA need to be noted to
|
|
|
9c73bd |
+ * evict AD user/group entries from a map cache while ID overrides
|
|
|
9c73bd |
+ * themselves aren't present in any map.
|
|
|
9c73bd |
+ * Note that we could do this as a part of backend_shr_entry_matches_set()
|
|
|
9c73bd |
+ * but it is better to isolate this operation in a separate call. */
|
|
|
9c73bd |
+ if (!backend_entry_is_add_related(group, set, secure,
|
|
|
9c73bd |
+ set_data, cbdata->pb,
|
|
|
9c73bd |
+ cbdata->e)) {
|
|
|
9c73bd |
+ slapi_log_error(SLAPI_LOG_PLUGIN,
|
|
|
9c73bd |
+ cbdata->state->plugin_desc->spd_id,
|
|
|
9c73bd |
+ "entry \"%s\" does not belong in "
|
|
|
9c73bd |
+ "\"%s\"/\"%s\"\n",
|
|
|
9c73bd |
+ cbdata->ndn, group, set);
|
|
|
9c73bd |
+ }
|
|
|
9c73bd |
return TRUE;
|
|
|
9c73bd |
}
|
|
|
9c73bd |
|
|
|
9c73bd |
@@ -2010,13 +2020,24 @@ backend_shr_modify_entry_cb(const char *group, const char *set, bool_t flag,
|
|
|
9c73bd |
cbdata->e_post) &&
|
|
|
9c73bd |
!backend_shr_entry_matches_set(set_data, cbdata->pb,
|
|
|
9c73bd |
cbdata->e_pre)) {
|
|
|
9c73bd |
- slapi_log_error(SLAPI_LOG_PLUGIN,
|
|
|
9c73bd |
- cbdata->state->plugin_desc->spd_id,
|
|
|
9c73bd |
- "\"%s\" not in \"%s\"/\"%s\", "
|
|
|
9c73bd |
- "before or after modify\n",
|
|
|
9c73bd |
- cbdata->ndn,
|
|
|
9c73bd |
- set_data->group,
|
|
|
9c73bd |
- set_data->set);
|
|
|
9c73bd |
+ /* Give backend a chance to perform other operations on the modify op.
|
|
|
9c73bd |
+ * For example, ID override updates in FreeIPA need to be noted to
|
|
|
9c73bd |
+ * evict AD user/group entries from a map cache while ID overrides
|
|
|
9c73bd |
+ * themselves aren't present in any map.
|
|
|
9c73bd |
+ * Note that we could do this as a part of backend_shr_entry_matches_set()
|
|
|
9c73bd |
+ * but it is better to isolate this operation in a separate call. */
|
|
|
9c73bd |
+ if (!backend_entry_is_modify_related(group, set, flag,
|
|
|
9c73bd |
+ set_data, cbdata->pb,
|
|
|
9c73bd |
+ cbdata->e_pre,
|
|
|
9c73bd |
+ cbdata->e_post)) {
|
|
|
9c73bd |
+ slapi_log_error(SLAPI_LOG_PLUGIN,
|
|
|
9c73bd |
+ cbdata->state->plugin_desc->spd_id,
|
|
|
9c73bd |
+ "\"%s\" not in \"%s\"/\"%s\", "
|
|
|
9c73bd |
+ "before or after modify\n",
|
|
|
9c73bd |
+ cbdata->ndn,
|
|
|
9c73bd |
+ set_data->group,
|
|
|
9c73bd |
+ set_data->set);
|
|
|
9c73bd |
+ }
|
|
|
9c73bd |
return TRUE;
|
|
|
9c73bd |
}
|
|
|
9c73bd |
if (set_data->skip_uninteresting_updates &&
|
|
|
9c73bd |
@@ -2631,6 +2652,16 @@ backend_shr_delete_entry_cb(const char *group, const char *set, bool_t flag,
|
|
|
9c73bd |
group, set, set_data->group, set_data->set,
|
|
|
9c73bd |
cbdata->ndn);
|
|
|
9c73bd |
map_data_unset_entry(cbdata->state, group, set, cbdata->ndn);
|
|
|
9c73bd |
+ } else {
|
|
|
9c73bd |
+ /* Give backend a chance to perform other operations on the delete op.
|
|
|
9c73bd |
+ * For example, ID override removal in FreeIPA need to be noted to
|
|
|
9c73bd |
+ * evict AD user/group entries from a map cache while ID overrides
|
|
|
9c73bd |
+ * themselves aren't present in any map.
|
|
|
9c73bd |
+ * Note that we could do this as a part of backend_shr_entry_matches_set()
|
|
|
9c73bd |
+ * but it is better to isolate this operation in a separate call. */
|
|
|
9c73bd |
+ (void) backend_entry_is_delete_related(group, set, flag,
|
|
|
9c73bd |
+ set_data, cbdata->pb,
|
|
|
9c73bd |
+ cbdata->e);
|
|
|
9c73bd |
}
|
|
|
9c73bd |
return TRUE;
|
|
|
9c73bd |
}
|
|
|
9c73bd |
diff --git a/src/backend.h b/src/backend.h
|
|
|
9c73bd |
index 4608d2d..f0a5bbb 100644
|
|
|
9c73bd |
--- a/src/backend.h
|
|
|
9c73bd |
+++ b/src/backend.h
|
|
|
9c73bd |
@@ -115,4 +115,24 @@ void backend_update_params(Slapi_PBlock *pb, struct plugin_state *state);
|
|
|
9c73bd |
bool_t backend_shr_is_caller(struct plugin_state *state,
|
|
|
9c73bd |
struct slapi_pblock *pb);
|
|
|
9c73bd |
|
|
|
9c73bd |
+/* Check if an operation is performed on an entry that is related to
|
|
|
9c73bd |
+ * any entry in the set. This allows to catch changes of the entries that
|
|
|
9c73bd |
+ * aren't directly included in the map set but should affect the set. */
|
|
|
9c73bd |
+bool_t
|
|
|
9c73bd |
+backend_entry_is_modify_related(const char *group, const char *set, bool_t flag,
|
|
|
9c73bd |
+ void *shared_set_data,
|
|
|
9c73bd |
+ Slapi_PBlock *pb,
|
|
|
9c73bd |
+ Slapi_Entry *e_pre,
|
|
|
9c73bd |
+ Slapi_Entry *e_post);
|
|
|
9c73bd |
+bool_t
|
|
|
9c73bd |
+backend_entry_is_add_related(const char *group, const char *set, bool_t flag,
|
|
|
9c73bd |
+ void *shared_set_data,
|
|
|
9c73bd |
+ Slapi_PBlock *pb,
|
|
|
9c73bd |
+ Slapi_Entry *e);
|
|
|
9c73bd |
+bool_t
|
|
|
9c73bd |
+backend_entry_is_delete_related(const char *group, const char *set, bool_t flag,
|
|
|
9c73bd |
+ void *shared_set_data,
|
|
|
9c73bd |
+ Slapi_PBlock *pb,
|
|
|
9c73bd |
+ Slapi_Entry *e);
|
|
|
9c73bd |
+
|
|
|
9c73bd |
#endif
|
|
|
9c73bd |
--
|
|
|
9c73bd |
2.13.6
|
|
|
9c73bd |
|