]> git.sur5r.net Git - openldap/commitdiff
Sync with HEAD
authorKurt Zeilenga <kurt@openldap.org>
Mon, 14 Mar 2005 23:24:58 +0000 (23:24 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Mon, 14 Mar 2005 23:24:58 +0000 (23:24 +0000)
59 files changed:
servers/slapd/back-ldap/back-ldap.h
servers/slapd/back-ldap/bind.c
servers/slapd/back-ldap/chain.c
servers/slapd/back-ldap/config.c
servers/slapd/back-ldap/search.c
servers/slapd/back-ldbm/modrdn.c
servers/slapd/back-ldbm/search.c
servers/slapd/back-ldif/Makefile.in [new file with mode: 0644]
servers/slapd/back-ldif/ldif.c [new file with mode: 0644]
servers/slapd/back-meta/add.c
servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/bind.c
servers/slapd/back-meta/compare.c
servers/slapd/back-meta/config.c
servers/slapd/back-meta/conn.c
servers/slapd/back-meta/delete.c
servers/slapd/back-meta/modify.c
servers/slapd/back-meta/modrdn.c
servers/slapd/back-meta/search.c
servers/slapd/back-monitor/database.c
servers/slapd/back-passwd/search.c
servers/slapd/back-sql/back-sql.h
servers/slapd/back-sql/search.c
servers/slapd/bconfig.c
servers/slapd/overlays/Makefile.in
servers/slapd/overlays/glue.c
servers/slapd/overlays/overlays.c
servers/slapd/overlays/rwm.c
servers/slapd/overlays/rwmmap.c
servers/slapd/overlays/syncprov.c
servers/slapd/overlays/translucent.c [new file with mode: 0644]
servers/slapd/overlays/unique.c
servers/slapd/slap.h
servers/slapd/slapi/plugin.c
servers/slapd/slapi/proto-slapi.h
servers/slapd/slapi/slapi.h
servers/slapd/slapi/slapi_pblock.c
tests/data/modify.out.master
tests/data/relay.out
tests/data/slapd-ldapgluegroups.conf
tests/data/slapd-ldapgluepeople.conf
tests/data/slapd-pw.conf
tests/data/slapd-translucent-local.conf [new file with mode: 0644]
tests/data/slapd-translucent-remote.conf [new file with mode: 0644]
tests/data/slapd-whoami.conf
tests/data/slapd.conf
tests/data/test-translucent-add.ldif [new file with mode: 0644]
tests/data/test-translucent-config.ldif [new file with mode: 0644]
tests/data/test-translucent-data.ldif [new file with mode: 0644]
tests/data/test-translucent-merged.ldif [new file with mode: 0644]
tests/data/test.schema
tests/run.in
tests/scripts/conf.sh
tests/scripts/defines.sh
tests/scripts/relay
tests/scripts/test004-modify
tests/scripts/test010-passwd
tests/scripts/test031-component-filter
tests/scripts/test034-translucent [new file with mode: 0755]

index f881c387495f499e684b0cf691884c8682b04d35..48b2e949ad14c4f1e718cfd72ec087037dbf5d00 100644 (file)
@@ -94,8 +94,16 @@ struct ldapinfo {
 #define LDAP_BACK_F_NONE               0x00U
 #define LDAP_BACK_F_SAVECRED           0x01U
 #define LDAP_BACK_F_USE_TLS            0x02U
-#define LDAP_BACK_F_TLS_CRITICAL       ( 0x04U | LDAP_BACK_F_USE_TLS )
-#define LDAP_BACK_F_CHASE_REFERRALS    0x8U
+#define LDAP_BACK_F_PROPAGATE_TLS      0x04U
+#define LDAP_BACK_F_TLS_CRITICAL       0x08U
+#define LDAP_BACK_F_CHASE_REFERRALS    0x10U
+
+#define LDAP_BACK_SAVECRED(li)         ( (li)->flags & LDAP_BACK_F_SAVECRED )
+#define LDAP_BACK_USE_TLS(li)          ( (li)->flags & LDAP_BACK_F_USE_TLS )
+#define LDAP_BACK_PROPAGATE_TLS(li)    ( (li)->flags & LDAP_BACK_F_PROPAGATE_TLS )
+#define LDAP_BACK_TLS_CRITICAL(li)     ( (li)->flags & LDAP_BACK_F_TLS_CRITICAL )
+#define LDAP_BACK_CHASE_REFERRALS(li)  ( (li)->flags & LDAP_BACK_F_CHASE_REFERRALS )
+
        Avlnode         *conntree;
 
        int             rwm_started;
index 817235ee3a36d7d957bac16540b95c534bbe6111..446ce1c458a74c0765857f0782154de1545b1d99 100644 (file)
@@ -87,7 +87,7 @@ ldap_back_bind( Operation *op, SlapReply *rs )
                lc->lc_bound = 1;
                ber_dupbv( &lc->lc_bound_ndn, &op->o_req_ndn );
 
-               if ( li->flags & LDAP_BACK_F_SAVECRED ) {
+               if ( LDAP_BACK_SAVECRED( li ) ) {
                        if ( !BER_BVISNULL( &lc->lc_cred ) ) {
                                memset( lc->lc_cred.bv_val, 0,
                                                lc->lc_cred.bv_len );
@@ -241,27 +241,99 @@ ldap_back_prepare_conn( struct ldapconn **lcp, Operation *op, SlapReply *rs, lda
         */
        ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, (const void *)&vers );
 
-       /* automatically chase referrals ("chase-referrals"/"dont-chase-referrals" statement) */
-       if ( li->flags & LDAP_BACK_F_CHASE_REFERRALS ) {
+       /* automatically chase referrals ("[dont-]chase-referrals" statement) */
+       if ( LDAP_BACK_CHASE_REFERRALS( li ) ) {
                ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON );
        }
 
-       /* start TLS ("start-tls"/"try-start-tls" statements) */
-       if ( ( li->flags & LDAP_BACK_F_USE_TLS )
-                       && !ldap_is_ldaps_url( li->url )
-                       && ( rs->sr_err = ldap_start_tls_s( ld, NULL, NULL ) ) != LDAP_SUCCESS )
+#ifdef HAVE_TLS
+       /* start TLS ("tls-[try-]{start,propagate}" statements) */
+       if ( ( LDAP_BACK_USE_TLS( li ) || ( op->o_conn->c_is_tls && LDAP_BACK_PROPAGATE_TLS( li ) ) )
+                               && !ldap_is_ldaps_url( li->url ) )
        {
+#if 1
+               /*
+                * use asynchronous StartTLS
+                * in case, chase referral (not implemented yet)
+                */
+               int             msgid;
+
+               rs->sr_err = ldap_start_tls( ld, NULL, NULL, &msgid );
+               if ( rs->sr_err == LDAP_SUCCESS ) {
+                       LDAPMessage     *res = NULL;
+                       int             rc, retries = 1;
+                       struct timeval  tv = { 0, 0 };
+
+retry:;
+                       rc = ldap_result( ld, msgid, LDAP_MSG_ALL, &tv, &res );
+                       if ( rc < 0 ) {
+                               rs->sr_err = LDAP_OTHER;
+
+                       } else if ( rc == 0 ) {
+                               if ( retries ) {
+                                       retries--;
+                                       tv.tv_sec = 0;
+                                       tv.tv_usec = 100000;
+                                       goto retry;
+                               }
+                               rs->sr_err = LDAP_OTHER;
+
+                       } else if ( rc == LDAP_RES_EXTENDED ) {
+                               struct berval   *data = NULL;
+
+                               rs->sr_err = ldap_parse_extended_result( ld, res,
+                                               NULL, &data, 0 );
+                               if ( rs->sr_err == LDAP_SUCCESS ) {
+                                       rs->sr_err = ldap_result2error( ld, res, 1 );
+                                       res = NULL;
+                                       
+                                       /* FIXME: in case a referral 
+                                        * is returned, should we try
+                                        * using it instead of the 
+                                        * configured URI? */
+                                       if ( rs->sr_err == LDAP_SUCCESS ) {
+                                               ldap_install_tls( ld );
+
+                                       } else if ( rs->sr_err == LDAP_REFERRAL ) {
+                                               rs->sr_err = LDAP_OTHER;
+                                               rs->sr_text = "unwilling to chase referral returned by Start TLS exop";
+                                       }
+
+                                       if ( data ) {
+                                               if ( data->bv_val ) {
+                                                       ber_memfree( data->bv_val );
+                                               }
+                                               ber_memfree( data );
+                                       }
+                               }
+
+                       } else {
+                               rs->sr_err = LDAP_OTHER;
+                       }
+
+                       if ( res != NULL ) {
+                               ldap_msgfree( res );
+                       }
+               }
+#else
+               /*
+                * use synchronous StartTLS
+                */
+               rs->sr_err = ldap_start_tls_s( ld, NULL, NULL );
+#endif
+
                /* if StartTLS is requested, only attempt it if the URL
                 * is not "ldaps://"; this may occur not only in case
                 * of misconfiguration, but also when used in the chain 
                 * overlay, where the "uri" can be parsed out of a referral */
                if ( rs->sr_err == LDAP_SERVER_DOWN
-                               || ( li->flags & LDAP_BACK_F_TLS_CRITICAL ) )
+                               || ( rs->sr_err != LDAP_SUCCESS && LDAP_BACK_TLS_CRITICAL( li ) ) )
                {
                        ldap_unbind_ext_s( ld, NULL, NULL );
                        goto error_return;
                }
        }
+#endif /* HAVE_TLS */
 
        if ( *lcp == NULL ) {
                *lcp = (struct ldapconn *)ch_malloc( sizeof( struct ldapconn ) );
@@ -797,8 +869,12 @@ done:;
  * If no server-side controls are defined for the operation,
  * simply add the proxyAuthz control; otherwise, if the
  * proxyAuthz control is not already set, add it as
- * the first one (FIXME: is controls order significant
- * for security?).
+ * the first one
+ *
+ * FIXME: is controls order significant for security?
+ * ANSWER: controls ordering and interoperability
+ * must be indicated by the specs of each control; if none
+ * is specified, the order is irrelevant.
  */
 int
 ldap_back_proxy_authz_ctrl(
index 7dcb95f29fc1d36a5c1c76e6fc8b8910d4f01bf1..543960f2280cd915791c327d9dc41c849d95f530 100644 (file)
 #include "back-ldap.h"
 
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+#define SLAP_CHAINING_DEFAULT                          LDAP_CHAINING_PREFERRED
 #define SLAP_CH_RESOLVE_SHIFT                          SLAP_CONTROL_SHIFT
 #define SLAP_CH_RESOLVE_MASK                           (0x3 << SLAP_CH_RESOLVE_SHIFT)
 #define SLAP_CH_RESOLVE_CHAINING_PREFERRED             (LDAP_CHAINING_PREFERRED << SLAP_CH_RESOLVE_SHIFT)
 #define SLAP_CH_RESOLVE_CHAINING_REQUIRED              (LDAP_CHAINING_REQUIRED << SLAP_CH_RESOLVE_SHIFT)
 #define SLAP_CH_RESOLVE_REFERRALS_PREFERRED            (LDAP_REFERRALS_PREFERRED << SLAP_CH_RESOLVE_SHIFT)
 #define SLAP_CH_RESOLVE_REFERRALS_REQUIRED             (LDAP_REFERRALS_REQUIRED << SLAP_CH_RESOLVE_SHIFT)
-#define SLAP_CH_RESOLVE_DEFAULT                                SLAP_CH_RESOLVE_CHAINING_PREFERRED
+#define SLAP_CH_RESOLVE_DEFAULT                                (SLAP_CHAINING_DEFAULT << SLAP_CH_RESOLVE_SHIFT)
 #define        SLAP_CH_CONTINUATION_SHIFT                      (SLAP_CH_RESOLVE_SHIFT + 2)
 #define SLAP_CH_CONTINUATION_MASK                      (0x3 << SLAP_CH_CONTINUATION_SHIFT)
 #define SLAP_CH_CONTINUATION_CHAINING_PREFERRED                (LDAP_CHAINING_PREFERRED << SLAP_CH_CONTINUATION_SHIFT)
 #define SLAP_CH_CONTINUATION_CHAINING_REQUIRED         (LDAP_CHAINING_REQUIRED << SLAP_CH_CONTINUATION_SHIFT)
 #define SLAP_CH_CONTINUATION_REFERRALS_PREFERRED       (LDAP_REFERRALS_PREFERRED << SLAP_CH_CONTINUATION_SHIFT)
 #define SLAP_CH_CONTINUATION_REFERRALS_REQUIRED                (LDAP_REFERRALS_REQUIRED << SLAP_CH_CONTINUATION_SHIFT)
-#define SLAP_CH_CONTINUATION_DEFAULT                   SLAP_CH_CONTINUATION_CHAINING_PREFERRED
+#define SLAP_CH_CONTINUATION_DEFAULT                   (SLAP_CHAINING_DEFAULT << SLAP_CH_CONTINUATION_SHIFT)
 
 #define o_chaining                     o_ctrlflag[sc_chainingBehavior]
 #define get_chaining(op)               ((op)->o_chaining & SLAP_CONTROL_MASK)
 #define get_chainingBehavior(op)       ((op)->o_chaining & (SLAP_CH_RESOLVE_MASK|SLAP_CH_CONTINUATION_MASK))
 #define get_resolveBehavior(op)                ((op)->o_chaining & SLAP_CH_RESOLVE_MASK)
 #define get_continuationBehavior(op)   ((op)->o_chaining & SLAP_CH_CONTINUATION_MASK)
+
+static int             sc_chainingBehavior;
 #endif /*  LDAP_CONTROL_X_CHAINING_BEHAVIOR */
 
 #define        LDAP_CH_NONE                    ((void *)(0))
 #define        LDAP_CH_RES                     ((void *)(1))
 #define LDAP_CH_ERR                    ((void *)(2))
 
-static int             sc_chainingBehavior;
 static BackendInfo     *lback;
 
+typedef struct ldap_chain_t {
+       struct ldapinfo         *lc_li;
+       unsigned                lc_flags;
+#define LDAP_CHAIN_F_NONE              0x00U
+#define        LDAP_CHAIN_F_CHAINING           0x01U
+
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+       LDAPControl             lc_chaining_ctrl;
+       char                    lc_chaining_ctrlflag;
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+} ldap_chain_t;
+
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+static int
+chaining_control_add(
+               ldap_chain_t    *lc,
+               Operation       *op, 
+               LDAPControl     ***oldctrlsp )
+{
+       LDAPControl     **ctrls = NULL;
+       int             c = 0;
+
+       *oldctrlsp = op->o_ctrls;
+
+       /* default chaining control not defined */
+       if ( !( lc->lc_flags & LDAP_CHAIN_F_CHAINING ) ) {
+               return 0;
+       }
+
+       /* already present */
+       if ( get_chaining( op ) > SLAP_CONTROL_IGNORED ) {
+               return 0;
+       }
+
+       /* FIXME: check other incompatibilities */
+
+       /* add to other controls */
+       if ( op->o_ctrls ) {
+               for ( c = 0; op->o_ctrls[ c ]; c++ )
+                       /* count them */ ;
+       }
+
+       ctrls = ch_calloc( sizeof( LDAPControl *), c + 2 );
+       ctrls[ 0 ] = &lc->lc_chaining_ctrl;
+       if ( op->o_ctrls ) {
+               for ( c = 0; op->o_ctrls[ c ]; c++ ) {
+                       ctrls[ c + 1 ] = op->o_ctrls[ c ];
+               }
+       }
+       ctrls[ c + 1 ] = NULL;
+
+       op->o_ctrls = ctrls;
+
+       op->o_chaining = lc->lc_chaining_ctrlflag;
+
+       return 0;
+}
+
+static int
+chaining_control_remove(
+               Operation       *op, 
+               LDAPControl     ***oldctrlsp )
+{
+       LDAPControl     **oldctrls = *oldctrlsp;
+
+       /* we assume that the first control is the chaining control
+        * added by the chain overlay, so it's the only one we explicitly 
+        * free */
+       if ( op->o_ctrls != oldctrls ) {
+               assert( op->o_ctrls );
+               assert( op->o_ctrls[ 0 ] );
+
+               free( op->o_ctrls );
+
+               op->o_chaining = 0;
+               op->o_ctrls = oldctrls;
+       } 
+
+       *oldctrlsp = NULL;
+
+       return 0;
+}
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
 static int
 ldap_chain_operational( Operation *op, SlapReply *rs )
 {
@@ -170,14 +256,22 @@ ldap_chain_op(
        BerVarray       ref )
 {
        slap_overinst   *on = (slap_overinst *) op->o_bd->bd_info;
-       struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private;
+       ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
+       struct ldapinfo li, *lip = lc->lc_li;
 
        /* NOTE: returned if ref is empty... */
        int             rc = LDAP_OTHER;
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+       LDAPControl     **ctrls = NULL;
+       
+       (void)chaining_control_add( lc, op, &ctrls );
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
        if ( lip->url != NULL ) {
-               op->o_bd->be_private = on->on_bi.bi_private;
-               return ( *op_f )( op, rs );
+               op->o_bd->be_private = lip;
+               rc = ( *op_f )( op, rs );
+               goto done;
        }
 
        li = *lip;
@@ -245,6 +339,11 @@ Document: draft-ietf-ldapbis-protocol-27.txt
                }
        }
 
+done:;
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+       (void)chaining_control_remove( op, &ctrls );
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
        return rc;
 }
 
@@ -260,7 +359,8 @@ ldap_chain_response( Operation *op, SlapReply *rs )
        BerVarray       ref;
        struct berval   ndn = op->o_ndn;
 
-       struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private;
+       ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
+       struct ldapinfo li, *lip = lc->lc_li;
 
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
        int             sr_err = rs->sr_err;
@@ -394,6 +494,12 @@ ldap_chain_response( Operation *op, SlapReply *rs )
                                        odn = op->o_req_dn,
                                        ondn = op->o_req_ndn;
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+                       LDAPControl     **ctrls = NULL;
+       
+                       (void)chaining_control_add( lc, op, &ctrls );
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
                        rs->sr_type = REP_SEARCH;
 
                        sc2.sc_response = ldap_chain_cb_search_response;
@@ -466,6 +572,10 @@ ldap_chain_response( Operation *op, SlapReply *rs )
                                rc = rs->sr_err;
                        }
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+                       (void)chaining_control_remove( op, &ctrls );
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
                        op->o_req_dn = odn;
                        op->o_req_ndn = ondn;
                        rs->sr_type = REP_SEARCHREF;
@@ -536,6 +646,33 @@ dont_chain:;
        return rc;
 }
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+static int
+ldap_chain_parse_ctrl(
+       Operation       *op,
+       SlapReply       *rs,
+       LDAPControl     *ctrl );
+
+static int
+str2chain( const char *s )
+{
+       if ( strcasecmp( s, "chainingPreferred" ) == 0 ) {
+               return LDAP_CHAINING_PREFERRED;
+               
+       } else if ( strcasecmp( s, "chainingRequired" ) == 0 ) {
+               return LDAP_CHAINING_REQUIRED;
+
+       } else if ( strcasecmp( s, "referralsPreferred" ) == 0 ) {
+               return LDAP_REFERRALS_PREFERRED;
+               
+       } else if ( strcasecmp( s, "referralsRequired" ) == 0 ) {
+               return LDAP_REFERRALS_REQUIRED;
+       }
+
+       return -1;
+}
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
 static int
 ldap_chain_db_config(
        BackendDB       *be,
@@ -546,21 +683,140 @@ ldap_chain_db_config(
 )
 {
        slap_overinst   *on = (slap_overinst *) be->bd_info;
+       ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
        void            *private = be->be_private;
        char            *argv0 = NULL;
        int             rc;
 
-       be->be_private = on->on_bi.bi_private;
        if ( strncasecmp( argv[ 0 ], "chain-", STRLENOF( "chain-" ) ) == 0 ) {
                argv0 = argv[ 0 ];
                argv[ 0 ] = &argv[ 0 ][ STRLENOF( "chain-" ) ];
+
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+               if ( strcasecmp( argv[ 0 ], "chaining" ) == 0 ) {
+                       char                    **tmpargv = argv;
+                       BerElementBuffer        berbuf;
+                       BerElement              *ber = (BerElement *)&berbuf;
+                       int                     resolve = -1,
+                                               continuation = -1,
+                                               iscritical = 0;
+                       Operation               op = { 0 };
+                       SlapReply               rs = { 0 };
+
+                       lc->lc_chaining_ctrlflag = 0;
+
+                       for ( argc--, tmpargv++; argc > 0; argc--, tmpargv++ ) {
+                               if ( strncasecmp( tmpargv[ 0 ], "resolve=", STRLENOF( "resolve=" ) ) == 0 ) {
+                                       resolve = str2chain( tmpargv[ 0 ] + STRLENOF( "resolve=" ) );
+                                       if ( resolve == -1 ) {
+                                               fprintf( stderr, "%s line %d: "
+                                                       "illegal <resolve> value %s "
+                                                       "in \"chain-chaining>\"\n",
+                                                       fname, lineno, tmpargv[ 0 ] );
+                                               return 1;
+                                       }
+
+                               } else if ( strncasecmp( tmpargv[ 0 ], "continuation=", STRLENOF( "continuation=" ) ) == 0 ) {
+                                       continuation = str2chain( tmpargv[ 0 ] + STRLENOF( "continuation=" ) );
+                                       if ( continuation == -1 ) {
+                                               fprintf( stderr, "%s line %d: "
+                                                       "illegal <continuation> value %s "
+                                                       "in \"chain-chaining\"\n",
+                                                       fname, lineno, tmpargv[ 0 ] );
+                                               return 1;
+                                       }
+
+                               } else if ( strcasecmp( tmpargv[ 0 ], "critical" ) == 0 ) {
+                                       iscritical = 1;
+
+                               } else {
+                                       fprintf( stderr, "%s line %d: "
+                                               "unknown option in \"chain-chaining\"\n",
+                                               fname, lineno );
+                                       return 1;
+                               }
+                       }
+
+                       if ( resolve != -1 || continuation != -1 ) {
+                               int     err;
+
+                               if ( resolve == -1 ) {
+                                       /* default */
+                                       resolve = SLAP_CHAINING_DEFAULT;
+                               }
+
+                               ber_init2( ber, NULL, LBER_USE_DER );
+
+                               err = ber_printf( ber, "{e" /* } */, resolve );
+                               if ( err == -1 ) {
+                                       ber_free( ber, 1 );
+                                       fprintf( stderr, "%s line %d: "
+                                               "chaining behavior control encoding error!\n",
+                                               fname, lineno );
+                                       return 1;
+                               }
+
+                               if ( continuation > -1 ) {
+                                       err = ber_printf( ber, "e", continuation );
+                                       if ( err == -1 ) {
+                                               ber_free( ber, 1 );
+                                               fprintf( stderr, "%s line %d: "
+                                                       "chaining behavior control encoding error!\n",
+                                                       fname, lineno );
+                                               return 1;
+                                       }
+                               }
+
+                               err = ber_printf( ber, /* { */ "N}" );
+                               if ( err == -1 ) {
+                                       ber_free( ber, 1 );
+                                       fprintf( stderr, "%s line %d: "
+                                               "chaining behavior control encoding error!\n",
+                                               fname, lineno );
+                                       return 1;
+                               }
+
+                               if ( ber_flatten2( ber, &lc->lc_chaining_ctrl.ldctl_value, 0 ) == -1 ) {
+                                       exit( EXIT_FAILURE );
+                               }
+
+                       } else {
+                               BER_BVZERO( &lc->lc_chaining_ctrl.ldctl_value );
+                       }
+
+                       lc->lc_chaining_ctrl.ldctl_oid = LDAP_CONTROL_X_CHAINING_BEHAVIOR;
+                       lc->lc_chaining_ctrl.ldctl_iscritical = iscritical;
+
+                       if ( ldap_chain_parse_ctrl( &op, &rs, &lc->lc_chaining_ctrl ) != LDAP_SUCCESS )
+                       {
+                               fprintf( stderr, "%s line %d: "
+                                       "unable to parse chaining control%s%s\n",
+                                       fname, lineno,
+                                       rs.sr_text ? ": " : "",
+                                       rs.sr_text ? rs.sr_text : "" );
+                               return 1;
+                       }
+
+                       lc->lc_chaining_ctrlflag = op.o_chaining;
+
+                       lc->lc_flags |= LDAP_CHAIN_F_CHAINING;
+
+                       rc = 0;
+                       goto done;
+               }
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
        }
+
+
+       be->be_private = lc->lc_li;
        rc = lback->bi_db_config( be, fname, lineno, argc, argv );
+       be->be_private = private;
+
+done:;
        if ( argv0 ) {
                argv[ 0 ] = argv0;
        }
-       
-       be->be_private = private;
+
        return rc;
 }
 
@@ -570,6 +826,7 @@ ldap_chain_db_init(
 )
 {
        slap_overinst   *on = (slap_overinst *)be->bd_info;
+       ldap_chain_t    *lc = NULL;
        int             rc;
        BackendDB       bd = *be;
 
@@ -581,35 +838,46 @@ ldap_chain_db_init(
                }
        }
 
+       lc = ch_malloc( sizeof( ldap_chain_t ) );
+       memset( lc, 0, sizeof( ldap_chain_t ) );
+
        bd.be_private = NULL;
        rc = lback->bi_db_init( &bd );
-       on->on_bi.bi_private = bd.be_private;
+       lc->lc_li = (struct ldapinfo *)bd.be_private;
+       on->on_bi.bi_private = (void *)lc;
 
        return rc;
 }
 
-#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
 static int
 ldap_chain_db_open(
        BackendDB *be
 )
 {
-       return overlay_register_control( be, LDAP_CONTROL_X_CHAINING_BEHAVIOR );
-}
+       int     rc = 0;
+
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+       rc = overlay_register_control( be, LDAP_CONTROL_X_CHAINING_BEHAVIOR );
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
 
+       return rc;
+}
+
 static int
 ldap_chain_db_destroy(
        BackendDB *be
 )
 {
-       slap_overinst *on = (slap_overinst *) be->bd_info;
-       void *private = be->be_private;
-       int rc;
+       slap_overinst   *on = (slap_overinst *) be->bd_info;
+       ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
+       void            *private = be->be_private;
+       int             rc;
 
-       be->be_private = on->on_bi.bi_private;
+       be->be_private = (void *)lc->lc_li;
        rc = lback->bi_db_destroy( be );
-       on->on_bi.bi_private = be->be_private;
+       lc->lc_li = be->be_private;
+       ch_free( lc );
+       on->on_bi.bi_private = NULL;
        be->be_private = private;
        return rc;
 }
@@ -620,14 +888,15 @@ ldap_chain_connection_destroy(
        Connection *conn
 )
 {
-       slap_overinst *on = (slap_overinst *) be->bd_info;
-       void *private = be->be_private;
-       int rc;
+       slap_overinst   *on = (slap_overinst *) be->bd_info;
+       ldap_chain_t    *lc = (ldap_chain_t *)on->on_bi.bi_private;
+       void            *private = be->be_private;
+       int             rc;
 
-       be->be_private = on->on_bi.bi_private;
+       be->be_private = (void *)lc->lc_li;
        rc = lback->bi_connection_destroy( be, conn );
-       on->on_bi.bi_private = be->be_private;
        be->be_private = private;
+
        return rc;
 }
 
@@ -778,9 +1047,7 @@ chain_init( void )
 
        ldapchain.on_bi.bi_type = "chain";
        ldapchain.on_bi.bi_db_init = ldap_chain_db_init;
-#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
        ldapchain.on_bi.bi_db_open = ldap_chain_db_open;
-#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
        ldapchain.on_bi.bi_db_config = ldap_chain_db_config;
        ldapchain.on_bi.bi_db_destroy = ldap_chain_db_destroy;
 
index afd8f712041c8a4b2f86764607f3ed35516be5a8..436c713c573671045a21fc92d0b10032adbce3bb 100644 (file)
@@ -213,26 +213,50 @@ ldap_back_db_config(
                li->url = ch_strdup( argv[ 1 ] );
 #endif
 
-       /* start tls */
-       } else if ( strcasecmp( argv[0], "start-tls" ) == 0 ) {
-               if ( argc != 1 ) {
-                       fprintf( stderr,
-       "%s: line %d: start-tls takes no arguments\n",
-                                       fname, lineno );
-                       return( 1 );
-               }
-               li->flags |= LDAP_BACK_F_TLS_CRITICAL;
+       } else if ( strncasecmp( argv[0], "tls-", STRLENOF( "tls-" ) ) == 0 ) {
+
+               /* start tls */
+               if ( strcasecmp( argv[0], "tls-start" ) == 0 ) {
+                       if ( argc != 1 ) {
+                               fprintf( stderr,
+               "%s: line %d: tls-start takes no arguments\n",
+                                               fname, lineno );
+                               return( 1 );
+                       }
+                       li->flags |= ( LDAP_BACK_F_USE_TLS | LDAP_BACK_F_TLS_CRITICAL );
        
-       /* try start tls */
-       } else if ( strcasecmp( argv[0], "try-start-tls" ) == 0 ) {
-               if ( argc != 1 ) {
-                       fprintf( stderr,
-       "%s: line %d: try-start-tls takes no arguments\n",
-                                       fname, lineno );
-                       return( 1 );
+               /* try start tls */
+               } else if ( strcasecmp( argv[0], "tls-try-start" ) == 0 ) {
+                       if ( argc != 1 ) {
+                               fprintf( stderr,
+               "%s: line %d: tls-try-start takes no arguments\n",
+                                               fname, lineno );
+                               return( 1 );
+                       }
+                       li->flags &= ~LDAP_BACK_F_TLS_CRITICAL;
+                       li->flags |= LDAP_BACK_F_USE_TLS;
+       
+               /* propagate start tls */
+               } else if ( strcasecmp( argv[0], "tls-propagate" ) == 0 ) {
+                       if ( argc != 1 ) {
+                               fprintf( stderr,
+               "%s: line %d: tls-propagate takes no arguments\n",
+                                               fname, lineno );
+                               return( 1 );
+                       }
+                       li->flags |= ( LDAP_BACK_F_PROPAGATE_TLS | LDAP_BACK_F_TLS_CRITICAL );
+               
+               /* try start tls */
+               } else if ( strcasecmp( argv[0], "tls-try-propagate" ) == 0 ) {
+                       if ( argc != 1 ) {
+                               fprintf( stderr,
+               "%s: line %d: tls-try-propagate takes no arguments\n",
+                                               fname, lineno );
+                               return( 1 );
+                       }
+                       li->flags &= ~LDAP_BACK_F_TLS_CRITICAL;
+                       li->flags |= LDAP_BACK_F_PROPAGATE_TLS;
                }
-               li->flags &= ~LDAP_BACK_F_TLS_CRITICAL;
-               li->flags |= LDAP_BACK_F_USE_TLS;
        
        /* name to use for ldap_back_group */
        } else if ( strcasecmp( argv[0], "acl-authcdn" ) == 0
@@ -723,7 +747,7 @@ parse_idassert(
                                                li->idassert_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ;
 
                                        } else {
-                                               fprintf( stderr, "%s: line %s: "
+                                               fprintf( stderr, "%s: line %d: "
                                                        "unknown authz mode \"%s\"\n",
                                                        fname, lineno, val );
                                                return 1;
index 8c610a57980b1c18b1006a4c2a060a51f58a5f17..edd5bba22de4b49be8dae0e7f1a6703e421fed93 100644 (file)
@@ -56,7 +56,6 @@ ldap_back_search(
        int             i;
        char            **attrs = NULL;
        int             dontfreetext = 0;
-       int             freeconn = 0;
        int             do_retry = 1;
        LDAPControl     **ctrls = NULL;
 
@@ -120,12 +119,18 @@ retry:
 
        if ( rs->sr_err != LDAP_SUCCESS ) {
 fail:;
-               rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDERR );
-               if ( freeconn ) {
+               if ( rs->sr_err == LDAP_SERVER_DOWN ) {
+                       if ( do_retry ) {
+                               do_retry = 0;
+                               if ( ldap_back_retry( lc, op, rs, LDAP_BACK_DONTSEND ) ) {
+                                       goto retry;
+                               }
+                       }
+                       rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
                        ldap_back_freeconn( op, lc );
                        lc = NULL;
+                       goto finish;
                }
-               goto finish;
        }
 
        /* We pull apart the ber result, stuff it into a slapd entry, and
@@ -138,7 +143,7 @@ fail:;
                /* check for abandon */
                if ( op->o_abandon ) {
                        ldap_abandon_ext( lc->lc_ld, msgid, NULL, NULL );
-                       rc = 0;
+                       rc = SLAPD_ABANDON;
                        goto finish;
                }
 
@@ -253,7 +258,7 @@ fail:;
                                rs->sr_ref = ch_calloc( cnt + 1, sizeof( struct berval ) );
 
                                for ( cnt = 0; references[ cnt ]; cnt++ ) {
-                                       ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] );
+                                       ber_str2bv( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ] );
                                }
 
                                /* cleanup */
@@ -274,9 +279,7 @@ fail:;
                                goto retry;
                        }
                }
-               /* FIXME: invalidate the connection? */
                rs->sr_err = LDAP_SERVER_DOWN;
-               freeconn = 1;
                goto fail;
        }
 
@@ -291,7 +294,9 @@ fail:;
        }
 
 finish:;
-       send_ldap_result( op, rs );
+       if ( rc != SLAPD_ABANDON ) {
+               send_ldap_result( op, rs );
+       }
 
        (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
 
index e9fd151fcc711fcd6d72ce043ca0b00ac08b9d8f..4df7478e0cd828f53b8aeb9393c65cf8a897f320 100644 (file)
@@ -361,6 +361,7 @@ ldbm_back_modrdn(
 
        /* check for abandon */
        if ( op->o_abandon ) {
+               rs->sr_err = SLAPD_ABANDON;
                goto return_results;
        }
 
@@ -420,6 +421,7 @@ ldbm_back_modrdn(
 
        /* check for abandon */
        if ( op->o_abandon ) {
+               rs->sr_err = SLAPD_ABANDON;
                goto return_results;
        }
 
index 3c09594ff134efd30a3e98ddcdac976418f063a9..1e414f6609a68bb6df93f12dd6bc376ff727295f 100644 (file)
@@ -232,7 +232,7 @@ searchit:
 
                /* check for abandon */
                if ( op->o_abandon ) {
-                       rc = LDAP_SUCCESS;
+                       rc = SLAPD_ABANDON;
                        goto done;
                }
 
diff --git a/servers/slapd/back-ldif/Makefile.in b/servers/slapd/back-ldif/Makefile.in
new file mode 100644 (file)
index 0000000..aa52168
--- /dev/null
@@ -0,0 +1,41 @@
+# Makefile.in for back-ldif
+# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2005 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+
+SRCS = ldif.c
+OBJS = ldif.lo
+
+LDAP_INCDIR= ../../../include       
+LDAP_LIBDIR= ../../../libraries
+
+BUILD_OPT = "--enable-ldif"
+BUILD_MOD = yes
+
+mod_DEFS = -DSLAPD_IMPORT
+MOD_DEFS = $(yes_DEFS)
+
+shared_LDAP_LIBS = $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA)
+NT_LINK_LIBS = -L.. -lslapd $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
+UNIX_LINK_LIBS = $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
+
+LIBBASE = back_ldif
+
+XINCPATH = -I.. -I$(srcdir)/..
+XDEFS = $(MODULES_CPPFLAGS)
+
+all-local-lib: ../.backend
+
+../.backend: lib$(LIBBASE).a
+       @touch $@
+
diff --git a/servers/slapd/back-ldif/ldif.c b/servers/slapd/back-ldif/ldif.c
new file mode 100644 (file)
index 0000000..56f1474
--- /dev/null
@@ -0,0 +1,993 @@
+/* ldif.c - the ldif backend */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2005 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by Eric Stokes for inclusion
+ * in OpenLDAP Software.
+ */
+
+#include "portable.h"
+#include <stdio.h>
+#include <ac/string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ac/dirent.h>
+#include <fcntl.h>
+#include <ac/errno.h>
+#include <ac/unistd.h>
+#include "slap.h"
+#include "lutil.h"
+
+struct ldif_info {
+       struct berval li_base_path;
+       ID tool_current;  
+       Entry ** tool_entries;
+       int tool_put_entry_flag;
+       int tool_numentries;
+       ldap_pvt_thread_mutex_t  li_mutex;
+};
+
+#define LDIF   ".ldif"
+
+#define ENTRY_BUFF_INCREMENT 500
+
+static char *
+dn2path(struct berval * dn, struct berval * rootdn, struct berval * base_path)
+{
+       char *result = ch_malloc( dn->bv_len + base_path->bv_len + 2 +
+               STRLENOF( LDIF ));
+       char *ptr, *sep, *end;
+
+       ptr = lutil_strcopy( result, base_path->bv_val );
+       *ptr++ = LDAP_DIRSEP[0];
+       ptr = lutil_strcopy( ptr, rootdn->bv_val );
+       end = dn->bv_val + dn->bv_len - rootdn->bv_len - 1;
+       while ( end > dn->bv_val ) {
+               for (sep = end-1; sep >=dn->bv_val && !DN_SEPARATOR( *sep ); sep--);
+               *ptr++ = LDAP_DIRSEP[0];
+               ptr = lutil_strncopy( ptr, sep+1, end-sep-1 );
+               end = sep;
+       }
+       strcpy(ptr, LDIF);
+       return result;
+}
+
+static char * slurp_file(int fd) {  
+       int entry_buf_size = 40 * ENTRY_BUFF_INCREMENT;
+       int read_chars_total = 0;
+       int read_chars = 0;
+       int entry_size = 40 * ENTRY_BUFF_INCREMENT;
+       char * entry = (char *) malloc(sizeof(char) * 40 * ENTRY_BUFF_INCREMENT);
+       char * entry_pos = entry;
+       
+       while(1) {
+         if(entry_size - read_chars_total == 0) {
+           entry = (char *) realloc(entry, sizeof(char) * 2 * entry_size);
+           entry_size = 2 * entry_size;
+         }
+         read_chars = read(fd, (void *) entry_pos, entry_size - read_chars_total);
+         if(read_chars == -1) {
+           SLAP_FREE(entry);
+           return NULL;
+         }
+         entry_pos += read_chars;
+         if(read_chars == 0) {
+           if(entry_size - read_chars_total > 0)
+       entry[read_chars_total] = '\0';
+           else {
+       entry = (char *) realloc(entry, sizeof(char) * entry_size + 1);
+       entry_size = entry_size + 1;
+       entry[read_chars_total] = '\0';
+           }   
+           break;
+         }
+         else {
+           read_chars_total += read_chars;
+         }
+       }
+       return entry;
+}
+
+static int spew_file(int fd, char * spew) {
+       int written = 0;
+       int writeres;
+       int len = strlen(spew);
+       char * spewptr = spew;
+       
+       while(written < len) {
+         writeres = write(fd, spewptr, len - written);
+         if(writeres == -1) {
+           perror("could not spew write");
+           return -1;
+         }
+         else {
+           spewptr += writeres;
+           written += writeres;
+         }
+       }
+       return writeres;
+}
+
+static int spew_entry(Entry * e, char * path) {
+       int rs;
+       int openres;
+       int spew_res;
+       int entry_length;
+       char * entry_as_string;
+
+       openres = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+       if(openres == -1) {
+         if(errno == ENOENT)
+           rs = LDAP_NO_SUCH_OBJECT;
+         else
+           rs = LDAP_UNWILLING_TO_PERFORM;
+       }
+       else {
+         entry_as_string = entry2str(e, &entry_length);
+         if(entry_as_string == NULL) {
+           rs = LDAP_UNWILLING_TO_PERFORM;
+           close(openres);
+         }
+         else {
+           spew_res = spew_file(openres, entry_as_string);
+           close(openres);
+           if(spew_res == -1)
+       rs = LDAP_UNWILLING_TO_PERFORM;
+           else
+       rs = LDAP_SUCCESS;
+         }
+       }    
+       return rs;
+}
+
+static Entry * get_entry_for_fd(int fd) {
+       char * entry = (char *) slurp_file(fd);
+       Entry * ldentry = NULL;
+       
+       /* error reading file */
+       if(entry == NULL) {
+         goto return_value;
+       }
+
+       ldentry = str2entry(entry);
+
+ return_value:
+       if(fd != -1) {
+         if(close(fd) != 0) {
+           /* log error */
+         }
+       }
+       if(entry != NULL)
+         SLAP_FREE(entry);
+       return ldentry;
+}
+
+static Entry * get_entry(struct berval * dn, struct berval * rootdn, struct berval * base_path) {
+       char * path = (char *) dn2path(dn, rootdn, base_path);
+       int fd = open(path, O_RDONLY);
+
+       /* error opening file (mebbe should log error) */
+       if(fd == -1) {
+         perror("failed to open file");
+         goto return_value;
+       }
+       goto return_value;
+
+ return_value:
+       if(path != NULL)
+         SLAP_FREE(path);
+       return get_entry_for_fd(fd);
+}
+
+/* takes a base path and a filename and opens that file */
+static int fd_for_path_components(char * base, char * name) {
+       char * absolutepath;
+       int fd;
+       absolutepath = (char *) SLAP_MALLOC(sizeof(char) * 
+                                     (strlen(base) + 
+                                      strlen(name) + 2));
+       absolutepath[0] = '\0';
+       strcat(absolutepath, base);
+       strcat(absolutepath, LDAP_DIRSEP);
+       strcat(absolutepath, name);
+       fd = open(absolutepath, O_RDONLY);
+       SLAP_FREE(absolutepath);
+       return fd;
+}
+
+static Entry ** r_enum_tree(Entry ** entries, int *elen, int *eind, char * path) {
+       DIR * dir_of_path = opendir(path);
+       int fd;
+       struct dirent * dir;
+       char * newpath;
+       Entry * e;
+
+       if(entries == NULL) {
+         entries = (Entry **) SLAP_MALLOC(sizeof(Entry *) * ENTRY_BUFF_INCREMENT);
+         *elen = ENTRY_BUFF_INCREMENT;
+       }
+       if(dir_of_path == NULL) {/* can't open directory */
+         perror("failed to open directory");
+         return entries;
+       }
+       
+       while(1) {
+         dir = readdir(dir_of_path);
+         if(dir == NULL) break; /* end of the directory */
+         if(dir->d_type == DT_REG) { /* regular file, read the entry into memory */
+           if(! (*eind < *elen)) { /* grow entries if necessary */     
+       entries = (Entry **) SLAP_REALLOC(entries, sizeof(Entry *) * (*elen) * 2);
+       *elen = *elen * 2;
+           }
+           fd = fd_for_path_components(path, dir->d_name);
+           if(fd != -1) {
+       e = get_entry_for_fd(fd);
+       if(e != NULL) {
+         entries[*eind] = e;
+         *eind = *eind + 1;
+       }
+       else
+         perror("failed to read entry");
+           }
+           else
+       perror("failed to open fd");
+         }
+         else if(dir->d_type == DT_DIR) {
+           if(! (strcasecmp(dir->d_name, ".") == 0 || strcasecmp(dir->d_name, "..") == 0)) {
+       newpath = (char *) SLAP_MALLOC(sizeof(char) * 
+                                      (strlen(path) + strlen(dir->d_name) + 2));
+       newpath[0] = '\0';
+       strcat(newpath, path);
+       strcat(newpath, LDAP_DIRSEP);
+       strcat(newpath, dir->d_name);
+       entries = r_enum_tree(entries, elen, eind, newpath);
+       SLAP_FREE(newpath);
+           }
+         }
+       }
+       closedir(dir_of_path);
+       return entries;
+}
+
+static Entry ** enum_tree(struct berval * path, int * length) {
+       int index = 0;
+       return r_enum_tree(NULL, &index, length, path->bv_val);
+}
+
+static char * get_parent_path(char * dnpath) {
+       int dnpathlen = strlen(dnpath);
+       char * result;
+       int i;
+       
+       for(i = dnpathlen;i>0;i--) /* find the first path seperator */
+         if(dnpath[i] == LDAP_DIRSEP[0])
+           break;
+       result = ch_malloc( i + 1 );
+       strncpy(result, dnpath, i);
+       result[i] = '\0';
+       return result;
+}
+
+static int apply_modify_to_entry(Entry * entry, 
+                         Modifications * modlist, 
+                         Operation * op,
+                         SlapReply * rs) 
+{
+       char textbuf[SLAP_TEXT_BUFLEN];
+       size_t textlen = sizeof textbuf;
+       int rc;
+       int tempdebug;
+       Modification *mods = NULL;
+       Attribute *save_attrs;
+
+       if (!acl_check_modlist(op, entry, modlist)) {
+         return LDAP_INSUFFICIENT_ACCESS;
+       }
+
+       /*  save_attrs = entry->e_attrs; Why?
+           entry->e_attrs = attrs_dup(entry->e_attrs); */
+
+       for (; modlist != NULL; modlist = modlist->sml_next) {
+         mods = &modlist->sml_mod;
+
+         switch (mods->sm_op) {
+         case LDAP_MOD_ADD:
+           rc = modify_add_values(entry, mods, 
+                            get_permissiveModify(op), 
+                            &rs->sr_text, textbuf, 
+                            textlen);
+           break;
+                               
+         case LDAP_MOD_DELETE:
+           rc = modify_delete_values(entry, mods, 
+                               get_permissiveModify(op), 
+                               &rs->sr_text, textbuf, 
+                               textlen);
+
+           break;
+                               
+         case LDAP_MOD_REPLACE:
+           rc = modify_replace_values(entry, mods, 
+                                get_permissiveModify(op), 
+                                &rs->sr_text, textbuf, 
+                                textlen);
+
+           break;
+         case LDAP_MOD_INCREMENT:
+           break;
+         case SLAP_MOD_SOFTADD:
+           mods->sm_op = LDAP_MOD_ADD;
+           rc = modify_add_values(entry, mods, 
+                            get_permissiveModify(op),
+                            &rs->sr_text, textbuf, 
+                            textlen);
+           mods->sm_op = SLAP_MOD_SOFTADD;
+           if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
+       rc = LDAP_SUCCESS;
+           }      
+           break;
+         default:
+           break;
+         }
+         if(rc != LDAP_SUCCESS) break;
+       }
+       
+       if(rc == LDAP_SUCCESS) {
+         if ( mods->sm_desc == slap_schema.si_ad_objectClass ) {
+           entry->e_ocflags = 0;
+         }
+         /* check that the entry still obeys the schema */
+         rc = entry_schema_check(op->o_bd, entry,
+                           save_attrs, &rs->sr_text, 
+                           textbuf, textlen);
+       }
+       return rc;
+}
+
+static int
+ldif_back_bind( Operation *op, SlapReply *rs )
+{
+       struct ldif_info *ni = NULL;
+       Attribute * a = NULL;
+       AttributeDescription *password = slap_schema.si_ad_userPassword;
+       int return_val = 0;
+       Entry * entry = NULL;
+
+       ni = (struct ldif_info *) op->o_bd->be_private;
+       ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+       entry = (Entry *) get_entry(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path);
+
+       /* no object is found for them */
+       if(entry == NULL) {
+         if(be_isroot_pw(op)) {
+           return_val = LDAP_SUCCESS;
+           goto return_result;
+         }
+         else if(be_root_dn(op->o_bd)) {
+           return_val = LDAP_INVALID_CREDENTIALS;
+           rs->sr_err = LDAP_INVALID_CREDENTIALS;
+           goto return_result;
+         }
+         else {
+           rs->sr_err = LDAP_NO_SUCH_OBJECT;
+           return_val = 1;
+           goto return_result;
+         }
+       }
+
+       /* they don't have userpassword */
+       if((a = attr_find(entry->e_attrs, password)) == NULL) {
+         rs->sr_err = LDAP_INAPPROPRIATE_AUTH;
+         return_val = 1;
+         goto return_result;
+       }
+
+       /* authentication actually failed */
+       if(slap_passwd_check(op, entry, a, &op->oq_bind.rb_cred,
+                      &rs->sr_text) != 0) {
+         rs->sr_err = LDAP_INVALID_CREDENTIALS;
+         return_val = 1;
+         goto return_result;
+       }
+
+       /* let the front-end send success */
+       return_val = 0;
+       goto return_result;
+
+ return_result:
+       ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+       if(return_val != 0)
+         send_ldap_result( op, rs );
+       if(entry != NULL)
+         entry_free(entry);
+       return return_val;
+}
+
+static int ldif_back_search(Operation *op, SlapReply *rs)
+{
+       struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+       int numentries = 0;
+       int i = 0;
+       Entry ** entries = NULL;
+
+       ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+       entries = (Entry **) enum_tree(&ni->li_base_path, &numentries);
+
+       if(entries != NULL) {
+         for(i=0;i<numentries;i++) {
+           if(test_filter(op, entries[i], op->ors_filter) == LDAP_COMPARE_TRUE) {
+       rs->sr_entry = entries[i];
+       rs->sr_attrs = op->ors_attrs;
+       rs->sr_flags = REP_ENTRY_MODIFIABLE;
+       send_search_entry(op, rs);
+           }
+           entry_free(entries[i]);
+         }
+         SLAP_FREE(entries);
+         rs->sr_err = LDAP_SUCCESS;
+         ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+         send_ldap_result(op, rs);
+       }
+       else {
+         rs->sr_err = LDAP_BUSY;
+         ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+         send_ldap_result(op, rs);
+       }
+
+       return 0;
+}
+
+static int ldif_back_add(Operation *op, SlapReply *rs) {
+       struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+       Entry * e = op->ora_e;
+       Attribute *save_attrs;
+       struct berval dn = e->e_nname;
+       char * leaf_path = NULL;
+       char * base = NULL;
+       char * base_ldif = NULL;
+       struct stat stats;
+       int statres;
+       char textbuf[SLAP_TEXT_BUFLEN];
+       size_t textlen = sizeof textbuf;
+
+       ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+       ldap_pvt_thread_mutex_lock(&entry2str_mutex);
+
+       leaf_path = (char *) dn2path(&dn, &op->o_bd->be_nsuffix[0], &ni->li_base_path);
+
+       /*  save_attrs = e->e_attrs; why?
+           e->e_attrs = attrs_dup(e->e_attrs);*/
+
+       if(leaf_path != NULL) {
+         char * tmp;
+         /* build path to container, and path to ldif of container */
+         base = (char *) get_parent_path(leaf_path);
+         base_ldif = (char *) SLAP_MALLOC(sizeof(char) * (strlen(base) + 6));
+         tmp = (char *) lutil_strcopy(base_ldif, base);
+         lutil_strcopy(tmp, LDIF);
+
+         rs->sr_err = entry_schema_check(op->o_bd, e,
+                                   save_attrs, 
+                                   &rs->sr_text, 
+                                   textbuf, textlen);
+         if(rs->sr_err == LDAP_SUCCESS) {
+           statres = stat(base, &stats); /* check if container exists */
+           if(statres == -1 && errno == ENOENT) { /* container missing */
+       statres = stat(base_ldif, &stats); /* check for leaf node */
+       if(statres == -1 && errno == ENOENT) {
+         rs->sr_err = LDAP_NO_SUCH_OBJECT; /* parent doesn't exist */
+       }
+       else if(statres != -1) { /* create parent */
+         int mkdirres = mkdir(base, 0750);
+         if(mkdirres == -1) {
+           rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+         }
+       }
+       else
+         rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+           }/* container was possibly created, move on to add the entry */
+           if(rs->sr_err == LDAP_SUCCESS) {
+       statres = stat(leaf_path, &stats);
+       if(statres == -1 && errno == ENOENT) {
+         rs->sr_err = (int) spew_entry(e, leaf_path);
+       }
+       else /* it already exists */
+         rs->sr_err = LDAP_ALREADY_EXISTS;
+           }  
+         }
+       }    
+
+       ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+       ldap_pvt_thread_mutex_unlock(&entry2str_mutex);
+
+       send_ldap_result(op, rs);  
+       if(leaf_path != NULL)
+         SLAP_FREE(leaf_path);
+       if(base != NULL)
+         SLAP_FREE(base);
+       if(base_ldif != NULL)
+         SLAP_FREE(base_ldif);
+       return 0;
+}
+
+static int ldif_back_modify(Operation *op, SlapReply *rs) {
+       struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+       Modifications * modlst = op->orm_modlist;
+       char * path = NULL;
+       Entry * entry = NULL;
+       int spew_res;
+
+       ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+       ldap_pvt_thread_mutex_lock(&entry2str_mutex);
+       path = (char *) dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path);
+       entry = (Entry *) get_entry(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path);
+
+       if(entry != NULL) {
+         rs->sr_err = apply_modify_to_entry(entry, modlst, op, rs);
+         if(rs->sr_err == LDAP_SUCCESS) {
+           spew_res = spew_entry(entry, path);
+           if(spew_res == -1) {
+       perror("could not output entry");
+       rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+           }
+         }
+       }
+       else {
+         rs->sr_err = LDAP_NO_SUCH_OBJECT;
+       }
+       
+       if(path != NULL)
+         SLAP_FREE(path);
+       if(entry != NULL)
+         entry_free(entry);
+       rs->sr_text = "";
+       ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+       ldap_pvt_thread_mutex_unlock(&entry2str_mutex);
+       send_ldap_result(op, rs);
+       return 0;
+}
+
+static int ldif_back_delete(Operation *op, SlapReply *rs) {
+       struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+       char * path = NULL;
+       int res = 0;
+
+       ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+       path = (char *) dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path);
+       res = unlink(path);
+
+       if(res == -1) {
+         if(errno == ENOENT)
+           rs->sr_err = LDAP_NO_SUCH_OBJECT;
+         else
+           rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+       }
+       else
+         rs->sr_err = LDAP_SUCCESS;
+
+       SLAP_FREE(path);
+       ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+       send_ldap_result(op, rs);
+       return 0;
+}
+
+static int is_leaf_node(char * path) {
+       DIR * nonleafnode;  
+       int path_len = strlen(path);
+       char * nonleafpath = (char *) SLAP_MALLOC(sizeof(char) * path_len + 1);
+       int res;
+
+       strncpy(nonleafpath, path, path_len);
+       nonleafpath[path_len - 5] = '\0';
+       nonleafnode = opendir(nonleafpath);
+       if(nonleafnode == NULL) {
+         res = 1;
+       }
+       else {
+         closedir(nonleafnode);
+         res = 0;
+       }
+       SLAP_FREE(nonleafpath);
+       return res;
+}
+
+static int move_entry(Entry * entry, struct berval * ndn, 
+              struct berval * newndn, struct berval * rootdn,
+              struct berval * base_path) {
+       int res;
+       int exists_res;
+       char * path = (char *) dn2path(ndn, rootdn, base_path);
+       char * newpath = (char *) dn2path(newndn, rootdn, base_path);
+       int path_len = strlen(path);
+
+       if((entry == NULL || path == NULL) || newpath == NULL) { /* some object doesn't exist */
+         res = LDAP_NO_SUCH_OBJECT;
+       }
+       else if(! is_leaf_node(path)) { /* entry is not a leaf node */
+         res = LDAP_NOT_ALLOWED_ON_NONLEAF;
+       }
+       else { /* do the modrdn */
+         exists_res = open(newpath, O_RDONLY);
+         if(exists_res == -1 && errno == ENOENT) {
+           res = spew_entry(entry, newpath);
+           if(res != -1) {
+       /* if this fails we should log something bad */
+       res = unlink(path);
+       res = LDAP_SUCCESS;
+           }
+           else {
+       if(errno == ENOENT)
+         res = LDAP_NO_SUCH_OBJECT;
+       else
+         res = LDAP_UNWILLING_TO_PERFORM;
+       unlink(newpath); /* in case file was created */            
+           }
+         }
+         else if(exists_res) {
+           res = LDAP_ALREADY_EXISTS;
+           int close_res = close(exists_res);
+           if(close_res == -1) {
+       /* log heinous error */
+           }
+         }
+         else {
+           res = LDAP_UNWILLING_TO_PERFORM;
+         }
+       }
+
+       if(path != NULL)
+         SLAP_FREE(path);
+       if(newpath != NULL)
+         SLAP_FREE(newpath);
+       return res;
+}
+
+static int ldif_back_modrdn(Operation *op, SlapReply *rs) {
+       struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+       struct berval new_dn = {0, NULL}, new_ndn = {0, NULL};
+       struct berval * new_parent_dn = NULL;
+       struct berval p_dn;
+       Entry * entry = NULL;
+       LDAPRDN new_rdn = NULL;
+       LDAPRDN old_rdn = NULL;
+       Modifications * mods = NULL;
+       int res;
+
+       ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+       ldap_pvt_thread_mutex_lock(&entry2str_mutex);
+       entry = (Entry *) get_entry(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path);
+
+       /* build the mods to the entry */
+       if(entry != NULL) {
+         if(ldap_bv2rdn(&op->oq_modrdn.rs_newrdn, &new_rdn, (char **)&rs->sr_text, 
+                  LDAP_DN_FORMAT_LDAP)) {
+           rs->sr_err = LDAP_INVALID_DN_SYNTAX;
+         }
+         else if(op->oq_modrdn.rs_deleteoldrdn &&
+           ldap_bv2rdn(&op->o_req_dn, &old_rdn, (char **)&rs->sr_text,
+                       LDAP_DN_FORMAT_LDAP)) {
+           rs->sr_err = LDAP_OTHER;
+         }
+         else { /* got both rdns successfully, ready to build mods */
+           if(slap_modrdn2mods(op, rs, entry, old_rdn, new_rdn, &mods) != LDAP_SUCCESS) {
+       rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+           }
+           else { /* built mods successfully */
+
+       /* build new dn, and new ndn for the entry */
+       if(op->oq_modrdn.rs_newSup != NULL) /* new superior */
+         p_dn = *op->oq_modrdn.rs_newSup;
+       else
+         p_dn = slap_empty_bv;
+       dnParent(&entry->e_name, &p_dn);
+       build_new_dn(&new_dn, &p_dn, &op->oq_modrdn.rs_newrdn, NULL); 
+       struct berval bv = {0, NULL};
+       dnNormalize( 0, NULL, NULL, &new_dn, &bv, op->o_tmpmemctx );
+       ber_dupbv( &new_ndn, &bv );
+       entry->e_name = new_dn;
+       entry->e_nname = new_ndn;
+
+       /* perform the modifications */
+       res = apply_modify_to_entry(entry, mods, op, rs);
+       if(res == LDAP_SUCCESS) {
+         rs->sr_err = move_entry(entry, &op->o_req_ndn, 
+                                 &new_ndn,
+                                 &op->o_bd->be_nsuffix[0],
+                                 &ni->li_base_path);
+       }
+       else
+         rs->sr_err = res;
+           }
+         }
+       }
+       else /* entry was null */
+         rs->sr_err = LDAP_NO_SUCH_OBJECT;
+
+       if(entry != NULL)
+         entry_free(entry);
+       rs->sr_text = "";
+       ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+       ldap_pvt_thread_mutex_unlock(&entry2str_mutex);
+       send_ldap_result(op, rs);
+       return 0;
+}
+
+static int ldif_back_compare(Operation *op, SlapReply *rs) {
+       struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
+       Entry * e = NULL;
+       Attribute       *a;
+
+       ldap_pvt_thread_mutex_lock(&ni->li_mutex);
+
+       e = (Entry *) get_entry(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path);
+       if(e != NULL) {
+         for(a = attrs_find( e->e_attrs, op->oq_compare.rs_ava->aa_desc );
+       a != NULL;
+       a = attrs_find( a->a_next, op->oq_compare.rs_ava->aa_desc ))
+           {
+       rs->sr_err = LDAP_COMPARE_FALSE;
+       
+       if (value_find_ex(op->oq_compare.rs_ava->aa_desc,
+                         SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
+                         SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
+                         a->a_nvals, &op->oq_compare.rs_ava->aa_value,
+                         op->o_tmpmemctx ) == 0)
+         {
+           rs->sr_err = LDAP_COMPARE_TRUE;
+           break;
+         }
+           }
+       }
+       else {
+         rs->sr_err = LDAP_NO_SUCH_OBJECT;
+       }
+
+       if(e != NULL)
+         entry_free(e);
+       ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+       send_ldap_result(op, rs);
+       return 0;
+}
+
+static int ldif_tool_entry_open(BackendDB * be, int mode) {
+       struct ldif_info *ni = (struct ldif_info *) be->be_private;  
+       ni->tool_entries = NULL;
+       ni->tool_numentries = 0;
+       ni->tool_current = 0;
+       ni->tool_put_entry_flag = 0;
+       return 0;
+}                                      
+
+static int ldif_tool_entry_close(BackendDB * be) {
+       struct ldif_info *ni = (struct ldif_info *) be->be_private;  
+       int i;
+       /*if(ni->tool_entries != NULL) {
+         for(i=0;i<ni->tool_numentries;i++) {
+           SLAP_FREE(ni->tool_entries[i]);
+           }*/
+       SLAP_FREE(ni->tool_entries);
+       return 0;
+}
+
+static ID ldif_tool_entry_first(BackendDB *be) {
+       struct ldif_info *ni = (struct ldif_info *) be->be_private;  
+       ID id = 1; /* first entry in the array of entries shifted by one */
+       ni->tool_current = 1;
+       if(ni->tool_entries == NULL || ni->tool_put_entry_flag) {
+         ni->tool_entries = (Entry **) enum_tree(&ni->li_base_path, &ni->tool_numentries);
+         ni->tool_put_entry_flag = 0;
+       }
+       return id;
+}
+
+static ID ldif_tool_entry_next(BackendDB *be) {
+       struct ldif_info *ni = (struct ldif_info *) be->be_private;  
+       ni->tool_current += 1;
+       if(ni->tool_put_entry_flag) {
+         ni->tool_entries = (Entry **) enum_tree(&ni->li_base_path, &ni->tool_numentries);
+         ni->tool_put_entry_flag = 0;
+       }
+       if(ni->tool_current > ni->tool_numentries)
+         return NOID;
+       else
+         return ni->tool_current;
+}
+
+static Entry * ldif_tool_entry_get(BackendDB * be, ID id) {
+       struct ldif_info *ni = (struct ldif_info *) be->be_private;  
+       Entry * e;
+
+       if(id > ni->tool_numentries || id < 1)
+         return NULL;
+       else {
+         e = ni->tool_entries[id - 1];
+         ni->tool_entries[id - 1] = NULL;
+         return e;
+       }
+}
+
+static ID ldif_tool_entry_put(BackendDB * be, Entry * e, struct berval *text) {
+       struct ldif_info *ni = (struct ldif_info *) be->be_private;  
+         Attribute *save_attrs;
+       struct berval dn = e->e_nname;
+       char * leaf_path = NULL;
+       char * base = NULL;
+       char * base_ldif = NULL;
+       struct stat stats;
+       int statres;
+       char textbuf[SLAP_TEXT_BUFLEN];
+       size_t textlen = sizeof textbuf;
+       int res = LDAP_SUCCESS;
+
+       leaf_path = (char *) dn2path(&dn, &be->be_nsuffix[0], &ni->li_base_path);
+
+       /*  save_attrs = e->e_attrs; why?
+           e->e_attrs = attrs_dup(e->e_attrs);*/
+
+       if(leaf_path != NULL) {
+         char * tmp;
+         /* build path to container, and path to ldif of container */
+         base = (char *) get_parent_path(leaf_path);
+         base_ldif = (char *) SLAP_MALLOC(sizeof(char) * (strlen(base) + 6));
+         tmp = (char *) lutil_strcopy(base_ldif, base);
+         lutil_strcopy(tmp, LDIF);
+
+         statres = stat(base, &stats); /* check if container exists */
+         if(statres == -1 && errno == ENOENT) { /* container missing */
+           statres = stat(base_ldif, &stats); /* check for leaf node */
+           if(statres == -1 && errno == ENOENT) {
+       res = LDAP_NO_SUCH_OBJECT; /* parent doesn't exist */
+           }
+           else if(statres != -1) { /* create parent */
+       int mkdirres = mkdir(base, 0750);
+       if(mkdirres == -1) {
+         res = LDAP_UNWILLING_TO_PERFORM;
+       }
+           }
+           else
+       res = LDAP_UNWILLING_TO_PERFORM;
+         }/* container was possibly created, move on to add the entry */
+         if(res == LDAP_SUCCESS) {
+           statres = stat(leaf_path, &stats);
+           if(statres == -1 && errno == ENOENT) {
+       res = (int) spew_entry(e, leaf_path);
+           }
+           else /* it already exists */
+       res = LDAP_ALREADY_EXISTS;
+         }  
+       }
+
+       if(leaf_path != NULL)
+         SLAP_FREE(leaf_path);
+       if(base != NULL)
+         SLAP_FREE(base);
+       if(base_ldif != NULL)
+         SLAP_FREE(base_ldif);
+       if(res == LDAP_SUCCESS) {
+         ni->tool_put_entry_flag = 1;
+         return 1;
+       }
+       else
+         return NOID;
+}
+
+static int
+ldif_back_db_config(
+                   BackendDB   *be,
+                   const char  *fname,
+                   int                 lineno,
+                   int                 argc,
+                   char                **argv )
+{
+       struct ldif_info *ni = (struct ldif_info *) be->be_private;
+
+       if ( strcasecmp( argv[0], "directory" ) == 0 ) {
+         if ( argc < 2 ) {
+           fprintf( stderr,
+              "%s: line %d: missing <path> in \"directory <path>\" line\n",
+              fname, lineno );
+           return 1;
+         }
+         ber_str2bv(argv[1], 0, 1, &ni->li_base_path);
+       } else {
+         return SLAP_CONF_UNKNOWN;
+       }
+       return 0;
+}
+
+
+static int
+ldif_back_db_init( BackendDB *be )
+{
+       struct ldif_info *ni;
+
+       ni = ch_calloc( 1, sizeof(struct ldif_info) );
+       be->be_private = ni;
+       ldap_pvt_thread_mutex_init(&ni->li_mutex);
+       return 0;
+}
+
+static int
+ldif_back_db_destroy(
+                    Backend    *be
+                    )
+{
+       struct ldif_info *ni = be->be_private;
+       ldap_pvt_thread_mutex_destroy(&ni->li_mutex);
+       free( be->be_private );
+       return 0;
+}
+
+static int
+ldif_back_db_open(
+                 Backend       *be
+                 )
+{
+       struct ldif_info *ni = (struct ldif_info *) be->be_private;
+       if( BER_BVISEMPTY(&ni->li_base_path)) {/* missing base path */
+         fprintf(stderr, "missing base path for back-ldif\n");
+         return 1;
+       }
+       return 0;
+}
+
+int
+ldif_back_initialize(
+                    BackendInfo        *bi
+                    )
+{
+       bi->bi_open = 0;
+       bi->bi_close = 0;
+       bi->bi_config = 0;
+       bi->bi_destroy = 0;
+
+       bi->bi_db_init = ldif_back_db_init;
+       bi->bi_db_config = ldif_back_db_config;
+       bi->bi_db_open = ldif_back_db_open;
+       bi->bi_db_close = 0;
+       bi->bi_db_destroy = ldif_back_db_destroy;
+
+       bi->bi_op_bind = ldif_back_bind;
+       bi->bi_op_unbind = 0;
+       bi->bi_op_search = ldif_back_search;
+       bi->bi_op_compare = ldif_back_compare;
+       bi->bi_op_modify = ldif_back_modify;
+       bi->bi_op_modrdn = ldif_back_modrdn;
+       bi->bi_op_add = ldif_back_add;
+       bi->bi_op_delete = ldif_back_delete;
+       bi->bi_op_abandon = 0;
+
+       bi->bi_extended = 0;
+
+       bi->bi_chk_referrals = 0;
+
+       bi->bi_connection_init = 0;
+       bi->bi_connection_destroy = 0;
+
+       bi->bi_tool_entry_open = ldif_tool_entry_open;
+       bi->bi_tool_entry_close = ldif_tool_entry_close;
+       bi->bi_tool_entry_first = ldif_tool_entry_first;
+       bi->bi_tool_entry_next = ldif_tool_entry_next;
+       bi->bi_tool_entry_get = ldif_tool_entry_get;
+       bi->bi_tool_entry_put = ldif_tool_entry_put;
+       bi->bi_tool_entry_reindex = 0;
+       bi->bi_tool_sync = 0;
+       
+       bi->bi_tool_dn2id_get = 0;
+       bi->bi_tool_id2entry_get = 0;
+       bi->bi_tool_entry_modify = 0;
+
+       return 0;
+}
index fe9af550d499b8e1bb14232228666680b49a4d6e..857ce7ec5f452c6b3a158990fb38faa6a1b978bd 100644 (file)
@@ -51,14 +51,12 @@ meta_back_add( Operation *op, SlapReply *rs )
         * get the current connection
         */
        lc = meta_back_getconn( op, rs, META_OP_REQUIRE_SINGLE,
-                       &op->o_req_ndn, &candidate );
-       if ( !lc ) {
-               send_ldap_result( op, rs );
+                       &op->o_req_ndn, &candidate, LDAP_BACK_SENDERR );
+       if ( !lc || !meta_back_dobind( lc, op, LDAP_BACK_SENDERR ) ) {
                return rs->sr_err;
        }
 
-       if ( !meta_back_dobind( lc, op )
-                       || !meta_back_is_valid( lc, candidate ) ) {
+       if ( !meta_back_is_valid( lc, candidate ) ) {
                rs->sr_err = LDAP_UNAVAILABLE;
                send_ldap_result( op, rs );
                return rs->sr_err;
index 3ead454bb45ad38946787d6598467ee48531a9cf..6df5a58e5c7149be6def00eac32c788fd781a0cd 100644 (file)
@@ -215,7 +215,14 @@ struct metainfo {
        ldap_pvt_thread_mutex_t conn_mutex;
        Avlnode                 *conntree;
 
-       int                     savecred;
+       unsigned                flags;
+/* defined in <back-ldap/back-ldap.h>
+#define LDAP_BACK_F_NONE               0x00U
+#define LDAP_BACK_F_SAVECRED           0x01U
+#define LDAP_BACK_F_USE_TLS            0x02U
+#define LDAP_BACK_F_TLS_CRITICAL       ( 0x04U | LDAP_BACK_F_USE_TLS )
+#define LDAP_BACK_F_CHASE_REFERRALS    0x8U
+*/
 };
 
 #define META_OP_ALLOW_MULTIPLE         0x00
@@ -227,13 +234,15 @@ meta_back_getconn(
                SlapReply               *rs,
                int                     op_type,
                struct berval           *dn,
-               int                     *candidate
+               int                     *candidate,
+               ldap_back_send_t        sendok
 );
 
 extern int
 meta_back_dobind(
                struct metaconn         *lc,
-               Operation               *op
+               Operation               *op,
+               ldap_back_send_t        sendok
 );
 
 extern int
index 0dde00f58452c78d516378613f92e03667eb7bc9..69fe2ea995ea527d5f127a425f0484a6123dad0f 100644 (file)
@@ -63,7 +63,7 @@ meta_back_bind( Operation *op, SlapReply *rs )
                op_type = META_OP_REQUIRE_ALL;
        }
        lc = meta_back_getconn( op, rs, op_type,
-                       &op->o_req_ndn, NULL );
+                       &op->o_req_ndn, NULL, LDAP_BACK_SENDERR );
        if ( !lc ) {
                Debug( LDAP_DEBUG_ANY,
                                "meta_back_bind: no target for dn %s.\n%s%s",
@@ -248,7 +248,7 @@ retry:;
        lsc->msc_bound = META_BOUND;
        lc->mc_bound_target = candidate;
 
-       if ( li->savecred ) {
+       if ( LDAP_BACK_SAVECRED( li ) ) {
                if ( !BER_BVISNULL( &lsc->msc_cred ) ) {
                        /* destroy sensitive data */
                        memset( lsc->msc_cred.bv_val, 0, lsc->msc_cred.bv_len );
@@ -277,7 +277,7 @@ return_results:;
  * meta_back_dobind
  */
 int
-meta_back_dobind( struct metaconn *lc, Operation *op )
+meta_back_dobind( struct metaconn *lc, Operation *op, ldap_back_send_t sendok )
 {
        struct metasingleconn   *lsc;
        int                     bound = 0, i;
@@ -328,7 +328,7 @@ meta_back_dobind( struct metaconn *lc, Operation *op )
                        BER_BVZERO( &lsc->msc_cred );
                }
 
-               /* FIXME: should be check if at least some of the op->o_ctrls
+               /* FIXME: should we check if at least some of the op->o_ctrls
                 * can/should be passed? */
                rc = ldap_sasl_bind( lsc->msc_ld, "", LDAP_SASL_SIMPLE, &cred,
                                NULL, NULL, &msgid );
index 3418717f7e88c61cec5eafc3dbdde94cb9f79a3b..ee15d1495d459409ef229e72c45721aecfee50ac 100644 (file)
@@ -51,18 +51,11 @@ meta_back_compare( Operation *op, SlapReply *rs )
        dncookie                dc;
 
        lc = meta_back_getconn( op, rs, META_OP_ALLOW_MULTIPLE,
-                       &op->o_req_ndn, NULL );
-       if ( !lc ) {
-               send_ldap_result( op, rs );
-               return -1;
+                       &op->o_req_ndn, NULL, LDAP_BACK_SENDERR );
+       if ( !lc || !meta_back_dobind( lc, op, LDAP_BACK_SENDERR ) ) {
+               return rs->sr_err;
        }
        
-       if ( !meta_back_dobind( lc, op ) ) {
-               rs->sr_err = LDAP_UNAVAILABLE;
-               send_ldap_result( op, rs );
-               return -1;
-       }
-
        msgid = ch_calloc( sizeof( int ), li->ntargets );
        if ( msgid == NULL ) {
                return -1;
index 28b057ed01e14bebfef21581c42609dac8d4dede..a7a6fa1805f6049f67ba74f6a9519c65bffd0d15 100644 (file)
@@ -384,7 +384,73 @@ meta_back_db_config(
                            fname, lineno );
                        return( 1 );
                }
-               li->savecred = 1;
+
+               li->flags |= LDAP_BACK_F_SAVECRED;
+
+       } else if ( strcasecmp( argv[0], "chase-referrals" ) == 0 ) {
+               if ( argc != 1 ) {
+                       fprintf( stderr,
+       "%s: line %d: \"chase-referrals\" takes no arguments\n",
+                                       fname, lineno );
+                       return( 1 );
+               }
+
+               li->flags |= LDAP_BACK_F_CHASE_REFERRALS;
+
+       } else if ( strcasecmp( argv[0], "dont-chase-referrals" ) == 0 ) {
+               if ( argc != 1 ) {
+                       fprintf( stderr,
+       "%s: line %d: \"dont-chase-referrals\" takes no arguments\n",
+                                       fname, lineno );
+                       return( 1 );
+               }
+
+               li->flags &= ~LDAP_BACK_F_CHASE_REFERRALS;
+
+       } else if ( strncasecmp( argv[0], "tls-", STRLENOF( "tls-" ) ) == 0 ) {
+
+               /* start tls */
+               if ( strcasecmp( argv[0], "tls-start" ) == 0 ) {
+                       if ( argc != 1 ) {
+                               fprintf( stderr,
+               "%s: line %d: tls-start takes no arguments\n",
+                                               fname, lineno );
+                               return( 1 );
+                       }
+                       li->flags |= ( LDAP_BACK_F_USE_TLS | LDAP_BACK_F_TLS_CRITICAL );
+       
+               /* try start tls */
+               } else if ( strcasecmp( argv[0], "tls-try-start" ) == 0 ) {
+                       if ( argc != 1 ) {
+                               fprintf( stderr,
+               "%s: line %d: tls-try-start takes no arguments\n",
+                                               fname, lineno );
+                               return( 1 );
+                       }
+                       li->flags &= ~LDAP_BACK_F_TLS_CRITICAL;
+                       li->flags |= LDAP_BACK_F_USE_TLS;
+       
+               /* propagate start tls */
+               } else if ( strcasecmp( argv[0], "tls-propagate" ) == 0 ) {
+                       if ( argc != 1 ) {
+                               fprintf( stderr,
+               "%s: line %d: tls-propagate takes no arguments\n",
+                                               fname, lineno );
+                               return( 1 );
+                       }
+                       li->flags |= ( LDAP_BACK_F_PROPAGATE_TLS | LDAP_BACK_F_TLS_CRITICAL );
+               
+               /* try start tls */
+               } else if ( strcasecmp( argv[0], "tls-try-propagate" ) == 0 ) {
+                       if ( argc != 1 ) {
+                               fprintf( stderr,
+               "%s: line %d: tls-try-propagate takes no arguments\n",
+                                               fname, lineno );
+                               return( 1 );
+                       }
+                       li->flags &= ~LDAP_BACK_F_TLS_CRITICAL;
+                       li->flags |= LDAP_BACK_F_PROPAGATE_TLS;
+               }
        
        /* name to use as pseudo-root dn */
        } else if ( strcasecmp( argv[ 0 ], "pseudorootdn" ) == 0 ) {
index 78fe9b4ccfd69bd89551aa2964cf6579544ed555..3b31118c3fabdcb1d155c366c1409b7c0bac59aa 100644 (file)
@@ -186,8 +186,8 @@ init_one_conn(
                Operation               *op,
                SlapReply               *rs,
                struct metatarget       *lt, 
-               struct metasingleconn   *lsc
-               )
+               struct metasingleconn   *lsc,
+               ldap_back_send_t        sendok )
 {
        struct metainfo *li = ( struct metainfo * )op->o_bd->be_private;
        int             vers;
@@ -205,7 +205,7 @@ init_one_conn(
         */
        rs->sr_err = ldap_initialize( &lsc->msc_ld, lt->mt_uri );
        if ( rs->sr_err != LDAP_SUCCESS ) {
-               return slap_map_api2result( rs );
+               goto error_return;
        }
 
        /*
@@ -214,8 +214,100 @@ init_one_conn(
         */
        vers = op->o_conn->c_protocol;
        ldap_set_option( lsc->msc_ld, LDAP_OPT_PROTOCOL_VERSION, &vers );
-       /* FIXME: configurable? */
-       ldap_set_option( lsc->msc_ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON );
+
+       /* automatically chase referrals ("chase-referrals"/"dont-chase-referrals" statement) */
+       if ( LDAP_BACK_CHASE_REFERRALS( li ) ) {
+               ldap_set_option( lsc->msc_ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON );
+       }
+
+#ifdef HAVE_TLS
+       /* start TLS ("start-tls"/"try-start-tls" statements) */
+       if ( ( LDAP_BACK_USE_TLS( li ) || ( op->o_conn->c_is_tls && LDAP_BACK_PROPAGATE_TLS( li ) ) )
+                       && !ldap_is_ldaps_url( lt->mt_uri ) )
+       {
+#if 1
+               /*
+                * use asynchronous StartTLS
+                * in case, chase referral (not implemented yet)
+                */
+               int             msgid;
+
+               rs->sr_err = ldap_start_tls( lsc->msc_ld, NULL, NULL, &msgid );
+               if ( rs->sr_err == LDAP_SUCCESS ) {
+                       LDAPMessage     *res = NULL;
+                       int             rc, retries = 1;
+                       struct timeval  tv = { 0, 0 };
+
+retry:;
+                       rc = ldap_result( lsc->msc_ld, msgid, LDAP_MSG_ALL, &tv, &res );
+                       if ( rc < 0 ) {
+                               rs->sr_err = LDAP_OTHER;
+
+                       } else if ( rc == 0 ) {
+                               if ( retries ) {
+                                       retries--;
+                                       tv.tv_sec = 0;
+                                       tv.tv_usec = 100000;
+                                       goto retry;
+                               }
+                               rs->sr_err = LDAP_OTHER;
+
+                       } else if ( rc == LDAP_RES_EXTENDED ) {
+                               struct berval   *data = NULL;
+
+                               rs->sr_err = ldap_parse_extended_result( lsc->msc_ld, res,
+                                               NULL, &data, 0 );
+                               if ( rs->sr_err == LDAP_SUCCESS ) {
+                                       rs->sr_err = ldap_result2error( lsc->msc_ld, res, 1 );
+                                       res = NULL;
+                                       
+                                       /* FIXME: in case a referral 
+                                        * is returned, should we try
+                                        * using it instead of the 
+                                        * configured URI? */
+                                       if ( rs->sr_err == LDAP_SUCCESS ) {
+                                               ldap_install_tls( lsc->msc_ld );
+
+                                       } else if ( rs->sr_err == LDAP_REFERRAL ) {
+                                               rs->sr_err = LDAP_OTHER;
+                                               rs->sr_text = "unwilling to chase referral returned by Start TLS exop";
+                                       }
+
+                                       if ( data ) {
+                                               if ( data->bv_val ) {
+                                                       ber_memfree( data->bv_val );
+                                               }
+                                               ber_memfree( data );
+                                       }
+                               }
+
+                       } else {
+                               rs->sr_err = LDAP_OTHER;
+                       }
+
+                       if ( res != NULL ) {
+                               ldap_msgfree( res );
+                       }
+               }
+#else
+               /*
+                * use synchronous StartTLS
+                */
+               rs->sr_err = ldap_start_tls_s( lsc->msc_ld, NULL, NULL );
+#endif
+
+               /* if StartTLS is requested, only attempt it if the URL
+                * is not "ldaps://"; this may occur not only in case
+                * of misconfiguration, but also when used in the chain 
+                * overlay, where the "uri" can be parsed out of a referral */
+               if ( rs->sr_err == LDAP_SERVER_DOWN
+                               || ( rs->sr_err != LDAP_SUCCESS && LDAP_BACK_TLS_CRITICAL( li ) ) )
+               {
+                       ldap_unbind_ext_s( lsc->msc_ld, NULL, NULL );
+                       goto error_return;
+               }
+       }
+#endif /* HAVE_TLS */
 
        /*
         * Set the network timeout if set
@@ -238,7 +330,7 @@ init_one_conn(
        /*
         * If the connection DN is not null, an attempt to rewrite it is made
         */
-       if ( op->o_conn->c_dn.bv_len != 0 ) {
+       if ( !BER_BVISEMPTY( &op->o_conn->c_dn ) ) {
                dc.rwmap = &lt->mt_rwmap;
                dc.conn = op->o_conn;
                dc.rs = rs;
@@ -250,8 +342,7 @@ init_one_conn(
                if ( ldap_back_dn_massage( &dc, &op->o_conn->c_dn,
                                        &lsc->msc_bound_ndn ) )
                {
-                       send_ldap_result( op, rs );
-                       return rs->sr_err;
+                       goto error_return;
                }
 
                /* copy the DN idf needed */
@@ -259,7 +350,7 @@ init_one_conn(
                        ber_dupbv( &lsc->msc_bound_ndn, &op->o_conn->c_dn );
                }
 
-               assert( lsc->msc_bound_ndn.bv_val );
+               assert( !BER_BVISNULL( &lsc->msc_bound_ndn ) );
 
        } else {
                ber_str2bv( "", 0, 1, &lsc->msc_bound_ndn );
@@ -267,11 +358,23 @@ init_one_conn(
 
        lsc->msc_bound = META_UNBOUND;
 
-       /*
-        * The candidate is activated
-        */
-       lsc->msc_candidate = META_CANDIDATE;
-       return LDAP_SUCCESS;
+error_return:;
+       if ( rs->sr_err != LDAP_SUCCESS ) {
+               rs->sr_err = slap_map_api2result( rs );
+               if ( sendok & LDAP_BACK_SENDERR ) {
+                       send_ldap_result( op, rs );
+                       rs->sr_text = NULL;
+               }
+
+       } else {
+
+               /*
+                * The candidate is activated
+                */
+               lsc->msc_candidate = META_CANDIDATE;
+       }
+
+       return rs->sr_err;
 }
 
 /*
@@ -288,11 +391,12 @@ init_one_conn(
  */
 struct metaconn *
 meta_back_getconn(
-               Operation       *op,
-               SlapReply       *rs,
-               int             op_type,
-               struct berval   *ndn,
-               int             *candidate )
+               Operation               *op,
+               SlapReply               *rs,
+               int                     op_type,
+               struct berval           *ndn,
+               int                     *candidate,
+               ldap_back_send_t        sendok )
 {
        struct metainfo *li = ( struct metainfo * )op->o_bd->be_private;
        struct metaconn *lc, lc_curr;
@@ -326,7 +430,7 @@ meta_back_getconn(
                         * also init'd
                         */
                        int lerr = init_one_conn( op, rs, li->targets[ i ],
-                                       &lc->mc_conns[ i ] );
+                                       &lc->mc_conns[ i ], sendok );
                        if ( lerr != LDAP_SUCCESS ) {
                                
                                /*
@@ -386,7 +490,7 @@ meta_back_getconn(
                 * sends the appropriate result.
                 */
                err = init_one_conn( op, rs, li->targets[ i ],
-                               &lc->mc_conns[ i ] );
+                               &lc->mc_conns[ i ], sendok );
                if ( err != LDAP_SUCCESS ) {
                
                        /*
@@ -420,7 +524,7 @@ meta_back_getconn(
                                 */
                                int lerr = init_one_conn( op, rs,
                                                li->targets[ i ],
-                                               &lc->mc_conns[ i ] );
+                                               &lc->mc_conns[ i ], sendok );
                                if ( lerr != LDAP_SUCCESS ) {
                                
                                        /*
index cd719c08d5e8102b4891857d2ac76a6e8883c5b0..646cbe8de646ad16823aeec17392017e11ab3be6 100644 (file)
@@ -41,22 +41,15 @@ meta_back_delete( Operation *op, SlapReply *rs )
        dncookie dc;
 
        lc = meta_back_getconn( op, rs, META_OP_REQUIRE_SINGLE,
-                       &op->o_req_ndn, &candidate );
-       if ( !lc ) {
-               send_ldap_result( op, rs );
-               return -1;
+                       &op->o_req_ndn, &candidate, LDAP_BACK_SENDERR );
+       if ( !lc || !meta_back_dobind( lc, op, LDAP_BACK_SENDERR ) ) {
+               return rs->sr_err;
        }
-       
-       if ( !meta_back_dobind( lc, op ) ) {
-               rs->sr_err = LDAP_UNAVAILABLE;
 
-       } else if ( !meta_back_is_valid( lc, candidate ) ) {
+       if ( !meta_back_is_valid( lc, candidate ) ) {
                rs->sr_err = LDAP_OTHER;
-       }
-
-       if ( rs->sr_err != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
-               return -1;
+               return rs->sr_err;
        }
 
        /*
index cd0a3ec00ec6b8ee2d3c2a4af9097d69f98e1c89..e09b9c35666347c744093e4da5a41ad4b6ca7f9c 100644 (file)
@@ -47,22 +47,15 @@ meta_back_modify( Operation *op, SlapReply *rs )
        dncookie        dc;
 
        lc = meta_back_getconn( op, rs, META_OP_REQUIRE_SINGLE,
-                       &op->o_req_ndn, &candidate );
-       if ( !lc ) {
-               rc = -1;
-               goto cleanup;
+                       &op->o_req_ndn, &candidate, LDAP_BACK_SENDERR );
+       if ( !lc || !meta_back_dobind( lc, op, LDAP_BACK_SENDERR ) ) {
+               return rs->sr_err;
        }
        
-       if ( !meta_back_dobind( lc, op ) ) {
-               rs->sr_err = LDAP_UNAVAILABLE;
-
-       } else if ( !meta_back_is_valid( lc, candidate ) ) {
+       if ( !meta_back_is_valid( lc, candidate ) ) {
                rs->sr_err = LDAP_OTHER;
-       }
-
-       if ( rs->sr_err != LDAP_SUCCESS ) {
-               rc = -1;
-               goto cleanup;
+               send_ldap_result( op, rs );
+               return rs->sr_err;
        }
 
        /*
index 756ae36d387c71526d402a34d3a94ec58427889e..a0d7e408ccd443925aa01126eb17465e8dc9f864 100644 (file)
@@ -43,24 +43,21 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
        dncookie                dc;
 
        lc = meta_back_getconn( op, rs, META_OP_REQUIRE_SINGLE,
-                       &op->o_req_ndn, &candidate );
+                       &op->o_req_ndn, &candidate, LDAP_BACK_SENDERR );
        if ( !lc ) {
-               rc = -1;
-               goto cleanup;
+               return rs->sr_err;
        }
 
        assert( candidate != META_TARGET_NONE );
 
-       if ( !meta_back_dobind( lc, op ) ) {
-               rs->sr_err = LDAP_UNAVAILABLE;
-
-       } else if ( !meta_back_is_valid( lc, candidate ) ) {
-               rs->sr_err = LDAP_OTHER;
+       if ( !meta_back_dobind( lc, op, LDAP_BACK_SENDERR ) ) {
+               return rs->sr_err;
        }
-
-       if ( rs->sr_err != LDAP_SUCCESS ) {
-               rc = -1;
-               goto cleanup;
+               
+       if ( !meta_back_is_valid( lc, candidate ) ) {
+               rs->sr_err = LDAP_OTHER;
+               send_ldap_result( op, rs );
+               return rs->sr_err;
        }
 
        dc.conn = op->o_conn;
index 6bc693b64b9893542f00576a828d325edd58ccd3..3dbd522a8be9a3b305032280a155caaef129ed33 100644 (file)
@@ -71,16 +71,9 @@ meta_back_search( Operation *op, SlapReply *rs )
         * to map attrs and maybe rewrite value
         */
        lc = meta_back_getconn( op, rs, META_OP_ALLOW_MULTIPLE, 
-                       &op->o_req_ndn, NULL );
-       if ( !lc ) {
-               send_ldap_result( op, rs );
-               return -1;
-       }
-
-       if ( !meta_back_dobind( lc, op ) ) {
-               rs->sr_err = LDAP_UNAVAILABLE;
-               send_ldap_result( op, rs );
-               return -1;
+                       &op->o_req_ndn, NULL, LDAP_BACK_SENDERR );
+       if ( !lc || !meta_back_dobind( lc, op, LDAP_BACK_SENDERR ) ) {
+               return rs->sr_err;
        }
 
        /*
@@ -310,7 +303,7 @@ new_candidate:;
                        
                        if ( ab ) {
                                ldap_abandon_ext( lsc->msc_ld, msgid[ i ], NULL, NULL );
-                               rc = 0;
+                               rc = SLAPD_ABANDON;
                                break;
                        }
 
index 1312d891a58004555e0986fccdd0a26d0821eb88..5acedec8ca62d38c332a522293caba376e9d25bf 100644 (file)
@@ -30,7 +30,7 @@
 
 #if defined(LDAP_SLAPI)
 #include "slapi.h"
-static int monitor_back_add_plugin( Backend *be, Entry *e );
+static int monitor_back_add_plugin( monitor_info_t *mi, Backend *be, Entry *e );
 #endif /* defined(LDAP_SLAPI) */
 
 #if defined(SLAPD_BDB)
@@ -391,7 +391,7 @@ monitor_subsys_database_init(
                }
 
 #if defined(LDAP_SLAPI)
-               monitor_back_add_plugin( be, e );
+               monitor_back_add_plugin( mi, be, e );
 #endif /* defined(LDAP_SLAPI) */
 
                if ( oi != NULL ) {
@@ -829,11 +829,10 @@ done:;
 
 #if defined(LDAP_SLAPI)
 static int
-monitor_back_add_plugin( Backend *be, Entry *e_database )
+monitor_back_add_plugin( monitor_info_t *mi, Backend *be, Entry *e_database )
 {
        Slapi_PBlock    *pCurrentPB; 
        int             i, rc = LDAP_SUCCESS;
-       monitor_info_t  *mi = ( monitor_info_t * )be->be_private;
 
        if ( slapi_int_pblock_get_first( be, &pCurrentPB ) != LDAP_SUCCESS ) {
                /*
index cfb55531e505e5fb1b2078cdcf3eca324e7975ad..ab2c7c1a2262af6289fd10dcf39a556db774de9f 100644 (file)
@@ -143,7 +143,7 @@ passwd_back_search(
                                if ( op->o_abandon ) {
                                        endpwent();
                                        ldap_pvt_thread_mutex_unlock( &passwd_mutex );
-                                       return( -1 );
+                                       return( SLAPD_ABANDON );
                                }
 
                                /* check time limit */
index 49af9ed694e9513f419c4d4c07013c31f9b54146..d905d2bf23943e7081101af57d330bfe11488c8a 100644 (file)
@@ -444,7 +444,6 @@ typedef struct backsql_srch_info {
                                **bsi_id_listtail,
                                *bsi_c_eid;
        int                     bsi_n_candidates;
-       int                     bsi_abandon;
        int                     bsi_status;
 
        backsql_oc_map_rec      *bsi_oc;
index 0381f6974f554bfc58e839e3b2e48f98d22ed49f..da3cea0d21fd9aa791a236147ed1a300dd15974c 100644 (file)
@@ -253,7 +253,6 @@ backsql_init_search(
                }
        }
 
-       bsi->bsi_abandon = 0;
        bsi->bsi_id_list = NULL;
        bsi->bsi_id_listtail = &bsi->bsi_id_list;
        bsi->bsi_n_candidates = 0;
@@ -1464,6 +1463,12 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi )
        Debug( LDAP_DEBUG_TRACE, "==>backsql_oc_get_candidates(): oc=\"%s\"\n",
                        BACKSQL_OC_NAME( oc ), 0, 0 );
 
+       /* check for abandon */
+       if ( op->o_abandon ) {
+               bsi->bsi_status = SLAPD_ABANDON;
+               return BACKSQL_AVL_STOP;
+       }
+
        if ( bsi->bsi_n_candidates == -1 ) {
                Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
                        "unchecked limit has been overcome\n", 0, 0, 0 );
@@ -1943,6 +1948,12 @@ backsql_search( Operation *op, SlapReply *rs )
                 */
                avl_apply( bi->sql_oc_by_oc, backsql_oc_get_candidates,
                                &bsi, BACKSQL_AVL_STOP, AVL_INORDER );
+
+               /* check for abandon */
+               if ( op->o_abandon ) {
+                       rs->sr_err = SLAPD_ABANDON;
+                       goto send_results;
+               }
        }
 
        if ( op->ors_limit != NULL      /* isroot == FALSE */
@@ -1973,7 +1984,8 @@ backsql_search( Operation *op, SlapReply *rs )
 
                /* check for abandon */
                if ( op->o_abandon ) {
-                       break;
+                       rs->sr_err = SLAPD_ABANDON;
+                       goto send_results;
                }
 
                /* check time limit */
@@ -1983,10 +1995,7 @@ backsql_search( Operation *op, SlapReply *rs )
                        rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
                        rs->sr_ctrls = NULL;
                        rs->sr_ref = rs->sr_v2ref;
-                       rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS
-                               : LDAP_REFERRAL;
-                       send_ldap_result( op, rs );
-                       goto end_of_search;
+                       goto send_results;
                }
 
 #ifdef BACKSQL_ARBITRARY_KEY
@@ -2217,17 +2226,11 @@ next_entry2:;
                                && rs->sr_nentries >= op->ors_slimit )
                {
                        rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
-                       send_ldap_result( op, rs );
-                       goto end_of_search;
+                       goto send_results;
                }
        }
 
 end_of_search:;
-       entry_clean( &base_entry );
-
-       /* in case we got here accidentally */
-       entry_clean( &user_entry );
-
        if ( rs->sr_nentries > 0 ) {
                rs->sr_ref = rs->sr_v2ref;
                rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS
@@ -2236,7 +2239,16 @@ end_of_search:;
        } else {
                rs->sr_err = bsi.bsi_status;
        }
-       send_ldap_result( op, rs );
+
+send_results:;
+       if ( rs->sr_err != SLAPD_ABANDON ) {
+               send_ldap_result( op, rs );
+       }
+
+       entry_clean( &base_entry );
+
+       /* in case we got here accidentally */
+       entry_clean( &user_entry );
 
        if ( rs->sr_v2ref ) {
                ber_bvarray_free( rs->sr_v2ref );
@@ -2284,7 +2296,8 @@ done:;
        }
 
        Debug( LDAP_DEBUG_TRACE, "<==backsql_search()\n", 0, 0, 0 );
-       return 0;
+
+       return rs->sr_err;
 }
 
 /* return LDAP_SUCCESS IFF we can retrieve the specified entry.
index 577b3309535737e5d79c921514957bc92f980c09..171b688354f6411bacc82addfedea4d0bf0e40bf 100644 (file)
@@ -578,7 +578,7 @@ static ConfigOCs cf_ocs[] = {
                "NAME 'olcDatabaseConfig' "
                "DESC 'OpenLDAP Database-specific options' "
                "SUP olcConfig STRUCTURAL "
-               "MAY ( olcDatabase $ olcAccess $ olcLastMod $ olcLimits $ "
+               "MAY ( olcDatabase $ olcLastMod $ olcLimits $ "
                 "olcMaxDerefDepth $ olcPlugin $ olcReadOnly $ olcReplica $ "
                 "olcReplogFile $ olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ "
                 "olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSuffix $ olcSyncrepl $ "
@@ -2862,7 +2862,6 @@ config_back_db_open( BackendDB *be )
                                oprev = ce;
                        }
                }
-#if 0
                /* Set up ACLs */
                if ( bptr->be_acl ) {
                        Entry *ae;
@@ -2881,7 +2880,6 @@ config_back_db_open( BackendDB *be )
                        }
                        opar->ce_kids = ce;
                }
-#endif
        }
 
        return 0;
@@ -2911,9 +2909,6 @@ config_back_db_init( Backend *be )
        ber_dupbv( &dn, &be->be_rootdn );
        ber_bvarray_add( &be->be_nsuffix, &dn );
 
-       /* Hide from namingContexts */
-       SLAP_BFLAGS(be) |= SLAP_BFLAG_CONFIG;
-
        return 0;
 }
 
index 9f95972edc29e1c6eed49e797d7890c39224122e..7abf065c22d0fe9ae03c175223596eb7baafb50b 100644 (file)
@@ -23,6 +23,7 @@ SRCS = overlays.c \
        refint.c \
        rwm.c rwmconf.c rwmdn.c rwmmap.c \
        syncprov.c \
+       translucent.c \
        unique.c
 OBJS = overlays.lo \
        denyop.lo \
@@ -34,6 +35,7 @@ OBJS = overlays.lo \
        refint.lo \
        rwm.lo rwmconf.lo rwmdn.lo rwmmap.lo \
        syncprov.lo \
+       translucent.lo \
        unique.lo
 
 LDAP_INCDIR= ../../../include       
@@ -78,6 +80,9 @@ rwm.la : rwm.lo $(@PLAT@_LINK_LIBS)
 syncprov.la : syncprov.lo $(@PLAT@_LINK_LIBS)
        $(LTLINK_MOD) -module -o $@ syncprov.lo version.lo $(LINK_LIBS)
 
+translucent.la : translucent.lo $(@PLAT@_LINK_LIBS)
+       $(LTLINK_MOD) -module -o $@ translucent.lo version.lo $(LINK_LIBS)
+
 unique.la : unique.lo $(@PLAT@_LINK_LIBS)
        $(LTLINK_MOD) -module -o $@ unique.lo version.lo $(LINK_LIBS)
 
index a09176e5c71f45dc92fc10cdd8f688b698b0a602..b5e53f13c868c6aed96268e374bf32e666eccecc 100644 (file)
@@ -396,7 +396,9 @@ end_of_loop:;
 
                break;
        }
-       if ( !op->o_abandon ) {
+       if ( op->o_abandon ) {
+               rs->sr_err = SLAPD_ABANDON;
+       } else {
                op->o_callback = cb.sc_next;
                rs->sr_err = gs.err;
                rs->sr_matched = gs.matched;
index 3e73167b208b315af15cafa3c1b8e23e3caa6959..8b1a19ec98c7d366b5fd9dfac732a325f54c90af 100644 (file)
@@ -50,6 +50,9 @@ extern int rwm_init();
 #if SLAPD_OVER_SYNCPROV == SLAPD_MOD_STATIC
 extern int syncprov_init();
 #endif
+#if SLAPD_OVER_TRANSLUCENT == SLAPD_MOD_STATIC
+extern int translucent_init();
+#endif
 #if SLAPD_OVER_UNIQUE == SLAPD_MOD_STATIC
 extern int unique_init();
 #endif
@@ -85,6 +88,9 @@ static struct {
 #if SLAPD_OVER_SYNCPROV == SLAPD_MOD_STATIC
        { "Syncrepl Provider", syncprov_init },
 #endif
+#if SLAPD_OVER_TRANSLUCENT == SLAPD_MOD_STATIC
+       { "Translucent Proxy", translucent_init },
+#endif
 #if SLAPD_OVER_UNIQUE == SLAPD_MOD_STATIC
        { "Attribute Uniqueness", unique_init },
 #endif
index 00227172c6c4db13531027568fcdc80d37acff28..b696e379427ac3b434ef4325fc62cb6fca642405 100644 (file)
@@ -171,8 +171,8 @@ rwm_op_add( Operation *op, SlapReply *rs )
                                }
                        }
 
-                       if ( (*ap)->a_desc->ad_type->sat_syntax
-                                       == slap_schema.si_syn_distinguishedName )
+                       if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
+                                       || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
                        {
                                /*
                                 * FIXME: rewrite could fail; in this case
@@ -327,7 +327,8 @@ rwm_op_compare( Operation *op, SlapReply *rs )
                        ad = mapping->m_dst_ad;
                }
 
-               if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
+               if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
+                               || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
                {
                        struct berval   *mapped_valsp[2];
                        
@@ -436,11 +437,11 @@ rwm_op_modify( Operation *op, SlapReply *rs )
                                last--;
 
                                for ( j = 0; !BER_BVISNULL( &(*mlp)->sml_values[ j ] ); j++ ) {
-                                       struct ldapmapping      *mapping = NULL;
-
+                                       struct ldapmapping      *oc_mapping = NULL;
+               
                                        ( void )rwm_mapping( &rwmap->rwm_oc, &(*mlp)->sml_values[ j ],
-                                                       &mapping, RWM_MAP );
-                                       if ( mapping == NULL ) {
+                                                       &oc_mapping, RWM_MAP );
+                                       if ( oc_mapping == NULL ) {
                                                if ( rwmap->rwm_at.drop_missing ) {
                                                        /* FIXME: we allow to remove objectClasses as well;
                                                         * if the resulting entry is inconsistent, that's
@@ -457,13 +458,13 @@ rwm_op_modify( Operation *op, SlapReply *rs )
        
                                        } else {
                                                ch_free( (*mlp)->sml_values[ j ].bv_val );
-                                               ber_dupbv( &(*mlp)->sml_values[ j ], &mapping->m_dst );
+                                               ber_dupbv( &(*mlp)->sml_values[ j ], &oc_mapping->m_dst );
                                        }
                                }
 
                        } else {
-                               if ( (*mlp)->sml_desc->ad_type->sat_syntax ==
-                                               slap_schema.si_syn_distinguishedName )
+                               if ( (*mlp)->sml_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
+                                               || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
                                {
 #ifdef ENABLE_REWRITE
                                        rc = rwm_dnattr_rewrite( op, rs, "modifyAttrDN",
@@ -516,7 +517,6 @@ cleanup_mod:;
                free( ml );
        }
 
-       /* TODO: rewrite attribute types, values of DN-valued attributes ... */
        return SLAP_CB_CONTINUE;
 }
 
@@ -822,7 +822,7 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
         * about duplicate values?) */
        isupdate = be_shadow_update( op );
        for ( ap = a_first; *ap; ) {
-               struct ldapmapping      *mapping;
+               struct ldapmapping      *mapping = NULL;
                int                     drop_missing;
                int                     last;
                Attribute               *a;
@@ -832,6 +832,13 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
                        /* go on */ ;
                        
                } else {
+                       if ( op->ors_attrs != NULL && 
+                                       !SLAP_USERATTRS( rs->sr_attr_flags ) &&
+                                       !ad_inlist( (*ap)->a_desc, op->ors_attrs ) )
+                       {
+                               goto cleanup_attr;
+                       }
+
                        drop_missing = rwm_mapping( &rwmap->rwm_at,
                                        &(*ap)->a_desc->ad_cname, &mapping, RWM_REMAP );
                        if ( drop_missing || ( mapping != NULL && BER_BVISEMPTY( &mapping->m_dst ) ) )
@@ -842,13 +849,6 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
                        if ( mapping != NULL ) {
                                (*ap)->a_desc = mapping->m_dst_ad;
                        }
-
-                       if ( op->ors_attrs != NULL && 
-                                       !SLAP_USERATTRS( rs->sr_attr_flags ) &&
-                                       !ad_inlist( (*ap)->a_desc, op->ors_attrs ) )
-                       {
-                               goto cleanup_attr;
-                       }
                }
 
                if ( (*ap)->a_desc == slap_schema.si_ad_entryDN ) {
@@ -915,8 +915,8 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
                 * everything pass thru the ldap backend. */
                /* FIXME: handle distinguishedName-like syntaxes, like
                 * nameAndOptionalUID */
-               } else if ( (*ap)->a_desc->ad_type->sat_syntax ==
-                               slap_schema.si_syn_distinguishedName )
+               } else if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
+                               || ( mapping != NULL && mapping->m_src_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
                {
 #ifdef ENABLE_REWRITE
                        dc.ctx = "searchAttrDN";
@@ -1253,7 +1253,9 @@ rwm_response( Operation *op, SlapReply *rs )
        switch( op->o_tag ) {
        case LDAP_REQ_SEARCH:
                /* Note: the operation attrs are remapped */
-               if ( op->ors_attrs != NULL && op->ors_attrs != rs->sr_attrs )
+               if ( rs->sr_type == REP_RESULT
+                               && op->ors_attrs != NULL
+                               && op->ors_attrs != rs->sr_attrs )
                {
                        ch_free( op->ors_attrs );
                        op->ors_attrs = rs->sr_attrs;
index e551f3568a30d9cca49a96cec965b4c5893231d9..e8a630cce6c57d115d33778ccbe478bf365412c7 100644 (file)
@@ -386,7 +386,8 @@ map_attr_value(
        if ( value != NULL ) {
                assert( mapped_value != NULL );
 
-               if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
+               if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
+                               || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
                {
                        dncookie        fdc = *dc;
                        int             rc;
index aa51bcd07ec7b094db044e0d1023dba82b368cb3..c406f5b1fa7fe206f4d7c93da9a7aa9c9c9c44da 100644 (file)
@@ -860,6 +860,16 @@ syncprov_drop_psearch( syncops *so, int lock )
        return 0;
 }
 
+static int
+syncprov_ab_cleanup( Operation *op, SlapReply *rs )
+{
+       slap_callback *sc = op->o_callback;
+       op->o_callback = sc->sc_next;
+       syncprov_drop_psearch( op->o_callback->sc_private, 0 );
+       op->o_tmpfree( sc, op->o_tmpmemctx );
+       return 0;
+}
+
 static int
 syncprov_op_abandon( Operation *op, SlapReply *rs )
 {
@@ -881,8 +891,17 @@ syncprov_op_abandon( Operation *op, SlapReply *rs )
        if ( so ) {
                /* Is this really a Cancel exop? */
                if ( op->o_tag != LDAP_REQ_ABANDON ) {
+                       so->s_op->o_cancel = SLAP_CANCEL_ACK;
                        rs->sr_err = LDAP_CANCELLED;
                        send_ldap_result( so->s_op, rs );
+                       if ( so->s_flags & PS_IS_DETACHED ) {
+                               slap_callback *cb;
+                               cb = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx );
+                               cb->sc_cleanup = syncprov_ab_cleanup;
+                               cb->sc_next = op->o_callback;
+                               cb->sc_private = so;
+                               return SLAP_CB_CONTINUE;
+                       }
                }
                syncprov_drop_psearch( so, 0 );
        }
@@ -1468,6 +1487,18 @@ syncprov_op_mod( Operation *op, SlapReply *rs )
                                ldap_pvt_thread_mutex_unlock( &mt->mt_mutex );
                                ldap_pvt_thread_yield();
                                ldap_pvt_thread_mutex_lock( &mt->mt_mutex );
+
+                               /* clean up if the caller is giving up */
+                               if ( op->o_abandon ) {
+                                       modinst *m2;
+                                       for ( m2 = mt->mt_mods; m2->mi_next != mi;
+                                               m2 = m2->mi_next );
+                                       m2->mi_next = mi->mi_next;
+                                       if ( mt->mt_tail == mi ) mt->mt_tail = m2;
+                                       op->o_tmpfree( cb, op->o_tmpmemctx );
+                                       ldap_pvt_thread_mutex_unlock( &mt->mt_mutex );
+                                       return SLAPD_ABANDON;
+                               }
                        }
                        ldap_pvt_thread_mutex_unlock( &mt->mt_mutex );
                } else {
diff --git a/servers/slapd/overlays/translucent.c b/servers/slapd/overlays/translucent.c
new file mode 100644 (file)
index 0000000..38ff003
--- /dev/null
@@ -0,0 +1,734 @@
+/* Copyright 2004, Symas Corporation.
+ * All Rights Reserved.
+ */
+
+#include "portable.h"
+
+#ifdef SLAPD_OVER_TRANSLUCENT
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+
+/* config block */
+
+typedef struct translucent_configuration {
+       int debug;
+       int strict;
+       int no_add;
+       int glue;
+} translucent_configuration;
+
+/* stack of captive backends */
+
+typedef struct overlay_stack {
+       BackendInfo *info;                      /* captive backend */
+       void *private;                          /* local backend_private */
+       translucent_configuration *config;      /* our_private: configuration */
+} overlay_stack;
+
+/* for translucent_init() */
+
+static slap_overinst translucent;
+
+/*
+** glue_parent()
+**     call syncrepl_add_glue() with the parent suffix;
+**
+*/
+
+static struct berval glue[] = { BER_BVC("top"), BER_BVC("glue"), BER_BVNULL };
+
+void glue_parent(Operation *op) {
+       Operation nop = *op;
+       slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+       struct berval dn = { 0, NULL };
+       char *odn = op->o_req_ndn.bv_val;
+       Attribute *a;
+       Entry *e;
+       int idn, ldn;
+
+       /* tis more work to use strchr() for a berval... */
+       for(idn = 0; odn[idn] && odn[idn] != ','; idn++);
+       if(!idn || !odn[idn]) return;   /* because you never know */
+       idn++;
+       ldn = dn.bv_len = op->o_req_ndn.bv_len - idn;
+       dn.bv_val = ch_malloc(ldn + 1);
+       strcpy(dn.bv_val, odn + idn);
+
+       Debug(LDAP_DEBUG_TRACE, "=> glue_parent: fabricating glue for <%s>\n", dn.bv_val, 0, 0);
+
+       e = ch_calloc(1, sizeof(Entry));
+       e->e_id = NOID;
+       ber_dupbv(&e->e_name, &dn);
+       ber_dupbv(&e->e_nname, &dn);
+
+       a = ch_calloc(1, sizeof(Attribute));
+       a->a_desc = slap_schema.si_ad_objectClass;
+       a->a_vals = ch_malloc(sizeof(struct berval) * 3);
+       ber_dupbv(&a->a_vals[0], &glue[0]);
+       ber_dupbv(&a->a_vals[1], &glue[1]);
+       ber_dupbv(&a->a_vals[2], &glue[2]);
+       a->a_nvals = a->a_vals;
+       a->a_next = e->e_attrs;
+       e->e_attrs = a;
+
+       a = ch_calloc(1, sizeof(Attribute));
+       a->a_desc = slap_schema.si_ad_structuralObjectClass;
+       a->a_vals = ch_malloc(sizeof(struct berval) * 2);
+       ber_dupbv(&a->a_vals[0], &glue[1]);
+       ber_dupbv(&a->a_vals[1], &glue[2]);
+       a->a_nvals = a->a_vals;
+       a->a_next = e->e_attrs;
+       e->e_attrs = a;
+
+       nop.o_req_dn = dn;
+       nop.o_req_ndn = dn;
+       nop.ora_e = e;
+       nop.o_bd->bd_info = (BackendInfo *) on->on_info->oi_orig;
+
+       syncrepl_add_glue(&nop, e);
+       return;
+}
+
+/*
+** dup_bervarray()
+**     copy a BerVarray;
+*/
+
+BerVarray dup_bervarray(BerVarray b) {
+       int i, len;
+       BerVarray nb;
+       for(len = 0; b[len].bv_val; len++);
+       nb = ch_malloc((len+1) * sizeof(BerValue));
+       for(i = 0; i < len; i++) ber_dupbv(&nb[i], &b[i]);
+       nb[len].bv_val = NULL;
+       nb[len].bv_len = 0;
+       return(nb);
+}
+
+/*
+** free_attr_chain()
+**     free only the Attribute*, not the contents;
+**
+*/
+void free_attr_chain(Attribute *a) {
+       Attribute *ax;
+       for(ax = NULL; a; a = a->a_next) {
+               if(ax) ch_free(ax);
+               ax = a;
+       }
+       return;
+}
+
+/*
+** translucent_add()
+**     if not bound as root, send ACCESS error;
+**     if config.glue, glue_parent();
+**     return CONTINUE;
+**
+*/
+
+static int translucent_add(Operation *op, SlapReply *rs) {
+       slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+       overlay_stack *ov = on->on_bi.bi_private;
+       Debug(LDAP_DEBUG_TRACE, "==> translucent_add: %s\n",
+               op->o_req_dn.bv_val, 0, 0);
+       if(!be_isroot(op)) {
+               op->o_bd->bd_info = (BackendInfo *) on->on_info;
+               send_ldap_error(op, rs, LDAP_INSUFFICIENT_ACCESS,
+                       "user modification of overlay database not permitted");
+               return(rs->sr_err);
+       }
+       if(!ov->config->glue) glue_parent(op);
+       return(SLAP_CB_CONTINUE);
+}
+
+/*
+** translucent_modrdn()
+**     if not bound as root, send ACCESS error;
+**     if !config.glue, glue_parent();
+**     else return CONTINUE;
+**
+*/
+
+static int translucent_modrdn(Operation *op, SlapReply *rs) {
+       slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+       overlay_stack *ov = on->on_bi.bi_private;
+       Debug(LDAP_DEBUG_TRACE, "==> translucent_modrdn: %s -> %s\n",
+               op->o_req_dn.bv_val, op->orr_newrdn.bv_val, 0);
+       if(!be_isroot(op)) {
+               op->o_bd->bd_info = (BackendInfo *) on->on_info;
+               send_ldap_error(op, rs, LDAP_INSUFFICIENT_ACCESS,
+                       "user modification of overlay database not permitted");
+               return(rs->sr_err);
+       }
+       if(!ov->config->glue) glue_parent(op);
+       return(SLAP_CB_CONTINUE);
+}
+
+/*
+** translucent_delete()
+**     if not bound as root, send ACCESS error;
+**     else return CONTINUE;
+**
+*/
+
+static int translucent_delete(Operation *op, SlapReply *rs) {
+       slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+       Debug(LDAP_DEBUG_TRACE, "==> translucent_delete: %s\n",
+               op->o_req_dn.bv_val, 0, 0);
+       if(!be_isroot(op)) {
+               op->o_bd->bd_info = (BackendInfo *) on->on_info;
+               send_ldap_error(op, rs, LDAP_INSUFFICIENT_ACCESS,
+                       "user modification of overlay database not permitted");
+               return(rs->sr_err);
+       }
+       return(SLAP_CB_CONTINUE);
+}
+
+/*
+** translucent_modify()
+**     modify in local backend if exists in both;
+**     otherwise, add to local backend;
+**     fail if not defined in captive backend;
+**
+*/
+
+static int translucent_modify(Operation *op, SlapReply *rs) {
+       SlapReply nrs = { REP_RESULT };
+       Operation nop = *op;
+
+       slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+       overlay_stack *ov = on->on_bi.bi_private;
+       translucent_configuration *cf = ov->config;
+       void *private = op->o_bd->be_private;
+       Entry ne, *e, *re = NULL;
+       Attribute *a, *ax;
+       Modifications *m, *mm;
+       int del, rc, erc = 0;
+
+       Debug(LDAP_DEBUG_TRACE, "==> translucent_modify: %s\n",
+               op->o_req_dn.bv_val, 0, 0);
+
+/*
+** fetch entry from the captive backend;
+** if it did not exist, fail;
+** release it, if captive backend supports this;
+**
+*/
+
+       op->o_bd->bd_info = (BackendInfo *) on->on_info;
+       op->o_bd->be_private = ov->private;
+       rc = ov->info->bi_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &re);
+       op->o_bd->be_private = private;
+
+       /* if(ov->config->no_add && (!re || rc != LDAP_SUCCESS)) */
+       if(!re || rc != LDAP_SUCCESS) {
+               send_ldap_error(op, rs, LDAP_NO_SUCH_OBJECT,
+                       "attempt to modify nonexistent local record");
+               return(rs->sr_err);
+       }
+
+/*
+** fetch entry from local backend;
+** if it exists:
+**     foreach Modification:
+**         if attr not present in local:
+**             if Mod == LDAP_MOD_DELETE:
+**                 if remote attr not present, return NO_SUCH;
+**                 if remote attr present, drop this Mod;
+**             else force this Mod to LDAP_MOD_ADD;
+**     return CONTINUE;
+**
+*/
+
+       rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &e);
+
+       if(e && rc == LDAP_SUCCESS) {
+               Debug(LDAP_DEBUG_TRACE, "=> translucent_modify: found local entry\n", 0, 0, 0);
+               for(m = op->orm_modlist; m; m = m->sml_next) {
+                       for(a = e->e_attrs; a; a = a->a_next)
+                               if(a->a_desc == m->sml_desc) break;
+                       if(a) continue;         /* found local attr */
+                       if(m->sml_op == LDAP_MOD_DELETE) {
+                               for(a = re->e_attrs; a; a = a->a_next)
+                                       if(a->a_desc == m->sml_desc) break;
+                               /* not found remote attr */
+                               if(!a) {
+                                       erc = LDAP_NO_SUCH_ATTRIBUTE;
+                                       goto release;
+                               }
+                               if(ov->config->strict) {
+                                       erc = LDAP_CONSTRAINT_VIOLATION;
+                                       goto release;
+                               }
+                               Debug(LDAP_DEBUG_TRACE,
+                                       "=> translucent_modify: silently dropping delete: %s\n",
+                                       m->sml_desc->ad_cname.bv_val, 0, 0);
+                               for(mm = op->orm_modlist; mm->sml_next != m; mm = mm->sml_next);
+                               mm->sml_next = m->sml_next;
+                               mm = m;
+                               m = m->sml_next;
+                               mm->sml_next = NULL;            /* hack */
+                               slap_mods_free(mm);
+                               if(m) continue;
+                       }
+                       m->sml_op = LDAP_MOD_ADD;
+               }
+               erc = SLAP_CB_CONTINUE;
+release:
+               if(re) {
+                       op->o_bd->be_private = ov->private;
+                       if(ov->info->bi_entry_release_rw)
+                               ov->info->bi_entry_release_rw(op, re, 0);
+                       else
+                               entry_free(re);
+                       op->o_bd->be_private = private;
+               }
+               be_entry_release_r(op, e);
+               if(erc == SLAP_CB_CONTINUE) {
+                       op->o_bd->bd_info = (BackendInfo *) on;
+                       return(erc);
+               } else if(erc) {
+                       send_ldap_error(op, rs, erc,
+                               "attempt to delete nonexistent attribute");
+                       return(erc);
+               }
+       }
+
+/*
+** foreach Modification:
+**     if MOD_ADD or MOD_REPLACE, add Attribute;
+** if no Modifications were suitable:
+**     if config.strict, throw CONSTRAINT_VIOLATION;
+**     else, return early SUCCESS;
+** fabricate Entry with new Attribute chain;
+** glue_parent() for this Entry;
+** call bi_op_add() in local backend;
+**
+*/
+
+       Debug(LDAP_DEBUG_TRACE, "=> translucent_modify: fabricating local add\n", 0, 0, 0);
+       a = NULL;
+       for(del = 0, ax = NULL, m = op->orm_modlist; m; m = m->sml_next) {
+               if(((m->sml_op & LDAP_MOD_OP) != LDAP_MOD_ADD) &&
+                  ((m->sml_op & LDAP_MOD_OP) != LDAP_MOD_REPLACE)) {
+                       Debug(LDAP_DEBUG_ANY,
+                               "=> translucent_modify: silently dropped modification(%d): %s\n",
+                               m->sml_op, m->sml_desc->ad_cname.bv_val, 0);
+                       if((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE) del++;
+                       continue;
+               }
+               a = ch_calloc(1, sizeof(Attribute));
+               a->a_desc  = m->sml_desc;
+               a->a_vals  = m->sml_values;
+               a->a_nvals = m->sml_nvalues;
+               a->a_next  = ax;
+               ax = a;
+       }
+
+       if(del && ov->config->strict) {
+               free_attr_chain(a);
+               send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION,
+                       "attempt to delete attributes from local database");
+               return(rs->sr_err);
+       }
+
+       if(!ax) {
+               if(ov->config->strict) {
+                       send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION,
+                               "modification contained other than ADD or REPLACE");
+                       return(rs->sr_err);
+               }
+               op->o_bd->bd_info = (BackendInfo *) on;
+               /* rs->sr_text = "no valid modification found"; */
+               rs->sr_err = LDAP_SUCCESS;
+               send_ldap_result(op, rs);
+               return(rs->sr_err);
+       }
+
+       ne.e_id         = NOID;
+       ne.e_name       = op->o_req_dn;
+       ne.e_nname      = op->o_req_ndn;
+       ne.e_attrs      = a;
+       ne.e_ocflags    = 0;
+       ne.e_bv.bv_len  = 0;
+       ne.e_bv.bv_val  = NULL;
+       ne.e_private    = NULL;
+
+       nop.o_tag       = LDAP_REQ_ADD;
+       nop.oq_add.rs_e = &ne;
+
+       op->o_bd->bd_info = (BackendInfo *) on;
+       glue_parent(&nop);
+
+       rc = on->on_info->oi_orig->bi_op_add(&nop, &nrs);
+       free_attr_chain(a);
+
+       return(rc);
+}
+
+static int translucent_compare(Operation *op, SlapReply *rs) {
+       slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+       overlay_stack *ov = on->on_bi.bi_private;
+       void *private = op->o_bd->be_private;
+       translucent_configuration *cf = ov->config;
+
+       AttributeAssertion *ava = op->orc_ava;
+       Attribute *a, *an, *ra, *as = NULL;
+       Entry *e, *ee, *re;
+       int rc;
+
+       Debug(LDAP_DEBUG_TRACE, "==> translucent_compare: <%s> %s:%s\n",
+               op->o_req_dn.bv_val, ava->aa_desc->ad_cname.bv_val, ava->aa_value.bv_val);
+
+/*
+** if the local backend has an entry for this attribute:
+**     CONTINUE and let it do the compare;
+**
+*/
+
+       op->o_bd->bd_info = (BackendInfo *) on->on_info;
+       rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, ava->aa_desc, 0, &e);
+       if(e && rc == LDAP_SUCCESS) {
+               be_entry_release_r(op, e);
+               op->o_bd->bd_info = (BackendInfo *) on;
+               return(SLAP_CB_CONTINUE);
+       }
+
+/*
+** call compare() in the captive backend;
+** return the result;
+**
+*/
+
+       op->o_bd->be_private = ov->private;
+       rc = ov->info->bi_op_compare(op, rs);
+       op->o_bd->be_private = private;
+       op->o_bd->bd_info = (BackendInfo *) on;
+       return(rc);
+}
+
+/*
+** translucent_search_cb()
+**     merge local data with the search result
+**
+*/
+
+static int translucent_search_cb(Operation *op, SlapReply *rs) {
+       slap_overinst *on;
+       Entry *e, *re = NULL;
+       Attribute *a, *ax, *an, *as = NULL;
+       BerVarray b, bx;
+       void *private;
+       int i, rc, size;
+
+       if(!op || !rs || rs->sr_type != REP_SEARCH || !rs->sr_entry)
+               return(SLAP_CB_CONTINUE);
+
+       Debug(LDAP_DEBUG_TRACE, "==> tranclucent_search_cb: %s\n",
+               rs->sr_entry->e_name.bv_val, 0, 0);
+
+       on = (slap_overinst *) op->o_bd->bd_info;
+       op->o_bd->bd_info = (BackendInfo *) on->on_info;
+
+       private = op->o_bd->be_private;
+       op->o_bd->be_private = op->o_callback->sc_private;
+
+       rc = be_entry_get_rw(op, &rs->sr_entry->e_nname, NULL, NULL, 0, &e);
+
+/*
+** if we got an entry from local backend:
+**     make a copy of this search result;
+**     foreach local attr:
+**             foreach search result attr:
+**                     if match, result attr with local attr;
+**                     if new local, add to list;
+**     append new local attrs to search result;
+**
+*/
+
+       if(e && rc == LDAP_SUCCESS) {
+               re = entry_dup(rs->sr_entry);
+               for(ax = e->e_attrs; ax; ax = ax->a_next) {
+#if 0
+                       if(is_at_operational(ax->a_desc->ad_type)) continue;
+#endif
+                       for(a = re->e_attrs; a; a = a->a_next) {
+                               if(a->a_desc == ax->a_desc) {
+                                       if(a->a_vals != a->a_nvals)
+                                               ber_bvarray_free(a->a_nvals);
+                                       ber_bvarray_free(a->a_vals);
+                                       a->a_vals = dup_bervarray(ax->a_vals);
+                                       a->a_nvals = (ax->a_vals == ax->a_nvals) ?
+                                               a->a_vals : dup_bervarray(ax->a_nvals);
+                                       break;
+                               }
+                       }
+                       if(a) continue;
+                       an = attr_dup(ax);
+                       an->a_next = as;
+                       as = an;
+               }
+               be_entry_release_r(op, e);
+
+               /* literally append, so locals are always last */
+               if(as) {
+                       if(re->e_attrs) {
+                               for(ax = re->e_attrs; ax->a_next; ax = ax->a_next);
+                               ax->a_next = as;
+                       } else {
+                               re->e_attrs = as;
+                       }
+               }
+               rs->sr_entry = re;
+               rs->sr_flags |= REP_ENTRY_MUSTBEFREED;
+       }
+
+       op->o_bd->be_private = private;
+       op->o_bd->bd_info = (BackendInfo *) on;
+
+       return(SLAP_CB_CONTINUE);
+}
+
+/*
+** translucent_search()
+**     search via captive backend;
+**     override results with any local data;
+**
+*/
+
+static int translucent_search(Operation *op, SlapReply *rs) {
+       Operation nop = *op;
+
+       slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+       slap_callback cb = { NULL, NULL, NULL, NULL };
+       overlay_stack *ov = on->on_bi.bi_private;
+       translucent_configuration *cf = ov->config;
+       void *private = op->o_bd->be_private;
+       int rc;
+
+       Debug(LDAP_DEBUG_TRACE, "==> translucent_search: <%s> %s\n",
+               op->o_req_dn.bv_val, op->ors_filterstr.bv_val, 0);
+       cb.sc_response = (slap_response *) translucent_search_cb;
+       cb.sc_private = private;
+
+       cb.sc_next = nop.o_callback;
+       nop.o_callback = &cb;
+
+       op->o_bd->be_private = ov->private;
+       rc = ov->info->bi_op_search(&nop, rs);
+       op->o_bd->be_private = private;
+
+       return(rs->sr_err);
+}
+
+
+/*
+** translucent_bind()
+**     pass bind request to captive backend;
+**
+*/
+
+static int translucent_bind(Operation *op, SlapReply *rs) {
+       slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+       overlay_stack *ov = on->on_bi.bi_private;
+       void *private = op->o_bd->be_private;
+       int rc = 0;
+
+       Debug(LDAP_DEBUG_TRACE, "translucent_bind: <%s> method %d\n",
+               op->o_req_dn.bv_val, op->orb_method, 0);
+
+       op->o_bd->be_private = ov->private;
+       rc = ov->info->bi_op_bind(op, rs);
+       op->o_bd->be_private = private;
+
+       return(rc);
+}
+
+/*
+** translucent_config()
+**     pass config directives to captive backend;
+**     parse unrecognized directives ourselves;
+**
+*/
+
+static int translucent_config(
+       BackendDB       *be,
+       const char      *fname,
+       int             lineno,
+       int             argc,
+       char            **argv
+)
+{
+       slap_overinst *on = (slap_overinst *) be->bd_info;
+       overlay_stack *ov = on->on_bi.bi_private;
+       void *private = be->be_private;
+       int rc;
+
+       /* "this should never happen" */
+       if(!ov->info) {
+               fprintf(stderr, "fatal: captive backend not initialized");
+               return(1);
+       }
+
+       be->be_private = ov->private;
+       rc = ov->info->bi_db_config ? ov->info->bi_db_config(be, fname, lineno, argc, argv) : 0;
+       be->be_private = private;
+
+       /* pass okay or error up, SLAP_CONF_UNKNOWN might be ours */
+       if(rc == 0 || rc == 1) return(rc);
+
+       rc = 0;
+       if(!strcasecmp(*argv, "translucent_strict")) {
+               ov->config->strict++;
+       } else if(!strcasecmp(*argv, "translucent_no_add")) {
+               ov->config->no_add++;
+       } else if(!strcasecmp(*argv, "translucent_no_glue")) {
+               ov->config->glue++;
+       } else if(!strcasecmp(*argv, "translucent_debug")) {
+               if(argc == 1) {
+                       ov->config->debug = 0xFFFF;
+                       rc = 0;
+               } else if(argc == 2) {
+                       ov->config->debug = atoi(argv[1]);
+                       rc = 0;
+               } else {
+                       fprintf(stderr, "%s: line %d: too many arguments (%d) to debug\n",
+                               fname, lineno, argc);
+                       rc = 1;
+               }
+       } else {
+               fprintf(stderr, "%s: line %d: unknown keyword %s\n",
+                       fname, lineno, *argv);
+               rc = SLAP_CONF_UNKNOWN;
+       }
+       return(rc);
+}
+
+/*
+** translucent_db_init()
+**     initialize the captive backend;
+**
+*/
+
+static int translucent_db_init(BackendDB *be) {
+       slap_overinst *on = (slap_overinst *) be->bd_info;
+       void *private = be->be_private;
+       overlay_stack *ov;
+       int rc;
+
+       Debug(LDAP_DEBUG_TRACE, "==> translucent_init\n", 0, 0, 0);
+
+       ov = ch_calloc(1, sizeof(overlay_stack));
+       ov->config = ch_calloc(1, sizeof(translucent_configuration));
+       ov->info = backend_info("ldap");
+
+       if(!ov->info) {
+               Debug(LDAP_DEBUG_ANY, "translucent: backend_info failed!\n", 0, 0, 0);
+               return(1);
+       }
+
+       /* forcibly disable schema checking on the local backend */
+       SLAP_DBFLAGS(be) |= SLAP_DBFLAG_NO_SCHEMA_CHECK;
+
+       be->be_private = NULL;
+       rc = ov->info->bi_db_init ? ov->info->bi_db_init(be) : 0;
+
+       if(rc) Debug(LDAP_DEBUG_TRACE,
+               "translucent: bi_db_init() returned error %d\n", rc, 0, 0);
+
+       ov->private = be->be_private;
+       be->be_private = private;
+       on->on_bi.bi_private = ov;
+       return(rc);
+}
+
+/*
+** translucent_open()
+**     if the captive backend has an open() method, call it;
+**
+*/
+
+static int translucent_open(BackendDB *be) {
+       slap_overinst *on = (slap_overinst *) be->bd_info;
+       overlay_stack *ov = on->on_bi.bi_private;
+       void *private = be->be_private;
+       int rc;
+
+       /* "should never happen" */
+       if(!ov->info) {
+               Debug(LDAP_DEBUG_ANY, "translucent_open() called with bad ov->info\n", 0, 0, 0);
+               return(LDAP_OTHER);
+       }
+
+       Debug(LDAP_DEBUG_TRACE, "translucent_open\n", 0, 0, 0);
+
+       be->be_private = ov->private;
+       rc = ov->info->bi_db_open ? ov->info->bi_db_open(be) : 0;
+       be->be_private = private;
+
+       if(rc) Debug(LDAP_DEBUG_TRACE,
+               "translucent: bi_db_open() returned error %d\n", rc, 0, 0);
+
+       return(rc);
+}
+
+/*
+** translucent_close()
+**     if the captive backend has a close() method, call it;
+**     free any config data;
+**
+*/
+
+static int translucent_close(BackendDB *be) {
+       slap_overinst *on = (slap_overinst *) be->bd_info;
+       overlay_stack *ov = on->on_bi.bi_private;
+       translucent_configuration *cf = ov->config;
+       void *private = be->be_private;
+       int rc;
+
+       be->be_private = ov->private;
+       rc = (ov->info && ov->info->bi_db_close) ? ov->info->bi_db_close(be) : 0;
+       be->be_private = private;
+       if(ov->config) ch_free(ov->config);
+       ch_free(ov);
+       return(rc);
+}
+
+/*
+** translucent_init()
+**     initialize the slap_overinst with our entry points;
+**
+*/
+
+int translucent_init() {
+
+       translucent.on_bi.bi_type       = "translucent";
+       translucent.on_bi.bi_db_init    = translucent_db_init;
+       translucent.on_bi.bi_db_config  = translucent_config;
+       translucent.on_bi.bi_db_open    = translucent_open;
+       translucent.on_bi.bi_db_close   = translucent_close;
+       translucent.on_bi.bi_op_bind    = translucent_bind;
+       translucent.on_bi.bi_op_add     = translucent_add;
+       translucent.on_bi.bi_op_modify  = translucent_modify;
+       translucent.on_bi.bi_op_modrdn  = translucent_modrdn;
+       translucent.on_bi.bi_op_delete  = translucent_delete;
+       translucent.on_bi.bi_op_search  = translucent_search;
+       translucent.on_bi.bi_op_compare = translucent_compare;
+
+       return(overlay_register(&translucent));
+}
+
+#if SLAPD_OVER_TRANSLUCENT == SLAPD_MOD_DYNAMIC && defined(PIC)
+int init_module(int argc, char *argv[]) {
+       return translucent_init();
+}
+#endif
+
+#endif /* SLAPD_OVER_TRANSLUCENT */
+
index d44e205fdf7003441d8d1409be58d8ca916eac9a..79e7db9403785bd5c59f1218097b9ec2eb872d6d 100644 (file)
@@ -46,6 +46,7 @@ typedef struct unique_data_s {
 } unique_data;
 
 typedef struct unique_counter_s {
+       struct berval *ndn;
        int count;
 } unique_counter;
 
@@ -231,16 +232,23 @@ static int count_attr_cb(
        SlapReply *rs
 )
 {
+       unique_counter *uc;
+
        /* because you never know */
        if(!op || !rs) return(0);
 
        /* Only search entries are interesting */
        if(rs->sr_type != REP_SEARCH) return(0);
 
+       uc = op->o_callback->sc_private;
+
+       /* Ignore the current entry */
+       if ( dn_match( uc->ndn, &rs->sr_entry->e_nname )) return(0);
+
        Debug(LDAP_DEBUG_TRACE, "==> count_attr_cb <%s>\n",
                rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
 
-       ((unique_counter*)op->o_callback->sc_private)->count++;
+       uc->count++;
 
        return(0);
 }
@@ -316,7 +324,7 @@ static int unique_search(
        unique_data *ud = on->on_bi.bi_private;
        SlapReply nrs = { REP_RESULT };
        slap_callback cb = { NULL, NULL, NULL, NULL }; /* XXX */
-       unique_counter uq = { 0 };
+       unique_counter uq = { NULL, 0 };
        int rc;
 
        nop->ors_filter = str2filter_x(nop, key);
@@ -334,6 +342,8 @@ static int unique_search(
        nop->ors_attrs  = slap_anlist_no_attrs;
        nop->ors_attrsonly = 1;
 
+       uq.ndn = &op->o_req_ndn;
+
        nop->o_req_ndn  = ud->dn;
        nop->o_ndn = op->o_bd->be_rootndn;
 
index 127ac5a45ba417c25e489f4cfa14a8b0ab794663..2214f0cb8e3247086e1e8f8b01724ac3f932a0d4 100644 (file)
@@ -822,7 +822,6 @@ struct slap_internal_schema {
        AttributeDescription *si_ad_monitorContext;
        AttributeDescription *si_ad_vendorName;
        AttributeDescription *si_ad_vendorVersion;
-       AttributeDescription *si_ad_configContext;
 
        /* subentry attribute descriptions */
        AttributeDescription *si_ad_administrativeRole;
@@ -2030,7 +2029,6 @@ struct slap_backend_info {
 
        slap_mask_t     bi_flags; /* backend flags */
 #define SLAP_BFLAG_MONITOR                     0x0001U /* a monitor backend */
-#define SLAP_BFLAG_CONFIG                      0x0002U /* a config backend */
 #define SLAP_BFLAG_NOLASTMODCMD                0x0010U
 #define SLAP_BFLAG_INCREMENT           0x0100U
 #define SLAP_BFLAG_ALIASES                     0x1000U
@@ -2040,7 +2038,6 @@ struct slap_backend_info {
 
 #define SLAP_BFLAGS(be)                ((be)->bd_info->bi_flags)
 #define SLAP_MONITOR(be)       (SLAP_BFLAGS(be) & SLAP_BFLAG_MONITOR)
-#define SLAP_CONFIG(be)                (SLAP_BFLAGS(be) & SLAP_BFLAG_CONFIG)
 #define SLAP_INCREMENT(be)     (SLAP_BFLAGS(be) & SLAP_BFLAG_INCREMENT)
 #define SLAP_ALIASES(be)       (SLAP_BFLAGS(be) & SLAP_BFLAG_ALIASES)
 #define SLAP_REFERRALS(be)     (SLAP_BFLAGS(be) & SLAP_BFLAG_REFERRALS)
index 428d1cf2fa79954adcd3681eb469b8bd4dd29d0e..6ebe04140852e8355b1c6694acd2b3a63206c749 100644 (file)
@@ -24,6 +24,7 @@
 #include <ldap_pvt_thread.h>
 #include <slap.h>
 #include <slapi.h>
+#include <lutil.h>
 
 /*
  * Note: if ltdl.h is not available, slapi should not be compiled
@@ -64,8 +65,6 @@ static Slapi_PBlock *pGPlugins = NULL;
 static Slapi_PBlock *
 plugin_pblock_new(
        int type, 
-       const char *path, 
-       const char *initfunc, 
        int argc, 
        char *argv[] ) 
 {
@@ -73,6 +72,9 @@ plugin_pblock_new(
        Slapi_PluginDesc *pPluginDesc = NULL;
        lt_dlhandle     hdLoadHandle;
        int             rc;
+       char **av2 = NULL, **ppPluginArgv;
+       char *path = argv[2];
+       char *initfunc = argv[3];
 
        pPlugin = slapi_pblock_new();
        if ( pPlugin == NULL ) {
@@ -90,7 +92,23 @@ plugin_pblock_new(
                goto done;
        }
 
-       rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGV, (void *)argv );
+       av2 = ldap_charray_dup( argv );
+       if ( !av2 ) {
+               rc = LDAP_NO_MEMORY;
+               goto done;
+       }
+
+       if ( argc > 0 ) {
+               ppPluginArgv = &av2[4];
+       } else {
+               ppPluginArgv = NULL;
+       }
+       rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGV, (void *)ppPluginArgv );
+       if ( rc != 0 ) { 
+               goto done;
+       }
+
+       rc = slapi_pblock_set( pPlugin, SLAPI_X_CONFIG_ARGV, (void *)av2 );
        if ( rc != 0 ) { 
                goto done;
        }
@@ -114,6 +132,9 @@ done:
        if ( rc != 0 && pPlugin != NULL ) {
                slapi_pblock_destroy( pPlugin );
                pPlugin = NULL;
+               if ( av2 ) {
+                       ldap_charray_free( av2 );
+               }
        }
 
        return pPlugin;
@@ -681,7 +702,6 @@ slapi_int_read_config(
 {
        int             iType = -1;
        int             numPluginArgc = 0;
-       char            **ppPluginArgv = NULL;
 
        if ( argc < 4 ) {
                fprintf( stderr,
@@ -707,11 +727,6 @@ slapi_int_read_config(
        }
        
        numPluginArgc = argc - 4;
-       if ( numPluginArgc > 0 ) {
-               ppPluginArgv = &argv[4];
-       } else {
-               ppPluginArgv = NULL;
-       }
 
        if ( iType == SLAPI_PLUGIN_PREOPERATION ||
                        iType == SLAPI_PLUGIN_EXTENDEDOP ||
@@ -720,8 +735,7 @@ slapi_int_read_config(
                int rc;
                Slapi_PBlock *pPlugin;
 
-               pPlugin = plugin_pblock_new( iType, argv[2], argv[3], 
-                                       numPluginArgc, ppPluginArgv );
+               pPlugin = plugin_pblock_new( iType, numPluginArgc, argv );
                if (pPlugin == NULL) {
                        return 1;
                }
@@ -747,6 +761,38 @@ slapi_int_read_config(
        return 0;
 }
 
+void
+slapi_int_plugin_unparse(
+       Backend *be,
+       BerVarray *out
+)
+{
+       Slapi_PBlock *pp;
+       int i, j, rc;
+       char **argv, ibuf[32], *ptr;
+       struct berval idx, bv;
+
+       *out = NULL;
+       idx.bv_val = ibuf;
+       i = 0;
+       for ( pp=be->be_pb; pp; slapi_pblock_get( pp, SLAPI_IBM_PBLOCK, &pp ) ) {
+               slapi_pblock_get( pp, SLAPI_X_CONFIG_ARGV, &argv );
+               idx.bv_len = sprintf( idx.bv_val, "{%d}", i );
+               bv.bv_len = idx.bv_len;
+               for (j=1; argv[j]; j++) {
+                       bv.bv_len += strlen(argv[j]);
+                       if ( j ) bv.bv_len++;
+               }
+               bv.bv_val = ch_malloc( bv.bv_len + 1 );
+               ptr = lutil_strcopy( bv.bv_val, ibuf );
+               for (j=1; argv[j]; j++) {
+                       if ( j ) *ptr++ = ' ';
+                       ptr = lutil_strcopy( ptr, argv[j] );
+               }
+               ber_bvarray_add( out, &bv );
+       }
+}
+
 int
 slapi_int_initialize(void)
 {
index 1470e345188c4b23eea944eeb41122b222433181..96dc7991c00595d0fae6226ab631bd4c775c49eb 100644 (file)
@@ -285,6 +285,7 @@ extern int slapi_int_register_extop(Backend *pBE, ExtendedOp **opList, Slapi_PBl
 extern int slapi_int_get_extop_plugin(struct berval  *reqoid, SLAPI_FUNC *pFuncAddr );
 extern int slapi_int_read_config(Backend *be, const char *fname, int lineno,
                int argc, char **argv );
+extern void slapi_int_plugin_unparse(Backend *be, BerVarray *out );
 extern int slapi_int_initialize(void);
 
 
index fea688d1eac6990916c384ee1568175b0e13291b..45c8aea68fd020abc6d321a0545335fec516ab0f 100644 (file)
@@ -131,13 +131,16 @@ typedef enum slapi_extension_e {
 
 #ifndef NO_PBLOCK_CLASS                /* where's this test from? */
 
-#if 0  /* unused (yet?) */
-#define CMP_EQUAL                      0
-#define CMP_GREATER                    1
-#define CMP_LOWER                      (-1)
-#endif
+typedef enum slapi_pblock_class_e {
+       PBLOCK_CLASS_INVALID = 0,
+       PBLOCK_CLASS_INTEGER,
+       PBLOCK_CLASS_LONG_INTEGER,
+       PBLOCK_CLASS_POINTER,
+       PBLOCK_CLASS_FUNCTION_POINTER
+} slapi_pblock_class_t;
+
+#define PBLOCK_SUCCESS                 (0)
 #define PBLOCK_ERROR                   (-1)
-#define INVALID_PARAM                  PBLOCK_ERROR
 #define PBLOCK_MAX_PARAMS              100
 
 struct slapi_pblock {
@@ -283,6 +286,8 @@ extern Backend * slapi_cl_get_be(char *dn);
 #define SLAPI_X_CONN_SSF                       1303
 #define SLAPI_X_CONN_SASL_CONTEXT              1304
 
+#define SLAPI_X_CONFIG_ARGV    1400
+
 #define SLAPD_AUTH_NONE   "none"
 #define SLAPD_AUTH_SIMPLE "simple"
 #define SLAPD_AUTH_SSL    "SSL"
index 79efa4124e461f1aee5663fb9fde92c31e462152..6dcbe7b536be212a556384340026d98cc2264dde 100644 (file)
 #include <slap.h>
 #include <slapi.h>
 
-static in
-isOkNetscapeParam( int param ) 
+static slapi_pblock_class_
+getPBlockClass( int param ) 
 {
        switch ( param ) {
-       case SLAPI_BACKEND:
-       case SLAPI_CONNECTION:
-       case SLAPI_OPERATION:
-       case SLAPI_OPERATION_PARAMETERS:
-       case SLAPI_OPERATION_TYPE:
-       case SLAPI_OPERATION_ID:
-       case SLAPI_OPERATION_AUTHTYPE:
+       case SLAPI_PLUGIN_TYPE:
+       case SLAPI_PLUGIN_ARGC:
+       case SLAPI_PLUGIN_VERSION:
+       case SLAPI_PLUGIN_OPRETURN:
+       case SLAPI_PLUGIN_INTOP_RESULT:
+       case SLAPI_CONFIG_LINENO:
+       case SLAPI_CONFIG_ARGC:
+       case SLAPI_BIND_METHOD:
+       case SLAPI_MODRDN_DELOLDRDN:
+       case SLAPI_SEARCH_SCOPE:
+       case SLAPI_SEARCH_DEREF:
+       case SLAPI_SEARCH_SIZELIMIT:
+       case SLAPI_SEARCH_TIMELIMIT:
+       case SLAPI_SEARCH_ATTRSONLY:
+       case SLAPI_NENTRIES:
+       case SLAPI_CHANGENUMBER:
+       case SLAPI_DBSIZE:
        case SLAPI_REQUESTOR_ISROOT:
-       case SLAPI_BE_MONITORDN:
-       case SLAPI_BE_TYPE:
        case SLAPI_BE_READONLY:
        case SLAPI_BE_LASTMOD:
-       case SLAPI_CONN_ID:
-       case SLAPI_OPINITIATED_TIME:
-       case SLAPI_REQUESTOR_DN:
+       case SLAPI_DB2LDIF_PRINTKEY:
+       case SLAPI_LDIF2DB_REMOVEDUPVALS:
+       case SLAPI_MANAGEDSAIT:
+       case SLAPI_IBM_BROADCAST_BE:
+       case SLAPI_IBM_REPLICATE:
+       case SLAPI_IBM_CL_MAX_ENTRIES:
+       case SLAPI_IBM_CL_FIRST_ENTRY:
+       case SLAPI_IBM_CL_LAST_ENTRY:
+       case SLAPI_IBM_EVENT_ENABLED:
+       case SLAPI_IBM_EVENT_MAXREG:
+       case SLAPI_IBM_EVENT_REGPERCONN:
        case SLAPI_REQUESTOR_ISUPDATEDN:
-       case SLAPI_CONN_DN:
-       case SLAPI_CONN_CLIENTIP:
-       case SLAPI_CONN_SERVERIP:
-       case SLAPI_CONN_AUTHTYPE:
-       case SLAPI_CONN_AUTHMETHOD:
-       case SLAPI_CONN_CERT:
        case SLAPI_X_CONN_IS_UDP:
-       case SLAPI_X_CONN_CLIENTPATH:
-       case SLAPI_X_CONN_SERVERPATH:
        case SLAPI_X_CONN_SSF:
-       case SLAPI_X_CONN_SASL_CONTEXT:
-       case SLAPI_IBM_CONN_DN_ALT:
-       case SLAPI_IBM_CONN_DN_ORIG:
-       case SLAPI_IBM_GSSAPI_CONTEXT:
-       case SLAPI_PLUGIN:
-       case SLAPI_PLUGIN_PRIVATE:
-       case SLAPI_PLUGIN_TYPE:
-       case SLAPI_PLUGIN_ARGV:
-       case SLAPI_PLUGIN_ARGC:
-       case SLAPI_PLUGIN_VERSION:
-       case SLAPI_PLUGIN_OPRETURN:
-       case SLAPI_PLUGIN_OBJECT:
+       case SLAPI_RESULT_CODE:
+               return PBLOCK_CLASS_INTEGER;
+               break;
+
+       case SLAPI_CONN_ID:
+       case SLAPI_OPERATION_ID:
+       case SLAPI_OPINITIATED_TIME:
+       case SLAPI_ABANDON_MSGID:
+               return PBLOCK_CLASS_LONG_INTEGER;
+               break;
+
+       case SLAPI_PLUGIN_DB_INIT_FN:
        case SLAPI_PLUGIN_DESTROY_FN:
-       case SLAPI_PLUGIN_DESCRIPTION:
-       case SLAPI_PLUGIN_INTOP_RESULT:
-       case SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES:
-       case SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS:
        case SLAPI_PLUGIN_DB_BIND_FN:
        case SLAPI_PLUGIN_DB_UNBIND_FN:
        case SLAPI_PLUGIN_DB_SEARCH_FN:
@@ -132,11 +136,49 @@ isOkNetscapeParam( int param )
        case SLAPI_PLUGIN_MR_FILTER_INDEX_FN:
        case SLAPI_PLUGIN_MR_FILTER_RESET_FN:
        case SLAPI_PLUGIN_MR_INDEX_FN:
+       case SLAPI_PLUGIN_COMPUTE_EVALUATOR_FN:
+       case SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN:
+       case SLAPI_PLUGIN_ACL_ALLOW_ACCESS:
+       case SLAPI_X_PLUGIN_PRE_GROUP_FN:
+       case SLAPI_X_PLUGIN_POST_GROUP_FN:
+       case SLAPI_PLUGIN_AUDIT_FN:
+               return PBLOCK_CLASS_FUNCTION_POINTER;
+               break;
+
+       case SLAPI_BACKEND:
+       case SLAPI_CONNECTION:
+       case SLAPI_OPERATION:
+       case SLAPI_OPERATION_PARAMETERS:
+       case SLAPI_OPERATION_TYPE:
+       case SLAPI_OPERATION_AUTHTYPE:
+       case SLAPI_BE_MONITORDN:
+       case SLAPI_BE_TYPE:
+       case SLAPI_REQUESTOR_DN:
+       case SLAPI_CONN_DN:
+       case SLAPI_CONN_CLIENTIP:
+       case SLAPI_CONN_SERVERIP:
+       case SLAPI_CONN_AUTHTYPE:
+       case SLAPI_CONN_AUTHMETHOD:
+       case SLAPI_CONN_CERT:
+       case SLAPI_X_CONN_CLIENTPATH:
+       case SLAPI_X_CONN_SERVERPATH:
+       case SLAPI_X_CONN_SASL_CONTEXT:
+       case SLAPI_X_CONFIG_ARGV:
+       case SLAPI_IBM_CONN_DN_ALT:
+       case SLAPI_IBM_CONN_DN_ORIG:
+       case SLAPI_IBM_GSSAPI_CONTEXT:
        case SLAPI_PLUGIN_MR_OID:
        case SLAPI_PLUGIN_MR_TYPE:
        case SLAPI_PLUGIN_MR_VALUE:
        case SLAPI_PLUGIN_MR_VALUES:
        case SLAPI_PLUGIN_MR_KEYS:
+       case SLAPI_PLUGIN:
+       case SLAPI_PLUGIN_PRIVATE:
+       case SLAPI_PLUGIN_ARGV:
+       case SLAPI_PLUGIN_OBJECT:
+       case SLAPI_PLUGIN_DESCRIPTION:
+       case SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES:
+       case SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS:
        case SLAPI_PLUGIN_MR_FILTER_REUSABLE:
        case SLAPI_PLUGIN_MR_QUERY_OPERATOR:
        case SLAPI_PLUGIN_MR_USAGE:
@@ -152,10 +194,7 @@ isOkNetscapeParam( int param )
        case SLAPI_PLUGIN_SYNTAX_OID:
        case SLAPI_PLUGIN_SYNTAX_FLAGS:
        case SLAPI_PLUGIN_SYNTAX_COMPARE:
-       case SLAPI_MANAGEDSAIT:
        case SLAPI_CONFIG_FILENAME:
-       case SLAPI_CONFIG_LINENO:
-       case SLAPI_CONFIG_ARGC:
        case SLAPI_CONFIG_ARGV:
        case SLAPI_TARGET_DN:
        case SLAPI_REQCONTROLS:
@@ -164,7 +203,6 @@ isOkNetscapeParam( int param )
        case SLAPI_RESCONTROLS:
        case SLAPI_ADD_RESCONTROL:
        case SLAPI_ADD_ENTRY:
-       case SLAPI_BIND_METHOD:
        case SLAPI_BIND_CREDENTIALS:
        case SLAPI_BIND_SASLMECHANISM:
        case SLAPI_BIND_RET_SASLCREDS:
@@ -172,17 +210,10 @@ isOkNetscapeParam( int param )
        case SLAPI_COMPARE_VALUE:
        case SLAPI_MODIFY_MODS:
        case SLAPI_MODRDN_NEWRDN:
-       case SLAPI_MODRDN_DELOLDRDN:
        case SLAPI_MODRDN_NEWSUPERIOR:
-       case SLAPI_SEARCH_SCOPE:
-       case SLAPI_SEARCH_DEREF:
-       case SLAPI_SEARCH_SIZELIMIT:
-       case SLAPI_SEARCH_TIMELIMIT:
        case SLAPI_SEARCH_FILTER:
        case SLAPI_SEARCH_STRFILTER:
        case SLAPI_SEARCH_ATTRS:
-       case SLAPI_SEARCH_ATTRSONLY:
-       case SLAPI_ABANDON_MSGID:
        case SLAPI_SEQ_TYPE:
        case SLAPI_SEQ_ATTRNAME:
        case SLAPI_SEQ_VAL:
@@ -196,57 +227,27 @@ isOkNetscapeParam( int param )
        case SLAPI_MR_FILTER_OID:
        case SLAPI_MR_FILTER_DNATTRS:
        case SLAPI_LDIF2DB_FILE:
-       case SLAPI_LDIF2DB_REMOVEDUPVALS:
-       case SLAPI_DB2LDIF_PRINTKEY:
        case SLAPI_PARENT_TXN:
        case SLAPI_TXN:
        case SLAPI_SEARCH_RESULT_SET:
        case SLAPI_SEARCH_RESULT_ENTRY:
-       case SLAPI_NENTRIES:
        case SLAPI_SEARCH_REFERRALS:
-       case SLAPI_CHANGENUMBER:
        case SLAPI_LOG_OPERATION:
-       case SLAPI_DBSIZE:
-       case SLAPI_RESULT_CODE:
        case SLAPI_RESULT_TEXT:
        case SLAPI_RESULT_MATCHED:
-       case SLAPI_PLUGIN_COMPUTE_EVALUATOR_FN:
-       case SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN:
-       case SLAPI_PLUGIN_ACL_ALLOW_ACCESS:
-       case SLAPI_X_PLUGIN_PRE_GROUP_FN:
-       case SLAPI_X_PLUGIN_POST_GROUP_FN:
        case SLAPI_X_GROUP_ENTRY:
        case SLAPI_X_GROUP_ATTRIBUTE:
        case SLAPI_X_GROUP_OPERATION_DN:
        case SLAPI_X_GROUP_TARGET_ENTRY:
-               return LDAP_SUCCESS;
+       case SLAPI_PLUGIN_AUDIT_DATA:
+       case SLAPI_IBM_PBLOCK:
+               return PBLOCK_CLASS_POINTER;
+               break;
        default:
-               return INVALID_PARAM;
+               break;
        }
-}
 
-static int
-isValidParam( Slapi_PBlock *pb, int param ) 
-{
-       if ( !pb ) {
-               return INVALID_PARAM;
-       }
-       
-       if ( pb->ckParams == TRUE ) {
-               if ( IBM_RESERVED( param ) ) return LDAP_SUCCESS;
-               if (param == SLAPI_PLUGIN_AUDIT_FN ||
-                               param == SLAPI_PLUGIN_AUDIT_DATA )
-                       return LDAP_SUCCESS;
-               if ( param < LAST_IBM_PARAM ) {
-                       return INVALID_PARAM;
-               } else if ( NETSCAPE_RESERVED( param ) ) {
-                       return INVALID_PARAM;
-               } else {
-                       return isOkNetscapeParam(param);
-               }
-       } else {
-               return LDAP_SUCCESS;
-       }
+       return PBLOCK_CLASS_INVALID;
 }
 
 static void
@@ -265,22 +266,49 @@ static int
 get( Slapi_PBlock *pb, int param, void **val ) 
 {      
        int i;
+       slapi_pblock_class_t pbClass;
 
-       if ( isValidParam( pb, param ) == INVALID_PARAM ) {
+       pbClass = getPBlockClass( param );
+       if ( pbClass == PBLOCK_CLASS_INVALID ) {
                return PBLOCK_ERROR;
        }
        
        Lock( pb );
-       
-       *val = NULL;
+
+       switch ( pbClass ) {
+       case PBLOCK_CLASS_INTEGER:
+               *((int *)val) = 0;
+               break;
+       case PBLOCK_CLASS_LONG_INTEGER:
+               *((long *)val) = 0L;
+               break;
+       case PBLOCK_CLASS_POINTER:
+       case PBLOCK_CLASS_FUNCTION_POINTER:
+               *val = NULL;
+               break;
+       }
+
        for ( i = 0; i < pb->numParams; i++ ) {
                if ( pb->curParams[i] == param ) {
-                       *val = pb->curVals[i];
+                       switch ( pbClass ) {
+                       case PBLOCK_CLASS_INTEGER:
+                               *((int *)val) = (int)pb->curVals[i];
+                               break;
+                       case PBLOCK_CLASS_LONG_INTEGER:
+                               *((long *)val) = (long)pb->curVals[i];
+                               break;
+                       case PBLOCK_CLASS_POINTER:
+                       case PBLOCK_CLASS_FUNCTION_POINTER:
+                               *val = pb->curVals[i];
+                               break;
+                       default:
+                               break;
+                       }
                        break;
                }
        }
        unLock( pb );   
-       return LDAP_SUCCESS;
+       return PBLOCK_SUCCESS;
 }
 
 static int 
@@ -289,8 +317,10 @@ set( Slapi_PBlock *pb, int param, void *val )
 #if defined(LDAP_SLAPI)
        int i, freeit;
        int addcon = 0;
+       slapi_pblock_class_t pbClass;
 
-       if ( isValidParam( pb, param ) == INVALID_PARAM ) {
+       pbClass = getPBlockClass( param );
+       if ( pbClass == PBLOCK_CLASS_INVALID ) {
                return PBLOCK_ERROR;
        }
 
@@ -313,9 +343,11 @@ set( Slapi_PBlock *pb, int param, void *val )
         case SLAPI_IBM_CONN_DN_ORIG:
         case SLAPI_RESULT_TEXT:
         case SLAPI_RESULT_MATCHED:
-               freeit = 1; break;
+               freeit = 1;
+               break;
        default:
-               freeit = 0; break;
+               freeit = 0;
+               break;
        }
        for( i = 0; i < pb->numParams; i++ ) { 
                if ( pb->curParams[i] == param ) {
@@ -347,7 +379,7 @@ set( Slapi_PBlock *pb, int param, void *val )
        }
 
        unLock( pb );   
-       return LDAP_SUCCESS;
+       return PBLOCK_SUCCESS;
 #endif /* LDAP_SLAPI */
        return PBLOCK_ERROR;
 }
@@ -386,7 +418,7 @@ deleteParam( Slapi_PBlock *p, int param )
        }
        p->numParams--;
        unLock( p );    
-       return LDAP_SUCCESS;
+       return PBLOCK_SUCCESS;
 }
 
 Slapi_PBlock *
index 1adb7a2bede081224b9fb614190b7dd18bfc6138..aed6b39df396e176946332c1f234b0052361efed 100644 (file)
@@ -98,7 +98,7 @@ associatedDomain: example.com
 
 dn: cn=Gern Jensen,ou=Information Technology Division,ou=People,dc=example,dc=
  com
-objectClass: OpenLDAPperson
+objectClass: testPerson
 cn: Gern Jensen
 sn: Jensen
 uid: gjensen
@@ -112,6 +112,7 @@ facsimileTelephoneNumber: +1 313 555 7557
 telephoneNumber: +1 313 555 8343
 mail: gjensen@mailgw.example.com
 homePhone: +1 313 555 8844
+testTime: 20050304001801.234Z
 
 dn: ou=Groups,dc=example,dc=com
 objectClass: organizationalUnit
index 9588fd7db7dc65ddb7c9bfa16d6dc0cf3fab2939..c88d78591d9d97b6871b5257e014133d970b7e3e 100644 (file)
@@ -2566,6 +2566,14 @@ seeAlso: cn=All Staff,ou=Groups,o=Example,c=US
 
 # refldap://localhost:9010/ou=Referrals,o=Beispiel,c=DE??sub
 
+# searching filter="(uid=example)"
+#      attrs="uid"
+#      base="o=Example,c=US"...
+dn: o=Example,c=US
+uid: example
+
+# refldap://localhost:9010/ou=Referrals,o=Beispiel,c=DE??sub
+
 # searching filter="(member=cn=Another Added Group,ou=Groups,o=Example,c=US)"
 #      attrs="member"
 #      base="o=Example,c=US"...
index 51513efb29e2645fe65b942adbb11922138c4bd8..ca0682ea89dfd7be53aeef05290045c9991346b4 100644 (file)
@@ -23,8 +23,6 @@ include ./schema/nis.schema
 pidfile     ./testrun/slapd.3.pid
 argsfile    ./testrun/slapd.3.args
 
-# password-hash        {md5}
-
 #mod#modulepath        ../servers/slapd/back-@BACKEND@/
 #mod#moduleload        back_@BACKEND@.la
 #monitormod#modulepath ../servers/slapd/back-monitor/
index 5c9155e1c9d9ed4c5289a7a1903bd66e89c3da56..0f3f4fa6ade461b2666dbdbdb0c4f36b10f2781f 100644 (file)
@@ -23,8 +23,6 @@ include ./schema/nis.schema
 pidfile     ./testrun/slapd.2.pid
 argsfile    ./testrun/slapd.2.args
 
-# password-hash        {md5}
-
 #mod#modulepath        ../servers/slapd/back-@BACKEND@/
 #mod#moduleload        back_@BACKEND@.la
 #monitormod#modulepath ../servers/slapd/back-monitor/
index cd3b42ded8e36ab324023bae77117b0b1f5a5449..4d7d3c85d536730e83317342631b7d97a660e1e2 100644 (file)
@@ -22,8 +22,6 @@ include ./schema/nis.schema
 pidfile     ./testrun/slapd.1.pid
 argsfile    ./testrun/slapd.1.args
 
-# password-hash        {md5}
-
 #mod#modulepath        ../servers/slapd/back-@BACKEND@/
 #mod#moduleload        back_@BACKEND@.la
 #monitormod#modulepath ../servers/slapd/back-monitor/
diff --git a/tests/data/slapd-translucent-local.conf b/tests/data/slapd-translucent-local.conf
new file mode 100644 (file)
index 0000000..8f9db68
--- /dev/null
@@ -0,0 +1,52 @@
+# stand-alone slapd config -- for testing (with translucent overlay)
+# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2004 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+
+ucdata-path    ./ucdata
+include ./schema/core.schema
+include ./schema/cosine.schema
+include ./schema/inetorgperson.schema
+include ./schema/openldap.schema
+include ./schema/nis.schema
+
+#
+pidfile     ./testrun/slapd.2.pid
+argsfile    ./testrun/slapd.2.args
+
+#mod#modulepath        ../servers/slapd/back-@BACKEND@/:../servers/slapd/back-ldap/:../servers/slapd/overlays
+#mod#moduleload        back_@BACKEND@.la
+#mod#moduleload back_ldap.la
+#translucentmod#modulepath     ../servers/slapd/overlays
+#translucentmod#moduleload     translucent.la
+
+#######################################################################
+# database definitions
+#######################################################################
+
+database       @BACKEND@
+suffix         "o=translucent"
+directory      ./testrun/db.2.a
+rootdn         "o=translucent"
+rootpw         secret
+index          objectClass     eq
+index          cn,sn,uid       pres,eq,sub
+
+overlay                translucent
+translucent_no_glue
+
+# XXX this uri really shouldn't be hardcoded
+uri            @URI1@
+lastmod                off
+acl-authcDN            uid=binder,o=translucent
+acl-passwd             bindtest
diff --git a/tests/data/slapd-translucent-remote.conf b/tests/data/slapd-translucent-remote.conf
new file mode 100644 (file)
index 0000000..b51b3c5
--- /dev/null
@@ -0,0 +1,41 @@
+# stand-alone slapd config -- for testing (with translucent overlay)
+# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2004 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+
+ucdata-path    ./ucdata
+include ./schema/core.schema
+include ./schema/cosine.schema
+include ./schema/inetorgperson.schema
+include ./schema/openldap.schema
+include ./schema/nis.schema
+
+#
+pidfile     ./testrun/slapd.1.pid
+argsfile    ./testrun/slapd.1.args
+
+#mod#modulepath        ../servers/slapd/back-@BACKEND@/:../servers/slapd/overlays
+#mod#moduleload        back_@BACKEND@.la
+
+#######################################################################
+# database definitions
+#######################################################################
+
+database       @BACKEND@
+suffix         "o=translucent"
+directory      ./testrun/db.1.a
+rootdn         "o=translucent"
+rootpw         secret
+index          objectClass     eq
+index          cn,sn,uid       pres,eq,sub
+
index 20d4ad379c4452cce2433cc03b3df622be5c94d5..cc82bbcafbd2633388a83f0c18f001abe9abbcca 100644 (file)
@@ -22,8 +22,6 @@ include ./schema/nis.schema
 pidfile     ./testrun/slapd.1.pid
 argsfile    ./testrun/slapd.1.args
 
-# password-hash        {md5}
-
 #mod#modulepath        ../servers/slapd/back-@BACKEND@/
 #mod#moduleload        back_@BACKEND@.la
 #monitormod#modulepath ../servers/slapd/back-monitor/
index abc0e2046ca33307e812e0a06b09b9c579a81124..45283e55e20de2700af15c4a88abe117cb35a9ed 100644 (file)
@@ -18,6 +18,7 @@ include ./schema/cosine.schema
 include ./schema/inetorgperson.schema
 include ./schema/openldap.schema
 include ./schema/nis.schema
+include ./testdata/test.schema
 
 #
 pidfile     ./testrun/slapd.1.pid
diff --git a/tests/data/test-translucent-add.ldif b/tests/data/test-translucent-add.ldif
new file mode 100644 (file)
index 0000000..fd6acc7
--- /dev/null
@@ -0,0 +1,10 @@
+dn: uid=danger,ou=users,o=translucent
+objectClass: inetOrgPerson
+uid: danger
+sn: danger
+cn: henry
+businessCategory: frontend-override
+carLicense: LIVID
+employeeType: special
+departmentNumber: 9999999
+roomNumber: 41L-535
diff --git a/tests/data/test-translucent-config.ldif b/tests/data/test-translucent-config.ldif
new file mode 100644 (file)
index 0000000..9285176
--- /dev/null
@@ -0,0 +1,26 @@
+# toplevel
+
+dn: o=translucent
+objectClass: top
+objectClass: organization
+o: translucent
+description: backend database root
+
+# backend OU
+
+dn: ou=users,o=translucent
+objectClass: top
+objectClass: organizationalUnit
+ou: users
+description: backend user container root
+
+# bind user for frontend connection
+
+dn: uid=binder,o=translucent
+objectClass: inetOrgPerson
+uid: binder
+sn: test
+cn: binder
+businessCategory: binder-test-user
+displayName: Binder Test User
+userPassword: bindtest
diff --git a/tests/data/test-translucent-data.ldif b/tests/data/test-translucent-data.ldif
new file mode 100644 (file)
index 0000000..ee32cbb
--- /dev/null
@@ -0,0 +1,42 @@
+# typical user
+dn: uid=danger,ou=users,o=translucent
+objectClass: inetOrgPerson
+uid: danger
+sn: warning
+cn: danger
+businessCategory: backend-opaque
+carLicense: BACK
+departmentNumber: 7341
+displayName: Warning
+employeeNumber: 5150
+employeeType: contractor
+givenName: Danger Warning
+
+# another example
+dn: uid=example,ou=users,o=translucent
+objectClass: inetOrgPerson
+uid: example
+sn: user
+cn: example
+businessCategory: backend-opaque
+carLicense: SAMPLE
+departmentNumber: 7341
+displayName: Example
+employeeNumber: 5150
+employeeType: fulltime
+givenName: Example User
+
+#
+dn: uid=fred,ou=users,o=translucent
+objectClass: inetOrgPerson
+uid: fred
+sn: said
+cn: said
+businessCategory: backend-opaque
+carLicense: RIGHT
+departmentNumber: 9919
+displayName: Right Said Fred
+employeeNumber: 44199
+employeeType: fulltime
+givenName: Right Said
+
diff --git a/tests/data/test-translucent-merged.ldif b/tests/data/test-translucent-merged.ldif
new file mode 100644 (file)
index 0000000..5bb54ec
--- /dev/null
@@ -0,0 +1,40 @@
+dn: uid=danger,ou=users,o=translucent
+objectClass: inetOrgPerson
+uid: danger
+sn: danger
+cn: henry
+businessCategory: frontend-override
+carLicense: LIVID
+departmentNumber: 9999999
+displayName: Warning
+employeeNumber: 5150
+employeeType: special
+givenName: Danger Warning
+roomNumber: 41L-535
+
+dn: uid=example,ou=users,o=translucent
+objectClass: inetOrgPerson
+uid: example
+sn: user
+cn: example
+businessCategory: backend-opaque
+carLicense: SAMPLE
+departmentNumber: 7341
+displayName: Example
+employeeNumber: 5150
+employeeType: fulltime
+givenName: Example User
+
+dn: uid=fred,ou=users,o=translucent
+objectClass: inetOrgPerson
+uid: fred
+sn: said
+cn: said
+businessCategory: backend-opaque
+carLicense: RIGHT
+departmentNumber: 9919
+displayName: Right Said Fred
+employeeNumber: 44199
+employeeType: fulltime
+givenName: Right Said
+
index 766ba1089bfec7b695dc805a0ad15491f0a188df..373d8ca10f8f8e20b02edbf4192146ee3647dde1 100644 (file)
 # For testing purposes only.
 
 # For Attribute Aliasing.
-attributetype ( 1.3.6.1.4.1.4203.666.1.34 NAME 'x509CertificateIssuer'
-       EQUALITY distinguishedNameMatch
-       DESC 'Aliasing attribute: Issuer, use'
-       SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+attributetype ( 1.3.6.1.4.1.4203.666.1.34
+       NAME 'x509CertificateIssuer'
+       EQUALITY distinguishedNameMatch
+       DESC 'Aliasing attribute: Issuer, use'
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
 
-attributetype ( 1.3.6.1.4.1.4203.666.1.35 NAME 'x509CertificateSerial'
-       DESC 'Aliasing attribute: Serial, use'
-       EQUALITY integerMatch
-       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+attributetype ( 1.3.6.1.4.1.4203.666.1.35
+       NAME 'x509CertificateSerial'
+       DESC 'Aliasing attribute: Serial, use'
+       EQUALITY integerMatch
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
 
-attributetype ( 1.3.6.1.4.1.4203.666.1.36 NAME 'x509CertificateSerialAndIssuer'
-       DESC 'Aliasing attribute: Serial and Issuer together, use'
-       EQUALITY certificateExactMatch
-       SYNTAX 1.2.826.0.1.3344810.7.1 )
+attributetype ( 1.3.6.1.4.1.4203.666.1.36
+       NAME 'x509CertificateSerialAndIssuer'
+       DESC 'Aliasing attribute: Serial and Issuer together, use'
+       EQUALITY certificateExactMatch
+       SYNTAX 1.2.826.0.1.3344810.7.1 )
+
+# generalized time testing
+
+attributetype ( 1.3.6.1.4.1.4203.666.1.37
+       name 'testTime'
+       equality generalizedTimeMatch
+       ordering generalizedTimeOrderingMatch
+       syntax 1.3.6.1.4.1.1466.115.121.1.24
+       single-value )
+
+objectClass ( 1.3.6.1.4.1.4203.666.1.38
+       name 'testPerson' sup OpenLDAPperson
+       may testTime )
index 5b212f2386a8c1ed94c6cf14b1e70c71b9b83b81..0754ba59d74323802ce0c230b9f802421424913e 100644 (file)
@@ -37,6 +37,7 @@ AC_glue=glue@BUILD_GLUE@
 AC_pcache=pcache@BUILD_PROXYCACHE@
 AC_ppolicy=ppolicy@BUILD_PPOLICY@
 AC_refint=refint@BUILD_REFINT@
+AC_translucent=translucent@BUILD_TRANSLUCENT@
 AC_unique=unique@BUILD_UNIQUE@
 AC_rwm=rwm@BUILD_RWM@
 AC_syncprov=syncprov@BUILD_SYNCPROV@
@@ -48,7 +49,7 @@ AC_WITH_MODULES_ENABLED=@WITH_MODULES_ENABLED@
 
 export AC_bdb AC_hdb AC_ldap AC_ldbm AC_meta AC_monitor AC_relay AC_sql 
 export AC_glue AC_pcache AC_ppolicy AC_refint AC_unique AC_rwm AC_syncprov
-export AC_WITH_SASL AC_WITH_TLS AC_WITH_MODULES_ENABLED
+export AC_translucent AC_WITH_SASL AC_WITH_TLS AC_WITH_MODULES_ENABLED
 
 if test ! -x ../servers/slapd/slapd ; then
        echo "Could not locate slapd(8)"
index 139267d748ccd1809b1c966c7ce9fa646acf6407..4e471a6da7067e35122cd4f3912c9cfc10343261 100755 (executable)
@@ -47,6 +47,7 @@ sed -e "s/@BACKEND@/${BACKEND}/"                      \
        -e "s/^#${AC_ppolicy}#//"                       \
        -e "s/^#${AC_refint}#//"                        \
        -e "s/^#${AC_syncprov}#//"                      \
+       -e "s/^#${AC_translucent}#//"           \
        -e "s/^#${AC_unique}#//"                        \
        -e "s/^#${AC_rwm}#//"                   \
        -e "s/^#${MON}#//"                              \
index 1bf43a34d1bbf03dbdabb17246e0b3439f63b1e5..e2a44ba9f1cd0bd98a25f8e619e8eeeb9e2ffbc8 100755 (executable)
@@ -25,6 +25,7 @@ PROXYCACHE=${AC_pcache-pcacheno}
 PPOLICY=${AC_ppolicy-ppolicyno}
 REFINT=${AC_refint-refintno}
 RWM=${AC_rwm-rwmno}
+TRANSLUCENT=${AC_translucent-translucentno}
 UNIQUE=${AC_unique-uniqueno}
 SYNCPROV=${AC_syncprov-syncprovno}
 WITH_SASL=${AC_WITH_SASL-no}
@@ -85,6 +86,8 @@ CHAINCONF2=$DATADIR/slapd-chain2.conf
 GLUESYNCCONF1=$DATADIR/slapd-glue-syncrepl1.conf
 GLUESYNCCONF2=$DATADIR/slapd-glue-syncrepl2.conf
 SQLCONF=$DATADIR/slapd-sql.conf
+TRANSLUCENTLOCALCONF=$DATADIR/slapd-translucent-local.conf
+TRANSLUCENTREMOTECONF=$DATADIR/slapd-translucent-remote.conf
 
 CONF1=$TESTDIR/slapd.1.conf
 CONF2=$TESTDIR/slapd.2.conf
@@ -169,6 +172,10 @@ LDIFLDAPGLUE3=$DATADIR/test-ldapgluegroups.ldif
 LDIFCOMPMATCH=$DATADIR/test-compmatch.ldif
 LDIFCHAIN1=$DATADIR/test-chain1.ldif
 LDIFCHAIN2=$DATADIR/test-chain2.ldif
+LDIFTRANSLUCENTDATA=$DATADIR/test-translucent-data.ldif
+LDIFTRANSLUCENTCONFIG=$DATADIR/test-translucent-config.ldif
+LDIFTRANSLUCENTADD=$DATADIR/test-translucent-add.ldif
+LDIFTRANSLUCENTMERGED=$DATADIR/test-translucent-merged.ldif
 SQLADD=$DATADIR/sql-add.ldif
 MONITOR=""
 REFDN="c=US"
@@ -182,6 +189,10 @@ JAJDN="cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com"
 REFINTDN="cn=Manager,o=refint"
 UNIQUEDN="cn=Manager,o=unique"
 EMPTYDNDN="cn=Manager,c=US"
+TRANSLUCENTROOT="o=translucent"
+TRANSLUCENTUSER="ou=users,o=translucent"
+TRANSLUCENTDN="uid=binder,o=translucent"
+TRANSLUCENTPASSWD="bindtest"
 
 LOG1=$TESTDIR/slapd.1.log
 LOG2=$TESTDIR/slapd.2.log
@@ -245,6 +256,7 @@ CHAINMODOUT=$DATADIR/chainmod.out
 GLUESYNCOUT=$DATADIR/gluesync.out
 SQLREAD=$DATADIR/sql-read.out
 SQLWRITE=$DATADIR/sql-write.out
+TRANSLUCENTOUT=$DATADIR/translucent.search.out
 
 # Just in case we linked the binaries dynamically
 LD_LIBRARY_PATH=`pwd`/../libraries:${LD_LIBRARY_PATH} export LD_LIBRARY_PATH
index befaee6cff95406ebf16d00a3464b2314e963efa..f6cfcef7c122e937fa7ff0806a542d4969e2281a 100755 (executable)
@@ -308,7 +308,22 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
-BASEDN="o=Example,c=US"
+FILTER="(uid=example)"
+echo "Searching filter=\"$FILTER\""
+echo " attrs=\"uid\""
+echo " base=\"$BASEDN\"..."
+echo "# searching filter=\"$FILTER\"" >> $SEARCHOUT
+echo "#        attrs=\"uid\"" >> $SEARCHOUT
+echo "#        base=\"$BASEDN\"..." >> $SEARCHOUT
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" "$FILTER" uid \
+       >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+       echo "Search failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
 FILTER="(member=cn=Another Added Group,ou=Groups,$BASEDN)"
 echo "Searching filter=\"$FILTER\""
 echo " attrs=\"member\""
index a82a7bde784f4edaef519f8d24e2d83b9d47cb84..53b237003e853fe0a725c31e11d97ec9c3d37dd6 100755 (executable)
@@ -135,7 +135,7 @@ objectClass: userSecurityInformation
 
 dn: cn=Gern Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com
 changetype: add
-objectclass: OpenLDAPperson
+objectclass: testPerson
 cn: Gern Jensen
 sn: Jensen
 uid: gjensen
@@ -149,6 +149,7 @@ facsimiletelephonenumber: +1 313 555 7557
 telephonenumber: +1 313 555 8343
 mail: gjensen@mailgw.example.com
 homephone: +1 313 555 8844
+testTime: 20050304001801.234Z
 
 dn: cn=James A Jones 2,ou=Information Technology Division,ou=People,dc=example,dc=com
 changetype: delete
index f79c5aca0a9d445ef25c9138b87ae862ae2a641f..636d0cece464fa8ec3587c02e514a5f44e35689b 100755 (executable)
@@ -139,6 +139,15 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
+echo "Logging end state with ldapsearch..."
+echo "" >> $TESTOUT
+echo "++ Initial search" >> $TESTOUT
+$LDAPSEARCH -h $LOCALHOST -p $PORT1 \
+       -D "$MANAGERDN" -w $PASSWD \
+       -b "$BASEDN" \
+       'objectclass=*' >> $TESTOUT 2>&1
+
+
 test $KILLSERVERS != no && kill -HUP $KILLPIDS
 
 echo ">>>>> Test succeeded"
index 0edf704842705e97cdf22776171fad4c06928345..437f152193835892288ccfbb02abd67ec0ffa92f 100755 (executable)
@@ -252,7 +252,7 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
-FILTER="(x509CertificateIssuer:distinguishedNameMatch:=c=US)"
+FILTER="(x509CertificateIssuer=c=US)"
 echo "        f=$FILTER ..."
 echo "#         f=$FILTER ..." >> $SEARCHOUT
 $LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
@@ -265,7 +265,7 @@ if test $RC != 0 ; then
        exit $RC
 fi
 
-FILTER="(x509CertificateSerial:integerMatch:=0)"
+FILTER="(x509CertificateSerial=0)"
 echo "        f=$FILTER ..."
 echo "#         f=$FILTER ..." >> $SEARCHOUT
 $LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
diff --git a/tests/scripts/test034-translucent b/tests/scripts/test034-translucent
new file mode 100755 (executable)
index 0000000..7728d67
--- /dev/null
@@ -0,0 +1,717 @@
+#! /bin/sh
+# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2004 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+
+echo "running defines.sh"
+. $SRCDIR/scripts/defines.sh
+
+PERSONAL="(objectClass=inetOrgPerson)"
+NOWHERE="/dev/null"
+FAILURE="additional info:"
+
+if test $TRANSLUCENT = translucentno ; then 
+       echo "Translucent Proxy overlay not available, test skipped"
+       exit 0
+fi 
+
+if test $BACKEND = ldbm ; then
+       echo "Translucent Proxy overlay not qualified for use with LDBM, skipping"
+       exit 0
+fi
+
+if test $AC_ldap = ldapno ; then
+       echo "Translucent Proxy overlay requires back-ldap backend, test skipped"
+       exit 0
+fi
+
+# configure backside
+mkdir -p $TESTDIR $DBDIR1
+
+. $CONFFILTER $BACKEND $MONITORDB < $TRANSLUCENTREMOTECONF > $CONF1
+echo "Running slapadd to build remote slapd database..."
+$SLAPADD -f $CONF1 -l $LDIFTRANSLUCENTCONFIG
+RC=$?
+if test $RC != 0 ; then
+       echo "slapadd failed ($RC)!"
+       exit $RC
+fi
+
+echo "Starting remote slapd on TCP/IP port $PORT1..."
+$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
+PID=$!
+if test $WAIT != 0 ; then
+    echo PID $PID
+    read foo
+fi
+REMOTEPID="$PID"
+KILLPIDS="$PID"
+
+for i in 0 1 2 3 4 5; do
+       $LDAPSEARCH -s base -b "$MONITOR" -H $URI1 \
+               'objectclass=*' > /dev/null 2>&1
+       RC=$?
+       if test $RC = 0 ; then
+               break
+       fi
+       echo "Waiting 5 seconds for remote slapd to start..."
+       sleep 5
+done
+
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+# configure frontside
+mkdir -p $DBDIR2
+
+. $CONFFILTER $BACKEND $MONITORDB < $TRANSLUCENTLOCALCONF > $CONF2
+
+echo "Starting local slapd on TCP/IP port $PORT2..."
+$SLAPD -f $CONF2 -h $URI2 -d $LVL $TIMING > $LOG2 2>&1 &
+PID=$!
+if test $WAIT != 0 ; then
+    echo PID $PID
+    read foo
+fi
+LOCALPID="$PID"
+KILLPIDS="$LOCALPID $REMOTEPID"
+
+for i in 0 1 2 3 4 5; do
+       $LDAPSEARCH -s base -b "$MONITOR" -H $URI2 \
+               'objectclass=*' > /dev/null 2>&1
+       RC=$?
+       if test $RC = 0 ; then
+               break
+       fi
+       echo "Waiting 5 seconds for local slapd to start..."
+       sleep 5
+done
+
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing slapd Translucent Proxy operations..."
+
+echo "Testing search: no remote data defined..."
+
+$LDAPSEARCH -H $URI2 -b "$TRANSLUCENTUSER" "$PERSONAL" >$SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+if test -s $SEARCHOUT; then
+       echo "ldapsearch should have returned no records!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit 1
+fi
+
+echo "Populating remote database..."
+
+$LDAPADD -D "$TRANSLUCENTROOT" -H $URI1 \
+       -w $PASSWD < $LDIFTRANSLUCENTDATA > $NOWHERE 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapadd failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing search: remote database via local slapd..."
+
+$LDAPSEARCH -H $URI2 -b "$TRANSLUCENTUSER" "$PERSONAL" > $SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+. $LDIFFILTER < $SEARCHOUT > $SEARCHFLT
+. $LDIFFILTER < $LDIFTRANSLUCENTDATA > $LDIFFLT
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
+
+if test $? != 0 ; then
+       echo "Comparison failed -- corruption from remote to local!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit 1
+fi
+
+echo "Testing add: prohibited local record..."
+
+$LDAPADD -D "$TRANSLUCENTDN" -H $URI2 \
+       -w $TRANSLUCENTPASSWD < $LDIFTRANSLUCENTADD > $TESTOUT 2>&1
+
+RC=$?
+if test $RC != 50 ; then
+       echo "ldapadd failed ($RC), expected INSUFFICIENT ACCESS!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing add: valid local record, no_glue..."
+
+$LDAPADD -v -v -v -D "$TRANSLUCENTROOT" -H $URI2 \
+       -w $PASSWD < $LDIFTRANSLUCENTADD > $TESTOUT 2>&1
+
+RC=$?
+if test $RC != 32 ; then
+       echo "ldapadd failed ($RC), expected NO SUCH OBJECT!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing modrdn: valid local record, no_glue..."
+
+$LDAPMODRDN -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \
+       $TESTOUT 2>&1 'uid=fred,ou=users,o=translucent' 'uid=someguy'
+
+RC=$?
+if test $RC != 32 ; then
+       echo "ldapmodrdn failed ($RC), expected NO SUCH OBJECT!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Shutting down local slapd..."
+kill -HUP $LOCALPID
+sleep 5
+
+echo "Configuring local slapd without translucent_no_glue..."
+. $CONFFILTER $BACKEND $MONITORDB < $TRANSLUCENTLOCALCONF | \
+       grep -v translucent_no_glue > $CONF2
+
+echo "Restarting local slapd on TCP/IP port $PORT2..."
+$SLAPD -f $CONF2 -h $URI2 -d $LVL $TIMING >> $LOG2 2>&1 &
+PID=$!
+if test $WAIT != 0 ; then
+    echo PID $PID
+    read foo
+fi
+LOCALPID="$PID"
+KILLPIDS="$REMOTEPID $PID"
+
+for i in 0 1 2 3 4 5; do
+       $LDAPSEARCH -s base -b "$MONITOR" -H $URI2 \
+               'objectclass=*' > /dev/null 2>&1
+       RC=$?
+       if test $RC = 0 ; then
+               break
+       fi
+       echo "Waiting 5 seconds for local slapd to start..."
+       sleep 5
+done
+
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing add: valid local record..."
+
+$LDAPADD -D "$TRANSLUCENTROOT" -H $URI2 \
+       -w $PASSWD < $LDIFTRANSLUCENTADD > $TESTOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapadd failed ($RC)!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing search: data merging..."
+
+$LDAPSEARCH -H $URI2 -b "$TRANSLUCENTUSER" "$PERSONAL" > $SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+$CMP $SEARCHOUT $LDIFTRANSLUCENTMERGED > $CMPOUT
+
+if test $? != 0 ; then
+       echo "Comparison failed -- local data failed to merge with remote!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit 1
+fi
+
+echo "Testing compare: valid local..."
+
+$LDAPCOMPARE -z -H $URI2 -w $TRANSLUCENTPASSWD -D $TRANSLUCENTDN \
+       "uid=danger,ou=users,o=translucent" "carLicense:LIVID"
+
+RC=$?
+if test $RC != 6 ; then
+       echo "ldapcompare failed ($RC), expected TRUE!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing compare: valid remote..."
+
+$LDAPCOMPARE -z -x -H $URI2 -w $TRANSLUCENTPASSWD -D $TRANSLUCENTDN \
+       "uid=binder,o=translucent" "businessCategory:binder-test-user"
+
+RC=$?
+if test $RC != 6 ; then
+       echo "ldapcompare failed ($RC), expected TRUE!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing compare: bogus local..."
+
+$LDAPCOMPARE -z -x -H $URI2 -w $TRANSLUCENTPASSWD -D $TRANSLUCENTDN \
+       "uid=danger,ou=users,o=translucent" "businessCategory:invalid-test-value"
+
+RC=$?
+if test $RC != 5 ; then
+       echo "ldapcompare failed ($RC), expected FALSE!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing compare: bogus remote..."
+
+$LDAPCOMPARE -z -x -H $URI2 -w $TRANSLUCENTPASSWD -D $TRANSLUCENTDN \
+       "uid=binder,o=translucent" "businessCategory:invalid-test-value"
+
+RC=$?
+if test $RC != 5 ; then
+       echo "ldapcompare failed ($RC), expected FALSE!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing modify: nonexistent record..."
+
+$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF_MOD
+version: 1
+dn: uid=bogus,ou=users,o=translucent
+changetype: modify
+replace: roomNumber
+roomNumber: 31J-2112
+EOF_MOD
+
+RC=$?
+if test $RC != 32 ; then
+       echo "ldapmodify failed ($RC), expected NO SUCH OBJECT!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing modify: valid local record, nonexistent attribute..."
+
+$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF_MOD1
+version: 1
+dn: uid=danger,ou=users,o=translucent
+changetype: modify
+replace: roomNumber
+roomNumber: 9N-21
+EOF_MOD1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapmodify failed ($RC)!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+$LDAPSEARCH -H $URI2 -b "uid=danger,ou=users,o=translucent" > $SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+ATTR=`grep roomNumber $SEARCHOUT` > $NOWHERE 2>&1
+if test "$ATTR" != "roomNumber: 9N-21" ; then
+       echo "modification failed!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit 1
+fi
+
+echo "Testing search: specific nonexistent remote attribute..."
+
+$LDAPSEARCH -H $URI2 -b "uid=danger,ou=users,o=translucent" roomNumber > $SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing modify: nonexistent local record, nonexistent attribute..."
+
+$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF_MOD2
+version: 1
+dn: uid=fred,ou=users,o=translucent
+changetype: modify
+replace: roomNumber
+roomNumber: 31J-2112
+EOF_MOD2
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapmodify failed ($RC)!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+$LDAPSEARCH -H $URI2 -b "uid=fred,ou=users,o=translucent" > $SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+ATTR=`grep roomNumber $SEARCHOUT` > $NOWHERE 2>&1
+if test "$ATTR" != "roomNumber: 31J-2112" ; then
+       echo "modification failed!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit 1
+fi
+
+echo "Testing modify: valid remote record, nonexistent attribute..."
+
+$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF_MOD9
+version: 1
+dn: uid=fred,ou=users,o=translucent
+changetype: modify
+delete: preferredLanguage
+EOF_MOD9
+
+RC=$?
+if test $RC != 16 ; then
+       echo "ldapmodify failed ($RC), expected NO SUCH ATTRIBUTE!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing delete: valid local record, nonexistent attribute..."
+
+$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF_MOD4
+version: 1
+dn: uid=fred,ou=users,o=translucent
+changetype: modify
+delete: roomNumber
+EOF_MOD4
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapmodify failed ($RC)!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing modrdn: prohibited local record..."
+
+$LDAPMODRDN -D "$TRANSLUCENTDN" -H $URI2 -w $TRANSLUCENTPASSWD > \
+       $TESTOUT 2>&1 'uid=fred,ou=users,o=translucent' 'uid=someguy'
+
+RC=$?
+if test $RC != 50 ; then
+       echo "ldapmodrdn failed ($RC), expected INSUFFICIENT ACCESS!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing modrdn: valid local record..."
+
+$LDAPMODRDN -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \
+       $TESTOUT 2>&1 'uid=fred,ou=users,o=translucent' 'uid=someguy'
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapmodrdn failed ($RC)!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing delete: prohibited local record..."
+
+$LDAPMODIFY -v -D "$TRANSLUCENTDN" -H $URI2 -w $TRANSLUCENTPASSWD > \
+        $TESTOUT 2>&1 << EOF_DEL2
+version: 1
+dn: uid=someguy,ou=users,o=translucent
+changetype: delete
+EOF_DEL2
+
+RC=$?
+if test $RC != 50 ; then
+       echo "ldapadd failed ($RC), expected INSUFFICIENT ACCESS!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing delete: valid local record..."
+
+$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF_DEL3
+version: 1
+dn: uid=someguy,ou=users,o=translucent
+changetype: delete
+EOF_DEL3
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapmodify failed ($RC)!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing delete: valid remote record..."
+
+$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF_DEL8
+version: 1
+dn: uid=fred,ou=users,o=translucent
+changetype: delete
+EOF_DEL8
+
+RC=$?
+if test $RC != 32 ; then
+       echo "ldapmodify failed ($RC), expected NO SUCH OBJECT!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing delete: nonexistent local record, nonexistent attribute..."
+
+$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF_DEL1
+version: 1
+dn: uid=fred,ou=users,o=translucent
+changetype: modify
+delete: roomNumber
+EOF_DEL1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapmodify failed ($RC)!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+$LDAPSEARCH -H $URI2 -b "uid=fred,ou=users,o=translucent" > $SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing delete: valid local record, nonexistent attribute..."
+
+$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF_MOD8
+version: 1
+dn: uid=danger,ou=users,o=translucent
+changetype: modify
+delete: preferredLanguage
+EOF_MOD8
+
+RC=$?
+if test $RC != 16 ; then
+       echo "ldapmodify failed ($RC), expected NO SUCH ATTRIBUTE!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing modify: valid remote record, combination add-modify-delete..."
+
+$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF_MOD6
+version: 1
+dn: uid=fred,ou=users,o=translucent
+changetype: modify
+delete: carLicense
+-
+add: preferredLanguage
+preferredLanguage: ISO8859-1
+-
+replace: employeeType
+employeeType: consultant
+EOF_MOD6
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapmodify failed ($RC)!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+$LDAPSEARCH -H $URI2 -b "uid=fred,ou=users,o=translucent" > $SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+ATTR=`grep employeeType $SEARCHOUT` > $NOWHERE 2>&1
+if test "$ATTR" != "employeeType: consultant" ; then
+       echo "modification failed!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit 1
+fi
+
+ATTR=`grep preferredLanguage $SEARCHOUT` > $NOWHERE 2>&1
+if test "$ATTR" != "preferredLanguage: ISO8859-1" ; then
+       echo "modification failed!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit 1
+fi
+
+echo "Shutting down local slapd..."
+kill -HUP $LOCALPID
+sleep 5
+
+echo "Configuring local slapd with translucent_strict..."
+echo translucent_strict >> $CONF2
+
+echo "Restarting slapd on TCP/IP port $PORT2..."
+$SLAPD -f $CONF2 -h $URI2 -d $LVL $TIMING >> $LOG2 2>&1 &
+PID=$!
+if test $WAIT != 0 ; then
+    echo PID $PID
+    read foo
+fi
+LOCALPID="$PID"
+KILLPIDS="$REMOTEPID $PID"
+
+for i in 0 1 2 3 4 5; do
+       $LDAPSEARCH -s base -b "$MONITOR" -H $URI2 \
+               'objectclass=*' > /dev/null 2>&1
+       RC=$?
+       if test $RC = 0 ; then
+               break
+       fi
+       echo "Waiting 5 seconds for local slapd to start..."
+       sleep 5
+done
+
+if test $RC != 0 ; then
+       echo "ldapsearch failed ($RC)!"
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing strict mode delete: nonexistent local attribute..."
+
+$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF_MOD5
+version: 1
+dn: uid=example,ou=users,o=translucent
+changetype: modify
+delete: preferredLanguage
+EOF_MOD5
+
+RC=$?
+if test $RC != 19 ; then
+       echo "ldapmodify failed ($RC), expected CONSTRAINT VIOLATION!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing strict mode delete: nonexistent remote attribute..."
+
+$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF_MOD3
+version: 1
+dn: uid=danger,ou=users,o=translucent
+changetype: modify
+delete: displayName
+EOF_MOD3
+
+RC=$?
+if test $RC != 19 ; then
+       echo "ldapmodify failed ($RC), expected CONSTRAINT VIOLATION!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+echo "Testing strict mode modify: combination add-modify-delete..."
+
+$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \
+        $TESTOUT 2>&1 << EOF_MOD6
+version: 1
+dn: uid=example,ou=users,o=translucent
+changetype: modify
+delete: carLicense
+-
+add: preferredLanguage
+preferredLanguage: ISO8859-1
+-
+replace: employeeType
+employeeType: consultant
+EOF_MOD6
+
+RC=$?
+if test $RC != 19 ; then
+       echo "ldapmodify failed ($RC), expected CONSTRAINT VIOLATION!"
+       grep "$FAILURE" $TESTOUT
+       test $KILLSERVERS != no && kill -HUP $KILLPIDS
+       exit $RC
+fi
+
+test $KILLSERVERS != no && kill -HUP $KILLPIDS
+
+echo ">>>>> Test succeeded"
+exit 0