|
|
5b4a29 |
From 053fb02f73220be53d1fb93511684a6f7aa3226f Mon Sep 17 00:00:00 2001
|
|
|
5b4a29 |
From: Thierry Bordaz <tbordaz@redhat.com>
|
|
|
5b4a29 |
Date: Thu, 10 Nov 2022 16:54:40 +0100
|
|
|
5b4a29 |
Subject: [PATCH 3/5] Issue 5440 - memberof is slow on update/fixup if there
|
|
|
5b4a29 |
are several 'groupattr' (#5455)
|
|
|
5b4a29 |
|
|
|
5b4a29 |
Bug description:
|
|
|
5b4a29 |
When there are several groupattr (attr_1, attr_2,..) in memberof config
|
|
|
5b4a29 |
To fixup entry 'e1', memberof does an internal search
|
|
|
5b4a29 |
"(|(attr_1=e1)(attr_2=e1)...(attr_n=e1))"
|
|
|
5b4a29 |
This is not valid regarding membership relation and in
|
|
|
5b4a29 |
addition it prevents the server to bypass the filter evaluation.
|
|
|
5b4a29 |
|
|
|
5b4a29 |
Fix description:
|
|
|
5b4a29 |
To fixup an entry iterate several internal searches
|
|
|
5b4a29 |
"(attr_1=e1)" , then "(attr_2=e1)", then "(attr_n=e1)"
|
|
|
5b4a29 |
|
|
|
5b4a29 |
relates: #5440
|
|
|
5b4a29 |
|
|
|
5b4a29 |
Reviewed by: Pierre Rogier, Mark Reynolds, Simon Pichugin (Thanks)
|
|
|
5b4a29 |
---
|
|
|
5b4a29 |
ldap/servers/plugins/memberof/memberof.c | 155 +++++++++++------------
|
|
|
5b4a29 |
1 file changed, 73 insertions(+), 82 deletions(-)
|
|
|
5b4a29 |
|
|
|
5b4a29 |
diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c
|
|
|
5b4a29 |
index b54eb3977..541b27250 100644
|
|
|
5b4a29 |
--- a/ldap/servers/plugins/memberof/memberof.c
|
|
|
5b4a29 |
+++ b/ldap/servers/plugins/memberof/memberof.c
|
|
|
5b4a29 |
@@ -704,8 +704,6 @@ memberof_call_foreach_dn(Slapi_PBlock *pb __attribute__((unused)), Slapi_DN *sdn
|
|
|
5b4a29 |
char *filter_str = NULL;
|
|
|
5b4a29 |
char *cookie = NULL;
|
|
|
5b4a29 |
int all_backends = config->allBackends;
|
|
|
5b4a29 |
- int types_name_len = 0;
|
|
|
5b4a29 |
- int num_types = 0;
|
|
|
5b4a29 |
int dn_len = slapi_sdn_get_ndn_len(sdn);
|
|
|
5b4a29 |
int free_it = 0;
|
|
|
5b4a29 |
int rc = 0;
|
|
|
5b4a29 |
@@ -744,107 +742,100 @@ memberof_call_foreach_dn(Slapi_PBlock *pb __attribute__((unused)), Slapi_DN *sdn
|
|
|
5b4a29 |
#if MEMBEROF_CACHE_DEBUG
|
|
|
5b4a29 |
slapi_log_err(SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_call_foreach_dn: Ancestors of %s not cached\n", ndn);
|
|
|
5b4a29 |
#endif
|
|
|
5b4a29 |
- /* Count the number of types. */
|
|
|
5b4a29 |
- for (num_types = 0; types && types[num_types]; num_types++) {
|
|
|
5b4a29 |
- /* Add up the total length of all attribute names.
|
|
|
5b4a29 |
- * We need to know this for building the filter. */
|
|
|
5b4a29 |
- types_name_len += strlen(types[num_types]);
|
|
|
5b4a29 |
- }
|
|
|
5b4a29 |
|
|
|
5b4a29 |
/* Escape the dn, and build the search filter. */
|
|
|
5b4a29 |
escaped_filter_val = slapi_escape_filter_value((char *)slapi_sdn_get_dn(sdn), dn_len);
|
|
|
5b4a29 |
if (escaped_filter_val) {
|
|
|
5b4a29 |
- dn_len = strlen(escaped_filter_val);
|
|
|
5b4a29 |
free_it = 1;
|
|
|
5b4a29 |
} else {
|
|
|
5b4a29 |
escaped_filter_val = (char *)slapi_sdn_get_dn(sdn);
|
|
|
5b4a29 |
}
|
|
|
5b4a29 |
|
|
|
5b4a29 |
- if (num_types > 1) {
|
|
|
5b4a29 |
- int bytes_out = 0;
|
|
|
5b4a29 |
- int filter_str_len = types_name_len + (num_types * (3 + dn_len)) + 4;
|
|
|
5b4a29 |
-
|
|
|
5b4a29 |
- /* Allocate enough space for the filter */
|
|
|
5b4a29 |
- filter_str = slapi_ch_malloc(filter_str_len);
|
|
|
5b4a29 |
-
|
|
|
5b4a29 |
- /* Add beginning of filter. */
|
|
|
5b4a29 |
- bytes_out = snprintf(filter_str, filter_str_len - bytes_out, "(|");
|
|
|
5b4a29 |
-
|
|
|
5b4a29 |
- /* Add filter section for each type. */
|
|
|
5b4a29 |
- for (i = 0; types[i]; i++) {
|
|
|
5b4a29 |
- bytes_out += snprintf(filter_str + bytes_out, filter_str_len - bytes_out,
|
|
|
5b4a29 |
- "(%s=%s)", types[i], escaped_filter_val);
|
|
|
5b4a29 |
- }
|
|
|
5b4a29 |
-
|
|
|
5b4a29 |
- /* Add end of filter. */
|
|
|
5b4a29 |
- snprintf(filter_str + bytes_out, filter_str_len - bytes_out, ")");
|
|
|
5b4a29 |
- } else if (num_types == 1) {
|
|
|
5b4a29 |
- filter_str = slapi_ch_smprintf("(%s=%s)", types[0], escaped_filter_val);
|
|
|
5b4a29 |
- }
|
|
|
5b4a29 |
-
|
|
|
5b4a29 |
- if (free_it)
|
|
|
5b4a29 |
- slapi_ch_free_string(&escaped_filter_val);
|
|
|
5b4a29 |
+ for (i = 0; types[i]; i++) {
|
|
|
5b4a29 |
+ /* Triggers one internal search per membership attribute.
|
|
|
5b4a29 |
+ * Assuming the attribute is indexed (eq), the search will
|
|
|
5b4a29 |
+ * bypass the evaluation of the filter (nsslapd-search-bypass-filter-test)
|
|
|
5b4a29 |
+ * against the candidates. This is important to bypass the filter
|
|
|
5b4a29 |
+ * because on large valueset (static group) it is very expensive
|
|
|
5b4a29 |
+ */
|
|
|
5b4a29 |
+ filter_str = slapi_ch_smprintf("(%s=%s)", types[i], escaped_filter_val);
|
|
|
5b4a29 |
|
|
|
5b4a29 |
- if (filter_str == NULL) {
|
|
|
5b4a29 |
- return rc;
|
|
|
5b4a29 |
- }
|
|
|
5b4a29 |
+ be = slapi_get_first_backend(&cookie);
|
|
|
5b4a29 |
+ while (be) {
|
|
|
5b4a29 |
+ PRBool do_suffix_search = PR_TRUE;
|
|
|
5b4a29 |
|
|
|
5b4a29 |
- search_pb = slapi_pblock_new();
|
|
|
5b4a29 |
- be = slapi_get_first_backend(&cookie);
|
|
|
5b4a29 |
- while (be) {
|
|
|
5b4a29 |
- Slapi_DN *scope_sdn = NULL;
|
|
|
5b4a29 |
+ if (!all_backends) {
|
|
|
5b4a29 |
+ be = slapi_be_select(sdn);
|
|
|
5b4a29 |
+ if (be == NULL) {
|
|
|
5b4a29 |
+ break;
|
|
|
5b4a29 |
+ }
|
|
|
5b4a29 |
+ }
|
|
|
5b4a29 |
+ if ((base_sdn = (Slapi_DN *) slapi_be_getsuffix(be, 0)) == NULL) {
|
|
|
5b4a29 |
+ if (!all_backends) {
|
|
|
5b4a29 |
+ break;
|
|
|
5b4a29 |
+ } else {
|
|
|
5b4a29 |
+ /* its ok, goto the next backend */
|
|
|
5b4a29 |
+ be = slapi_get_next_backend(cookie);
|
|
|
5b4a29 |
+ continue;
|
|
|
5b4a29 |
+ }
|
|
|
5b4a29 |
+ }
|
|
|
5b4a29 |
|
|
|
5b4a29 |
- if (!all_backends) {
|
|
|
5b4a29 |
- be = slapi_be_select(sdn);
|
|
|
5b4a29 |
- if (be == NULL) {
|
|
|
5b4a29 |
- break;
|
|
|
5b4a29 |
+ search_pb = slapi_pblock_new();
|
|
|
5b4a29 |
+ if (config->entryScopes || config->entryScopeExcludeSubtrees) {
|
|
|
5b4a29 |
+ if (memberof_entry_in_scope(config, base_sdn)) {
|
|
|
5b4a29 |
+ /* do nothing, entry scope is spanning
|
|
|
5b4a29 |
+ * multiple suffixes, start at suffix */
|
|
|
5b4a29 |
+ } else if (config->entryScopes) {
|
|
|
5b4a29 |
+ for (size_t i = 0; config->entryScopes[i]; i++) {
|
|
|
5b4a29 |
+ if (slapi_sdn_issuffix(config->entryScopes[i], base_sdn)) {
|
|
|
5b4a29 |
+ /* Search each include scope */
|
|
|
5b4a29 |
+ slapi_search_internal_set_pb(search_pb, slapi_sdn_get_dn(config->entryScopes[i]),
|
|
|
5b4a29 |
+ LDAP_SCOPE_SUBTREE, filter_str, 0, 0, 0, 0,
|
|
|
5b4a29 |
+ memberof_get_plugin_id(), 0);
|
|
|
5b4a29 |
+ slapi_search_internal_callback_pb(search_pb, callback_data, 0, callback, 0);
|
|
|
5b4a29 |
+ /* We already did the search for this backend, don't
|
|
|
5b4a29 |
+ * do it again when we fall through */
|
|
|
5b4a29 |
+ do_suffix_search = PR_FALSE;
|
|
|
5b4a29 |
+ }
|
|
|
5b4a29 |
+ }
|
|
|
5b4a29 |
+ } else if (!all_backends) {
|
|
|
5b4a29 |
+ slapi_pblock_destroy(search_pb);
|
|
|
5b4a29 |
+ break;
|
|
|
5b4a29 |
+ } else {
|
|
|
5b4a29 |
+ /* its ok, goto the next backend */
|
|
|
5b4a29 |
+ be = slapi_get_next_backend(cookie);
|
|
|
5b4a29 |
+ slapi_pblock_destroy(search_pb);
|
|
|
5b4a29 |
+ continue;
|
|
|
5b4a29 |
+ }
|
|
|
5b4a29 |
}
|
|
|
5b4a29 |
- }
|
|
|
5b4a29 |
- if ((base_sdn = (Slapi_DN *)slapi_be_getsuffix(be, 0)) == NULL) {
|
|
|
5b4a29 |
- if (!all_backends) {
|
|
|
5b4a29 |
- break;
|
|
|
5b4a29 |
- } else {
|
|
|
5b4a29 |
- /* its ok, goto the next backend */
|
|
|
5b4a29 |
- be = slapi_get_next_backend(cookie);
|
|
|
5b4a29 |
- continue;
|
|
|
5b4a29 |
+
|
|
|
5b4a29 |
+ if (do_suffix_search) {
|
|
|
5b4a29 |
+ slapi_search_internal_set_pb(search_pb, slapi_sdn_get_dn(base_sdn),
|
|
|
5b4a29 |
+ LDAP_SCOPE_SUBTREE, filter_str, 0, 0, 0, 0,
|
|
|
5b4a29 |
+ memberof_get_plugin_id(), 0);
|
|
|
5b4a29 |
+ slapi_search_internal_callback_pb(search_pb, callback_data, 0, callback, 0);
|
|
|
5b4a29 |
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
|
|
|
5b4a29 |
+ if (rc != LDAP_SUCCESS) {
|
|
|
5b4a29 |
+ slapi_pblock_destroy(search_pb);
|
|
|
5b4a29 |
+ break;
|
|
|
5b4a29 |
+ }
|
|
|
5b4a29 |
}
|
|
|
5b4a29 |
- }
|
|
|
5b4a29 |
|
|
|
5b4a29 |
- if (config->entryScopes || config->entryScopeExcludeSubtrees) {
|
|
|
5b4a29 |
- if (memberof_entry_in_scope(config, base_sdn)) {
|
|
|
5b4a29 |
- /* do nothing, entry scope is spanning
|
|
|
5b4a29 |
- * multiple suffixes, start at suffix */
|
|
|
5b4a29 |
- } else if ((scope_sdn = memberof_scope_is_child_of_dn(config, base_sdn))) {
|
|
|
5b4a29 |
- /* scope is below suffix, set search base */
|
|
|
5b4a29 |
- base_sdn = scope_sdn;
|
|
|
5b4a29 |
- } else if (!all_backends) {
|
|
|
5b4a29 |
+ if (!all_backends) {
|
|
|
5b4a29 |
+ slapi_pblock_destroy(search_pb);
|
|
|
5b4a29 |
break;
|
|
|
5b4a29 |
- } else {
|
|
|
5b4a29 |
- /* its ok, goto the next backend */
|
|
|
5b4a29 |
- be = slapi_get_next_backend(cookie);
|
|
|
5b4a29 |
- continue;
|
|
|
5b4a29 |
}
|
|
|
5b4a29 |
- }
|
|
|
5b4a29 |
-
|
|
|
5b4a29 |
- slapi_search_internal_set_pb(search_pb, slapi_sdn_get_dn(base_sdn),
|
|
|
5b4a29 |
- LDAP_SCOPE_SUBTREE, filter_str, 0, 0, 0, 0, memberof_get_plugin_id(), 0);
|
|
|
5b4a29 |
- slapi_search_internal_callback_pb(search_pb, callback_data, 0, callback, 0);
|
|
|
5b4a29 |
- slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
|
|
|
5b4a29 |
- if (rc != LDAP_SUCCESS) {
|
|
|
5b4a29 |
- break;
|
|
|
5b4a29 |
- }
|
|
|
5b4a29 |
|
|
|
5b4a29 |
- if (!all_backends) {
|
|
|
5b4a29 |
- break;
|
|
|
5b4a29 |
+ be = slapi_get_next_backend(cookie);
|
|
|
5b4a29 |
+ slapi_pblock_destroy(search_pb);
|
|
|
5b4a29 |
}
|
|
|
5b4a29 |
- slapi_pblock_init(search_pb);
|
|
|
5b4a29 |
- be = slapi_get_next_backend(cookie);
|
|
|
5b4a29 |
+ slapi_ch_free((void **)&cookie);
|
|
|
5b4a29 |
+ slapi_ch_free_string(&filter_str);
|
|
|
5b4a29 |
}
|
|
|
5b4a29 |
|
|
|
5b4a29 |
- slapi_pblock_destroy(search_pb);
|
|
|
5b4a29 |
- slapi_ch_free((void **)&cookie);
|
|
|
5b4a29 |
- slapi_ch_free_string(&filter_str);
|
|
|
5b4a29 |
-
|
|
|
5b4a29 |
+ if (free_it) {
|
|
|
5b4a29 |
+ slapi_ch_free_string(&escaped_filter_val);
|
|
|
5b4a29 |
+ }
|
|
|
5b4a29 |
return rc;
|
|
|
5b4a29 |
}
|
|
|
5b4a29 |
|
|
|
5b4a29 |
--
|
|
|
5b4a29 |
2.39.1
|
|
|
5b4a29 |
|