]> git.sur5r.net Git - openldap/commitdiff
Sync with HEAD
authorKurt Zeilenga <kurt@openldap.org>
Wed, 5 Oct 2005 19:42:19 +0000 (19:42 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Wed, 5 Oct 2005 19:42:19 +0000 (19:42 +0000)
19 files changed:
CHANGES
doc/man/man5/slapd-meta.5
libraries/libldap/cyrus.c
libraries/libldap/tls.c
libraries/libldap/unbind.c
libraries/liblutil/csn.c
servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/bind.c
servers/slapd/back-meta/conn.c
servers/slapd/back-meta/init.c
servers/slapd/back-sql/schema-map.c
servers/slapd/backend.c
servers/slapd/backover.c
servers/slapd/overlays/accesslog.c
servers/slapd/overlays/syncprov.c
servers/slapd/overlays/unique.c
servers/slapd/passwd.c
servers/slapd/slap.h
servers/slapd/syncrepl.c

diff --git a/CHANGES b/CHANGES
index 45b863c4a58a0291599aba77b57a8188601e6b5f..859b1708d177b3f00dbf7cc7d86b2ae214d94d1a 100644 (file)
--- a/CHANGES
+++ b/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
index 9c61bb15d1283a46a1c3443a8d4ca984828cf7db..548e9a2bbcd5ea384930c1bea781119df966b4fe 100644 (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.
index 564cee70726c602bc14e93eb788dfcdb5cbe92fd..99893b285d87ccbd01bcae215868ffc8b23d57ce 100644 (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 );
index 5e43f8aeb6ae26c1267b066588b04e6a9518d041..71a5e33d20b6f14a752976d0ca622ccc08386afd 100644 (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);
index 3d92fc507653bfda4ed45e1573b80fe5411fdf10..86b9ab2baa13fd17ca855ca50fee525778d1ad21 100644 (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;
index b6a43ddb3340dd478ad9cb09a10a3c9666be6a7f..4dcfc68079480bece55aafccf20769fc872f4395 100644 (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 );
index 5a7f92e1c2dca5046f9eb2ea5b250b960f2b8755..5d1911d3ed0d5eb6e44dff746e5bd6ff824822e2 100644 (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
index 17dab2f39712ceb34df2f693cf95ef7b93b62f0e..2106a2d7e539964e82ac3aeed9a71f5c7f1930fb 100644 (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 {
index 0c8d140166ad33eba1676524c58b451fff3a7607..1d0a548958edfb671cdfe210ab6b75f2e0805a1a 100644 (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;
-               }
 
-               /* 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 );
+       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 );
                }
 
-               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 );
 
index fb2b0d50ceb888241511c95a434b30397b052c47..3f71a429f25882e9ca123a5474241d74e4404e5e 100644 (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 );
                }
 
                /*
index 02a73924cedaa9a2aefe538f122360b7677a1f67..ae97d27cf0e53ab9be99587cc9d8500e4c67fce5 100644 (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 );
index f6f868a30d52d0b061e65f49992eb8b010aba4c6..77dcf4a422b7eb562738fb6e564b50a26b8820da 100644 (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;
                        }
index 4f5d1042f92a2cb4367dce7d72a4cbfbf7d994e6..054edbe11ab1fbf3cdef36d4f3c903fd83e011e2 100644 (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
index 2cbda0046eaf84b1b94a1419d70f5a2da4406e66..88500027f888fbe35b307330f6a0238f6edad991 100644 (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 ) {
index 05f56c447de41e0a5df8e2a814d1524c0ccdc816..4316dd042d959d638a6864958ca9977a3b099426 100644 (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,90 +697,38 @@ again:
        return rc;
 }
 
-/* Queue a persistent search response */
-static int
-syncprov_qresp( opcookie *opc, syncops *so, int mode )
+static void
+syncprov_free_syncop( syncops *so )
 {
-       syncres *sr;
-
-       sr = ch_malloc(sizeof(syncres) + opc->suuid.bv_len + 1 +
-               opc->sdn.bv_len + 1 + opc->sndn.bv_len + 1 + opc->sctxcsn.bv_len + 1 );
-       sr->s_next = NULL;
-       sr->s_dn.bv_val = (char *)(sr + 1);
-       sr->s_dn.bv_len = opc->sdn.bv_len;
-       sr->s_mode = mode;
-       sr->s_isreference = opc->sreference;
-       sr->s_ndn.bv_val = lutil_strcopy( sr->s_dn.bv_val, opc->sdn.bv_val );
-       sr->s_ndn.bv_len = opc->sndn.bv_len;
-       *(sr->s_ndn.bv_val++) = '\0';
-       sr->s_uuid.bv_val = lutil_strcopy( sr->s_ndn.bv_val, opc->sndn.bv_val );
-       sr->s_uuid.bv_len = opc->suuid.bv_len;
-       *(sr->s_uuid.bv_val++) = '\0';
-       sr->s_csn.bv_val = lutil_strcopy( sr->s_uuid.bv_val, opc->suuid.bv_val );
-       sr->s_csn.bv_len = opc->sctxcsn.bv_len;
-       strcpy( sr->s_csn.bv_val, opc->sctxcsn.bv_val );
+       syncres *sr, *srnext;
+       GroupAssertion *ga, *gnext;
 
-       if ( !so->s_res ) {
-               so->s_res = sr;
-       } else {
-               so->s_restail->s_next = sr;
+       ldap_pvt_thread_mutex_lock( &so->s_mutex );
+       if ( --so->s_inuse > 0 ) {
+               ldap_pvt_thread_mutex_unlock( &so->s_mutex );
+               return;
        }
-       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;
-                       }
-               }
-               rc = syncprov_sendresp( op, &opc, so, &e, sr->s_mode, 0 );
-
-               if ( e ) {
-                       be_entry_release_rw( op, e, 0 );
+       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 );
                }
-               if ( rc )
-                       break;
-
+               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 );
-               so->s_res = srnext;
        }
-       op->o_bd->bd_info = (BackendInfo *)on;
-       if ( !so->s_res )
-               so->s_restail = NULL;
-       return rc;
+       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, int queue )
+syncprov_sendresp( Operation *op, opcookie *opc, syncops *so, Entry **e, int mode)
 {
        slap_overinst *on = opc->son;
 
@@ -772,56 +737,17 @@ syncprov_sendresp( Operation *op, opcookie *opc, syncops *so, Entry **e, int mod
        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,
+       rs.sr_err = syncprov_state_ctrl( op, &rs, &e_uuid,
                mode, ctrls, 0, 1, &cookie );
 
        rs.sr_ctrls = ctrls;
@@ -832,8 +758,8 @@ syncprov_sendresp( Operation *op, opcookie *opc, syncops *so, Entry **e, int mod
                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 );
+                       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;
@@ -844,8 +770,8 @@ syncprov_sendresp( Operation *op, opcookie *opc, syncops *so, Entry **e, int mod
                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 );
+               rs.sr_attrs = op->ors_attrs;
+               send_search_entry( op, &rs );
                if ( !rs.sr_entry )
                        *e = NULL;
                break;
@@ -857,60 +783,176 @@ syncprov_sendresp( Operation *op, opcookie *opc, syncops *so, Entry **e, int mod
                if ( opc->sreference ) {
                        struct berval bv = BER_BVNULL;
                        rs.sr_ref = &bv;
-                       send_search_reference( &sop, &rs );
+                       send_search_reference( op, &rs );
                } else {
-                       send_search_entry( &sop, &rs );
+                       send_search_entry( op, &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;
+       /* 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;
+       }
 
-       if ( rs.sr_err == LDAP_SUCCESS && queue && so->s_res ) {
+       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 );
-               rs.sr_err = syncprov_qplay( &sop, on, so );
+               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;
        }
-       return rs.sr_err;
+       op->o_bd->bd_info = (BackendInfo *)on;
+       return rc;
 }
 
-static void
-syncprov_free_syncop( syncops *so )
+/* runqueue task for playing back queued responses */
+static void *
+syncprov_qtask( void *ctx, void *arg )
 {
-       syncres *sr, *srnext;
-       GroupAssertion *ga, *gnext;
+       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 )
+{
+       syncres *sr;
+
+       sr = ch_malloc(sizeof(syncres) + opc->suuid.bv_len + 1 +
+               opc->sdn.bv_len + 1 + opc->sndn.bv_len + 1 + opc->sctxcsn.bv_len + 1 );
+       sr->s_next = NULL;
+       sr->s_dn.bv_val = (char *)(sr + 1);
+       sr->s_dn.bv_len = opc->sdn.bv_len;
+       sr->s_mode = mode;
+       sr->s_isreference = opc->sreference;
+       sr->s_ndn.bv_val = lutil_strcopy( sr->s_dn.bv_val, opc->sdn.bv_val );
+       sr->s_ndn.bv_len = opc->sndn.bv_len;
+       *(sr->s_ndn.bv_val++) = '\0';
+       sr->s_uuid.bv_val = lutil_strcopy( sr->s_ndn.bv_val, opc->sndn.bv_val );
+       sr->s_uuid.bv_len = opc->suuid.bv_len;
+       *(sr->s_uuid.bv_val++) = '\0';
+       sr->s_csn.bv_val = lutil_strcopy( sr->s_uuid.bv_val, opc->suuid.bv_val );
+       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 );
-       so->s_inuse--;
-       if ( so->s_inuse > 0 ) {
-               ldap_pvt_thread_mutex_unlock( &so->s_mutex );
-               return;
+       if ( !so->s_res ) {
+               so->s_res = sr;
+       } else {
+               so->s_restail->s_next = sr;
+       }
+       so->s_restail = sr;
+
+       /* 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;
        }
-       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 );
+               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;
+                       }
                }
-               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_unlock( &slapd_rq.rq_mutex );
        }
-       ldap_pvt_thread_mutex_destroy( &so->s_mutex );
-       ch_free( so );
+       ldap_pvt_thread_mutex_unlock( &so->s_mutex );
+       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;
index 9668b4b9457598eee0af03264642ede2ad9865c1..f80a1c35fed9e3285a9c7f2d1f7c15a2fba856ba 100644 (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 )) {
index 385e2be3c1c46480642787a7fa592314979d557b..c8f8ce75b510b2e3350c61250f5857221eacf7b6 100644 (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;
 
index bf02fa366625a1aa6129bf8ab1d1273a57245e18..0d4a7fb9835dcdd580c4fc888c40785d266e9d0a 100644 (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;
 
index 429638165d3516e79146d68f203d8dfaf832fe11..2a4220be9a8c1a0b2943b5b40670a542267c2c6d 100644 (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;
                                }