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;
+}
ldap/servers/slapd/back-ldbm/idl_new.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
New commits:
commit 5d45dd8de06aaee3e0a52c85fa5b3e18febd7a27
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Fri Apr 20 20:15:21 2012 -0600
Ticket #347 - IPA dirsvr seg-fault during system longevity test
https://fedorahosted.org/389/ticket/347
Resolves: Ticket 347
Bug Description: IPA dirsvr seg-fault during system longevity test
Reviewed by: nhosoi, mreynolds (Thanks!)
Branch: master
Fix Description: Somehow the DB_MULTIPLE_NEXT pointer is being set to
an invalid value (-5). This causes the next iteration to return memory
that points to before the stack buffer, causing a seg fault. Valid
values for the pointer are > -1. The value -1 is used as the list terminator
value. The code that constructs the buffer is in the libdb function
__bam_bulk in bt_cursor.c. The fix is to check for a value < -1,
assume the page or value has been deleted out from under us, and do
a dbc->get to get the next buffer full, if any. The code also needs to
check for duplicate IDs being returned. In the failure case described
above, it is possible that the last ID returned in the multiple buffer is
the first ID in the next buffer. In that case, we want to skip the ID that
was already added to the IDL.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/slapd/back-ldbm/idl_new.c b/ldap/servers/slapd/back-ldbm/idl_new.c
index d62511c..9cd3daf 100644
--- a/ldap/servers/slapd/back-ldbm/idl_new.c
+++ b/ldap/servers/slapd/back-ldbm/idl_new.c
@@ -242,6 +242,7 @@ IDList * idl_new_fetch(
/* Iterate over the duplicates, amassing them into an IDL */
#ifdef DB_USE_BULK_FETCH
for (;;) {
+ ID lastid = 0;
DB_MULTIPLE_INIT(ptr, &data);
@@ -250,6 +251,13 @@ IDList * idl_new_fetch(
if (dataret.data == NULL) break;
if (ptr == NULL) break;
+ if (*(int32_t *)ptr < -1) {
+ LDAPDebug1Arg(LDAP_DEBUG_TRACE, "DB_MULTIPLE buffer is corrupt; "
+ "next offset [%d] is less than zero\n",
+ *(int32_t *)ptr);
+ /* retry the read */
+ break;
+ }
if (dataret.size != sizeof(ID)) {
LDAPDebug(LDAP_DEBUG_ANY, "database index is corrupt; "
"key %s has a data item with the wrong size (%d)\n",
@@ -257,7 +265,14 @@ IDList * idl_new_fetch(
goto error;
}
memcpy(&id, dataret.data, sizeof(ID));
-
+ if (id == lastid) { /* dup */
+ LDAPDebug1Arg(LDAP_DEBUG_TRACE, "Detedted duplicate id "
+ "%d due to DB_MULTIPLE error - skipping\n",
+ id);
+ continue; /* get next one */
+ }
+ /* note the last id read to check for dups */
+ lastid = id;
/* we got another ID, add it to our IDL */
idl_rc = idl_append_extend(&idl, id);
if (idl_rc) {