Sync with HEAD

This commit is contained in:
Kurt Zeilenga 2005-10-05 19:42:19 +00:00
parent bf637ea2a9
commit 164d5c2d0f
19 changed files with 519 additions and 454 deletions

View file

@ -38,6 +38,7 @@ OpenLDAP 2.3.8 Release
Fixed slapcat out-of-memory problem (ITS#4010)
Fixed slurpd unrecognized slave names bug (ITS#4012)
Fixed liblber dgram len bug (ITS#4046)
Updated contrib/ldapc++ to avoid deprecated functions
Documentation
Added slapo-valsort(5) man page (ITS#3994)
Added slap tool -F option documentation (ITS#4026)
@ -46,6 +47,7 @@ OpenLDAP 2.3.8 Release
Fixed --without-threads build issue (ITS#4006)
Fixed test script exit checks (ITS#4045)
Added test suite parameterized directory support
Updated contrib/ldapc++ build environment
OpenLDAP 2.3.7 Release
Updated slapd ManageDIT support

View file

@ -244,6 +244,13 @@ the target using the "pseudorootdn" DN.
Note: cleartext credentials must be supplied here; as a consequence,
using the pseudorootdn/pseudorootpw directives is inherently unsafe.
.TP
.B pseudoroot-bind-defer {NO|yes}
This directive, when set to
.BR yes ,
causes the authentication to the remote servers with the pseudo-root
identity to be deferred until actually needed by subsequent operations.
.TP
.B rewrite* ...
The rewrite options are described in the "REWRITING" section.

View file

@ -689,6 +689,9 @@ ldap_int_sasl_bind(
if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
rc = ld->ld_errno = sasl_err2ldap( saslrc );
#if SASL_VERSION_MAJOR >= 2
if ( ld->ld_error ) {
LDAP_FREE( ld->ld_error );
}
ld->ld_error = LDAP_STRDUP( sasl_errdetail( ctx ) );
#endif
goto done;
@ -710,11 +713,13 @@ ldap_int_sasl_bind(
}
if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) {
if( scred && scred->bv_len ) {
/* and server provided us with data? */
Debug( LDAP_DEBUG_TRACE,
"ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n",
rc, saslrc, scred->bv_len );
if( scred ) {
if ( scred->bv_len ) {
/* and server provided us with data? */
Debug( LDAP_DEBUG_TRACE,
"ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n",
rc, saslrc, scred->bv_len );
}
ber_bvfree( scred );
}
rc = ld->ld_errno;
@ -723,11 +728,13 @@ ldap_int_sasl_bind(
if( rc == LDAP_SUCCESS && saslrc == SASL_OK ) {
/* we're done, no need to step */
if( scred && scred->bv_len ) {
/* but server provided us with data! */
Debug( LDAP_DEBUG_TRACE,
"ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n",
rc, saslrc, scred->bv_len );
if( scred ) {
if ( scred->bv_len ) {
/* but server provided us with data! */
Debug( LDAP_DEBUG_TRACE,
"ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n",
rc, saslrc, scred->bv_len );
}
ber_bvfree( scred );
rc = ld->ld_errno = LDAP_LOCAL_ERROR;
goto done;
@ -760,6 +767,9 @@ ldap_int_sasl_bind(
if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
ld->ld_errno = sasl_err2ldap( saslrc );
#if SASL_VERSION_MAJOR >= 2
if ( ld->ld_error ) {
LDAP_FREE( ld->ld_error );
}
ld->ld_error = LDAP_STRDUP( sasl_errdetail( ctx ) );
#endif
rc = ld->ld_errno;
@ -771,6 +781,9 @@ ldap_int_sasl_bind(
if ( saslrc != SASL_OK ) {
#if SASL_VERSION_MAJOR >= 2
if ( ld->ld_error ) {
LDAP_FREE( ld->ld_error );
}
ld->ld_error = LDAP_STRDUP( sasl_errdetail( ctx ) );
#endif
rc = ld->ld_errno = sasl_err2ldap( saslrc );

View file

@ -753,6 +753,10 @@ ldap_int_tls_connect( LDAP *ld, LDAPConn *conn )
if ((err = ERR_peek_error())) {
char buf[256];
if ( ld->ld_error ) {
LDAP_FREE( ld->ld_error );
}
ld->ld_error = LDAP_STRDUP(ERR_error_string(err, buf));
#ifdef HAVE_EBCDIC
if ( ld->ld_error ) __etoa(ld->ld_error);
@ -1036,7 +1040,10 @@ ldap_pvt_tls_check_hostname( LDAP *ld, void *s, const char *name_in )
Debug( LDAP_DEBUG_ANY,
"TLS: unable to get common name from peer certificate.\n",
0, 0, 0 );
ret = LDAP_CONNECT_ERROR;
ret = LDAP_CONNECT_ERROR;
if ( ld->ld_error ) {
LDAP_FREE( ld->ld_error );
}
ld->ld_error = LDAP_STRDUP(
_("TLS: unable to get CN from peer certificate"));
@ -1061,12 +1068,15 @@ ldap_pvt_tls_check_hostname( LDAP *ld, void *s, const char *name_in )
}
if( ret == LDAP_LOCAL_ERROR ) {
Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
"common name in certificate (%s).\n",
name, buf, 0 );
ret = LDAP_CONNECT_ERROR;
ld->ld_error = LDAP_STRDUP(
_("TLS: hostname does not match CN in peer certificate"));
Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
"common name in certificate (%s).\n",
name, buf, 0 );
ret = LDAP_CONNECT_ERROR;
if ( ld->ld_error ) {
LDAP_FREE( ld->ld_error );
}
ld->ld_error = LDAP_STRDUP(
_("TLS: hostname does not match CN in peer certificate"));
}
}
X509_free(x);

View file

@ -140,6 +140,13 @@ ldap_ld_free(
ld->ld_options.ldo_defludp = NULL;
}
#ifdef LDAP_CONNECTIONLESS
if ( ld->ld_options.ldo_peer != NULL ) {
LDAP_FREE( ld->ld_options.ldo_peer );
ld->ld_options.ldo_peer = NULL;
}
#endif
if ( ld->ld_options.ldo_tm_api != NULL ) {
LDAP_FREE( ld->ld_options.ldo_tm_api );
ld->ld_options.ldo_tm_api = NULL;

View file

@ -67,7 +67,7 @@ lutil_csnstr(char *buf, size_t len, unsigned int replica, unsigned int mod)
csntime = t;
csnop = 0;
}
op = ++csnop;
op = csnop++;
#ifdef HAVE_GMTIME_R
ltm = gmtime_r( &t, &ltm_buf );

View file

@ -312,14 +312,17 @@ meta_back_retry(
extern void
meta_back_conn_free(
metaconn_t *mc );
void *v_mc );
extern int
meta_back_init_one_conn(
Operation *op,
SlapReply *rs,
metatarget_t *mt,
metaconn_t *mc,
metasingleconn_t *msc,
int ispriv,
int isauthz,
ldap_back_send_t sendok );
extern int

View file

@ -391,7 +391,9 @@ retry:;
/* mc here must be the regular mc,
* reset and ready for init */
rc = meta_back_init_one_conn( op, rs,
mt, msc, LDAP_BACK_DONTSEND );
mt, mc, msc, LDAP_BACK_CONN_ISPRIV( mc ),
candidate == mc->mc_authz_target,
LDAP_BACK_DONTSEND );
} else {
/* can't do anything about it */
@ -567,7 +569,10 @@ retry:;
/* mc here must be the regular mc,
* reset and ready for init */
rc = meta_back_init_one_conn( op, rs,
mt, msc, LDAP_BACK_DONTSEND );
mt, mc, msc,
LDAP_BACK_CONN_ISPRIV( mc ),
candidate == mc->mc_authz_target,
LDAP_BACK_DONTSEND );
} else {

View file

@ -176,27 +176,6 @@ metaconn_alloc(
return mc;
}
/*
* meta_back_conn_free
*
* clears a metaconn
*/
void
meta_back_conn_free(
metaconn_t *mc )
{
assert( mc != NULL );
assert( mc->mc_refcnt == 0 );
if ( !BER_BVISNULL( &mc->mc_local_ndn ) ) {
free( mc->mc_local_ndn.bv_val );
}
ldap_pvt_thread_mutex_destroy( &mc->mc_mutex );
free( mc );
}
static void
meta_back_freeconn(
Operation *op,
@ -225,7 +204,10 @@ meta_back_init_one_conn(
Operation *op,
SlapReply *rs,
metatarget_t *mt,
metaconn_t *mc,
metasingleconn_t *msc,
int ispriv,
int isauthz,
ldap_back_send_t sendok )
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
@ -367,32 +349,54 @@ retry:;
/*
* If the connection DN is not null, an attempt to rewrite it is made
*/
if ( !BER_BVISEMPTY( &op->o_conn->c_dn ) ) {
dc.target = mt;
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = "bindDN";
/*
* Rewrite the bind dn if needed
*/
if ( ldap_back_dn_massage( &dc, &op->o_conn->c_dn,
&msc->msc_bound_ndn ) )
{
goto error_return;
if ( ispriv ) {
if ( !BER_BVISNULL( &mt->mt_pseudorootdn ) ) {
ber_dupbv( &msc->msc_bound_ndn, &mt->mt_pseudorootdn );
if ( !BER_BVISNULL( &mt->mt_pseudorootpw ) ) {
ber_dupbv( &msc->msc_cred, &mt->mt_pseudorootpw );
}
} else {
ber_str2bv( "", 0, 1, &msc->msc_bound_ndn );
}
/* copy the DN idf needed */
if ( msc->msc_bound_ndn.bv_val == op->o_conn->c_dn.bv_val ) {
ber_dupbv( &msc->msc_bound_ndn, &op->o_conn->c_dn );
}
assert( !BER_BVISNULL( &msc->msc_bound_ndn ) );
LDAP_BACK_CONN_ISPRIV_SET( msc );
} else {
ber_str2bv( "", 0, 1, &msc->msc_bound_ndn );
BER_BVZERO( &msc->msc_cred );
BER_BVZERO( &msc->msc_bound_ndn );
if ( !BER_BVISEMPTY( &op->o_ndn )
&& SLAP_IS_AUTHZ_BACKEND( op )
&& isauthz )
{
dc.target = mt;
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = "bindDN";
/*
* Rewrite the bind dn if needed
*/
if ( ldap_back_dn_massage( &dc, &op->o_conn->c_dn,
&msc->msc_bound_ndn ) )
{
ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
goto error_return;
}
/* copy the DN idf needed */
if ( msc->msc_bound_ndn.bv_val == op->o_conn->c_dn.bv_val ) {
ber_dupbv( &msc->msc_bound_ndn, &op->o_conn->c_dn );
}
} else {
ber_str2bv( "", 0, 1, &msc->msc_bound_ndn );
}
}
assert( !BER_BVISNULL( &msc->msc_bound_ndn ) );
LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
error_return:;
@ -450,7 +454,9 @@ retry_lock:;
( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn );
/* mc here must be the regular mc, reset and ready for init */
rc = meta_back_init_one_conn( op, rs, mt, msc, sendok );
rc = meta_back_init_one_conn( op, rs, mt, mc, msc,
LDAP_BACK_CONN_ISPRIV( mc ),
candidate == mc->mc_authz_target, sendok );
if ( rc == LDAP_SUCCESS ) {
rc = meta_back_single_dobind( op, rs, mc, candidate,
@ -781,27 +787,13 @@ meta_back_getconn(
* also init'd
*/
candidates[ i ].sr_err = meta_back_init_one_conn( op,
rs, mt, msc, sendok );
rs, mt, mc, msc,
LDAP_BACK_CONN_ISPRIV( &mc_curr ),
i == mc->mc_authz_target, sendok );
if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {
candidates[ i ].sr_tag = META_CANDIDATE;
ncandidates++;
if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
ber_dupbv( &msc->msc_cred, &mt->mt_pseudorootpw );
ber_dupbv( &msc->msc_bound_ndn, &mt->mt_pseudorootdn );
LDAP_BACK_CONN_ISPRIV_SET( msc );
} else {
BER_BVZERO( &msc->msc_cred );
BER_BVZERO( &msc->msc_bound_ndn );
if ( !BER_BVISEMPTY( &op->o_ndn )
&& SLAP_IS_AUTHZ_BACKEND( op )
&& i == mc->mc_authz_target )
{
ber_dupbv( &msc->msc_bound_ndn, &op->o_ndn );
}
}
} else {
/*
@ -941,7 +933,9 @@ meta_back_getconn(
* also init'd. In case of error, meta_back_init_one_conn
* sends the appropriate result.
*/
err = meta_back_init_one_conn( op, rs, mt, msc, sendok );
err = meta_back_init_one_conn( op, rs, mt, mc, msc,
LDAP_BACK_CONN_ISPRIV( &mc_curr ),
i == mc->mc_authz_target, sendok );
if ( err != LDAP_SUCCESS ) {
/*
* FIXME: in case one target cannot
@ -967,22 +961,6 @@ meta_back_getconn(
*candidate = i;
}
if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
ber_dupbv( &msc->msc_cred, &mt->mt_pseudorootpw );
ber_dupbv( &msc->msc_bound_ndn, &mt->mt_pseudorootdn );
LDAP_BACK_CONN_ISPRIV_SET( msc );
} else {
BER_BVZERO( &msc->msc_cred );
BER_BVZERO( &msc->msc_bound_ndn );
if ( !BER_BVISEMPTY( &op->o_ndn )
&& SLAP_IS_AUTHZ_BACKEND( op )
&& i == mc->mc_authz_target )
{
ber_dupbv( &msc->msc_bound_ndn, &op->o_ndn );
}
}
/*
* if no unique candidate ...
*/
@ -1012,28 +990,15 @@ meta_back_getconn(
* also init'd
*/
int lerr = meta_back_init_one_conn( op, rs,
mt, msc, sendok );
mt, mc, msc,
LDAP_BACK_CONN_ISPRIV( &mc_curr ),
i == mc->mc_authz_target,
sendok );
if ( lerr == LDAP_SUCCESS ) {
candidates[ i ].sr_tag = META_CANDIDATE;
candidates[ i ].sr_err = LDAP_SUCCESS;
ncandidates++;
if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
ber_dupbv( &msc->msc_cred, &mt->mt_pseudorootpw );
ber_dupbv( &msc->msc_bound_ndn, &mt->mt_pseudorootdn );
LDAP_BACK_CONN_ISPRIV_SET( msc );
} else {
BER_BVZERO( &msc->msc_cred );
BER_BVZERO( &msc->msc_bound_ndn );
if ( !BER_BVISEMPTY( &op->o_ndn )
&& SLAP_IS_AUTHZ_BACKEND( op )
&& i == mc->mc_authz_target )
{
ber_dupbv( &msc->msc_bound_ndn, &op->o_ndn );
}
}
Debug( LDAP_DEBUG_TRACE, "%s: meta_back_init_one_conn(%d)\n",
op->o_log_prefix, i, 0 );

View file

@ -126,13 +126,20 @@ meta_back_db_open(
return 0;
}
static void
conn_free(
void
meta_back_conn_free(
void *v_mc )
{
metaconn_t *mc = v_mc;
int i, ntargets;
assert( mc != NULL );
assert( mc->mc_refcnt == 0 );
if ( !BER_BVISNULL( &mc->mc_local_ndn ) ) {
free( mc->mc_local_ndn.bv_val );
}
assert( mc->mc_conns != NULL );
/* at least one must be present... */
@ -156,6 +163,7 @@ conn_free(
}
}
ldap_pvt_thread_mutex_destroy( &mc->mc_mutex );
free( mc );
}
@ -220,7 +228,7 @@ meta_back_db_destroy(
ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
if ( mi->mi_conntree ) {
avl_free( mi->mi_conntree, conn_free );
avl_free( mi->mi_conntree, meta_back_conn_free );
}
/*

View file

@ -231,7 +231,7 @@ backsql_add_sysmaps( backsql_info *bi, backsql_oc_map_rec *oc_map )
snprintf( tmp, sizeof(tmp),
"DELETE FROM ldap_entry_objclasses "
"WHERE entry_id=(SELECT id FROM ldap_entries "
"WHERE oc_map_id=%lu"
"WHERE oc_map_id=%lu "
"AND keyval=?) AND oc_name=?",
oc_map->bom_id );
at_map->bam_delete_proc = ch_strdup( tmp );

View file

@ -614,7 +614,13 @@ select_backend(
continue;
}
} else {
b2 = be;
/* If any parts of the tree are glued, use the first
* match regardless of manageDSAit. Otherwise use the
* last match.
*/
if( !( SLAP_DBFLAGS( be ) & ( SLAP_DBFLAG_GLUE_INSTANCE |
SLAP_DBFLAG_GLUE_SUBORDINATE )))
b2 = be;
}
return b2;
}

View file

@ -868,6 +868,7 @@ overlay_config( BackendDB *be, const char *ov )
oi = ch_malloc( sizeof( slap_overinfo ) );
oi->oi_orig = be->bd_info;
oi->oi_bi = *be->bd_info;
oi->oi_origdb = be;
/* NOTE: the first time a global overlay is configured,
* frontendDB gets this flag; it is used later by overlays

View file

@ -654,30 +654,41 @@ static Entry *accesslog_entry( Operation *op, int logop ) {
log_info *li = on->on_bi.bi_private;
char rdnbuf[STRLENOF(RDNEQ)+LDAP_LUTIL_GENTIME_BUFSIZE+8];
struct berval rdn, timestamp, bv;
char nrdnbuf[STRLENOF(RDNEQ)+LDAP_LUTIL_GENTIME_BUFSIZE+8];
struct berval rdn, nrdn, timestamp, ntimestamp, bv;
slap_verbmasks *lo = logops+logop+EN_OFFSET;
Entry *e = ch_calloc( 1, sizeof(Entry) );
strcpy( rdnbuf, RDNEQ );
rdn.bv_val = rdnbuf;
strcpy( nrdnbuf, RDNEQ );
nrdn.bv_val = nrdnbuf;
timestamp.bv_val = rdnbuf+STRLENOF(RDNEQ);
timestamp.bv_len = sizeof(rdnbuf) - STRLENOF(RDNEQ);
slap_timestamp( &op->o_time, &timestamp );
if ( op->o_tincr ) {
sprintf( timestamp.bv_val + timestamp.bv_len-1, ".%06dZ", op->o_tincr );
timestamp.bv_len += 7;
}
sprintf( timestamp.bv_val + timestamp.bv_len-1, ".%06dZ", op->o_tincr );
timestamp.bv_len += 7;
rdn.bv_len = STRLENOF(RDNEQ)+timestamp.bv_len;
ad_reqStart->ad_type->sat_equality->smr_normalize(
SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, ad_reqStart->ad_type->sat_syntax,
ad_reqStart->ad_type->sat_equality, &timestamp, &ntimestamp,
op->o_tmpmemctx );
strcpy( nrdn.bv_val + STRLENOF(RDNEQ), ntimestamp.bv_val );
nrdn.bv_len += ntimestamp.bv_len;
build_new_dn( &e->e_name, li->li_db->be_suffix, &rdn, NULL );
build_new_dn( &e->e_nname, li->li_db->be_nsuffix, &rdn, NULL );
build_new_dn( &e->e_nname, li->li_db->be_nsuffix, &nrdn, NULL );
attr_merge_one( e, slap_schema.si_ad_objectClass,
&log_ocs[logop]->soc_cname, NULL );
attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
&log_ocs[logop]->soc_cname, NULL );
attr_merge_one( e, ad_reqStart, &timestamp, NULL );
attr_merge_one( e, ad_reqStart, &timestamp, &ntimestamp );
op->o_tmpfree( ntimestamp.bv_val, op->o_tmpmemctx );
/* Exops have OID appended */
if ( logop == LOG_EN_EXTENDED ) {

View file

@ -26,6 +26,7 @@
#include "lutil.h"
#include "slap.h"
#include "config.h"
#include "ldap_rq.h"
/* A modify request on a particular entry */
typedef struct modinst {
@ -60,9 +61,16 @@ typedef struct syncops {
int s_rid;
struct berval s_filterstr;
int s_flags; /* search status */
#define PS_IS_REFRESHING 0x01
#define PS_IS_DETACHED 0x02
#define PS_WROTE_BASE 0x04
#define PS_FIND_BASE 0x08
int s_inuse; /* reference count */
struct syncres *s_res;
struct syncres *s_restail;
struct re_s *s_qtask; /* task for playing psearch responses */
#define RUNQ_INTERVAL 36000 /* a long time */
ldap_pvt_thread_mutex_t s_mutex;
} syncops;
@ -83,9 +91,6 @@ typedef struct sync_control {
#define SLAP_SYNC_PERSIST (LDAP_SYNC_RESERVED<<SLAP_CONTROL_SHIFT)
#define SLAP_SYNC_REFRESH_AND_PERSIST (LDAP_SYNC_REFRESH_AND_PERSIST<<SLAP_CONTROL_SHIFT)
#define PS_IS_REFRESHING 0x01
#define PS_IS_DETACHED 0x02
/* Record of which searches matched at premodify step */
typedef struct syncmatches {
struct syncmatches *sm_next;
@ -360,36 +365,15 @@ findbase_cb( Operation *op, SlapReply *rs )
* Just store whatever we got.
*/
if ( fc->fss->s_eid == NOID ) {
fc->fbase = 1;
fc->fbase = 2;
fc->fss->s_eid = rs->sr_entry->e_id;
ber_dupbv( &fc->fss->s_base, &rs->sr_entry->e_nname );
} else if ( rs->sr_entry->e_id == fc->fss->s_eid &&
dn_match( &rs->sr_entry->e_nname, &fc->fss->s_base )) {
/* OK, the DN is the same and the entryID is the same. Now
* see if the fdn resides in the scope.
*/
/* OK, the DN is the same and the entryID is the same. */
fc->fbase = 1;
switch ( fc->fss->s_op->ors_scope ) {
case LDAP_SCOPE_BASE:
fc->fscope = dn_match( fc->fdn, &rs->sr_entry->e_nname );
break;
case LDAP_SCOPE_ONELEVEL: {
struct berval pdn;
dnParent( fc->fdn, &pdn );
fc->fscope = dn_match( &pdn, &rs->sr_entry->e_nname );
break; }
case LDAP_SCOPE_SUBTREE:
fc->fscope = dnIsSuffix( fc->fdn, &rs->sr_entry->e_nname );
break;
#ifdef LDAP_SCOPE_SUBORDINATE
case LDAP_SCOPE_SUBORDINATE:
fc->fscope = dnIsSuffix( fc->fdn, &rs->sr_entry->e_nname ) &&
!dn_match( fc->fdn, &rs->sr_entry->e_nname );
break;
#endif
}
}
}
if ( rs->sr_err != LDAP_SUCCESS ) {
@ -404,40 +388,73 @@ syncprov_findbase( Operation *op, fbase_cookie *fc )
opcookie *opc = op->o_callback->sc_private;
slap_overinst *on = opc->son;
slap_callback cb = {0};
Operation fop;
SlapReply frs = { REP_RESULT };
int rc;
/* Use basic parameters from syncrepl search, but use
* current op's threadctx / tmpmemctx
*/
fop = *fc->fss->s_op;
ldap_pvt_thread_mutex_lock( &fc->fss->s_mutex );
if ( fc->fss->s_flags & PS_FIND_BASE ) {
slap_callback cb = {0};
Operation fop;
SlapReply frs = { REP_RESULT };
int rc;
fop.o_hdr = op->o_hdr;
fop.o_bd = op->o_bd;
fop.o_time = op->o_time;
fop.o_tincr = op->o_tincr;
fc->fss->s_flags ^= PS_FIND_BASE;
ldap_pvt_thread_mutex_unlock( &fc->fss->s_mutex );
cb.sc_response = findbase_cb;
cb.sc_private = fc;
fop = *fc->fss->s_op;
fop.o_sync_mode = 0; /* turn off sync mode */
fop.o_managedsait = SLAP_CONTROL_CRITICAL;
fop.o_callback = &cb;
fop.o_tag = LDAP_REQ_SEARCH;
fop.ors_scope = LDAP_SCOPE_BASE;
fop.ors_limit = NULL;
fop.ors_slimit = 1;
fop.ors_tlimit = SLAP_NO_LIMIT;
fop.ors_attrs = slap_anlist_no_attrs;
fop.ors_attrsonly = 1;
fop.o_hdr = op->o_hdr;
fop.o_bd = op->o_bd;
fop.o_time = op->o_time;
fop.o_tincr = op->o_tincr;
fop.o_bd->bd_info = on->on_info->oi_orig;
rc = fop.o_bd->be_search( &fop, &frs );
fop.o_bd->bd_info = (BackendInfo *)on;
cb.sc_response = findbase_cb;
cb.sc_private = fc;
if ( fc->fbase ) return LDAP_SUCCESS;
fop.o_sync_mode = 0; /* turn off sync mode */
fop.o_managedsait = SLAP_CONTROL_CRITICAL;
fop.o_callback = &cb;
fop.o_tag = LDAP_REQ_SEARCH;
fop.ors_scope = LDAP_SCOPE_BASE;
fop.ors_limit = NULL;
fop.ors_slimit = 1;
fop.ors_tlimit = SLAP_NO_LIMIT;
fop.ors_attrs = slap_anlist_no_attrs;
fop.ors_attrsonly = 1;
fop.o_bd->bd_info = on->on_info->oi_orig;
rc = fop.o_bd->be_search( &fop, &frs );
fop.o_bd->bd_info = (BackendInfo *)on;
} else {
ldap_pvt_thread_mutex_unlock( &fc->fss->s_mutex );
fc->fbase = 1;
}
/* After the first call, see if the fdn resides in the scope */
if ( fc->fbase == 1 ) {
switch ( fc->fss->s_op->ors_scope ) {
case LDAP_SCOPE_BASE:
fc->fscope = dn_match( fc->fdn, &fc->fss->s_base );
break;
case LDAP_SCOPE_ONELEVEL: {
struct berval pdn;
dnParent( fc->fdn, &pdn );
fc->fscope = dn_match( &pdn, &fc->fss->s_base );
break; }
case LDAP_SCOPE_SUBTREE:
fc->fscope = dnIsSuffix( fc->fdn, &fc->fss->s_base );
break;
#ifdef LDAP_SCOPE_SUBORDINATE
case LDAP_SCOPE_SUBORDINATE:
fc->fscope = dnIsSuffix( fc->fdn, &fc->fss->s_base ) &&
!dn_match( fc->fdn, &fc->fss->s_base );
break;
#endif
}
}
if ( fc->fbase )
return LDAP_SUCCESS;
/* If entryID has changed, then the base of this search has
* changed. Invalidate the psearch.
@ -680,6 +697,206 @@ again:
return rc;
}
static void
syncprov_free_syncop( syncops *so )
{
syncres *sr, *srnext;
GroupAssertion *ga, *gnext;
ldap_pvt_thread_mutex_lock( &so->s_mutex );
if ( --so->s_inuse > 0 ) {
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
return;
}
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
if ( so->s_flags & PS_IS_DETACHED ) {
filter_free( so->s_op->ors_filter );
for ( ga = so->s_op->o_groups; ga; ga=gnext ) {
gnext = ga->ga_next;
ch_free( ga );
}
ch_free( so->s_op );
}
ch_free( so->s_base.bv_val );
for ( sr=so->s_res; sr; sr=srnext ) {
srnext = sr->s_next;
ch_free( sr );
}
ldap_pvt_thread_mutex_destroy( &so->s_mutex );
ch_free( so );
}
/* Send a persistent search response */
static int
syncprov_sendresp( Operation *op, opcookie *opc, syncops *so, Entry **e, int mode)
{
slap_overinst *on = opc->son;
SlapReply rs = { REP_SEARCH };
LDAPControl *ctrls[2];
struct berval cookie;
Entry e_uuid = {0};
Attribute a_uuid = {0};
if ( so->s_op->o_abandon )
return SLAPD_ABANDON;
ctrls[1] = NULL;
slap_compose_sync_cookie( op, &cookie, &opc->sctxcsn, so->s_rid );
e_uuid.e_attrs = &a_uuid;
a_uuid.a_desc = slap_schema.si_ad_entryUUID;
a_uuid.a_nvals = &opc->suuid;
rs.sr_err = syncprov_state_ctrl( op, &rs, &e_uuid,
mode, ctrls, 0, 1, &cookie );
rs.sr_ctrls = ctrls;
op->o_bd->bd_info = (BackendInfo *)on->on_info;
switch( mode ) {
case LDAP_SYNC_ADD:
rs.sr_entry = *e;
if ( rs.sr_entry->e_private )
rs.sr_flags = REP_ENTRY_MUSTRELEASE;
if ( opc->sreference ) {
rs.sr_ref = get_entry_referrals( op, rs.sr_entry );
send_search_reference( op, &rs );
ber_bvarray_free( rs.sr_ref );
if ( !rs.sr_entry )
*e = NULL;
break;
}
/* fallthru */
case LDAP_SYNC_MODIFY:
rs.sr_entry = *e;
if ( rs.sr_entry->e_private )
rs.sr_flags = REP_ENTRY_MUSTRELEASE;
rs.sr_attrs = op->ors_attrs;
send_search_entry( op, &rs );
if ( !rs.sr_entry )
*e = NULL;
break;
case LDAP_SYNC_DELETE:
e_uuid.e_attrs = NULL;
e_uuid.e_name = opc->sdn;
e_uuid.e_nname = opc->sndn;
rs.sr_entry = &e_uuid;
if ( opc->sreference ) {
struct berval bv = BER_BVNULL;
rs.sr_ref = &bv;
send_search_reference( op, &rs );
} else {
send_search_entry( op, &rs );
}
break;
default:
assert(0);
}
/* In case someone else freed it already? */
if ( rs.sr_ctrls ) {
op->o_tmpfree( rs.sr_ctrls[0], op->o_tmpmemctx );
rs.sr_ctrls = NULL;
}
return rs.sr_err;
}
/* Play back queued responses */
static int
syncprov_qplay( Operation *op, slap_overinst *on, syncops *so )
{
syncres *sr;
Entry *e;
opcookie opc;
int rc;
opc.son = on;
op->o_bd->bd_info = (BackendInfo *)on->on_info;
for (;;) {
ldap_pvt_thread_mutex_lock( &so->s_mutex );
sr = so->s_res;
if ( sr )
so->s_res = sr->s_next;
if ( !so->s_res )
so->s_restail = NULL;
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
if ( !sr || so->s_op->o_abandon )
break;
opc.sdn = sr->s_dn;
opc.sndn = sr->s_ndn;
opc.suuid = sr->s_uuid;
opc.sctxcsn = sr->s_csn;
opc.sreference = sr->s_isreference;
e = NULL;
if ( sr->s_mode != LDAP_SYNC_DELETE ) {
rc = be_entry_get_rw( op, &opc.sndn, NULL, NULL, 0, &e );
if ( rc ) {
ch_free( sr );
continue;
}
}
rc = syncprov_sendresp( op, &opc, so, &e, sr->s_mode );
if ( e ) {
be_entry_release_rw( op, e, 0 );
}
ch_free( sr );
if ( rc )
break;
}
op->o_bd->bd_info = (BackendInfo *)on;
return rc;
}
/* runqueue task for playing back queued responses */
static void *
syncprov_qtask( void *ctx, void *arg )
{
struct re_s *rtask = arg;
syncops *so = rtask->arg;
slap_overinst *on = so->s_op->o_private;
char opbuf[OPERATION_BUFFER_SIZE];
Operation *op;
BackendDB be;
op = (Operation *)opbuf;
*op = *so->s_op;
op->o_hdr = (Opheader *)(op+1);
op->o_controls = (void **)(op->o_hdr+1);
memset( op->o_controls, 0, SLAP_MAX_CIDS * sizeof(void *));
*op->o_hdr = *so->s_op->o_hdr;
op->o_tmpmemctx = slap_sl_mem_create(SLAP_SLAB_SIZE, SLAP_SLAB_STACK, ctx);
op->o_tmpmfuncs = &slap_sl_mfuncs;
op->o_threadctx = ctx;
/* syncprov_qplay expects a fake db */
be = *so->s_op->o_bd;
be.be_flags |= SLAP_DBFLAG_OVERLAY;
op->o_bd = &be;
op->o_private = NULL;
op->o_callback = NULL;
syncprov_qplay( op, on, so );
/* decrement use count... */
syncprov_free_syncop( so );
/* wait until we get explicitly scheduled again */
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
ldap_pvt_runqueue_stoptask( &slapd_rq, so->s_qtask );
ldap_pvt_runqueue_resched( &slapd_rq, so->s_qtask, 1 );
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
return NULL;
}
/* Queue a persistent search response */
static int
syncprov_qresp( opcookie *opc, syncops *so, int mode )
@ -703,214 +920,39 @@ syncprov_qresp( opcookie *opc, syncops *so, int mode )
sr->s_csn.bv_len = opc->sctxcsn.bv_len;
strcpy( sr->s_csn.bv_val, opc->sctxcsn.bv_val );
ldap_pvt_thread_mutex_lock( &so->s_mutex );
if ( !so->s_res ) {
so->s_res = sr;
} else {
so->s_restail->s_next = sr;
}
so->s_restail = sr;
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
return LDAP_SUCCESS;
}
/* Play back queued responses */
static int
syncprov_sendresp( Operation *op, opcookie *opc, syncops *so, Entry **e, int mode, int queue );
static int
syncprov_qplay( Operation *op, slap_overinst *on, syncops *so )
{
syncres *sr, *srnext;
Entry *e;
opcookie opc;
int rc;
opc.son = on;
op->o_bd->bd_info = (BackendInfo *)on->on_info;
for (sr = so->s_res; sr; sr=srnext) {
srnext = sr->s_next;
opc.sdn = sr->s_dn;
opc.sndn = sr->s_ndn;
opc.suuid = sr->s_uuid;
opc.sctxcsn = sr->s_csn;
opc.sreference = sr->s_isreference;
e = NULL;
if ( sr->s_mode != LDAP_SYNC_DELETE ) {
rc = be_entry_get_rw( op, &opc.sndn, NULL, NULL, 0, &e );
if ( rc ) {
ch_free( sr );
so->s_res = srnext;
continue;
/* If the base of the psearch was modified, check it next time round */
if ( so->s_flags & PS_WROTE_BASE ) {
so->s_flags ^= PS_WROTE_BASE;
so->s_flags |= PS_FIND_BASE;
}
if ( so->s_flags & PS_IS_DETACHED ) {
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
if ( !so->s_qtask ) {
so->s_qtask = ldap_pvt_runqueue_insert( &slapd_rq, RUNQ_INTERVAL,
syncprov_qtask, so, "syncprov_qtask",
so->s_op->o_conn->c_peer_name.bv_val );
++so->s_inuse;
} else {
if (!ldap_pvt_runqueue_isrunning( &slapd_rq, so->s_qtask ) &&
!so->s_qtask->next_sched.tv_sec ) {
so->s_qtask->interval.tv_sec = 0;
ldap_pvt_runqueue_resched( &slapd_rq, so->s_qtask, 0 );
so->s_qtask->interval.tv_sec = RUNQ_INTERVAL;
++so->s_inuse;
}
}
rc = syncprov_sendresp( op, &opc, so, &e, sr->s_mode, 0 );
if ( e ) {
be_entry_release_rw( op, e, 0 );
}
if ( rc )
break;
ch_free( sr );
so->s_res = srnext;
}
op->o_bd->bd_info = (BackendInfo *)on;
if ( !so->s_res )
so->s_restail = NULL;
return rc;
}
/* Send a persistent search response */
static int
syncprov_sendresp( Operation *op, opcookie *opc, syncops *so, Entry **e, int mode, int queue )
{
slap_overinst *on = opc->son;
SlapReply rs = { REP_SEARCH };
LDAPControl *ctrls[2];
struct berval cookie;
Entry e_uuid = {0};
Attribute a_uuid = {0};
Operation sop = *so->s_op;
Opheader ohdr;
if ( so->s_op->o_abandon )
return SLAPD_ABANDON;
ohdr = *sop.o_hdr;
sop.o_hdr = &ohdr;
sop.o_tmpmemctx = op->o_tmpmemctx;
sop.o_bd = op->o_bd;
sop.o_controls = op->o_controls;
sop.o_private = op->o_private;
sop.o_callback = NULL;
/* If queueing is allowed */
if ( queue ) {
ldap_pvt_thread_mutex_lock( &so->s_mutex );
/* If we're still in refresh mode, must queue */
if (so->s_flags & PS_IS_REFRESHING) {
return syncprov_qresp( opc, so, mode );
}
/* If connection is free but queue is non-empty,
* try to flush the queue.
*/
if ( so->s_res ) {
rs.sr_err = syncprov_qplay( &sop, on, so );
}
/* If the connection is busy, must queue */
if ( sop.o_conn->c_writewaiter || rs.sr_err == LDAP_BUSY ) {
return syncprov_qresp( opc, so, mode );
}
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
/* If syncprov_qplay returned any other error, bail out. */
if ( rs.sr_err ) {
return rs.sr_err;
}
} else {
/* Queueing not allowed and conn is busy, give up */
if ( sop.o_conn->c_writewaiter )
return LDAP_BUSY;
}
ctrls[1] = NULL;
slap_compose_sync_cookie( op, &cookie, &opc->sctxcsn, so->s_rid );
e_uuid.e_attrs = &a_uuid;
a_uuid.a_desc = slap_schema.si_ad_entryUUID;
a_uuid.a_nvals = &opc->suuid;
rs.sr_err = syncprov_state_ctrl( &sop, &rs, &e_uuid,
mode, ctrls, 0, 1, &cookie );
rs.sr_ctrls = ctrls;
op->o_bd->bd_info = (BackendInfo *)on->on_info;
switch( mode ) {
case LDAP_SYNC_ADD:
rs.sr_entry = *e;
if ( rs.sr_entry->e_private )
rs.sr_flags = REP_ENTRY_MUSTRELEASE;
if ( opc->sreference ) {
rs.sr_ref = get_entry_referrals( &sop, rs.sr_entry );
send_search_reference( &sop, &rs );
ber_bvarray_free( rs.sr_ref );
if ( !rs.sr_entry )
*e = NULL;
break;
}
/* fallthru */
case LDAP_SYNC_MODIFY:
rs.sr_entry = *e;
if ( rs.sr_entry->e_private )
rs.sr_flags = REP_ENTRY_MUSTRELEASE;
rs.sr_attrs = sop.ors_attrs;
send_search_entry( &sop, &rs );
if ( !rs.sr_entry )
*e = NULL;
break;
case LDAP_SYNC_DELETE:
e_uuid.e_attrs = NULL;
e_uuid.e_name = opc->sdn;
e_uuid.e_nname = opc->sndn;
rs.sr_entry = &e_uuid;
if ( opc->sreference ) {
struct berval bv = BER_BVNULL;
rs.sr_ref = &bv;
send_search_reference( &sop, &rs );
} else {
send_search_entry( &sop, &rs );
}
break;
default:
assert(0);
}
op->o_tmpfree( rs.sr_ctrls[0], op->o_tmpmemctx );
op->o_private = sop.o_private;
rs.sr_ctrls = NULL;
/* Check queue again here; if we were hanging in a send and eventually
* recovered, there may be more to send now. But don't check if the
* original psearch has been abandoned.
*/
if ( so->s_op->o_abandon )
return SLAPD_ABANDON;
if ( rs.sr_err == LDAP_SUCCESS && queue && so->s_res ) {
ldap_pvt_thread_mutex_lock( &so->s_mutex );
rs.sr_err = syncprov_qplay( &sop, on, so );
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
}
return rs.sr_err;
}
static void
syncprov_free_syncop( syncops *so )
{
syncres *sr, *srnext;
GroupAssertion *ga, *gnext;
ldap_pvt_thread_mutex_lock( &so->s_mutex );
so->s_inuse--;
if ( so->s_inuse > 0 ) {
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
return;
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
}
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
if ( so->s_flags & PS_IS_DETACHED ) {
filter_free( so->s_op->ors_filter );
for ( ga = so->s_op->o_groups; ga; ga=gnext ) {
gnext = ga->ga_next;
ch_free( ga );
}
ch_free( so->s_op );
}
ch_free( so->s_base.bv_val );
for ( sr=so->s_res; sr; sr=srnext ) {
srnext = sr->s_next;
ch_free( sr );
}
ldap_pvt_thread_mutex_destroy( &so->s_mutex );
ch_free( so );
return LDAP_SUCCESS;
}
static int
@ -1019,15 +1061,18 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
e = op->ora_e;
}
if ( saveit ) {
if ( saveit || op->o_tag == LDAP_REQ_ADD ) {
ber_dupbv_x( &opc->sdn, &e->e_name, op->o_tmpmemctx );
ber_dupbv_x( &opc->sndn, &e->e_nname, op->o_tmpmemctx );
opc->sreference = is_entry_referral( e );
}
if ( saveit || op->o_tag == LDAP_REQ_ADD ) {
a = attr_find( e->e_attrs, slap_schema.si_ad_entryUUID );
if ( a )
ber_dupbv_x( &opc->suuid, &a->a_nvals[0], op->o_tmpmemctx );
} else if ( op->o_tag == LDAP_REQ_MODRDN && !saveit ) {
op->o_tmpfree( opc->sndn.bv_val, op->o_tmpmemctx );
op->o_tmpfree( opc->sdn.bv_val, op->o_tmpmemctx );
ber_dupbv_x( &opc->sdn, &e->e_name, op->o_tmpmemctx );
ber_dupbv_x( &opc->sndn, &e->e_nname, op->o_tmpmemctx );
}
ldap_pvt_thread_mutex_lock( &si->si_ops_mutex );
@ -1055,9 +1100,18 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
continue;
}
/* If we're sending results now, look for this op in old matches */
if ( !saveit ) {
syncmatches *old;
/* Did we modify the search base? */
if ( dn_match( &op->o_req_ndn, &ss->s_base )) {
ldap_pvt_thread_mutex_lock( &ss->s_mutex );
ss->s_flags |= PS_WROTE_BASE;
ldap_pvt_thread_mutex_unlock( &ss->s_mutex );
}
for ( sm=opc->smatches, old=(syncmatches *)&opc->smatches; sm;
old=sm, sm=sm->sm_next ) {
if ( sm->sm_op == ss ) {
@ -1076,22 +1130,18 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
sm = op->o_tmpalloc( sizeof(syncmatches), op->o_tmpmemctx );
sm->sm_next = opc->smatches;
sm->sm_op = ss;
ss->s_inuse++;
ldap_pvt_thread_mutex_lock( &ss->s_mutex );
++ss->s_inuse;
ldap_pvt_thread_mutex_unlock( &ss->s_mutex );
opc->smatches = sm;
} else {
/* if found send UPDATE else send ADD */
ss->s_inuse++;
ldap_pvt_thread_mutex_unlock( &si->si_ops_mutex );
syncprov_sendresp( op, opc, ss, &e,
found ? LDAP_SYNC_MODIFY : LDAP_SYNC_ADD, 1 );
ldap_pvt_thread_mutex_lock( &si->si_ops_mutex );
ss->s_inuse--;
syncprov_qresp( opc, ss,
found ? LDAP_SYNC_MODIFY : LDAP_SYNC_ADD );
}
} else if ( !saveit && found ) {
/* send DELETE */
ldap_pvt_thread_mutex_unlock( &si->si_ops_mutex );
syncprov_sendresp( op, opc, ss, NULL, LDAP_SYNC_DELETE, 1 );
ldap_pvt_thread_mutex_lock( &si->si_ops_mutex );
syncprov_qresp( opc, ss, LDAP_SYNC_DELETE );
}
}
ldap_pvt_thread_mutex_unlock( &si->si_ops_mutex );
@ -1444,8 +1494,7 @@ syncprov_op_response( Operation *op, SlapReply *rs )
for ( sm = opc->smatches; sm; sm=sm->sm_next ) {
if ( sm->sm_op->s_op->o_abandon )
continue;
syncprov_sendresp( op, opc, sm->sm_op, NULL,
LDAP_SYNC_DELETE, 1 );
syncprov_qresp( opc, sm->sm_op, LDAP_SYNC_DELETE );
}
break;
}
@ -1633,7 +1682,7 @@ syncprov_search_cleanup( Operation *op, SlapReply *rs )
}
static void
syncprov_detach_op( Operation *op, syncops *so )
syncprov_detach_op( Operation *op, syncops *so, slap_overinst *on )
{
Operation *op2;
int i, alen = 0;
@ -1659,8 +1708,9 @@ syncprov_detach_op( Operation *op, syncops *so )
*op2->o_hdr = *op->o_hdr;
op2->o_tag = op->o_tag;
op2->o_time = op->o_time;
op2->o_bd = op->o_bd;
op2->o_bd = on->on_info->oi_origdb;
op2->o_request = op->o_request;
op2->o_private = on;
if ( i ) {
op2->ors_attrs = (AttributeName *)(op2->o_hdr + 1);
@ -1761,25 +1811,19 @@ syncprov_search_response( Operation *op, SlapReply *rs )
0, 1, &cookie, ss->ss_present ? LDAP_SYNC_REFRESH_PRESENTS :
LDAP_SYNC_REFRESH_DELETES );
} else {
int locked = 0;
/* It's RefreshAndPersist, transition to Persist phase */
syncprov_sendinfo( op, rs, ( ss->ss_present && rs->sr_nentries ) ?
LDAP_TAG_SYNC_REFRESH_PRESENT : LDAP_TAG_SYNC_REFRESH_DELETE,
&cookie, 1, NULL, 0 );
/* Flush any queued persist messages */
if ( ss->ss_so->s_res ) {
ldap_pvt_thread_mutex_lock( &ss->ss_so->s_mutex );
locked = 1;
syncprov_qplay( op, on, ss->ss_so );
}
/* Detach this Op from frontend control */
ldap_pvt_thread_mutex_lock( &ss->ss_so->s_mutex );
/* Turn off the refreshing flag */
ss->ss_so->s_flags ^= PS_IS_REFRESHING;
if ( locked )
ldap_pvt_thread_mutex_unlock( &ss->ss_so->s_mutex );
/* Detach this Op from frontend control */
syncprov_detach_op( op, ss->ss_so );
syncprov_detach_op( op, ss->ss_so, on );
ldap_pvt_thread_mutex_unlock( &ss->ss_so->s_mutex );
return LDAP_SUCCESS;
}
@ -1824,7 +1868,7 @@ syncprov_op_search( Operation *op, SlapReply *rs )
fc.fbase = 0;
so.s_eid = NOID;
so.s_op = op;
so.s_flags = PS_IS_REFRESHING;
so.s_flags = PS_IS_REFRESHING | PS_FIND_BASE;
/* syncprov_findbase expects to be called as a callback... */
sc.sc_private = &opc;
opc.son = on;

View file

@ -347,6 +347,7 @@ static int unique_search(
nop->o_req_ndn = ud->dn;
nop->o_ndn = op->o_bd->be_rootndn;
nop->o_bd = on->on_info->oi_origdb;
rc = nop->o_bd->be_search(nop, &nrs);
filter_free_x(nop, nop->ors_filter);
ch_free( key );
@ -384,21 +385,8 @@ static int unique_add(
Debug(LDAP_DEBUG_TRACE, "==> unique_add <%s>\n", op->o_req_dn.bv_val, 0, 0);
/* validate backend. Should have already been done, but whatever */
nop.o_bd = select_backend(&ud->dn, 0, 1);
if(nop.o_bd) {
if (!nop.o_bd->be_search) {
op->o_bd->bd_info = (BackendInfo *) on->on_info;
send_ldap_error(op, rs, LDAP_UNWILLING_TO_PERFORM,
"backend missing search function");
return(rs->sr_err);
}
} else {
op->o_bd->bd_info = (BackendInfo *) on->on_info;
send_ldap_error(op, rs, LDAP_OTHER,
"no known backend? this shouldn't be happening!");
return(rs->sr_err);
}
if ( !dnIsSuffix( &op->o_req_ndn, &ud->dn ))
return SLAP_CB_CONTINUE;
/*
** count everything first;
@ -447,20 +435,8 @@ static int unique_modify(
Debug(LDAP_DEBUG_TRACE, "==> unique_modify <%s>\n", op->o_req_dn.bv_val, 0, 0);
nop.o_bd = select_backend(&ud->dn, 0, 1);
if(nop.o_bd) {
if (!nop.o_bd->be_search) {
op->o_bd->bd_info = (BackendInfo *) on->on_info;
send_ldap_error(op, rs, LDAP_UNWILLING_TO_PERFORM,
"backend missing search function");
return(rs->sr_err);
}
} else {
op->o_bd->bd_info = (BackendInfo *) on->on_info;
send_ldap_error(op, rs, LDAP_OTHER,
"no known backend? this shouldn't be happening!");
return(rs->sr_err);
}
if ( !dnIsSuffix( &op->o_req_ndn, &ud->dn ))
return SLAP_CB_CONTINUE;
/*
** count everything first;
@ -513,20 +489,9 @@ static int unique_modrdn(
Debug(LDAP_DEBUG_TRACE, "==> unique_modrdn <%s> <%s>\n",
op->o_req_dn.bv_val, op->orr_newrdn.bv_val, 0);
nop.o_bd = select_backend(&ud->dn, 0, 1);
if(nop.o_bd) {
if (!nop.o_bd->be_search) {
op->o_bd->bd_info = (BackendInfo *) on->on_info;
send_ldap_error(op, rs, LDAP_UNWILLING_TO_PERFORM,
"backend missing search function");
return(rs->sr_err);
}
} else {
op->o_bd->bd_info = (BackendInfo *) on->on_info;
send_ldap_error(op, rs, LDAP_OTHER,
"no known backend? this shouldn't be happening!");
return(rs->sr_err);
}
if ( !dnIsSuffix( &op->o_req_ndn, &ud->dn ) &&
(!op->orr_nnewSup || !dnIsSuffix( &op->orr_nnewSup, &ud->dn )))
return SLAP_CB_CONTINUE;
if(ldap_bv2rdn_x(&op->oq_modrdn.rs_newrdn, &newrdn,
(char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx )) {

View file

@ -68,9 +68,7 @@ int passwd_extop(
return LDAP_STRONG_AUTH_REQUIRED;
}
qpw->rs_old.bv_len = 0;
qpw->rs_old.bv_val = NULL;
qpw->rs_new.bv_len = 0;
qpw->rs_new.bv_val = NULL;
qpw->rs_mods = NULL;
qpw->rs_modtail = NULL;
@ -84,8 +82,10 @@ int passwd_extop(
qpw->rs_old.bv_val ? " old" : "",
qpw->rs_new.bv_val ? " new" : "", 0 );
} else {
Statslog( LDAP_DEBUG_STATS, "%s PASSMOD\n",
op->o_log_prefix, 0, 0, 0, 0 );
Statslog( LDAP_DEBUG_STATS, "%s PASSMOD %s%s\n",
op->o_log_prefix,
qpw->rs_old.bv_val ? " old" : "",
qpw->rs_new.bv_val ? " new" : "", 0, 0 );
}
if ( rs->sr_err != LDAP_SUCCESS ) {
@ -209,11 +209,27 @@ int passwd_extop(
}
if ( qpw->rs_old.bv_val != NULL ) {
Entry *e = NULL;
rc = be_entry_get_rw( op, &op->o_req_ndn, NULL,
slap_schema.si_ad_userPassword, 0, &e );
if ( rc == LDAP_SUCCESS && e ) {
Attribute *a = attr_find( e->e_attrs,
slap_schema.si_ad_userPassword );
if ( a )
rc = slap_passwd_check( op, e, a, &qpw->rs_old, &rs->sr_text );
else
rc = 1;
be_entry_release_r( op, e );
if ( rc == LDAP_SUCCESS )
goto old_good;
}
rs->sr_text = "unwilling to verify old password";
rc = LDAP_UNWILLING_TO_PERFORM;
goto error_return;
}
old_good:
ml = ch_malloc( sizeof(Modifications) );
if ( !qpw->rs_modtail ) qpw->rs_modtail = &ml->sml_next;

View file

@ -2274,6 +2274,7 @@ typedef struct slap_overinst {
typedef struct slap_overinfo {
BackendInfo oi_bi;
BackendInfo *oi_orig;
BackendDB *oi_origdb;
struct slap_overinst *oi_list;
} slap_overinfo;

View file

@ -2227,10 +2227,11 @@ dn_callback(
* discover if the deleteOldRdn argument applies here. It
* would save an unnecessary Modify if we detected it, but
* that's a fair amount of trouble to compare the two attr
* lists in detail.
* lists in detail. (Just test normalized DN; we ignore
* insignificant changes here.)
*/
if ( !dn_match( &rs->sr_entry->e_name,
&dni->new_entry->e_name ) )
if ( !dn_match( &rs->sr_entry->e_nname,
&dni->new_entry->e_nname ) )
{
dni->renamed = 1;
}