ldap/admin
by Mark Reynolds
ldap/admin/src/logconv.pl | 140 ++++++++++++++++++++++------------------------
1 file changed, 67 insertions(+), 73 deletions(-)
New commits:
commit 066a7d6434f8e65272142d424198af4634168227
Author: Mark Reynolds <mareynol(a)redhat.com>
Date: Tue Apr 10 13:30:14 2012 -0400
Ticket #325 - logconv.pl : use of getopts to parse command line options
RFE Description: use "GetOpt::Long" to parse the command line options
https://fedorahosted.org/389/ticket/325
Reviewed by: richm (Thanks Rich!)
diff --git a/ldap/admin/src/logconv.pl b/ldap/admin/src/logconv.pl
index c65e5b6..3f73bb7 100755
--- a/ldap/admin/src/logconv.pl
+++ b/ldap/admin/src/logconv.pl
@@ -45,6 +45,10 @@
#
use Time::Local;
use IO::File;
+use Getopt::Long;
+
+Getopt::Long::Configure ("bundling");
+Getopt::Long::Configure ("permute");
if ($#ARGV < 0){;
&displayUsage;
@@ -59,7 +63,6 @@ if ($#ARGV < 0){;
$x = "0";
$fc = 0;
$sn = 0;
-$manager = "cn=directory manager";
$logversion = "6.1";
$sizeCount = "20";
$startFlag = 0;
@@ -69,59 +72,50 @@ $endTime = 0;
$s_stats = new_stats_block( );
$m_stats = new_stats_block( );
+GetOptions(
+ 'd|rootDN=s' => \$manager,
+ 'v|version' => sub { print "Access Log Analyzer v$logversion\n"; exit (0); },
+ 'V|verbose' => sub { $verb = "yes"; },
+ 'X|excludeIP=s' => \$exclude[$xi++],
+ 's|sizeLimit=s' => \$sizeCount,
+ 'S|startTime=s' => \$startTime,
+ 'E|endTime=s' => \$endTime,
+ 'm|reportFileSecs=s' => sub { my ($opt,$value) = @_; $s_stats = new_stats_block($value); },
+ 'M|reportFileMins=s' => sub { my ($opt,$value) = @_; $m_stats = new_stats_block($value); },
+ 'h|help' => sub { displayUsage() },
+ # usage options '-efcibaltnxgjuiryp'
+ 'e' => sub { $usage = $usage . "e"; },
+ 'f' => sub { $usage = $usage . "f"; },
+ 'c' => sub { $usage = $usage . "c"; },
+ 'i' => sub { $usage = $usage . "i"; },
+ 'b' => sub { $usage = $usage . "b"; },
+ 'a' => sub { $usage = $usage . "a"; },
+ 'l' => sub { $usage = $usage . "l"; },
+ 't' => sub { $usage = $usage . "t"; },
+ 'n' => sub { $usage = $usage . "n"; },
+ 'x' => sub { $usage = $usage . "x"; },
+ 'g' => sub { $usage = $usage . "g"; },
+ 'j' => sub { $usage = $usage . "j"; },
+ 'u' => sub { $usage = $usage . "u"; },
+ 'r' => sub { $usage = $usage . "r"; },
+ 'y' => sub { $usage = $usage . "y"; },
+ 'p' => sub { $usage = $usage . "p"; }
+);
-while ($sn <= $#ARGV)
-{
- if ("$ARGV[$sn]" eq "-d")
- {
- $manager = $ARGV[++$sn];
- }
- elsif ("$ARGV[$sn]" eq "-v")
- {
- print "Access Log Analyzer v$logversion\n";;
- exit (0);
- }
- elsif ("$ARGV[$sn]" eq "-V")
- {
- $verb = "yes";
- }
- elsif ("$ARGV[$sn]" eq "-X"){
- $exclude[$x] = $ARGV[++$sn];
- $x++;
- }
- elsif ("$ARGV[$sn]" eq "-s")
- {
- $sizeCount = $ARGV[++$sn];
- }
- elsif ("$ARGV[$sn]" eq "-S")
- {
- $startTime = $ARGV[++$sn];
- }
- elsif ("$ARGV[$sn]" eq "-E")
- {
- $endTime = $ARGV[++$sn];
- }
- elsif ("$ARGV[$sn]" eq "-m")
- {
- $s_stats = new_stats_block( $ARGV[++$sn] );
- }
- elsif ("$ARGV[$sn]" eq "-M")
- {
- $m_stats = new_stats_block( $ARGV[++$sn] );
- }
- elsif ("$ARGV[$sn]" eq "-h")
- {
- &displayUsage;
- }
- elsif ("$ARGV[$sn]" =~ m/^-/){
- $usage = $ARGV[$sn];
- }
- else
- {
- $files[$fc] = $ARGV[$sn];
- $fc++;
- }
- $sn++;
+#
+# set the default root DN
+#
+if($manager eq ""){
+ $manager = "cn=directory manager";
+}
+
+#
+# get the logs
+#
+while($sn <= $#ARGV){
+ $files[$fc] = $ARGV[$sn];
+ $fc++;
+ $sn++;
}
if ($sizeCount eq "all"){$sizeCount = "100000";}
@@ -208,7 +202,7 @@ $maxsimConnection = 0;
$firstFile = "1";
$elapsedDays = "0";
$logCount = "0";
-$limit = "10000"; # number of lines processed to trigger output
+$limit = "25000"; # number of lines processed to trigger output
$err[0] = "Successful Operations\n";
$err[1] = "Operations Error(s)\n";
@@ -1187,25 +1181,25 @@ sub displayUsage {
print "Usage:\n\n";
- print " ./logconv.pl [-h] [-d <rootDN>] [-s <size limit>] [-v] [-V]\n";
- print " [-S <start time>] [-E <end time>]\n";
- print " [-efcibaltnxgju] [ access log ... ... ]\n\n";
+ print " ./logconv.pl [-h] [-d|--rootdn <rootDN>] [-s|--sizeLimit <size limit>] [-v|verison] [-Vi|verbose]\n";
+ print " [-S|--startTime <start time>] [-E|--endTime <end time>] \n";
+ print " [-efcibaltnxrgjuyp] [ access log ... ... ]\n\n";
print "- Commandline Switches:\n\n";
- print " -h help/usage\n";
- print " -d <Directory Managers DN> DEFAULT -> cn=directory manager\n";
- print " -s <Number of results to return per catagory> DEFAULT -> 20\n";
- print " -X <IP address to exclude from connection stats> E.g. Load balancers\n";
- print " -v show version of tool\n";
- print " -S <time to begin analyzing logfile from>\n";
- print " E.g. [28/Mar/2002:13:14:22 -0800]\n";
- print " -E <time to stop analyzing logfile>\n";
- print " E.g. [28/Mar/2002:13:24:62 -0800]\n";
- print " -m <CSV output file - per second stats>\n";
- print " -M <CSV output file - per minute stats>\n";
- print " -V <enable verbose output - includes all stats listed below>\n";
- print " -[efcibaltnxgju]\n\n";
+ print " -h, --help help/usage\n";
+ print " -d, --rootDN <Directory Managers DN> DEFAULT -> cn=directory manager\n";
+ print " -s, --sizeLimit <Number of results to return per catagory> DEFAULT -> 20\n";
+ print " -X, --excludeIP <IP address to exclude from connection stats> E.g. Load balancers\n";
+ print " -v, --version show version of tool\n";
+ print " -S, --startTime <time to begin analyzing logfile from>\n";
+ print " E.g. \"[28/Mar/2002:13:14:22 -0800]\"\n";
+ print " -E, --endTime <time to stop analyzing logfile>\n";
+ print " E.g. \"[28/Mar/2002:13:24:62 -0800]\"\n";
+ print " -m, --reportFileSecs <CSV output file - per second stats>\n";
+ print " -M, --reportFileMins <CSV output file - per minute stats>\n";
+ print " -V, --verbose <enable verbose output - includes all stats listed below>\n";
+ print " -[efcibaltnxrgjuyp]\n\n";
print " e Error Code stats\n";
print " f Failed Login Stats\n";
@@ -1228,11 +1222,11 @@ sub displayUsage {
print " ./logconv.pl -s 10 -V /logs/access*\n\n";
- print " ./logconv.pl -d cn=dm /logs/access*\n\n";
+ print " ./logconv.pl --rootDN cn=dm /logs/access*\n\n";
- print " ./logconv.pl -s 50 -ibgju /logs/access*\n\n";
+ print " ./logconv.pl --sizeLimit 50 -ibgju /logs/access*\n\n";
- print " ./logconv.pl -S \"\[28/Mar/2002:13:14:22 -0800\]\" -E \"\[28/Mar/2002:13:50:05 -0800\]\" -e /logs/access*\n\n";
+ print " ./logconv.pl -S \"\[28/Mar/2002:13:14:22 -0800\]\" --endTime \"\[28/Mar/2002:13:50:05 -0800\]\" -e /logs/access*\n\n";
print " ./logconv.pl -m log-minute-stats-csv.out /logs/access*\n\n";
exit 1;
11 years, 11 months
ldap/servers
by Richard Allen Megginson
ldap/servers/slapd/back-ldbm/idl_new.c | 44 ++++++++++++++-----
ldap/servers/slapd/back-ldbm/index.c | 25 +++++++----
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 31 +++++++++++--
ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 60 +++++++++++++++++++++------
4 files changed, 124 insertions(+), 36 deletions(-)
New commits:
commit d09ce0e3ab2ea24496ee44622b050e007bb3cb8a
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Sat Apr 7 09:05:18 2012 -0600
Ticket #336 - [abrt] 389-ds-base-1.2.10.4-2.fc16: index_range_read_ext: Process /usr/sbin/ns-slapd was killed by signal 11 (SIGSEGV)
https://fedorahosted.org/389/ticket/336
Resolves: Ticket #336
Bug Description: [abrt] 389-ds-base-1.2.10.4-2.fc16: index_range_read_ext: Process /usr/sbin/ns-slapd was killed by signal 11 (SIGSEGV)
Reviewed by: nhosoi (Thanks!)
Branch: master
Fix Description:
1) Entries can be deleted out from under a search operation. The range read
code was not handling this situation correctly. The code should notice that
the index query was empty, and continue to the next highest key in the range.
2) DB cursor c_close() functions can return DB_LOCK_DEADLOCK that must be
reported to the higher level operation functions. If not, then subsequent
operations in the same transaction fail. When a DB_LOCK_DEADLOCK is returned
by any DB update operation in the transaction, the transaction must be aborted
and a new transaction begun before any other transacted db operations can
occur.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
BZ: 808770
diff --git a/ldap/servers/slapd/back-ldbm/idl_new.c b/ldap/servers/slapd/back-ldbm/idl_new.c
index 4667c87..d62511c 100644
--- a/ldap/servers/slapd/back-ldbm/idl_new.c
+++ b/ldap/servers/slapd/back-ldbm/idl_new.c
@@ -333,8 +333,14 @@ IDList * idl_new_fetch(
error:
/* Close the cursor */
if (NULL != cursor) {
- if (0 != cursor->c_close(cursor)) {
- ldbm_nasty(filename,3,ret);
+ int ret2 = cursor->c_close(cursor);
+ if (ret2) {
+ ldbm_nasty(filename,3,ret2);
+ if (!ret) {
+ /* if cursor close returns DEADLOCK, we must bubble that up
+ to the higher layers for retries */
+ ret = ret2;
+ }
}
}
*flag_err = ret;
@@ -418,8 +424,9 @@ int idl_new_insert_key(
error:
/* Close the cursor */
if (NULL != cursor) {
- if (0 != cursor->c_close(cursor)) {
- ldbm_nasty(filename,56,ret);
+ int ret2 = cursor->c_close(cursor);
+ if (ret2) {
+ ldbm_nasty(filename,56,ret2);
}
}
#else
@@ -439,7 +446,7 @@ error:
/* this is okay */
ret = 0;
} else {
- ldbm_nasty(filename,50,ret);
+ ldbm_nasty(filename,60,ret);
}
}
#endif
@@ -491,8 +498,14 @@ int idl_new_delete_key(
error:
/* Close the cursor */
if (NULL != cursor) {
- if (0 != cursor->c_close(cursor)) {
- ldbm_nasty(filename,24,ret);
+ int ret2 = cursor->c_close(cursor);
+ if (ret2) {
+ ldbm_nasty(filename,24,ret2);
+ if (!ret) {
+ /* if cursor close returns DEADLOCK, we must bubble that up
+ to the higher layers for retries */
+ ret = ret2;
+ }
}
}
return ret;
@@ -559,14 +572,17 @@ static int idl_new_store_allids(backend *be, DB *db, DBT *key, DB_TXN *txn)
error:
/* Close the cursor */
if (NULL != cursor) {
- if (0 != cursor->c_close(cursor)) {
- ldbm_nasty(filename,33,ret);
+ int ret2 = cursor->c_close(cursor);
+ if (ret2) {
+ ldbm_nasty(filename,33,ret2);
}
}
return ret;
+#ifdef KRAZY_K0DE
/* If this function is called in "no-allids" mode, then it's a bug */
ldbm_nasty(filename,63,0);
return -1;
+#endif
}
#endif
@@ -662,8 +678,14 @@ int idl_new_store_block(
error:
/* Close the cursor */
if (NULL != cursor) {
- if (0 != cursor->c_close(cursor)) {
- ldbm_nasty(filename,49,ret);
+ int ret2 = cursor->c_close(cursor);
+ if (ret2) {
+ ldbm_nasty(filename,49,ret2);
+ if (!ret) {
+ /* if cursor close returns DEADLOCK, we must bubble that up
+ to the higher layers for retries */
+ ret = ret2;
+ }
}
}
return ret;
diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c
index 0ed6918..0ede6de 100644
--- a/ldap/servers/slapd/back-ldbm/index.c
+++ b/ldap/servers/slapd/back-ldbm/index.c
@@ -1496,14 +1496,23 @@ index_range_read_ext(
if(retry_count == IDL_FETCH_RETRY_COUNT) {
ldbm_nasty("index_range_read retry count exceeded",1095,*err);
}
- tmp2 = idl_union( be, idl, tmp );
- idl_free( idl );
- idl_free( tmp );
- idl = tmp2;
- if (ALLIDS(idl)) {
- LDAPDebug(LDAP_DEBUG_TRACE, "index_range_read hit an allids value\n",
- 0, 0, 0);
- break;
+ if (!idl) {
+ if (slapi_is_loglevel_set(LDAP_DEBUG_TRACE)) {
+ char encbuf[BUFSIZ];
+ LDAPDebug2Args(LDAP_DEBUG_TRACE,
+ "index_range_read_ext: cur_key=%s(%li bytes) was deleted - skipping\n",
+ encoded(&cur_key, encbuf), (long)cur_key.dsize);
+ }
+ } else {
+ tmp2 = idl_union( be, idl, tmp );
+ idl_free( idl );
+ idl_free( tmp );
+ idl = tmp2;
+ if (ALLIDS(idl)) {
+ LDAPDebug(LDAP_DEBUG_TRACE, "index_range_read hit an allids value\n",
+ 0, 0, 0);
+ break;
+ }
}
if (DBT_EQ (&cur_key, &upperkey)) { /* this is the last key */
break;
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index d8773f1..447ab84 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -727,6 +727,12 @@ ldbm_back_delete( Slapi_PBlock *pb )
retval = index_addordel_values_sv(be, LDBM_PARENTID_STR,
svals, NULL, e->ep_id,
BE_INDEX_ADD, &txn);
+ if (DB_LOCK_DEADLOCK == retval) {
+ LDAPDebug0Args( LDAP_DEBUG_ARGS,
+ "delete (updating " LDBM_PARENTID_STR ") DB_LOCK_DEADLOCK\n");
+ /* Retry txn */
+ continue;
+ }
if ( retval ) {
LDAPDebug( LDAP_DEBUG_TRACE,
"delete (deleting %s) failed, err=%d %s\n",
@@ -738,18 +744,33 @@ ldbm_back_delete( Slapi_PBlock *pb )
goto error_return;
}
}
- entryrdn_index_entry(be, e, BE_INDEX_DEL, &txn);
- retval =
- entryrdn_index_entry(be, tombstone, BE_INDEX_ADD, &txn);
+ retval = entryrdn_index_entry(be, e, BE_INDEX_DEL, &txn);
+ if (DB_LOCK_DEADLOCK == retval) {
+ LDAPDebug0Args( LDAP_DEBUG_ARGS,
+ "delete (deleting entryrdn) DB_LOCK_DEADLOCK\n");
+ /* Retry txn */
+ continue;
+ }
+ if (0 != retval) {
+ LDAPDebug2Args( LDAP_DEBUG_TRACE,
+ "delete (deleting entryrdn) failed, err=%d %s\n",
+ retval,
+ (msg = dblayer_strerror( retval )) ? msg : "" );
+ if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
+ DEL_SET_ERROR(ldap_result_code,
+ LDAP_OPERATIONS_ERROR, retry_count);
+ goto error_return;
+ }
+ retval = entryrdn_index_entry(be, tombstone, BE_INDEX_ADD, &txn);
if (DB_LOCK_DEADLOCK == retval) {
LDAPDebug0Args( LDAP_DEBUG_ARGS,
- "delete (adding entryrdn) DB_LOCK_DEADLOCK\n");
+ "adding (adding tombstone entryrdn) DB_LOCK_DEADLOCK\n");
/* Retry txn */
continue;
}
if (0 != retval) {
LDAPDebug2Args( LDAP_DEBUG_TRACE,
- "delete (adding entryrdn) failed, err=%d %s\n",
+ "adding (adding tombstone entryrdn) failed, err=%d %s\n",
retval,
(msg = dblayer_strerror( retval )) ? msg : "" );
if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
index 2a7b1e4..4eba4ed 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
@@ -280,9 +280,15 @@ bail:
if (cursor) {
int myrc = cursor->c_close(cursor);
if (0 != myrc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
+ slapi_log_error(loglevel, ENTRYRDN_TAG,
"entryrdn_index_entry: Failed to close cursor: %s(%d)\n",
- dblayer_strerror(rc), rc);
+ dblayer_strerror(myrc), myrc);
+ if (!rc) {
+ /* if cursor close returns DEADLOCK, we must bubble that up
+ to the higher layers for retries */
+ rc = myrc;
+ }
}
}
if (db) {
@@ -388,9 +394,15 @@ bail:
if (cursor) {
int myrc = cursor->c_close(cursor);
if (0 != myrc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
- "entryrdn_index_read: Failed to close cursor: "
- "%s(%d)\n", dblayer_strerror(rc), rc);
+ int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
+ slapi_log_error(loglevel, ENTRYRDN_TAG,
+ "entryrdn_index_read: Failed to close cursor: %s(%d)\n",
+ dblayer_strerror(myrc), myrc);
+ if (!rc) {
+ /* if cursor close returns DEADLOCK, we must bubble that up
+ to the higher layers for retries */
+ rc = myrc;
+ }
}
}
if (db) {
@@ -841,9 +853,15 @@ bail:
if (cursor) {
int myrc = cursor->c_close(cursor);
if (0 != myrc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
+ slapi_log_error(loglevel, ENTRYRDN_TAG,
"entryrdn_rename_subtree: Failed to close cursor: %s(%d)\n",
- dblayer_strerror(rc), rc);
+ dblayer_strerror(myrc), myrc);
+ if (!rc) {
+ /* if cursor close returns DEADLOCK, we must bubble that up
+ to the higher layers for retries */
+ rc = myrc;
+ }
}
}
if (db) {
@@ -983,9 +1001,15 @@ bail:
if (cursor) {
int myrc = cursor->c_close(cursor);
if (0 != myrc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
+ slapi_log_error(loglevel, ENTRYRDN_TAG,
"entryrdn_get_subordinates: Failed to close cursor: %s(%d)\n",
- dblayer_strerror(rc), rc);
+ dblayer_strerror(myrc), myrc);
+ if (!rc) {
+ /* if cursor close returns DEADLOCK, we must bubble that up
+ to the higher layers for retries */
+ rc = myrc;
+ }
}
}
if (db) {
@@ -1147,9 +1171,15 @@ bail:
if (cursor) {
int myrc = cursor->c_close(cursor);
if (0 != myrc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
+ slapi_log_error(loglevel, ENTRYRDN_TAG,
"entryrdn_lookup_dn: Failed to close cursor: %s(%d)\n",
dblayer_strerror(myrc), myrc);
+ if (!rc) {
+ /* if cursor close returns DEADLOCK, we must bubble that up
+ to the higher layers for retries */
+ rc = myrc;
+ }
}
}
/* it is guaranteed that db is not NULL. */
@@ -1294,9 +1324,15 @@ bail:
if (cursor) {
int myrc = cursor->c_close(cursor);
if (0 != myrc) {
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+ int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
+ slapi_log_error(loglevel, ENTRYRDN_TAG,
"entryrdn_get_parent: Failed to close cursor: %s(%d)\n",
- dblayer_strerror(rc), rc);
+ dblayer_strerror(myrc), myrc);
+ if (!rc) {
+ /* if cursor close returns DEADLOCK, we must bubble that up
+ to the higher layers for retries */
+ rc = myrc;
+ }
}
}
/* it is guaranteed that db is not NULL. */
11 years, 11 months
ldap/servers
by Mark Reynolds
ldap/servers/plugins/automember/automember.c | 12 ++----------
ldap/servers/slapd/daemon.c | 1 +
2 files changed, 3 insertions(+), 10 deletions(-)
New commits:
commit 554e29d0f9ad1bdf77b3b868cccd853f023f0a05
Author: Mark Reynolds <mareynol(a)redhat.com>
Date: Mon Apr 9 15:56:46 2012 -0400
Coverity Fixes
Bug Description: Fixes coverity errors from ticket 315 & 20
diff --git a/ldap/servers/plugins/automember/automember.c b/ldap/servers/plugins/automember/automember.c
index d638374..17590ef 100644
--- a/ldap/servers/plugins/automember/automember.c
+++ b/ldap/servers/plugins/automember/automember.c
@@ -2043,7 +2043,6 @@ automember_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
int rv = SLAPI_DSE_CALLBACK_OK;
task_data *mytaskdata = NULL;
Slapi_Task *task = NULL;
- Slapi_DN *basedn = NULL;
PRThread *thread = NULL;
char *bind_dn = NULL;
const char *base_dn;
@@ -2067,9 +2066,6 @@ automember_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
*returncode = LDAP_OBJECT_CLASS_VIOLATION;
rv = SLAPI_DSE_CALLBACK_ERROR;
goto out;
- } else {
- /* convert the base_dn to a slapi dn */
- basedn = slapi_sdn_new_dn_byval(base_dn);
}
if((filter = fetch_attr(e, "filter", 0)) == NULL){
*returncode = LDAP_OBJECT_CLASS_VIOLATION;
@@ -2089,7 +2085,7 @@ automember_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
slapi_pblock_get(pb, SLAPI_REQUESTOR_DN, &bind_dn);
mytaskdata->bind_dn = slapi_ch_strdup(bind_dn);
- mytaskdata->base_dn = basedn;
+ mytaskdata->base_dn = slapi_sdn_new_dn_byval(base_dn);
mytaskdata->filter_str = slapi_ch_strdup(filter);
if(scope){
if(strcasecmp(scope,"sub")== 0){
@@ -2236,7 +2232,6 @@ automember_task_add_export_updates(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry
int rv = SLAPI_DSE_CALLBACK_OK;
task_data *mytaskdata = NULL;
Slapi_Task *task = NULL;
- Slapi_DN *basedn = NULL;
PRThread *thread = NULL;
char *bind_dn = NULL;
const char *base_dn = NULL;
@@ -2264,9 +2259,6 @@ automember_task_add_export_updates(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry
*returncode = LDAP_OBJECT_CLASS_VIOLATION;
rv = SLAPI_DSE_CALLBACK_ERROR;
goto out;
- } else {
- /* convert the base dn to a slapi dn */
- basedn = slapi_sdn_new_dn_byval(base_dn);
}
if((filter = fetch_attr(e, "filter", 0)) == NULL){
*returncode = LDAP_OBJECT_CLASS_VIOLATION;
@@ -2285,7 +2277,7 @@ automember_task_add_export_updates(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry
}
mytaskdata->bind_dn = slapi_ch_strdup(bind_dn);
mytaskdata->ldif_out = slapi_ch_strdup(ldif);
- mytaskdata->base_dn = basedn;
+ mytaskdata->base_dn = slapi_sdn_new_dn_byval(base_dn);
mytaskdata->filter_str = slapi_ch_strdup(filter);
if(scope){
if(strcasecmp(scope,"sub")== 0){
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index 01d307d..597e131 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -629,6 +629,7 @@ disk_mon_get_dirs(char ***list, int logs_critical){
}
be = (backend *)slapi_get_next_backend (cookie);
}
+ slapi_ch_free((void **)&cookie);
}
/*
11 years, 11 months
ldap/admin
by Noriko Hosoi
ldap/admin/src/scripts/DSUtil.pm.in | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
New commits:
commit 7ef6558922e8ba0f5281c59dd2953b260b4eccff
Author: Noriko Hosoi <nhosoi(a)dhcp-32-235.sjc.redhat.com>
Date: Thu Apr 5 16:23:11 2012 -0700
Trac Ticket #46 - (additional 2) setup-ds-admin.pl does not like ipv6 only hostnames
https://fedorahosted.org/389/ticket/46
Fix description:
1) When Socket6 is used, if the same FQDN appears twice in
/etc/hosts (e.g., localhost.localdomain for 127.0.0.1 and
::1), the result from getaddrinfo was not correctly shifted.
2) perl require takes package name. In the commit 850005499bd9-
2c5b9b0027f944fcd33633c8db46, a tag ':addrinfo" was mistakenly
passed and it was ignored. This patch checks the version of
Socket. If it is greater than 2.000, getaddrinfo in the
Socket module is used. Otherwise, it falls back to Socket6.
diff --git a/ldap/admin/src/scripts/DSUtil.pm.in b/ldap/admin/src/scripts/DSUtil.pm.in
index e84f482..cc64a2d 100644
--- a/ldap/admin/src/scripts/DSUtil.pm.in
+++ b/ldap/admin/src/scripts/DSUtil.pm.in
@@ -58,17 +58,20 @@ require Exporter;
use strict;
-use Socket;
+my $sockVersion;
BEGIN {
- if (eval {require Socket::addrinfo; 1}) {
- import Socket qw (:addrinfo inet_ntoa
- unpack_sockaddr_in unpack_sockaddr_in6
- AF_INET INADDR_ANY
- PF_INET SO_REUSEADDR SOCK_STREAM SOL_SOCKET);
+ use Socket;
+ $sockVersion = Socket->VERSION;
+ if ($sockVersion >= 2.000) {
+ import Socket qw ( :addrinfo inet_ntoa
+ unpack_sockaddr_in unpack_sockaddr_in6
+ AF_INET INADDR_ANY
+ PF_INET SO_REUSEADDR SOCK_STREAM SOL_SOCKET );
} elsif (eval {require Socket6; 1}) {
import Socket6 qw (getaddrinfo getnameinfo unpack_sockaddr_in6);
}
}
+$sockVersion = Socket->VERSION;
use NetAddr::IP::Util qw( ipv6_n2x );
use File::Temp qw(tempfile tempdir);
@@ -221,7 +224,8 @@ sub checkHostname {
# see if we can resolve the hostname (IPv6 supported)
my $found = 0;
my @hostip = ();
- if (eval {require Socket::addrinfo; 1}) {
+ if ($sockVersion >= 2.000) {
+ debug(1, "Socket version $sockVersion\n");
my %hints = (socktype => SOCK_STREAM);
my ($err, @aires) = getaddrinfo($hn, "ldap", \%hints);
if ($err) {
@@ -249,6 +253,7 @@ sub checkHostname {
}
}
} elsif (eval {require Socket6; 1}) {
+ debug(1, "Socket6\n");
my @aires = getaddrinfo($hn, "ldap", AF_UNSPEC, SOCK_STREAM);
if (scalar(@aires) < 5) {
return $res->getText('warning_no_such_hostname', $hn);
@@ -256,7 +261,11 @@ sub checkHostname {
my $ailen = scalar(@aires);
while ($ailen >= 5) {
debug(1, "found for hostname $hn\n");
- my ($family, $socktype, $proto, $saddr, $canonname, @aires) = @aires;
+ my $family = shift @aires;
+ my $socktype = shift @aires;
+ my $proto = shift @aires;
+ my $saddr = shift @aires;
+ my $canonname = shift @aires;
$ailen = scalar(@aires);
my $ip;
if ($family == AF_INET) {
@@ -277,6 +286,7 @@ sub checkHostname {
}
}
} else {
+ debug(1, "gethostbyname ...\n");
# see if we can resolve the hostname
my ($name, $aliases, $addrtype, $length, @addrs) = gethostbyname($hn);
if (!$name) {
11 years, 11 months
ldap/servers
by Mark Reynolds
ldap/servers/slapd/libglobs.c | 30 ++++++++++++++++++++++++++++++
ldap/servers/slapd/proto-slap.h | 1 +
ldap/servers/slapd/pw.h | 2 +-
ldap/servers/slapd/pw_retry.c | 38 +++++++++++++++++++++++---------------
ldap/servers/slapd/result.c | 10 +++++++++-
ldap/servers/slapd/slap.h | 2 ++
6 files changed, 66 insertions(+), 17 deletions(-)
New commits:
commit 396c9320f51c751e040da97ba8396c0f36de88f1
Author: Mark Reynolds <mareynol(a)redhat.com>
Date: Thu Apr 5 22:40:01 2012 -0400
Ticket #183 - passwordMaxFailure should lockout password one sooner - and should be configurable to avoid regressions
Bug Description: DS doesn't return error LDAP_CONSTRAINT_VIOLATION until after the retry limit is exceeded
Fix Description: DS has essentially locked the account, but we didn't log the error until
the next bind. Added a new config option "passwordLegacyPolicy: on|off"
that will trigger the error LDAP_CONSTRAINT_VIOLATION, if "legacy" is off,
when the limit is actually reached. The default is to continue to do
things the "old" way, or legacy "on".
https://fedorahosted.org/389/ticket/183
reviewed by: Noriko (Thanks!)
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index 8bcd544..d5b8faf 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -373,6 +373,9 @@ static struct config_get_and_set {
{CONFIG_PW_ISGLOBAL_ATTRIBUTE, config_set_pw_is_global_policy,
NULL, 0,
(void**)&global_slapdFrontendConfig.pw_is_global_policy, CONFIG_ON_OFF, NULL},
+ {CONFIG_PW_IS_LEGACY, config_set_pw_is_legacy_policy,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.pw_policy.pw_is_legacy, CONFIG_ON_OFF, NULL},
{CONFIG_AUDITLOG_MAXNUMOFLOGSPERDIR_ATTRIBUTE, NULL,
log_set_numlogsperdir, SLAPD_AUDIT_LOG,
(void**)&global_slapdFrontendConfig.auditlog_maxnumlogs, CONFIG_INT, NULL},
@@ -1017,6 +1020,7 @@ FrontendConfig_init () {
cfg->pw_policy.pw_lockduration = 3600; /* 60 minutes */
cfg->pw_policy.pw_resetfailurecount = 600; /* 10 minutes */
cfg->pw_policy.pw_gracelimit = 0;
+ cfg->pw_policy.pw_is_legacy = LDAP_ON;
cfg->pw_is_global_policy = LDAP_OFF;
cfg->accesslog_logging_enabled = LDAP_ON;
@@ -2417,6 +2421,20 @@ config_set_pw_is_global_policy( const char *attrname, char *value, char *errorbu
}
int
+config_set_pw_is_legacy_policy( const char *attrname, char *value, char *errorbuf, int apply ) {
+ int retVal = LDAP_SUCCESS;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ retVal = config_set_onoff ( attrname,
+ value,
+ &(slapdFrontendConfig->pw_policy.pw_is_legacy),
+ errorbuf,
+ apply);
+
+ return retVal;
+}
+
+int
config_set_pw_exp( const char *attrname, char *value, char *errorbuf, int apply ) {
int retVal = LDAP_SUCCESS;
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
@@ -4235,6 +4253,18 @@ config_get_pw_is_global_policy() {
}
int
+config_get_pw_is_legacy_policy() {
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ int retVal;
+
+ CFG_LOCK_READ(slapdFrontendConfig);
+ retVal = slapdFrontendConfig->pw_policy.pw_is_legacy;
+ CFG_UNLOCK_READ(slapdFrontendConfig);
+
+ return retVal;
+}
+
+int
config_get_pw_exp() {
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
int retVal;
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 9bbcf53..d291be3 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -340,6 +340,7 @@ int config_set_pw_unlock(const char *attrname, char *value, char *errorbuf, int
int config_set_pw_lockduration(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_pw_resetfailurecount(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_pw_is_global_policy(const char *attrname, char *value, char *errorbuf, int apply );
+int config_set_pw_is_legacy_policy(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_pw_gracelimit(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_useroc(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_return_exact_case(const char *attrname, char *value, char *errorbuf, int apply );
diff --git a/ldap/servers/slapd/pw.h b/ldap/servers/slapd/pw.h
index 83f0003..a470fdd 100644
--- a/ldap/servers/slapd/pw.h
+++ b/ldap/servers/slapd/pw.h
@@ -96,6 +96,6 @@ int check_pw_storagescheme_value( const char *attr_name, char *value, long minva
* Public functions from pw_retry.c:
*/
Slapi_Entry *get_entry ( Slapi_PBlock *pb, const char *dn );
-void set_retry_cnt_mods ( Slapi_PBlock *pb, Slapi_Mods *smods, int count);
+int set_retry_cnt_mods ( Slapi_PBlock *pb, Slapi_Mods *smods, int count);
#endif /* _SLAPD_PW_H_ */
diff --git a/ldap/servers/slapd/pw_retry.c b/ldap/servers/slapd/pw_retry.c
index 5244622..09d0ed0 100644
--- a/ldap/servers/slapd/pw_retry.c
+++ b/ldap/servers/slapd/pw_retry.c
@@ -50,8 +50,8 @@
/* prototypes */
/****************************************************************************/
/* Slapi_Entry *get_entry ( Slapi_PBlock *pb, const char *dn ); */
-static void set_retry_cnt ( Slapi_PBlock *pb, int count);
-static void set_retry_cnt_and_time ( Slapi_PBlock *pb, int count, time_t cur_time);
+static int set_retry_cnt ( Slapi_PBlock *pb, int count);
+static int set_retry_cnt_and_time ( Slapi_PBlock *pb, int count, time_t cur_time);
/*
* update_pw_retry() is called when bind operation fails
@@ -72,6 +72,7 @@ int update_pw_retry ( Slapi_PBlock *pb )
char *cur_time_str = NULL;
char *retryCountResetTime;
int passwordRetryCount;
+ int rc = 0;
/* get the entry */
e = get_entry ( pb, NULL );
@@ -93,18 +94,18 @@ int update_pw_retry ( Slapi_PBlock *pb )
{
/* set passwordRetryCount to 1 */
/* reset retryCountResetTime */
- set_retry_cnt_and_time ( pb, 1, cur_time );
+ rc = set_retry_cnt_and_time ( pb, 1, cur_time );
slapi_ch_free((void **) &cur_time_str );
slapi_entry_free( e );
- return ( 0 ); /* success */
+ return ( rc ); /* success */
} else {
slapi_ch_free((void **) &cur_time_str );
}
} else {
/* initialize passwordRetryCount and retryCountResetTime */
- set_retry_cnt_and_time ( pb, 1, cur_time );
+ rc = set_retry_cnt_and_time ( pb, 1, cur_time );
slapi_entry_free( e );
- return ( 0 ); /* success */
+ return ( rc ); /* success */
}
passwordRetryCount = slapi_entry_attr_get_int(e, "passwordRetryCount");
if (passwordRetryCount >= 0)
@@ -112,24 +113,25 @@ int update_pw_retry ( Slapi_PBlock *pb )
retry_cnt = passwordRetryCount + 1;
if ( retry_cnt == 1 ) {
/* set retryCountResetTime */
- set_retry_cnt_and_time ( pb, retry_cnt, cur_time );
+ rc = set_retry_cnt_and_time ( pb, retry_cnt, cur_time );
} else {
/* set passwordRetryCount to retry_cnt */
- set_retry_cnt ( pb, retry_cnt );
+ rc = set_retry_cnt ( pb, retry_cnt );
}
}
slapi_entry_free( e );
- return 0; /* success */
+ return rc; /* success */
}
static
-void set_retry_cnt_and_time ( Slapi_PBlock *pb, int count, time_t cur_time ) {
+int set_retry_cnt_and_time ( Slapi_PBlock *pb, int count, time_t cur_time ) {
const char *dn = NULL;
Slapi_DN *sdn = NULL;
Slapi_Mods smods;
time_t reset_time;
char *timestr;
passwdPolicy *pwpolicy = NULL;
+ int rc = 0;
slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn );
dn = slapi_sdn_get_dn(sdn);
@@ -144,14 +146,16 @@ void set_retry_cnt_and_time ( Slapi_PBlock *pb, int count, time_t cur_time ) {
slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "retryCountResetTime", timestr);
slapi_ch_free((void **)×tr);
- set_retry_cnt_mods(pb, &smods, count);
+ rc = set_retry_cnt_mods(pb, &smods, count);
pw_apply_mods(sdn, &smods);
slapi_mods_done(&smods);
delete_passwdPolicy(&pwpolicy);
+
+ return rc;
}
-void set_retry_cnt_mods(Slapi_PBlock *pb, Slapi_Mods *smods, int count)
+int set_retry_cnt_mods(Slapi_PBlock *pb, Slapi_Mods *smods, int count)
{
char *timestr;
time_t unlock_time;
@@ -159,6 +163,7 @@ void set_retry_cnt_mods(Slapi_PBlock *pb, Slapi_Mods *smods, int count)
const char *dn = NULL;
Slapi_DN *sdn = NULL;
passwdPolicy *pwpolicy = NULL;
+ int rc = 0;
slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn );
dn = slapi_sdn_get_dn(sdn);
@@ -182,23 +187,26 @@ void set_retry_cnt_mods(Slapi_PBlock *pb, Slapi_Mods *smods, int count)
timestr= format_genTime ( unlock_time );
slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "accountUnlockTime", timestr);
slapi_ch_free((void **)×tr);
+ rc = LDAP_CONSTRAINT_VIOLATION;
}
}
delete_passwdPolicy(&pwpolicy);
- return;
+ return rc;
}
static
-void set_retry_cnt ( Slapi_PBlock *pb, int count)
+int set_retry_cnt ( Slapi_PBlock *pb, int count)
{
Slapi_DN *sdn = NULL;
Slapi_Mods smods;
+ int rc = 0;
slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn );
slapi_mods_init(&smods, 0);
- set_retry_cnt_mods(pb, &smods, count);
+ rc = set_retry_cnt_mods(pb, &smods, count);
pw_apply_mods(sdn, &smods);
slapi_mods_done(&smods);
+ return rc;
}
diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c
index 6f36a60..4712ea1 100644
--- a/ldap/servers/slapd/result.c
+++ b/ldap/servers/slapd/result.c
@@ -377,7 +377,15 @@ send_ldap_result_ext(
dn = slapi_sdn_get_dn(sdn);
pwpolicy = new_passwdPolicy(pb, dn);
if (pwpolicy && (pwpolicy->pw_lockout == 1)) {
- update_pw_retry ( pb );
+ if(update_pw_retry( pb ) == LDAP_CONSTRAINT_VIOLATION && !pwpolicy->pw_is_legacy){
+ /*
+ * If we are not using the legacy pw policy behavior,
+ * convert the error 49 to 19 (constraint violation)
+ * and log a message
+ */
+ err = LDAP_CONSTRAINT_VIOLATION;
+ text = "Invalid credentials, you now have exceeded the password retry limit.";
+ }
}
}
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index f7c0bf2..669e304 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1952,6 +1952,7 @@ typedef struct _slapdEntryPoints {
#define CONFIG_PW_RESETFAILURECOUNT_ATTRIBUTE "passwordResetFailureCount"
#define CONFIG_PW_ISGLOBAL_ATTRIBUTE "passwordIsGlobalPolicy"
#define CONFIG_PW_GRACELIMIT_ATTRIBUTE "passwordGraceLimit"
+#define CONFIG_PW_IS_LEGACY "passwordLegacyPolicy"
#define CONFIG_ACCESSLOG_BUFFERING_ATTRIBUTE "nsslapd-accesslog-logbuffering"
#define CONFIG_CSNLOGGING_ATTRIBUTE "nsslapd-csnlogging"
#define CONFIG_RETURN_EXACT_CASE_ATTRIBUTE "nsslapd-return-exact-case"
@@ -2039,6 +2040,7 @@ typedef struct passwordpolicyarray {
long pw_lockduration;
long pw_resetfailurecount;
int pw_gracelimit;
+ int pw_is_legacy;
struct pw_scheme *pw_storagescheme;
} passwdPolicy;
11 years, 11 months
ldap/servers
by Mark Reynolds
ldap/servers/slapd/libglobs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
New commits:
commit c039fd48c4af834503306e52a97e3856eb33c010
Author: Mark Reynolds <mareynol(a)redhat.com>
Date: Thu Apr 5 11:14:52 2012 -0400
Ticket #315 - small fix to libglobs
Accidentally used CONFIG_DISK_PRESERVE_LOGGING instead of CONFIG_DISK_LOGGING_CRITICAL
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index 26c696e..8bcd544 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -674,7 +674,7 @@ static struct config_get_and_set {
NULL, 0,
(void**)&global_slapdFrontendConfig.disk_grace_period,
CONFIG_INT, (ConfigGetFunc)config_get_disk_grace_period},
- {CONFIG_DISK_PRESERVE_LOGGING, config_set_disk_logging_critical,
+ {CONFIG_DISK_LOGGING_CRITICAL, config_set_disk_logging_critical,
NULL, 0,
(void**)&global_slapdFrontendConfig.disk_logging_critical,
CONFIG_ON_OFF, (ConfigGetFunc)config_get_disk_logging_critical},
11 years, 12 months
ldap/servers
by Mark Reynolds
ldap/servers/slapd/back-ldbm/dblayer.c | 18
ldap/servers/slapd/back-ldbm/ldbm_config.c | 12
ldap/servers/slapd/back-ldbm/proto-back-ldbm.h | 1
ldap/servers/slapd/daemon.c | 511 ++++++++++++++++++++++++-
ldap/servers/slapd/libglobs.c | 257 +++++++++++-
ldap/servers/slapd/log.c | 65 +++
ldap/servers/slapd/proto-slap.h | 16
ldap/servers/slapd/slap.h | 12
ldap/servers/slapd/slapi-plugin.h | 4
9 files changed, 849 insertions(+), 47 deletions(-)
New commits:
commit 65f473cb6d1299d88a0d2decf7d49eee3164702a
Author: Mark Reynolds <mareynol(a)redhat.com>
Date: Wed Apr 4 17:50:16 2012 -0400
Ticket #315 - ns-slapd exits/crashes if /var fills up
Bug Description: Once /var fills up the DS will crash.
Fix Description: Created a new feature to monitor the disk space used by DS.
Once the available disk space gets critical we shutdown
the process.
For complete details see "Disk_Monitoring" text file
https://fedorahosted.org/389/ticket/315
Reviewed by:
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
index c1a123c..132b2b9 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -6613,6 +6613,24 @@ ldbm_back_get_info(Slapi_Backend *be, int cmd, void **info)
}
break;
}
+ case BACK_INFO_DIRECTORY:
+ {
+ struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private;
+ if (li) {
+ *(char **)info = li->li_directory;
+ rc = 0;
+ }
+ break;
+ }
+ case BACK_INFO_LOG_DIRECTORY:
+ {
+ struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private;
+ if (li) {
+ *(char **)info = ldbm_config_db_logdirectory_get_ext((void *)li);
+ rc = 0;
+ }
+ break;
+ }
default:
break;
}
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c
index b179591..d0664eb 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_config.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c
@@ -469,7 +469,7 @@ static int ldbm_config_dbncache_set(void *arg, void *value, char *errorbuf, int
return retval;
}
-static void *ldbm_config_db_logdirectory_get(void *arg)
+void *ldbm_config_db_logdirectory_get(void *arg)
{
struct ldbminfo *li = (struct ldbminfo *) arg;
@@ -483,7 +483,17 @@ static void *ldbm_config_db_logdirectory_get(void *arg)
return (void *) slapi_ch_strdup(li->li_dblayer_private->dblayer_log_directory);
else
return (void *) slapi_ch_strdup(li->li_new_directory);
+}
+
+/* Does not return a copy of the string - used by disk space monitoring feature */
+void *ldbm_config_db_logdirectory_get_ext(void *arg)
+{
+ struct ldbminfo *li = (struct ldbminfo *) arg;
+ if (strlen(li->li_dblayer_private->dblayer_log_directory) > 0)
+ return (void *)li->li_dblayer_private->dblayer_log_directory;
+ else
+ return (void *)li->li_new_directory;
}
static int ldbm_config_db_logdirectory_set(void *arg, void *value, char *errorbuf, int phase, int apply)
diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
index 0734162..f93358b 100644
--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
@@ -615,6 +615,7 @@ int dbversion_exists(struct ldbminfo *li, const char *directory);
int ldbm_config_load_dse_info(struct ldbminfo *li);
void ldbm_config_setup_default(struct ldbminfo *li);
void ldbm_config_internal_set(struct ldbminfo *li, char *attrname, char *value);
+void *ldbm_config_db_logdirectory_get_ext(void *arg);
void ldbm_instance_config_internal_set(ldbm_instance *inst, char *attrname, char *value);
void ldbm_instance_config_setup_default(ldbm_instance *inst);
int ldbm_instance_postadd_instance_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg);
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index 85daa28..01d307d 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -59,6 +59,7 @@
#include <sys/time.h>
#include <sys/wait.h>
#include <pthread.h>
+#include <mntent.h>
#endif
#include <time.h>
#include <signal.h>
@@ -81,15 +82,17 @@
/* for some reason, linux tty stuff defines CTIME */
#ifdef LINUX
#undef CTIME
+#include <sys/statfs.h>
+#else
+#include <sys/statvfs.h>
+#include <sys/mnttab.h>
#endif
#include "slap.h"
#include "slapi-plugin.h"
-
#include "snmp_collator.h"
#include <private/pprio.h>
-
#include <ssl.h>
-
+#include <stdio.h>
#include "fe.h"
#if defined(ENABLE_LDAPI)
@@ -126,9 +129,12 @@ PRFileDesc* signalpipe[2];
static int writesignalpipe = SLAPD_INVALID_SOCKET;
static int readsignalpipe = SLAPD_INVALID_SOCKET;
-#define FDS_SIGNAL_PIPE 0
-
+static PRThread *disk_thread_p = NULL;
+static PRCondVar *diskmon_cvar = NULL;
+static PRLock *diskmon_mutex = NULL;
+void disk_monitoring_stop();
+#define FDS_SIGNAL_PIPE 0
static int get_configured_connection_table_size();
#ifdef RESOLVER_NEEDS_LOW_FILE_DESCRIPTORS
@@ -155,7 +161,6 @@ HANDLE hServDoneEvent = NULL;
static int createsignalpipe( void );
-
#if defined( _WIN32 )
/* Set an event to hook the NT Service termination */
void *slapd_service_exit_wait()
@@ -470,6 +475,444 @@ time_thread(void *nothing)
return(NULL);
}
+/*
+ * Return a copy of the mount point for the specified directory
+ */
+#ifdef SOLARIS
+char *
+disk_mon_get_mount_point(char *dir)
+{
+ struct mnttab *mnt;
+ struct stat s;
+ dev_t dev_id;
+ FILE *fp;
+
+ fp = fopen("/etc/mnttab", "r");
+
+ if (fp == NULL || stat(dir, &s) != 0) {
+ return NULL;
+ }
+
+ dev_id = s.st_dev;
+
+ while((mnt = getmntent(fp))){
+ if (stat(mnt->mnt_mountp, &s) != 0) {
+ continue;
+ }
+ if (s.st_dev == dev_id) {
+ return (slapi_ch_strdup(mnt->mnt_mountp));
+ }
+ }
+
+ return NULL;
+}
+#elif HPUX
+char *
+disk_mon_get_mount_point(char *dir)
+{
+ struct mntent *mnt;
+ struct stat s;
+ dev_t dev_id;
+ FILE *fp;
+
+ if ((fp = setmntent("/etc/mnttab", "r")) == NULL) {
+ return NULL;
+ }
+
+ if (stat(dir, &s) != 0) {
+ return NULL;
+ }
+
+ dev_id = s.st_dev;
+
+ while((mnt = getmntent(fp))){
+ if (stat(mnt->mnt_dir, &s) != 0) {
+ continue;
+ }
+ if (s.st_dev == dev_id) {
+ endmntent(fp);
+ return (slapi_ch_strdup(mnt->mnt_dir));
+ }
+ }
+ endmntent(fp);
+
+ return NULL;
+}
+#else /* Linux */
+char *
+disk_mon_get_mount_point(char *dir)
+{
+ struct mntent *mnt;
+ struct stat s;
+ dev_t dev_id;
+ FILE *fp;
+
+ if (stat(dir, &s) != 0) {
+ return NULL;
+ }
+
+ dev_id = s.st_dev;
+ if ((fp = setmntent("/proc/mounts", "r")) == NULL) {
+ return NULL;
+ }
+ while((mnt = getmntent(fp))){
+ if (stat(mnt->mnt_dir, &s) != 0) {
+ continue;
+ }
+ if (s.st_dev == dev_id) {
+ endmntent(fp);
+ return (slapi_ch_strdup(mnt->mnt_dir));
+ }
+ }
+ endmntent(fp);
+
+ return NULL;
+}
+#endif
+
+/*
+ * Get the mount point of the directory, and add it to the
+ * list. Skip duplicate mount points.
+ */
+void
+disk_mon_add_dir(char ***list, char *directory)
+{
+ char *dir = disk_mon_get_mount_point(directory);
+
+ if(dir == NULL)
+ return;
+
+ if(!charray_inlist(*list,dir)){
+ slapi_ch_array_add(list, dir);
+ } else {
+ slapi_ch_free((void **)&dir);
+ }
+}
+
+/*
+ * We gather all the log, txn log, config, and db directories
+ */
+void
+disk_mon_get_dirs(char ***list, int logs_critical){
+ slapdFrontendConfig_t *config = getFrontendConfig();
+ Slapi_Backend *be = NULL;
+ char *cookie = NULL;
+ char *dir = NULL;
+
+ if(logs_critical){
+ slapi_rwlock_rdlock(config->cfg_rwlock);
+ disk_mon_add_dir(list, config->accesslog);
+ disk_mon_add_dir(list, config->errorlog);
+ disk_mon_add_dir(list, config->auditlog);
+ slapi_rwlock_unlock(config->cfg_rwlock);
+ }
+
+ /* Add /var just to be safe */
+#ifdef LOCALSTATEDIR
+ disk_mon_add_dir(list, LOCALSTATEDIR);
+#else
+ disk_mon_add_dir(list, "/var");
+#endif
+
+ /* config and backend directories */
+ slapi_rwlock_rdlock(config->cfg_rwlock);
+ disk_mon_add_dir(list, config->configdir);
+ slapi_rwlock_unlock(config->cfg_rwlock);
+
+ be = slapi_get_first_backend (&cookie);
+ while (be) {
+ if(slapi_back_get_info(be, BACK_INFO_DIRECTORY, (void **)&dir) == LDAP_SUCCESS){ /* db directory */
+ disk_mon_add_dir(list, dir);
+ }
+ if(slapi_back_get_info(be, BACK_INFO_LOG_DIRECTORY, (void **)&dir) == LDAP_SUCCESS){ /* txn log dir */
+ disk_mon_add_dir(list, dir);
+ }
+ be = (backend *)slapi_get_next_backend (cookie);
+ }
+}
+
+/*
+ * This function checks the list of directories to see if any are below the
+ * threshold. We return the the directory/free disk space of the most critical
+ * directory.
+ */
+char *
+disk_mon_check_diskspace(char **dirs, PRInt64 threshold, PRInt64 *disk_space)
+{
+#ifdef LINUX
+ struct statfs buf;
+#else
+ struct statvfs buf;
+#endif
+ PRInt64 worst_disk_space = threshold;
+ PRInt64 freeBytes = 0;
+ PRInt64 blockSize = 0;
+ char *worst_dir = NULL;
+ int hit_threshold = 0;
+ int i = 0;
+
+ for(i = 0; dirs && dirs[i]; i++){
+#ifndef LINUX
+ if (statvfs(dirs[i], &buf) != -1)
+#else
+ if (statfs(dirs[i], &buf) != -1)
+#endif
+ {
+ LL_UI2L(freeBytes, buf.f_bavail);
+ LL_UI2L(blockSize, buf.f_bsize);
+ LL_MUL(freeBytes, freeBytes, blockSize);
+
+ if(LL_UCMP(freeBytes, <, threshold)){
+ hit_threshold = 1;
+ if(LL_UCMP(freeBytes, <, worst_disk_space)){
+ worst_disk_space = freeBytes;
+ worst_dir = dirs[i];
+ }
+ }
+ }
+ }
+
+ if(hit_threshold){
+ *disk_space = worst_disk_space;
+ return worst_dir;
+ } else {
+ *disk_space = 0;
+ return NULL;
+ }
+}
+
+#define LOGGING_OFF 0
+#define LOGGING_ON 1
+/*
+ * Disk Space Monitoring Thread
+ *
+ * We need to monitor the free disk space of critical disks.
+ *
+ * If we get below the free disk space threshold, start taking measures
+ * to avoid additional disk space consumption by stopping verbose logging,
+ * access/audit logging, and deleting rotated logs.
+ *
+ * If this is not enough, then we need to shut slapd down to avoid
+ * possibly corrupting the db.
+ *
+ * Future - it would be nice to be able to email an alert.
+ */
+void
+disk_monitoring_thread(void *nothing)
+{
+ char errorbuf[BUFSIZ];
+ char **dirs = NULL;
+ char *dirstr = NULL;
+ PRInt64 previous_mark = 0;
+ PRInt64 disk_space = 0;
+ PRInt64 threshold = 0;
+ time_t start = 0;
+ time_t now = 0;
+ int deleted_rotated_logs = 0;
+ int logging_critical = 0;
+ int preserve_logging = 0;
+ int passed_threshold = 0;
+ int verbose_logging = 0;
+ int using_accesslog = 0;
+ int using_auditlog = 0;
+ int logs_disabled = 0;
+ int grace_period = 0;
+ int first_pass = 1;
+ int halfway = 0;
+ int ok_now = 0;
+
+ while(!g_get_shutdown()) {
+ if(!first_pass){
+ PR_Lock(diskmon_mutex);
+ PR_WaitCondVar(diskmon_cvar, PR_SecondsToInterval(10));
+ PR_Unlock(diskmon_mutex);
+ /*
+ * We need to subtract from disk_space to account for the
+ * logging we just did, it doesn't hurt if we subtract a
+ * little more than necessary.
+ */
+ previous_mark = disk_space - 512;
+ ok_now = 0;
+ } else {
+ first_pass = 0;
+ }
+ /*
+ * Get the config settings, as they could have changed
+ */
+ logging_critical = config_get_disk_logging_critical();
+ preserve_logging = config_get_disk_preserve_logging();
+ grace_period = 60 * config_get_disk_grace_period(); /* convert it to seconds */
+ verbose_logging = config_get_errorlog_level();
+ threshold = config_get_disk_threshold();
+ halfway = threshold / 2;
+
+ if(config_get_auditlog_logging_enabled()){
+ using_auditlog = 1;
+ }
+ if(config_get_accesslog_logging_enabled()){
+ using_accesslog = 1;
+ }
+ /*
+ * Check the disk space. Always refresh the list, as backends can be added
+ */
+ slapi_ch_array_free(dirs);
+ dirs = NULL;
+ disk_mon_get_dirs(&dirs, logging_critical);
+ dirstr = disk_mon_check_diskspace(dirs, threshold, &disk_space);
+ if(dirstr == NULL){
+ /*
+ * Good, none of our disks are within the threshold,
+ * reset the logging if we turned it off
+ */
+ if(passed_threshold){
+ if(logs_disabled){
+ LDAPDebug(LDAP_DEBUG_ANY, "Disk space is now within acceptable levels. "
+ "Restoring the log settings.\n",0,0,0);
+ if(using_accesslog){
+ config_set_accesslog_enabled(LOGGING_ON);
+ }
+ if(using_auditlog){
+ config_set_auditlog_enabled(LOGGING_ON);
+ }
+ } else {
+ LDAPDebug(LDAP_DEBUG_ANY, "Disk space is now within acceptable levels.\n",0,0,0);
+ }
+ deleted_rotated_logs = 0;
+ passed_threshold = 0;
+ previous_mark = 0;
+ logs_disabled = 0;
+ }
+ continue;
+ } else {
+ passed_threshold = 1;
+ }
+ /*
+ * Check if we are already critical
+ */
+ if(disk_space < 4096){ /* 4 k */
+ LDAPDebug(LDAP_DEBUG_ANY, "Disk space is critically low on disk (%s), remaining space: %d Kb. "
+ "Signaling slapd for shutdown...\n", dirstr , (disk_space / 1024), 0);
+ g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
+ return;
+ }
+ /*
+ * If we are low, see if we are using verbose error logging, and turn it off
+ */
+ if(verbose_logging){
+ LDAPDebug(LDAP_DEBUG_ANY, "Disk space is low on disk (%s), remaining space: %d Kb, "
+ "setting error loglevel to zero.\n", dirstr, (disk_space / 1024), 0);
+ config_set_errorlog_level(CONFIG_LOGLEVEL_ATTRIBUTE, 0, errorbuf, CONFIG_APPLY);
+ continue;
+ }
+ /*
+ * If we are low, there's no verbose logging, logs are not critical, then disable the
+ * access/audit logs, log another error, and continue.
+ */
+ if(!logs_disabled && (!preserve_logging || !logging_critical)){
+ if(disk_space < previous_mark){
+ LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb, "
+ "disabling access and audit logging.\n", dirstr, (disk_space / 1024), 0);
+ config_set_accesslog_enabled(LOGGING_OFF);
+ config_set_auditlog_enabled(LOGGING_OFF);
+ logs_disabled = 1;
+ }
+ continue;
+ }
+ /*
+ * If we are low, we turned off verbose logging, logs are not critical, and we disabled
+ * access/audit logging, then delete the rotated logs, log another error, and continue.
+ */
+ if(!deleted_rotated_logs && (!preserve_logging || !logging_critical)){
+ if(disk_space < previous_mark){
+ LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb, "
+ "deleting rotated logs.\n", dirstr, (disk_space / 1024), 0);
+ log__delete_rotated_logs();
+ deleted_rotated_logs = 1;
+ }
+ continue;
+ }
+ /*
+ * Ok, we've done what we can, log a message if we continue to lose available disk space
+ */
+ if(disk_space < previous_mark){
+ LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb\n",
+ dirstr, (disk_space / 1024), 0);
+ }
+ /*
+ *
+ * If we are below the halfway mark, and we did everything else,
+ * go into shutdown mode. If the disk space doesn't get critical,
+ * wait for the grace period before shutting down. This gives an
+ * admin the chance to clean things up.
+ *
+ */
+ if(disk_space < halfway){
+ LDAPDebug(LDAP_DEBUG_ANY, "Disk space on (%s) is too far below the threshold(%d bytes). "
+ "Waiting %d minutes for disk space to be cleaned up before shutting slapd down...\n",
+ dirstr, threshold, (grace_period / 60));
+ time(&start);
+ now = start;
+ while( (now - start) < grace_period ){
+ if(g_get_shutdown()){
+ return;
+ }
+ /*
+ * Sleep for a little bit, but we don't want to run out of disk space
+ * while sleeping for the entire grace period
+ */
+ DS_Sleep(PR_SecondsToInterval(1));
+ /*
+ * Now check disk space again in hopes some space was freed up
+ */
+ dirstr = disk_mon_check_diskspace(dirs, threshold, &disk_space);
+ if(!dirstr){
+ /*
+ * Excellent, we are back to acceptable levels, reset everything...
+ */
+ LDAPDebug(LDAP_DEBUG_ANY, "Available disk space is now acceptable (%d bytes). Aborting"
+ " shutdown, and restoring the log settings.\n",disk_space,0,0);
+ if(!preserve_logging && using_accesslog){
+ config_set_accesslog_enabled(LOGGING_ON);
+ }
+ if(!preserve_logging && using_auditlog){
+ config_set_auditlog_enabled(LOGGING_ON);
+ }
+ deleted_rotated_logs = 0;
+ passed_threshold = 0;
+ logs_disabled = 0;
+ previous_mark = 0;
+ ok_now = 1;
+ start = 0;
+ now = 0;
+ break;
+ } else if(disk_space < 4096){ /* 4 k */
+ /*
+ * Disk space is critical, log an error, and shut it down now!
+ */
+ LDAPDebug(LDAP_DEBUG_ANY, "Disk space is critically low on disk (%s), remaining space: %d Kb."
+ " Signaling slapd for shutdown...\n", dirstr, (disk_space / 1024), 0);
+ g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
+ return;
+ }
+ time(&now);
+ }
+
+ if(ok_now){
+ /*
+ * Disk space is acceptable, resume normal processing
+ */
+ continue;
+ }
+ /*
+ * If disk space was freed up we would of detected in the above while loop. So shut it down.
+ */
+ LDAPDebug(LDAP_DEBUG_ANY, "Disk space is still too low (%d Kb). Signaling slapd for shutdown...\n",
+ (disk_space / 1024), 0, 0);
+ g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
+ return;
+ }
+ }
+}
void slapd_daemon( daemon_ports_t *ports )
{
@@ -563,7 +1006,44 @@ void slapd_daemon( daemon_ports_t *ports )
g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
}
- /* We are now ready to accept imcoming connections */
+ /*
+ * If we are monitoring disk space, then create the mutex, the cvar,
+ * and the monitoring thread.
+ */
+ if( config_get_disk_monitoring() ){
+ if ( ( diskmon_mutex = PR_NewLock() ) == NULL ) {
+ slapi_log_error(SLAPI_LOG_FATAL, NULL,
+ "Cannot create new lock for disk space monitoring. "
+ SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
+ PR_GetError(), slapd_pr_strerror( PR_GetError() ));
+ g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
+ }
+ if ( diskmon_mutex ){
+ if(( diskmon_cvar = PR_NewCondVar( diskmon_mutex )) == NULL ) {
+ slapi_log_error(SLAPI_LOG_FATAL, NULL,
+ "Cannot create new condition variable for disk space monitoring. "
+ SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
+ PR_GetError(), slapd_pr_strerror( PR_GetError() ));
+ g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
+ }
+ }
+ if( diskmon_mutex && diskmon_cvar ){
+ disk_thread_p = PR_CreateThread(PR_SYSTEM_THREAD,
+ (VFP) (void *) disk_monitoring_thread, NULL,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ SLAPD_DEFAULT_THREAD_STACKSIZE);
+ if ( NULL == disk_thread_p ) {
+ PRErrorCode errorCode = PR_GetError();
+ LDAPDebug(LDAP_DEBUG_ANY, "Unable to create disk monitoring thread - Shutting Down ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)\n",
+ errorCode, slapd_pr_strerror(errorCode), 0);
+ g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
+ }
+ }
+ }
+
+ /* We are now ready to accept incoming connections */
#if defined( XP_WIN32 )
if ( n_tcps != SLAPD_INVALID_SOCKET
&& listen( n_tcps, DAEMON_LISTEN_SIZE ) == -1 ) {
@@ -807,6 +1287,7 @@ void slapd_daemon( daemon_ports_t *ports )
be_flushall();
op_thread_cleanup();
housekeeping_stop(); /* Run this after op_thread_cleanup() logged sth */
+ disk_monitoring_stop(disk_thread_p);
#ifndef _WIN32
threads = g_get_active_threadcnt();
@@ -3128,10 +3609,10 @@ void configure_ns_socket( int * ns )
on = 0;
setsockopt( *ns, IPPROTO_TCP, TCP_NODELAY, (char * ) &on, sizeof(on) );
} /* else (!enable_nagle) */
-
-
+
+
return;
-
+
}
@@ -3158,3 +3639,13 @@ get_loopback_by_addr( void )
AF_INET, &hp, hbuf, sizeof(hbuf), &herrno );
}
#endif /* RESOLVER_NEEDS_LOW_FILE_DESCRIPTORS */
+
+void
+disk_monitoring_stop()
+{
+ if ( disk_thread_p ) {
+ PR_Lock( diskmon_mutex );
+ PR_NotifyCondVar( diskmon_cvar );
+ PR_Unlock( diskmon_mutex );
+ }
+}
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index b6c0c1f..26c696e 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -662,6 +662,26 @@ static struct config_get_and_set {
NULL, 0,
(void**)&global_slapdFrontendConfig.default_naming_context,
CONFIG_STRING, (ConfigGetFunc)config_get_default_naming_context},
+ {CONFIG_DISK_MONITORING, config_set_disk_monitoring,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.disk_monitoring, CONFIG_ON_OFF,
+ (ConfigGetFunc)config_get_disk_monitoring},
+ {CONFIG_DISK_THRESHOLD, config_set_disk_threshold,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.disk_threshold, CONFIG_INT,
+ (ConfigGetFunc)config_get_disk_threshold},
+ {CONFIG_DISK_GRACE_PERIOD, config_set_disk_grace_period,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.disk_grace_period,
+ CONFIG_INT, (ConfigGetFunc)config_get_disk_grace_period},
+ {CONFIG_DISK_PRESERVE_LOGGING, config_set_disk_logging_critical,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.disk_logging_critical,
+ CONFIG_ON_OFF, (ConfigGetFunc)config_get_disk_logging_critical},
+ {CONFIG_DISK_PRESERVE_LOGGING, config_set_disk_preserve_logging,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.disk_preserve_logging,
+ CONFIG_ON_OFF, (ConfigGetFunc)config_get_disk_preserve_logging},
#ifdef MEMPOOL_EXPERIMENTAL
,{CONFIG_MEMPOOL_SWITCH_ATTRIBUTE, config_set_mempool_switch,
NULL, 0,
@@ -1050,6 +1070,12 @@ FrontendConfig_init () {
cfg->allowed_to_delete_attrs = slapi_ch_strdup("nsslapd-listenhost nsslapd-securelistenhost nsslapd-defaultnamingcontext");
cfg->default_naming_context = NULL; /* store normalized dn */
+ cfg->disk_monitoring = LDAP_OFF;
+ cfg->disk_threshold = 2097152; /* 2 mb */
+ cfg->disk_grace_period = 60; /* 1 hour */
+ cfg->disk_preserve_logging = LDAP_OFF;
+ cfg->disk_logging_critical = LDAP_OFF;
+
#ifdef MEMPOOL_EXPERIMENTAL
cfg->mempool_switch = LDAP_ON;
cfg->mempool_maxfreelist = 1024;
@@ -1159,7 +1185,98 @@ config_value_is_null( const char *attrname, const char *value, char *errorbuf,
return 0;
}
+int
+config_set_disk_monitoring( const char *attrname, char *value, char *errorbuf, int apply )
+{
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ int retVal = LDAP_SUCCESS;
+ retVal = config_set_onoff ( attrname, value, &(slapdFrontendConfig->disk_monitoring),
+ errorbuf, apply);
+ return retVal;
+}
+
+int
+config_set_disk_threshold( const char *attrname, char *value, char *errorbuf, int apply )
+{
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ int retVal = LDAP_SUCCESS;
+ long threshold = 0;
+ char *endp = NULL;
+
+ if ( config_value_is_null( attrname, value, errorbuf, 0 )) {
+ return LDAP_OPERATIONS_ERROR;
+ }
+
+ threshold = strtol(value, &endp, 10);
+
+ if ( *endp != '\0' || threshold < 2048 ) {
+ PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "%s: \"%s\" is invalid, threshold must be greater than 2048 and less then %ld",
+ attrname, value, LONG_MAX );
+ retVal = LDAP_OPERATIONS_ERROR;
+ return retVal;
+ }
+
+ if (apply) {
+ CFG_LOCK_WRITE(slapdFrontendConfig);
+ slapdFrontendConfig->disk_threshold = threshold;
+ CFG_UNLOCK_WRITE(slapdFrontendConfig);
+ }
+
+ return retVal;
+}
+
+int
+config_set_disk_preserve_logging( const char *attrname, char *value, char *errorbuf, int apply )
+{
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ int retVal = LDAP_SUCCESS;
+
+ retVal = config_set_onoff ( attrname, value, &(slapdFrontendConfig->disk_preserve_logging),
+ errorbuf, apply);
+ return retVal;
+}
+
+int
+config_set_disk_logging_critical( const char *attrname, char *value, char *errorbuf, int apply )
+{
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ int retVal = LDAP_SUCCESS;
+
+ retVal = config_set_onoff ( attrname, value, &(slapdFrontendConfig->disk_logging_critical),
+ errorbuf, apply);
+ return retVal;
+}
+
+int
+config_set_disk_grace_period( const char *attrname, char *value, char *errorbuf, int apply )
+{
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ int retVal = LDAP_SUCCESS;
+ int period = 0;
+ char *endp = NULL;
+
+ if ( config_value_is_null( attrname, value, errorbuf, 0 )) {
+ return LDAP_OPERATIONS_ERROR;
+ }
+
+ period = strtol(value, &endp, 10);
+
+ if ( *endp != '\0' || period < 1 ) {
+ PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "%s: \"%s\" is invalid, grace period must be at least 1 minute",
+ attrname, value);
+ retVal = LDAP_OPERATIONS_ERROR;
+ return retVal;
+ }
+
+ if (apply) {
+ CFG_LOCK_WRITE(slapdFrontendConfig);
+ slapdFrontendConfig->disk_grace_period = period;
+ CFG_UNLOCK_WRITE(slapdFrontendConfig);
+ }
+
+ return retVal;
+}
int
config_set_port( const char *attrname, char *port, char *errorbuf, int apply ) {
@@ -3552,6 +3669,66 @@ config_get_port(){
}
+int
+config_get_disk_monitoring(){
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ int retVal;
+
+ CFG_LOCK_READ(slapdFrontendConfig);
+ retVal = slapdFrontendConfig->disk_monitoring;
+ CFG_UNLOCK_READ(slapdFrontendConfig);
+
+ return retVal;
+}
+
+int
+config_get_disk_preserve_logging(){
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ int retVal;
+
+ CFG_LOCK_READ(slapdFrontendConfig);
+ retVal = slapdFrontendConfig->disk_preserve_logging;
+ CFG_UNLOCK_READ(slapdFrontendConfig);
+
+ return retVal;
+}
+
+int
+config_get_disk_logging_critical(){
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ int retVal;
+
+ CFG_LOCK_READ(slapdFrontendConfig);
+ retVal = slapdFrontendConfig->disk_logging_critical;
+ CFG_UNLOCK_READ(slapdFrontendConfig);
+
+ return retVal;
+}
+
+int
+config_get_disk_grace_period(){
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ int retVal;
+
+ CFG_LOCK_READ(slapdFrontendConfig);
+ retVal = slapdFrontendConfig->disk_grace_period;
+ CFG_UNLOCK_READ(slapdFrontendConfig);
+
+ return retVal;
+}
+
+long
+config_get_disk_threshold(){
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ long retVal;
+
+ CFG_LOCK_READ(slapdFrontendConfig);
+ retVal = slapdFrontendConfig->disk_threshold;
+ CFG_UNLOCK_READ(slapdFrontendConfig);
+
+ return retVal;
+}
+
char *
config_get_ldapi_filename(){
char *retVal;
@@ -4008,8 +4185,6 @@ config_get_pw_maxfailure() {
}
-
-
int
config_get_pw_inhistory() {
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
@@ -4022,9 +4197,6 @@ config_get_pw_inhistory() {
return retVal;
}
-
-
-
long
config_get_pw_lockduration() {
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
@@ -4038,7 +4210,6 @@ config_get_pw_lockduration() {
}
-
long
config_get_pw_resetfailurecount() {
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
@@ -4088,7 +4259,6 @@ config_get_pw_unlock() {
return retVal;
}
-
int
config_get_pw_lockout(){
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
@@ -4101,7 +4271,6 @@ config_get_pw_lockout(){
return retVal;
}
-
int
config_get_pw_gracelimit() {
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
@@ -4115,7 +4284,6 @@ config_get_pw_gracelimit() {
}
-
int
config_get_lastmod(){
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
@@ -4128,7 +4296,6 @@ config_get_lastmod(){
return retVal;
}
-
int
config_get_enquote_sup_oc(){
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
@@ -4141,7 +4308,6 @@ config_get_enquote_sup_oc(){
return retVal;
}
-
int
config_get_nagle() {
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
@@ -4150,8 +4316,8 @@ config_get_nagle() {
CFG_LOCK_READ(slapdFrontendConfig);
retVal = slapdFrontendConfig->nagle;
CFG_UNLOCK_READ(slapdFrontendConfig);
-return retVal; }
-
+ return retVal;
+}
int
config_get_accesscontrol() {
@@ -4197,7 +4363,7 @@ config_get_security() {
CFG_UNLOCK_READ(slapdFrontendConfig);
return retVal;
- }
+}
int
slapi_config_get_readonly() {
@@ -4209,8 +4375,7 @@ slapi_config_get_readonly() {
CFG_UNLOCK_READ(slapdFrontendConfig);
return retVal;
- }
-
+}
int
config_get_schemacheck() {
@@ -4222,7 +4387,7 @@ config_get_schemacheck() {
CFG_UNLOCK_READ(slapdFrontendConfig);
return retVal;
- }
+}
int
config_get_syntaxcheck() {
@@ -4270,7 +4435,7 @@ config_get_ds4_compatible_schema() {
CFG_UNLOCK_READ(slapdFrontendConfig);
return retVal;
- }
+}
int
config_get_schema_ignore_trailing_spaces() {
@@ -4282,7 +4447,7 @@ config_get_schema_ignore_trailing_spaces() {
CFG_UNLOCK_READ(slapdFrontendConfig);
return retVal;
- }
+}
char *
config_get_rootdn() {
@@ -4325,7 +4490,6 @@ config_get_rootpwstoragescheme() {
return retVal;
}
-
#ifndef _WIN32
char *
@@ -4406,8 +4570,6 @@ config_get_reservedescriptors(){
return retVal;
}
-
-
int
config_get_ioblocktimeout(){
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
@@ -4418,8 +4580,7 @@ config_get_ioblocktimeout(){
CFG_UNLOCK_READ(slapdFrontendConfig);
return retVal;
- }
-
+}
int
config_get_idletimeout(){
@@ -4574,7 +4735,6 @@ config_get_pw_minage(){
return retVal;
}
-
long
config_get_pw_warning() {
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
@@ -4587,7 +4747,6 @@ config_get_pw_warning() {
return retVal;
}
-
int
config_get_errorlog_level(){
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
@@ -4600,7 +4759,6 @@ config_get_errorlog_level(){
return retVal;
}
-
/* return integer -- don't worry about locking similar to config_check_referral_mode
below */
@@ -4627,6 +4785,16 @@ config_get_auditlog_logging_enabled(){
return retVal;
}
+int
+config_get_accesslog_logging_enabled(){
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ int retVal;
+
+ retVal = slapdFrontendConfig->accesslog_logging_enabled;
+
+ return retVal;
+}
+
char *config_get_referral_mode(void)
{
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
@@ -4649,8 +4817,7 @@ config_get_conntablesize(void){
CFG_UNLOCK_READ(slapdFrontendConfig);
return retVal;
- }
-
+}
/* return yes/no without actually copying the referral url
we don't worry about another thread changing this value
@@ -4661,7 +4828,6 @@ int config_check_referral_mode(void)
return(slapdFrontendConfig->refer_mode & REFER_MODE_ON);
}
-
int
config_get_outbound_ldap_io_timeout(void)
{
@@ -4674,7 +4840,6 @@ config_get_outbound_ldap_io_timeout(void)
return retVal;
}
-
int
config_get_unauth_binds_switch(void)
{
@@ -4687,7 +4852,6 @@ config_get_unauth_binds_switch(void)
return retVal;
}
-
int
config_get_require_secure_binds(void)
{
@@ -6281,3 +6445,32 @@ config_allowed_to_delete_attrs(const char *attr_type)
return rc;
}
+void
+config_set_accesslog_enabled(int value){
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ char errorbuf[BUFSIZ];
+
+ CFG_LOCK_WRITE(slapdFrontendConfig);
+ slapdFrontendConfig->accesslog_logging_enabled = value;
+ if(value){
+ log_set_logging(CONFIG_ACCESSLOG_LOGGING_ENABLED_ATTRIBUTE, "on", SLAPD_ACCESS_LOG, errorbuf, CONFIG_APPLY);
+ } else {
+ log_set_logging(CONFIG_ACCESSLOG_LOGGING_ENABLED_ATTRIBUTE, "off", SLAPD_ACCESS_LOG, errorbuf, CONFIG_APPLY);
+ }
+ CFG_UNLOCK_WRITE(slapdFrontendConfig);
+}
+
+void
+config_set_auditlog_enabled(int value){
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ char errorbuf[BUFSIZ];
+
+ CFG_LOCK_WRITE(slapdFrontendConfig);
+ slapdFrontendConfig->auditlog_logging_enabled = value;
+ if(value){
+ log_set_logging(CONFIG_AUDITLOG_LOGGING_ENABLED_ATTRIBUTE, "on", SLAPD_AUDIT_LOG, errorbuf, CONFIG_APPLY);
+ } else {
+ log_set_logging(CONFIG_AUDITLOG_LOGGING_ENABLED_ATTRIBUTE, "off", SLAPD_AUDIT_LOG, errorbuf, CONFIG_APPLY);
+ }
+ CFG_UNLOCK_WRITE(slapdFrontendConfig);
+}
diff --git a/ldap/servers/slapd/log.c b/ldap/servers/slapd/log.c
index ebec254..60a49ab 100644
--- a/ldap/servers/slapd/log.c
+++ b/ldap/servers/slapd/log.c
@@ -2532,6 +2532,69 @@ delete_logfile:
return 1;
}
+/*
+ * This function is used by the disk monitoring thread (daemon.c)
+ *
+ * When we get close to running out of disk space we delete the rotated logs
+ * as a last resort to help keep the server up and running.
+ */
+void
+log__delete_rotated_logs()
+{
+ struct logfileinfo *logp = NULL;
+ char buffer[BUFSIZ];
+ char tbuf[TBUFSIZE];
+
+ /*
+ * Access Log
+ */
+ logp = loginfo.log_access_logchain;
+ while (logp) {
+ tbuf[0] = buffer[0] = '\0';
+ log_convert_time (logp->l_ctime, tbuf, 1);
+ PR_snprintf (buffer, sizeof(buffer), "%s.%s", loginfo.log_access_file, tbuf);
+
+ LDAPDebug(LDAP_DEBUG_ANY,"Deleted Rotated Log: %s\n",buffer,0,0); /* MARK */
+
+ if (PR_Delete(buffer) != PR_SUCCESS) {
+ logp = logp->l_next;
+ continue;
+ }
+ loginfo.log_numof_access_logs--;
+ logp = logp->l_next;
+ }
+ /*
+ * Audit Log
+ */
+ logp = loginfo.log_audit_logchain;
+ while (logp) {
+ tbuf[0] = buffer[0] = '\0';
+ log_convert_time (logp->l_ctime, tbuf, 1);
+ PR_snprintf (buffer, sizeof(buffer), "%s.%s", loginfo.log_audit_file, tbuf);
+ if (PR_Delete(buffer) != PR_SUCCESS) {
+ logp = logp->l_next;
+ continue;
+ }
+ loginfo.log_numof_audit_logs--;
+ logp = logp->l_next;
+ }
+ /*
+ * Error log
+ */
+ logp = loginfo.log_error_logchain;
+ while (logp) {
+ tbuf[0] = buffer[0] = '\0';
+ log_convert_time (logp->l_ctime, tbuf, 1);
+ PR_snprintf (buffer, sizeof(buffer), "%s.%s", loginfo.log_error_file, tbuf);
+ if (PR_Delete(buffer) != PR_SUCCESS) {
+ logp = logp->l_next;
+ continue;
+ }
+ loginfo.log_numof_error_logs--;
+ logp = logp->l_next;
+ }
+}
+
#define ERRORSLOG 1
#define ACCESSLOG 2
#define AUDITLOG 3
@@ -3776,7 +3839,7 @@ log__open_errorlogfile(int logfile_state, int locked)
while (logp) {
log_convert_time (logp->l_ctime, tbuf, 1 /*short */);
PR_snprintf(buffer, sizeof(buffer), "LOGINFO:%s%s.%s (%lu) (%"
- NSPRI64 "d)\n", PREVLOGFILE, loginfo.log_error_file, tbuf,
+ NSPRI64 "d)\n", PREVLOGFILE, loginfo.log_error_file, tbuf,
logp->l_ctime, logp->l_size);
LOG_WRITE(fpinfo, buffer, strlen(buffer), 0);
logp = logp->l_next;
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index a624187..9bbcf53 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -380,6 +380,11 @@ int config_set_entryusn_global( const char *attrname, char *value, char *errorbu
int config_set_allowed_to_delete_attrs( const char *attrname, char *value, char *errorbuf, int apply );
int config_set_entryusn_import_init( const char *attrname, char *value, char *errorbuf, int apply );
int config_set_default_naming_context( const char *attrname, char *value, char *errorbuf, int apply );
+int config_set_disk_monitoring( const char *attrname, char *value, char *errorbuf, int apply );
+int config_set_disk_threshold( const char *attrname, char *value, char *errorbuf, int apply );
+int config_set_disk_grace_period( const char *attrname, char *value, char *errorbuf, int apply );
+int config_set_disk_preserve_logging( const char *attrname, char *value, char *errorbuf, int apply );
+int config_set_disk_logging_critical( const char *attrname, char *value, char *errorbuf, int apply );
#if !defined(_WIN32) && !defined(AIX)
int config_set_maxdescriptors( const char *attrname, char *value, char *errorbuf, int apply );
@@ -526,8 +531,15 @@ int config_get_entryusn_global(void);
char *config_get_allowed_to_delete_attrs(void);
char *config_get_entryusn_import_init(void);
char *config_get_default_naming_context(void);
-
int config_allowed_to_delete_attrs(const char *attr_type);
+void config_set_accesslog_enabled(int value);
+void config_set_auditlog_enabled(int value);
+int config_get_accesslog_logging_enabled();
+int config_get_disk_monitoring();
+long config_get_disk_threshold();
+int config_get_disk_grace_period();
+int config_get_disk_preserve_logging();
+int config_get_disk_logging_critical();
int is_abspath(const char *);
char* rel2abspath( char * );
@@ -737,7 +749,7 @@ int check_log_max_size(
void g_set_accesslog_level(int val);
-
+void log__delete_rotated_logs();
/*
* util.c
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 025f749..f7c0bf2 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1989,6 +1989,11 @@ typedef struct _slapdEntryPoints {
#define CONFIG_ENTRYUSN_IMPORT_INITVAL "nsslapd-entryusn-import-initval"
#define CONFIG_ALLOWED_TO_DELETE_ATTRIBUTE "nsslapd-allowed-to-delete-attrs"
#define CONFIG_DEFAULT_NAMING_CONTEXT "nsslapd-defaultnamingcontext"
+#define CONFIG_DISK_MONITORING "nsslapd-disk-monitoring"
+#define CONFIG_DISK_THRESHOLD "nsslapd-disk-monitoring-threshold"
+#define CONFIG_DISK_GRACE_PERIOD "nsslapd-disk-monitoring-grace-period"
+#define CONFIG_DISK_PRESERVE_LOGGING "nsslapd-disk-monitoring-preserve-logging"
+#define CONFIG_DISK_LOGGING_CRITICAL "nsslapd-disk-monitoring-logging-critical"
#ifdef MEMPOOL_EXPERIMENTAL
#define CONFIG_MEMPOOL_SWITCH_ATTRIBUTE "nsslapd-mempool"
@@ -2214,6 +2219,13 @@ typedef struct _slapdFrontendConfig {
char *entryusn_import_init; /* Entry USN: determine the initital value of import */
int pagedsizelimit;
char *default_naming_context; /* Default naming context (normalized) */
+
+ /* disk monitoring */
+ int disk_monitoring;
+ int disk_threshold;
+ int disk_grace_period;
+ int disk_preserve_logging;
+ int disk_logging_critical;
} slapdFrontendConfig_t;
/* possible values for slapdFrontendConfig_t.schemareplace */
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 63eeb37..fa4892d 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -6903,7 +6903,9 @@ enum
BACK_INFO_DBENV_OPENFLAGS, /* Get the dbenv openflags */
BACK_INFO_CRYPT_INIT, /* Ctrl: clcrypt_init */
BACK_INFO_CRYPT_ENCRYPT_VALUE, /* Ctrl: clcrypt_encrypt_value */
- BACK_INFO_CRYPT_DECRYPT_VALUE /* Ctrl: clcrypt_decrypt_value */
+ BACK_INFO_CRYPT_DECRYPT_VALUE, /* Ctrl: clcrypt_decrypt_value */
+ BACK_INFO_DIRECTORY, /* Get the directory path */
+ BACK_INFO_LOG_DIRECTORY /* Get the txn log directory */
};
struct _back_info_crypt_init {
11 years, 12 months
ldap/servers
by Mark Reynolds
ldap/servers/plugins/automember/automember.c | 718 ++++++++++++++++++++++++++-
1 file changed, 710 insertions(+), 8 deletions(-)
New commits:
commit a4e4edc6ac37d03ac38c264be2ddbd8e08f8cb16
Author: Mark Reynolds <mareynol(a)redhat.com>
Date: Wed Apr 4 17:25:17 2012 -0400
Ticket #20 - Allow automember to work on entries that have already been added
Bug Description: Currently only ADD's will trigger the automember update. Modifies
are not checked due to performance reasons.
Fix Description: Created 3 new tasks:
[1] Rebuild Membership Task - this task takes a filter, base, scope.
Then it will look through the database for matches and then do
the automember update. This is designed to catch entries that were
modified that match the automembership criteria.
[2] Export Updates Task - this will write an ldif file of the changes
that the "Rebuild Memebership Task" would do, if it was run.
[3] Map Updates Task - this takes an ldif of new entries, and then writes
an ldif file of the changes that would take place if those entries
were added.
So tasks 2 & 3 just provide the changes that would take place, but they don't
change any data in the database. This is a customer RFE.
https://fedorahosted.org/389/ticket/20
Reviewed by: richm & noriko (Thanks!)
diff --git a/ldap/servers/plugins/automember/automember.c b/ldap/servers/plugins/automember/automember.c
index 391dde7..d638374 100644
--- a/ldap/servers/plugins/automember/automember.c
+++ b/ldap/servers/plugins/automember/automember.c
@@ -103,9 +103,28 @@ 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_update_membership(struct configEntry *config, Slapi_Entry *e, PRFileDesc *ldif_fd);
static void automember_add_member_value(Slapi_Entry *member_e, const char *group_dn,
- char *grouping_attr, char *grouping_value);
+ char *grouping_attr, char *grouping_value, PRFileDesc *ldif_fd);
+const char *fetch_attr(Slapi_Entry *e, const char *attrname, const char *default_val);
+
+/*
+ * task functions
+ */
+static int automember_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
+ int *returncode, char *returntext, void *arg);
+static int automember_task_add_export_updates(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
+ int *returncode, char *returntext, void *arg);
+static int automember_task_add_map_entries(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
+ int *returncode, char *returntext, void *arg);
+void automember_rebuild_task_thread(void *arg);
+void automember_export_task_thread(void *arg);
+void automember_map_task_thread(void *arg);
+void automember_task_destructor(Slapi_Task *task);
+void automember_task_export_destructor(Slapi_Task *task);
+void automember_task_map_destructor(Slapi_Task *task);
+
+#define DEFAULT_FILE_MODE PR_IRUSR | PR_IWUSR
/*
* Config cache locking functions
@@ -325,6 +344,10 @@ automember_start(Slapi_PBlock * pb)
goto done;
}
+ slapi_task_register_handler("automember rebuild membership", automember_task_add);
+ slapi_task_register_handler("automember export updates", automember_task_add_export_updates);
+ slapi_task_register_handler("automember map updates", automember_task_add_map_entries);
+
g_automember_config_lock = slapi_new_rwlock();
if (!g_automember_config_lock) {
@@ -1379,7 +1402,7 @@ automember_parse_grouping_attr(char *value, char **grouping_attr, char **groupin
* the rules in config, then performs the updates.
*/
static void
-automember_update_membership(struct configEntry *config, Slapi_Entry *e)
+automember_update_membership(struct configEntry *config, Slapi_Entry *e, PRFileDesc *ldif_fd)
{
PRCList *rule = NULL;
struct automemberRegexRule *curr_rule = NULL;
@@ -1533,14 +1556,14 @@ automember_update_membership(struct configEntry *config, Slapi_Entry *e)
/* 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);
+ config->grouping_attr, config->grouping_value, ldif_fd);
}
} 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);
+ config->grouping_attr, config->grouping_value, ldif_fd);
dnitem = (struct automemberDNListItem *)PR_NEXT_LINK((PRCList *)dnitem);
}
}
@@ -1567,8 +1590,8 @@ automember_update_membership(struct configEntry *config, Slapi_Entry *e)
* 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)
+automember_add_member_value(Slapi_Entry *member_e, const char *group_dn, char *grouping_attr,
+ char *grouping_value, PRFileDesc *ldif_fd)
{
Slapi_PBlock *mod_pb = slapi_pblock_new();
int result = LDAP_SUCCESS;
@@ -1586,6 +1609,19 @@ automember_add_member_value(Slapi_Entry *member_e, const char *group_dn,
freeit = 1;
}
+ /*
+ * If ldif_fd is set, we are performing an export task. Write the changes to the
+ * file instead of performing them
+ */
+ if(ldif_fd){
+ PR_fprintf(ldif_fd, "dn: %s\n", group_dn);
+ PR_fprintf(ldif_fd, "changetype: modify\n");
+ PR_fprintf(ldif_fd, "add: %s\n", grouping_attr);
+ PR_fprintf(ldif_fd, "%s: %s\n", grouping_attr, member_value);
+ PR_fprintf(ldif_fd, "\n");
+ goto out;
+ }
+
if (member_value) {
/* Set up the operation. */
vals[0] = member_value;
@@ -1621,6 +1657,7 @@ automember_add_member_value(Slapi_Entry *member_e, const char *group_dn,
grouping_value, slapi_entry_get_dn(member_e));
}
+out:
/* Cleanup */
if (freeit) {
slapi_ch_free_string(&member_value);
@@ -1853,7 +1890,7 @@ automember_add_post_op(Slapi_PBlock *pb)
if (slapi_dn_issuffix(slapi_sdn_get_dn(sdn), 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);
+ automember_update_membership(config, e, NULL);
}
list = PR_NEXT_LINK(list);
@@ -1907,6 +1944,671 @@ automember_del_post_op(Slapi_PBlock *pb)
return 0;
}
+typedef struct _task_data
+{
+ char *filter_str;
+ char *ldif_out;
+ char *ldif_in;
+ Slapi_DN *base_dn;
+ char *bind_dn;
+ int scope;
+} task_data;
+
+/*
+ * extract a single value from the entry (as a string) -- if it's not in the
+ * entry, the default will be returned (which can be NULL).
+ * you do not need to free anything returned by this.
+ */
+const char *
+fetch_attr(Slapi_Entry *e, const char *attrname, const char *default_val)
+{
+ Slapi_Value *val = NULL;
+ Slapi_Attr *attr;
+
+ if(slapi_entry_attr_find(e, attrname, &attr) != 0){
+ return default_val;
+ }
+ slapi_attr_first_value(attr, &val);
+
+ return slapi_value_get_string(val);
+}
+
+void
+automember_task_destructor(Slapi_Task *task)
+{
+ if (task) {
+ task_data *mydata = (task_data *)slapi_task_get_data(task);
+ if (mydata) {
+ slapi_ch_free_string(&mydata->bind_dn);
+ slapi_sdn_free(&mydata->base_dn);
+ slapi_ch_free_string(&mydata->filter_str);
+ slapi_ch_free((void **)&mydata);
+ }
+ }
+}
+
+void
+automember_task_export_destructor(Slapi_Task *task)
+{
+ if (task) {
+ task_data *mydata = (task_data *)slapi_task_get_data(task);
+ if (mydata) {
+ slapi_ch_free_string(&mydata->ldif_out);
+ slapi_ch_free_string(&mydata->bind_dn);
+ slapi_sdn_free(&mydata->base_dn);
+ slapi_ch_free_string(&mydata->filter_str);
+ slapi_ch_free((void **)&mydata);
+ }
+ }
+}
+
+void
+automember_task_map_destructor(Slapi_Task *task)
+{
+ if (task) {
+ task_data *mydata = (task_data *)slapi_task_get_data(task);
+ if (mydata) {
+ slapi_ch_free_string(&mydata->ldif_out);
+ slapi_ch_free_string(&mydata->ldif_in);
+ slapi_ch_free_string(&mydata->bind_dn);
+ slapi_ch_free((void **)&mydata);
+ }
+ }
+}
+
+/*
+ * automember_task_add
+ *
+ * This task is designed to "retro-fit" entries that existed prior to
+ * enabling this plugin. This can be an expensive task to run, but it's
+ * better than processing every modify operation in an attempt to catch
+ * entries that have not been processed.
+ *
+ * task entry:
+ *
+ * dn: cn=my rebuild task, cn=automember rebuild membership,cn=tasks,cn=config
+ * objectClass: top
+ * objectClass: extensibleObject
+ * cn: my rebuild task
+ * basedn: dc=example,dc=com
+ * filter: (uid=*)
+ * scope: sub
+ *
+ * basedn and filter are required. If scope is omitted, the default is sub
+ */
+static int
+automember_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
+ int *returncode, char *returntext, void *arg)
+{
+ int rv = SLAPI_DSE_CALLBACK_OK;
+ task_data *mytaskdata = NULL;
+ Slapi_Task *task = NULL;
+ Slapi_DN *basedn = NULL;
+ PRThread *thread = NULL;
+ char *bind_dn = NULL;
+ const char *base_dn;
+ const char *filter;
+ const char *scope;
+
+ *returncode = LDAP_SUCCESS;
+
+ /*
+ * Make sure the plugin is started
+ */
+ if(!g_plugin_started){
+ *returncode = LDAP_OPERATIONS_ERROR;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto out;
+ }
+ /*
+ * Grab the task params
+ */
+ if((base_dn = fetch_attr(e, "basedn", 0)) == NULL){
+ *returncode = LDAP_OBJECT_CLASS_VIOLATION;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto out;
+ } else {
+ /* convert the base_dn to a slapi dn */
+ basedn = slapi_sdn_new_dn_byval(base_dn);
+ }
+ if((filter = fetch_attr(e, "filter", 0)) == NULL){
+ *returncode = LDAP_OBJECT_CLASS_VIOLATION;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto out;
+ }
+ scope = fetch_attr(e, "scope", "sub");
+ /*
+ * setup our task data
+ */
+ mytaskdata = (task_data*)slapi_ch_malloc(sizeof(task_data));
+ if (mytaskdata == NULL){
+ *returncode = LDAP_OPERATIONS_ERROR;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto out;
+ }
+
+ slapi_pblock_get(pb, SLAPI_REQUESTOR_DN, &bind_dn);
+ mytaskdata->bind_dn = slapi_ch_strdup(bind_dn);
+ mytaskdata->base_dn = basedn;
+ mytaskdata->filter_str = slapi_ch_strdup(filter);
+ if(scope){
+ if(strcasecmp(scope,"sub")== 0){
+ mytaskdata->scope = 2;
+ } else if(strcasecmp(scope,"one")== 0){
+ mytaskdata->scope = 1;
+ } else if(strcasecmp(scope,"base")== 0){
+ mytaskdata->scope = 0;
+ } else {
+ /* Hmm, possible typo, use subtree */
+ mytaskdata->scope = 2;
+ }
+ } else {
+ /* subtree by default */
+ mytaskdata->scope = 2;
+ }
+ task = slapi_new_task(slapi_entry_get_ndn(e));
+ slapi_task_set_destructor_fn(task, automember_task_destructor);
+ slapi_task_set_data(task, mytaskdata);
+ /*
+ * Start the task as a separate thread
+ */
+ thread = PR_CreateThread(PR_USER_THREAD, automember_rebuild_task_thread,
+ (void *)task, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
+ if (thread == NULL){
+ slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "unable to create task thread!\n");
+ *returncode = LDAP_OPERATIONS_ERROR;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ slapi_task_finish(task, *returncode);
+ } else {
+ rv = SLAPI_DSE_CALLBACK_OK;
+ }
+
+out:
+ return rv;
+}
+
+/*
+ * automember_rebuild_task_thread()
+ *
+ * Search using the basedn, filter, and scope provided from the task data.
+ * Then loop of each entry, and apply the membership if applicable.
+ */
+void automember_rebuild_task_thread(void *arg){
+ Slapi_Task *task = (Slapi_Task *)arg;
+ struct configEntry *config = NULL;
+ Slapi_PBlock *search_pb = NULL;
+ Slapi_Entry **entries = NULL;
+ task_data *td = NULL;
+ PRCList *list = NULL;
+ int result = 0;
+ int i = 0;
+
+ /*
+ * Fetch our task data from the task
+ */
+ td = (task_data *)slapi_task_get_data(task);
+ slapi_task_begin(task, 1);
+ slapi_task_log_notice(task, "Automember rebuild task starting (base dn: (%s) filter (%s)...\n",
+ slapi_sdn_get_dn(td->base_dn),td->filter_str);
+ slapi_task_log_status(task, "Automember rebuild task starting (base dn: (%s) filter (%s)...\n",
+ slapi_sdn_get_dn(td->base_dn),td->filter_str);
+ /*
+ * Set the bind dn in the local thread data
+ */
+ slapi_td_set_dn(slapi_ch_strdup(td->bind_dn));
+ /*
+ * Search the database
+ */
+ search_pb = slapi_pblock_new();
+ slapi_search_internal_set_pb_ext(search_pb, td->base_dn, td->scope, td->filter_str, 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){
+ slapi_task_log_notice(task, "Automember rebuild membership task unable to search"
+ " on base (%s) filter (%s) error (%d)\n", slapi_sdn_get_dn(td->base_dn),
+ td->filter_str, result);
+ slapi_task_log_status(task, "Automember rebuild membership task unable to search"
+ " on base (%s) filter (%s) error (%d)\n", slapi_sdn_get_dn(td->base_dn),
+ td->filter_str, result);
+ slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "Task: unable to search on base (%s) filter (%s) error (%d)\n",
+ slapi_sdn_get_dn(td->base_dn), td->filter_str, result);
+ goto out;
+ }
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ /*
+ * Grab the config read lock, and loop over the entries
+ */
+ automember_config_read_lock();
+ for (i = 0; entries && (entries[i] != NULL); i++){
+ /* make sure the plugin is still up, as this loop could run for awhile */
+ if (!g_plugin_started) {
+ automember_config_unlock();
+ result = -1;
+ goto out;
+ }
+ if (!PR_CLIST_IS_EMPTY(g_automember_config)) {
+ list = PR_LIST_HEAD(g_automember_config);
+ while (list != g_automember_config) {
+ config = (struct configEntry *)list;
+ automember_update_membership(config, entries[i], NULL);
+ list = PR_NEXT_LINK(list);
+ }
+ }
+ }
+ automember_config_unlock();
+ slapi_free_search_results_internal(search_pb);
+
+out:
+ if(result){
+ /* error */
+ slapi_task_log_notice(task, "Automember rebuild task aborted. Error (%d)", result);
+ slapi_task_log_status(task, "Automember rebuild task aborted. Error (%d)", result);
+ } else {
+ slapi_task_log_notice(task, "Automember rebuild task finished. Processed (%d) entries.", i);
+ slapi_task_log_status(task, "Automember rebuild task finished. Processed (%d) entries.", i);
+ }
+ slapi_task_inc_progress(task);
+ slapi_task_finish(task, result);
+}
+
+/*
+ * Export an ldif of the changes that would be made if we ran the automember rebuild membership task
+ *
+ * task entry:
+ *
+ * dn: cn=my export task, cn=automember export updates,cn=tasks,cn=config
+ * objectClass: top
+ * objectClass: extensibleObject
+ * cn: my export task
+ * basedn: dc=example,dc=com
+ * filter: (uid=*)
+ * scope: sub
+ * ldif: /tmp/automem-updates.ldif
+ */
+static int
+automember_task_add_export_updates(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
+ int *returncode, char *returntext, void *arg)
+{
+ int rv = SLAPI_DSE_CALLBACK_OK;
+ task_data *mytaskdata = NULL;
+ Slapi_Task *task = NULL;
+ Slapi_DN *basedn = NULL;
+ PRThread *thread = NULL;
+ char *bind_dn = NULL;
+ const char *base_dn = NULL;
+ const char *filter = NULL;
+ const char *ldif = NULL;
+ const char *scope = NULL;
+
+ *returncode = LDAP_SUCCESS;
+
+ /*
+ * Make sure the plugin is started
+ */
+ if(!g_plugin_started){
+ *returncode = LDAP_OPERATIONS_ERROR;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto out;
+ }
+
+ if((ldif = fetch_attr(e, "ldif", 0)) == NULL){
+ *returncode = LDAP_OBJECT_CLASS_VIOLATION;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto out;
+ }
+ if((base_dn = fetch_attr(e, "basedn", 0)) == NULL){
+ *returncode = LDAP_OBJECT_CLASS_VIOLATION;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto out;
+ } else {
+ /* convert the base dn to a slapi dn */
+ basedn = slapi_sdn_new_dn_byval(base_dn);
+ }
+ if((filter = fetch_attr(e, "filter", 0)) == NULL){
+ *returncode = LDAP_OBJECT_CLASS_VIOLATION;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto out;
+ }
+ scope = fetch_attr(e, "scope", "sub");
+
+ slapi_pblock_get(pb, SLAPI_REQUESTOR_DN, &bind_dn);
+
+ mytaskdata = (task_data*)slapi_ch_malloc(sizeof(task_data));
+ if (mytaskdata == NULL){
+ *returncode = LDAP_OPERATIONS_ERROR;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto out;
+ }
+ mytaskdata->bind_dn = slapi_ch_strdup(bind_dn);
+ mytaskdata->ldif_out = slapi_ch_strdup(ldif);
+ mytaskdata->base_dn = basedn;
+ mytaskdata->filter_str = slapi_ch_strdup(filter);
+ if(scope){
+ if(strcasecmp(scope,"sub")== 0){
+ mytaskdata->scope = 2;
+ } else if(strcasecmp(scope,"one")== 0){
+ mytaskdata->scope = 1;
+ } else if(strcasecmp(scope,"base")== 0){
+ mytaskdata->scope = 0;
+ } else {
+ /* Hmm, possible typo, use subtree */
+ mytaskdata->scope = 2;
+ }
+ } else {
+ /* subtree by default */
+ mytaskdata->scope = 2;
+ }
+
+ task = slapi_new_task(slapi_entry_get_ndn(e));
+ slapi_task_set_destructor_fn(task, automember_task_export_destructor);
+ slapi_task_set_data(task, mytaskdata);
+ /*
+ * Start the task as a separate thread
+ */
+ thread = PR_CreateThread(PR_USER_THREAD, automember_export_task_thread,
+ (void *)task, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
+ if (thread == NULL){
+ slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "unable to create export task thread!\n");
+ *returncode = LDAP_OPERATIONS_ERROR;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ slapi_task_finish(task, *returncode);
+ } else {
+ rv = SLAPI_DSE_CALLBACK_OK;
+ }
+
+out:
+ return rv;
+}
+
+void automember_export_task_thread(void *arg){
+ Slapi_Task *task = (Slapi_Task *)arg;
+ Slapi_PBlock *search_pb = NULL;
+ Slapi_Entry **entries = NULL;
+ int result = SLAPI_DSE_CALLBACK_OK;
+ struct configEntry *config = NULL;
+ PRCList *list = NULL;
+ task_data *td = NULL;
+ PRFileDesc *ldif_fd;
+ int i = 0;
+
+ td = (task_data *)slapi_task_get_data(task);
+ slapi_task_begin(task, 1);
+ slapi_task_log_notice(task, "Automember export task starting. Exporting changes to (%s)", td->ldif_out);
+ slapi_task_log_status(task, "Automember export task starting. Exporting changes to (%s)", td->ldif_out);
+
+ /* make sure we can open the ldif file */
+ if (( ldif_fd = PR_Open( td->ldif_out, PR_CREATE_FILE | PR_WRONLY, DEFAULT_FILE_MODE )) == NULL ){
+ slapi_task_log_notice(task, "Automember export task could not open ldif file \"%s\" for writing %d\n",
+ td->ldif_out, PR_GetError() );
+ slapi_task_log_status(task, "Automember export task could not open ldif file \"%s\" for writing %d\n",
+ td->ldif_out, PR_GetError() );
+ slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "Could not open ldif file \"%s\" for writing %d\n",
+ td->ldif_out, PR_GetError() );
+ result = SLAPI_DSE_CALLBACK_ERROR;
+ goto out;
+ }
+
+ /*
+ * Set the bind dn in the local thread data
+ */
+ slapi_td_set_dn(slapi_ch_strdup(td->bind_dn));
+ /*
+ * Search the database
+ */
+ search_pb = slapi_pblock_new();
+ slapi_search_internal_set_pb_ext(search_pb, td->base_dn, td->scope, td->filter_str, 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){
+ slapi_task_log_notice(task, "Automember task failed to search on base (%s) filter (%s) error (%d)\n",
+ slapi_sdn_get_dn(td->base_dn), td->filter_str, result);
+ slapi_task_log_status(task, "Automember task failed to search on base (%s) filter (%s) error (%d)\n",
+ slapi_sdn_get_dn(td->base_dn), td->filter_str, result);
+ slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "Task: unable to search on base (%s) filter (%s) error (%d)\n",
+ slapi_sdn_get_dn(td->base_dn), td->filter_str, result);
+ goto out;
+ }
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ /*
+ * Grab the config read lock, and loop over the entries
+ */
+ automember_config_read_lock();
+ for (i = 0; entries && (entries[i] != NULL); i++){
+ /* make sure the plugin is still up, as this loop could run for awhile */
+ if (!g_plugin_started) {
+ automember_config_unlock();
+ result = -1;
+ goto out;
+ }
+ if (!PR_CLIST_IS_EMPTY(g_automember_config)) {
+ list = PR_LIST_HEAD(g_automember_config);
+ while (list != g_automember_config) {
+ config = (struct configEntry *)list;
+ automember_update_membership(config, entries[i], ldif_fd);
+ list = PR_NEXT_LINK(list);
+ }
+ }
+ }
+ automember_config_unlock();
+ slapi_free_search_results_internal(search_pb);
+
+out:
+ if(ldif_fd){
+ PR_Close(ldif_fd);
+ }
+ if(result){
+ /* error */
+ slapi_task_log_notice(task, "Automember export task aborted. Error (%d)", result);
+ slapi_task_log_status(task, "Automember export task aborted. Error (%d)", result);
+ } else {
+ slapi_task_log_notice(task, "Automember export task finished. Processed (%d) entries.", i);
+ slapi_task_log_status(task, "Automember export task finished. Processed (%d) entries.", i);
+ }
+ slapi_task_inc_progress(task);
+ slapi_task_finish(task, result);
+}
+
+/*
+ * Export an ldif of the changes that would be made from the entries
+ * in the provided ldif file
+ *
+ * task entry:
+ *
+ * dn: cn=my map task, cn=automember map updates,cn=tasks,cn=config
+ * objectClass: top
+ * objectClass: extensibleObject
+ * cn: my export task
+ * ldif_in: /tmp/entries.ldif
+ * ldif_out: /tmp/automem-updates.ldif
+ */
+static int
+automember_task_add_map_entries(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
+ int *returncode, char *returntext, void *arg)
+{
+ int rv = SLAPI_DSE_CALLBACK_OK;
+ task_data *mytaskdata = NULL;
+ Slapi_Task *task = NULL;
+ PRThread *thread = NULL;
+ char *bind_dn;
+ const char *ldif_out;
+ const char *ldif_in;
+
+ *returncode = LDAP_SUCCESS;
+ /*
+ * Make sure the plugin is started
+ */
+ if(!g_plugin_started){
+ *returncode = LDAP_OPERATIONS_ERROR;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto out;
+ }
+ /*
+ * Get the params
+ */
+ if((ldif_in = fetch_attr(e, "ldif_in", 0)) == NULL){
+ *returncode = LDAP_OBJECT_CLASS_VIOLATION;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto out;
+ }
+ if((ldif_out = fetch_attr(e, "ldif_out", 0)) == NULL){
+ *returncode = LDAP_OBJECT_CLASS_VIOLATION;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto out;
+ }
+ /*
+ * Setup the task data
+ */
+ mytaskdata = (task_data*)slapi_ch_malloc(sizeof(task_data));
+ if (mytaskdata == NULL){
+ *returncode = LDAP_OPERATIONS_ERROR;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto out;
+ }
+ slapi_pblock_get(pb, SLAPI_REQUESTOR_DN, &bind_dn);
+ mytaskdata->bind_dn = slapi_ch_strdup(bind_dn);
+ mytaskdata->ldif_out = slapi_ch_strdup(ldif_out);
+ mytaskdata->ldif_in = slapi_ch_strdup(ldif_in);
+
+ task = slapi_new_task(slapi_entry_get_ndn(e));
+ slapi_task_set_destructor_fn(task, automember_task_map_destructor);
+ slapi_task_set_data(task, mytaskdata);
+ /*
+ * Start the task as a separate thread
+ */
+ thread = PR_CreateThread(PR_USER_THREAD, automember_map_task_thread,
+ (void *)task, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
+ if (thread == NULL){
+ slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "unable to create map task thread!\n");
+ *returncode = LDAP_OPERATIONS_ERROR;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ slapi_task_finish(task, *returncode);
+ } else {
+ rv = SLAPI_DSE_CALLBACK_OK;
+ }
+
+out:
+
+ return rv;
+}
+
+/*
+ * Read in the text entries from ldif_in, and convert them to slapi_entries.
+ * Then, write to ldif_out what the updates would be if these entries were added
+ */
+void automember_map_task_thread(void *arg){
+ Slapi_Task *task = (Slapi_Task *)arg;
+ Slapi_Entry *e = NULL;
+ int result = SLAPI_DSE_CALLBACK_OK;
+ struct configEntry *config = NULL;
+ PRCList *list = NULL;
+ task_data *td = NULL;
+ PRFileDesc *ldif_fd_out = NULL;
+ char *entrystr = NULL;
+#if defined(USE_OPENLDAP)
+ int buflen = 0;
+ LDIFFP *ldif_fd_in = NULL;
+#else
+ PRFileDesc *ldif_fd_in = NULL;
+#endif
+ int lineno = 0;
+ int rc = 0;
+
+ td = (task_data *)slapi_task_get_data(task);
+ slapi_task_begin(task, 1);
+ slapi_task_log_notice(task, "Automember map task starting... Reading entries from (%s)"
+ " and writing the updates to (%s)",td->ldif_in, td->ldif_out);
+ slapi_task_log_status(task, "Automember map task starting... Reading entries from (%s)"
+ " and writing the updates to (%s)",td->ldif_in, td->ldif_out);
+
+ /* make sure we can open the ldif files */
+ if(( ldif_fd_out = PR_Open( td->ldif_out, PR_CREATE_FILE | PR_WRONLY, DEFAULT_FILE_MODE )) == NULL ){
+ slapi_task_log_notice(task, "The ldif file %s could not be accessed, error %d. Aborting task.\n",
+ td->ldif_out, rc);
+ slapi_task_log_status(task, "The ldif file %s could not be accessed, error %d. Aborting task.\n",
+ td->ldif_out, rc);
+ slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "Could not open ldif file \"%s\" for writing %d\n",
+ td->ldif_out, PR_GetError() );
+ result = SLAPI_DSE_CALLBACK_ERROR;
+ goto out;
+ }
+
+#if defined(USE_OPENLDAP)
+ if(( ldif_fd_in = ldif_open(td->ldif_in, "r")) == NULL ){
+#else
+ if(( ldif_fd_in = PR_Open( td->ldif_in, PR_RDONLY, DEFAULT_FILE_MODE )) == NULL ){
+#endif
+ slapi_task_log_notice(task, "The ldif file %s could not be accessed, error %d. Aborting task.\n",
+ td->ldif_in, rc);
+ slapi_task_log_status(task, "The ldif file %s could not be accessed, error %d. Aborting task.\n",
+ td->ldif_in, rc);
+ slapi_log_error( SLAPI_LOG_FATAL, AUTOMEMBER_PLUGIN_SUBSYSTEM,
+ "Could not open ldif file \"%s\" for reading %d\n",
+ td->ldif_out, PR_GetError() );
+ result = SLAPI_DSE_CALLBACK_ERROR;
+ goto out;
+ }
+ /*
+ * Convert each LDIF entry to a slapi_entry
+ */
+ automember_config_read_lock();
+#if defined(USE_OPENLDAP)
+ while (ldif_read_record(ldif_fd_in, &lineno, &entrystr, &buflen)){
+ buflen = 0;
+#else
+ while ((entrystr = ldif_get_entry(ldif_fd_in, &lineno)) != NULL){
+#endif
+ e = slapi_str2entry( entrystr, 0 );
+ if ( e != NULL ){
+ if (!g_plugin_started) {
+ automember_config_unlock();
+ result = -1;
+ goto out;
+ }
+ if (!PR_CLIST_IS_EMPTY(g_automember_config)) {
+ list = PR_LIST_HEAD(g_automember_config);
+ while (list != g_automember_config) {
+ config = (struct configEntry *)list;
+ automember_update_membership(config, e, ldif_fd_out);
+ list = PR_NEXT_LINK(list);
+ }
+ }
+ slapi_entry_free(e);
+ } else {
+ /* invalid entry */
+ slapi_task_log_notice(task, "Automember map task, skipping invalid entry.");
+ slapi_task_log_status(task, "Automember map task, skipping invalid entry.");
+ }
+ slapi_ch_free((void **)&entrystr);
+ }
+ automember_config_unlock();
+
+out:
+ if(ldif_fd_out){
+ PR_Close(ldif_fd_out);
+ }
+ if(ldif_fd_in){
+#if defined(USE_OPENLDAP)
+ ldif_close(ldif_fd_in);
+#else
+ PR_Close(ldif_fd_in);
+#endif
+ }
+ slapi_task_inc_progress(task);
+ slapi_task_finish(task, result);
+}
+
/*
* automember_modrdn_post_op()
*
11 years, 12 months
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/entry.c | 24 ++++++++++++++++++------
ldap/servers/slapd/entrywsi.c | 20 +++++++++++++++-----
ldap/servers/slapd/modify.c | 37 ++++++++++++++++++++++++-------------
ldap/servers/slapd/pw.c | 16 +++++++++++++++-
ldap/servers/slapd/slapi-private.h | 1 +
5 files changed, 73 insertions(+), 25 deletions(-)
New commits:
commit b8e6b1394ee20434f2ecf4c70451f4f0bcc2b6bf
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Mon Apr 2 16:51:02 2012 -0700
Trac Ticket #45 - Fine Grained Password policy:
if passwordHistory is on, deleting the password fails.
https://fedorahosted.org/389/ticket/45
Bug description: To allow replicating unhashed password, an internal
entry contains the key value pair when the entry is newly added or
the password is updated. In that case, deleting the userpassword
attribute leaves the unhashed password in the internal entry.
If you attempt to add a new userpassword, the remaining unhashed
password makes the attempt fail due to LDAP_TYPE_OR_VALUE_EXISTS.
Fix description: This patch cleans up the unhashed password if a
userpassword is deleted and the unhashed password is found in the
internal entry. If it does not exist, the deletion does nothing.
(If the entry is read from the database, the unhashed password
does not exist in the internal entry since it is not stored in
the database.)
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c
index 5afba09..c235431 100644
--- a/ldap/servers/slapd/entry.c
+++ b/ldap/servers/slapd/entry.c
@@ -63,7 +63,6 @@
/* a helper function to set special rdn to a tombstone entry */
static int _entry_set_tombstone_rdn(Slapi_Entry *e, const char *normdn);
-static int is_type_protected(const char *type);
/* protected attributes which are not included in the flattened entry,
* which will be stored in the db. */
@@ -1613,7 +1612,7 @@ entry2str_internal_put_valueset( const char *attrtype, const CSN *attrcsn, CSNTy
}
}
-static int
+int
is_type_protected(const char *type)
{
char **paap = NULL;
@@ -3393,24 +3392,37 @@ slapi_entry_delete_values(
return(rc);
}
-
static int
delete_values_sv_internal(
Slapi_Entry *e,
const char *type,
Slapi_Value **valuestodelete,
- int flags
+ int flags
)
{
Slapi_Attr *a;
int retVal= LDAP_SUCCESS;
+ /*
+ * If type is in the protected_attrs_all list, we could ignore the failure,
+ * as the attribute could only exist in the entry in the memory when the
+ * add/mod operation is done, while the retried entry from the db does not
+ * contain the attribute.
+ */
+ if (is_type_protected(type)) {
+ flags |= SLAPI_VALUE_FLAG_IGNOREERROR;
+ }
+
/* delete the entire attribute */
if ( valuestodelete == NULL || valuestodelete[0] == NULL ){
LDAPDebug( LDAP_DEBUG_ARGS, "removing entire attribute %s\n",
type, 0, 0 );
- return( attrlist_delete( &e->e_attrs, type) ?
- LDAP_NO_SUCH_ATTRIBUTE : LDAP_SUCCESS );
+ retVal = attrlist_delete( &e->e_attrs, type);
+ if (flags & SLAPI_VALUE_FLAG_IGNOREERROR) {
+ return LDAP_SUCCESS;
+ } else {
+ }
+ return(retVal ? LDAP_NO_SUCH_ATTRIBUTE : LDAP_SUCCESS);
}
/* delete specific values - find the attribute first */
diff --git a/ldap/servers/slapd/entrywsi.c b/ldap/servers/slapd/entrywsi.c
index a749cee..05dbb36 100644
--- a/ldap/servers/slapd/entrywsi.c
+++ b/ldap/servers/slapd/entrywsi.c
@@ -638,12 +638,22 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval
}
else if (attr_state==ATTRIBUTE_NOTFOUND)
{
- if (!urp)
- {
- /* Only warn if not urping */
- LDAPDebug( LDAP_DEBUG_ARGS, "could not find attribute %s\n", type, 0, 0 );
+ /*
+ * If type is in the protected_attrs_all list, we could ignore the
+ * failure, as the attribute could only exist in the entry in the
+ * memory when the add/mod operation is done, while the retried entry
+ * from the db does not contain the attribute.
+ */
+ if (is_type_protected(type)) {
+ retVal = LDAP_SUCCESS;
+ } else {
+ if (!urp) {
+ /* Only warn if not urping */
+ LDAPDebug1Arg(LDAP_DEBUG_ARGS, "could not find attribute %s\n",
+ type);
+ }
+ retVal = LDAP_NO_SUCH_ATTRIBUTE;
}
- retVal= LDAP_NO_SUCH_ATTRIBUTE;
/* NOTE: LDAP says that a MOD REPLACE with no vals of a non-existent
attribute is a no-op - MOD REPLACE with some vals will add the attribute */
/* if we are doing a replace with actual values, meaning the result
diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c
index 7ec9ff9..73752ed 100644
--- a/ldap/servers/slapd/modify.c
+++ b/ldap/servers/slapd/modify.c
@@ -299,9 +299,8 @@ do_modify( Slapi_PBlock *pb )
continue;
}
- /* check for password change */
- if ( mod->mod_bvalues != NULL &&
- strcasecmp( mod->mod_type, SLAPI_USERPWD_ATTR ) == 0 ){
+ /* check for password change (including deletion) */
+ if ( strcasecmp( mod->mod_type, SLAPI_USERPWD_ATTR ) == 0 ){
has_password_mod++;
}
@@ -357,11 +356,11 @@ do_modify( Slapi_PBlock *pb )
for (mod = slapi_mods_get_first_mod(&smods);
mod;
mod = slapi_mods_get_next_mod(&smods)) {
- if ( mod->mod_bvalues != NULL &&
- strcasecmp( mod->mod_type, SLAPI_USERPWD_ATTR ) == 0 ) {
+ /* check for password change (including deletion) */
+ if ( strcasecmp( mod->mod_type, SLAPI_USERPWD_ATTR ) == 0 ) {
/* assumes controls have already been decoded and placed
in the pblock */
- pw_change = op_shared_allow_pw_change (pb, mod, &old_pw, &smods);
+ pw_change = op_shared_allow_pw_change(pb, mod, &old_pw, &smods);
if (pw_change == -1) {
goto free_and_return;
}
@@ -821,8 +820,9 @@ static void op_shared_modify (Slapi_PBlock *pb, int pw_change, char *old_pw)
}
/*
- * Add the unhashed password pseudo-attribute before
- * calling the preop plugins
+ * Add the unhashed password pseudo-attribute (for add) OR
+ * Delete the unhashed password pseudo-attribute (for delete)
+ * before calling the preop plugins
*/
if (pw_change && !repl_op)
@@ -837,10 +837,20 @@ static void op_shared_modify (Slapi_PBlock *pb, int pw_change, char *old_pw)
if (strcasecmp (pw_mod->mod_type, SLAPI_USERPWD_ATTR) != 0)
continue;
- /* add pseudo password attribute */
- valuearray_init_bervalarray(pw_mod->mod_bvalues, &va);
- slapi_mods_add_mod_values(&smods, pw_mod->mod_op, unhashed_pw_attr, va);
- valuearray_free(&va);
+ if (LDAP_MOD_DELETE == pw_mod->mod_op) {
+ Slapi_Attr *a = NULL;
+ /* delete pseudo password attribute if it exists in the entry */
+ if (!slapi_entry_attr_find(e, unhashed_pw_attr, &a)) {
+ slapi_mods_add_mod_values(&smods, pw_mod->mod_op,
+ unhashed_pw_attr, va);
+ }
+ } else {
+ /* add pseudo password attribute */
+ valuearray_init_bervalarray(pw_mod->mod_bvalues, &va);
+ slapi_mods_add_mod_values(&smods, pw_mod->mod_op,
+ unhashed_pw_attr, va);
+ valuearray_free(&va);
+ }
/* Init new value array for hashed value */
valuearray_init_bervalarray(pw_mod->mod_bvalues, &va);
@@ -1199,7 +1209,8 @@ static int op_shared_allow_pw_change (Slapi_PBlock *pb, LDAPMod *mod, char **old
/* check password syntax; remember the old password;
error sent directly from check_pw_syntax function */
valuearray_init_bervalarray(mod->mod_bvalues, &values);
- switch (check_pw_syntax_ext (pb, &sdn, values, old_pw, NULL, 1, smods))
+ switch (check_pw_syntax_ext (pb, &sdn, values, old_pw, NULL,
+ mod->mod_op, smods))
{
case 0: /* success */
rc = 1;
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index 3bc7334..0dac10b 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -788,6 +788,20 @@ check_pw_syntax_ext ( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals,
passwdPolicy *pwpolicy = NULL;
Slapi_Operation *operation = NULL;
+ /*
+ * check_pw_syntax_ext could be called with mod_op == LDAP_MOD_DELETE.
+ * In that case, no need to check the password syntax, but just returns
+ * PASS == 0.
+ */
+ if (LDAP_MOD_DELETE == (mod_op & LDAP_MOD_OP)) {
+ return 0;
+ }
+ if (NULL == vals) {
+ slapi_log_error( SLAPI_LOG_FATAL, NULL,
+ "check_pw_syntax_ext: no passwords to check\n" );
+ return -1;
+ }
+
pwpolicy = new_passwdPolicy(pb, dn);
slapi_pblock_get ( pb, SLAPI_PWPOLICY, &pwresponse_req );
@@ -967,7 +981,7 @@ check_pw_syntax_ext ( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals,
}
/* get the entry and check for the password history if this is called by a modify operation */
- if ( mod_op ) {
+ if ( mod_op ) {
/* retrieve the entry */
e = get_entry ( pb, dn );
if ( e == NULL ) {
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index 7d4e944..75f8e8f 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -330,6 +330,7 @@ int entry_next_deleted_attribute( const Slapi_Entry *e, Slapi_Attr **a);
/* entry.c */
int entry_apply_mods( Slapi_Entry *e, LDAPMod **mods );
+int is_type_protected(const char *type);
int slapi_entries_diff(Slapi_Entry **old_entries, Slapi_Entry **new_entries, int testall, const char *logging_prestr, const int force_update, void *plg_id);
11 years, 12 months
Branch 'Directory_Server_8_2_Branch' - ldap/servers
by Mark Reynolds
ldap/servers/plugins/cos/cos.c | 36 -
ldap/servers/plugins/cos/cos_cache.c | 833 ++++++++++++++++++-----------------
2 files changed, 460 insertions(+), 409 deletions(-)
New commits:
commit 452d2b8a588a47a05ca31270a039607e69acdf6b
Author: Mark Reynolds <mareynol(a)redhat.com>
Date: Wed Apr 4 11:26:03 2012 -0400
Ticket #300 - password polcies not sticking
Bug Description: Under load the cos cache can become corrupted. This would cause
the subtree defined passwd policy to stop working
Fix Description: Used the entire cos code from DS 9 as it doesn't display this
behavior.
https://fedorahosted.org/389/ticket/300
diff --git a/ldap/servers/plugins/cos/cos.c b/ldap/servers/plugins/cos/cos.c
index 78ae5d6..8a7029d 100644
--- a/ldap/servers/plugins/cos/cos.c
+++ b/ldap/servers/plugins/cos/cos.c
@@ -170,17 +170,18 @@ int
cos_postop_init ( Slapi_PBlock *pb )
{
int rc = 0;
+ int postadd = SLAPI_PLUGIN_POST_ADD_FN;
+ int postmod = SLAPI_PLUGIN_POST_MODIFY_FN;
+ int postmdn = SLAPI_PLUGIN_POST_MODRDN_FN;
+ int postdel = SLAPI_PLUGIN_POST_DELETE_FN;
+
if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
SLAPI_PLUGIN_VERSION_01 ) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN,
- (void *)cos_post_op ) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN,
- (void *)cos_post_op ) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN,
- (void *) cos_post_op ) != 0 ||
- slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN,
- (void *) cos_post_op ) != 0 )
+ slapi_pblock_set(pb, postmod, (void *)cos_post_op ) != 0 ||
+ slapi_pblock_set(pb, postmdn, (void *)cos_post_op ) != 0 ||
+ slapi_pblock_set(pb, postadd, (void *) cos_post_op ) != 0 ||
+ slapi_pblock_set(pb, postdel, (void *) cos_post_op ) != 0 )
{
slapi_log_error( SLAPI_LOG_FATAL, COS_PLUGIN_SUBSYSTEM,
"cos_postop_init: failed to register plugin\n" );
@@ -221,9 +222,13 @@ int cos_init( Slapi_PBlock *pb )
{
int ret = 0;
void * plugin_identity=NULL;
+ Slapi_Entry *plugin_entry = NULL;
+ int is_betxn = 0;
+ const char *plugintype = "postoperation";
LDAPDebug( LDAP_DEBUG_TRACE, "--> cos_init\n",0,0,0);
+
/*
** Store the plugin identity for later use.
** Used for internal operations
@@ -248,7 +253,10 @@ int cos_init( Slapi_PBlock *pb )
goto bailout;
}
- ret = slapi_register_plugin("postoperation", 1 /* Enabled */,
+ if (is_betxn) {
+ plugintype = "betxnpostoperation";
+ }
+ ret = slapi_register_plugin(plugintype, 1 /* Enabled */,
"cos_postop_init", cos_postop_init,
"Class of Service postoperation plugin", NULL,
plugin_identity);
@@ -256,10 +264,12 @@ int cos_init( Slapi_PBlock *pb )
goto bailout;
}
- ret = slapi_register_plugin("internalpostoperation", 1 /* Enabled */,
- "cos_internalpostop_init", cos_internalpostop_init,
- "Class of Service internalpostoperation plugin", NULL,
- plugin_identity);
+ if (!is_betxn) {
+ ret = slapi_register_plugin("internalpostoperation", 1 /* Enabled */,
+ "cos_internalpostop_init", cos_internalpostop_init,
+ "Class of Service internalpostoperation plugin", NULL,
+ plugin_identity);
+ }
bailout:
LDAPDebug( LDAP_DEBUG_TRACE, "<-- cos_init\n",0,0,0);
diff --git a/ldap/servers/plugins/cos/cos_cache.c b/ldap/servers/plugins/cos/cos_cache.c
index 496f749..2c5bf3f 100644
--- a/ldap/servers/plugins/cos/cos_cache.c
+++ b/ldap/servers/plugins/cos/cos_cache.c
@@ -326,8 +326,6 @@ static int cos_cache_vattr_compare(vattr_sp_handle *handle, vattr_context *c, Sl
static int cos_cache_vattr_types(vattr_sp_handle *handle,Slapi_Entry *e,vattr_type_list_context *type_context,int flags);
static int cos_cache_query_attr(cos_cache *ptheCache, vattr_context *context, Slapi_Entry *e, char *type, Slapi_ValueSet **out_attr, Slapi_Value *test_this, int *result, int *ops);
-static int hexchar2int( char c );
-
/*
compares s2 to s1 starting from end of string until the beginning of either
matches result in the s2 value being clipped from s1 with a NULL char
@@ -679,57 +677,58 @@ static int cos_cache_build_definition_list(cosDefinitions **pDefs, int *vattr_ca
if(pSuffixSearch)
slapi_pblock_get( pSuffixSearch, SLAPI_PLUGIN_INTOP_RESULT, &ret);
- if(pSuffixSearch && ret == LDAP_SUCCESS)
+ if(!pSuffixSearch || ret != LDAP_SUCCESS) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "cos_cache_build_definition_list: failed to find suffixes\n",
+ 0,0,0);
+ ret = -1;
+ goto next;
+ }
+
+ /* iterate through the suffixes and search for cos definitions */
+ slapi_pblock_get( pSuffixSearch, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
+ &pSuffixList );
+ if(!pSuffixList) {
+ goto next;
+ }
+ while(pSuffixList[suffixIndex])
{
- /* iterate through the suffixes and search for cos definitions */
- slapi_pblock_get( pSuffixSearch, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &pSuffixList);
- if(pSuffixList)
+ if(!slapi_entry_first_attr(pSuffixList[suffixIndex], &suffixAttr))
{
- while(pSuffixList[suffixIndex])
+ do
{
- if(!slapi_entry_first_attr(pSuffixList[suffixIndex], &suffixAttr))
+ attrType = 0;
+ slapi_attr_get_type(suffixAttr, &attrType);
+ if(attrType && !slapi_utf8casecmp((unsigned char*)attrType, (unsigned char*)"namingcontexts"))
{
- do
+ if(!slapi_attr_get_bervals_copy(suffixAttr, &suffixVals))
{
- attrType = 0;
- slapi_attr_get_type(suffixAttr, &attrType);
- if(attrType && !slapi_utf8casecmp((unsigned char*)attrType, (unsigned char*)"namingcontexts"))
+ valIndex = 0;
+
+ if(suffixVals)
{
- if(!slapi_attr_get_bervals_copy(suffixAttr, &suffixVals))
+ while(suffixVals[valIndex])
{
- valIndex = 0;
-
- if(suffixVals)
- {
- while(suffixVals[valIndex])
- {
- /* here's a suffix, lets search it... */
- if(suffixVals[valIndex]->bv_val)
- if(!cos_cache_add_dn_defs(suffixVals[valIndex]->bv_val ,pDefs, vattr_cacheable))
- cos_def_available = 1;
-
- valIndex++;
- }
+ /* here's a suffix, lets search it... */
+ if(suffixVals[valIndex]->bv_val)
+ if(!cos_cache_add_dn_defs(suffixVals[valIndex]->bv_val ,pDefs, vattr_cacheable))
+ cos_def_available = 1;
+
+ valIndex++;
+ }
- ber_bvecfree( suffixVals );
- suffixVals = NULL;
- }
- }
+ ber_bvecfree( suffixVals );
+ suffixVals = NULL;
}
-
- } while(!slapi_entry_next_attr(pSuffixList[suffixIndex], suffixAttr, &suffixAttr));
+ }
}
- suffixIndex++;
- }
+
+ } while(!slapi_entry_next_attr(pSuffixList[suffixIndex], suffixAttr, &suffixAttr));
}
+ suffixIndex++;
}
- else
- {
- LDAPDebug( LDAP_DEBUG_ANY, "cos_cache_build_definition_list: failed to find suffixes\n",0,0,0);
- ret = -1;
- }
-
+next:
if(cos_def_available == 0)
{
if(firstTime)
@@ -768,7 +767,8 @@ struct dn_defs_info {
* if a particular attempt to add a definition fails: info.ret gets set to
* zero only if we succed to add a def.
*/
-static int cos_dn_defs_cb (Slapi_Entry* e, void *callback_data) {
+static int cos_dn_defs_cb (Slapi_Entry* e, void *callback_data)
+{
struct dn_defs_info *info;
cosAttrValue **pSneakyVal = 0;
cosAttrValue *pObjectclass = 0;
@@ -786,6 +786,7 @@ static int cos_dn_defs_cb (Slapi_Entry* e, void *callback_data) {
int valIndex = 0;
Slapi_Attr *dnAttr;
char *attrType = 0;
+ char *norm_dn = NULL;
info=(struct dn_defs_info *)callback_data;
@@ -793,284 +794,283 @@ static int cos_dn_defs_cb (Slapi_Entry* e, void *callback_data) {
info->vattr_cacheable = -1;
cos_cache_add_attrval(&pDn, slapi_entry_get_dn(e));
- if(!slapi_entry_first_attr(e, &dnAttr))
- {
- do
+ if(slapi_entry_first_attr(e, &dnAttr)) {
+ goto bail;
+ }
+
+ do {
+ attrType = 0;
+ /* we need to fill in the details of the definition now */
+ slapi_attr_get_type(dnAttr, &attrType);
+ if(!attrType) {
+ continue;
+ }
+ pSneakyVal = 0;
+ if(!slapi_utf8casecmp((unsigned char*)attrType, (unsigned char*)"objectclass"))
+ pSneakyVal = &pObjectclass;
+ else if(!slapi_utf8casecmp((unsigned char*)attrType, (unsigned char*)"cosTargetTree")){
+ if(pCosTargetTree){
+ norm_dn = slapi_create_dn_string("%s", pCosTargetTree->val);
+ if(norm_dn){
+ slapi_ch_free_string(&pCosTargetTree->val);
+ pCosTargetTree->val = norm_dn;
+ }
+ }
+ pSneakyVal = &pCosTargetTree;
+ } else if(!slapi_utf8casecmp((unsigned char*)attrType, (unsigned char*)"cosTemplateDn"))
+ pSneakyVal = &pCosTemplateDn;
+ else if(!slapi_utf8casecmp((unsigned char*)attrType, (unsigned char*)"cosSpecifier"))
+ pSneakyVal = &pCosSpecifier;
+ else if(!slapi_utf8casecmp((unsigned char*)attrType, (unsigned char*)"cosAttribute"))
+ pSneakyVal = &pCosAttribute;
+ else if(!slapi_utf8casecmp((unsigned char*)attrType, (unsigned char*)"cosIndirectSpecifier"))
+ pSneakyVal = &pCosSpecifier;
+ if(!pSneakyVal) {
+ continue;
+ }
+ /* It's a type we're interested in */
+ if(slapi_attr_get_bervals_copy(dnAttr, &dnVals)) {
+ continue;
+ }
+ valIndex = 0;
+ if(!dnVals) {
+ continue;
+ }
+ for (valIndex = 0; dnVals[valIndex]; valIndex++)
{
- attrType = 0;
- /* we need to fill in the details of the definition now */
- slapi_attr_get_type(dnAttr, &attrType);
- if(attrType)
+ if(!dnVals[valIndex]->bv_val) {
+ continue;
+ }
+ /*
+ parse any overide or default values
+ and deal with them
+ */
+ if(pSneakyVal == &pCosAttribute)
{
- pSneakyVal = 0;
- if(!slapi_utf8casecmp((unsigned char*)attrType, (unsigned char*)"objectclass"))
- pSneakyVal = &pObjectclass;
- else if(!slapi_utf8casecmp((unsigned char*)attrType, (unsigned char*)"cosTargetTree"))
- pSneakyVal = &pCosTargetTree;
- else if(!slapi_utf8casecmp((unsigned char*)attrType, (unsigned char*)"cosTemplateDn"))
- pSneakyVal = &pCosTemplateDn;
- else if(!slapi_utf8casecmp((unsigned char*)attrType, (unsigned char*)"cosSpecifier"))
- pSneakyVal = &pCosSpecifier;
- else if(!slapi_utf8casecmp((unsigned char*)attrType, (unsigned char*)"cosAttribute"))
- pSneakyVal = &pCosAttribute;
- else if(!slapi_utf8casecmp((unsigned char*)attrType, (unsigned char*)"cosIndirectSpecifier"))
- pSneakyVal = &pCosSpecifier;
- if(pSneakyVal)
+ int qualifier_hit = 0;
+ int op_qualifier_hit = 0;
+ int merge_schemes_qualifier_hit = 0;
+ int override_qualifier_hit =0;
+ int default_qualifier_hit = 0;
+ int operational_default_qualifier_hit = 0;
+ do
{
- /* It's a type we're interested in */
- if(!slapi_attr_get_bervals_copy(dnAttr, &dnVals))
+ qualifier_hit = 0;
+
+ if(cos_cache_backwards_stricmp_and_clip(dnVals[valIndex]->bv_val, " operational"))
{
- valIndex = 0;
- if(dnVals)
- {
- while(dnVals[valIndex])
- {
- if(dnVals[valIndex]->bv_val)
- {
- /*
- parse any overide or default values
- and deal with them
- */
- if(pSneakyVal == &pCosAttribute)
- {
- int qualifier_hit = 0;
- int op_qualifier_hit = 0;
- int merge_schemes_qualifier_hit = 0;
- int override_qualifier_hit =0;
- int default_qualifier_hit = 0;
- int operational_default_qualifier_hit = 0;
- do
- {
- qualifier_hit = 0;
+ /* matched */
+ op_qualifier_hit = 1;
+ qualifier_hit = 1;
+ }
+
+ if(cos_cache_backwards_stricmp_and_clip(dnVals[valIndex]->bv_val, " merge-schemes"))
+ {
+ /* matched */
+ merge_schemes_qualifier_hit = 1;
+ qualifier_hit = 1;
+ }
- if(cos_cache_backwards_stricmp_and_clip(dnVals[valIndex]->bv_val, " operational"))
- {
- /* matched */
- op_qualifier_hit = 1;
- qualifier_hit = 1;
- }
-
- if(cos_cache_backwards_stricmp_and_clip(dnVals[valIndex]->bv_val, " merge-schemes"))
- {
- /* matched */
- merge_schemes_qualifier_hit = 1;
- qualifier_hit = 1;
- }
+ if(cos_cache_backwards_stricmp_and_clip(dnVals[valIndex]->bv_val, " override"))
+ {
+ /* matched */
+ override_qualifier_hit = 1;
+ qualifier_hit = 1;
+ }
+
+ if(cos_cache_backwards_stricmp_and_clip(dnVals[valIndex]->bv_val, " default")) {
+ default_qualifier_hit = 1;
+ qualifier_hit = 1;
+ }
- if(cos_cache_backwards_stricmp_and_clip(dnVals[valIndex]->bv_val, " override"))
- {
- /* matched */
- override_qualifier_hit = 1;
- qualifier_hit = 1;
- }
-
- if(cos_cache_backwards_stricmp_and_clip(dnVals[valIndex]->bv_val, " default")) {
- default_qualifier_hit = 1;
- qualifier_hit = 1;
- }
+ if(cos_cache_backwards_stricmp_and_clip(dnVals[valIndex]->bv_val, " operational-default")) {
+ operational_default_qualifier_hit = 1;
+ qualifier_hit = 1;
+ }
+ }
+ while(qualifier_hit == 1);
- if(cos_cache_backwards_stricmp_and_clip(dnVals[valIndex]->bv_val, " operational-default")) {
- operational_default_qualifier_hit = 1;
- qualifier_hit = 1;
- }
- }
- while(qualifier_hit == 1);
-
- /*
- * At this point, dnVals[valIndex]->bv_val
- * is the value of cosAttribute, stripped of
- * any qualifiers, so add this pure attribute type to
- * the appropriate lists.
- */
-
- if ( op_qualifier_hit ) {
- cos_cache_add_attrval(&pCosOperational,
- dnVals[valIndex]->bv_val);
- }
- if ( merge_schemes_qualifier_hit ) {
- cos_cache_add_attrval(&pCosMerge,
- dnVals[valIndex]->bv_val);
- }
- if ( override_qualifier_hit ) {
- cos_cache_add_attrval(&pCosOverrides,
- dnVals[valIndex]->bv_val);
- }
- if ( default_qualifier_hit ) {
- /* attr is added below in pSneakyVal, in any case */
- }
+ /*
+ * At this point, dnVals[valIndex]->bv_val
+ * is the value of cosAttribute, stripped of
+ * any qualifiers, so add this pure attribute type to
+ * the appropriate lists.
+ */
+
+ if ( op_qualifier_hit ) {
+ cos_cache_add_attrval(&pCosOperational,
+ dnVals[valIndex]->bv_val);
+ }
+ if ( merge_schemes_qualifier_hit ) {
+ cos_cache_add_attrval(&pCosMerge, dnVals[valIndex]->bv_val);
+ }
+ if ( override_qualifier_hit ) {
+ cos_cache_add_attrval(&pCosOverrides,
+ dnVals[valIndex]->bv_val);
+ }
+ if ( default_qualifier_hit ) {
+ /* attr is added below in pSneakyVal, in any case */
+ }
- if ( operational_default_qualifier_hit ) {
- cos_cache_add_attrval(&pCosOpDefault,
- dnVals[valIndex]->bv_val);
- }
+ if ( operational_default_qualifier_hit ) {
+ cos_cache_add_attrval(&pCosOpDefault,
+ dnVals[valIndex]->bv_val);
+ }
- if(!pCosTargetTree)
- {
- /* get the parent of the definition */
-
- char *parent = NULL;
- size_t plen = 0;
- int rc = 0;
- char *orig = slapi_dn_parent(pDn->val);
- rc = slapi_dn_normalize_ext(orig,
- 0, &parent, &plen);
- if (rc < 0) {
- LDAPDebug(LDAP_DEBUG_ANY,
- "cos_cache_build_definition_list: failed to normalize parent dn %s. Adding the pre normalized dn.\n", orig, 0, 0);
- parent = orig;
- } else if (rc == 0) {
- /* passed in. not terminated */
- *(parent + plen) = '\0';
- }
-
- cos_cache_add_attrval(&pCosTargetTree, parent);
- if(!pCosTemplateDn)
- cos_cache_add_attrval(&pCosTemplateDn, parent);
-
- if (orig != parent) {
- slapi_ch_free_string(&orig);
- }
- slapi_ch_free_string(&parent);
- }
-
- slapi_vattrspi_regattr((vattr_sp_handle *)vattr_handle, dnVals[valIndex]->bv_val, NULL, NULL);
- } /* if(attrType is cosAttribute) */
-
- /*
- * Add the attributetype to the appropriate
- * list.
- */
- cos_cache_add_attrval(pSneakyVal,
- dnVals[valIndex]->bv_val);
- }/*if(dnVals[valIndex]->bv_val)*/
-
- valIndex++;
- }/* while(dnVals[valIndex]) */
-
- ber_bvecfree( dnVals );
- dnVals = NULL;
- }/*if(dnVals)*/
+ if(!pCosTargetTree)
+ {
+ /* get the parent of the definition */
+ char *orig = slapi_dn_parent(pDn->val);
+ Slapi_DN *psdn = slapi_sdn_new_dn_byval(orig);
+ char *parent = (char *)slapi_sdn_get_dn(psdn);
+ if (!parent) {
+ parent = (char *)slapi_sdn_get_ndn(psdn);
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "cos_cache_build_definition_list: "
+ "failed to normalize parent dn %s. "
+ "Adding the pre normalized dn.\n",
+ parent, 0, 0);
}
- }/*if(pSneakyVal)*/
- }/*if(attrType)*/
+ cos_cache_add_attrval(&pCosTargetTree, parent);
+ if (!pCosTemplateDn) {
+ cos_cache_add_attrval(&pCosTemplateDn, parent);
+ }
+ slapi_sdn_free(&psdn);
+ }
+
+ slapi_vattrspi_regattr((vattr_sp_handle *)vattr_handle,
+ dnVals[valIndex]->bv_val, NULL, NULL);
+ } /* if(attrType is cosAttribute) */
+
+ /*
+ * Add the attributetype to the appropriate
+ * list.
+ */
+ cos_cache_add_attrval(pSneakyVal, dnVals[valIndex]->bv_val);
- } while(!slapi_entry_next_attr(e, dnAttr, &dnAttr));
-
- /*
- determine the type of class of service scheme
- */
+ }/* for (valIndex = 0; dnVals[valIndex]; valIndex++) */
- if(pObjectclass)
+ ber_bvecfree( dnVals );
+ dnVals = NULL;
+ } while(!slapi_entry_next_attr(e, dnAttr, &dnAttr));
+
+ /*
+ determine the type of class of service scheme
+ */
+
+ if(pObjectclass)
+ {
+ if(cos_cache_attrval_exists(pObjectclass, "cosDefinition"))
{
- if(cos_cache_attrval_exists(pObjectclass, "cosDefinition"))
- {
- cosType = COSTYPE_CLASSIC;
- }
- else if(cos_cache_attrval_exists(pObjectclass, "cosClassicDefinition"))
- {
- cosType = COSTYPE_CLASSIC;
-
- }
- else if(cos_cache_attrval_exists(pObjectclass, "cosPointerDefinition"))
- {
- cosType = COSTYPE_POINTER;
-
- }
- else if(cos_cache_attrval_exists(pObjectclass, "cosIndirectDefinition"))
- {
- cosType = COSTYPE_INDIRECT;
-
- }
- else
- cosType = COSTYPE_BADTYPE;
+ cosType = COSTYPE_CLASSIC;
}
-
- /*
- we should now have a full definition,
- do some sanity checks because we don't
- want bogus entries in the cache
- then ship it
- */
-
- /* these must exist */
- if( pDn &&
- pObjectclass &&
+ else if(cos_cache_attrval_exists(pObjectclass, "cosClassicDefinition"))
+ {
+ cosType = COSTYPE_CLASSIC;
- (
- (cosType == COSTYPE_CLASSIC &&
- pCosTemplateDn &&
- pCosSpecifier &&
- pCosAttribute )
- ||
- (cosType == COSTYPE_POINTER &&
- pCosTemplateDn &&
- pCosAttribute )
- ||
- (cosType == COSTYPE_INDIRECT &&
- pCosSpecifier &&
- pCosAttribute )
- )
- )
+ }
+ else if(cos_cache_attrval_exists(pObjectclass, "cosPointerDefinition"))
{
- int rc = 0;
- /*
- we'll leave the referential integrity stuff
- up to the referint plug-in and assume all
- is good - if it's not then we just have a
- useless definition and we'll nag copiously later.
- */
- char *pTmpDn = slapi_ch_strdup(pDn->val); /* because dn gets hosed on error */
- char ebuf[ BUFSIZ ];
+ cosType = COSTYPE_POINTER;
- if(!(rc = cos_cache_add_defn(info->pDefs, &pDn, cosType,
- &pCosTargetTree, &pCosTemplateDn,
- &pCosSpecifier, &pCosAttribute,
- &pCosOverrides, &pCosOperational,
- &pCosMerge, &pCosOpDefault))) {
- info->ret = 0; /* we have succeeded to add the defn*/
- } else {
- /*
- * Failed but we will continue the search for other defs
- * Don't reset info->ret....it keeps track of any success
- */
- if ( rc == COS_DEF_ERROR_NO_TEMPLATES) {
- LDAPDebug(LDAP_DEBUG_ANY, "skipping cos definition %s"
- "--no templates found\n",
- escape_string(pTmpDn, ebuf),0,0);
- } else {
- LDAPDebug(LDAP_DEBUG_ANY, "skipping cos definition %s\n"
- ,escape_string(pTmpDn, ebuf),0,0);
- }
- }
+ }
+ else if(cos_cache_attrval_exists(pObjectclass, "cosIndirectDefinition"))
+ {
+ cosType = COSTYPE_INDIRECT;
- slapi_ch_free_string(&pTmpDn);
}
else
- {
- /*
- this definition is brain dead - bail
- if we have a dn use it to report, if not then *really* bad
- things are going on
+ cosType = COSTYPE_BADTYPE;
+ }
+
+ /*
+ we should now have a full definition,
+ do some sanity checks because we don't
+ want bogus entries in the cache
+ then ship it
+ */
+
+ /* these must exist */
+ if( pDn &&
+ pObjectclass &&
+
+ (
+ (cosType == COSTYPE_CLASSIC &&
+ pCosTemplateDn &&
+ pCosSpecifier &&
+ pCosAttribute )
+ ||
+ (cosType == COSTYPE_POINTER &&
+ pCosTemplateDn &&
+ pCosAttribute )
+ ||
+ (cosType == COSTYPE_INDIRECT &&
+ pCosSpecifier &&
+ pCosAttribute )
+ )
+ )
+ {
+ int rc = 0;
+ /*
+ we'll leave the referential integrity stuff
+ up to the referint plug-in and assume all
+ is good - if it's not then we just have a
+ useless definition and we'll nag copiously later.
+ */
+ char *pTmpDn = slapi_ch_strdup(pDn->val); /* because dn gets hosed on error */
+ char ebuf[ BUFSIZ ];
+
+ if(!(rc = cos_cache_add_defn(info->pDefs, &pDn, cosType,
+ &pCosTargetTree, &pCosTemplateDn,
+ &pCosSpecifier, &pCosAttribute,
+ &pCosOverrides, &pCosOperational,
+ &pCosMerge, &pCosOpDefault))) {
+ info->ret = 0; /* we have succeeded to add the defn*/
+ } else {
+ /*
+ * Failed but we will continue the search for other defs
+ * Don't reset info->ret....it keeps track of any success
*/
- if(pDn)
- {
- LDAPDebug( LDAP_DEBUG_ANY, "cos_cache_add_dn_defs: incomplete cos definition detected in %s, discarding from cache.\n",pDn->val,0,0);
+ if ( rc == COS_DEF_ERROR_NO_TEMPLATES) {
+ LDAPDebug(LDAP_DEBUG_ANY, "Skipping CoS Definition %s"
+ "--no CoS Templates found, "
+ "which should be added before the CoS Definition.\n",
+ escape_string(pTmpDn, ebuf), 0, 0);
+ } else {
+ LDAPDebug(LDAP_DEBUG_ANY, "Skipping CoS Definition %s\n"
+ "--error(%d)\n",
+ escape_string(pTmpDn, ebuf), rc, 0);
}
- else
- LDAPDebug( LDAP_DEBUG_ANY, "cos_cache_add_dn_defs: incomplete cos definition detected, no DN to report, discarding from cache.\n",0,0,0);
-
- if(pCosTargetTree)
- cos_cache_del_attrval_list(&pCosTargetTree);
- if(pCosTemplateDn)
- cos_cache_del_attrval_list(&pCosTemplateDn);
- if(pCosSpecifier)
- cos_cache_del_attrval_list(&pCosSpecifier);
- if(pCosAttribute)
- cos_cache_del_attrval_list(&pCosAttribute);
- if(pDn)
- cos_cache_del_attrval_list(&pDn);
}
- }/*if(!slapi_entry_first_attr(e, &dnAttr))*/
+
+ slapi_ch_free_string(&pTmpDn);
+ }
+ else
+ {
+ /*
+ this definition is brain dead - bail
+ if we have a dn use it to report, if not then *really* bad
+ things are going on
+ */
+ if(pDn)
+ {
+ LDAPDebug( LDAP_DEBUG_ANY, "cos_cache_add_dn_defs: incomplete cos definition detected in %s, discarding from cache.\n",pDn->val,0,0);
+ }
+ else
+ LDAPDebug( LDAP_DEBUG_ANY, "cos_cache_add_dn_defs: incomplete cos definition detected, no DN to report, discarding from cache.\n",0,0,0);
+
+ if(pCosTargetTree)
+ cos_cache_del_attrval_list(&pCosTargetTree);
+ if(pCosTemplateDn)
+ cos_cache_del_attrval_list(&pCosTemplateDn);
+ if(pCosSpecifier)
+ cos_cache_del_attrval_list(&pCosSpecifier);
+ if(pCosAttribute)
+ cos_cache_del_attrval_list(&pCosAttribute);
+ if(pDn)
+ cos_cache_del_attrval_list(&pDn);
+ }
+bail:
/* we don't keep the objectclasses, so lets free them */
if(pObjectclass) {
cos_cache_del_attrval_list(&pObjectclass);
@@ -1085,6 +1085,32 @@ static int cos_dn_defs_cb (Slapi_Entry* e, void *callback_data) {
}
+static const int char2intarray[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+int
+slapi_hexchar2int(char c)
+{
+ return char2intarray[(unsigned char)c];
+}
+
+
/*
cos_cache_add_dn_defs
-------------------------
@@ -1101,7 +1127,7 @@ static int cos_dn_defs_cb (Slapi_Entry* e, void *callback_data) {
static int cos_cache_add_dn_defs(char *dn, cosDefinitions **pDefs, int *vattr_cacheable)
{
Slapi_PBlock *pDnSearch = 0;
- struct dn_defs_info info;
+ struct dn_defs_info info = {NULL, 0, 0};
pDnSearch = slapi_pblock_new();
if (pDnSearch) {
info.ret=-1; /* assume no good defs */
@@ -1314,7 +1340,7 @@ static int cos_cache_add_dn_tmpls(char *dn, cosAttrValue *pCosSpecifier, cosAttr
{
void *plugin_id;
int scope;
- struct tmpl_info info;
+ struct tmpl_info info = {NULL, 0, 0};
Slapi_PBlock *pDnSearch = 0;
LDAPDebug( LDAP_DEBUG_TRACE, "--> cos_cache_add_dn_tmpls\n",0,0,0);
@@ -1383,14 +1409,28 @@ static int cos_cache_add_defn(
int ret = 0;
int tmplCount = 0;
cosDefinitions *theDef = 0;
- cosAttrValue *pTmpTmplDn = *tmpDn;
+ cosAttrValue *pTmpTmplDn = 0;
cosAttrValue *pDummyAttrVal = 0;
cosAttrValue *pAttrsIter = 0;
cosAttributes *pDummyAttributes = 0;
- cosAttrValue *pSpecsIter = *spec;
+ cosAttrValue *pSpecsIter = 0;
LDAPDebug( LDAP_DEBUG_TRACE, "--> cos_cache_add_defn\n",0,0,0);
+ if (!spec) {
+ LDAPDebug( LDAP_DEBUG_ANY, "missing spec\n",0,0,0);
+ ret = -1;
+ goto out;
+ }
+ pSpecsIter = *spec;
+
+ if (!tmpDn) {
+ LDAPDebug( LDAP_DEBUG_ANY, "missing tmpDn\n",0,0,0);
+ ret = -1;
+ goto out;
+ }
+ pTmpTmplDn = *tmpDn;
+
/* we don't want cosspecifiers that can be supplied by the same scheme */
while( pSpecsIter )
{
@@ -1481,9 +1521,10 @@ static int cos_cache_add_defn(
ret = -1;
}
}
-
- if(ret == -1)
+out:
+ if(ret < 0)
{
+ slapi_ch_free((void**)&theDef);
if(dn)
cos_cache_del_attrval_list(dn);
if(tree)
@@ -1494,8 +1535,6 @@ static int cos_cache_add_defn(
cos_cache_del_attrval_list(spec);
if(pAttrs)
cos_cache_del_attrval_list(pAttrs);
- if(theDef)
- slapi_ch_free((void**)&theDef);
}
LDAPDebug( LDAP_DEBUG_TRACE, "<-- cos_cache_add_defn\n",0,0,0);
@@ -1529,7 +1568,8 @@ static void cos_cache_del_attrval_list(cosAttrValue **pVal)
---------------------
adds a value to an attribute value list
*/
-static int cos_cache_add_attrval(cosAttrValue **attrval, char *val)
+static int
+cos_cache_add_attrval(cosAttrValue **attrval, char *val)
{
int ret = 0;
cosAttrValue *theVal;
@@ -1714,7 +1754,7 @@ int cos_cache_getref(cos_cache **pptheCache)
*/
int cos_cache_addref(cos_cache *ptheCache)
{
- int ret;
+ int ret = 0;
cosCache *pCache = (cosCache*)ptheCache;
LDAPDebug( LDAP_DEBUG_TRACE, "--> cos_cache_addref\n",0,0,0);
@@ -1938,36 +1978,28 @@ static int cos_cache_add_tmpl(cosTemplates **pTemplates, cosAttrValue *dn, cosAt
char *grade = NULL;
int grade_index = 0;
int index = 0;
- int lastindex = 0;
int template_default = 0;
- char *dnval = NULL;
- size_t dnlen = 0;
- int rc = 0;
-
- rc = slapi_dn_normalize_ext(dn->val, 0, &dnval, &dnlen);
- if (rc < 0) {
+ char *ptr = NULL;
+ char *normed = slapi_create_dn_string("%s", dn->val);
+ if (normed) {
+ slapi_ch_free_string(&dn->val);
+ dn->val = normed;
+ } else {
LDAPDebug(LDAP_DEBUG_ANY,
"cos_cache_add_tmpl: failed to normalize dn %s. "
- "Processing the pre normalized dn.\n", dn->val, 0, 0);
- } else if (rc == 0) {
- /* passed in. not terminated */
- *(dnval + dnlen) = '\0';
- } else {
- slapi_ch_free_string(&dn->val);
- dn->val = dnval;
+ "Processing the pre normalized dn.\n",
+ dn->val, 0, 0);
}
grade = (char*)slapi_ch_malloc(strlen(dn->val)+1);
/* extract the cos grade */
- while(dn->val[index] != '=' && dn->val[index] != '\0')
- index++;
- lastindex = strlen(dn->val) - 1;
-
- if(dn->val[index] == '=')
+ ptr = strchr(dn->val, '=');
+
+ if (ptr)
{
int quotes = 0;
-
- index++;
+ int lastindex = strlen(dn->val) - 1;
+ index = ptr - dn->val + 1;
/* copy the grade (supports one level of quote nesting in rdn) */
while(dn->val[index] != ',' || dn->val[index-1] == '\\' || quotes == 1)
@@ -1986,8 +2018,8 @@ static int cos_cache_add_tmpl(cosTemplates **pTemplates, cosAttrValue *dn, cosAt
if ((index+2 <= lastindex) && isxdigit(dn->val[index+1]) &&
isxdigit(dn->val[index+2])) {
/* Convert ESC HEX HEX to a real char */
- int n = hexchar2int(dn->val[index+1]);
- int n2 = hexchar2int(dn->val[index+2]);
+ int n = slapi_hexchar2int(dn->val[index+1]);
+ int n2 = slapi_hexchar2int(dn->val[index+2]);
n = (n << 4) + n2;
if (n == 0) { /* don't change \00 */
grade[grade_index] = dn->val[index++]; /* '\\' */
@@ -2354,9 +2386,10 @@ static int cos_cache_query_attr(cos_cache *ptheCache, vattr_context *context, Sl
/** class of service specifier **/
/*
- now we need to iterate through the attributes to discover
+ Now we need to iterate through the attributes to discover
if one fits all the criteria, we'll take the first that does
- and blow off the rest
+ and blow off the rest unless the definition has merge-scheme
+ set.
*/
do
{
@@ -2384,29 +2417,11 @@ static int cos_cache_query_attr(cos_cache *ptheCache, vattr_context *context, Sl
continue;
}
- /* is this entry a child of the target tree(s)? */
- do
+ /* If we haven't found a hit yet, or if we are in merge mode, look for
+ * hits. We only check if this entry is a child of the target tree(s). */
+ while((hit == 0 || merge_mode) && pTargetTree)
{
- if(pTargetTree) {
- int rc = 0;
- char *tval = NULL;
- size_t tlen = 0;
- rc = slapi_dn_normalize_ext(pTargetTree->val, 0, &tval, &tlen);
- if (rc < 0) {
- LDAPDebug(LDAP_DEBUG_ANY,
- "cos_cache_query_attr: failed to normalize dn %s. "
- "Processing the pre normalized dn.\n",
- pTargetTree->val, 0, 0);
- } else if (rc == 0) {
- /* passed in. not terminated */
- *(tval + tlen) = '\0';
- } else {
- slapi_ch_free_string(&pTargetTree->val);
- pTargetTree->val = tval;
- }
- }
-
- if( pTargetTree->val == 0 ||
+ if( pTargetTree->val == 0 ||
slapi_dn_issuffix(pDn, pTargetTree->val) != 0 ||
(views_api && views_entry_exists(views_api, pTargetTree->val, e)) /* might be in a view */
)
@@ -2427,10 +2442,6 @@ static int cos_cache_query_attr(cos_cache *ptheCache, vattr_context *context, Sl
/* MAB: We need to free actual_type_name here !!!
XXX BAD--should use slapi_vattr_values_free() */
slapi_ch_free((void **) &actual_type_name);
- if (SLAPI_VIRTUALATTRS_LOOP_DETECTED == ret) {
- ret = LDAP_UNWILLING_TO_PERFORM;
- goto bail;
- }
}
if(pAttrSpecs || pDef->cosType == COSTYPE_POINTER)
@@ -2447,16 +2458,73 @@ static int cos_cache_query_attr(cos_cache *ptheCache, vattr_context *context, Sl
Note: we support one dn only, the result of multiple pointers is undefined
*/
Slapi_Value *indirectdn;
+ Slapi_ValueSet *tmp_vals = NULL;
int pointer_flags = 0;
+ int hint = 0;
- slapi_valueset_first_value( pAttrSpecs, &indirectdn );
+ hint = slapi_valueset_first_value( pAttrSpecs, &indirectdn );
if(props)
pointer_flags = *props;
- if( indirectdn != NULL &&
- !cos_cache_follow_pointer( context, (char*)slapi_value_get_string(indirectdn), type, out_attr, test_this, result, pointer_flags))
- hit = 1;
+ while (indirectdn != NULL)
+ {
+ if (cos_cache_follow_pointer( context, (char*)slapi_value_get_string(indirectdn),
+ type, &tmp_vals, test_this, result, pointer_flags) == 0)
+ {
+ hit = 1;
+ /* If the caller requested values, set them. We need
+ * to append values when we follow multiple pointers DNs. */
+ if (out_attr && tmp_vals)
+ {
+ if (*out_attr)
+ {
+ Slapi_Attr *attr = NULL;
+ Slapi_Value *val = NULL;
+ int idx = 0;
+
+ /* Create an attr to use for duplicate detection. */
+ attr = slapi_attr_new();
+ slapi_attr_init(attr, type);
+
+ /* Copy any values into out_attr if they don't already exist. */
+ for (idx = slapi_valueset_first_value(tmp_vals, &val);
+ val && (idx != -1);
+ idx = slapi_valueset_next_value(tmp_vals, idx, &val))
+ {
+ if (slapi_valueset_find(attr, *out_attr, val) == NULL)
+ {
+ slapi_valueset_add_value(*out_attr, val);
+ }
+ }
+
+ slapi_attr_free(&attr);
+ slapi_valueset_free(tmp_vals);
+ tmp_vals = NULL;
+ } else {
+ *out_attr = tmp_vals;
+ tmp_vals = NULL;
+ }
+ }
+ }
+
+ /* If this definition has merge-scheme set, we
+ * need to follow the rest of the pointers. */
+ if (pAttr->attr_cos_merge)
+ {
+ hint = slapi_valueset_next_value(pAttrSpecs, hint, &indirectdn);
+ } else {
+ indirectdn = NULL;
+ }
+ }
+
+ /* If merge-scheme is specified, set merge mode. This will allow
+ * us to merge in values from other CoS definitions for this attr. */
+ if (pAttr->attr_cos_merge)
+ {
+ merge_mode = 1;
+ attr_matched_index = attr_index;
+ }
}
else
{
@@ -2531,7 +2599,7 @@ static int cos_cache_query_attr(cos_cache *ptheCache, vattr_context *context, Sl
pTargetTree = pTargetTree->list.pNext;
- } while(hit == 0 && pTargetTree);
+ } /* while(hit == 0 && pTargetTree) */
if(hit==0 || merge_mode)
@@ -2874,22 +2942,15 @@ static int cos_cache_index_all(cosCache *pCache)
while(pAttrVal)
{
- int rc = 0;
- char *dnval = NULL;
- size_t dnlen = 0;
- rc = slapi_dn_normalize_ext(pAttrVal->val, 0,
- &dnval, &dnlen);
- if (rc < 0) {
+ char *normed = slapi_create_dn_string("%s", pAttrVal->val);
+ if (normed) {
+ slapi_ch_free_string(&pAttrVal->val);
+ pAttrVal->val = normed;
+ } else {
LDAPDebug(LDAP_DEBUG_ANY,
"cos_cache_index_all: failed to normalize dn %s. "
"Processing the pre normalized dn.\n",
pAttrVal->val, 0, 0);
- } else if (rc == 0) {
- /* passed in. not terminated */
- *(dnval + dnlen) = '\0';
- } else {
- slapi_ch_free_string(&pAttrVal->val);
- pAttrVal->val = dnval;
}
pCache->ppTemplateList[tmpindex] = pAttrVal->val;
@@ -3287,7 +3348,8 @@ bail:
*/
void cos_cache_change_notify(Slapi_PBlock *pb)
{
- char *dn;
+ const char *dn;
+ Slapi_DN *sdn = NULL;
int do_update = 0;
struct slapi_entry *e;
Slapi_Backend *be=NULL;
@@ -3521,14 +3583,10 @@ static int cos_cache_follow_pointer( vattr_context *c, const char *dn, char *typ
/* this must be a compare op */
ret = slapi_vattr_value_compare_sp(c, pEntryList[0],type, test_this, result, flags);
break;
-
- default:
- goto bail;
}
}
}
-bail:
/* clean up */
if(pDnSearch)
{
@@ -3609,20 +3667,3 @@ static int cos_cache_entry_is_cos_related( Slapi_Entry *e) {
}
return(rc);
}
-
-/* copied from dn.c */
-static int
-hexchar2int( char c )
-{
- if ( '0' <= c && c <= '9' ) {
- return( c - '0' );
- }
- if ( 'a' <= c && c <= 'f' ) {
- return( c - 'a' + 10 );
- }
- if ( 'A' <= c && c <= 'F' ) {
- return( c - 'A' + 10 );
- }
- return( -1 );
-}
-
11 years, 12 months