ldap/servers/plugins/memberof/memberof.c | 191 +++++++++++++++++++++---
ldap/servers/plugins/memberof/memberof.h | 9 +
ldap/servers/plugins/memberof/memberof_config.c | 167 +++++++++++++++++++-
ldap/servers/slapd/slapi-plugin.h | 3
4 files changed, 337 insertions(+), 33 deletions(-)
New commits:
commit f81ac81a475bcc92f54bffd2c6d9cb45dbf9a324
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Fri Nov 22 15:48:59 2013 -0500
Ticket 47525 - Allow memberOf to use an alternate config area
Description: Added support for nsslapd-pluginConfigArea. If this attribute is set
the config settings in the plugin entry are ignored, and only the
shared config entry will apply.
Registered a preop plugin function to perform config validation on
the shared config entry. Then in the modify postop function we
apply the changes.
https://fedorahosted.org/389/ticket/47525
Reviewed by: richm(Thanks!)
diff --git a/ldap/servers/plugins/memberof/memberof.c
b/ldap/servers/plugins/memberof/memberof.c
index 443b9ae..f8fb10f 100644
--- a/ldap/servers/plugins/memberof/memberof.c
+++ b/ldap/servers/plugins/memberof/memberof.c
@@ -75,10 +75,13 @@ static Slapi_PluginDesc pdesc = { "memberof", VENDOR,
DS_PACKAGE_VERSION, "memberof plugin" };
static void* _PluginID = NULL;
+static Slapi_DN* _ConfigAreaDN = NULL;
+static Slapi_DN* _pluginDN = NULL;
static PRMonitor *memberof_operation_lock = 0;
MemberOfConfig *qsortConfig = 0;
static int g_plugin_started = 0;
static int usetxn = 0;
+static int premodfn = 0;
typedef struct _memberofstringll
{
@@ -99,6 +102,7 @@ typedef struct _memberof_get_groups_data
/* exported functions */
int memberof_postop_init(Slapi_PBlock *pb );
static int memberof_internal_postop_init(Slapi_PBlock *pb);
+static int memberof_preop_init(Slapi_PBlock *pb);
/* plugin callbacks */
static int memberof_postop_del(Slapi_PBlock *pb );
@@ -140,7 +144,6 @@ static int memberof_moddn_attr_list(Slapi_PBlock *pb, MemberOfConfig
*config,
static int memberof_replace_list(Slapi_PBlock *pb, MemberOfConfig *config,
Slapi_DN *group_sdn);
static void memberof_set_plugin_id(void * plugin_id);
-static void *memberof_get_plugin_id();
static int memberof_compare(MemberOfConfig *config, const void *a, const void *b);
static int memberof_qsort_compare(const void *a, const void *b);
static void memberof_load_array(Slapi_Value **array, Slapi_Attr *attr);
@@ -193,6 +196,7 @@ memberof_postop_init(Slapi_PBlock *pb)
char *memberof_plugin_identity = 0;
Slapi_Entry *plugin_entry = NULL;
char *plugin_type = NULL;
+ char *preop_plugin_type = NULL;
int delfn = SLAPI_PLUGIN_POST_DELETE_FN;
int mdnfn = SLAPI_PLUGIN_POST_MODRDN_FN;
int modfn = SLAPI_PLUGIN_POST_MODIFY_FN;
@@ -214,6 +218,18 @@ memberof_postop_init(Slapi_PBlock *pb)
}
slapi_ch_free_string(&plugin_type);
+ if(usetxn){
+ preop_plugin_type = "betxnpreoperation";
+ premodfn = SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN;
+ } else {
+ preop_plugin_type = "preoperation";
+ premodfn = SLAPI_PLUGIN_PRE_MODIFY_FN;
+ }
+
+ if(plugin_entry){
+ memberof_set_plugin_area(slapi_entry_get_sdn(plugin_entry));
+ }
+
/*
* Get plugin identity and stored it for later use
* Used for internal operations
@@ -223,21 +239,17 @@ memberof_postop_init(Slapi_PBlock *pb)
PR_ASSERT (memberof_plugin_identity);
memberof_set_plugin_id(memberof_plugin_identity);
- ret = ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
- SLAPI_PLUGIN_VERSION_01 ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
- (void *)&pdesc ) != 0 ||
- slapi_pblock_set( pb, delfn, (void *) memberof_postop_del ) != 0 ||
- slapi_pblock_set( pb, mdnfn, (void *) memberof_postop_modrdn ) != 0 ||
- slapi_pblock_set( pb, modfn, (void *) memberof_postop_modify ) != 0 ||
- slapi_pblock_set( pb, addfn, (void *) memberof_postop_add ) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
- (void *) memberof_postop_start ) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
- (void *) memberof_postop_close ) != 0 );
+ ret = ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&pdesc ) != 0 ||
+ slapi_pblock_set( pb, delfn, (void *) memberof_postop_del ) != 0 ||
+ slapi_pblock_set( pb, mdnfn, (void *) memberof_postop_modrdn ) != 0 ||
+ slapi_pblock_set( pb, modfn, (void *) memberof_postop_modify ) != 0 ||
+ slapi_pblock_set( pb, addfn, (void *) memberof_postop_add ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN, (void *) memberof_postop_start ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN, (void *) memberof_postop_close ) != 0 );
if (!ret && !usetxn &&
- slapi_register_plugin("internalpostoperation", /* op type */
+ slapi_register_plugin("internalpostoperation", /* op type */
1, /* Enabled */
"memberof_postop_init", /* this function desc */
memberof_internal_postop_init, /* init func */
@@ -255,13 +267,53 @@ memberof_postop_init(Slapi_PBlock *pb)
"memberof_postop_init failed\n" );
ret = -1;
}
+ /*
+ * Setup the preop plugin for shared config updates
+ */
+ if (!ret && !usetxn &&
+ slapi_register_plugin(preop_plugin_type, /* op type */
+ 1, /* Enabled */
+ "memberof_preop_init", /* this function desc */
+ memberof_preop_init, /* init func */
+ MEMBEROF_PREOP_DESC, /* plugin desc */
+ NULL, /* ? */
+ memberof_plugin_identity /* access control */))
+ {
+ slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "memberof_preop_init failed\n" );
+ ret = -1;
+ }
+ else if (ret)
+ {
+ slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "memberof_preop_init failed\n");
+ ret = -1;
+ }
slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
"<-- memberof_postop_init\n" );
+
return ret;
}
static int
+memberof_preop_init(Slapi_PBlock *pb)
+{
+ int status = 0;
+
+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *) &pdesc) != 0 ||
+ slapi_pblock_set(pb, premodfn, (void *)memberof_shared_config_validate) != 0)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "memberof_internal_postop_init: failed to register plugin\n");
+ status = -1;
+ }
+
+ return status;
+}
+
+static int
memberof_internal_postop_init(Slapi_PBlock *pb)
{
int status = 0;
@@ -294,8 +346,12 @@ memberof_internal_postop_init(Slapi_PBlock *pb)
*/
int memberof_postop_start(Slapi_PBlock *pb)
{
- int rc = 0;
+ Slapi_PBlock *search_pb = NULL;
+ Slapi_Entry **entries = NULL;
Slapi_Entry *config_e = NULL; /* entry containing plugin config */
+ char *config_area = NULL;
+ int result = 0;
+ int rc = 0;
slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
"--> memberof_postop_start\n" );
@@ -311,18 +367,53 @@ int memberof_postop_start(Slapi_PBlock *pb)
rc = -1;
goto bail;
}
-
- if ( slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &config_e ) != 0 ) {
- slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
- "missing config entry\n" );
- rc = -1;
- goto bail;
+ /* Set the alternate config area if one is defined. */
+ slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_AREA, &config_area);
+ if (config_area)
+ {
+ search_pb = slapi_pblock_new();
+ slapi_search_internal_set_pb(search_pb, config_area, LDAP_SCOPE_BASE,
"objectclass=*",
+ NULL, 0, NULL, NULL, memberof_get_plugin_id(), 0);
+ slapi_search_internal_pb(search_pb);
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
+ if (LDAP_SUCCESS != result) {
+ if (result == LDAP_NO_SUCH_OBJECT) {
+ /* log an error and use the plugin entry for the config */
+ slapi_log_error(SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "memberof_postop_start: Config entry \"%s\" does "
+ "not exist.\n", config_area);
+ rc = -1;
+ goto bail;
+ }
+ } else {
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ if(entries && entries[0]){
+ config_e = entries[0];
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "memberof_postop_start: Config entry \"%s\" was "
+ "not located.\n", config_area);
+ rc = -1;
+ goto bail;
+ }
+ }
+ } else {
+ /* The plugin entry itself contains the config */
+ if ( slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &config_e ) != 0 ) {
+ slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "missing config entry\n" );
+ rc = -1;
+ goto bail;
+ }
}
+ memberof_set_plugin_area(slapi_entry_get_sdn(config_e));
+ memberof_set_config_area(slapi_entry_get_sdn(config_e));
if (( rc = memberof_config( config_e )) != LDAP_SUCCESS ) {
slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
"configuration failed (%s)\n", ldap_err2string( rc ));
- return( -1 );
+ rc = -1;
+ goto bail;
}
rc = slapi_task_register_handler("memberof task", memberof_task_add);
@@ -344,6 +435,9 @@ int memberof_postop_start(Slapi_PBlock *pb)
*/
bail:
+ slapi_free_search_results_internal(search_pb);
+ slapi_pblock_destroy(search_pb);
+
slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
"<-- memberof_postop_start\n" );
@@ -368,6 +462,32 @@ int memberof_postop_close(Slapi_PBlock *pb)
return 0;
}
+void
+memberof_set_config_area(Slapi_DN *dn)
+{
+ slapi_sdn_free(&_ConfigAreaDN);
+ _ConfigAreaDN = slapi_sdn_dup(dn);
+}
+
+Slapi_DN *
+memberof_get_config_area()
+{
+ return _ConfigAreaDN;
+}
+
+void
+memberof_set_plugin_area(Slapi_DN *sdn)
+{
+ slapi_sdn_free(&_pluginDN);
+ _pluginDN = slapi_sdn_dup(sdn);
+}
+
+Slapi_DN *
+memberof_get_plugin_area()
+{
+ return _pluginDN;
+}
+
/*
* memberof_postop_del()
*
@@ -821,6 +941,32 @@ int memberof_postop_modify(Slapi_PBlock *pb)
return SLAPI_PLUGIN_SUCCESS;
}
+ /* check if we are updating the shared config entry */
+ slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
+ if (slapi_sdn_issuffix(sdn, memberof_get_config_area()) &&
+ slapi_sdn_compare(sdn, memberof_get_config_area()) == 0)
+ {
+ Slapi_Entry *entry = NULL;
+ char returntext[SLAPI_DSE_RETURNTEXT_SIZE];
+ int result = 0;
+
+ slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &entry);
+ if(entry){
+ if( SLAPI_DSE_CALLBACK_ERROR == memberof_apply_config (pb, NULL, entry, &result,
returntext, NULL)){
+ slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM, "%s",
returntext);
+ ret = SLAPI_PLUGIN_FAILURE;
+ goto done;
+ }
+ } else {
+ /* this should not happen since this was validated in preop */
+ ret = SLAPI_PLUGIN_FAILURE;
+ goto done;
+ }
+ /* we're done, no need to do the other processing */
+ goto done;
+ }
+
+
if(memberof_oktodo(pb) && (sdn = memberof_getsdn(pb)))
{
int config_copied = 0;
@@ -932,6 +1078,7 @@ int memberof_postop_modify(Slapi_PBlock *pb)
slapi_mods_free(&smods);
}
+done:
slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
"<-- memberof_postop_modify\n" );
return ret;
diff --git a/ldap/servers/plugins/memberof/memberof.h
b/ldap/servers/plugins/memberof/memberof.h
index 65398aa..d308022 100644
--- a/ldap/servers/plugins/memberof/memberof.h
+++ b/ldap/servers/plugins/memberof/memberof.h
@@ -63,6 +63,7 @@
*/
#define MEMBEROF_PLUGIN_SUBSYSTEM "memberof-plugin" /* used for logging */
#define MEMBEROF_INT_PREOP_DESC "memberOf internal postop plugin"
+#define MEMBEROF_PREOP_DESC "memberof preop plugin"
#define MEMBEROF_GROUP_ATTR "memberOfGroupAttr"
#define MEMBEROF_ATTR "memberOfAttr"
#define MEMBEROF_BACKEND_ATTR "memberOfAllBackends"
@@ -95,5 +96,13 @@ void memberof_rlock_config();
void memberof_wlock_config();
void memberof_unlock_config();
int memberof_config_get_all_backends();
+void memberof_set_config_area(Slapi_DN *sdn);
+Slapi_DN * memberof_get_config_area();
+void memberof_set_plugin_area(Slapi_DN *sdn);
+Slapi_DN * memberof_get_plugin_area();
+int memberof_shared_config_validate(Slapi_PBlock *pb);
+int memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
+ int *returncode, char *returntext, void *arg);
+void *memberof_get_plugin_id();
#endif /* _MEMBEROF_H_ */
diff --git a/ldap/servers/plugins/memberof/memberof_config.c
b/ldap/servers/plugins/memberof/memberof_config.c
index 3fd63a9..0e74928 100644
--- a/ldap/servers/plugins/memberof/memberof_config.c
+++ b/ldap/servers/plugins/memberof/memberof_config.c
@@ -65,8 +65,6 @@
*/
static int memberof_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore,
Slapi_Entry* e,
int *returncode, char *returntext, void *arg);
-static int memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore,
Slapi_Entry* e,
- int *returncode, char *returntext, void *arg);
static int memberof_search (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
int *returncode, char *returntext, void *arg)
{
@@ -117,14 +115,17 @@ memberof_config(Slapi_Entry *config_e)
/* initialize fields */
if (SLAPI_DSE_CALLBACK_OK == memberof_validate_config(NULL, NULL, config_e,
- &returncode, returntext, NULL)) {
- memberof_apply_config(NULL, NULL, config_e,
- &returncode, returntext, NULL);
+ &returncode, returntext, NULL))
+ {
+ memberof_apply_config(NULL, NULL, config_e, &returncode, returntext, NULL);
}
- /* config DSE must be initialized before we get here */
+ /*
+ * config DSE must be initialized before we get here we only need the dse callbacks
+ * for the plugin entry, but not the shared config entry.
+ */
if (returncode == LDAP_SUCCESS) {
- const char *config_dn = slapi_entry_get_dn_const(config_e);
+ const char *config_dn = slapi_sdn_get_dn(memberof_get_plugin_area());
slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP,
config_dn, LDAP_SCOPE_BASE, MEMBEROF_CONFIG_FILTER,
memberof_validate_config,NULL);
@@ -164,7 +165,9 @@ memberof_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore,
Slapi_Entr
{
Slapi_Attr *memberof_attr = NULL;
Slapi_Attr *group_attr = NULL;
+ Slapi_DN *config_sdn = NULL;
char *syntaxoid = NULL;
+ char *config_dn = NULL;
int not_dn_syntax = 0;
*returncode = LDAP_UNWILLING_TO_PERFORM; /* be pessimistic */
@@ -230,20 +233,54 @@ memberof_validate_config (Slapi_PBlock *pb, Slapi_Entry*
entryBefore, Slapi_Entr
"an attribute defined to use the Distinguished "
"Name syntax. (illegal value: %s)",
slapi_value_get_string(value), MEMBEROF_ATTR);
+ goto done;
}
else
{
*returncode = LDAP_SUCCESS;
}
}
- }
- else
- {
+ } else {
PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
"The %s and %s configuration attributes must be provided",
MEMBEROF_GROUP_ATTR, MEMBEROF_ATTR);
+ goto done;
}
+ if ((config_dn = slapi_entry_attr_get_charptr(e, SLAPI_PLUGIN_SHARED_CONFIG_AREA))){
+ /* Now check the shared config attribute, validate it now */
+
+ Slapi_Entry *e = NULL;
+ int rc = 0;
+
+ rc = slapi_dn_syntax_check(pb, config_dn, 1);
+ if (rc) { /* syntax check failed */
+ slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
"memberof_validate_config: "
+ "%s does not contain a valid DN (%s)\n",
+ SLAPI_PLUGIN_SHARED_CONFIG_AREA, config_dn);
+ *returncode = LDAP_INVALID_DN_SYNTAX;
+ goto done;
+ }
+ config_sdn = slapi_sdn_new_dn_byval(config_dn);
+
+ slapi_search_internal_get_entry(config_sdn, NULL, &e, memberof_get_plugin_id());
+ if(e){
+ slapi_entry_free(e);
+ *returncode = LDAP_SUCCESS;
+ } else {
+ /* config area does not exist! */
+ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+ "The %s configuration attribute points to an entry that "
+ "can not be found. (%s)",
+ SLAPI_PLUGIN_SHARED_CONFIG_AREA, config_dn);
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ }
+ }
+
+done:
+ slapi_sdn_free(&config_sdn);
+ slapi_ch_free_string(&config_dn);
+
if (*returncode != LDAP_SUCCESS)
{
return SLAPI_DSE_CALLBACK_ERROR;
@@ -261,19 +298,65 @@ memberof_validate_config (Slapi_PBlock *pb, Slapi_Entry*
entryBefore, Slapi_Entr
* Apply the pending changes in the e entry to our config struct.
* memberof_validate_config() must have already been called.
*/
-static int
+int
memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
int *returncode, char *returntext, void *arg)
{
+ Slapi_Entry *config_entry = NULL;
+ Slapi_DN *config_sdn = NULL;
char **groupattrs = NULL;
char *memberof_attr = NULL;
char *filter_str = NULL;
int num_groupattrs = 0;
int groupattr_name_len = 0;
char *allBackends = NULL;
+ char *sharedcfg = NULL;
*returncode = LDAP_SUCCESS;
+ /*
+ * Apply the config settings from the shared config entry
+ */
+ sharedcfg = slapi_entry_attr_get_charptr(e, SLAPI_PLUGIN_SHARED_CONFIG_AREA);
+ if(sharedcfg){
+ int rc = 0;
+
+ rc = slapi_dn_syntax_check(pb, sharedcfg, 1);
+ if (rc) { /* syntax check failed */
+ slapi_log_error( SLAPI_LOG_FATAL,
MEMBEROF_PLUGIN_SUBSYSTEM,"memberof_apply_config: "
+ "%s does not contain a valid DN (%s)\n",
+ SLAPI_PLUGIN_SHARED_CONFIG_AREA, sharedcfg);
+ *returncode = LDAP_INVALID_DN_SYNTAX;
+ goto done;
+ }
+ if((config_sdn = slapi_sdn_new_dn_byval(sharedcfg))){
+ slapi_search_internal_get_entry(config_sdn, NULL, &config_entry,
memberof_get_plugin_id());
+ if(config_entry){
+ char errtext[SLAPI_DSE_RETURNTEXT_SIZE];
+ int err = 0;
+ /*
+ * If we got here, we are updating the shared config area, so we need to
+ * validate and apply the settings from that config area.
+ */
+ if ( SLAPI_DSE_CALLBACK_ERROR == memberof_validate_config (pb, NULL, config_entry,
&err, errtext,0))
+ {
+ slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "%s", errtext);
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+
+ }
+ e = config_entry;
+ } else {
+ /* this should of been checked in preop validation */
+ slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
"memberof_apply_config: "
+ "Failed to locate shared config entry (%s)\n",sharedcfg);
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ goto done;
+ }
+ }
+ }
+
groupattrs = slapi_entry_attr_get_charray(e, MEMBEROF_GROUP_ATTR);
memberof_attr = slapi_entry_attr_get_charptr(e, MEMBEROF_ATTR);
allBackends = slapi_entry_attr_get_charptr(e, MEMBEROF_BACKEND_ATTR);
@@ -389,6 +472,13 @@ memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore,
Slapi_Entry*
/* release the lock */
memberof_unlock_config();
+done:
+ slapi_ch_free_string(&sharedcfg);
+ slapi_sdn_free(&config_sdn);
+ if(config_entry){
+ /* we switched the entry pointer to the shared config entry - which needs to be freed
*/
+ slapi_entry_free(e);
+ }
slapi_ch_array_free(groupattrs);
slapi_ch_free_string(&memberof_attr);
slapi_ch_free_string(&allBackends);
@@ -557,3 +647,58 @@ memberof_config_get_all_backends()
return all_backends;
}
+
+/*
+ * Check if we are modifying the config, or changing the shared config entry
+ */
+int
+memberof_shared_config_validate(Slapi_PBlock *pb)
+{
+ Slapi_Entry *e = 0;
+ Slapi_DN *sdn = 0;
+ Slapi_Mods *smods = 0;
+ LDAPMod **mods = NULL;
+ char returntext[SLAPI_DSE_RETURNTEXT_SIZE];
+ int ret = SLAPI_PLUGIN_SUCCESS;
+
+ slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
+
+ if (slapi_sdn_issuffix(sdn, memberof_get_config_area()) &&
+ slapi_sdn_compare(sdn, memberof_get_config_area()) == 0)
+ {
+ /*
+ * This is the shared config entry. Apply the mods and set/validate
+ * the config
+ */
+ int result = 0;
+
+ slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &e);
+ if(e){
+ slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
+ smods = slapi_mods_new();
+ slapi_mods_init_byref(smods, mods);
+
+ /* Apply the mods to create the resulting entry. */
+ if (mods && (slapi_entry_apply_mods(e, mods) != LDAP_SUCCESS)) {
+ /* we don't care about this, the update is invalid and will be caught later */
+ goto bail;
+ }
+
+ if ( SLAPI_DSE_CALLBACK_ERROR == memberof_validate_config (pb, NULL, e, &ret,
returntext,0)) {
+ slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "%s", returntext);
+ ret = LDAP_UNWILLING_TO_PERFORM;
+ }
+ } else {
+ slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
"memberof_shared_config_validate: "
+ "Unable to locate shared config entry (%s) error %d\n",
+ slapi_sdn_get_dn(memberof_get_config_area()), result);
+ ret = LDAP_UNWILLING_TO_PERFORM;
+ }
+ }
+
+bail:
+ slapi_entry_free(e);
+
+ return ret;
+}
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 497ce8f..86f2d0c 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -479,6 +479,9 @@ NSPR_API(PRUint32) PR_fprintf(struct PRFileDesc* fd, const char *fmt,
...)
#define SLAPI_ATTR_ENTRYUSN "entryusn"
#define SLAPI_ATTR_ENTRYDN "entrydn"
+/* plugin shared config area */
+#define SLAPI_PLUGIN_SHARED_CONFIG_AREA "nsslapd-pluginConfigArea"
+
/* opaque structures */
/**