mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-02-18 18:18:06 -05:00
Sync with HEAD
This commit is contained in:
parent
bf637ea2a9
commit
164d5c2d0f
19 changed files with 519 additions and 454 deletions
2
CHANGES
2
CHANGES
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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, <m_buf );
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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, ×tamp );
|
||||
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, ×tamp, &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, ×tamp, NULL );
|
||||
attr_merge_one( e, ad_reqStart, ×tamp, &ntimestamp );
|
||||
op->o_tmpfree( ntimestamp.bv_val, op->o_tmpmemctx );
|
||||
|
||||
/* Exops have OID appended */
|
||||
if ( logop == LOG_EN_EXTENDED ) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 )) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue