ldap/servers/plugins/memberof/memberof.c | 233 ++++++++++++------------
ldap/servers/plugins/memberof/memberof.h | 3
ldap/servers/plugins/memberof/memberof_config.c | 33 +++
3 files changed, 160 insertions(+), 109 deletions(-)
New commits:
commit 118e483ca9240b32f0e36dd74dc9f88669220ee7
Author: root <root(a)localhost.localdomain>
Date: Tue Apr 24 17:40:35 2012 -0400
Ticket #326 - MemberOf plugin should work on all backends
Bug Description: By design the memberOf plugin would only look at the backend from
which the group belonged to. This makes it impossible to maintain
users and groups from different suffixes.
Fix Description: First I added a new config setting in the plugin to turn this on
and off. Then we just look at all the backends when searching.
https://fedorahosted.org/389/ticket/326
Reviewed by: ?
diff --git a/ldap/servers/plugins/memberof/memberof.c
b/ldap/servers/plugins/memberof/memberof.c
index 655054c..229b962 100644
--- a/ldap/servers/plugins/memberof/memberof.c
+++ b/ldap/servers/plugins/memberof/memberof.c
@@ -67,10 +67,8 @@
#endif
#include "slapi-plugin.h"
-
#include "string.h"
#include "nspr.h"
-
#include "memberof.h"
static Slapi_PluginDesc pdesc = { "memberof", VENDOR,
@@ -507,94 +505,101 @@ int memberof_del_dn_type_callback(Slapi_Entry *e, void
*callback_data)
}
/*
- * Does a callback search of "type=dn" under the db suffix that "dn"
is in.
- * If "dn" is a user, you'd want "type" to be "member".
If "dn" is a group,
- * you could want type to be either "member" or "memberOf" depending
on the
- * case.
+ * Does a callback search of "type=dn" under the db suffix that "dn"
is in,
+ * unless all_backends is set, then we look at all the backends. If "dn"
+ * is a user, you'd want "type" to be "member". If
"dn" is a group, you
+ * could want type to be either "member" or "memberOf" depending on
the case.
*/
int memberof_call_foreach_dn(Slapi_PBlock *pb, char *dn,
char **types, plugin_search_entry_callback callback, void *callback_data)
{
- int rc = 0;
Slapi_PBlock *search_pb = slapi_pblock_new();
- Slapi_Backend *be = 0;
- Slapi_DN *sdn = 0;
- Slapi_DN *base_sdn = 0;
- char *filter_str = 0;
- int num_types = 0;
+ Slapi_DN *base_sdn = NULL;
+ Slapi_Backend *be = NULL;
+ Slapi_DN *sdn = NULL;
+ char *filter_str = NULL;
+ char *cookie = NULL;
+ int all_backends = memberof_config_get_all_backends();
int types_name_len = 0;
- int dn_len = 0;
+ int num_types = 0;
+ int dn_len = strlen(dn);
+ int rc = 0;
int i = 0;
- /* get the base dn for the backend we are in
- (we don't support having members and groups in
- different backends - issues with offline / read only backends)
- */
- sdn = slapi_sdn_new_normdn_byref(dn);
- be = slapi_be_select(sdn);
- if(be)
+ /* Count the number of types. */
+ for (num_types = 0; types && types[num_types]; num_types++)
{
- base_sdn = (Slapi_DN*)slapi_be_getsuffix(be,0);
+ /* Add up the total length of all attribute names.
+ * We need to know this for building the filter. */
+ types_name_len += strlen(types[num_types]);
}
- if(base_sdn)
+ /* Build the search filter. */
+ if (num_types > 1)
{
- /* Find the length of the dn */
- dn_len = strlen(dn);
+ int bytes_out = 0;
+ int filter_str_len = types_name_len + (num_types * (3 + dn_len)) + 4;
- /* Count the number of types. */
- for (num_types = 0; types && types[num_types]; num_types++)
- {
- /* Add up the total length of all attribute names.
- * We need to know this for building the filter. */
- types_name_len += strlen(types[num_types]);
- }
+ /* Allocate enough space for the filter */
+ filter_str = slapi_ch_malloc(filter_str_len);
- /* Build the search filter. */
- if (num_types > 1)
+ /* Add beginning of filter. */
+ bytes_out = snprintf(filter_str, filter_str_len - bytes_out, "(|");
+
+ /* Add filter section for each type. */
+ for (i = 0; types[i]; i++)
{
- int bytes_out = 0;
- int filter_str_len = types_name_len + (num_types * (3 + dn_len)) + 4;
+ bytes_out += snprintf(filter_str + bytes_out, filter_str_len - bytes_out,
+ "(%s=%s)", types[i], dn);
+ }
- /* Allocate enough space for the filter */
- filter_str = slapi_ch_malloc(filter_str_len);
+ /* Add end of filter. */
+ snprintf(filter_str + bytes_out, filter_str_len - bytes_out, ")");
+ }
+ else if (num_types == 1)
+ {
+ filter_str = slapi_ch_smprintf("(%s=%s)", types[0], dn);
+ }
- /* Add beginning of filter. */
- bytes_out = snprintf(filter_str, filter_str_len - bytes_out, "(|");
+ if(filter_str == NULL){
+ return rc;
+ }
- /* Add filter section for each type. */
- for (i = 0; types[i]; i++)
- {
- bytes_out += snprintf(filter_str + bytes_out, filter_str_len - bytes_out,
- "(%s=%s)", types[i], dn);
+ be = slapi_get_first_backend(&cookie);
+ while(be){
+ if(!all_backends){
+ sdn = slapi_sdn_new_normdn_byref(dn);
+ be = slapi_be_select(sdn);
+ if(be == NULL){
+ break;
}
-
- /* Add end of filter. */
- snprintf(filter_str + bytes_out, filter_str_len - bytes_out, ")");
}
- else if (num_types == 1)
- {
- filter_str = slapi_ch_smprintf("(%s=%s)", types[0], dn);
+ if((base_sdn = (Slapi_DN *)slapi_be_getsuffix(be,0)) == NULL){
+ if(!all_backends){
+ break;
+ } else {
+ /* its ok, goto the next backend */
+ be = slapi_get_next_backend(cookie);
+ continue;
+ }
}
- }
- if(filter_str)
- {
slapi_search_internal_set_pb(search_pb, slapi_sdn_get_dn(base_sdn),
- LDAP_SCOPE_SUBTREE, filter_str, 0, 0,
- 0, 0,
- memberof_get_plugin_id(),
- 0);
-
- slapi_search_internal_callback_pb(search_pb,
- callback_data,
- 0, callback,
- 0);
+ LDAP_SCOPE_SUBTREE, filter_str, 0, 0, 0, 0, memberof_get_plugin_id(), 0);
+ slapi_search_internal_callback_pb(search_pb, callback_data, 0, callback, 0);
+
+ if(!all_backends){
+ break;
+ }
+ slapi_pblock_init(search_pb);
+ be = slapi_get_next_backend(cookie);
}
slapi_sdn_free(&sdn);
slapi_pblock_destroy(search_pb);
+ slapi_ch_free((void **)&cookie);
slapi_ch_free_string(&filter_str);
+
return rc;
}
@@ -1123,60 +1128,72 @@ int memberof_modop_one_replace_r(Slapi_PBlock *pb, MemberOfConfig
*config,
Slapi_DN *base_sdn = 0;
Slapi_Backend *be = 0;
char *filter_str = 0;
+ char *cookie = NULL;
int n_entries = 0;
-
- /* We can't tell for sure if the op_to entry is a
- * user or a group since the entry doesn't exist
- * anymore. We can safely ignore the missing entry
- * if no other entries have a memberOf attribute that
- * points to the missing entry. */
- be = slapi_be_select(op_to_sdn);
- if(be)
- {
- base_sdn = (Slapi_DN*)slapi_be_getsuffix(be,0);
- }
-
- if(base_sdn)
- {
- filter_str = slapi_ch_smprintf("(%s=%s)",
- config->memberof_attr, op_to);
- }
-
- if(filter_str)
- {
- slapi_search_internal_set_pb(search_pb, slapi_sdn_get_dn(base_sdn),
- LDAP_SCOPE_SUBTREE, filter_str, 0, 0, 0, 0,
- memberof_get_plugin_id(), 0);
-
- if (slapi_search_internal_pb(search_pb))
+ int all_backends = config->allBackends;
+
+ filter_str = slapi_ch_smprintf("(%s=%s)", config->memberof_attr, op_to);
+ be = slapi_get_first_backend(&cookie);
+ while(be){
+ /*
+ * We can't tell for sure if the op_to entry is a
+ * user or a group since the entry doesn't exist
+ * anymore. We can safely ignore the missing entry
+ * if no other entries have a memberOf attribute that
+ * points to the missing entry.
+ */
+ if(!all_backends){
+ be = slapi_be_select(op_to_sdn);
+ if(be == NULL){
+ break;
+ }
+ }
+ if((base_sdn = (Slapi_DN*)slapi_be_getsuffix(be,0)) == NULL){
+ if(!all_backends){
+ break;
+ } else {
+ be = slapi_get_next_backend (cookie);
+ continue;
+ }
+ }
+ if(filter_str)
{
- /* get result and log an error */
- int res = 0;
- slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
- slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_modop_one_replace_r: error searching for members: "
- "%d", res);
- } else {
- slapi_pblock_get(search_pb, SLAPI_NENTRIES, &n_entries);
-
- if(n_entries > 0)
+ slapi_search_internal_set_pb(search_pb, slapi_sdn_get_dn(base_sdn),
+ LDAP_SCOPE_SUBTREE, filter_str, 0, 0, 0, 0,
+ memberof_get_plugin_id(), 0);
+
+ if (slapi_search_internal_pb(search_pb))
{
- /* We want to fixup the membership for the
- * entries that referred to the missing group
- * entry. This will fix the references to
- * the missing group as well as the group
- * represented by op_this. */
- memberof_test_membership(pb, config, op_to);
+ /* get result and log an error */
+ int res = 0;
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
+ slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "memberof_modop_one_replace_r: error searching for members: "
+ "%d", res);
+ } else {
+ slapi_pblock_get(search_pb, SLAPI_NENTRIES, &n_entries);
+ if(n_entries > 0)
+ {
+ /* We want to fixup the membership for the
+ * entries that referred to the missing group
+ * entry. This will fix the references to
+ * the missing group as well as the group
+ * represented by op_this. */
+ memberof_test_membership(pb, config, op_to);
+ }
}
+ slapi_free_search_results_internal(search_pb);
}
-
- slapi_free_search_results_internal(search_pb);
- slapi_ch_free_string(&filter_str);
+ slapi_pblock_init(search_pb);
+ if(!all_backends){
+ break;
+ }
+ be = slapi_get_next_backend (cookie);
}
-
slapi_pblock_destroy(search_pb);
+ slapi_ch_free_string(&filter_str);
+ slapi_ch_free((void **)&cookie);
}
-
goto bail;
}
diff --git a/ldap/servers/plugins/memberof/memberof.h
b/ldap/servers/plugins/memberof/memberof.h
index fdf1253..36901e3 100644
--- a/ldap/servers/plugins/memberof/memberof.h
+++ b/ldap/servers/plugins/memberof/memberof.h
@@ -65,6 +65,7 @@
#define MEMBEROF_INT_PREOP_DESC "memberOf internal postop plugin"
#define MEMBEROF_GROUP_ATTR "memberOfGroupAttr"
#define MEMBEROF_ATTR "memberOfAttr"
+#define MEMBEROF_BACKEND_ATTR "memberOfAllBackends"
#define DN_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.12"
#define NAME_OPT_UID_SYNTAX_OID "1.3.6.1.4.1.1466.115.121.1.34"
@@ -75,6 +76,7 @@
typedef struct memberofconfig {
char **groupattrs;
char *memberof_attr;
+ int allBackends;
Slapi_Filter *group_filter;
Slapi_Attr **group_slapiattrs;
} MemberOfConfig;
@@ -92,6 +94,7 @@ void memberof_unlock();
void memberof_rlock_config();
void memberof_wlock_config();
void memberof_unlock_config();
+int memberof_config_get_all_backends();
int g_get_shutdown(); /* declared in proto-slap.h */
diff --git a/ldap/servers/plugins/memberof/memberof_config.c
b/ldap/servers/plugins/memberof/memberof_config.c
index a30d448..b4d557a 100644
--- a/ldap/servers/plugins/memberof/memberof_config.c
+++ b/ldap/servers/plugins/memberof/memberof_config.c
@@ -270,11 +270,13 @@ memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore,
Slapi_Entry*
char *filter_str = NULL;
int num_groupattrs = 0;
int groupattr_name_len = 0;
+ char *allBackends = NULL;
*returncode = LDAP_SUCCESS;
groupattrs = slapi_entry_attr_get_charray(e, MEMBEROF_GROUP_ATTR);
- memberof_attr = slapi_entry_attr_get_charptr(e, MEMBEROF_ATTR);
+ memberof_attr = slapi_entry_attr_get_charptr(e, MEMBEROF_ATTR);
+ allBackends = slapi_entry_attr_get_charptr(e, MEMBEROF_BACKEND_ATTR);
/* We want to be sure we don't change the config in the middle of
* a memberOf operation, so we obtain an exclusive lock here */
@@ -373,11 +375,23 @@ memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore,
Slapi_Entry*
memberof_attr = NULL; /* config now owns memory */
}
+ if (allBackends)
+ {
+ if(strcasecmp(allBackends,"on")==0){
+ theConfig.allBackends = 1;
+ } else {
+ theConfig.allBackends = 0;
+ }
+ } else {
+ theConfig.allBackends = 0;
+ }
+
/* release the lock */
memberof_unlock_config();
slapi_ch_array_free(groupattrs);
slapi_ch_free_string(&memberof_attr);
+ slapi_ch_free_string(&allBackends);
if (*returncode != LDAP_SUCCESS)
{
@@ -449,6 +463,11 @@ memberof_copy_config(MemberOfConfig *dest, MemberOfConfig *src)
slapi_ch_free_string(&dest->memberof_attr);
dest->memberof_attr = slapi_ch_strdup(src->memberof_attr);
}
+
+ if(src->allBackends)
+ {
+ dest->allBackends = src->allBackends;
+ }
}
}
@@ -526,3 +545,15 @@ memberof_unlock_config()
{
slapi_rwlock_unlock(memberof_config_lock);
}
+
+int
+memberof_config_get_all_backends()
+{
+ int all_backends;
+
+ slapi_rwlock_rdlock(memberof_config_lock);
+ all_backends = theConfig.allBackends;
+ slapi_rwlock_unlock(memberof_config_lock);
+
+ return all_backends;
+}