5 commits - admserv/cgi-ds admserv/cgi-src40 lib/libadmin
by Nathan Kinder
admserv/cgi-ds/ds_snmpctrl.c | 2 +-
admserv/cgi-src40/security.c | 4 ++--
admserv/cgi-src40/ugdsconfig.c | 38 ++++++++++++++++++++++----------------
admserv/cgi-src40/viewdata.c | 2 +-
lib/libadmin/httpcon.c | 2 +-
5 files changed, 27 insertions(+), 21 deletions(-)
New commits:
commit 0a28e3d0e6d574d025020e0f8c1f822cebaefed4
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Wed Apr 27 09:11:04 2011 -0700
Bug 699907 - (cov#10833) Use of uninitialized vars in SNMP code
We should initialize the sin struct to be empty to prevent the
uninitialized contents from being used when bind() is called.
diff --git a/admserv/cgi-ds/ds_snmpctrl.c b/admserv/cgi-ds/ds_snmpctrl.c
index 11df251..757d60a 100644
--- a/admserv/cgi-ds/ds_snmpctrl.c
+++ b/admserv/cgi-ds/ds_snmpctrl.c
@@ -204,7 +204,7 @@ smux_master_is_running()
{
struct servent *pse;
struct protoent *ppe;
- struct sockaddr_in sin;
+ struct sockaddr_in sin = {0};
int s;
sin.sin_family = AF_INET;
commit 43104bf6d73bb6a26753a594f4ff8a59ad1c13ca
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Wed Apr 27 09:00:52 2011 -0700
Bug 699907 - (cov#10836) Use of uninitialized var in http conn code
The make_http_request() function is designed to work with hostnames
only. If is possible that we use the uninitialized err variable if
an IP address is passed in as the server command. We should
initialize err to prevent this.
diff --git a/lib/libadmin/httpcon.c b/lib/libadmin/httpcon.c
index b8f78ee..4bc5abe 100644
--- a/lib/libadmin/httpcon.c
+++ b/lib/libadmin/httpcon.c
@@ -316,7 +316,7 @@ make_http_request(char *protocol, char *server, unsigned int port, char *request
PRHostEnt *hstruct;
PRHostEnt hent;
char buf[PR_NETDB_BUF_SIZE];
- PRStatus err;
+ PRStatus err = PR_FAILURE;
const char *configdir = util_get_conf_dir();
const char *secdir = util_get_security_dir();
commit 0bb1c192ad71d4a9dd19f83232a825076c3f2f35
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Wed Apr 27 08:19:18 2011 -0700
Bug 699907 - (cov#10840) Use of uninitialized buffer in security cgi
There is a chance that we call system(cmd) when we have not set anything
in the cmd buffer. We should not call system(cmd) if we have not filled
in the cmd buffer.
diff --git a/admserv/cgi-src40/security.c b/admserv/cgi-src40/security.c
index 2941eb3..32933bb 100644
--- a/admserv/cgi-src40/security.c
+++ b/admserv/cgi-src40/security.c
@@ -1861,7 +1861,7 @@ static void moduleOperation(char* op) {
const char *binary = "modutil"; /* PATH and LD_LIBRARY_PATH must already be set correctly */
const char *install_dir = LIBDIR;
char *filename, *filetype, *dllname;
- char cmd[BIG_LINE];
+ char cmd[BIG_LINE] = "";
char msg[BIG_LINE];
dllname = get_cgi_var("dllname", NULL, NULL);
@@ -1926,7 +1926,7 @@ static void moduleOperation(char* op) {
rpt_err(INCORRECT_USAGE, msg, NULL, NULL);
}
- if(system(cmd) != 0) {
+ if(*cmd && (system(cmd) != 0)) {
if (!PORT_Strcmp(op, "add")) {
PR_snprintf(msg, sizeof(msg), getResourceString(DBT_MODUTIL_FAILURE), filename);
} else if (!PORT_Strcmp(op, "remove")) {
commit 5293ab9b6b35633182183ff2506ced7bbb641fa4
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Tue Apr 26 15:07:16 2011 -0700
Bug 699907 - (cov#10843) Use of uninitialized variable in logging code
The first time that logMsg is called, logEnabled and enableVerified will
both be 0. This will cause us to fill in the logfile buffer with the file
name and then check for the existence of the logfile. If the logfile does
not exist, we leave enable_verified set and log_enable unset. This will
make future calls to logMsg() just return at line 82.
If we were able to access the file fine for reading the first time logMsg()
is called at line 90, we will then go into the if condition at line 100
to set logfp. We are guaranteed that logfile is filled in at this point.
Further calls to logMsg() will have logfp set, so we no longer need logfile
to be filled in.
The problem here is that the call to fopen() at line 101 might fail, leaving
logfp NULL and log_enabled set to 1. The next time logMsg() is called, we
would call fopen again at line 101, but logfile would not be filled in.
To fix this, we should not set log_enabled to 1 unless we have successfully
opened the log file for writing. I also moved the code around so we only
attempt to call fopen on the file if we have filled the filename buffer in.
diff --git a/admserv/cgi-src40/ugdsconfig.c b/admserv/cgi-src40/ugdsconfig.c
index 4a20903..9be5332 100644
--- a/admserv/cgi-src40/ugdsconfig.c
+++ b/admserv/cgi-src40/ugdsconfig.c
@@ -74,7 +74,7 @@ static char *nonull_value(char *str);
/*
* Logging function
*/
-static FILE * logfp;
+static FILE * logfp = NULL;
static int log_enabled = 0, enable_verified=0;
static void logMsg(char *format, ...) {
char logfile[512];
@@ -83,22 +83,28 @@ static void logMsg(char *format, ...) {
/* Automatically enable logging if <cgi-name>.dbg file exists in the logs directory */
if (!log_enabled && !enable_verified) {
- const char *logdir = util_get_log_dir();
+ const char *logdir = util_get_log_dir();
enable_verified = 1;
- if (util_is_dir_ok(logdir)) {
- PR_snprintf(logfile, sizeof(logfile), "%s/ugdsconfig.dbg", logdir);
- logfp = fopen(logfile, "r");
- if (logfp == NULL) {
- return;
- }
- log_enabled = 1;
- fclose(logfp);
- logfp=NULL;
- }
- }
-
- if (logfp==NULL) {
- logfp = fopen(logfile, "w");
+ if (util_is_dir_ok(logdir)) {
+ PR_snprintf(logfile, sizeof(logfile), "%s/ugdsconfig.dbg", logdir);
+
+ /* Attempt to optn the log for reading
+ * to check if it exists. */
+ logfp = fopen(logfile, "r");
+ if (logfp == NULL) {
+ return;
+ }
+ fclose(logfp);
+
+ /* Attempt to open the file for writing. */
+ logfp = fopen(logfile, "w");
+
+ /* If we opened the log for writing, go
+ * ahead and enable logging. */
+ if (logfp != NULL) {
+ log_enabled = 1;
+ }
+ }
}
if (logfp != NULL) {
commit 68b330854301c503c08878311c1e682a3fe11e1e
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Tue Apr 26 14:55:40 2011 -0700
Bug 699907 - (cov#10844) Uninitialized time struct
We have an uninitialized "struct tm" that ends up getting passed
to strftime(). We should initialize the struct contents.
diff --git a/admserv/cgi-src40/viewdata.c b/admserv/cgi-src40/viewdata.c
index 05a6c1d..25b66c9 100644
--- a/admserv/cgi-src40/viewdata.c
+++ b/admserv/cgi-src40/viewdata.c
@@ -291,7 +291,7 @@ void output_data(LDAP *server, char *sie) {
if((vals = util_ldap_get_values(server, entry, "installationtimestamp"))) {
- struct tm tm;
+ struct tm tm = {0};
char buf[BIG_LINE];
int rc;
13 years
3 commits - admserv/cgi-src40 mod_admserv/mod_admserv.c
by Nathan Kinder
admserv/cgi-src40/admpw.c | 3 +--
admserv/cgi-src40/config.c | 3 ---
admserv/cgi-src40/viewlog.c | 2 +-
mod_admserv/mod_admserv.c | 9 ++++++---
4 files changed, 8 insertions(+), 9 deletions(-)
New commits:
commit 0f9bcc0f95dd5523b4a5f4739ae095b6adfd5af0
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Tue Apr 26 13:54:07 2011 -0700
Bug 699815 - (cov#10849,10851) Remove unused variables
There are a few unused variables that should be removed from the
adminserver code.
diff --git a/admserv/cgi-src40/admpw.c b/admserv/cgi-src40/admpw.c
index cbba671..ff0dc6c 100644
--- a/admserv/cgi-src40/admpw.c
+++ b/admserv/cgi-src40/admpw.c
@@ -264,7 +264,7 @@ static void output_admuid(AdmldapInfo admInfo) {
static void update_uidpwd(AdmldapInfo admInfo) {
FILE *f;
- char *uid=NULL ,*pw=NULL, *col=NULL;
+ char *uid=NULL, *pw=NULL, *col=NULL;
char *newuid=NULL, *newpw=NULL;
static char filename[BIG_LINE];
static char inbuf[BIG_LINE];
@@ -273,7 +273,6 @@ static void update_uidpwd(AdmldapInfo admInfo) {
PR_snprintf(filename, sizeof(filename), tmpfile);
PL_strfree(tmpfile);
- uid = admldapGetLocalAdminName(admInfo);
newuid = get_cgi_var("admpw.uid",NULL, NULL);
newpw = get_cgi_var("admpw.pw",NULL, NULL);
if (newuid==NULL && newpw==NULL) {
diff --git a/admserv/cgi-src40/config.c b/admserv/cgi-src40/config.c
index 8e04f88..69e89f6 100644
--- a/admserv/cgi-src40/config.c
+++ b/admserv/cgi-src40/config.c
@@ -165,7 +165,6 @@ int main(int argc, char *argv[])
AttributePtr nv;
char *acceptLanguage = (char*)"en";
Resource *i18nResource = NULL;
- AdmldapInfo adminfo = NULL;
char *configdir = util_get_conf_dir();
char *secdir = util_get_security_dir();
char *logdir = util_get_log_dir();
@@ -263,8 +262,6 @@ int main(int argc, char *argv[])
if (binddn) rv = ADM_GetCurrentPassword(&err, &bindpw);
- adminfo = admldapBuildInfo(configdir, &rv);
-
errorCode = ADMSSL_InitSimple(configdir, secdir, 1);
if (errorCode) {
if (i18nResource)
commit 511a345be262920d19ecf73bc7093446c2d03b1a
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Tue Apr 26 09:57:04 2011 -0700
Bug 699815 - (cov#10858) getenv() called twice in viewlog cgi
We call getenv() twice to set qs. We should only call getenv() to
set qs if the GET method is being used.
diff --git a/admserv/cgi-src40/viewlog.c b/admserv/cgi-src40/viewlog.c
index 2eff9c2..a24130b 100644
--- a/admserv/cgi-src40/viewlog.c
+++ b/admserv/cgi-src40/viewlog.c
@@ -305,7 +305,7 @@ int main(int argc, char *argv[])
{
int _ai = ADMUTIL_Init();
- char *qs = getenv("QUERY_STRING");
+ char *qs = NULL;
char line[BIG_LINE];
FILE *html = open_html_file(MY_PAGE);
char *method = NULL;
commit 0241013085c58b6af06bb6f6633fcbf81fc1ae54
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Tue Apr 26 09:42:32 2011 -0700
Bug 699815 - (cov#10859) Add missing braces in mod_admserv code
There are a few spots in mod_admserv where we attempt to reconnect
to DS. The braces on the if statements were left out, so the loops
that retry the connection are only executed once. This adds the
braces so the connection is retried.
diff --git a/mod_admserv/mod_admserv.c b/mod_admserv/mod_admserv.c
index ede5c33..3c3e9e0 100644
--- a/mod_admserv/mod_admserv.c
+++ b/mod_admserv/mod_admserv.c
@@ -2652,10 +2652,11 @@ authenticate_user(LdapServerData *data, char *baseDN, char *user, const char *pw
break;
closeLDAPConnection(server);
- if (!(server = openLDAPConnection(data)))
+ if (!(server = openLDAPConnection(data))) {
ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
"unable to open LDAPConnection to server [%s:%d]", data->host, data->port);
return DECLINED;
+ }
} while (server != NULL && ++tries < 2);
if (ldapError != LDAPU_SUCCESS)
@@ -2683,11 +2684,12 @@ authenticate_user(LdapServerData *data, char *baseDN, char *user, const char *pw
break;
closeLDAPConnection(server);
- if(!(server = openLDAPConnection(data)))
+ if(!(server = openLDAPConnection(data))) {
ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
"unable to find user [%s] in server [%s:%d] under base DN [%s]",
user, data->host, data->port, data->baseDN ? data->baseDN : baseDN);
return DECLINED;
+ }
} while (server != NULL && ++tries < 2);
if (ldapError != LDAPU_SUCCESS)
@@ -2725,11 +2727,12 @@ authenticate_user(LdapServerData *data, char *baseDN, char *user, const char *pw
break;
closeLDAPConnection(server);
- if(!(server = openLDAPConnection(data)))
+ if(!(server = openLDAPConnection(data))) {
ap_log_rerror(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, 0, r,
"unable to bind as [%s] to server [%s:%d]",
userdn, data->host, data->port); /*i18n*/
return DECLINED;
+ }
} while (server != NULL && ++tries < 2);
if (ldapError != LDAP_SUCCESS)
13 years
Branch '389-ds-base-1.2.8' - ldap/servers
by Nathan Kinder
ldap/servers/plugins/replication/windows_protocol_util.c | 24 +++++++++++++--
ldap/servers/slapd/entry.c | 8 +++++
ldap/servers/slapd/slapi-plugin.h | 15 ++++++++-
3 files changed, 43 insertions(+), 4 deletions(-)
New commits:
commit 2be27d35da9fdf6d5f35ff4fb94906f4fe193133
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Thu Apr 21 15:42:28 2011 -0700
Bug 695779 - windows sync can lose old values when a new value is added
When a single modify operation with multiple mods is played back to
AD, it is possible for some old values to be lost. We check if a
mod is necessary to send to AD to detect loops, and skip sending
operations or values that are not necessary. This doesn't take
prior mods in the same modify operation into account though, which
can make the results incorrect.
This patch makes the sync code keep a running copy of the AD entry
that the mods are applied to. We use this copy to check which mods
can be skipped and which we must send.
diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c
index 716f4be..abcdbc3 100644
--- a/ldap/servers/plugins/replication/windows_protocol_util.c
+++ b/ldap/servers/plugins/replication/windows_protocol_util.c
@@ -2063,12 +2063,11 @@ windows_delete_local_entry(Slapi_DN *sdn){
error message to that effect.
*/
static int
-mod_already_made(Private_Repl_Protocol *prp, Slapi_Mod *smod)
+mod_already_made(Private_Repl_Protocol *prp, Slapi_Mod *smod, Slapi_Entry *ad_entry)
{
int retval = 0;
int op = 0;
const char *type = NULL;
- const Slapi_Entry *ad_entry = windows_private_get_raw_entry(prp->agmt);
if (!slapi_mod_isvalid(smod)) { /* bogus */
slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
@@ -2155,6 +2154,15 @@ mod_already_made(Private_Repl_Protocol *prp, Slapi_Mod *smod)
agmt_get_long_name(prp->agmt), op);
}
+ /* If the mod shouldn't be skipped, we should
+ * apply it to the entry that was passed in. This
+ * allows a single modify operation with multiple
+ * mods to take prior mods into account when
+ * determining what can be skipped. */
+ if (retval == 0) {
+ slapi_entry_apply_mod(ad_entry, slapi_mod_get_ldapmod_byref(smod));
+ }
+
return retval;
}
@@ -2438,10 +2446,18 @@ windows_map_mods_for_replay(Private_Repl_Protocol *prp,LDAPMod **original_mods,
LDAPMod *mod = NULL;
int is_nt4 = windows_private_get_isnt4(prp->agmt);
Slapi_Mod *mysmod = NULL;
+ const Slapi_Entry *ad_entry = NULL;
+ Slapi_Entry *ad_entry_copy = NULL;
LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_map_mods_for_replay\n", 0, 0, 0 );
/* Iterate through the original mods, looking each attribute type up in the maps for either user or group */
+
+ /* Make a copy of the AD entry. */
+ ad_entry = windows_private_get_raw_entry(prp->agmt);
+ if (ad_entry) {
+ ad_entry_copy = slapi_entry_dup(ad_entry);
+ }
slapi_mods_init_byref(&smods, original_mods);
slapi_mods_init(&mapped_smods,10);
@@ -2603,7 +2619,7 @@ windows_map_mods_for_replay(Private_Repl_Protocol *prp,LDAPMod **original_mods,
}
}
/* Otherwise we do not copy this mod at all */
- if (mysmod && !mod_already_made(prp, mysmod)) { /* make sure this mod is still valid to send */
+ if (mysmod && !mod_already_made(prp, mysmod, ad_entry_copy)) { /* make sure this mod is still valid to send */
slapi_mods_add_ldapmod(&mapped_smods, slapi_mod_get_ldapmod_passout(mysmod));
}
if (mysmod) {
@@ -2612,6 +2628,8 @@ windows_map_mods_for_replay(Private_Repl_Protocol *prp,LDAPMod **original_mods,
mod = slapi_mods_get_next_mod(&smods);
}
+
+ slapi_entry_free(ad_entry_copy);
slapi_mods_done (&smods);
/* Extract the mods for the caller */
*returned_mods = slapi_mods_get_ldapmods_passout(&mapped_smods);
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c
index 9e0b57f..a945485 100644
--- a/ldap/servers/slapd/entry.c
+++ b/ldap/servers/slapd/entry.c
@@ -3176,6 +3176,14 @@ slapi_entry_apply_mods( Slapi_Entry *e, LDAPMod **mods )
return entry_apply_mods(e, mods);
}
+/*
+ * Apply a single mod to an entry
+ */
+int slapi_entry_apply_mod( Slapi_Entry *e, LDAPMod *mod )
+{
+ return entry_apply_mod(e, mod);
+}
+
int
entry_apply_mods( Slapi_Entry *e, LDAPMod **mods )
{
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 8531fbe..898e0f8 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -1978,7 +1978,7 @@ int slapi_entry_delete_string(Slapi_Entry *e, const char *type, const char *valu
void slapi_entry_diff(Slapi_Mods *smods, Slapi_Entry *e1, Slapi_Entry *e2, int diff_ctrl);
/**
- * Applies an array of \c LDAPMod modifications a Slapi_Entry.
+ * Applies an array of \c LDAPMod modifications to a Slapi_Entry.
*
* \param e Entry to which you want to apply the modifications.
* \param mods \c NULL terminated array of \c LDAPMod modifications that you
@@ -1991,6 +1991,19 @@ void slapi_entry_diff(Slapi_Mods *smods, Slapi_Entry *e1, Slapi_Entry *e2, int d
int slapi_entry_apply_mods(Slapi_Entry *e, LDAPMod **mods);
/**
+ * Applies a single \c LDAPMod modification to a Slapi_Entry.
+ *
+ * \param e Entry to which you want to apply the modification.
+ * \param mod A pointer to the \c LDAPMod modification that you
+ * want to apply to the specified entry.
+ * \return \c LDAP_SUCCESS if the mod applied to the entry cleanly, otherwise
+ * an LDAP error is returned.
+ * \warning It is up to the caller to free the \c LDAPMod after the mod has
+ * been applied.
+ */
+int slapi_entry_apply_mod(Slapi_Entry *e, LDAPMod *mod);
+
+/**
* Renames a Slapi_Entry.
*
* This function will rename an existing \c Slapi_Entry, similar to what
13 years
ldap/servers
by Nathan Kinder
ldap/servers/plugins/replication/windows_protocol_util.c | 24 +++++++++++++--
ldap/servers/slapd/entry.c | 8 +++++
ldap/servers/slapd/slapi-plugin.h | 15 ++++++++-
3 files changed, 43 insertions(+), 4 deletions(-)
New commits:
commit fb7aee0ae6cbc11d7d35808585a2617adeff5c65
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Thu Apr 21 15:42:28 2011 -0700
Bug 695779 - windows sync can lose old values when a new value is added
When a single modify operation with multiple mods is played back to
AD, it is possible for some old values to be lost. We check if a
mod is necessary to send to AD to detect loops, and skip sending
operations or values that are not necessary. This doesn't take
prior mods in the same modify operation into account though, which
can make the results incorrect.
This patch makes the sync code keep a running copy of the AD entry
that the mods are applied to. We use this copy to check which mods
can be skipped and which we must send.
diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c
index a54fe9e..ec67612 100644
--- a/ldap/servers/plugins/replication/windows_protocol_util.c
+++ b/ldap/servers/plugins/replication/windows_protocol_util.c
@@ -2063,12 +2063,11 @@ windows_delete_local_entry(Slapi_DN *sdn){
error message to that effect.
*/
static int
-mod_already_made(Private_Repl_Protocol *prp, Slapi_Mod *smod)
+mod_already_made(Private_Repl_Protocol *prp, Slapi_Mod *smod, Slapi_Entry *ad_entry)
{
int retval = 0;
int op = 0;
const char *type = NULL;
- const Slapi_Entry *ad_entry = windows_private_get_raw_entry(prp->agmt);
if (!slapi_mod_isvalid(smod)) { /* bogus */
slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
@@ -2155,6 +2154,15 @@ mod_already_made(Private_Repl_Protocol *prp, Slapi_Mod *smod)
agmt_get_long_name(prp->agmt), op);
}
+ /* If the mod shouldn't be skipped, we should
+ * apply it to the entry that was passed in. This
+ * allows a single modify operation with multiple
+ * mods to take prior mods into account when
+ * determining what can be skipped. */
+ if (retval == 0) {
+ slapi_entry_apply_mod(ad_entry, slapi_mod_get_ldapmod_byref(smod));
+ }
+
return retval;
}
@@ -2438,10 +2446,18 @@ windows_map_mods_for_replay(Private_Repl_Protocol *prp,LDAPMod **original_mods,
LDAPMod *mod = NULL;
int is_nt4 = windows_private_get_isnt4(prp->agmt);
Slapi_Mod *mysmod = NULL;
+ const Slapi_Entry *ad_entry = NULL;
+ Slapi_Entry *ad_entry_copy = NULL;
LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_map_mods_for_replay\n", 0, 0, 0 );
/* Iterate through the original mods, looking each attribute type up in the maps for either user or group */
+
+ /* Make a copy of the AD entry. */
+ ad_entry = windows_private_get_raw_entry(prp->agmt);
+ if (ad_entry) {
+ ad_entry_copy = slapi_entry_dup(ad_entry);
+ }
slapi_mods_init_byref(&smods, original_mods);
slapi_mods_init(&mapped_smods,10);
@@ -2603,7 +2619,7 @@ windows_map_mods_for_replay(Private_Repl_Protocol *prp,LDAPMod **original_mods,
}
}
/* Otherwise we do not copy this mod at all */
- if (mysmod && !mod_already_made(prp, mysmod)) { /* make sure this mod is still valid to send */
+ if (mysmod && !mod_already_made(prp, mysmod, ad_entry_copy)) { /* make sure this mod is still valid to send */
slapi_mods_add_ldapmod(&mapped_smods, slapi_mod_get_ldapmod_passout(mysmod));
}
if (mysmod) {
@@ -2612,6 +2628,8 @@ windows_map_mods_for_replay(Private_Repl_Protocol *prp,LDAPMod **original_mods,
mod = slapi_mods_get_next_mod(&smods);
}
+
+ slapi_entry_free(ad_entry_copy);
slapi_mods_done (&smods);
/* Extract the mods for the caller */
*returned_mods = slapi_mods_get_ldapmods_passout(&mapped_smods);
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c
index 24f18aa..9e0ea2e 100644
--- a/ldap/servers/slapd/entry.c
+++ b/ldap/servers/slapd/entry.c
@@ -3175,6 +3175,14 @@ slapi_entry_apply_mods( Slapi_Entry *e, LDAPMod **mods )
return entry_apply_mods(e, mods);
}
+/*
+ * Apply a single mod to an entry
+ */
+int slapi_entry_apply_mod( Slapi_Entry *e, LDAPMod *mod )
+{
+ return entry_apply_mod(e, mod);
+}
+
int
entry_apply_mods( Slapi_Entry *e, LDAPMod **mods )
{
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 4ec8c70..8f6065b 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -1978,7 +1978,7 @@ int slapi_entry_delete_string(Slapi_Entry *e, const char *type, const char *valu
void slapi_entry_diff(Slapi_Mods *smods, Slapi_Entry *e1, Slapi_Entry *e2, int diff_ctrl);
/**
- * Applies an array of \c LDAPMod modifications a Slapi_Entry.
+ * Applies an array of \c LDAPMod modifications to a Slapi_Entry.
*
* \param e Entry to which you want to apply the modifications.
* \param mods \c NULL terminated array of \c LDAPMod modifications that you
@@ -1991,6 +1991,19 @@ void slapi_entry_diff(Slapi_Mods *smods, Slapi_Entry *e1, Slapi_Entry *e2, int d
int slapi_entry_apply_mods(Slapi_Entry *e, LDAPMod **mods);
/**
+ * Applies a single \c LDAPMod modification to a Slapi_Entry.
+ *
+ * \param e Entry to which you want to apply the modification.
+ * \param mod A pointer to the \c LDAPMod modification that you
+ * want to apply to the specified entry.
+ * \return \c LDAP_SUCCESS if the mod applied to the entry cleanly, otherwise
+ * an LDAP error is returned.
+ * \warning It is up to the caller to free the \c LDAPMod after the mod has
+ * been applied.
+ */
+int slapi_entry_apply_mod(Slapi_Entry *e, LDAPMod *mod);
+
+/**
* Renames a Slapi_Entry.
*
* This function will rename an existing \c Slapi_Entry, similar to what
13 years
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/back-ldbm/cache.c | 3 ---
1 file changed, 3 deletions(-)
New commits:
commit 11c8bf1adaf925aedef76df4095abe2d47fe0223
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Thu Apr 21 10:24:39 2011 -0700
Bug 697027 - 3 - minor memory leaks found by Valgrind + TET
https://bugzilla.redhat.com/show_bug.cgi?id=697027
Description: Previous commit fe9b6a6bab32353f55a6ce2123f7df6b72a9a5a7
failed to remove unnecessary 3 slapi_counter_destroy calls.
diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c
index 95fa638..ff9921a 100644
--- a/ldap/servers/slapd/back-ldbm/cache.c
+++ b/ldap/servers/slapd/back-ldbm/cache.c
@@ -652,9 +652,6 @@ static void erase_cache(struct cache *cache, int type)
#ifdef UUIDCACHE_ON
slapi_ch_free((void **)&cache->c_uuidtable);
#endif
- slapi_counter_destroy(&cache->c_cursize);
- slapi_counter_destroy(&cache->c_hits);
- slapi_counter_destroy(&cache->c_tries);
}
/* to be used on shutdown or when destroying a backend instance */
13 years
ldap/servers
by Nathan Kinder
ldap/servers/plugins/automember/automember.c | 70 +++++++++++++++------------
1 file changed, 39 insertions(+), 31 deletions(-)
New commits:
commit 16f3ead8001550afb73419943eb466684132c5ae
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Wed Apr 20 14:06:55 2011 -0700
Bug 698428 - Make auto membership use Slapi_DN for DN comparisons
The Auto Membership plug-in should use slapi_sdn_compare() for DN
comparisons instead of strcmp(). This will ensure that normalized
DNs are used and the comparison results are correct.
diff --git a/ldap/servers/plugins/automember/automember.c b/ldap/servers/plugins/automember/automember.c
index 89b492a..a015eae 100644
--- a/ldap/servers/plugins/automember/automember.c
+++ b/ldap/servers/plugins/automember/automember.c
@@ -52,8 +52,8 @@ static PRCList *g_automember_config = NULL;
static PRRWLock *g_automember_config_lock;
static void *_PluginID = NULL;
-static char *_PluginDN = NULL;
-static char *_ConfigAreaDN = NULL;
+static Slapi_DN *_PluginDN = NULL;
+static Slapi_DN *_ConfigAreaDN = NULL;
static int g_plugin_started = 0;
static Slapi_PluginDesc pdesc = { AUTOMEMBER_FEATURE_DESC,
@@ -93,8 +93,8 @@ static void automember_free_config_entry(struct configEntry ** entry);
* helpers
*/
static char *automember_get_dn(Slapi_PBlock * pb);
-static char *automember_get_config_area();
-static void automember_set_config_area(char *dn);
+static Slapi_DN *automember_get_config_area();
+static void automember_set_config_area(Slapi_DN *sdn);
static int automember_dn_is_config(char *dn);
static int automember_oktodo(Slapi_PBlock *pb);
static int automember_isrepl(Slapi_PBlock *pb);
@@ -144,13 +144,13 @@ automember_get_plugin_id()
}
void
-automember_set_plugin_dn(char *pluginDN)
+automember_set_plugin_sdn(Slapi_DN *pluginDN)
{
_PluginDN = pluginDN;
}
-char *
-automember_get_plugin_dn()
+Slapi_DN *
+automember_get_plugin_sdn()
{
return _PluginDN;
}
@@ -304,12 +304,12 @@ automember_start(Slapi_PBlock * pb)
return -1;
}
- automember_set_plugin_dn(plugindn);
+ automember_set_plugin_sdn(slapi_sdn_new_dn_byref(plugindn));
/* Set the alternate config area if one is defined. */
slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_AREA, &config_area);
if (config_area) {
- automember_set_config_area(slapi_ch_strdup(config_area));
+ automember_set_config_area(slapi_sdn_new_dn_byval(config_area));
}
/*
@@ -352,7 +352,8 @@ automember_close(Slapi_PBlock * pb)
automember_delete_config();
slapi_ch_free((void **)&g_automember_config);
- slapi_ch_free_string(&_ConfigAreaDN);
+ slapi_sdn_free(&_PluginDN);
+ slapi_sdn_free(&_ConfigAreaDN);
if (g_automember_config_lock) {
PR_DestroyRWLock(g_automember_config_lock);
@@ -399,11 +400,11 @@ automember_load_config()
slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
"automember_load_config: Looking for config entries "
- "beneath \"%s\".\n", automember_get_plugin_dn());
+ "beneath \"%s\".\n", slapi_sdn_get_ndn(automember_get_plugin_sdn()));
/* Find the config entries beneath our plugin entry. */
search_pb = slapi_pblock_new();
- slapi_search_internal_set_pb(search_pb, automember_get_plugin_dn(),
+ slapi_search_internal_set_pb(search_pb, slapi_sdn_get_ndn(automember_get_plugin_sdn()),
LDAP_SCOPE_SUBTREE, "objectclass=*",
NULL, 0, NULL, NULL, automember_get_plugin_id(), 0);
slapi_search_internal_pb(search_pb);
@@ -438,9 +439,9 @@ automember_load_config()
slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
"automember_load_config: Looking for config entries "
- "beneath \"%s\".\n", automember_get_config_area());
+ "beneath \"%s\".\n", slapi_sdn_get_ndn(automember_get_config_area()));
- slapi_search_internal_set_pb(search_pb, automember_get_config_area(),
+ slapi_search_internal_set_pb(search_pb, slapi_sdn_get_ndn(automember_get_config_area()),
LDAP_SCOPE_SUBTREE, "objectclass=*",
NULL, 0, NULL, NULL, automember_get_plugin_id(), 0);
slapi_search_internal_pb(search_pb);
@@ -504,9 +505,9 @@ automember_parse_config_entry(Slapi_Entry * e, int apply)
/* If this is the main plug-in config entry or
* the config area container, just bail. */
- if ((strcasecmp(automember_get_plugin_dn(), slapi_entry_get_ndn(e)) == 0) ||
- (automember_get_config_area() && (strcasecmp(automember_get_config_area(),
- slapi_entry_get_ndn(e)) == 0))) {
+ if ((slapi_sdn_compare(automember_get_plugin_sdn(), slapi_entry_get_sdn(e)) == 0) ||
+ (automember_get_config_area() && (slapi_sdn_compare(automember_get_config_area(),
+ slapi_entry_get_sdn(e)) == 0))) {
goto bail;
}
@@ -594,8 +595,7 @@ automember_parse_config_entry(Slapi_Entry * e, int apply)
while (list != (PRCList *)entry->exclusive_rules) {
struct automemberRegexRule *curr_rule = (struct automemberRegexRule *)list;
/* Order rules by target group DN */
- if (strcmp(slapi_sdn_get_dn(rule->target_group_dn),
- slapi_sdn_get_dn(curr_rule->target_group_dn)) < 0) {
+ if (slapi_sdn_compare(rule->target_group_dn, curr_rule->target_group_dn) < 0) {
PR_INSERT_BEFORE(&(rule->list), list);
break;
}
@@ -647,8 +647,7 @@ automember_parse_config_entry(Slapi_Entry * e, int apply)
while (list != (PRCList *)entry->inclusive_rules) {
struct automemberRegexRule *curr_rule = (struct automemberRegexRule *)list;
/* Order rules by target group DN */
- if (strcmp(slapi_sdn_get_dn(rule->target_group_dn),
- slapi_sdn_get_dn(curr_rule->target_group_dn)) < 0) {
+ if (slapi_sdn_compare(rule->target_group_dn, curr_rule->target_group_dn) < 0) {
PR_INSERT_BEFORE(&(rule->list), list);
break;
}
@@ -887,12 +886,12 @@ automember_get_dn(Slapi_PBlock * pb)
}
void
-automember_set_config_area(char *dn)
+automember_set_config_area(Slapi_DN *sdn)
{
- _ConfigAreaDN = dn;
+ _ConfigAreaDN = sdn;
}
-char *
+Slapi_DN *
automember_get_config_area()
{
return _ConfigAreaDN;
@@ -907,20 +906,29 @@ static int
automember_dn_is_config(char *dn)
{
int ret = 0;
+ Slapi_DN *sdn = NULL;
slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
"--> automember_dn_is_config\n");
+ if (dn == NULL) {
+ goto bail;
+ }
+
+ sdn = slapi_sdn_new_dn_byref(dn);
+
/* Return 1 if the passed in dn is a child of the main
* plugin config entry, or if it is a child of the
* container defined as a config area. */
- if ((slapi_dn_issuffix(dn, automember_get_plugin_dn()) &&
- strcasecmp(dn, automember_get_plugin_dn())) ||
- (automember_get_config_area() && slapi_dn_issuffix(dn,
+ if ((slapi_sdn_issuffix(sdn, automember_get_plugin_sdn()) &&
+ slapi_sdn_compare(sdn, automember_get_plugin_sdn()))||
+ (automember_get_config_area() && slapi_sdn_issuffix(sdn,
automember_get_config_area()))) {
ret = 1;
}
+bail:
+ slapi_sdn_free(&sdn);
slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
"<-- automember_dn_is_config\n");
@@ -1379,9 +1387,9 @@ automember_update_membership(struct configEntry *config, Slapi_Entry *e)
* until we find a target that is the same or comes after the
* current rule. */
if (curr_exclusion) {
- while ((curr_exclusion != &exclusions) && (strcmp(slapi_sdn_get_ndn(
- ((struct automemberDNListItem *)curr_exclusion)->dn),
- slapi_sdn_get_ndn(curr_rule->target_group_dn)) < 0)) {
+ while ((curr_exclusion != &exclusions) && (slapi_sdn_compare(
+ ((struct automemberDNListItem *)curr_exclusion)->dn,
+ curr_rule->target_group_dn) < 0)) {
curr_exclusion = PR_NEXT_LINK(curr_exclusion);
}
}
@@ -1810,7 +1818,7 @@ automember_modrdn_post_op(Slapi_PBlock *pb)
/* Just bail if we aren't ready to service requests yet. */
if (!g_plugin_started || !automember_oktodo(pb))
- return 0;;
+ return 0;
/* Reload config if an existing config entry was renamed,
* or if the new dn brings an entry into the scope of the
13 years
ldap/admin ldap/ldif ldap/schema ldap/servers Makefile.am Makefile.in
by Nathan Kinder
Makefile.am | 18
Makefile.in | 59
ldap/admin/src/scripts/50automemberplugin.ldif | 15
ldap/ldif/template-dse.ldif.in | 11
ldap/schema/01core389.ldif | 3
ldap/schema/10automember-plugin.ldif | 106 +
ldap/servers/plugins/automember/automember.c | 1842 +++++++++++++++++++++++++
ldap/servers/plugins/automember/automember.h | 128 +
ldap/servers/slapd/pblock.c | 6
ldap/servers/slapd/plugin.c | 11
ldap/servers/slapd/slap.h | 2
ldap/servers/slapd/slapi-plugin.h | 2
12 files changed, 2192 insertions(+), 11 deletions(-)
New commits:
commit 006083a8c2fce66b49508f46c700721ed3ce2463
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Tue Apr 19 11:35:46 2011 -0700
Add Auto Membership Plug-in
This adds a new auto-membership plug-in. This plug-in allows one
to define rules that can assign newly added entries to groups.
For details, see the design document on the 389 wiki, located
at http://directory.fedoraproject.org/wiki/Auto_Membership_Design
diff --git a/Makefile.am b/Makefile.am
index a6c1c67..5a29505 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -189,9 +189,10 @@ enable_acctpolicy = 1
endif
serverplugin_LTLIBRARIES = libacl-plugin.la libattr-unique-plugin.la \
- libback-ldbm.la libchainingdb-plugin.la libcollation-plugin.la \
- libcos-plugin.la libderef-plugin.la libdes-plugin.la libdistrib-plugin.la \
- libhttp-client-plugin.la liblinkedattrs-plugin.la libmanagedentries-plugin.la \
+ libautomember-plugin.la libback-ldbm.la libchainingdb-plugin.la \
+ libcollation-plugin.la libcos-plugin.la libderef-plugin.la \
+ libdes-plugin.la libdistrib-plugin.la libhttp-client-plugin.la \
+ liblinkedattrs-plugin.la libmanagedentries-plugin.la \
libmemberof-plugin.la libpassthru-plugin.la libpwdstorage-plugin.la \
libreferint-plugin.la libreplication-plugin.la libretrocl-plugin.la \
libroles-plugin.la libstatechange-plugin.la libsyntax-plugin.la \
@@ -267,6 +268,7 @@ schema_DATA = $(srcdir)/ldap/schema/00core.ldif \
$(srcdir)/ldap/schema/05rfc4523.ldif \
$(srcdir)/ldap/schema/05rfc4524.ldif \
$(srcdir)/ldap/schema/06inetorgperson.ldif \
+ $(srcdir)/ldap/schema/10automember-plugin.ldif \
$(srcdir)/ldap/schema/10mep-plugin.ldif \
$(srcdir)/ldap/schema/10rfc2307.ldif \
$(srcdir)/ldap/schema/20subscriber.ldif \
@@ -441,6 +443,7 @@ update_DATA = ldap/admin/src/scripts/exampleupdate.pl \
ldap/admin/src/scripts/10delautodnsuffix.pl \
ldap/admin/src/scripts/10fixrundir.pl \
ldap/admin/src/scripts/50addchainingsaslpwroles.ldif \
+ ldap/admin/src/scripts/50automemberplugin.ldif \
ldap/admin/src/scripts/50memberofindex.ldif \
ldap/admin/src/scripts/50bitstringsyntaxplugin.ldif \
ldap/admin/src/scripts/50managedentriesplugin.ldif \
@@ -789,6 +792,15 @@ libacl_plugin_la_LDFLAGS = -avoid-version
libacl_plugin_la_LINK = $(CXXLINK) -avoid-version
#------------------------
+# libautomember-plugin
+#------------------------
+libautomember_plugin_la_SOURCES = ldap/servers/plugins/automember/automember.c
+
+libautomember_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS)
+libautomember_plugin_la_LIBADD = libslapd.la $(NSPR_LINK)
+libautomember_plugin_la_LDFLAGS = -avoid-version
+
+#------------------------
# libattr-unique-plugin
#------------------------
libattr_unique_plugin_la_SOURCES = ldap/servers/plugins/uiduniq/7bit.c \
diff --git a/Makefile.in b/Makefile.in
index 47aa1f4..c653e04 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -166,6 +166,14 @@ libattr_unique_plugin_la_OBJECTS = \
libattr_unique_plugin_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libattr_unique_plugin_la_LDFLAGS) $(LDFLAGS) -o $@
+libautomember_plugin_la_DEPENDENCIES = libslapd.la \
+ $(am__DEPENDENCIES_1)
+am_libautomember_plugin_la_OBJECTS = ldap/servers/plugins/automember/libautomember_plugin_la-automember.lo
+libautomember_plugin_la_OBJECTS = \
+ $(am_libautomember_plugin_la_OBJECTS)
+libautomember_plugin_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libautomember_plugin_la_LDFLAGS) $(LDFLAGS) -o $@
libback_ldbm_la_DEPENDENCIES = libslapd.la $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
am_libback_ldbm_la_OBJECTS = \
@@ -964,7 +972,8 @@ CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libavl_a_SOURCES) $(libldaputil_a_SOURCES) \
$(libacctpolicy_plugin_la_SOURCES) $(libacl_plugin_la_SOURCES) \
- $(libattr_unique_plugin_la_SOURCES) $(libback_ldbm_la_SOURCES) \
+ $(libattr_unique_plugin_la_SOURCES) \
+ $(libautomember_plugin_la_SOURCES) $(libback_ldbm_la_SOURCES) \
$(libbitwise_plugin_la_SOURCES) \
$(libchainingdb_plugin_la_SOURCES) \
$(libcollation_plugin_la_SOURCES) $(libcos_plugin_la_SOURCES) \
@@ -993,7 +1002,8 @@ SOURCES = $(libavl_a_SOURCES) $(libldaputil_a_SOURCES) \
$(rsearch_bin_SOURCES)
DIST_SOURCES = $(libavl_a_SOURCES) $(libldaputil_a_SOURCES) \
$(libacctpolicy_plugin_la_SOURCES) $(libacl_plugin_la_SOURCES) \
- $(libattr_unique_plugin_la_SOURCES) $(libback_ldbm_la_SOURCES) \
+ $(libattr_unique_plugin_la_SOURCES) \
+ $(libautomember_plugin_la_SOURCES) $(libback_ldbm_la_SOURCES) \
$(libbitwise_plugin_la_SOURCES) \
$(libchainingdb_plugin_la_SOURCES) \
$(libcollation_plugin_la_SOURCES) $(libcos_plugin_la_SOURCES) \
@@ -1368,9 +1378,10 @@ server_LTLIBRARIES = libslapd.la libns-dshttpd.la
@enable_acctpolicy_TRUE@LIBACCTPOLICY_SCHEMA = $(srcdir)/ldap/schema/60acctpolicy.ldif
@enable_acctpolicy_TRUE@enable_acctpolicy = 1
serverplugin_LTLIBRARIES = libacl-plugin.la libattr-unique-plugin.la \
- libback-ldbm.la libchainingdb-plugin.la libcollation-plugin.la \
- libcos-plugin.la libderef-plugin.la libdes-plugin.la libdistrib-plugin.la \
- libhttp-client-plugin.la liblinkedattrs-plugin.la libmanagedentries-plugin.la \
+ libautomember-plugin.la libback-ldbm.la libchainingdb-plugin.la \
+ libcollation-plugin.la libcos-plugin.la libderef-plugin.la \
+ libdes-plugin.la libdistrib-plugin.la libhttp-client-plugin.la \
+ liblinkedattrs-plugin.la libmanagedentries-plugin.la \
libmemberof-plugin.la libpassthru-plugin.la libpwdstorage-plugin.la \
libreferint-plugin.la libreplication-plugin.la libretrocl-plugin.la \
libroles-plugin.la libstatechange-plugin.la libsyntax-plugin.la \
@@ -1444,6 +1455,7 @@ schema_DATA = $(srcdir)/ldap/schema/00core.ldif \
$(srcdir)/ldap/schema/05rfc4523.ldif \
$(srcdir)/ldap/schema/05rfc4524.ldif \
$(srcdir)/ldap/schema/06inetorgperson.ldif \
+ $(srcdir)/ldap/schema/10automember-plugin.ldif \
$(srcdir)/ldap/schema/10mep-plugin.ldif \
$(srcdir)/ldap/schema/10rfc2307.ldif \
$(srcdir)/ldap/schema/20subscriber.ldif \
@@ -1620,6 +1632,7 @@ update_DATA = ldap/admin/src/scripts/exampleupdate.pl \
ldap/admin/src/scripts/10delautodnsuffix.pl \
ldap/admin/src/scripts/10fixrundir.pl \
ldap/admin/src/scripts/50addchainingsaslpwroles.ldif \
+ ldap/admin/src/scripts/50automemberplugin.ldif \
ldap/admin/src/scripts/50memberofindex.ldif \
ldap/admin/src/scripts/50bitstringsyntaxplugin.ldif \
ldap/admin/src/scripts/50managedentriesplugin.ldif \
@@ -1914,6 +1927,14 @@ libacl_plugin_la_LDFLAGS = -avoid-version
libacl_plugin_la_LINK = $(CXXLINK) -avoid-version
#------------------------
+# libautomember-plugin
+#------------------------
+libautomember_plugin_la_SOURCES = ldap/servers/plugins/automember/automember.c
+libautomember_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS)
+libautomember_plugin_la_LIBADD = libslapd.la $(NSPR_LINK)
+libautomember_plugin_la_LDFLAGS = -avoid-version
+
+#------------------------
# libattr-unique-plugin
#------------------------
libattr_unique_plugin_la_SOURCES = ldap/servers/plugins/uiduniq/7bit.c \
@@ -2800,6 +2821,17 @@ ldap/servers/plugins/uiduniq/libattr_unique_plugin_la-utils.lo: \
ldap/servers/plugins/uiduniq/$(DEPDIR)/$(am__dirstamp)
libattr-unique-plugin.la: $(libattr_unique_plugin_la_OBJECTS) $(libattr_unique_plugin_la_DEPENDENCIES)
$(libattr_unique_plugin_la_LINK) -rpath $(serverplugindir) $(libattr_unique_plugin_la_OBJECTS) $(libattr_unique_plugin_la_LIBADD) $(LIBS)
+ldap/servers/plugins/automember/$(am__dirstamp):
+ @$(MKDIR_P) ldap/servers/plugins/automember
+ @: > ldap/servers/plugins/automember/$(am__dirstamp)
+ldap/servers/plugins/automember/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) ldap/servers/plugins/automember/$(DEPDIR)
+ @: > ldap/servers/plugins/automember/$(DEPDIR)/$(am__dirstamp)
+ldap/servers/plugins/automember/libautomember_plugin_la-automember.lo: \
+ ldap/servers/plugins/automember/$(am__dirstamp) \
+ ldap/servers/plugins/automember/$(DEPDIR)/$(am__dirstamp)
+libautomember-plugin.la: $(libautomember_plugin_la_OBJECTS) $(libautomember_plugin_la_DEPENDENCIES)
+ $(libautomember_plugin_la_LINK) -rpath $(serverplugindir) $(libautomember_plugin_la_OBJECTS) $(libautomember_plugin_la_LIBADD) $(LIBS)
ldap/servers/slapd/back-ldbm/$(am__dirstamp):
@$(MKDIR_P) ldap/servers/slapd/back-ldbm
@: > ldap/servers/slapd/back-ldbm/$(am__dirstamp)
@@ -4667,6 +4699,8 @@ mostlyclean-compile:
-rm -f ldap/servers/plugins/acl/libacl_plugin_la-aclplugin.lo
-rm -f ldap/servers/plugins/acl/libacl_plugin_la-aclutil.$(OBJEXT)
-rm -f ldap/servers/plugins/acl/libacl_plugin_la-aclutil.lo
+ -rm -f ldap/servers/plugins/automember/libautomember_plugin_la-automember.$(OBJEXT)
+ -rm -f ldap/servers/plugins/automember/libautomember_plugin_la-automember.lo
-rm -f ldap/servers/plugins/bitwise/libbitwise_plugin_la-bitwise.$(OBJEXT)
-rm -f ldap/servers/plugins/bitwise/libbitwise_plugin_la-bitwise.lo
-rm -f ldap/servers/plugins/chainingdb/libchainingdb_plugin_la-cb_abandon.$(OBJEXT)
@@ -5493,6 +5527,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/acl/$(DEPDIR)/libacl_plugin_la-aclparse.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/acl/$(DEPDIR)/libacl_plugin_la-aclplugin.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/acl/$(DEPDIR)/libacl_plugin_la-aclutil.Plo(a)am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/automember/$(DEPDIR)/libautomember_plugin_la-automember.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/bitwise/$(DEPDIR)/libbitwise_plugin_la-bitwise.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/chainingdb/$(DEPDIR)/libchainingdb_plugin_la-cb_abandon.Plo(a)am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/chainingdb/$(DEPDIR)/libchainingdb_plugin_la-cb_acl.Plo(a)am__quote@
@@ -6225,6 +6260,13 @@ ldap/servers/plugins/uiduniq/libattr_unique_plugin_la-utils.lo: ldap/servers/plu
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libattr_unique_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/uiduniq/libattr_unique_plugin_la-utils.lo `test -f 'ldap/servers/plugins/uiduniq/utils.c' || echo '$(srcdir)/'`ldap/servers/plugins/uiduniq/utils.c
+ldap/servers/plugins/automember/libautomember_plugin_la-automember.lo: ldap/servers/plugins/automember/automember.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libautomember_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/automember/libautomember_plugin_la-automember.lo -MD -MP -MF ldap/servers/plugins/automember/$(DEPDIR)/libautomember_plugin_la-automember.Tpo -c -o ldap/servers/plugins/automember/libautomember_plugin_la-automember.lo `test -f 'ldap/servers/plugins/automember/automember.c' || echo '$(srcdir)/'`ldap/servers/plugins/automember/automember.c
+@am__fastdepCC_TRUE@ $(am__mv) ldap/servers/plugins/automember/$(DEPDIR)/libautomember_plugin_la-automember.Tpo ldap/servers/plugins/automember/$(DEPDIR)/libautomember_plugin_la-automember.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ldap/servers/plugins/automember/automember.c' object='ldap/servers/plugins/automember/libautomember_plugin_la-automember.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libautomember_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/automember/libautomember_plugin_la-automember.lo `test -f 'ldap/servers/plugins/automember/automember.c' || echo '$(srcdir)/'`ldap/servers/plugins/automember/automember.c
+
ldap/servers/slapd/back-ldbm/libback_ldbm_la-ancestorid.lo: ldap/servers/slapd/back-ldbm/ancestorid.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libback_ldbm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/slapd/back-ldbm/libback_ldbm_la-ancestorid.lo -MD -MP -MF ldap/servers/slapd/back-ldbm/$(DEPDIR)/libback_ldbm_la-ancestorid.Tpo -c -o ldap/servers/slapd/back-ldbm/libback_ldbm_la-ancestorid.lo `test -f 'ldap/servers/slapd/back-ldbm/ancestorid.c' || echo '$(srcdir)/'`ldap/servers/slapd/back-ldbm/ancestorid.c
@am__fastdepCC_TRUE@ $(am__mv) ldap/servers/slapd/back-ldbm/$(DEPDIR)/libback_ldbm_la-ancestorid.Tpo ldap/servers/slapd/back-ldbm/$(DEPDIR)/libback_ldbm_la-ancestorid.Plo
@@ -9659,6 +9701,7 @@ clean-libtool:
-rm -rf ldap/libraries/libavl/.libs ldap/libraries/libavl/_libs
-rm -rf ldap/servers/plugins/acctpolicy/.libs ldap/servers/plugins/acctpolicy/_libs
-rm -rf ldap/servers/plugins/acl/.libs ldap/servers/plugins/acl/_libs
+ -rm -rf ldap/servers/plugins/automember/.libs ldap/servers/plugins/automember/_libs
-rm -rf ldap/servers/plugins/bitwise/.libs ldap/servers/plugins/bitwise/_libs
-rm -rf ldap/servers/plugins/chainingdb/.libs ldap/servers/plugins/chainingdb/_libs
-rm -rf ldap/servers/plugins/collation/.libs ldap/servers/plugins/collation/_libs
@@ -10261,6 +10304,8 @@ distclean-generic:
-rm -f ldap/servers/plugins/acctpolicy/$(am__dirstamp)
-rm -f ldap/servers/plugins/acl/$(DEPDIR)/$(am__dirstamp)
-rm -f ldap/servers/plugins/acl/$(am__dirstamp)
+ -rm -f ldap/servers/plugins/automember/$(DEPDIR)/$(am__dirstamp)
+ -rm -f ldap/servers/plugins/automember/$(am__dirstamp)
-rm -f ldap/servers/plugins/bitwise/$(DEPDIR)/$(am__dirstamp)
-rm -f ldap/servers/plugins/bitwise/$(am__dirstamp)
-rm -f ldap/servers/plugins/chainingdb/$(DEPDIR)/$(am__dirstamp)
@@ -10351,7 +10396,7 @@ clean-am: clean-binPROGRAMS clean-generic clean-libtool clean-local \
distclean: distclean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
- -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acctpolicy/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR) ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR) ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/deref/$(DEPDIR) ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR) ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR) ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/mep/$(DEPDIR) ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR) ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR) ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR) ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$(DEPDIR) ldap/servers/plugins/roles/$(DEPDIR) ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR)
ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR) ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR) ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR) ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR) ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR) ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR) lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
+ -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acctpolicy/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR) ldap/servers/plugins/automember/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR) ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR) ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/deref/$(DEPDIR) ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR) ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR) ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/mep/$(DEPDIR) ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR) ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR) ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR) ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$(DEPDIR) ldap/servers/plugins/roles/$(DEPDIR) ldap/servers/plugins/schema_reload/$(DEPDIR)
ldap/servers/plugins/statechange/$(DEPDIR) ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR) ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR) ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR) ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR) ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR) ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR) lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-hdr distclean-libtool distclean-tags
@@ -10407,7 +10452,7 @@ installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
- -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acctpolicy/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR) ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR) ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/deref/$(DEPDIR) ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR) ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR) ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/mep/$(DEPDIR) ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR) ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR) ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR) ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$(DEPDIR) ldap/servers/plugins/roles/$(DEPDIR) ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR)
ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR) ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR) ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR) ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR) ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR) ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR) lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
+ -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acctpolicy/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR) ldap/servers/plugins/automember/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR) ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR) ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/deref/$(DEPDIR) ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR) ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR) ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/mep/$(DEPDIR) ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR) ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR) ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR) ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$(DEPDIR) ldap/servers/plugins/roles/$(DEPDIR) ldap/servers/plugins/schema_reload/$(DEPDIR)
ldap/servers/plugins/statechange/$(DEPDIR) ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR) ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR) ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR) ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR) ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR) ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR) lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/ldap/admin/src/scripts/50automemberplugin.ldif b/ldap/admin/src/scripts/50automemberplugin.ldif
new file mode 100644
index 0000000..d0c201a
--- /dev/null
+++ b/ldap/admin/src/scripts/50automemberplugin.ldif
@@ -0,0 +1,15 @@
+dn: cn=Auto Membership Plugin,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: Auto Membership Plugin
+nsslapd-pluginpath: libautomember-plugin
+nsslapd-plugininitfunc: automember_init
+nsslapd-plugintype: preoperation
+nsslapd-pluginenabled: on
+nsslapd-plugin-depends-on-type: database
+# these will be replaced when the server loads the plugin
+nsslapd-pluginId: ID
+nsslapd-pluginVersion: PACKAGE_VERSION
+nsslapd-pluginVendor: VENDOR
+nsslapd-pluginDescription: DESC
diff --git a/ldap/ldif/template-dse.ldif.in b/ldap/ldif/template-dse.ldif.in
index cd98d16..a345a40 100644
--- a/ldap/ldif/template-dse.ldif.in
+++ b/ldap/ldif/template-dse.ldif.in
@@ -619,6 +619,17 @@ nsslapd-pluginarg3: ,
nsslapd-pluginarg4: %ds_suffix%
nsslapd-plugin-depends-on-type: database
+dn: cn=Auto Membership Plugin,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: Auto Membership Plugin
+nsslapd-pluginpath: libautomember-plugin
+nsslapd-plugininitfunc: automember_init
+nsslapd-plugintype: preoperation
+nsslapd-pluginenabled: on
+nsslapd-plugin-depends-on-type: database
+
dn: cn=deref,cn=plugins,cn=config
objectclass: top
objectclass: nsSlapdPlugin
diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif
index 95607fc..3402430 100644
--- a/ldap/schema/01core389.ldif
+++ b/ldap/schema/01core389.ldif
@@ -54,6 +54,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.228 NAME 'nsslapd-pluginVersion' DESC 'N
attributeTypes: ( 2.16.840.1.113730.3.1.229 NAME 'nsslapd-pluginVendor' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.230 NAME 'nsslapd-pluginDescription' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.231 NAME 'nsslapd-pluginEnabled' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2104 NAME 'nsslapd-pluginConfigArea' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.232 NAME 'nsSNMPEnabled' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.233 NAME 'nsSNMPOrganization' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.234 NAME 'nsSNMPLocation' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' )
@@ -129,7 +130,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2095 NAME 'connection' DESC 'Netscape de
# objectclasses
#
objectClasses: ( 2.16.840.1.113730.3.2.40 NAME 'directoryServerFeature' DESC 'Netscape defined objectclass' SUP top MAY ( oid $ cn $ multiLineDescription ) X-ORIGIN 'Netscape Directory Server' )
-objectClasses: ( 2.16.840.1.113730.3.2.41 NAME 'nsslapdPlugin' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsslapd-pluginPath $ nsslapd-pluginInitFunc $ nsslapd-pluginType $ nsslapd-pluginId $ nsslapd-pluginVersion $ nsslapd-pluginVendor $ nsslapd-pluginDescription $ nsslapd-pluginEnabled ) X-ORIGIN 'Netscape Directory Server' )
+objectClasses: ( 2.16.840.1.113730.3.2.41 NAME 'nsslapdPlugin' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsslapd-pluginPath $ nsslapd-pluginInitFunc $ nsslapd-pluginType $ nsslapd-pluginId $ nsslapd-pluginVersion $ nsslapd-pluginVendor $ nsslapd-pluginDescription $ nsslapd-pluginEnabled ) MAY ( nsslapd-pluginConfigArea ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.44 NAME 'nsIndex' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsSystemIndex ) MAY ( description $ nsIndexType $ nsMatchingRule ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.109 NAME 'nsBackendInstance' DESC 'Netscape defined objectclass' SUP top MUST ( CN ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.110 NAME 'nsMappingTree' DESC 'Netscape defined objectclass' SUP top MUST ( CN ) X-ORIGIN 'Netscape Directory Server' )
diff --git a/ldap/schema/10automember-plugin.ldif b/ldap/schema/10automember-plugin.ldif
new file mode 100644
index 0000000..3428f07
--- /dev/null
+++ b/ldap/schema/10automember-plugin.ldif
@@ -0,0 +1,106 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# This Program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; version 2 of the License.
+#
+# This Program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA.
+#
+# In addition, as a special exception, Red Hat, Inc. gives You the additional
+# right to link the code of this Program with code not covered under the GNU
+# General Public License ("Non-GPL Code") and to distribute linked combinations
+# including the two, subject to the limitations in this paragraph. Non-GPL Code
+# permitted under this exception must only link to the code of this Program
+# through those well defined interfaces identified in the file named EXCEPTION
+# found in the source code files (the "Approved Interfaces"). The files of
+# Non-GPL Code may instantiate templates or use macros or inline functions from
+# the Approved Interfaces without causing the resulting work to be covered by
+# the GNU General Public License. Only Red Hat, Inc. may make changes or
+# additions to the list of Approved Interfaces. You must obey the GNU General
+# Public License in all respects for all of the Program code and other code used
+# in conjunction with the Program except the Non-GPL Code covered by this
+# exception. If you modify this file, you may extend this exception to your
+# version of the file, but you are not obligated to do so. If you do not wish to
+# provide this exception without modification, you must delete this exception
+# statement from your version and license this file solely under the GPL without
+# exception.
+#
+#
+# Copyright (C) 2011 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+#
+# Schema for Auto Membership Plugin
+#
+dn: cn=schema
+#
+################################################################################
+#
+attributeTypes: ( 2.16.840.1.113730.3.1.2097 NAME 'autoMemberScope'
+ DESC 'Auto Membership scope criteria'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ SINGLE-VALUE
+ X-ORIGIN '389 Directory Server' )
+#
+################################################################################
+#
+attributeTypes: ( 2.16.840.1.113730.3.1.2098 NAME 'autoMemberFilter'
+ DESC 'Auto Membership filter criteria'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ SINGLE-VALUE
+ X-ORIGIN '389 Directory Server' )
+#
+################################################################################
+#
+attributeTypes: ( 2.16.840.1.113730.3.1.2099 NAME 'autoMemberExclusiveRegex'
+ DESC 'Auto Membership exclusive regex rule'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ X-ORIGIN '389 Directory Server' )
+#
+################################################################################
+#
+attributeTypes: ( 2.16.840.1.113730.3.1.2100 NAME 'autoMemberInclusiveRegex'
+ DESC 'Auto Membership inclusive regex rule'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ X-ORIGIN '389 Directory Server' )
+#
+################################################################################
+#
+attributeTypes: ( 2.16.840.1.113730.3.1.2101 NAME 'autoMemberDefaultGroup'
+ DESC 'Auto Membership default group'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ X-ORIGIN '389 Directory Server' )
+#
+################################################################################
+#
+attributeTypes: ( 2.16.840.1.113730.3.1.2102 NAME 'autoMemberGroupingAttr'
+ DESC 'Auto Membership grouping attribute'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+ SINGLE-VALUE
+ X-ORIGIN '389 Directory Server' )
+#
+################################################################################
+#
+attributeTypes: ( 2.16.840.1.113730.3.1.2103 NAME 'autoMemberDisabled'
+ DESC 'Auto Membership disabled attribute'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ SINGLE-VALUE
+ X-ORIGIN '389 Directory Server' )
+#
+################################################################################
+#
+objectClasses: ( 2.16.840.1.113730.3.2.322 NAME 'autoMemberDefinition'
+ DESC 'Auto Membership Config Definition Entry'
+ SUP top
+ STRUCTURAL
+ MUST ( cn $ autoMemberScope $ autoMemberFilter $ autoMemberGroupingAttr )
+ MAY ( autoMemberExclusiveRegex $ autoMemberInclusiveRegex $ autoMemberDefaultGroup
+ $ autoMemberDisabled )
+ X-ORIGIN '389 Directory Server' )
diff --git a/ldap/servers/plugins/automember/automember.c b/ldap/servers/plugins/automember/automember.c
new file mode 100644
index 0000000..89b492a
--- /dev/null
+++ b/ldap/servers/plugins/automember/automember.c
@@ -0,0 +1,1842 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/*
+ * Auto Membership Plug-in
+ */
+#include "automember.h"
+
+
+/*
+ * Plug-in globals
+ */
+static PRCList *g_automember_config = NULL;
+static PRRWLock *g_automember_config_lock;
+
+static void *_PluginID = NULL;
+static char *_PluginDN = NULL;
+static char *_ConfigAreaDN = NULL;
+static int g_plugin_started = 0;
+
+static Slapi_PluginDesc pdesc = { AUTOMEMBER_FEATURE_DESC,
+ VENDOR,
+ DS_PACKAGE_VERSION,
+ AUTOMEMBER_PLUGIN_DESC };
+
+/*
+ * Plug-in management functions
+ */
+int automember_init(Slapi_PBlock * pb);
+static int automember_start(Slapi_PBlock * pb);
+static int automember_close(Slapi_PBlock * pb);
+static int automember_postop_init(Slapi_PBlock * pb);
+static int automember_internal_postop_init(Slapi_PBlock *pb);
+
+/*
+ * Operation callbacks (where the real work is done)
+ */
+static int automember_mod_post_op(Slapi_PBlock *pb);
+static int automember_add_post_op(Slapi_PBlock *pb);
+static int automember_del_post_op(Slapi_PBlock *pb);
+static int automember_modrdn_post_op(Slapi_PBlock *pb);
+static int automember_pre_op(Slapi_PBlock *pb, int modop);
+static int automember_mod_pre_op(Slapi_PBlock *pb);
+static int automember_add_pre_op(Slapi_PBlock *pb);
+
+/*
+ * Config cache management functions
+ */
+static int automember_load_config();
+static void automember_delete_config();
+static int automember_parse_config_entry(Slapi_Entry * e, int apply);
+static void automember_free_config_entry(struct configEntry ** entry);
+
+/*
+ * helpers
+ */
+static char *automember_get_dn(Slapi_PBlock * pb);
+static char *automember_get_config_area();
+static void automember_set_config_area(char *dn);
+static int automember_dn_is_config(char *dn);
+static int automember_oktodo(Slapi_PBlock *pb);
+static int automember_isrepl(Slapi_PBlock *pb);
+static struct automemberRegexRule *automember_parse_regex_rule(char *rule_string);
+static void automember_free_regex_rule(struct automemberRegexRule *rule);
+static int automember_parse_grouping_attr(char *value, char **grouping_attr,
+ char **grouping_value);
+static void automember_update_membership(struct configEntry *config, Slapi_Entry *e);
+static void automember_add_member_value(Slapi_Entry *member_e, const char *group_dn,
+ char *grouping_attr, char *grouping_value);
+
+/*
+ * Config cache locking functions
+ */
+void
+automember_config_read_lock()
+{
+ PR_RWLock_Rlock(g_automember_config_lock);
+}
+
+void
+automember_config_write_lock()
+{
+ PR_RWLock_Wlock(g_automember_config_lock);
+}
+
+void
+automember_config_unlock()
+{
+ PR_RWLock_Unlock(g_automember_config_lock);
+}
+
+
+/*
+ * Plugin identity functions
+ */
+void
+automember_set_plugin_id(void *pluginID)
+{
+ _PluginID = pluginID;
+}
+
+void *
+automember_get_plugin_id()
+{
+ return _PluginID;
+}
+
+void
+automember_set_plugin_dn(char *pluginDN)
+{
+ _PluginDN = pluginDN;
+}
+
+char *
+automember_get_plugin_dn()
+{
+ return _PluginDN;
+}
+
+
+/*
+ * Plug-in initialization functions
+ */
+int
+automember_init(Slapi_PBlock *pb)
+{
+ int status = 0;
+ char *plugin_identity = NULL;
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "--> automember_init\n");
+
+ /* Store the plugin identity for later use.
+ * Used for internal operations. */
+ slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &plugin_identity);
+ PR_ASSERT(plugin_identity);
+ automember_set_plugin_id(plugin_identity);
+
+ /* Register callbacks */
+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
+ SLAPI_PLUGIN_VERSION_01) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
+ (void *) automember_start) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
+ (void *) automember_close) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
+ (void *) &pdesc) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_MODIFY_FN,
+ (void *) automember_mod_pre_op) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ADD_FN,
+ (void *) automember_add_pre_op) != 0 ||
+ slapi_register_plugin("internalpostoperation", /* op type */
+ 1, /* Enabled */
+ "automember_init", /* this function desc */
+ automember_internal_postop_init, /* init func */
+ AUTOMEMBER_INT_POSTOP_DESC, /* plugin desc */
+ NULL, /* ? */
+ plugin_identity /* access control */
+ ) ||
+ slapi_register_plugin("postoperation", /* op type */
+ 1, /* Enabled */
+ "automember_init", /* this function desc */
+ automember_postop_init, /* init func for post op */
+ AUTOMEMBER_POSTOP_DESC, /* plugin desc */
+ NULL, /* ? */
+ plugin_identity /* access control */
+ )
+ ) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_init: failed to register plugin\n");
+ status = -1;
+ }
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "<-- automember_init\n");
+ return status;
+}
+
+static int
+automember_internal_postop_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, SLAPI_PLUGIN_INTERNAL_POST_ADD_FN,
+ (void *) automember_add_post_op) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN,
+ (void *) automember_del_post_op) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN,
+ (void *) automember_mod_post_op) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN,
+ (void *) automember_modrdn_post_op) != 0) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_internal_postop_init: failed to register plugin\n");
+ status = -1;
+ }
+
+ return status;
+}
+
+static int
+automember_postop_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, SLAPI_PLUGIN_POST_ADD_FN,
+ (void *) automember_add_post_op) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN,
+ (void *) automember_del_post_op) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN,
+ (void *) automember_mod_post_op) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN,
+ (void *) automember_modrdn_post_op) != 0) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_postop_init: failed to register plugin\n");
+ status = -1;
+ }
+
+ return status;
+}
+
+
+/* Stash the config area in the pblock for start functions? */
+/*
+ * automember_start()
+ *
+ * Creates config lock and loads config cache.
+ */
+static int
+automember_start(Slapi_PBlock * pb)
+{
+ char *plugindn = NULL;
+ char *config_area = NULL;
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "--> automember_start\n");
+
+ /* Check if we're already started */
+ if (g_plugin_started) {
+ goto done;
+ }
+
+ g_automember_config_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "automember_config");
+
+ if (!g_automember_config_lock) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_start: lock creation failed\n");
+
+ return -1;
+ }
+
+ /*
+ * Get the plug-in target dn from the system
+ * and store it for future use. */
+ slapi_pblock_get(pb, SLAPI_TARGET_DN, &plugindn);
+ if (NULL == plugindn || 0 == strlen(plugindn)) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_start: unable to retrieve plugin dn\n");
+ return -1;
+ }
+
+ automember_set_plugin_dn(plugindn);
+
+ /* Set the alternate config area if one is defined. */
+ slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_AREA, &config_area);
+ if (config_area) {
+ automember_set_config_area(slapi_ch_strdup(config_area));
+ }
+
+ /*
+ * Load the config cache
+ */
+ g_automember_config = (PRCList *)slapi_ch_calloc(1, sizeof(struct configEntry));
+ PR_INIT_CLIST(g_automember_config);
+
+ if (automember_load_config() != 0) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_start: unable to load plug-in configuration\n");
+ return -1;
+ }
+
+ g_plugin_started = 1;
+ slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "auto membership plug-in: ready for service\n");
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "<-- automember_start\n");
+
+done:
+ return 0;
+}
+
+/*
+ * automember_close()
+ *
+ * Cleans up the config cache.
+ */
+static int
+automember_close(Slapi_PBlock * pb)
+{
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "--> automember_close\n");
+
+ if (!g_plugin_started) {
+ goto done;
+ }
+
+ automember_delete_config();
+
+ slapi_ch_free((void **)&g_automember_config);
+ slapi_ch_free_string(&_ConfigAreaDN);
+
+ if (g_automember_config_lock) {
+ PR_DestroyRWLock(g_automember_config_lock);
+ }
+
+done:
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "<-- automember_close\n");
+
+ return 0;
+}
+
+/*
+ * automember_get_config()
+ *
+ * Get the config list.
+ */
+PRCList *
+automember_get_config()
+{
+ return g_automember_config;
+}
+
+/*
+ * automember_load_config()
+ *
+ * Parse and load the config entries.
+ */
+static int
+automember_load_config()
+{
+ int status = 0;
+ int result;
+ int i;
+ Slapi_PBlock *search_pb;
+ Slapi_Entry **entries = NULL;
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "--> automember_load_config\n");
+
+ /* Clear out any old config. */
+ automember_config_write_lock();
+ automember_delete_config();
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_load_config: Looking for config entries "
+ "beneath \"%s\".\n", automember_get_plugin_dn());
+
+ /* Find the config entries beneath our plugin entry. */
+ search_pb = slapi_pblock_new();
+ slapi_search_internal_set_pb(search_pb, automember_get_plugin_dn(),
+ LDAP_SCOPE_SUBTREE, "objectclass=*",
+ NULL, 0, NULL, NULL, automember_get_plugin_id(), 0);
+ slapi_search_internal_pb(search_pb);
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
+
+ if (LDAP_SUCCESS != result) {
+ status = -1;
+ goto cleanup;
+ }
+
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
+ &entries);
+
+ /* Loop through all of the entries we found and parse them. */
+ for (i = 0; entries && (entries[i] != NULL); i++) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_load_config: parsing config entry "
+ "\"%s\".\n", slapi_entry_get_dn(entries[i]));
+ /* We don't care about the status here because we may have
+ * some invalid config entries, but we just want to continue
+ * looking for valid ones. */
+ automember_parse_config_entry(entries[i], 1);
+ }
+
+ /* If an alternate config area is configured, find
+ * the config entries that are beneath it. */
+ if (automember_get_config_area()) {
+ /* Clean up the previous search results
+ * and clear out the pblock for reuse. */
+ slapi_free_search_results_internal(search_pb);
+ slapi_pblock_init(search_pb);
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_load_config: Looking for config entries "
+ "beneath \"%s\".\n", automember_get_config_area());
+
+ slapi_search_internal_set_pb(search_pb, automember_get_config_area(),
+ LDAP_SCOPE_SUBTREE, "objectclass=*",
+ NULL, 0, NULL, NULL, automember_get_plugin_id(), 0);
+ slapi_search_internal_pb(search_pb);
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
+
+ if ((LDAP_SUCCESS != result) && (LDAP_NO_SUCH_OBJECT != result)) {
+ status = -1;
+ goto cleanup;
+ }
+
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
+ &entries);
+
+ /* Loop through all of the entries we found and parse them. */
+ for (i = 0; entries && (entries[i] != NULL); i++) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_load_config: parsing config entry "
+ "\"%s\".\n", slapi_entry_get_dn(entries[i]));
+
+ /* We don't care about the status here because we may have
+ * some invalid config entries, but we just want to continue
+ * looking for valid ones. */
+ automember_parse_config_entry(entries[i], 1);
+ }
+ }
+
+ cleanup:
+ slapi_free_search_results_internal(search_pb);
+ slapi_pblock_destroy(search_pb);
+ automember_config_unlock();
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "<-- automember_load_config\n");
+
+ return status;
+}
+
+/*
+ * automember_parse_config_entry()
+ *
+ * Parses a single config entry. If apply is non-zero, then
+ * we will load and start using the new config. You can simply
+ * validate config without making any changes by setting apply
+ * to 0.
+ *
+ * Returns 0 if the entry is valid and -1 if it is invalid.
+ */
+static int
+automember_parse_config_entry(Slapi_Entry * e, int apply)
+{
+ char *value = NULL;
+ char **values = NULL;
+ struct configEntry *entry = NULL;
+ struct configEntry *config_entry;
+ PRCList *list;
+ int entry_added = 0;
+ int i = 0;
+ int ret = 0;
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "--> automember_parse_config_entry\n");
+
+ /* If this is the main plug-in config entry or
+ * the config area container, just bail. */
+ if ((strcasecmp(automember_get_plugin_dn(), slapi_entry_get_ndn(e)) == 0) ||
+ (automember_get_config_area() && (strcasecmp(automember_get_config_area(),
+ slapi_entry_get_ndn(e)) == 0))) {
+ goto bail;
+ }
+
+ /* If marked as disabled, just bail. */
+ value = slapi_entry_attr_get_charptr(e, AUTOMEMBER_DISABLED_TYPE);
+ if (value) {
+ slapi_ch_free_string(&value);
+ goto bail;
+ }
+
+ entry = (struct configEntry *)slapi_ch_calloc(1, sizeof(struct configEntry));
+ if (NULL == entry) {
+ ret = -1;
+ goto bail;
+ }
+
+ value = slapi_entry_get_ndn(e);
+ if (value) {
+ entry->dn = slapi_ch_strdup(value);
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_config_entry: Error "
+ "reading dn from config entry\n");
+ ret = -1;
+ goto bail;
+ }
+
+ slapi_log_error(SLAPI_LOG_CONFIG, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "----------> dn [%s]\n", entry->dn);
+
+ /* Load the scope */
+ value = slapi_entry_attr_get_charptr(e, AUTOMEMBER_SCOPE_TYPE);
+ if (value) {
+ entry->scope = value;
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_config_entry: The %s config "
+ "setting is required for config entry \"%s\".\n",
+ AUTOMEMBER_SCOPE_TYPE, entry->dn);
+ ret = -1;
+ goto bail;
+ }
+
+ /* Load the filter */
+ value = slapi_entry_attr_get_charptr(e, AUTOMEMBER_FILTER_TYPE);
+ if (value) {
+ /* Convert to a Slapi_Filter to improve performance. */
+ if (NULL == (entry->filter = slapi_str2filter(value))) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM ,
+ "automember_parse_config_entry: Invalid search filter in "
+ "%s config setting for config entry \"%s\" "
+ "(filter = \"%s\").\n", AUTOMEMBER_FILTER_TYPE, entry->dn, value);
+ ret = -1;
+ }
+
+ slapi_ch_free_string(&value);
+
+ if (ret != 0) {
+ goto bail;
+ }
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_config_entry: The %s config "
+ "setting is required for config entry \"%s\".\n",
+ AUTOMEMBER_FILTER_TYPE, entry->dn);
+ ret = -1;
+ goto bail;
+ }
+
+ /* Load exclusive regex rules */
+ values = slapi_entry_attr_get_charray(e, AUTOMEMBER_EXC_REGEX_TYPE);
+ if (values) {
+ struct automemberRegexRule *rule = NULL;
+
+ /* Create a list to hold our regex rules */
+ entry->exclusive_rules = (struct automemberRegexRule *)slapi_ch_calloc(1, sizeof(struct automemberRegexRule));
+ PR_INIT_CLIST((PRCList *)entry->exclusive_rules);
+
+ /* Parse each regex rule and add to the list */
+ for (i = 0; values && values[i]; ++i) {
+ rule = automember_parse_regex_rule(values[i]);
+ if (rule) {
+ if (!PR_CLIST_IS_EMPTY((PRCList *)entry->exclusive_rules)) {
+ list = PR_LIST_HEAD((PRCList *)entry->exclusive_rules);
+ while (list != (PRCList *)entry->exclusive_rules) {
+ struct automemberRegexRule *curr_rule = (struct automemberRegexRule *)list;
+ /* Order rules by target group DN */
+ if (strcmp(slapi_sdn_get_dn(rule->target_group_dn),
+ slapi_sdn_get_dn(curr_rule->target_group_dn)) < 0) {
+ PR_INSERT_BEFORE(&(rule->list), list);
+ break;
+ }
+
+ list = PR_NEXT_LINK(list);
+
+ /* If we hit the end of the list, add to the tail. */
+ if ((PRCList *)entry->exclusive_rules == list) {
+ PR_INSERT_BEFORE(&(rule->list), list);
+ break;
+ }
+ }
+ } else {
+ /* Add to head of list */
+ PR_INSERT_LINK(&(rule->list), (PRCList *)entry->exclusive_rules);
+ }
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_config_entry: Invalid exclusive "
+ "regex rule in config entry \"%s\" (rule = \"%s\").\n",
+ entry->dn, values[i]);
+ ret = -1;
+ }
+ }
+ slapi_ch_array_free(values);
+ values = NULL;
+
+ /* Bail if we had a bad regex rule */
+ if (ret == -1) {
+ goto bail;
+ }
+ }
+
+ /* Load inclusive regex rules */
+ values = slapi_entry_attr_get_charray(e, AUTOMEMBER_INC_REGEX_TYPE);
+ if (values) {
+ struct automemberRegexRule *rule = NULL;
+
+ /* Create a list to hold our regex rules */
+ entry->inclusive_rules = (struct automemberRegexRule *)slapi_ch_calloc(1, sizeof(struct automemberRegexRule));
+ PR_INIT_CLIST((PRCList *)entry->inclusive_rules);
+
+ /* Parse each regex rule and add to the list */
+ for (i = 0; values && values[i]; ++i) {
+ rule = automember_parse_regex_rule(values[i]);
+ if (rule) {
+ if (!PR_CLIST_IS_EMPTY((PRCList *)entry->inclusive_rules)) {
+ list = PR_LIST_HEAD((PRCList *)entry->inclusive_rules);
+ while (list != (PRCList *)entry->inclusive_rules) {
+ struct automemberRegexRule *curr_rule = (struct automemberRegexRule *)list;
+ /* Order rules by target group DN */
+ if (strcmp(slapi_sdn_get_dn(rule->target_group_dn),
+ slapi_sdn_get_dn(curr_rule->target_group_dn)) < 0) {
+ PR_INSERT_BEFORE(&(rule->list), list);
+ break;
+ }
+
+ list = PR_NEXT_LINK(list);
+
+ /* If we hit the end of the list, add to the tail. */
+ if ((PRCList *)entry->inclusive_rules == list) {
+ PR_INSERT_BEFORE(&(rule->list), list);
+ break;
+ }
+ }
+ } else {
+ /* Add to head of list */
+ PR_INSERT_LINK(&(rule->list), (PRCList *)entry->inclusive_rules);
+ }
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_config_entry: Invalid inclusive "
+ "regex rule in config entry \"%s\" (rule = \"%s\").\n",
+ entry->dn, values[i]);
+ ret = -1;
+ }
+ }
+ slapi_ch_array_free(values);
+ values = NULL;
+ }
+
+ /* Load the default groups */
+ values = slapi_entry_attr_get_charray(e, AUTOMEMBER_DEFAULT_GROUP_TYPE);
+ if (values) {
+ /* Just hand off the values */
+ entry->default_groups = values;
+ values = NULL;
+ }
+
+ /* Load the grouping attr */
+ value = slapi_entry_attr_get_charptr(e, AUTOMEMBER_GROUPING_ATTR_TYPE);
+ if (value) {
+ if (automember_parse_grouping_attr(value, &(entry->grouping_attr),
+ &(entry->grouping_value)) != 0) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_config_entry: Invalid "
+ "%s config setting for config entry \"%s\" "
+ "(value: \"%s\").\n", AUTOMEMBER_GROUPING_ATTR_TYPE,
+ entry->dn, value);
+ ret = -1;
+ }
+
+ slapi_ch_free_string(&value);
+ if (ret != 0) {
+ goto bail;
+ }
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_config_entry: The %s config "
+ "setting is required for config entry \"%s\".\n",
+ AUTOMEMBER_GROUPING_ATTR_TYPE, entry->dn);
+ ret = -1;
+ goto bail;
+ }
+
+ /* If we were only called to validate config, we can
+ * just bail out before applying the config changes */
+ if (apply == 0) {
+ goto bail;
+ }
+
+ /* Add the config object to the list. We order by scope. */
+ if (!PR_CLIST_IS_EMPTY(g_automember_config)) {
+ list = PR_LIST_HEAD(g_automember_config);
+ while (list != g_automember_config) {
+ config_entry = (struct configEntry *) list;
+
+ /* If the config entry we are adding has a scope that is
+ * a child of the scope of the current list item, we insert
+ * the entry before that list item. */
+ if (slapi_dn_issuffix(entry->scope, config_entry->scope)) {
+ PR_INSERT_BEFORE(&(entry->list), list);
+ slapi_log_error(SLAPI_LOG_CONFIG, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "store [%s] before [%s] \n", entry->dn,
+ config_entry->dn);
+
+ entry_added = 1;
+ break;
+ }
+
+ list = PR_NEXT_LINK(list);
+
+ /* If we hit the end of the list, add to the tail. */
+ if (g_automember_config == list) {
+ PR_INSERT_BEFORE(&(entry->list), list);
+ slapi_log_error(SLAPI_LOG_CONFIG, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "store [%s] at tail\n", entry->dn);
+
+ entry_added = 1;
+ break;
+ }
+ }
+ } else {
+ /* first entry */
+ PR_INSERT_LINK(&(entry->list), g_automember_config);
+ slapi_log_error(SLAPI_LOG_CONFIG, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "store [%s] at head \n", entry->dn);
+
+ entry_added = 1;
+ }
+
+ bail:
+ if (0 == entry_added) {
+ /* Don't log error if we weren't asked to apply config */
+ if ((apply != 0) && (entry != NULL)) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_config_entry: Invalid config entry "
+ "[%s] skipped\n", entry->dn);
+ }
+ automember_free_config_entry(&entry);
+ } else {
+ ret = 0;
+ }
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "<-- automember_parse_config_entry\n");
+
+ return ret;
+}
+
+static void
+automember_free_config_entry(struct configEntry ** entry)
+{
+ struct configEntry *e = *entry;
+
+ if (e == NULL)
+ return;
+
+ if (e->dn) {
+ slapi_log_error(SLAPI_LOG_CONFIG, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "freeing config entry [%s]\n", e->dn);
+ slapi_ch_free_string(&e->dn);
+ }
+
+ if (e->scope) {
+ slapi_ch_free_string(&e->scope);
+ }
+
+ if (e->filter) {
+ slapi_filter_free(e->filter, 1);
+ }
+
+ if (e->exclusive_rules) {
+ PRCList *list;
+
+ /* Clear out the list contents. */
+ while (!PR_CLIST_IS_EMPTY((PRCList *)e->exclusive_rules)) {
+ list = PR_LIST_HEAD((PRCList *)e->exclusive_rules);
+ PR_REMOVE_LINK(list);
+ automember_free_regex_rule((struct automemberRegexRule *)list);
+ }
+
+ /* Free the list itself. */
+ slapi_ch_free((void **)&(e->exclusive_rules));
+ }
+
+ /* Clear out the list contents. */
+ if (e->inclusive_rules) {
+ PRCList *list;
+
+ while (!PR_CLIST_IS_EMPTY((PRCList *)e->inclusive_rules)) {
+ list = PR_LIST_HEAD((PRCList *)e->inclusive_rules);
+ PR_REMOVE_LINK(list);
+ automember_free_regex_rule((struct automemberRegexRule *)list);
+ }
+
+ /* Free the list itself. */
+ slapi_ch_free((void **)&(e->inclusive_rules));
+ }
+
+ if (e->default_groups) {
+ slapi_ch_array_free(e->default_groups);
+ }
+
+ if (e->grouping_attr) {
+ slapi_ch_free_string(&e->grouping_attr);
+ }
+
+ if (e->grouping_value) {
+ slapi_ch_free_string(&e->grouping_value);
+ }
+
+ slapi_ch_free((void **)entry);
+}
+
+static void
+automember_delete_configEntry(PRCList *entry)
+{
+ PR_REMOVE_LINK(entry);
+ automember_free_config_entry((struct configEntry **) &entry);
+}
+
+static void
+automember_delete_config()
+{
+ PRCList *list;
+
+ /* Delete the config cache. */
+ while (!PR_CLIST_IS_EMPTY(g_automember_config)) {
+ list = PR_LIST_HEAD(g_automember_config);
+ automember_delete_configEntry(list);
+ }
+
+ return;
+}
+
+
+/*
+ * Helper functions
+ */
+static char *
+automember_get_dn(Slapi_PBlock * pb)
+{
+ char *dn = 0;
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "--> automember_get_dn\n");
+
+ if (slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn)) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_get_dn: failed to get dn of changed entry");
+ goto bail;
+ }
+
+ bail:
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "<-- automember_get_dn\n");
+
+ return dn;
+}
+
+void
+automember_set_config_area(char *dn)
+{
+ _ConfigAreaDN = dn;
+}
+
+char *
+automember_get_config_area()
+{
+ return _ConfigAreaDN;
+}
+
+/*
+ * automember_dn_is_config()
+ *
+ * Checks if dn is an auto membership config entry.
+ */
+static int
+automember_dn_is_config(char *dn)
+{
+ int ret = 0;
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "--> automember_dn_is_config\n");
+
+ /* Return 1 if the passed in dn is a child of the main
+ * plugin config entry, or if it is a child of the
+ * container defined as a config area. */
+ if ((slapi_dn_issuffix(dn, automember_get_plugin_dn()) &&
+ strcasecmp(dn, automember_get_plugin_dn())) ||
+ (automember_get_config_area() && slapi_dn_issuffix(dn,
+ automember_get_config_area()))) {
+ ret = 1;
+ }
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "<-- automember_dn_is_config\n");
+
+ return ret;
+}
+
+/*
+ * automember_oktodo()
+ *
+ * Check if we want to process this operation. We need to be
+ * sure that the operation succeeded.
+ */
+static int
+automember_oktodo(Slapi_PBlock *pb)
+{
+ int ret = 1;
+ int oprc = 0;
+
+ slapi_log_error( SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "--> automember_oktodo\n" );
+
+ if(slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &oprc) != 0) {
+ slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_oktodo: could not get parameters\n" );
+ ret = -1;
+ }
+
+ /* This plugin should only execute if the operation succeeded. */
+ if(oprc != 0) {
+ ret = 0;
+ }
+
+ slapi_log_error( SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "<-- automember_oktodo\n" );
+
+ return ret;
+}
+
+/*
+ * automember_isrepl()
+ *
+ * Returns 1 if the operation associated with pb
+ * is a replicated op. Returns 0 otherwise.
+ */
+static int
+automember_isrepl(Slapi_PBlock *pb)
+{
+ int is_repl = 0;
+
+ slapi_log_error( SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "--> automember_isrepl\n" );
+
+ slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_repl);
+
+ slapi_log_error( SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "<-- automember_isrepl\n" );
+
+ return is_repl;
+}
+
+/*
+ * automember_parse_regex_rule()
+ *
+ * Parses a regex rule and returns a regex rule struct. The caller
+ * will need to free this struct when it is finished with it. If
+ * there is a problem parsing the regex rule, an error will be
+ * logged and NULL will be returned.
+ */
+static struct automemberRegexRule *
+automember_parse_regex_rule(char *rule_string)
+{
+ struct automemberRegexRule *rule = NULL;
+ Slapi_DN *target_group_dn = NULL;
+ char *desc = NULL;
+ char *attr = NULL;
+ Slapi_Regex *regex = NULL;
+ const char *recomp_result = NULL;
+ char *dn_string = NULL;
+ char *p = NULL;
+ char *p2 = NULL;
+
+ /* A rule is in the form "target:desc:attr=regex" */
+ /* Find the target group DN. */
+ if ((p = strchr(rule_string, ':')) == NULL) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_regex_rule: Unable to parse "
+ "regex rule (missing first ':' delimeter).\n");
+ goto bail;
+ }
+
+ /* Ensure the target group DN is not empty. */
+ if (p == rule_string) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_regex_rule: Unable to parse "
+ " regex rule (missing target group DN).\n");
+ goto bail;
+ }
+
+ if ((dn_string = strndup(rule_string, p - rule_string)) == NULL) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_regex_rule: Error allocating "
+ "memory.\n");
+ goto bail;
+ }
+
+ /* Ensure that the DN is valid. */
+ if (slapi_dn_syntax_check(NULL, dn_string, 1) != 0) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_regex_rule: Unable to parse "
+ " regex rule (invalid target group DN).\n");
+ slapi_cn_free_string(&dn_string);
+ goto bail;
+ }
+
+ /* Create a Slapi_DN. */
+ target_group_dn = slapi_sdn_new_dn_passin(dn_string);
+
+ /* Find the description. */
+ p++;
+ if (*p == '\0') {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_regex_rule: Unable to parse "
+ "regex rule (missing description).\n");
+ goto bail;
+ }
+
+ p2 = p;
+ if ((p = strchr(p2, ':')) == NULL) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_regex_rule: Unable to parse "
+ "regex rule (missing second ':' delimeter).\n");
+ goto bail;
+ }
+
+ /* We allow an empty description. */
+ if (p == p2) {
+ desc = slapi_ch_strdup("");
+ } else {
+ if ((desc = strndup(p2, p - p2)) == NULL) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_regex_rule: Unable to allocate "
+ "memory.\n");
+ goto bail;
+ }
+ }
+
+ /* Find the comparison attribute name. */
+ p++;
+ if (*p == '\0') {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_regex_rule: Unable to parse "
+ "regex rule (missing comparison attribute).\n");
+ goto bail;
+ }
+
+ p2 = p;
+ if ((p = strchr(p2, '=')) == NULL) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_regex_rule: Unable to parse "
+ "regex rule (missing '=' delimeter).\n");
+ goto bail;
+ }
+
+
+ if ((attr = strndup(p2, p - p2)) == NULL) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_regex_rule: Unable to allocate "
+ "memory.\n");
+ goto bail;
+ }
+
+ /* Validate the attribute. */
+ for (p2 = attr; p2 && (*p2 != '\0'); p2++) {
+ if (!IS_ATTRDESC_CHAR(*p2)) {
+ slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_regex_rule: Invalid comparison "
+ "attribute name \"%s\".\n", attr);
+ goto bail;
+ }
+ }
+
+ /* Find the regex. */
+ p++;
+ if (*p == '\0') {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_regex_rule: Unable to parse "
+ "regex rule (missing regex).\n");
+ goto bail;
+ }
+
+ /* Compile the regex to validate it. */
+ regex = slapi_re_comp(p, &recomp_result);
+ if (!regex) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_regex_rule: Unable to parse "
+ "regex rule (invalid regex). Error \"%s\".\n",
+ recomp_result?recomp_result:"unknown");
+ }
+
+ /* Validation has passed, so create the regex rule struct and fill it in.
+ * We hand off everything we have allocated. All of this will be free'd
+ * when the rule struct itself is freed. */
+ rule = (struct automemberRegexRule *)slapi_ch_calloc(1, sizeof(struct automemberRegexRule));
+ rule->target_group_dn = target_group_dn;
+ rule->desc = desc;
+ rule->attr = attr;
+ rule->regex_str = slapi_ch_strdup(p);
+ rule->regex = regex;
+
+bail:
+ /* Cleanup if we didn't successfully create a rule. */
+ if (!rule) {
+ slapi_sdn_free(&target_group_dn);
+ slapi_ch_free_string(&desc);
+ slapi_ch_free_string(&attr);
+ slapi_re_free(regex);
+ }
+
+ return rule;
+}
+
+/*
+ * automember_free_regex_rule()
+ *
+ * Frees a regex rule and all of it's contents from memory.
+ */
+static void
+automember_free_regex_rule(struct automemberRegexRule *rule)
+{
+ if (rule) {
+ if (rule->target_group_dn) {
+ slapi_sdn_free(&(rule->target_group_dn));
+ }
+
+ if (rule->desc) {
+ slapi_ch_free_string(&(rule->desc));
+ }
+
+ if (rule->attr) {
+ slapi_ch_free_string(&(rule->attr));
+ }
+
+ if (rule->regex_str) {
+ slapi_ch_free_string(&(rule->regex_str));
+ }
+
+ if (rule->regex) {
+ slapi_re_free(rule->regex);
+ }
+ }
+
+ slapi_ch_free((void **)&rule);
+}
+
+/*
+ * automember_parse_grouping_attr()
+ *
+ * Parses a grouping attribute and grouping value from
+ * the passed in config string. Memory will be allocated
+ * for grouping_attr and grouping_value, so it is up to
+ * the called to free them when they are no longer needed.
+ * Returns 0 upon success and 1 upon failure.
+ */
+static int
+automember_parse_grouping_attr(char *value, char **grouping_attr, char **grouping_value)
+{
+ int ret = 0;
+ char *p = NULL;
+
+ /* Clear out any existing type or value. */
+ slapi_ch_free_string(grouping_attr);
+ slapi_ch_free_string(grouping_value);
+
+ /* split out the type from the value (use the first ':') */
+ if ((p = strchr(value, ':')) == NULL) {
+ slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_grouping_attr: Value for grouping attribute "
+ "is not in the correct format. (value: \"%s\").\n", value);
+ ret = 1;
+ goto bail;
+ }
+
+ /* Ensure the type is not empty. */
+ if (p == value) {
+ slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_grouping_attr: Value for grouping attribute "
+ "is not in the correct format. The grouping attribute is missing. "
+ "(value: \"%s\").\n", value);
+ ret = 1;
+ goto bail;
+ }
+
+ /* Duplicate the type to be returned. */
+ *grouping_attr = strndup(value, p - value);
+
+ /* Advance p to point to the beginning of the value. */
+ p++;
+ while (*p == ' ') {
+ p++;
+ }
+
+ /* Ensure the value is not empty. */
+ if (*p == '\0') {
+ slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_grouping_attr: Value for grouping attribute "
+ "is not in the correct format. The grouping value is "
+ "missing. (value: \"%s\").\n", value);
+ ret = 1;
+ goto bail;
+ }
+
+ /* Duplicate the value to be returned. */
+ *grouping_value = slapi_ch_strdup(p);
+
+ /* Ensure that memory was allocated successfully. */
+ if ((*grouping_attr == NULL) || (*grouping_value == NULL)) {
+ slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_grouping_attr: Error allocating memory.\n");
+ ret = 1;
+ goto bail;
+ }
+
+ /* Ensure that the grouping attr is a legal attr name. */
+ for (p = *grouping_attr; p && (*p != '\0'); p++) {
+ if (!IS_ATTRDESC_CHAR(*p)) {
+ slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_grouping_attr: Invalid value for "
+ "grouping attribute. The grouping attribute type is "
+ "illegal. (type: \"%s\").\n", *grouping_attr);
+ ret = 1;
+ goto bail;
+ }
+ }
+
+ /* Ensure that the grouping value type is a legal attr name. */
+ for (p = *grouping_value; p && (*p != '\0'); p++) {
+ if (!IS_ATTRDESC_CHAR(*p)) {
+ slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_parse_grouping_attr: Invalid value for "
+ "grouping attribute. The grouping value type is "
+ "illegal. (type: \"%s\").\n", *grouping_value);
+ ret = 1;
+ goto bail;
+ }
+ }
+
+ bail:
+ if (ret != 0) {
+ slapi_ch_free_string(grouping_attr);
+ slapi_ch_free_string(grouping_value);
+ }
+
+ return ret;
+}
+
+/*
+ * automember_update_membership()
+ *
+ * Determines which target groups need to be updated according to
+ * the rules in config, then performs the updates.
+ */
+static void
+automember_update_membership(struct configEntry *config, Slapi_Entry *e)
+{
+ PRCList *rule = NULL;
+ struct automemberRegexRule *curr_rule = NULL;
+ PRCList exclusions;
+ PRCList targets;
+ struct automemberDNListItem *dnitem = NULL;
+ Slapi_DN *last = NULL;
+ PRCList *curr_exclusion = NULL;
+ char **vals = NULL;
+ int i = 0;
+
+ if (!config || !e) {
+ return;
+ }
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_update_membership: Processing \"%s\" "
+ "definition entry for candidate entry \"%s\".\n",
+ config->dn, slapi_entry_get_dn(e));
+
+ /* Initialize our lists that keep track of targets. */
+ PR_INIT_CLIST(&exclusions);
+ PR_INIT_CLIST(&targets);
+
+ /* Go through exclusive rules and build an exclusion list. */
+ if (config->exclusive_rules) {
+ if (!PR_CLIST_IS_EMPTY((PRCList *)config->exclusive_rules)) {
+ rule = PR_LIST_HEAD((PRCList *)config->exclusive_rules);
+ while (rule != (PRCList *)config->exclusive_rules) {
+ curr_rule = (struct automemberRegexRule *)rule;
+
+ /* Regex rules are sorted by the target group DN. This means
+ * we can skip all rules for the last target group DN that we
+ * added to the exclusions list. */
+ if ((last == NULL) || slapi_sdn_compare(last, curr_rule->target_group_dn) != 0) {
+ /* Get comparison attr and loop through values. */
+ vals = slapi_entry_attr_get_charray(e, curr_rule->attr);
+ for (i = 0; vals && vals[i]; ++i) {
+ /* Evaluate the regex. */
+ if (slapi_re_exec(curr_rule->regex, vals[i], -1) == 1) {
+ /* Found a match. Add to end of the exclusion list
+ * and set last as a hint to ourselves. */
+ slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_update_membership: Adding \"%s\" "
+ "to list of excluded groups for \"%s\" "
+ "(matched: \"%s=%s\").\n",
+ slapi_sdn_get_dn(curr_rule->target_group_dn),
+ slapi_entry_get_dn(e), curr_rule->attr,
+ curr_rule->regex_str);
+ dnitem = (struct automemberDNListItem *)slapi_ch_calloc(1,
+ sizeof(struct automemberDNListItem));
+ /* We are just referencing the dn from the regex rule. We
+ * will not free it when we clean up this list. This list
+ * is more short-lived than the regex rule list, so we can
+ * get away with this optimization. */
+ dnitem->dn = curr_rule->target_group_dn;
+ PR_APPEND_LINK(&(dnitem->list), &exclusions);
+ last = curr_rule->target_group_dn;
+ }
+ }
+
+ slapi_ch_array_free(vals);
+ vals = NULL;
+ }
+
+ rule = PR_NEXT_LINK(rule);
+ }
+ }
+ }
+
+ /* Go through inclusive rules and build the target list. */
+ if (config->inclusive_rules) {
+ if (!PR_CLIST_IS_EMPTY((PRCList *)config->inclusive_rules)) {
+ /* Clear out our last hint from processing exclusions. */
+ last = NULL;
+
+ /* Get the first excluded target for exclusion checking. */
+ if (!PR_CLIST_IS_EMPTY(&exclusions)) {
+ curr_exclusion = PR_LIST_HEAD(&exclusions);
+ }
+
+ rule = PR_LIST_HEAD((PRCList *)config->inclusive_rules);
+ while (rule != (PRCList *)config->inclusive_rules) {
+ curr_rule = (struct automemberRegexRule *)rule;
+
+ /* The excluded targets are stored in alphabetical order. Instead
+ * of going through the entire exclusion list for each inclusive
+ * rule, we can simply go through the exclusion list once and keep
+ * track of our position. If the curent exclusion comes after
+ * the target DN used in the current inclusive rule, it can't be
+ * excluded. If the current exclusion comes before the target
+ * in the current rule, we need to go through the exclusion list
+ * until we find a target that is the same or comes after the
+ * current rule. */
+ if (curr_exclusion) {
+ while ((curr_exclusion != &exclusions) && (strcmp(slapi_sdn_get_ndn(
+ ((struct automemberDNListItem *)curr_exclusion)->dn),
+ slapi_sdn_get_ndn(curr_rule->target_group_dn)) < 0)) {
+ curr_exclusion = PR_NEXT_LINK(curr_exclusion);
+ }
+ }
+
+ /* Regex rules are sorted by the target group DN. This means
+ * we can skip all rules for the last target group DN that we
+ * added to the targets list. We also skip any rules for
+ * target groups that have been excluded by an exclusion rule. */
+ if (((curr_exclusion == NULL) || (curr_exclusion == &exclusions) ||
+ slapi_sdn_compare(((struct automemberDNListItem *)curr_exclusion)->dn,
+ curr_rule->target_group_dn) != 0) && ((last == NULL) ||
+ (slapi_sdn_compare(last, curr_rule->target_group_dn) != 0))) {
+ /* Get comparison attr and loop through values. */
+ vals = slapi_entry_attr_get_charray(e, curr_rule->attr);
+ for (i = 0; vals && vals[i]; ++i) {
+ /* Evaluate the regex. */
+ if (slapi_re_exec(curr_rule->regex, vals[i], -1) == 1) {
+ /* Found a match. Add to the end of the targets list
+ * and set last as a hint to ourselves. */
+ slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_update_membership: Adding \"%s\" "
+ "to list of target groups for \"%s\" "
+ "(matched: \"%s=%s\").\n",
+ slapi_sdn_get_dn(curr_rule->target_group_dn),
+ slapi_entry_get_dn(e), curr_rule->attr,
+ curr_rule->regex_str);
+ dnitem = (struct automemberDNListItem *)slapi_ch_calloc(1,
+ sizeof(struct automemberDNListItem));
+ /* We are just referencing the dn from the regex rule. We
+ * will not free it when we clean up this list. This list
+ * is more short-lived than the regex rule list, so we can
+ * get away with this optimization. */
+ dnitem->dn = curr_rule->target_group_dn;
+ PR_APPEND_LINK(&(dnitem->list), &targets);
+ last = curr_rule->target_group_dn;
+ }
+ }
+
+ slapi_ch_array_free(vals);
+ vals = NULL;
+ }
+
+ rule = PR_NEXT_LINK(rule);
+ }
+ }
+ }
+
+ /* If no targets, update default groups if set. Otherwise, update
+ * targets. Use a helper to do the actual updates. We can just pass an
+ * array of target group DNs along with our entry DN, the grouping attr,
+ * and the grouping value. */
+ if (PR_CLIST_IS_EMPTY(&targets)) {
+ /* Add to each default group. */
+ for (i = 0; config->default_groups && config->default_groups[i]; i++) {
+ automember_add_member_value(e, config->default_groups[i],
+ config->grouping_attr, config->grouping_value);
+ }
+ } else {
+ /* Update the target groups. */
+ dnitem = (struct automemberDNListItem *)PR_LIST_HEAD(&targets);
+ while ((PRCList *)dnitem != &targets) {
+ automember_add_member_value(e, slapi_sdn_get_dn(dnitem->dn),
+ config->grouping_attr, config->grouping_value);
+ dnitem = (struct automemberDNListItem *)PR_NEXT_LINK((PRCList *)dnitem);
+ }
+ }
+
+ /* Free the exclusions and targets lists. Remember that the DN's
+ * are not ours, so don't free them! */
+ while (!PR_CLIST_IS_EMPTY(&exclusions)) {
+ dnitem = (struct automemberDNListItem *)PR_LIST_HEAD(&exclusions);
+ PR_REMOVE_LINK((PRCList *)dnitem);
+ slapi_ch_free((void**)&dnitem);
+ }
+
+ while (!PR_CLIST_IS_EMPTY(&targets)) {
+ dnitem = (struct automemberDNListItem *)PR_LIST_HEAD(&targets);
+ PR_REMOVE_LINK((PRCList *)dnitem);
+ slapi_ch_free((void**)&dnitem);
+ }
+
+}
+
+/*
+ * automember_add_member_value()
+ *
+ * Adds a member entry to a group.
+ */
+static void
+automember_add_member_value(Slapi_Entry *member_e, const char *group_dn,
+ char *grouping_attr, char *grouping_value)
+{
+ Slapi_PBlock *mod_pb = slapi_pblock_new();
+ int result = LDAP_SUCCESS;
+ LDAPMod mod;
+ LDAPMod *mods[2];
+ char *vals[2];
+ char *member_value = NULL;
+ int freeit = 0;
+
+ /* If grouping_value is dn, we need to fetch the dn instead. */
+ if (slapi_attr_type_cmp(grouping_value, "dn", SLAPI_TYPE_CMP_EXACT) == 0) {
+ member_value = slapi_entry_get_ndn(member_e);
+ } else {
+ member_value = slapi_entry_attr_get_charptr(member_e, grouping_value);
+ freeit = 1;
+ }
+
+ if (member_value) {
+ /* Set up the operation. */
+ vals[0] = member_value;
+ vals[1] = 0;
+ mod.mod_op = LDAP_MOD_ADD;
+ mod.mod_type = grouping_attr;
+ mod.mod_values = vals;
+ mods[0] = &mod;
+ mods[1] = 0;
+
+ /* Perform the modify operation. */
+ slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_add_member_value: Adding \"%s\" as "
+ "a \"%s\" value to group \"%s\".\n",
+ member_value, grouping_attr, group_dn);
+
+ slapi_modify_internal_set_pb(mod_pb, group_dn,
+ mods, 0, 0, automember_get_plugin_id(), 0);
+ slapi_modify_internal_pb(mod_pb);
+ slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
+
+ if ((result != LDAP_SUCCESS) && (result != LDAP_TYPE_OR_VALUE_EXISTS)) {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_add_member_value: Unable to add \"%s\" as "
+ "a \"%s\" value to group \"%s\" (%s).\n",
+ member_value, grouping_attr, group_dn,
+ ldap_err2string(result));
+ }
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_add_member_value: Unable to find grouping "
+ "value attribute \"%s\" in entry \"%s\".\n",
+ grouping_value, slapi_entry_get_dn(member_e));
+ }
+
+ /* Cleanup */
+ if (freeit) {
+ slapi_ch_free_string(&member_value);
+ }
+
+ slapi_pblock_destroy(mod_pb);
+}
+
+
+/*
+ * Operation callback functions
+ */
+
+/*
+ * automember_pre_op()
+ *
+ * Checks if an operation affects the auto membership
+ * config and validates the config changes.
+ */
+static int
+automember_pre_op(Slapi_PBlock * pb, int modop)
+{
+ char *dn = 0;
+ Slapi_Entry *e = 0;
+ Slapi_Mods *smods = 0;
+ LDAPMod **mods;
+ int free_entry = 0;
+ char *errstr = NULL;
+ int ret = 0;
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "--> automember_pre_op\n");
+
+ /* Just bail if we aren't ready to service requests yet. */
+ if (!g_plugin_started)
+ goto bail;
+
+ if (0 == (dn = automember_get_dn(pb)))
+ goto bail;
+
+ if (automember_dn_is_config(dn)) {
+ /* Validate config changes, but don't apply them.
+ * This allows us to reject invalid config changes
+ * here at the pre-op stage. Applying the config
+ * needs to be done at the post-op stage. */
+
+ if (LDAP_CHANGETYPE_ADD == modop) {
+ slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
+
+ } else if (LDAP_CHANGETYPE_MODIFY == modop) {
+ /* Fetch the entry being modified so we can
+ * create the resulting entry for validation. */
+ Slapi_DN *tmp_dn = slapi_sdn_new_dn_byref(dn);
+ if (tmp_dn) {
+ slapi_search_internal_get_entry(tmp_dn, 0, &e, automember_get_plugin_id());
+ slapi_sdn_free(&tmp_dn);
+ free_entry = 1;
+ }
+
+ /* If the entry doesn't exist, just bail and
+ * let the server handle it. */
+ if (e == NULL) {
+ goto bail;
+ }
+
+ /* Grab the mods. */
+ 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)) {
+ /* The mods don't apply cleanly, so we just let this op go
+ * to let the main server handle it. */
+ goto bailmod;
+ }
+ }
+
+ if (automember_parse_config_entry(e, 0) != 0) {
+ /* Refuse the operation if config parsing failed. */
+ ret = LDAP_UNWILLING_TO_PERFORM;
+ if (LDAP_CHANGETYPE_ADD == modop) {
+ errstr = slapi_ch_smprintf("Not a valid auto membership configuration entry.");
+ } else {
+ errstr = slapi_ch_smprintf("Changes result in an invalid "
+ "auto membership configuration.");
+ }
+ }
+ }
+
+ bailmod:
+ /* Clean up smods. */
+ if (LDAP_CHANGETYPE_MODIFY == modop) {
+ slapi_mods_free(&smods);
+ }
+
+ bail:
+ if (free_entry && e)
+ slapi_entry_free(e);
+
+ if (ret) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_pre_op: operation failure [%d]\n", ret);
+ slapi_send_ldap_result(pb, ret, NULL, errstr, 0, NULL);
+ slapi_ch_free((void **)&errstr);
+ ret = -1;
+ }
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "<-- automember_pre_op\n");
+
+ return ret;
+}
+
+static int
+automember_add_pre_op(Slapi_PBlock * pb)
+{
+ return automember_pre_op(pb, LDAP_CHANGETYPE_ADD);
+}
+
+static int
+automember_mod_pre_op(Slapi_PBlock * pb)
+{
+ return automember_pre_op(pb, LDAP_CHANGETYPE_MODIFY);
+}
+
+/*
+ * automember_mod_post_op()
+ *
+ * Reloads the auto membership config
+ * if config changes were made.
+ */
+static int
+automember_mod_post_op(Slapi_PBlock *pb)
+{
+ Slapi_Mods *smods = NULL;
+ char *dn = NULL;
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "--> automember_mod_post_op\n");
+
+ /* Just bail if we aren't ready to service requests yet. */
+ if (!g_plugin_started)
+ return 0;
+
+ if (automember_oktodo(pb) && (dn = automember_get_dn(pb))) {
+ /* Check if the config is being modified and reload if so. */
+ if (automember_dn_is_config(dn)) {
+ automember_load_config();
+ }
+ }
+
+ bail:
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "<-- automember_mod_post_op\n");
+
+ return 0;
+}
+
+static int
+automember_add_post_op(Slapi_PBlock *pb)
+{
+ Slapi_Entry *e = NULL;
+ char *dn = NULL;
+ struct configEntry *config = NULL;
+ PRCList *list = NULL;
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "--> automember_add_post_op\n");
+
+ /* Just bail if we aren't ready to service requests yet. */
+ if (!g_plugin_started || !automember_oktodo(pb))
+ return 0;
+
+ /* Reload config if a config entry was added. */
+ if ((dn = automember_get_dn(pb))) {
+ if (automember_dn_is_config(dn)) {
+ automember_load_config();
+ }
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_add_post_op: Error "
+ "retrieving dn\n");
+ }
+
+ /* If replication, just bail. */
+ if (automember_isrepl(pb)) {
+ return 0;
+ }
+
+ /* Get the newly added entry. */
+ slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &e);
+
+ if (e) {
+ /* If the entry is a tombstone, just bail. */
+ if (slapi_entry_attr_hasvalue(e, SLAPI_ATTR_OBJECTCLASS,
+ SLAPI_ATTR_VALUE_TOMBSTONE)) {
+ return 0;
+ }
+
+ /* Check if a config entry applies
+ * to the entry being added. */
+ automember_config_read_lock();
+
+ if (!PR_CLIST_IS_EMPTY(g_automember_config)) {
+ list = PR_LIST_HEAD(g_automember_config);
+ while (list != g_automember_config) {
+ config = (struct configEntry *)list;
+
+ /* Does the entry meet scope and filter requirements? */
+ if (slapi_dn_issuffix(dn, config->scope) &&
+ (slapi_filter_test_simple(e, config->filter) == 0)) {
+ /* Find out what membership changes are needed and make them. */
+ automember_update_membership(config, e);
+ }
+
+ list = PR_NEXT_LINK(list);
+ }
+ }
+
+ automember_config_unlock();
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_add_post_op: Error "
+ "retrieving post-op entry %s\n", dn);
+ }
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "<-- automember_add_post_op\n");
+
+ return 0;
+}
+
+/*
+ * automember_del_post_op()
+ *
+ * Removes deleted config.
+ */
+static int
+automember_del_post_op(Slapi_PBlock *pb)
+{
+ char *dn = NULL;
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "--> automember_del_post_op\n");
+
+ /* Just bail if we aren't ready to service requests yet. */
+ if (!g_plugin_started || !automember_oktodo(pb)) {
+ return 0;
+ }
+
+ /* Reload config if a config entry was deleted. */
+ if ((dn = automember_get_dn(pb))) {
+ if (automember_dn_is_config(dn))
+ automember_load_config();
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_del_post_op: Error "
+ "retrieving dn\n");
+ }
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "<-- automember_del_post_op\n");
+
+ return 0;
+}
+
+/*
+ * automember_modrdn_post_op()
+ *
+ * Reloads config if config entries move
+ * into or out of our config scope.
+ */
+static int
+automember_modrdn_post_op(Slapi_PBlock *pb)
+{
+ char *old_dn = NULL;
+ char *new_dn = NULL;
+ Slapi_Entry *post_e = NULL;
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "--> automember_modrdn_post_op\n");
+
+ /* Just bail if we aren't ready to service requests yet. */
+ if (!g_plugin_started || !automember_oktodo(pb))
+ return 0;;
+
+ /* Reload config if an existing config entry was renamed,
+ * or if the new dn brings an entry into the scope of the
+ * config entries. */
+ slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &post_e);
+ if (post_e) {
+ new_dn = slapi_entry_get_ndn(post_e);
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_modrdn_post_op: Error "
+ "retrieving post-op entry\n");
+ return 0;
+ }
+
+ if ((old_dn = automember_get_dn(pb))) {
+ if (automember_dn_is_config(old_dn) || automember_dn_is_config(new_dn))
+ automember_load_config();
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "automember_modrdn_post_op: Error "
+ "retrieving dn\n");
+ }
+
+ slapi_log_error(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "<-- automember_modrdn_post_op\n");
+
+ return 0;
+}
+
diff --git a/ldap/servers/plugins/automember/automember.h b/ldap/servers/plugins/automember/automember.h
new file mode 100644
index 0000000..979de92
--- /dev/null
+++ b/ldap/servers/plugins/automember/automember.h
@@ -0,0 +1,128 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/*
+ * Auto Membership plug-in header file
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+#include "portable.h"
+#include "nspr.h"
+#include "slapi-plugin.h"
+#include "prclist.h"
+#include "ldif.h"
+
+/*
+ * Plug-in defines
+ */
+#define AUTOMEMBER_PLUGIN_SUBSYSTEM "auto-membership-plugin"
+#define AUTOMEMBER_FEATURE_DESC "Auto Membership"
+#define AUTOMEMBER_PLUGIN_DESC "Auto Membership plugin"
+#define AUTOMEMBER_INT_POSTOP_DESC "Auto Membership internal postop plugin"
+#define AUTOMEMBER_POSTOP_DESC "Auto Membership postop plugin"
+
+/*
+ * Config type defines
+ */
+#define AUTOMEMBER_SCOPE_TYPE "autoMemberScope"
+#define AUTOMEMBER_FILTER_TYPE "autoMemberFilter"
+#define AUTOMEMBER_EXC_REGEX_TYPE "autoMemberExclusiveRegex"
+#define AUTOMEMBER_INC_REGEX_TYPE "autoMemberInclusiveRegex"
+#define AUTOMEMBER_DEFAULT_GROUP_TYPE "autoMemberDefaultGroup"
+#define AUTOMEMBER_GROUPING_ATTR_TYPE "autoMemberGroupingAttr"
+#define AUTOMEMBER_DISABLED_TYPE "autoMemberDisabled"
+
+/*
+ * Helper defines
+ */
+#define IS_ATTRDESC_CHAR(c) ( isalnum(c) || (c == '.') || (c == ';') || (c == '-') )
+
+struct automemberRegexRule {
+ PRCList list;
+ Slapi_DN *target_group_dn;
+ char *desc;
+ char *attr;
+ char *regex_str;
+ Slapi_Regex *regex;
+};
+
+struct automemberDNListItem {
+ PRCList list;
+ Slapi_DN *dn;
+};
+
+/*
+ * Linked list of config entries.
+ */
+struct configEntry {
+ PRCList list;
+ char *dn;
+ char *scope;
+ Slapi_Filter *filter;
+ struct automemberRegexRule *exclusive_rules;
+ struct automemberRegexRule *inclusive_rules;
+ char **default_groups;
+ char *grouping_attr;
+ char *grouping_value;
+};
+
+/*
+ * Config fetch function
+ */
+PRCList *automember_get_config();
+
+/*
+ * Config cache locking functions
+ */
+void automember_config_read_lock();
+void automember_config_write_lock();
+void automember_config_unlock();
+
+/*
+ * Plugin identity functions
+ */
+void automember_set_plugin_id(void *pluginID);
+void *automember_get_plugin_id();
+void automember_set_plugin_dn(char *pluginDN);
+char *automember_get_plugin_dn();
+
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index 6bc2375..215b7df 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -499,6 +499,9 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
case SLAPI_PLUGIN_IDENTITY:
(*(void**)value) = pblock->pb_plugin_identity;
break;
+ case SLAPI_PLUGIN_CONFIG_AREA:
+ (*(char **)value) = pblock->pb_plugin_config_area;
+ break;
case SLAPI_PLUGIN_INTOP_RESULT:
(*(int *)value) = pblock->pb_internal_op_result;
break;
@@ -1931,6 +1934,9 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value )
case SLAPI_PLUGIN_IDENTITY:
pblock->pb_plugin_identity = (void*)value;
break;
+ case SLAPI_PLUGIN_CONFIG_AREA:
+ pblock->pb_plugin_config_area = (char *) value;
+ break;
case SLAPI_PLUGIN_DESTROY_FN:
pblock->pb_destroy_fn = (IFP) value;
break;
diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c
index cc88dc4..fae1f8e 100644
--- a/ldap/servers/slapd/plugin.c
+++ b/ldap/servers/slapd/plugin.c
@@ -724,6 +724,7 @@ typedef struct _plugin_dep_config {
int total_type;
char **depends_named_list;
int total_named;
+ char *config_area;
} plugin_dep_config;
/* list of plugins which should be shutdown in reverse order */
@@ -994,6 +995,16 @@ plugin_dependency_startall(int argc, char** argv, char *errmsg, int operation)
slapi_pblock_set(&(config[plugin_index].pb), SLAPI_ADD_ENTRY,
plugin_entry );
+ /* Pass the plugin alternate config area DN in SLAPI_PLUGIN_CONFIG_AREA. */
+ value = slapi_entry_attr_get_charptr(plugin_entry, ATTR_PLUGIN_CONFIG_AREA);
+ if(value)
+ {
+ config[plugin_index].config_area = value;
+ value = NULL;
+ slapi_pblock_set(&(config[plugin_index].pb), SLAPI_PLUGIN_CONFIG_AREA,
+ config[plugin_index].config_area);
+ }
+
value = slapi_entry_attr_get_charptr(plugin_entry, "nsslapd-plugintype");
if(value)
{
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index b3728d3..1af2eec 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -709,6 +709,7 @@ struct matchingRuleList {
#define ATTR_PLUGIN_DESC "nsslapd-pluginDescription"
#define ATTR_PLUGIN_ENABLED "nsslapd-pluginEnabled"
#define ATTR_PLUGIN_ARG "nsslapd-pluginArg"
+#define ATTR_PLUGIN_CONFIG_AREA "nsslapd-pluginConfigArea"
#define ATTR_PLUGIN_BACKEND "nsslapd-backend"
#define ATTR_PLUGIN_SCHEMA_CHECK "nsslapd-schemaCheck"
#define ATTR_PLUGIN_LOG_ACCESS "nsslapd-logAccess"
@@ -1515,6 +1516,7 @@ typedef struct slapi_pblock {
Slapi_Entry **pb_plugin_internal_search_op_entries;
char **pb_plugin_internal_search_op_referrals;
void *pb_plugin_identity; /* identifies plugin for internal operation */
+ char *pb_plugin_config_area; /* optional config area */
void *pb_parent_txn; /* parent transaction ID */
void *pb_txn; /* transaction ID */
IFP pb_txn_ruv_mods_fn; /* Function to fetch RUV mods for txn */
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 8531fbe..4ec8c70 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -5904,6 +5904,8 @@ typedef struct slapi_plugindesc {
#define SLAPI_PLUGIN_ENTRY_STORE_FUNC 814
#define SLAPI_PLUGIN_ENABLED 815
+#define SLAPI_PLUGIN_CONFIG_AREA 816
+
/*
* Defined values of SLAPI_PLUGIN_SYNTAX_FLAGS:
*/
13 years
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/back-ldbm/cache.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
New commits:
commit fe9b6a6bab32353f55a6ce2123f7df6b72a9a5a7
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Apr 19 12:17:49 2011 -0700
Bug 697027 - 3 - minor memory leaks found by Valgrind + TET
https://bugzilla.redhat.com/show_bug.cgi?id=697027
Description: Adding slapi_counter_destroy to destroy counters
cache->c_cursize, c_hits, and c_tries used in the entry cache.
Additionally, changing to make cache_init fail if slapi_counter
is not enabled since cache->c_cursize depends upon the counter
and the cache module cannot function unless c_cursize is available.
diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c
index e29247e..95fa638 100644
--- a/ldap/servers/slapd/back-ldbm/cache.c
+++ b/ldap/servers/slapd/back-ldbm/cache.c
@@ -519,14 +519,24 @@ int cache_init(struct cache *cache, size_t maxsize, long maxentries, int type)
LDAPDebug(LDAP_DEBUG_TRACE, "=> cache_init\n", 0, 0, 0);
cache->c_maxsize = maxsize;
cache->c_maxentries = maxentries;
- cache->c_cursize = slapi_counter_new();
cache->c_curentries = 0;
if (config_get_slapi_counters()) {
+ if (cache->c_cursize) {
+ slapi_counter_destroy(&cache->c_cursize);
+ }
+ cache->c_cursize = slapi_counter_new();
+ if (cache->c_hits) {
+ slapi_counter_destroy(&cache->c_hits);
+ }
cache->c_hits = slapi_counter_new();
+ if (cache->c_tries) {
+ slapi_counter_destroy(&cache->c_tries);
+ }
cache->c_tries = slapi_counter_new();
} else {
- cache->c_hits = NULL;
- cache->c_tries = NULL;
+ LDAPDebug0Args(LDAP_DEBUG_ANY,
+ "cache_init: slapi counter is not available.\n");
+ return 0;
}
cache->c_lruhead = cache->c_lrutail = NULL;
cache_make_hashes(cache, type);
@@ -651,6 +661,9 @@ static void erase_cache(struct cache *cache, int type)
void cache_destroy_please(struct cache *cache, int type)
{
erase_cache(cache, type);
+ slapi_counter_destroy(&cache->c_cursize);
+ slapi_counter_destroy(&cache->c_hits);
+ slapi_counter_destroy(&cache->c_tries);
PR_DestroyLock(cache->c_mutex);
PR_DestroyLock(cache->c_emutexalloc_mutex);
}
13 years
6 commits - lib/libadminutil lib/libadmsslutil
by Nathan Kinder
lib/libadminutil/admutil.c | 41 ++++++++++++++++++++++++-----------------
lib/libadminutil/psetc.c | 32 +++++++++++++++++++++-----------
lib/libadmsslutil/certmgt.c | 19 +++++++++++++++----
3 files changed, 60 insertions(+), 32 deletions(-)
New commits:
commit e0da40846c56e8cae9a64ba0a20c0194bd74577b
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Mon Apr 18 15:07:32 2011 -0700
Bug 697641 - Check if strchr() returns NULL before dereferencing
If we don't find the ':' delimiter, we can end up dereferencing a NULL
pointer. We should check if strchr() returned NULL before dereferencing
password.
cov#10761
diff --git a/lib/libadminutil/admutil.c b/lib/libadminutil/admutil.c
index ee3197b..51dae4e 100644
--- a/lib/libadminutil/admutil.c
+++ b/lib/libadminutil/admutil.c
@@ -1251,21 +1251,24 @@ admldapBuildInfoOnly(char* configRoot, int *errorcode)
/* EOF */
default:
password = strchr(buf, ':');
- *password++ = '\0';
- while (*password) {
- if (*password == ' ') password++;
- else break;
- }
+ if (password) {
+ *password++ = '\0';
+ while (*password) {
+ if (*password == ' ') password++;
+ else break;
+ }
- name = buf;
- if (*password) {
- *errorcode = ADMUTIL_OP_OK;
- admInfo->admpwFilePath = path; /* hand off memory */
- path = NULL;
- admInfo->localAdminName = PL_strdup(name);
- admInfo->localAdminPassword = PL_strdup(password);
- }
- else {
+ name = buf;
+ if (*password) {
+ *errorcode = ADMUTIL_OP_OK;
+ admInfo->admpwFilePath = path; /* hand off memory */
+ path = NULL;
+ admInfo->localAdminName = PL_strdup(name);
+ admInfo->localAdminPassword = PL_strdup(password);
+ } else {
+ *errorcode = ADMUTIL_OP_FAIL;
+ }
+ } else {
*errorcode = ADMUTIL_OP_FAIL;
}
}
commit b1181e4ea020c9866b8058f5b3c0c4520c764342
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Mon Apr 18 15:00:07 2011 -0700
Bug 697641 - Check list->name for NULL before dereferencing
The code assumes that list->name will not be NULL, which is likely a
correct assumption if the list API was used properly. To be same, we
should check if list->name is NULL before dereferencing it.
cov#10762
diff --git a/lib/libadminutil/admutil.c b/lib/libadminutil/admutil.c
index ea207d8..ee3197b 100644
--- a/lib/libadminutil/admutil.c
+++ b/lib/libadminutil/admutil.c
@@ -530,9 +530,11 @@ listDelete(ListNodePtr list, char* name) {
/* Not implemented */
ListNodePtr node, nextptr;
- if (!list) return NULL;
+ if (!list || !name) {
+ goto done;
+ }
- if (!strcasecmp(list->name, name)) {
+ if (list->name && !strcasecmp(list->name, name)) {
nextptr = list->next;
if (list->name) PR_Free(list->name);
if (list->dflag) deleteValue ((ValueType)list->val);
@@ -542,7 +544,7 @@ listDelete(ListNodePtr list, char* name) {
node = list;
while (node->next) {
- if (!strcasecmp(node->next->name, name)) {
+ if (node->next->name && !strcasecmp(node->next->name, name)) {
nextptr = node->next->next;
if (node->next->name) PR_Free (node->next->name);
if (node->next->dflag) deleteValue ((ValueType)node->next->val);
@@ -552,6 +554,8 @@ listDelete(ListNodePtr list, char* name) {
}
node = node->next;
}
+
+done:
return list;
}
commit 14b558e289b3b1ec5fc5d7681eb1bd1522657e8a
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Mon Apr 18 15:12:04 2011 -0700
Bug 697641 - Check if valBuf is NULL before dereferencing
If PR_Realloc() fails to calculate memory for valBuf, we will end up
dereferencing a NULL pointer. We should check if valBuf is NULL before
dereferencing it.
cov#10758
diff --git a/lib/libadminutil/psetc.c b/lib/libadminutil/psetc.c
index 3d01d38..42d0871 100644
--- a/lib/libadminutil/psetc.c
+++ b/lib/libadminutil/psetc.c
@@ -757,6 +757,10 @@ psetNodeFileExport(PsetNodePtr nodePtr, LDAP *ld, FILE *fstream)
valBuf = (char *)PR_Realloc(valBuf, valLen + 1); /*+1 for ending '\0'*/
prevValLen = valLen;
}
+ if (!valBuf) {
+ errorCode = PSET_SYSTEM_ERR;
+ goto bail;
+ }
PR_snprintf(valBuf, valLen + 1, "%s", valList[i]);
sptr = valBuf;
while ((cptr = strchr(sptr, '\n'))) {
@@ -770,6 +774,7 @@ psetNodeFileExport(PsetNodePtr nodePtr, LDAP *ld, FILE *fstream)
}
listPtr = listPtr->next;
}
+bail:
nvlistDestroy(resultList);
}
commit b83d718da4b7e0f20f0039a439215e19c5a43daf
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Mon Apr 18 14:33:03 2011 -0700
Bug 697641 - Check if pset is NULL before dereferencing
We should check if pset is NULL before dereferencing it.
cov#10759
diff --git a/lib/libadminutil/psetc.c b/lib/libadminutil/psetc.c
index f70b514..3d01d38 100644
--- a/lib/libadminutil/psetc.c
+++ b/lib/libadminutil/psetc.c
@@ -1204,7 +1204,7 @@ psetRootModAttrList(PsetRootPtr psetRoot, int mode, AttributeList nvl)
return PSET_LOCAL_MODE;
}
- if (target && nodeFlag) {
+ if (target && nodeFlag && pset) {
attrList = (ListNodePtr)nodePtr->val;
/* Check the existence of the attribute */
@@ -1283,7 +1283,9 @@ psetRootModAttrList(PsetRootPtr psetRoot, int mode, AttributeList nvl)
}
nodePtr=nodePtr->next;
}
- psetFileExportP(pset);
+ if (pset) {
+ psetFileExportP(pset);
+ }
destroyUpdateList(updateList);
return errorcode;
}
commit a551b3ba27dbd253acb16a72f806df3ff3dc9983
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Mon Apr 18 14:21:49 2011 -0700
Bug 697641 - Check if nodeName is NULL before dereferencing
We should check if nodeName is NULL before dereferencing it.
cov#10763,10706
diff --git a/lib/libadminutil/psetc.c b/lib/libadminutil/psetc.c
index 79f2b6d..f70b514 100644
--- a/lib/libadminutil/psetc.c
+++ b/lib/libadminutil/psetc.c
@@ -822,11 +822,10 @@ psetLDAPRefresh(PsetPtr pset)
nodeName = dn2AttrName(dn, pset->sieDN);
ldap_memfree(dn);
- if (nodeName[0] == '\0') {
+ if (!nodeName || (nodeName[0] == '\0')) {
psetNodeSetLDAP(pset->info, result);
pset->info->attrLDAP = e;
- }
- else {
+ } else {
target = psetNodeFindNode(pset->info, pset->ld, nodeName, &nodeFlag,
&errorCode);
if (target) {
@@ -909,12 +908,14 @@ psetFileImportP(PsetPtr pset)
case 1:
/* EOF, out of here */
if (namebuf[0] != '\0') {
- if (nodeName[0] == '\0') target = pset->info;
- else if (lastPsetNode && !strcasecmp(nodeName, lastPsetNode->attrName))
+ if (!nodeName || (nodeName[0] == '\0')) {
+ target = pset->info;
+ } else if (lastPsetNode && !strcasecmp(nodeName, lastPsetNode->attrName)) {
/* Is the last node? -> strcasecmp node name */
target = lastPsetNode;
- else /* No, Locate and build node -> psetnodeBuildNodes */
+ } else { /* No, Locate and build node -> psetnodeBuildNodes */
target = psetNodeBuildNodes(pset->info, nodeName, &errorCode);
+ }
/* psetNodeAddNameValue */
if (target) {
@@ -958,12 +959,14 @@ psetFileImportP(PsetPtr pset)
}
else {
if (namebuf[0] != '\0') {
- if (nodeName[0] == '\0') target = pset->info;
- else if (lastPsetNode && !strcasecmp(nodeName, lastPsetNode->attrName))
+ if (!nodeName || (nodeName[0] == '\0')) {
+ target = pset->info;
+ } else if (lastPsetNode && !strcasecmp(nodeName, lastPsetNode->attrName)) {
/* Is the last node? -> strcasecmp node name */
target = lastPsetNode;
- else /* No, Locate and build node -> psetnodeBuildNodes */
+ } else { /* No, Locate and build node -> psetnodeBuildNodes */
target = psetNodeBuildNodes(pset->info, nodeName, &errorCode);
+ }
/* psetNodeAddNameValue */
if (target) {
commit 72f7b32ab6ad9b77bc92df4f7918ae1e7170ffd9
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Mon Apr 18 12:55:51 2011 -0700
Bug 697641 - Check return value of DER_UTCTimeToAscii()
We should check if DER_UTCTimeToAscii() returns NULL before
dereferencing the returned pointer.
cov#10766,10765
diff --git a/lib/libadmsslutil/certmgt.c b/lib/libadmsslutil/certmgt.c
index f0b2aea..a674571 100644
--- a/lib/libadmsslutil/certmgt.c
+++ b/lib/libadmsslutil/certmgt.c
@@ -75,10 +75,15 @@ static SECStatus cmgShowCrlRow(CERTSignedCrl *crl)
}
datestr = DER_UTCTimeToAscii(&crl->crl.nextUpdate);
+ if (!datestr) {
+ return SECFailure;
+ }
/* validity = SEC_CheckCrlTimes(&crl->crl, time(NULL)); */
printf("%s;%s\n", nn, datestr);
+ PORT_Free(datestr);
+
return SECSuccess;
}
@@ -105,21 +110,26 @@ cmgShowCrls(CERTCertDBHandle *handle, int list_type)
PR_IMPLEMENT(char *)
cmgHTMLCrlInfo(CERTSignedCrl *crl)
{
- char *issuer;
- char *notBefore, *notAfter;
+ char *issuer = NULL;
+ char *notBefore = NULL;
+ char *notAfter = NULL;
#define NCHARPERLINE 50
#define NLINES 20
- char * outputBuffer;
+ char *outputBuffer = NULL;
if (!crl) {
- return(0);
+ goto bail;
}
issuer = CERT_FormatName(&crl->crl.name);
notBefore = (char *)DER_UTCTimeToAscii(&crl->crl.lastUpdate);
notAfter = (char *)DER_UTCTimeToAscii(&crl->crl.nextUpdate);
+ if (!issuer || !notBefore || !notAfter) {
+ goto bail;
+ }
+
/* reformat dates */
notBefore[10] = ',';
notAfter[10] = ',';
@@ -133,6 +143,7 @@ cmgHTMLCrlInfo(CERTSignedCrl *crl)
outputBuffer = PR_smprintf("ISSUER=%s\nNOTBEFORE=%s\nNOTAFTER=%s\n",
issuer, notBefore, notAfter);
+bail:
if ( issuer ) {
PORT_Free(issuer);
}
13 years
Branch '389-ds-base-1.2.8' - ldap/servers
by Noriko Hosoi
ldap/servers/slapd/valueset.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
New commits:
commit c51c77b302f0e7ed2df32de54385295090ae6c85
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Apr 15 14:18:55 2011 -0700
Bug 697027 - 12 - minor memory leaks found by Valgrind + TET
https://bugzilla.redhat.com/show_bug.cgi?id=697027
[Case 12]
Description: The caller of valuearray_remove_value is responsible
for freeing the removed value. Adding slapi_value_free to free it.
diff --git a/ldap/servers/slapd/valueset.c b/ldap/servers/slapd/valueset.c
index a2ae334..6a3a205 100644
--- a/ldap/servers/slapd/valueset.c
+++ b/ldap/servers/slapd/valueset.c
@@ -399,6 +399,7 @@ valuearray_remove_value_atindex(Slapi_Value **va, int index)
* Find the value in the array,
* shunt up the array to cover it,
* return a ptr to the value.
+ * The caller is responsible for freeing the value.
*/
Slapi_Value *
valuearray_remove_value(const Slapi_Attr *a, Slapi_Value **va, const Slapi_Value *v)
@@ -1043,9 +1044,13 @@ void
valueset_remove_string(const Slapi_Attr *a, Slapi_ValueSet *vs, const char *s)
{
Slapi_Value v;
+ Slapi_Value *removed;
value_init(&v,NULL,CSN_TYPE_NONE,NULL);
slapi_value_set_string(&v,s);
- valuearray_remove_value(a,vs->va,&v);
+ removed = valuearray_remove_value(a, vs->va, &v);
+ if(removed) {
+ slapi_value_free(&removed);
+ }
value_done(&v);
}
13 years