OpenLDAP 2.1 Change Log
+OpenLDAP 2.1.14 Engineering
+ Fix slapd directoryString exact index normalization bug
+ Fix back-bdb bdb_cache_find_entry* retry bug
+ Fix back-bdb log message bug
+ Fix back-bdb group/atttribute txn code
+ Updated slapadd to complain about holes in the DIT
+ Documentation
+ Misc man page updates
+
OpenLDAP 2.1.13 Release
Fixed back-bdb group ACL deadlock bug (ITS#2195)
Fixed back-bdb passwd hang bug (ITS#2122)
Build Environment
Check back-bdb requirement for BDB 4.1
Removed configure flags for deprecated features
- Misc man page updates
Updated test suite
+ Documentation
+ Misc man page updates
OpenLDAP 2.1.12 Release
Build Environment
}
d2 = ch_malloc(sizeof(AttributeDescription) + dlen);
+ d2->ad_next = NULL;
d2->ad_type = desc.ad_type;
d2->ad_flags = desc.ad_flags;
d2->ad_cname.bv_len = desc.ad_type->sat_cname.bv_len;
rc = TXN_ABORT( ltid );
ltid = NULL;
op->o_private = NULL;
+ op->o_do_not_cache = opinfo.boi_acl_cache;
if( rc != 0 ) {
rc = LDAP_OTHER;
text = "internal error";
opinfo.boi_txn = ltid;
opinfo.boi_locker = locker;
opinfo.boi_err = 0;
+ opinfo.boi_acl_cache = op->o_do_not_cache;
op->o_private = &opinfo;
/*
rc = access_allowed( be, conn, op, p,
children, NULL, ACL_WRITE, NULL );
- switch( opinfo.boi_err ) {
- case DB_LOCK_DEADLOCK:
- case DB_LOCK_NOTGRANTED:
- goto retry;
- }
-
if ( ! rc ) {
+ switch( opinfo.boi_err ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ }
+
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"bdb_add: no write access to parent\n", 0, 0, 0 );
p = NULL;
- switch( opinfo.boi_err ) {
- case DB_LOCK_DEADLOCK:
- case DB_LOCK_NOTGRANTED:
- goto retry;
- }
-
if ( ! rc ) {
+ switch( opinfo.boi_err ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ }
+
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"bdb_add: no write access to parent\n", 0, 0, 0 );
rc = access_allowed( be, conn, op, e,
entry, NULL, ACL_WRITE, NULL );
- switch( opinfo.boi_err ) {
- case DB_LOCK_DEADLOCK:
- case DB_LOCK_NOTGRANTED:
- goto retry;
- }
-
if ( ! rc ) {
+ switch( opinfo.boi_err ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ }
+
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"bdb_add: no write access to entry\n", 0, 0, 0 );
} else {
dn2entry_retry:
/* can we find entry */
- rc = bdb_dn2entry_r( be, NULL, entry_ndn, &e, NULL, 0, locker, &lock );
+ rc = bdb_dn2entry_r( be, txn, entry_ndn, &e, NULL, 0, locker, &lock );
switch( rc ) {
case DB_NOTFOUND:
case 0:
break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
+ /* the txn must abort and retry */
+ if ( txn ) {
+ boi->boi_err = rc;
+ return LDAP_BUSY;
+ }
+ ldap_pvt_thread_yield();
goto dn2entry_retry;
default:
boi->boi_err = rc;
DB_TXN* boi_txn;
u_int32_t boi_err;
u_int32_t boi_locker;
+ int boi_acl_cache;
};
#define DB_OPEN(db, file, name, type, flags, mode) \
/*
* entry is deleted or not fully created yet
*/
- if ( state != CACHE_ENTRY_READY ) {
+ if ( state != CACHE_ENTRY_READY && state != CACHE_ENTRY_COMMITTED ) {
assert(state != CACHE_ENTRY_UNDEFINED);
/* free cache read lock */
/*
* entry is deleted or not fully created yet
*/
- if ( state != CACHE_ENTRY_READY ) {
+ if ( state != CACHE_ENTRY_READY && state != CACHE_ENTRY_COMMITTED ) {
assert(state != CACHE_ENTRY_UNDEFINED);
rc = TXN_ABORT( ltid );
ltid = NULL;
op->o_private = NULL;
+ op->o_do_not_cache = opinfo.boi_acl_cache;
if( rc != 0 ) {
rc = LDAP_OTHER;
text = "internal error";
opinfo.boi_txn = ltid;
opinfo.boi_locker = locker;
opinfo.boi_err = 0;
+ opinfo.boi_acl_cache = op->o_do_not_cache;
op->o_private = &opinfo;
if ( !be_issuffix( be, ndn ) ) {
bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
p = NULL;
- switch( opinfo.boi_err ) {
- case DB_LOCK_DEADLOCK:
- case DB_LOCK_NOTGRANTED:
- goto retry;
- }
-
if ( !rc ) {
+ switch( opinfo.boi_err ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ }
+
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"<=- bdb_delete: no write access to parent\n", 0, 0, 0 );
p = NULL;
- switch( opinfo.boi_err ) {
- case DB_LOCK_DEADLOCK:
- case DB_LOCK_NOTGRANTED:
- goto retry;
- }
-
if ( !rc ) {
+ switch( opinfo.boi_err ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ }
+
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"<=- bdb_delete: no access to parent\n", 0, 0, 0 );
rc = access_allowed( be, conn, op, e,
entry, NULL, ACL_WRITE, NULL );
- switch( opinfo.boi_err ) {
- case DB_LOCK_DEADLOCK:
- case DB_LOCK_NOTGRANTED:
- goto retry;
- }
-
if ( !rc ) {
+ switch( opinfo.boi_err ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ }
+
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"<=- bdb_delete: no write access to entry\n", 0, 0, 0 );
} else {
dn2entry_retry:
/* can we find group entry */
- rc = bdb_dn2entry_r( be, NULL, gr_ndn, &e, NULL, 0, locker, &lock );
+ rc = bdb_dn2entry_r( be, txn, gr_ndn, &e, NULL, 0, locker, &lock );
if( rc ) {
- if ( rc == DB_LOCK_DEADLOCK || rc == DB_LOCK_NOTGRANTED )
- goto dn2entry_retry;
boi->boi_err = rc;
+ if ( rc == DB_LOCK_DEADLOCK || rc == DB_LOCK_NOTGRANTED ) {
+ if ( txn ) {
+ /* must let owning txn abort, but our result
+ * is still inconclusive, so don't let it
+ * get cached.
+ */
+ op->o_do_not_cache = 1;
+ return( 1 );
+ }
+ ldap_pvt_thread_yield();
+ goto dn2entry_retry;
+ }
if ( free_lock_id ) {
LOCK_ID_FREE ( bdb->bi_dbenv, locker );
}
group_oc_name, group_at_name, 0 );
#endif
- if( value_find_ex( group_at, SLAP_MR_VALUE_NORMALIZED_MATCH,
- attr->a_vals, op_ndn ) != LDAP_SUCCESS ) {
+ if( value_find_ex( group_at,
+ SLAP_MR_VALUE_NORMALIZED_MATCH,
+ attr->a_vals, op_ndn ) != LDAP_SUCCESS )
+ {
#ifdef NEW_LOGGING
LDAP_LOG( BACK_BDB, DETAIL1,
"bdb_group: \"%s\" not in \"%s\": %s\n",
if( (void *) e->e_attrs != (void *) (e+1)) {
attrs_free( e->e_attrs );
}
+#ifdef SLAP_NVALUES
+ else {
+ /* nvals are not contiguous with the rest. oh well. */
+ Attribute *a;
+ for (a = e->e_attrs; a; a=a->a_next) {
+ if (a->a_nvals) {
+ ber_bvarray_free( a->a_nvals );
+ a->a_nvals = NULL;
+ }
+ }
+ }
+#endif
#ifndef BDB_HIER
/* See if the DNs were changed by modrdn */
for ( ap = save_attrs; ap != NULL; ap = ap->a_next ) {
if ( ap->a_flags & SLAP_ATTR_IXDEL ) {
rc = bdb_index_values( be, tid, ap->a_desc, ap->a_vals,
- e->e_id, SLAP_INDEX_DELETE_OP );
+ e->e_id, SLAP_INDEX_DELETE_OP );
if ( rc != LDAP_SUCCESS ) {
attrs_free( e->e_attrs );
e->e_attrs = save_attrs;
for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
if (ap->a_flags & SLAP_ATTR_IXADD) {
rc = bdb_index_values( be, tid, ap->a_desc, ap->a_vals,
- e->e_id, SLAP_INDEX_ADD_OP );
+ e->e_id, SLAP_INDEX_ADD_OP );
if ( rc != LDAP_SUCCESS ) {
attrs_free( e->e_attrs );
e->e_attrs = save_attrs;
rc = TXN_ABORT( ltid );
ltid = NULL;
op->o_private = NULL;
+ op->o_do_not_cache = opinfo.boi_acl_cache;
if( rc != 0 ) {
rc = LDAP_OTHER;
text = "internal error";
opinfo.boi_txn = ltid;
opinfo.boi_locker = locker;
opinfo.boi_err = 0;
+ opinfo.boi_acl_cache = op->o_do_not_cache;
op->o_private = &opinfo;
/* get entry */
"bdb_modify: modify failed (%d)\n",
rc, 0, 0 );
#endif
+ if ( (rc == LDAP_INSUFFICIENT_ACCESS) && opinfo.boi_err ) {
+ rc = opinfo.boi_err;
+ }
switch( rc ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
rc = TXN_ABORT( ltid );
ltid = NULL;
op->o_private = NULL;
+ op->o_do_not_cache = opinfo.boi_acl_cache;
if( rc != 0 ) {
rc = LDAP_OTHER;
text = "internal error";
opinfo.boi_txn = ltid;
opinfo.boi_locker = locker;
opinfo.boi_err = 0;
+ opinfo.boi_acl_cache = op->o_do_not_cache;
op->o_private = &opinfo;
/* get entry */
/* check write on old entry */
rc = access_allowed( be, conn, op, e, entry, NULL, ACL_WRITE, NULL );
- switch( opinfo.boi_err ) {
- case DB_LOCK_DEADLOCK:
- case DB_LOCK_NOTGRANTED:
- goto retry;
- }
-
if ( ! rc ) {
+ switch( opinfo.boi_err ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ }
+
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
"==>bdb_modrdn: no access to entry\n", 0, 0, 0 );
children, NULL, ACL_WRITE, NULL );
if ( ! rc ) {
+ switch( opinfo.boi_err ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ }
+
rc = LDAP_INSUFFICIENT_ACCESS;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
p = NULL;
if ( ! rc ) {
+ switch( opinfo.boi_err ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ }
+
rc = LDAP_INSUFFICIENT_ACCESS;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
NULL, ACL_WRITE, NULL );
if( ! rc ) {
+ switch( opinfo.boi_err ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ }
+
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"==>bdb_modrdn: no wr to newSup children\n", 0, 0, 0 );
np = NULL;
if ( ! rc ) {
+ switch( opinfo.boi_err ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ }
+
rc = LDAP_INSUFFICIENT_ACCESS;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
goto return_results;
}
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ERR,
- "bdb_modrdn: new ndn=%s does not exist\n", new_ndn.bv_val, 0, 0 );
-#else
- Debug( LDAP_DEBUG_TRACE,
- "bdb_modrdn: new ndn=%s does not exist\n",
- new_ndn.bv_val, 0, 0 );
-#endif
-
/* Get attribute type and attribute value of our new rdn, we will
* need to add that to our new entry
*/
&text, textbuf, textlen );
if( rc != LDAP_SUCCESS ) {
+ if ( ( rc == LDAP_INSUFFICIENT_ACCESS ) && opinfo.boi_err ) {
+ rc = opinfo.boi_err;
+ }
switch( rc ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
int rc;
- DB_TXN *ltid = NULL;
- struct bdb_op_info opinfo;
assert( e );
assert( hasSubordinates );
- if( 0 ) {
-retry: /* transaction retry */
-#if 0
- if( e != NULL ) {
- bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
- }
-#endif
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, DETAIL1,
- "=> bdb_hasSubordinates: retrying...\n", 0, 0, 0 );
-#else
- Debug( LDAP_DEBUG_TRACE, "==> bdb_hasSubordinates: retrying...\n",
- 0, 0, 0 );
-#endif
- rc = TXN_ABORT( ltid );
- ltid = NULL;
- op->o_private = NULL;
- if( rc != 0 ) {
- rc = LDAP_OTHER;
- goto return_results;
- }
- ldap_pvt_thread_yield();
- }
-
- /* begin transaction */
- rc = TXN_BEGIN( bdb->bi_dbenv, NULL, <id, bdb->bi_db_opflags );
- if ( rc != 0 ) {
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ERR,
- "=> bdb_hasSubordinates: txn_begin failed: %s (%d)\n",
- db_strerror(rc), rc, 0 );
-#else
- Debug( LDAP_DEBUG_TRACE,
- "bdb_hasSubordinates: txn_begin failed: %s (%d)\n",
- db_strerror( rc ), rc, 0 );
-#endif
- rc = LDAP_OTHER;
- return rc;
- }
-
- opinfo.boi_bdb = be;
- opinfo.boi_txn = ltid;
- opinfo.boi_locker = TXN_ID ( ltid );
- opinfo.boi_err = 0;
- op->o_private = &opinfo;
-
- rc = bdb_dn2id_children( be, ltid, &e->e_nname, 0 );
+retry:
+ rc = bdb_dn2id_children( be, NULL, &e->e_nname, 0 );
switch( rc ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
+ ldap_pvt_thread_yield();
goto retry;
case 0:
rc = LDAP_OTHER;
}
-return_results:
- if ( rc == LDAP_SUCCESS && bdb->bi_txn_cp ) {
- ldap_pvt_thread_yield();
- TXN_CHECKPOINT( bdb->bi_dbenv,
- bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
- }
-
- if ( ltid != NULL ) {
- TXN_ABORT( ltid );
- op->o_private = NULL;
- }
-
return rc;
}
rc = TXN_ABORT( ltid );
ltid = NULL;
op->o_private = NULL;
+ op->o_do_not_cache = opinfo.boi_acl_cache;
if( rc != 0 ) {
rc = LDAP_OTHER;
*text = "internal error";
opinfo.boi_txn = ltid;
opinfo.boi_locker = locker;
opinfo.boi_err = 0;
+ opinfo.boi_acl_cache = op->o_do_not_cache;
op->o_private = &opinfo;
/* get entry */
rc = bdb_modify_internal( be, conn, op, ltid,
&ml, e, text, textbuf, textlen );
+ if ( (rc == LDAP_INSUFFICIENT_ACCESS) && opinfo.boi_err ) {
+ rc = opinfo.boi_err;
+ }
switch(rc) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
u_int32_t locker = 0;
DB_LOCK lock;
- struct bdb_op_info opinfo;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ENTRY, "bdb_back_search\n", 0, 0, 0 );
return rc;
}
- opinfo.boi_bdb = be;
- opinfo.boi_txn = NULL;
- opinfo.boi_locker = locker;
- opinfo.boi_err = 0;
- op->o_private = &opinfo;
-
if ( nbase->bv_len == 0 ) {
/* DIT root special case */
e = (Entry *) &slap_entry_root;
} else {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
- "bdb_search: %ld does match filter\n", (long) id, 0, 0);
+ "bdb_search: %ld does not match filter\n", (long) id, 0, 0);
#else
Debug( LDAP_DEBUG_TRACE,
- "bdb_search: %ld does match filter\n",
+ "bdb_search: %ld does not match filter\n",
(long) id, 0, 0 );
#endif
}
static DBC *cursor = NULL;
static DBT key, data;
+typedef struct dn_id {
+ ID id;
+ struct berval dn;
+} dn_id;
+
+#define HOLE_SIZE 4096
+dn_id hbuf[HOLE_SIZE], *holes = hbuf;
+unsigned nhmax = HOLE_SIZE;
+unsigned nholes;
+
int bdb_tool_entry_open(
BackendDB *be, int mode )
{
cursor = NULL;
}
+ if( nholes ) {
+ unsigned i;
+ fprintf( stderr, "Error, entries missing!\n");
+ for (i=0; i<nholes; i++) {
+ fprintf(stderr, " entry %d: %s\n",
+ holes[i].id, holes[i].dn.bv_val, 0);
+ }
+ return -1;
+ }
+
return 0;
}
BackendDB *be,
DB_TXN *tid,
Entry *e,
- struct berval *text )
+ struct berval *text,
+ int hole )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
struct berval dn = e->e_nname;
} else {
dnParent( &dn, &pdn );
e->e_nname = pdn;
- rc = bdb_tool_next_id( be, tid, e, text );
+ rc = bdb_tool_next_id( be, tid, e, text, 1 );
if ( rc ) {
return rc;
}
Debug( LDAP_DEBUG_ANY,
"=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
#endif
+ } else if ( hole ) {
+ if ( nholes == nhmax - 1 ) {
+ if ( holes == hbuf ) {
+ holes = malloc( nhmax * sizeof(ID) * 2 );
+ AC_MEMCPY( holes, hbuf, sizeof(hbuf) );
+ } else {
+ holes = realloc( holes, nhmax * sizeof(ID) * 2 );
+ }
+ nhmax *= 2;
+ }
+ ber_dupbv( &holes[nholes].dn, &dn );
+ holes[nholes++].id = e->e_id;
+ }
+ } else if ( !hole ) {
+ unsigned i;
+
+ for ( i=0; i<nholes; i++) {
+ if ( holes[i].id == e->e_id ) {
+ int j;
+ free(holes[i].dn.bv_val);
+ for (j=i;j<nholes;j++) holes[j] = holes[j+1];
+ holes[j].id = 0;
+ nholes--;
+ break;
+ } else if ( holes[i].id > e->e_id ) {
+ break;
+ }
}
}
return rc;
}
/* add dn2id indices */
- rc = bdb_tool_next_id( be, tid, e, text );
+ rc = bdb_tool_next_id( be, tid, e, text, 0 );
if( rc != 0 ) {
goto done;
}
e->e_id = NOID;
/* dn + attributes */
+ vals[0].bv_len = 0;
vals[1].bv_val = NULL;
next = s;
BerVarray values,
BerVarray *keysp )
{
- int i;
- unsigned casefold;
+ int i,j;
+ unsigned casefold,wasspace;
size_t slen, mlen;
BerVarray keys;
HASH_CONTEXT HASHcontext;
? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
for( i=0; values[i].bv_val != NULL; i++ ) {
- struct berval value;
+ struct berval value, nvalue;
UTF8bvnormalize( &values[i], &value, casefold );
+ /* collapse spaces (in place) */
+ nvalue.bv_len = 0;
+ nvalue.bv_val = value.bv_val;
+
+ wasspace=1;
+ for( j=0; j<value.bv_len; j++) {
+ if ( ASCII_SPACE( value.bv_val[j] )) {
+ if( wasspace++ == 0 ) {
+ nvalue.bv_val[nvalue.bv_len++] = value.bv_val[j];
+ }
+ } else {
+ wasspace = 0;
+ nvalue.bv_val[nvalue.bv_len++] = value.bv_val[j];
+ }
+ }
+
+ if( nvalue.bv_len == 0 ) {
+ nvalue.bv_val = " ";
+ nvalue.bv_len = sizeof(" ")-1;
+ } else {
+ if( wasspace ) --nvalue.bv_len;
+ nvalue.bv_val[nvalue.bv_len] = '\0';
+ }
+
HASH_Init( &HASHcontext );
if( prefix != NULL && prefix->bv_len > 0 ) {
HASH_Update( &HASHcontext,
HASH_Update( &HASHcontext,
mr->smr_oid, mlen );
HASH_Update( &HASHcontext,
- value.bv_val, value.bv_len );
+ nvalue.bv_val, nvalue.bv_len );
HASH_Final( HASHdigest, &HASHcontext );
free( value.bv_val );
-
ber_dupbv( &keys[i], &digest );
}
BerVarray values,
BerVarray *keysp )
{
- unsigned casefold;
- ber_len_t i, nkeys;
+ unsigned casefold, wasspace;
+ ber_len_t i, j, nkeys;
size_t slen, mlen;
BerVarray keys;
- BerVarray nvalues;
+ BerVarray tvalues, nvalues;
HASH_CONTEXT HASHcontext;
unsigned char HASHdigest[HASH_BYTES];
casefold = ( mr != caseExactSubstringsMatchingRule )
? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
+ tvalues = ch_malloc( sizeof( struct berval ) * (i+1) );
nvalues = ch_malloc( sizeof( struct berval ) * (i+1) );
+
for( i=0; values[i].bv_val != NULL; i++ ) {
- UTF8bvnormalize( &values[i], &nvalues[i], casefold );
+ UTF8bvnormalize( &values[i], &tvalues[i], casefold );
+
+ /* collapse spaces (in place) */
+ nvalues[i].bv_len = 0;
+ nvalues[i].bv_val = tvalues[i].bv_val;
+
+ wasspace=1;
+ for( j=0; j<tvalues[i].bv_len; j++) {
+ if ( ASCII_SPACE( tvalues[i].bv_val[j] )) {
+ if( wasspace++ == 0 ) {
+ nvalues[i].bv_val[nvalues[i].bv_len++] =
+ tvalues[i].bv_val[j];
+ }
+ } else {
+ wasspace = 0;
+ nvalues[i].bv_val[nvalues[i].bv_len++] = tvalues[i].bv_val[j];
+ }
+ }
+
+ if( nvalues[i].bv_len == 0 ) {
+ nvalues[i].bv_val = " ";
+ nvalues[i].bv_len = sizeof(" ")-1;
+ } else {
+ if( wasspace ) --nvalues[i].bv_len;
+ nvalues[i].bv_val[nvalues[i].bv_len] = '\0';
+ }
}
+
+ tvalues[i].bv_val = NULL;
nvalues[i].bv_val = NULL;
values = nvalues;
if( nkeys == 0 ) {
/* no keys to generate */
*keysp = NULL;
- ber_bvarray_free( nvalues );
+ ber_bvarray_free( tvalues );
+ ch_free( nvalues );
return LDAP_SUCCESS;
}
*keysp = NULL;
}
- ber_bvarray_free( nvalues );
+ ber_bvarray_free( tvalues );
+ ch_free( nvalues );
return LDAP_SUCCESS;
}
{ "monitorContext", "( 1.3.6.1.4.1.4203.666.1.10 "
"NAME 'monitorContext' "
"DESC 'monitor context' "
- "EQUALITY objectIdentifierMatch "
- "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
"SINGLE-VALUE NO-USER-MODIFICATION "
"USAGE dSAOperation )",
rootDseAttribute, SLAP_AT_HIDE,
# Sample access control policy:
# Root DSE: allow anyone to read it
+# Subschema (sub)entry DSE: allow anyone to read it
# Other DSEs:
# Allow self write access
# Allow authenticated users read access
# Allow anonymous users to authenticate
# Directives needed to implement policy:
# access to dn.base="" by * read
+# access to dn.base="cn=Subschema" by * read
# access to *
# by self write
# by users read
ch_free( buf );
- be->be_entry_close( be );
+ if( be->be_entry_close( be )) rc = EXIT_FAILURE;
if( be->be_sync ) {
be->be_sync( be );