OpenLDAP 2.2 Change Log
OpenLDAP 2.2.6 Engineering
+ Fixed slapd SASL callback handling
+ Fixed slapd backglue sizelimit bug
+ Fixed slapd numericStringMatch bug
Fixed numericStringsMatch mis-definition bug (ITS#2938)
+ Fixed libldap reference handling
+ Fixed libldap_r abandon msgid mutex bug
+ Fixed liblutil NS MTA MD5 passwd len bug
+ Fixed slapd pcache DB init bug
+ Updated slapd syncrepl support
+ Updated slapd connection deferred logging
+ Updated slapd filter logging
+ Updated slapd back-ldap
+ Added slapd limit groups
Build Environment
Fixed test021 portable echo bug (ITS#2933, ITS#2879)
+ Fixed EBCDIC conversion bugs
+ Documentation
+ Misc. man page updates
+ Contributed Software
+ Added slapd passwd modules
+ Updated libcldap++
OpenLDAP 2.2.5 Release
Fixed slapd filter bug (ITS#2901)
ol_minor=2
ol_patch=X
ol_api_inc=20204
-ol_api_lib=202:4:1
-ol_release_date="2004/01/22"
+ol_api_lib=202:4:2
+ol_release_date="2004/01/29"
#! /bin/sh
# $OpenLDAP$
-# from OpenLDAP: pkg/ldap/configure.in,v 1.478.2.11 2004/01/01 18:16:25 kurt Exp
+# from OpenLDAP: pkg/ldap/configure.in,v 1.478.2.12 2004/01/17 18:36:41 kurt Exp
# This work is part of OpenLDAP Software <http://www.openldap.org/>.
#
ol_with_sql_module=static
if test $ol_with_dyngroup = mod ; then
echo "configure: warning: building static dyngroup overlay" 1>&2
- ol_with_dyngroup = yes
+ ol_with_dyngroup=yes
fi
if test $ol_with_proxycache = mod ; then
echo "configure: warning: building static proxycache overlay" 1>&2
- ol_with_proxycache = yes
+ ol_with_proxycache=yes
fi
fi
ol_with_sql_module=static
if test $ol_with_dyngroup = mod ; then
AC_MSG_WARN([building static dyngroup overlay])
- ol_with_dyngroup = yes
+ ol_with_dyngroup=yes
fi
if test $ol_with_proxycache = mod ; then
AC_MSG_WARN([building static proxycache overlay])
- ol_with_proxycache = yes
+ ol_with_proxycache=yes
fi
fi
Examples are reported below.
.SH "Additional configuration syntax:"
.TP
-.B rewriteMap "<map name>" "<map type>" "[ <map attrs> ]"
+.B rewriteMap "<map type>" "<map name>" "[ <map attrs> ]"
Allows to define a map that transforms substring rewriting into
something else.
The map is referenced inside the substitution pattern of a rule.
.RS
.RS
.TP
-anonymous | users | [dn[.<style>]=]<pattern>
+anonymous | users | [dn[.<style>]=]<pattern> | group[/oc[/at]]=<pattern>
.RE
with
The term
.B anonymous
matches all unauthenticated clients.
-the term
+The term
.B users
matches all authenticated clients;
-otherwise a
-.B regex
+otherwise an
+.B exact
dn pattern is assumed unless otherwise specified by qualifying
the (optional) key string
.B dn
form of the
.B who
clause.
+The term
+.BR group ,
+with the optional objectClass
+.B oc
+and attributeType
+.B at
+fields, followed by
+.BR pattern ,
+sets the limits for any DN listed in the values of the
+.B at
+attribute (default
+.BR member )
+of the
+.B oc
+group objectClass (default
+.BR groupOfNames )
+whose DN exactly matches
+.BR pattern .
The currently supported limits are
.B size
the entries.
.TP
.BI \-r
-If the LDIF input represents a syncrepl provider replica,
-demote it to the syncrepl consumer replica after adding
-the entries.
+If the LDIF input represents a syncrepl provider, demote
+it to the syncrepl consumer replica after adding the entries.
.TP
.BI \-w
When used with either
# ifdef LDAP_SYSLOG
extern int ldap_syslog;
extern int ldap_syslog_level;
+
+# ifdef HAVE_EBCDIC
+# define syslog eb_syslog
+ extern void eb_syslog(int pri, const char *fmt, ...);
+# endif
+
# endif /* LDAP_SYSLOG */
/* this doesn't below as part of ldap.h */
fputs( buffer, stderr );
va_end( vl );
}
+
+#if defined(HAVE_EBCDIC) && defined(LDAP_SYSLOG)
+#undef syslog
+void eb_syslog( int pri, const char *fmt, ... )
+{
+ char buffer[4096];
+ va_list vl;
+
+ va_start( vl, fmt );
+ vsnprintf( buffer, sizeof(buffer), fmt, vl );
+ buffer[sizeof(buffer)-1] = '\0';
+
+ /* The syslog function appears to only work with pure EBCDIC */
+ __atoe(buffer);
+#pragma convlit(suspend)
+ syslog( pri, "%s", buffer );
+#pragma convlit(resume)
+ va_end( vl );
+}
+#endif
ld->ld_errno = LDAP_NO_MEMORY;
} else {
- LDAP_NEXT_MSGID(ld, i);
+ /*
+ * We already have the mutex in LDAP_R_COMPILE, so
+ * don't try to get it again.
+ * LDAP_NEXT_MSGID(ld, i);
+ */
+ i = ++(ld)->ld_msgid;
#ifdef LDAP_CONNECTIONLESS
if ( LDAP_IS_UDP(ld) ) {
err = ber_write( ber, ld->ld_options.ldo_peer,
* Various Cyrus SASL related stuff.
*/
+static const sasl_callback_t client_callbacks[] = {
+#ifdef SASL_CB_GETREALM
+ { SASL_CB_GETREALM, NULL, NULL },
+#endif
+ { SASL_CB_USER, NULL, NULL },
+ { SASL_CB_AUTHNAME, NULL, NULL },
+ { SASL_CB_PASS, NULL, NULL },
+ { SASL_CB_ECHOPROMPT, NULL, NULL },
+ { SASL_CB_NOECHOPROMPT, NULL, NULL },
+ { SASL_CB_LIST_END, NULL, NULL }
+};
+
int ldap_int_sasl_init( void )
{
/* XXX not threadsafe */
static int sasl_initialized = 0;
- static sasl_callback_t client_callbacks[] = {
-#ifdef SASL_CB_GETREALM
- { SASL_CB_GETREALM, NULL, NULL },
-#endif
- { SASL_CB_USER, NULL, NULL },
- { SASL_CB_AUTHNAME, NULL, NULL },
- { SASL_CB_PASS, NULL, NULL },
- { SASL_CB_ECHOPROMPT, NULL, NULL },
- { SASL_CB_NOECHOPROMPT, NULL, NULL },
- { SASL_CB_LIST_END, NULL, NULL }
- };
-
#ifdef HAVE_SASL_VERSION
/* stringify the version number, sasl.h doesn't do it for us */
#define VSTR0(maj, min, pat) #maj "." #min "." #pat
ldap_pvt_thread_mutex_init( &ldap_int_sasl_mutex );
#endif
- if ( sasl_client_init( client_callbacks ) == SASL_OK ) {
+ if ( sasl_client_init( NULL ) == SASL_OK ) {
sasl_initialized = 1;
return 0;
}
#if SASL_VERSION_MAJOR >= 2
rc = sasl_client_new( "ldap", host, NULL, NULL,
- NULL, 0, &ctx );
+ client_callbacks, 0, &ctx );
#else
- rc = sasl_client_new( "ldap", host, NULL,
+ rc = sasl_client_new( "ldap", host, client_callbacks,
SASL_SECURITY_LAYER, &ctx );
#endif
char **refarray = NULL;
LDAPConn *lc;
int rc, count, i, j, id;
+ int parent_was_reference;
LDAPreqinfo rinfo;
ld->ld_errno = LDAP_SUCCESS; /* optimistic */
goto done;
}
+ /* check if parent request was a search reference */
+ parent_was_reference = ( lr->lr_parent &&
+ lr->lr_parent->lr_res_msgtype == LDAP_RES_SEARCH_REFERENCE ) ?
+ 1 : 0;
+
/* find original request */
for ( origreq = lr;
origreq->lr_parent != NULL;
ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
rc = ldap_send_server_request( ld, ber, id,
- origreq, srv, NULL, &rinfo );
+ (sref && !parent_was_reference) ? origreq : lr,
+ srv, NULL, &rinfo );
#ifdef LDAP_R_COMPILE
ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
#endif /* SLAPD_LMHASH */
#ifdef SLAPD_NS_MTA_MD5
+#define NS_MTA_MD5_PASSLEN 64
static int chk_ns_mta_md5(
const struct berval *scheme,
const struct berval *passwd,
char buffer[LUTIL_MD5_BYTES*2];
int i;
- if( passwd->bv_len != LUTIL_MD5_BYTES*2 ) {
+ if( passwd->bv_len != NS_MTA_MD5_PASSLEN ) {
return 1;
}
#include "back-bdb.h"
#include "lutil_hash.h"
+#ifdef BDB_INDEX_USE_HASH
/* Pass-thru hash function. Since the indexer is already giving us hash
* values as keys, we don't need BDB to re-hash them.
*/
}
return ret;
}
+#define BDB_INDEXTYPE DB_HASH
+#else
+#define BDB_INDEXTYPE DB_BTREE
+#endif
int
bdb_db_cache(
}
rc = db->bdi_db->set_pagesize( db->bdi_db, BDB_PAGESIZE );
+#ifdef BDB_INDEX_USE_HASH
rc = db->bdi_db->set_h_hash( db->bdi_db, bdb_db_hash );
+#endif
rc = db->bdi_db->set_flags( db->bdi_db, DB_DUP | DB_DUPSORT );
rc = db->bdi_db->set_dup_compare( db->bdi_db, bdb_bt_compare );
#endif
rc = DB_OPEN( db->bdi_db,
file, NULL /* name */,
- DB_HASH, bdb->bi_db_opflags | DB_CREATE | DB_THREAD,
+ BDB_INDEXTYPE, bdb->bi_db_opflags | DB_CREATE | DB_THREAD,
bdb->bi_dbenv_mode );
ch_free( file );
LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
int num_ctrls = 0;
+ int parent_is_glue = 0;
+ int parent_is_leaf = 0;
+
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ARGS, "==> bdb_delete: %s\n", op->o_req_dn.bv_val, 0, 0 );
#else
rs->sr_text = "internal error";
goto return_results;
}
+ parent_is_glue = 0;
+ parent_is_leaf = 0;
ldap_pvt_thread_yield();
bdb_trans_backoff( ++num_retries );
}
rs->sr_err = LDAP_OTHER;
goto return_results;
}
+
+ bdb_cache_find_id( op, lt2, eip->bei_id, &eip, 0, locker, &plock );
+ if ( eip ) p = eip->bei_e;
+ if ( pdn.bv_len != 0 ) {
+ parent_is_glue = is_entry_glue(p);
+ rs->sr_err = bdb_cache_children( op, lt2, p );
+ if ( rs->sr_err != DB_NOTFOUND ) {
+ switch( rs->sr_err ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ case 0:
+ break;
+ default:
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, ERR,
+ "<=- bdb_delete: has_children failed %s (%d)\n",
+ db_strerror(rs->sr_err), rs->sr_err, 0 );
+#else
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- bdb_delete: has_children failed: %s (%d)\n",
+ db_strerror(rs->sr_err), rs->sr_err, 0 );
+#endif
+ rs->sr_err = LDAP_OTHER;
+ rs->sr_text = "internal error";
+ goto return_results;
+ }
+ parent_is_leaf = 1;
+ }
+ bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
+ p = NULL;
+ }
+
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "txn_commit(2) failed";
bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
}
+ if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) {
+ op->o_delete_glue_parent = 1;
+ }
+
done:
/* free entry */
if( e != NULL ) {
Modifications *ml;
Attribute *save_attrs;
Attribute *ap;
+ int glue_attr_delete = 0;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ENTRY, "bdb_modify_internal: 0x%08lx: %s\n",
save_attrs = e->e_attrs;
e->e_attrs = attrs_dup( e->e_attrs );
+ for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
+ mod = &ml->sml_mod;
+ switch( mod->sm_op ) {
+ case LDAP_MOD_ADD:
+ case LDAP_MOD_REPLACE:
+ if ( mod->sm_desc == slap_schema.si_ad_structuralObjectClass ) {
+ /* sc modify is internally allowed only to make an entry a glue */
+ glue_attr_delete = 1;
+ }
+ }
+ if ( glue_attr_delete )
+ break;
+ }
+
+ if ( glue_attr_delete ) {
+ Attribute **app = &e->e_attrs;
+ while ( *app != NULL ) {
+ if ( !is_at_operational( (*app)->a_desc->ad_type )) {
+ Attribute *save = *app;
+ *app = (*app)->a_next;
+ attr_free( save );
+ continue;
+ }
+ app = &(*app)->a_next;
+ }
+ }
+
for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
mod = &ml->sml_mod;
break;
case LDAP_MOD_DELETE:
+ if ( glue_attr_delete )
+ break;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"bdb_modify_internal: delete\n", 0, 0, 0 );
e->e_ocflags = 0;
}
+ if ( glue_attr_delete ) {
+ e->e_ocflags = 0;
+ }
+
/* check if modified attribute was indexed
* but not in case of NOOP... */
err = bdb_index_is_indexed( op->o_bd, mod->sm_desc );
Entry *ctxcsn_e;
int ctxcsn_added = 0;
+ int parent_is_glue = 0;
+ int parent_is_leaf = 0;
+
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ENTRY, "==>bdb_modrdn(%s,%s,%s)\n",
op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val,
rs->sr_text = "internal error";
goto return_results;
}
+ parent_is_glue = 0;
+ parent_is_leaf = 0;
ldap_pvt_thread_yield();
bdb_trans_backoff( ++num_retries );
}
rs->sr_text = "entry update failed";
goto return_results;
}
+
+ bdb_cache_find_id( op, lt2, eip->bei_id, &eip, 0, locker, &plock );
+ if ( eip ) p = eip->bei_e;
+ if ( p_ndn.bv_len != 0 ) {
+ parent_is_glue = is_entry_glue(p);
+ rs->sr_err = bdb_cache_children( op, lt2, p );
+ if ( rs->sr_err != DB_NOTFOUND ) {
+ switch( rs->sr_err ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ case 0:
+ break;
+ default:
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, ERR,
+ "<=- bdb_modrdn: has_children failed %s (%d)\n",
+ db_strerror(rs->sr_err), rs->sr_err, 0 );
+#else
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- bdb_modrdn: has_children failed: %s (%d)\n",
+ db_strerror(rs->sr_err), rs->sr_err, 0 );
+#endif
+ rs->sr_err = LDAP_OTHER;
+ rs->sr_text = "internal error";
+ goto return_results;
+ }
+ parent_is_leaf = 1;
+ }
+ bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
+ p = NULL;
+ }
+
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "txn_commit(2) failed";
TXN_CHECKPOINT( bdb->bi_dbenv,
bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
}
+
+ if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) {
+ op->o_delete_glue_parent = 1;
+ }
done:
if( new_dn.bv_val != NULL ) free( new_dn.bv_val );
if ( be_isroot( op->o_bd, &sop->o_ndn ) ) {
isroot = 1;
} else {
- ( void ) get_limits( op->o_bd, &sop->o_ndn, &limit );
+ ( void ) get_limits( op, &sop->o_ndn, &limit );
}
/* The time/size limits come first because they require very little
0, 0, 0 );
#endif
- rs->sr_err = LDAP_SUCCESS;
- rs->sr_entry = NULL;
- send_ldap_result( sop, rs );
- goto done;
+ goto nochange;
}
/* if not root and candidates exceed to-be-checked entries, abort */
struct berval mdn = { 0, NULL };
ber_int_t msgid;
dncookie dc;
+ int isupdate;
#ifdef LDAP_BACK_PROXY_AUTHZ
LDAPControl **ctrls = NULL;
int rc = LDAP_SUCCESS;
#ifdef ENABLE_REWRITE
dc.ctx = "addDnAttr";
#endif
+
+ isupdate = be_isupdate( op->o_bd, &op->o_ndn );
for (i=0, a=op->oq_add.rs_e->e_attrs; a; a=a->a_next) {
- if ( a->a_desc->ad_type->sat_no_user_mod ) {
+ if ( !isupdate && a->a_desc->ad_type->sat_no_user_mod ) {
continue;
}
struct berval mdn = { 0, NULL };
ber_int_t msgid;
dncookie dc;
+ int isupdate;
#ifdef LDAP_BACK_PROXY_AUTHZ
LDAPControl **ctrls = NULL;
#endif /* LDAP_BACK_PROXY_AUTHZ */
#ifdef ENABLE_REWRITE
dc.ctx = "modifyAttrDN";
#endif
+
+ isupdate = be_isupdate( op->o_bd, &op->o_ndn );
for (i=0, ml=op->oq_modify.rs_modlist; ml; ml=ml->sml_next) {
int is_oc = 0;
- if ( ml->sml_desc->ad_type->sat_no_user_mod ) {
+ if ( !isupdate && ml->sml_desc->ad_type->sat_no_user_mod ) {
continue;
}
if ( be_isroot( op->o_bd, &op->o_ndn ) ) {
isroot = 1;
} else {
- ( void ) get_limits( op->o_bd, &op->o_ndn, &limit );
+ ( void ) get_limits( op, &op->o_ndn, &limit );
}
/* if no time limit requested, rely on remote server limits */
} else if (rc == LDAP_RES_SEARCH_ENTRY) {
Entry ent = {0};
struct berval bdn;
+ int abort = 0;
e = ldap_first_entry(lc->ld,res);
- if ( ldap_build_entry(op, e, &ent, &bdn,
- LDAP_BUILD_ENTRY_PRIVATE) == LDAP_SUCCESS ) {
+ if ( ( rc = ldap_build_entry(op, e, &ent, &bdn,
+ LDAP_BUILD_ENTRY_PRIVATE)) == LDAP_SUCCESS ) {
rs->sr_entry = &ent;
rs->sr_attrs = op->oq_search.rs_attrs;
- send_search_entry( op, rs );
+ abort = send_search_entry( op, rs );
while (ent.e_attrs) {
Attribute *a;
BerVarray v;
free( ent.e_ndn );
}
ldap_msgfree(res);
+ if ( abort ) {
+ ldap_abandon(lc->ld, msgid);
+ goto finish;
+ }
} else if ( rc == LDAP_RES_SEARCH_REFERENCE ) {
char **references = NULL;
{
char *version;
+#ifdef HAVE_EBCDIC
+ char v2[1024];
+#endif
int major, minor, patch;
version = db_version( &major, &minor, &patch );
+#ifdef HAVE_EBCDIC
+ strcpy( v2, version );
+ __etoa( v2 );
+ version = v2;
+#endif
if( major != DB_VERSION_MAJOR ||
minor < DB_VERSION_MINOR )
*/
isroot = 1;
} else {
- ( void ) get_limits( op->o_bd, &op->o_ndn, &limit );
+ ( void ) get_limits( op, &op->o_ndn, &limit );
}
/* if candidates exceed to-be-checked entries, abort */
if ( be_isroot( op->o_bd, &op->o_ndn ) ) {
isroot = 1;
} else {
- ( void ) get_limits( op->o_bd, &op->o_ndn, &limit );
+ ( void ) get_limits( op, &op->o_ndn, &limit );
}
/* if no time limit requested, rely on remote server limits */
insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (2,1,'telephoneNumber','phones.phone','persons,phones','phones.pers_id=persons.id','select add_phone(?,?)','select delete_phone(?,?)',3,0);
insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (3,1,'givenName','persons.name','persons',NULL,'update persons set name=? where id=?',NULL,3,0);
-insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (6,1,'sn','persons.surname','persons',NULL,'update persons set surname=? where id=?',NULL,3,0);
+insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (4,1,'sn','persons.surname','persons',NULL,'update persons set surname=? where id=?',NULL,3,0);
-insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (4,2,'description','documents.abstract','documents',NULL,NULL,NULL,3,0);
+insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (5,2,'description','documents.abstract','documents',NULL,NULL,NULL,3,0);
-insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (5,2,'documentTitle','documents.title','documents',NULL,NULL,NULL,3,0);
+insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (6,2,'documentTitle','documents.title','documents',NULL,NULL,NULL,3,0);
-insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (6,2,'documentAuthor','documentAuthor.dn','ldap_entries AS documentAuthor,documents,authors_docs,persons','documentAuthor.keyval=persons.id AND documentAuthor.oc_map_id=1 AND authors_docs.doc_id=documents.id AND authors_docs.pers_id=persons.id',NULL,NULL,3,0);
+insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (7,2,'documentAuthor','documentAuthor.dn','ldap_entries AS documentAuthor,documents,authors_docs,persons','documentAuthor.keyval=persons.id AND documentAuthor.oc_map_id=1 AND authors_docs.doc_id=documents.id AND authors_docs.pers_id=persons.id',NULL,NULL,3,0);
-insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (7,3,'o','institutes.name','institutes',NULL,NULL,NULL,3,0);
+insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (8,3,'o','institutes.name','institutes',NULL,NULL,NULL,3,0);
-insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (8,1,'documentIdentifier','documentIdentifier.dn','ldap_entries AS documentIdentifier,documents,authors_docs,persons','documentIdentifier.keyval=documents.id AND documentIdentifier.oc_map_id=2 AND authors_docs.doc_id=documents.id AND authors_docs.pers_id=persons.id',NULL,NULL,3,0);
+insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (9,1,'documentIdentifier','documentIdentifier.dn','ldap_entries AS documentIdentifier,documents,authors_docs,persons','documentIdentifier.keyval=documents.id AND documentIdentifier.oc_map_id=2 AND authors_docs.doc_id=documents.id AND authors_docs.pers_id=persons.id',NULL,NULL,3,0);
-- entries mapping: each entry must appear in this table, with a unique DN rooted at the database naming context
if ( be_isroot( op->o_bd, &op->o_ndn ) ) {
isroot = 1;
} else {
- ( void ) get_limits( op->o_bd, &op->o_ndn, &limit );
+ ( void ) get_limits( op, &op->o_ndn, &limit );
}
/* The time/size limits come first because they require very little
switch(rs->sr_type) {
case REP_SEARCH:
if ( gs->slimit && rs->sr_nentries >= gs->slimit ) {
- gs->err = LDAP_SIZELIMIT_EXCEEDED;
+ rs->sr_err = gs->err = LDAP_SIZELIMIT_EXCEEDED;
return -1;
}
/* fallthru */
static int
connection_input(
- Connection *conn
-)
+ Connection *conn )
{
Operation *op;
ber_tag_t tag;
Sockaddr peeraddr;
char *cdn = NULL;
#endif
+ char *defer = NULL;
if ( conn->c_currentber == NULL &&
( conn->c_currentber = ber_alloc()) == NULL )
* Bind, or if it's closing. Also, don't let any single conn
* use up all the available threads, and don't execute if we're
* currently blocked on output. And don't execute if there are
- * already pending ops, let them go first.
- *
- * But always allow Abandon through; it won't cost much.
+ * already pending ops, let them go first. Abandon operations
+ * get exceptions to some, but not all, cases.
*/
- if ( tag != LDAP_REQ_ABANDON && (conn->c_conn_state == SLAP_C_BINDING
- || conn->c_conn_state == SLAP_C_CLOSING
- || conn->c_n_ops_executing >= connection_pool_max/2
- || conn->c_n_ops_pending
- || conn->c_writewaiter))
- {
+ if (tag != LDAP_REQ_ABANDON && conn->c_conn_state == SLAP_C_CLOSING) {
+ defer = "closing";
+ } else if (tag != LDAP_REQ_ABANDON && conn->c_writewaiter) {
+ defer = "awaiting write";
+ } else if (conn->c_n_ops_executing >= connection_pool_max/2) {
+ defer = "too many executing";
+ } else if (conn->c_conn_state == SLAP_C_BINDING ) {
+ defer = "binding";
+ } else if (tag != LDAP_REQ_ABANDON && conn->c_n_ops_pending) {
+ defer = "pending operations";
+ }
+
+ if( defer ) {
int max = conn->c_dn.bv_len
? slap_conn_max_pending_auth
: slap_conn_max_pending;
#ifdef NEW_LOGGING
LDAP_LOG( CONNECTION, INFO,
- "connection_input: conn %lu deferring operation\n",
- conn->c_connid, 0, 0 );
+ "connection_input: conn %lu deferring operation: %s\n",
+ conn->c_connid, defer, 0 );
#else
Debug( LDAP_DEBUG_ANY,
- "connection_input: conn=%lu deferring operation\n",
- conn->c_connid, 0, 0 );
+ "connection_input: conn=%lu deferring operation: %s\n",
+ conn->c_connid, defer, 0 );
#endif
conn->c_n_ops_pending++;
LDAP_STAILQ_INSERT_TAIL( &conn->c_pending_ops, op, o_next );
)
{
struct berval dn = { 0, NULL };
+ struct berval pdn = { 0, NULL };
+ struct berval org_req_dn = { 0, NULL };
+ struct berval org_req_ndn = { 0, NULL };
+ struct berval org_dn = { 0, NULL };
+ struct berval org_ndn = { 0, NULL };
+ int org_managedsait;
int manageDSAit;
#ifdef NEW_LOGGING
cb.sc_next = op->o_callback;
op->o_callback = &cb;
}
+
op->o_bd->be_delete( op, rs );
+
+ org_req_dn = op->o_req_dn;
+ org_req_ndn = op->o_req_ndn;
+ org_dn = op->o_dn;
+ org_ndn = op->o_ndn;
+ org_managedsait = get_manageDSAit( op );
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_ndn = op->o_bd->be_rootndn;
+ op->o_managedsait = 1;
+
+ while ( rs->sr_err == LDAP_SUCCESS &&
+ op->o_delete_glue_parent ) {
+ op->o_delete_glue_parent = 0;
+ if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) {
+ slap_callback cb = { NULL };
+ cb.sc_response = slap_null_cb;
+ dnParent( &op->o_req_ndn, &pdn );
+ op->o_req_dn = pdn;
+ op->o_req_ndn = pdn;
+ op->o_callback = &cb;
+ op->o_bd->be_delete( op, rs );
+ } else {
+ break;
+ }
+ }
+
+ op->o_managedsait = org_managedsait;
+ op->o_dn = org_dn;
+ op->o_ndn = org_ndn;
+ op->o_req_dn = org_req_dn;
+ op->o_req_ndn = org_req_ndn;
+ op->o_delete_glue_parent = 0;
+
#ifndef SLAPD_MULTIMASTER
} else {
BerVarray defref = NULL;
if( err != LDAP_SUCCESS ) {
/* unrecognized attribute description or other error */
+#ifdef NEW_LOGGING
+ LDAP_LOG( FILTER, ERR,
+ "get_filter: conn %d unknown attribute "
+ "type=%s (%d)\n",
+ op->o_connid, type.bv_val, err );
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "get_filter: conn %d unknown attribute "
+ "type=%s (%d)\n",
+ op->o_connid, type.bv_val, err );
+#endif
+
f.f_choice = SLAPD_FILTER_COMPUTED;
f.f_result = LDAP_COMPARE_FALSE;
err = LDAP_SUCCESS;
rc = slap_bv2ad( &desc, &ssa.sa_desc, text );
if( rc != LDAP_SUCCESS ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG( FILTER, ERR,
+ "get_ssa: conn %d d unknown attribute type=%s (%d)\n",
+ op->o_connid, desc.bv_val, rc );
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "get_ssa: conn %d unknown attribute type=%s (%d)\n",
+ op->o_connid, desc.bv_val, rc );
+#endif
+
/* skip over the rest of this filter */
for ( tag = ber_first_element( ber, &len, &last );
tag != LBER_DEFAULT;
if( err != LDAP_SUCCESS ) {
/* unrecognized attribute description or other error */
+#ifdef NEW_LOGGING
+ LDAP_LOG( FILTER, ERR,
+ "get_simple_vrFilter: conn %d unknown "
+ "attribute type=%s (%d)\n",
+ op->o_connid, type.bv_val, err );
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "get_simple_vrFilter: conn %d unknown "
+ "attribute type=%s (%d)\n",
+ op->o_connid, type.bv_val, err );
+#endif
+
vrf.vrf_choice = SLAPD_FILTER_COMPUTED;
vrf.vrf_result = LDAP_COMPARE_FALSE;
err = LDAP_SUCCESS;
int
get_limits(
- Backend *be,
+ Operation *op,
struct berval *ndn,
struct slap_limits_set **limit
)
{
struct slap_limits **lm;
- assert( be );
+ assert( op );
assert( limit );
/*
* default values
*/
- *limit = &be->be_def_limit;
+ *limit = &op->o_bd->be_def_limit;
- if ( be->be_limits == NULL ) {
+ if ( op->o_bd->be_limits == NULL ) {
return( 0 );
}
- for ( lm = be->be_limits; lm[0] != NULL; lm++ ) {
- switch ( lm[0]->lm_type ) {
+ for ( lm = op->o_bd->be_limits; lm[0] != NULL; lm++ ) {
+ unsigned style = lm[0]->lm_flags & SLAP_LIMITS_MASK;
+ unsigned type = lm[0]->lm_flags & SLAP_LIMITS_TYPE_MASK;
+
+ switch ( style ) {
case SLAP_LIMITS_EXACT:
if ( ndn->bv_len == 0 ) {
break;
}
- if ( dn_match( &lm[0]->lm_dn_pat, ndn ) ) {
+
+ if ( type == SLAP_LIMITS_TYPE_GROUP ) {
+ int rc;
+
+ rc = backend_group( op, NULL,
+ &lm[0]->lm_pat, ndn,
+ lm[0]->lm_group_oc,
+ lm[0]->lm_group_ad );
+ if ( rc == 0 ) {
+ *limit = &lm[0]->lm_limits;
+ return( 0 );
+ }
+ }
+
+ if ( dn_match( &lm[0]->lm_pat, ndn ) ) {
*limit = &lm[0]->lm_limits;
return( 0 );
}
}
/* ndn shorter than dn_pat */
- if ( ndn->bv_len < lm[0]->lm_dn_pat.bv_len ) {
+ if ( ndn->bv_len < lm[0]->lm_pat.bv_len ) {
break;
}
- d = ndn->bv_len - lm[0]->lm_dn_pat.bv_len;
+ d = ndn->bv_len - lm[0]->lm_pat.bv_len;
/* allow exact match for SUBTREE only */
if ( d == 0 ) {
- if ( lm[0]->lm_type != SLAP_LIMITS_SUBTREE ) {
+ if ( style != SLAP_LIMITS_SUBTREE ) {
break;
}
} else {
}
/* in case of (sub)match ... */
- if ( lm[0]->lm_dn_pat.bv_len == ( ndn->bv_len - d )
- && strcmp( lm[0]->lm_dn_pat.bv_val, &ndn->bv_val[d] ) == 0 ) {
+ if ( lm[0]->lm_pat.bv_len == ( ndn->bv_len - d )
+ && strcmp( lm[0]->lm_pat.bv_val,
+ &ndn->bv_val[d] ) == 0 )
+ {
/* check for exactly one rdn in case of ONE */
- if ( lm[0]->lm_type == SLAP_LIMITS_ONE ) {
+ if ( style == SLAP_LIMITS_ONE ) {
/*
* if ndn is more that one rdn
* below dn_pat, continue
*/
- if ( (size_t) dn_rdnlen( NULL, ndn ) != d - 1 ) {
+ if ( (size_t) dn_rdnlen( NULL, ndn )
+ != d - 1 )
+ {
break;
}
}
if ( ndn->bv_len == 0 ) {
break;
}
- if ( regexec( &lm[0]->lm_dn_regex, ndn->bv_val, 0, NULL, 0 )
- == 0 )
+ if ( regexec( &lm[0]->lm_regex, ndn->bv_val,
+ 0, NULL, 0 ) == 0 )
{
*limit = &lm[0]->lm_limits;
return( 0 );
static int
add_limits(
Backend *be,
- int type,
+ unsigned flags,
const char *pattern,
+ ObjectClass *group_oc,
+ AttributeDescription *group_ad,
struct slap_limits_set *limit
)
{
int i;
struct slap_limits *lm;
+ unsigned type, style;
assert( be );
assert( limit );
- switch ( type ) {
+ type = flags & SLAP_LIMITS_TYPE_MASK;
+ style = flags & SLAP_LIMITS_MASK;
+
+ switch ( style ) {
case SLAP_LIMITS_ANONYMOUS:
case SLAP_LIMITS_USERS:
case SLAP_LIMITS_ANY:
for ( i = 0; be->be_limits && be->be_limits[ i ]; i++ ) {
- if ( be->be_limits[ i ]->lm_type == type ) {
+ if ( be->be_limits[ i ]->lm_flags == style ) {
return( -1 );
}
}
lm = ( struct slap_limits * )ch_calloc( sizeof( struct slap_limits ), 1 );
- switch ( type ) {
+ switch ( style ) {
+ case SLAP_LIMITS_UNDEFINED:
+ style = SLAP_LIMITS_EXACT;
+ /* continue to next cases */
case SLAP_LIMITS_EXACT:
case SLAP_LIMITS_ONE:
case SLAP_LIMITS_SUBTREE:
case SLAP_LIMITS_CHILDREN:
- lm->lm_type = type;
+ lm->lm_flags = style | type;
{
int rc;
struct berval bv;
bv.bv_val = (char *) pattern;
bv.bv_len = strlen( pattern );
- rc = dnNormalize( 0, NULL, NULL, &bv, &lm->lm_dn_pat, NULL );
+ rc = dnNormalize( 0, NULL, NULL, &bv, &lm->lm_pat, NULL );
if ( rc != LDAP_SUCCESS ) {
ch_free( lm );
return( -1 );
break;
case SLAP_LIMITS_REGEX:
- case SLAP_LIMITS_UNDEFINED:
- lm->lm_type = SLAP_LIMITS_REGEX;
- ber_str2bv( pattern, 0, 1, &lm->lm_dn_pat );
- if ( regcomp( &lm->lm_dn_regex, lm->lm_dn_pat.bv_val,
+ lm->lm_flags = style | type;
+ ber_str2bv( pattern, 0, 1, &lm->lm_pat );
+ if ( regcomp( &lm->lm_regex, lm->lm_pat.bv_val,
REG_EXTENDED | REG_ICASE ) ) {
- free( lm->lm_dn_pat.bv_val );
+ free( lm->lm_pat.bv_val );
ch_free( lm );
return( -1 );
}
case SLAP_LIMITS_ANONYMOUS:
case SLAP_LIMITS_USERS:
case SLAP_LIMITS_ANY:
- lm->lm_type = type;
- lm->lm_dn_pat.bv_val = NULL;
- lm->lm_dn_pat.bv_len = 0;
+ lm->lm_flags = style | type;
+ lm->lm_pat.bv_val = NULL;
+ lm->lm_pat.bv_len = 0;
+ break;
+ }
+
+ switch ( type ) {
+ case SLAP_LIMITS_TYPE_GROUP:
+ assert( group_oc );
+ assert( group_ad );
+ lm->lm_group_oc = group_oc;
+ lm->lm_group_ad = group_ad;
break;
}
char **argv
)
{
- int type = SLAP_LIMITS_UNDEFINED;
- char *pattern;
- struct slap_limits_set limit;
- int i, rc = 0;
+ int flags = SLAP_LIMITS_UNDEFINED;
+ char *pattern;
+ struct slap_limits_set limit;
+ int i, rc = 0;
+ ObjectClass *group_oc = NULL;
+ AttributeDescription *group_ad = NULL;
assert( be );
pattern = argv[1];
if ( strcmp( pattern, "*" ) == 0) {
- type = SLAP_LIMITS_ANY;
+ flags = SLAP_LIMITS_ANY;
} else if ( strcasecmp( pattern, "anonymous" ) == 0 ) {
- type = SLAP_LIMITS_ANONYMOUS;
+ flags = SLAP_LIMITS_ANONYMOUS;
} else if ( strcasecmp( pattern, "users" ) == 0 ) {
- type = SLAP_LIMITS_USERS;
+ flags = SLAP_LIMITS_USERS;
- } else if ( strncasecmp( pattern, "dn", sizeof( "dn") - 1 ) == 0 ) {
- pattern += 2;
+ } else if ( strncasecmp( pattern, "dn", sizeof( "dn" ) - 1 ) == 0 ) {
+ pattern += sizeof( "dn" ) - 1;
if ( pattern[0] == '.' ) {
pattern++;
if ( strncasecmp( pattern, "exact", sizeof( "exact" ) - 1 ) == 0 ) {
- type = SLAP_LIMITS_EXACT;
- pattern += 5;
+ flags = SLAP_LIMITS_EXACT;
+ pattern += sizeof( "exact" ) - 1;
- } else if ( strncasecmp( pattern, "base", sizeof( "base " ) - 1 ) == 0 ) {
- type = SLAP_LIMITS_BASE;
- pattern += 4;
+ } else if ( strncasecmp( pattern, "base", sizeof( "base" ) - 1 ) == 0 ) {
+ flags = SLAP_LIMITS_BASE;
+ pattern += sizeof( "base" ) - 1;
} else if ( strncasecmp( pattern, "one", sizeof( "one" ) - 1 ) == 0 ) {
- type = SLAP_LIMITS_ONE;
- pattern += 3;
+ flags = SLAP_LIMITS_ONE;
+ pattern += sizeof( "one" ) - 1;
} else if ( strncasecmp( pattern, "subtree", sizeof( "subtree" ) - 1 ) == 0 ) {
- type = SLAP_LIMITS_SUBTREE;
- pattern += 7;
+ flags = SLAP_LIMITS_SUBTREE;
+ pattern += sizeof( "subtree" ) - 1;
} else if ( strncasecmp( pattern, "children", sizeof( "children" ) - 1 ) == 0 ) {
- type = SLAP_LIMITS_CHILDREN;
- pattern += 8;
+ flags = SLAP_LIMITS_CHILDREN;
+ pattern += sizeof( "children" ) - 1;
} else if ( strncasecmp( pattern, "regex", sizeof( "regex" ) - 1 ) == 0 ) {
- type = SLAP_LIMITS_REGEX;
- pattern += 5;
+ flags = SLAP_LIMITS_REGEX;
+ pattern += sizeof( "regex" ) - 1;
/*
* this could be deprecated in favour
* of the pattern = "anonymous" form
*/
} else if ( strncasecmp( pattern, "anonymous", sizeof( "anonymous" ) - 1 ) == 0 ) {
- type = SLAP_LIMITS_ANONYMOUS;
+ flags = SLAP_LIMITS_ANONYMOUS;
pattern = NULL;
}
}
/* pre-check the data */
- switch ( type ) {
+ switch ( flags ) {
case SLAP_LIMITS_ANONYMOUS:
case SLAP_LIMITS_USERS:
/* trim obvious cases */
if ( strcmp( pattern, "*" ) == 0 ) {
- type = SLAP_LIMITS_ANY;
+ flags = SLAP_LIMITS_ANY;
pattern = NULL;
- } else if ( ( type == SLAP_LIMITS_REGEX || type == SLAP_LIMITS_UNDEFINED )
+ } else if ( flags == SLAP_LIMITS_REGEX
&& strcmp( pattern, ".*" ) == 0 ) {
- type = SLAP_LIMITS_ANY;
+ flags = SLAP_LIMITS_ANY;
pattern = NULL;
}
}
+
+ } else if (strncasecmp( pattern, "group", sizeof( "group" ) - 1 ) == 0 ) {
+ pattern += sizeof( "group" ) - 1;
+
+ if ( pattern[0] == '/' ) {
+ struct berval oc, ad;
+
+ oc.bv_val = pattern + 1;
+
+ ad.bv_val = strchr(pattern, '/');
+ if ( ad.bv_val != NULL ) {
+ const char *text = NULL;
+ int rc;
+
+ oc.bv_len = ad.bv_val - oc.bv_val;
+
+ ad.bv_val++;
+ ad.bv_len = strlen( ad.bv_val );
+ rc = slap_bv2ad( &ad, &group_ad, &text );
+ if ( rc != LDAP_SUCCESS ) {
+ goto no_ad;
+ }
+
+ pattern = ad.bv_val + ad.bv_len;
+
+ } else {
+ oc.bv_len = strlen( oc.bv_val );
+
+ pattern = oc.bv_val + oc.bv_len;
+ }
+
+ group_oc = oc_bvfind( &oc );
+ if ( group_oc == NULL ) {
+ goto no_oc;
+ }
+ }
+
+ if ( group_oc == NULL ) {
+ group_oc = oc_find( SLAPD_GROUP_CLASS );
+ if ( group_oc == NULL ) {
+no_oc:;
+ return( -1 );
+ }
+ }
+
+ if ( group_ad == NULL ) {
+ const char *text = NULL;
+ int rc;
+
+ rc = slap_str2ad( SLAPD_GROUP_ATTR, &group_ad, &text );
+
+ if ( rc != LDAP_SUCCESS ) {
+no_ad:;
+ return( -1 );
+ }
+ }
+
+ flags = SLAP_LIMITS_TYPE_GROUP | SLAP_LIMITS_EXACT;
+
+ if ( pattern[0] != '=' ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG( CONFIG, CRIT,
+ "%s : line %d: missing '=' in "
+ "\"group[/objectClass[/attributeType]]"
+ "=<pattern>\" in "
+ "\"limits <pattern> <limits>\" line.\n",
+ fname, lineno, 0 );
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "%s : line %d: missing '=' in "
+ "\"group[/objectClass[/attributeType]]"
+ "=<pattern>\" in "
+ "\"limits <pattern> <limits>\" line.\n",
+ fname, lineno, 0 );
+#endif
+ return( -1 );
+ }
+
+ /* skip '=' (required) */
+ pattern++;
}
/* get the limits */
#ifdef NEW_LOGGING
LDAP_LOG( CONFIG, CRIT,
- "%s : line %d: unknown limit type \"%s\" in "
+ "%s : line %d: unknown limit values \"%s\" in "
"\"limits <pattern> <limits>\" line.\n",
fname, lineno, argv[i] );
#else
Debug( LDAP_DEBUG_ANY,
- "%s : line %d: unknown limit type \"%s\" in "
+ "%s : line %d: unknown limit values \"%s\" in "
"\"limits <pattern> <limits>\" line.\n",
fname, lineno, argv[i] );
#endif
limit.lms_s_hard = limit.lms_s_soft;
}
- rc = add_limits( be, type, pattern, &limit );
+ rc = add_limits( be, flags, pattern, group_oc, group_ad, &limit );
if ( rc ) {
#ifdef NEW_LOGGING
}
}
+ {
+ char *logName;
+#ifdef HAVE_EBCDIC
+ logName = ch_strdup( serverName );
+ __atoe( logName );
+#else
+ logName = serverName;
+#endif
+
#ifdef LOG_LOCAL4
- openlog( serverName, OPENLOG_OPTIONS, syslogUser );
+ openlog( logName, OPENLOG_OPTIONS, syslogUser );
#elif LOG_DEBUG
- openlog( serverName, OPENLOG_OPTIONS );
+ openlog( logName, OPENLOG_OPTIONS );
+#endif
+#ifdef HAVE_EBCDIC
+ free( logName );
#endif
+ }
#ifdef NEW_LOGGING
LDAP_LOG( SLAPD, INFO, "%s", Versionstr, 0, 0 );
ber_len_t length;
int manageDSAit;
+ struct berval pdn = { 0, NULL };
+ struct berval org_req_dn = { 0, NULL };
+ struct berval org_req_ndn = { 0, NULL };
+ struct berval org_dn = { 0, NULL };
+ struct berval org_ndn = { 0, NULL };
+ int org_managedsait;
+
#ifdef NEW_LOGGING
LDAP_LOG( OPERATION, ENTRY, "do_modrdn: begin\n", 0, 0, 0 );
#else
}
op->o_bd->be_modrdn( op, rs );
+ if ( op->o_bd->be_delete ) {
+ org_req_dn = op->o_req_dn;
+ org_req_ndn = op->o_req_ndn;
+ org_dn = op->o_dn;
+ org_ndn = op->o_ndn;
+ org_managedsait = get_manageDSAit( op );
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_ndn = op->o_bd->be_rootndn;
+ op->o_managedsait = 1;
+
+ while ( rs->sr_err == LDAP_SUCCESS &&
+ op->o_delete_glue_parent ) {
+ op->o_delete_glue_parent = 0;
+ if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) {
+ slap_callback cb = { NULL };
+ cb.sc_response = slap_null_cb;
+ dnParent( &op->o_req_ndn, &pdn );
+ op->o_req_dn = pdn;
+ op->o_req_ndn = pdn;
+ op->o_callback = &cb;
+ op->o_bd->be_delete( op, rs );
+ } else {
+ break;
+ }
+ }
+ op->o_managedsait = org_managedsait;
+ op->o_dn = org_dn;
+ op->o_ndn = org_ndn;
+ op->o_req_dn = org_req_dn;
+ op->o_req_ndn = org_req_ndn;
+ op->o_delete_glue_parent = 0;
+ }
+
#ifndef SLAPD_MULTIMASTER
} else {
BerVarray defref = NULL;
}
if ( cm->db.bd_info->bi_db_init( &cm->db ) ) return( 1 );
+ /* This type is in use, needs to be opened */
+ cm->db.bd_info->bi_nDB++;
+
cm->max_entries = atoi( argv[2] );
cm->numattrsets = atoi( argv[3] );
* limits.c
*/
LDAP_SLAPD_F (int) get_limits LDAP_P((
- Backend *be, struct berval *ndn,
+ Operation *op, struct berval *ndn,
struct slap_limits_set **limit ));
LDAP_SLAPD_F (int) parse_limits LDAP_P((
Backend *be, const char *fname, int lineno,
LDAP_SLAPD_F (void) init_syncrepl LDAP_P((syncinfo_t *));
LDAP_SLAPD_F (void*) do_syncrepl LDAP_P((void *, void *));
-LDAP_SLAPD_F (Entry*) syncrepl_message_to_entry LDAP_P((
+LDAP_SLAPD_F (int) syncrepl_message_to_entry LDAP_P((
syncinfo_t *, Operation *, LDAPMessage *,
- Modifications **, int ));
+ Modifications **, Entry **, int ));
LDAP_SLAPD_F (int) syncrepl_entry LDAP_P((
syncinfo_t *, Operation*, Entry*,
Modifications*,int, struct berval*,
rs->sr_type = REP_RESULT;
- assert( !LDAP_API_ERROR( rs->sr_err ) && ( rs->sr_err >= 0 ));
+ assert( !LDAP_API_ERROR( rs->sr_err ));
#ifdef NEW_LOGGING
LDAP_LOG( OPERATION, ENTRY,
};
struct slap_limits {
- int lm_type; /* type of pattern */
-#define SLAP_LIMITS_UNDEFINED 0x0000
-#define SLAP_LIMITS_EXACT 0x0001
+ unsigned lm_flags; /* type of pattern */
+#define SLAP_LIMITS_UNDEFINED 0x0000U
+#define SLAP_LIMITS_EXACT 0x0001U
#define SLAP_LIMITS_BASE SLAP_LIMITS_EXACT
-#define SLAP_LIMITS_ONE 0x0002
-#define SLAP_LIMITS_SUBTREE 0x0003
-#define SLAP_LIMITS_CHILDREN 0x0004
-#define SLAP_LIMITS_REGEX 0x0005
-#define SLAP_LIMITS_ANONYMOUS 0x0006
-#define SLAP_LIMITS_USERS 0x0007
-#define SLAP_LIMITS_ANY 0x0008
- regex_t lm_dn_regex; /* regex data for REGEX */
+#define SLAP_LIMITS_ONE 0x0002U
+#define SLAP_LIMITS_SUBTREE 0x0003U
+#define SLAP_LIMITS_CHILDREN 0x0004U
+#define SLAP_LIMITS_REGEX 0x0005U
+#define SLAP_LIMITS_ANONYMOUS 0x0006U
+#define SLAP_LIMITS_USERS 0x0007U
+#define SLAP_LIMITS_ANY 0x0008U
+#define SLAP_LIMITS_MASK 0x000FU
+
+#define SLAP_LIMITS_TYPE_DN 0x0000U
+#define SLAP_LIMITS_TYPE_GROUP 0x0010U
+#define SLAP_LIMITS_TYPE_MASK 0x00F0U
+
+ regex_t lm_regex; /* regex data for REGEX */
/*
* normalized DN for EXACT, BASE, ONE, SUBTREE, CHILDREN;
* pattern for REGEX; NULL for ANONYMOUS, USERS
*/
- struct berval lm_dn_pat;
+ struct berval lm_pat;
+
+ /* if lm_flags & SLAP_LIMITS_TYPE_MASK == SLAP_LIMITS_GROUP,
+ * lm_group_oc is objectClass and lm_group_at is attributeType
+ * of member in oc for match; then lm_flags & SLAP_LIMITS_MASK
+ * can only be SLAP_LIMITS_EXACT */
+ ObjectClass *lm_group_oc;
+ AttributeDescription *lm_group_ad;
struct slap_limits_set lm_limits;
};
ValuesReturnFilter *o_vrFilter; /* ValuesReturnFilter */
int o_nocaching;
+ int o_delete_glue_parent;
#ifdef LDAP_SLAPI
void *o_pb; /* NS-SLAPI plugin */
int rc, err, i;
ber_len_t len;
- int rc_efree;
+ int rc_efree = 1;
struct berval *psub;
Modifications *modlist = NULL;
syncCookie.octet_str[0].bv_val )
slap_parse_sync_cookie( &syncCookie );
}
- entry = syncrepl_message_to_entry( si, op, msg,
- &modlist, syncstate );
- rc_efree = syncrepl_entry( si, op, entry, modlist, syncstate,
- &syncUUID, &syncCookie_req );
- if ( syncCookie.octet_str && syncCookie.octet_str[0].bv_val ) {
- syncrepl_updateCookie( si, op, psub, &syncCookie );
+ if ( syncrepl_message_to_entry( si, op, msg,
+ &modlist, &entry, syncstate ) == LDAP_SUCCESS ) {
+ rc_efree = syncrepl_entry( si, op, entry, modlist,
+ syncstate, &syncUUID, &syncCookie_req );
+ if ( syncCookie.octet_str &&
+ syncCookie.octet_str[0].bv_val ) {
+ syncrepl_updateCookie( si, op, psub, &syncCookie );
+ }
}
ldap_controls_free( rctrls );
if ( modlist ) {
&syncCookie_req.ctxcsn[0], &syncCookie.ctxcsn[0], &text );
}
if ( syncCookie.octet_str && syncCookie.octet_str->bv_val
- && match < 0 ) {
+ && match < 0 && err == LDAP_SUCCESS ) {
syncrepl_updateCookie( si, op, psub, &syncCookie );
}
if ( rctrls ) {
* 1) err code : LDAP_BUSY ...
* 2) on err policy : stop service, stop sync, retry
*/
- if ( refreshDeletes == 0 && match < 0 ) {
+ if ( refreshDeletes == 0 && match < 0 &&
+ err == LDAP_SUCCESS ) {
syncrepl_del_nonpresent( op, si );
} else {
avl_free( si->si_presentlist, avl_ber_bvfree );
return NULL;
}
-Entry*
+int
syncrepl_message_to_entry(
syncinfo_t *si,
Operation *op,
LDAPMessage *msg,
Modifications **modlist,
+ Entry **entry,
int syncstate
)
{
Debug( LDAP_DEBUG_ANY,
"Message type should be entry (%d)", ldap_msgtype( msg ), 0, 0 );
#endif
- return NULL;
+ return -1;
}
op->o_tag = LDAP_REQ_ADD;
Debug( LDAP_DEBUG_ANY,
"syncrepl_message_to_entry : dn get failed (%d)", rc, 0, 0 );
#endif
- return NULL;
+ return rc;
}
dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx );
if ( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_DELETE )
{
- return NULL;
+ return LDAP_SUCCESS;
+ }
+
+ if ( entry == NULL ) {
+ return -1;
}
e = ( Entry * ) ch_calloc( 1, sizeof( Entry ) );
+ *entry = e;
e->e_name = op->o_req_dn;
e->e_nname = op->o_req_ndn;
e = NULL;
}
- return e;
+ return rc;
}
int
int ret = LDAP_SUCCESS;
const char *text;
+ struct berval pdn = { 0, NULL };
+ struct berval org_req_dn = { 0, NULL };
+ struct berval org_req_ndn = { 0, NULL };
+ struct berval org_dn = { 0, NULL };
+ struct berval org_ndn = { 0, NULL };
+ int org_managedsait;
+
if (( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_ADD ))
{
syncuuid_bv = ber_dupbv( NULL, syncUUID );
op->o_req_ndn = si->si_syncUUID_ndn;
op->o_tag = LDAP_REQ_DELETE;
rc = be->be_delete( op, &rs );
+
+ org_req_dn = op->o_req_dn;
+ org_req_ndn = op->o_req_ndn;
+ org_dn = op->o_dn;
+ org_ndn = op->o_ndn;
+ org_managedsait = get_manageDSAit( op );
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_ndn = op->o_bd->be_rootndn;
+ op->o_managedsait = 1;
+
+ while ( rs.sr_err == LDAP_SUCCESS &&
+ op->o_delete_glue_parent ) {
+ op->o_delete_glue_parent = 0;
+ if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) {
+ slap_callback cb = { NULL };
+ cb.sc_response = slap_null_cb;
+ dnParent( &op->o_req_ndn, &pdn );
+ op->o_req_dn = pdn;
+ op->o_req_ndn = pdn;
+ op->o_callback = &cb;
+ op->o_bd->be_delete( op, &rs );
+ } else {
+ break;
+ }
+ }
+
+ op->o_managedsait = org_managedsait;
+ op->o_dn = org_dn;
+ op->o_ndn = org_ndn;
+ op->o_req_dn = org_req_dn;
+ op->o_req_ndn = org_req_ndn;
+ op->o_delete_glue_parent = 0;
+
op->o_no_psearch = 0;
}
case LDAP_SYNC_MODIFY:
if ( rc == LDAP_SUCCESS ||
rc == LDAP_REFERRAL ||
- rc == LDAP_NO_SUCH_OBJECT )
+ rc == LDAP_NO_SUCH_OBJECT ||
+ rc == LDAP_NOT_ALLOWED_ON_NONLEAF )
{
attr_delete( &e->e_attrs, slap_schema.si_ad_entryUUID );
attr_merge_one( e, slap_schema.si_ad_entryUUID,
rc = be->be_add( op, &rs );
if ( rc != LDAP_SUCCESS ) {
- if ( rc == LDAP_ALREADY_EXISTS ) {
+ if ( rc == LDAP_ALREADY_EXISTS ) {
op->o_tag = LDAP_REQ_MODIFY;
op->orm_modlist = modlist;
op->o_req_dn = e->e_name;
return ret;
}
+static struct berval gcbva[] = {
+ BER_BVC("top"),
+ BER_BVC("glue"),
+ BER_BVNULL
+};
+
static void
syncrepl_del_nonpresent(
Operation *op,
slap_callback cb = { NULL };
SlapReply rs = {REP_RESULT};
struct nonpresent_entry *np_list, *np_prev;
+ int rc;
+ Modifications *ml;
+ Modifications *mlnext;
+ Modifications *mod;
+ Modifications *modlist = NULL;
+ Modifications **modtail = &modlist;
+ Attribute *attr;
+
+ struct berval pdn = { 0, NULL };
+ struct berval org_req_dn = { 0, NULL };
+ struct berval org_req_ndn = { 0, NULL };
+ struct berval org_dn = { 0, NULL };
+ struct berval org_ndn = { 0, NULL };
+ int org_managedsait;
op->o_req_dn = si->si_base;
op->o_req_ndn = si->si_base;
op->ors_filterstr = si->si_filterstr;
op->o_nocaching = 1;
+ op->o_managedsait = 0;
be->be_search( op, &rs );
+ op->o_managedsait = 1;
op->o_nocaching = 0;
if ( op->ors_filter ) filter_free_x( op, op->ors_filter );
cb.sc_private = si;
op->o_req_dn = *np_prev->npe_name;
op->o_req_ndn = *np_prev->npe_nname;
- op->o_bd->be_delete( op, &rs );
+ rc = op->o_bd->be_delete( op, &rs );
+
+ if ( rc == LDAP_NOT_ALLOWED_ON_NONLEAF ) {
+ mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
+ mod->sml_op = LDAP_MOD_REPLACE;
+ mod->sml_desc = slap_schema.si_ad_objectClass;
+ mod->sml_type = mod->sml_desc->ad_cname;
+ mod->sml_bvalues = &gcbva[0];
+ *modtail = mod;
+ modtail = &mod->sml_next;
+
+ mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
+ mod->sml_op = LDAP_MOD_REPLACE;
+ mod->sml_desc = slap_schema.si_ad_structuralObjectClass;
+ mod->sml_type = mod->sml_desc->ad_cname;
+ mod->sml_bvalues = &gcbva[1];
+ *modtail = mod;
+ modtail = &mod->sml_next;
+
+ op->o_tag = LDAP_REQ_MODIFY;
+ op->orm_modlist = modlist;
+
+ rc = be->be_modify( op, &rs );
+
+ for ( ml = modlist; ml != NULL; ml = mlnext ) {
+ mlnext = ml->sml_next;
+ free( ml );
+ }
+ }
+
+ org_req_dn = op->o_req_dn;
+ org_req_ndn = op->o_req_ndn;
+ org_dn = op->o_dn;
+ org_ndn = op->o_ndn;
+ org_managedsait = get_manageDSAit( op );
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_ndn = op->o_bd->be_rootndn;
+ op->o_managedsait = 1;
+
+ while ( rs.sr_err == LDAP_SUCCESS &&
+ op->o_delete_glue_parent ) {
+ op->o_delete_glue_parent = 0;
+ if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) {
+ slap_callback cb = { NULL };
+ cb.sc_response = slap_null_cb;
+ dnParent( &op->o_req_ndn, &pdn );
+ op->o_req_dn = pdn;
+ op->o_req_ndn = pdn;
+ op->o_callback = &cb;
+ /* give it a root privil ? */
+ op->o_bd->be_delete( op, &rs );
+ } else {
+ break;
+ }
+ }
+
+ op->o_managedsait = org_managedsait;
+ op->o_dn = org_dn;
+ op->o_ndn = org_ndn;
+ op->o_req_dn = org_req_dn;
+ op->o_req_ndn = org_req_ndn;
+ op->o_delete_glue_parent = 0;
+
ber_bvfree( np_prev->npe_name );
ber_bvfree( np_prev->npe_nname );
op->o_req_dn.bv_val = NULL;
}
-static struct berval gcbva[] = {
- BER_BVC("top"),
- BER_BVC("glue")
-};
-
void
syncrepl_add_glue(
Operation* op,
a->a_vals = ch_calloc( 3, sizeof( struct berval ));
ber_dupbv( &a->a_vals[0], &gcbva[0] );
ber_dupbv( &a->a_vals[1], &gcbva[1] );
- a->a_vals[2].bv_len = 0;
- a->a_vals[2].bv_val = NULL;
+ ber_dupbv( &a->a_vals[2], &gcbva[2] );
a->a_nvals = a->a_vals;
a->a_vals = ch_calloc( 2, sizeof( struct berval ));
ber_dupbv( &a->a_vals[0], &gcbva[1] );
- a->a_vals[1].bv_len = 0;
- a->a_vals[1].bv_val = NULL;
+ ber_dupbv( &a->a_vals[1], &gcbva[2] );
a->a_nvals = a->a_vals;
return 0;
}
-int get_limits( Backend *be, struct berval *ndn, struct slap_limits_set **limit )
+int get_limits( Operation *op, struct berval *ndn, struct slap_limits_set **limit )
{
return 0;
}
}
}
- if ( update_ctxcsn == SLAP_TOOL_CTXCSN_KEEP ) {
+ if ( update_ctxcsn == SLAP_TOOL_CTXCSN_KEEP &&
+ ( replica_promotion || replica_demotion )) {
if ( is_entry_syncProviderSubentry( e )) {
if ( !LDAP_SLIST_EMPTY( &consumer_subentry )) {
fprintf( stderr, "%s: consumer and provider subentries "
}
}
- if ( !is_entry_syncProviderSubentry( e ) &&
- !is_entry_syncConsumerSubentry( e )) {
+ if (( !is_entry_syncProviderSubentry( e ) &&
+ !is_entry_syncConsumerSubentry( e )) ||
+ ( !replica_promotion && !replica_demotion )) {
if (!dryrun) {
ID id = be->be_entry_put( be, e, &bvtext );
if( id == NOID ) {